From e43578427fc5b91364dfc27d8f5e1fb1036fa8ef Mon Sep 17 00:00:00 2001 From: DavidbrOFS <101847651+DavidbrOFS@users.noreply.github.com> Date: Tue, 6 Feb 2024 14:22:08 -0600 Subject: [PATCH] Delete sw directory this folder is not longer required Signed-off-by: DavidbrOFS <101847651+DavidbrOFS@users.noreply.github.com> --- sw/build_chain/fpga_api/api_build/index.html | 1827 ----------- .../fpga_driver/driver_build/index.html | 1801 ----------- sw/drv_arch/Driver_Organization.png | Bin 58991 -> 0 bytes sw/drv_arch/FPGA_PCIe_Device.png | Bin 3976 -> 0 bytes sw/drv_arch/FPGA_PCIe_Device_SRIOV.png | Bin 4487 -> 0 bytes sw/drv_arch/drv_arch/index.html | 2209 ------------- sw/drv_arch/fme_init_flow.mscgen | 12 - sw/drv_arch/fme_init_flow.png | Bin 4999 -> 0 bytes sw/drv_arch/pci_init_flow.mscgen | 39 - sw/drv_arch/port_init_flow.mscgen | 12 - sw/drv_arch/port_init_flow.png | Bin 4919 -> 0 bytes sw/fpga_api/fpga_api/index.html | 2402 --------------- sw/fpga_api/fpga_cxx_api/index.html | 2255 -------------- sw/fpga_api/fpga_python_api/index.html | 1993 ------------ sw/fpga_api/plug_guide/readme/index.html | 2296 -------------- sw/fpga_api/prog_guide/FPGA-lib-1.png | Bin 65857 -> 0 bytes sw/fpga_api/prog_guide/FPGA-lib-2.png | Bin 27097 -> 0 bytes sw/fpga_api/prog_guide/FPGA-lib-3.PNG | Bin 19554 -> 0 bytes sw/fpga_api/prog_guide/readme/index.html | 2721 ----------------- sw/fpga_api/quick_start/readme/index.html | 2365 -------------- sw/fpga_dfl_drv/fpga_dfl_drv/index.html | 1796 ----------- sw/fpga_dfl_drv/pcie_dfl_drv_arch.PNG | Bin 35483 -> 0 bytes sw/fpga_tools/coreidle/coreidle/index.html | 1832 ----------- sw/fpga_tools/fecmode/fecmode/index.html | 1858 ----------- sw/fpga_tools/fpgabist/fpgabist/index.html | 1864 ----------- sw/fpga_tools/fpgaconf/fpgaconf/index.html | 1924 ------------ sw/fpga_tools/fpgad/fpgad/index.html | 1964 ------------ sw/fpga_tools/fpgadiag/index.html | 2311 -------------- sw/fpga_tools/fpgaflash/fpgaflash/index.html | 1848 ----------- sw/fpga_tools/fpgaflash/superrsu/index.html | 2153 ------------- sw/fpga_tools/fpgainfo/fpgainfo/index.html | 2087 ------------- sw/fpga_tools/fpgamux/fpgamux/index.html | 1918 ------------ sw/fpga_tools/fpgaport/fpgaport/index.html | 1860 ----------- .../fpgasupdate/fpgasupdate/index.html | 1920 ------------ .../host_exerciser/host_exerciser/index.html | 2076 ------------- sw/fpga_tools/hssi/hssi/index.html | 1981 ------------ sw/fpga_tools/hssi_config/readme/index.html | 2083 ------------- .../hssi_ethernet/hssiloopback/index.html | 1917 ------------ .../hssi_ethernet/hssimac/index.html | 1915 ------------ .../hssi_ethernet/hssistats/index.html | 1913 ------------ sw/fpga_tools/hssi_loopback/readme/index.html | 1906 ------------ sw/fpga_tools/mem_tg/mem_tg/index.html | 1990 ------------ sw/fpga_tools/mmlink/mmlink/index.html | 1943 ------------ sw/fpga_tools/ofs.uio/ofs.uio/index.html | 2167 ------------- sw/fpga_tools/opae.io/opae.io/index.html | 2135 ------------- sw/fpga_tools/opaeuio/opaeuio/index.html | 1929 ------------ sw/fpga_tools/opaevfio/opaevfio/index.html | 1935 ------------ .../pac_hssi_config/dcp_hssi_arch.PNG | Bin 27780 -> 0 bytes .../pac_hssi_config/index.html | 1941 ------------ sw/fpga_tools/pac_hssi_config/reg_output.PNG | Bin 18154 -> 0 bytes .../pac_hssi_config/reg_output_2cards.PNG | Bin 17987 -> 0 bytes sw/fpga_tools/packager/packager/index.html | 2019 ------------ .../pci_device/pci_device/index.html | 2058 ------------- sw/fpga_tools/readme/index.html | 2436 --------------- sw/fpga_tools/rsu/rsu/index.html | 2009 ------------ sw/fpga_tools/super-rsu/super-rsu/index.html | 1884 ------------ sw/fpga_tools/userclk/userclk/index.html | 1926 ------------ sw/fpga_tools/vabtool/vabtool/index.html | 1928 ------------ sw/include/opae/access.h | 108 - sw/include/opae/buffer.h | 142 - sw/include/opae/cxx/core.h | 35 - sw/include/opae/cxx/core/errors.h | 101 - sw/include/opae/cxx/core/events.h | 112 - sw/include/opae/cxx/core/except.h | 340 -- sw/include/opae/cxx/core/handle.h | 198 -- sw/include/opae/cxx/core/properties.h | 143 - sw/include/opae/cxx/core/pvalue.h | 278 -- sw/include/opae/cxx/core/shared_buffer.h | 177 -- sw/include/opae/cxx/core/sysobject.h | 200 -- sw/include/opae/cxx/core/token.h | 81 - sw/include/opae/cxx/core/version.h | 55 - sw/include/opae/enum.h | 140 - sw/include/opae/error.h | 113 - sw/include/opae/event.h | 160 - sw/include/opae/fpga.h | 57 - sw/include/opae/hash_map.h | 235 -- sw/include/opae/init.h | 64 - sw/include/opae/log.h | 105 - sw/include/opae/manage.h | 148 - sw/include/opae/mem_alloc.h | 176 -- sw/include/opae/metrics.h | 139 - sw/include/opae/mmio.h | 207 -- sw/include/opae/properties.h | 825 ----- sw/include/opae/sysobject.h | 242 -- sw/include/opae/types.h | 295 -- sw/include/opae/types_enum.h | 218 -- sw/include/opae/uio.h | 175 -- sw/include/opae/umsg.h | 114 - sw/include/opae/userclk.h | 73 - sw/include/opae/utils.h | 58 - sw/include/opae/version.h | 79 - sw/include/opae/vfio.h | 542 ---- .../installation_guide/index.html | 2452 --------------- sw/pyopae/python_bindings/index.html | 2034 ------------ sw/samples/hello_events/CMakeLists.txt | 46 - sw/samples/hello_events/hello_events.c | 345 --- sw/samples/hello_fpga/CMakeLists.txt | 46 - sw/samples/hello_fpga/hello_fpga.c | 544 ---- sw/tod/tod/index.html | 2012 ------------ 99 files changed, 100972 deletions(-) delete mode 100644 sw/build_chain/fpga_api/api_build/index.html delete mode 100644 sw/build_chain/fpga_driver/driver_build/index.html delete mode 100644 sw/drv_arch/Driver_Organization.png delete mode 100644 sw/drv_arch/FPGA_PCIe_Device.png delete mode 100644 sw/drv_arch/FPGA_PCIe_Device_SRIOV.png delete mode 100644 sw/drv_arch/drv_arch/index.html delete mode 100644 sw/drv_arch/fme_init_flow.mscgen delete mode 100644 sw/drv_arch/fme_init_flow.png delete mode 100644 sw/drv_arch/pci_init_flow.mscgen delete mode 100644 sw/drv_arch/port_init_flow.mscgen delete mode 100644 sw/drv_arch/port_init_flow.png delete mode 100644 sw/fpga_api/fpga_api/index.html delete mode 100644 sw/fpga_api/fpga_cxx_api/index.html delete mode 100644 sw/fpga_api/fpga_python_api/index.html delete mode 100644 sw/fpga_api/plug_guide/readme/index.html delete mode 100644 sw/fpga_api/prog_guide/FPGA-lib-1.png delete mode 100644 sw/fpga_api/prog_guide/FPGA-lib-2.png delete mode 100644 sw/fpga_api/prog_guide/FPGA-lib-3.PNG delete mode 100644 sw/fpga_api/prog_guide/readme/index.html delete mode 100644 sw/fpga_api/quick_start/readme/index.html delete mode 100644 sw/fpga_dfl_drv/fpga_dfl_drv/index.html delete mode 100644 sw/fpga_dfl_drv/pcie_dfl_drv_arch.PNG delete mode 100644 sw/fpga_tools/coreidle/coreidle/index.html delete mode 100644 sw/fpga_tools/fecmode/fecmode/index.html delete mode 100644 sw/fpga_tools/fpgabist/fpgabist/index.html delete mode 100644 sw/fpga_tools/fpgaconf/fpgaconf/index.html delete mode 100644 sw/fpga_tools/fpgad/fpgad/index.html delete mode 100644 sw/fpga_tools/fpgadiag/index.html delete mode 100644 sw/fpga_tools/fpgaflash/fpgaflash/index.html delete mode 100644 sw/fpga_tools/fpgaflash/superrsu/index.html delete mode 100644 sw/fpga_tools/fpgainfo/fpgainfo/index.html delete mode 100644 sw/fpga_tools/fpgamux/fpgamux/index.html delete mode 100644 sw/fpga_tools/fpgaport/fpgaport/index.html delete mode 100644 sw/fpga_tools/fpgasupdate/fpgasupdate/index.html delete mode 100644 sw/fpga_tools/host_exerciser/host_exerciser/index.html delete mode 100644 sw/fpga_tools/hssi/hssi/index.html delete mode 100644 sw/fpga_tools/hssi_config/readme/index.html delete mode 100644 sw/fpga_tools/hssi_ethernet/hssiloopback/index.html delete mode 100644 sw/fpga_tools/hssi_ethernet/hssimac/index.html delete mode 100644 sw/fpga_tools/hssi_ethernet/hssistats/index.html delete mode 100644 sw/fpga_tools/hssi_loopback/readme/index.html delete mode 100644 sw/fpga_tools/mem_tg/mem_tg/index.html delete mode 100644 sw/fpga_tools/mmlink/mmlink/index.html delete mode 100644 sw/fpga_tools/ofs.uio/ofs.uio/index.html delete mode 100644 sw/fpga_tools/opae.io/opae.io/index.html delete mode 100644 sw/fpga_tools/opaeuio/opaeuio/index.html delete mode 100644 sw/fpga_tools/opaevfio/opaevfio/index.html delete mode 100644 sw/fpga_tools/pac_hssi_config/dcp_hssi_arch.PNG delete mode 100644 sw/fpga_tools/pac_hssi_config/pac_hssi_config/index.html delete mode 100644 sw/fpga_tools/pac_hssi_config/reg_output.PNG delete mode 100644 sw/fpga_tools/pac_hssi_config/reg_output_2cards.PNG delete mode 100644 sw/fpga_tools/packager/packager/index.html delete mode 100644 sw/fpga_tools/pci_device/pci_device/index.html delete mode 100644 sw/fpga_tools/readme/index.html delete mode 100644 sw/fpga_tools/rsu/rsu/index.html delete mode 100644 sw/fpga_tools/super-rsu/super-rsu/index.html delete mode 100644 sw/fpga_tools/userclk/userclk/index.html delete mode 100644 sw/fpga_tools/vabtool/vabtool/index.html delete mode 100644 sw/include/opae/access.h delete mode 100644 sw/include/opae/buffer.h delete mode 100644 sw/include/opae/cxx/core.h delete mode 100644 sw/include/opae/cxx/core/errors.h delete mode 100644 sw/include/opae/cxx/core/events.h delete mode 100644 sw/include/opae/cxx/core/except.h delete mode 100644 sw/include/opae/cxx/core/handle.h delete mode 100644 sw/include/opae/cxx/core/properties.h delete mode 100644 sw/include/opae/cxx/core/pvalue.h delete mode 100644 sw/include/opae/cxx/core/shared_buffer.h delete mode 100644 sw/include/opae/cxx/core/sysobject.h delete mode 100644 sw/include/opae/cxx/core/token.h delete mode 100644 sw/include/opae/cxx/core/version.h delete mode 100644 sw/include/opae/enum.h delete mode 100644 sw/include/opae/error.h delete mode 100644 sw/include/opae/event.h delete mode 100644 sw/include/opae/fpga.h delete mode 100644 sw/include/opae/hash_map.h delete mode 100644 sw/include/opae/init.h delete mode 100644 sw/include/opae/log.h delete mode 100644 sw/include/opae/manage.h delete mode 100644 sw/include/opae/mem_alloc.h delete mode 100644 sw/include/opae/metrics.h delete mode 100644 sw/include/opae/mmio.h delete mode 100644 sw/include/opae/properties.h delete mode 100644 sw/include/opae/sysobject.h delete mode 100644 sw/include/opae/types.h delete mode 100644 sw/include/opae/types_enum.h delete mode 100644 sw/include/opae/uio.h delete mode 100644 sw/include/opae/umsg.h delete mode 100644 sw/include/opae/userclk.h delete mode 100644 sw/include/opae/utils.h delete mode 100644 sw/include/opae/version.h delete mode 100644 sw/include/opae/vfio.h delete mode 100644 sw/install_guide/installation_guide/index.html delete mode 100644 sw/pyopae/python_bindings/index.html delete mode 100644 sw/samples/hello_events/CMakeLists.txt delete mode 100644 sw/samples/hello_events/hello_events.c delete mode 100644 sw/samples/hello_fpga/CMakeLists.txt delete mode 100644 sw/samples/hello_fpga/hello_fpga.c delete mode 100644 sw/tod/tod/index.html diff --git a/sw/build_chain/fpga_api/api_build/index.html b/sw/build_chain/fpga_api/api_build/index.html deleted file mode 100644 index fec2c5194..000000000 --- a/sw/build_chain/fpga_api/api_build/index.html +++ /dev/null @@ -1,1827 +0,0 @@ - - - - - - - - - - - - - - - - - - Api build - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - Skip to content - - -
-
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

Building OPAE SDK Artifacts

-

Steps

-
    -
  1. Fetch the OPAE SDK source tree
  2. -
  3. Configure the OPAE SDK CMake project
  4. -
  5. Build OPAE SDK targets
  6. -
-

The example below lists commands that can be used to fetch and build OPAE SDK.

-
# fetch the source
-git clone https://github.com/OPAE/opae-sdk.git
-cd opae-sdk
-# configure CMake
-cmake ..
-# build
-make
-
-

For a list of targets that can be built, type make help from the build -directory.

-

CMake options that may be set during the configuration include the following:

-
|----------------------------|-----------------------|-------------------------------------|---------------------------------------|----------------|
-| cmake flag                 | Optional or Mandatory | Purpose                             | Valid values                          | Default value  |
-|----------------------------|-----------------------|-------------------------------------|---------------------------------------|----------------|
-| -DCMAKE_BUILD_TYPE         | Optional              | Set compiler flags                  | Debug/Release/Coverage/RelWithDebInfo | RelWithDebInfo |
-| -DOPAE_BUILD_LEGACY        | Optional              | Enable/disable opae-legacy.git      | ON/OFF                                | OFF            |
-| -DOPAE_BUILD_SPHINX_DOC    | Optional              | Enable/disable documentation build  | ON/OFF                                | OFF            |
-| -DOPAE_BUILD_TESTS         | Optional              | Enable/disable building unit tests  | ON/OFF                                | OFF            |
-| -DOPAE_INSTALL_RPATH       | Optional              | Enable/disable rpath for install    | ON/OFF                                | OFF            |
-| -DOPAE_BUILD_LIBOPAE_CXX   | Optional              | Enable/disable OPAE C++ bindings    | ON/OFF                                | ON             | 
-| -DOPAE_WITH_PYBIND11       | Optional              | Enable/disable pybind11 binaries    | ON/OFF                                | ON             |
-| -DOPAE_BUILD_PYTHON_DIST   | Optional              | Enable/disable Python Distribution  | ON/OFF                                | OFF            |
-| -DOPAE_ENABLE_MOCK         | Optional              | Enable/disable mocks for unit tests | ON/OFF                                | OFF            |
-| -DOPAE_BUILD_SIM           | Optional              | Enable/disable opae-sim.git         | ON/OFF                                | OFF            |
-
- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/build_chain/fpga_driver/driver_build/index.html b/sw/build_chain/fpga_driver/driver_build/index.html deleted file mode 100644 index 30a60382e..000000000 --- a/sw/build_chain/fpga_driver/driver_build/index.html +++ /dev/null @@ -1,1801 +0,0 @@ - - - - - - - - - - - - - - - - - - Driver build - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - Skip to content - - -
-
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

Building the OPAE Intel FPGA driver (out-of-tree)

-

The Intel FPGA driver included with OPAE SDK releases is packaged as an RPM or -DEB package as well as a source tarball. Starting with OPAE SDK release of 1.4, -the driver can be built from source out-of-tree but requires the following -packages:

-

For RPM package managers (Red Hat, CentOS, Fedora, etc.) -* kernel-headers -* kernel-devel -* gcc -* make

-

For DEB package managers (Debian, Ubuntu, etc.) -* kernel-headers-generic -* gcc -* make

-

After installation of necessary distribution packages, follow the steps in the -example below to build the Intel Kernel driver. -NOTE The example below references Intel FPGA Kernel driver version 2.0.2. but -can be applied to later versions.

-
tar zxf opae-intel-fpga-driver-2.0.2-1.tar.gz
-cd opae-intel-fpga-driver-2.0.2
-make
-
- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/drv_arch/Driver_Organization.png b/sw/drv_arch/Driver_Organization.png deleted file mode 100644 index 83a7ab706ccfec74be56c2ef78f2270089159769..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58991 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 L4XU@e`Safa5DrJ4 diff --git a/sw/drv_arch/FPGA_PCIe_Device_SRIOV.png b/sw/drv_arch/FPGA_PCIe_Device_SRIOV.png deleted file mode 100644 index 145525732e750ad29e454e043c1f5fb2f9aee9de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4487 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 diff --git a/sw/drv_arch/drv_arch/index.html b/sw/drv_arch/drv_arch/index.html deleted file mode 100644 index 78a251f71..000000000 --- a/sw/drv_arch/drv_arch/index.html +++ /dev/null @@ -1,2209 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - Open Programmable Accelerator Engine (OPAE) Linux Device Driver Architecture - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - - - - - -
-
- - - - - - - -

Open Programmable Accelerator Engine (OPAE) Linux Device Driver Architecture

-

The OPAE FPGA Linux Device Driver provides interfaces for user-space applications to -configure, enumerate, open, and access FPGA accelerators on platforms equipped -with Intel FPGA solutions. The OPAE FPGA driver also enables system-level management functions such -as FPGA reconfiguration and virtualization.

-

Hardware Architecture

-

The Linux Operating System treats the FPGA hardware as a PCIe* device. A predefined data structure, -Device Feature List (DFL), allows for dynamic feature discovery in an Intel -FPGA solution.

-

FPGA PCIe Device

-

The Linux Device Driver implements PCIe Single Root I/O Virtualization (SR-IOV) for the creation of -Virtual Functions (VFs). The device driver can release individual accelerators -for assignment to virtual machines (VMs).

-

Virtualized FPGA PCIe Device

-

FPGA Management Engine (FME)

-

The FPGA Management Engine provides error reporting, reconfiguration, performance reporting, and other -infrastructure functions. Each FPGA has one FME which is always accessed through the Physical -Function (PF). The Intel Xeon® Processor with Integrated FPGA also performs power and thermal management. -These functions are not available on the Intel Programmable Acceleration Card (PAC).

-

User-space applications can acquire exclusive access to the FME using open(), -and release it using close(). Device access may be managed by standard Linux -interfaces and tools.

-
-

If an application terminates without freeing the FME or Port resources, Linux closes all file descriptors owned by the terminating process, freeing those resources.

-
-

Port

-

A Port represents the interface between two components: -* The FPGA Interface Manager (FIM) which is part of the static FPGA fabric -* The Accelerator Function Unit (AFU) which is the partially reconfigurable region

-

The Port controls the communication from software to the AFU and makes features such as reset and debug available.

-

Accelerator Function Unit (AFU)

-

An AFU attaches to a Port. The AFU provides a 256 KB memory mapped I/O (MMIO) region for accelerator-specific control registers.

-
    -
  • Use open() on the Port device to acquire access to an AFU associated with the Port device.
  • -
  • Use close()on the Port device to release the AFU associated with the Port device.
  • -
  • Use mmap() on the Port device to map accelerator MMIO regions.
  • -
-

Partial Reconfiguration (PR)

-

Use PR to reconfigure an AFU from a bitstream file. Successful reconfiguration has the following requirement:

-
    -
  • You must generate the reconfiguration AFU for the exact FIM. The AFU and FIM are compatible if their interface IDs match. -You can verify this match by comparing the interface ID in the bitstream header against the interface ID that is -exported by the driver in sysfs.
  • -
-

In all other cases PR fails and may cause system instability.

-
-

Platforms that support 512-bit Partial Reconfiguration require binutils >= version 2.25.

-
-

Close any software programs accessing the FPGA, including those running in a virtualized host before -initiating PR. For virtualized environments, the recommended sequence is as -follows:

-
    -
  1. Unload the driver from the guest
  2. -
  3. Release the VF from the guest
  4. -
-
-

Releasing the VF from the guest while an application on the guest is still accessing its resources may lead to VM instabilities. We recommend closing all applications accessing the VF in the guest before releasing the VF.

-
-
    -
  1. Disable SR-IOV
  2. -
  3. Perform PR
  4. -
  5. Enable SR-IOV
  6. -
  7. Assign the VF to the guest
  8. -
  9. Load the driver in the guest
  10. -
-

FPGA Virtualization

-

To enable accelerator access from applications running on a VM, create a VF for -the port using the following process:

-
    -
  1. -

    Release the Port from the PF using the associated ioctl on the FME device.

    -
  2. -
  3. -

    Use the following command to enable SR-IOV and VFs. Each VF can own a single Port with an AFU. In the following command, -N is the number of Port released from the PF.

    -
  4. -
-
    echo N > $PCI_DEVICE_PATH/sriov_numvfs
-
-
-

The number, 'N', cannot be greater than the number of supported VFs. This can be read from $PCI_DEVICE_PATH/sriov_totalvfs.

-
-
    -
  1. -

    Pass the VFs through to VMs using hypervisor interfaces.

    -
  2. -
  3. -

    Access the AFU on a VF from applications running on the VM using the same driver inside the VM.

    -
  4. -
-
-

Creating VFs is only supported for port devices. Consequently, PR and other management functions are only available through the PF.

-
-


-
-

If assigning multiple devices to the same VM on a guest IOMMU, you may need to increase the hard_limit option in order to avoid hitting a limit of pinned memory. The hard limit should be more than (VM memory size x Number of PCIe devices).

-
-

Driver Organization

-

PCIe Module Device Driver

-

Driver Organization

-

FPGA devices appear as a PCIe devices. Once enumeration detects a PCIe PF or VF, the Linux OS loads the FPGA PCIe -device driver. The device driver performs the following functions:

-
    -
  1. Walks through the Device Feature List in PCIe device base address register (BAR) memory to discover features -and their sub-features and creates necessary platform devices.
  2. -
  3. Enables SR-IOV.
  4. -
  5. Introduces the feature device infrastructure, which abstracts operations for sub-features and provides common functions -to feature device drivers.
  6. -
-

PCIe Module Device Driver Functions

-

The PCIe Module Device Driver performs the following functions:

-
    -
  1. PCIe discovery, device enumeration, and feature discovery.
  2. -
  3. Creates sysfs directories for the device, FME, and Port.
  4. -
  5. Creates the platform driver instances, causing the Linux kernel to load their respective drivers.
  6. -
-

FME Platform Module Device Driver

-

The FME Platform Module Device Driver loads automatically after the PCIe driver creates the -FME Platform Module. It provides the following features for FPGA management:

-
    -
  1. -

    Power and thermal management, error reporting, performance reporting, and other infrastructure functions. You can access -these functions via sysfs interfaces the FME driver provides.

    -
  2. -
  3. -

    Partial Reconfiguration. During PR sub-feature initialization, the FME driver registers the FPGA Manager framework -to support PR. When the FME receives the relevant ioctl request from user-space, it invokes the common interface -function from the FPGA Manager to reconfigure the AFU using PR.

    -
  4. -
  5. -

    Port management for virtualization (releasing/assigning port device).

    -
  6. -
-

After a port device is released, you can use the PCIe driver SR-IOV interfaces to create/destroy VFs.

-

For more information, refer to "FPGA Virtualization".

-

FME Platform Module Device Driver Functions

-

The FME Platform Module Device Driver performs the the following functions:

-
    -
  • Creates the FME character device node.
  • -
  • Creates the FME sysfs files and implements the FME sysfs file accessors.
  • -
  • Implements the FME private feature sub-drivers.
  • -
  • FME private feature sub-drivers: - * FME Header - * Partial Reconfiguration - * Global Error - * Global Performance
  • -
-

Port Platform Module Device Driver

-

After the PCIe Module Device Driver creates the Port Platform Module device, -the FPGA Port and AFU driver are loaded. This module provides an -interface for user-space applications to access the individual -accelerators, including basic reset control on the Port, AFU MMIO region -export, DMA buffer mapping service, and remote debug functions.

-

Port Platform Module Device Driver Functions

-

The Port Platform Module Device Driver performs the the following functions:

-
    -
  • Creates the Port character device node.
  • -
  • Creates the Port sysfs files and implements the Port sysfs file accessors.
  • -
  • Implements the following Port private feature sub-drivers. - * Port Header - * AFU - * Port Error - * Signal Tap
  • -
-

OPAE FPGA Driver Interface

-

The user-space interface consists of a sysfs hierarchy and ioctl requests. Most -kernel attributes can be accessed/modified via sysfs nodes in this hierarchy. -More complex I/O operations are controlled via ioctl requests. The OPAE API -implementation, libopae-c, has been designed to use this interface to -interact with the OPAE FPGA kernel drivers.

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/drv_arch/fme_init_flow.mscgen b/sw/drv_arch/fme_init_flow.mscgen deleted file mode 100644 index a8f836cf0..000000000 --- a/sw/drv_arch/fme_init_flow.mscgen +++ /dev/null @@ -1,12 +0,0 @@ -msc { - hscale = "2"; - - fme_probe,fme_dev_init,fpga_dev_feature_init,feature_instance_init,fpga_register_dev_ops; - - fme_probe=>fme_dev_init; - - fme_probe=>fpga_dev_feature_init; - fpga_dev_feature_init=>feature_instance_init; - - fme_probe=>fpga_register_dev_ops; -} diff --git a/sw/drv_arch/fme_init_flow.png b/sw/drv_arch/fme_init_flow.png deleted file mode 100644 index 9fd6167e8095a13ba432a4834e00fc238306d3df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4999 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 ZmsDYd(~Fni4M9^#|D2IdftFq9e*jM>Xs!SN diff --git a/sw/drv_arch/pci_init_flow.mscgen b/sw/drv_arch/pci_init_flow.mscgen deleted file mode 100644 index 71c579f99..000000000 --- a/sw/drv_arch/pci_init_flow.mscgen +++ /dev/null @@ -1,39 +0,0 @@ -msc { - hscale = "1"; - - ccidrv_init,b,c,d,e,cci_pci_probe,f,g,h,i,j,k,l,m,n,o,p,q,r,s; - -// parse_feature_list,parse_feature,parse_feature_afus,parse_feature_fme, -// build_info_create_dev,h,create_feature_instance,build_info_add_sub_feature, -// i,j,k; - - -// idr_init,alloc_chrdev_region,class_create,pci_register_driver, -// cci_pci_probe,create_init_drvdata,cci_pci_create_feature_devs, -// build_info_alloc_and_init,parse_feature_list,parse_feature,parse_feature_afus, -// parse_feature_fme,build_info_create_dev,idr_alloc,create_feature_instance,build_info_add_sub_feature, -// feature_platform_data_add,parse_ports_from_fme,build_info_commit_dev; - - ccidrv_init=>b [ label="idr_init" ]; - ccidrv_init=>c [ label="alloc_chrdev_region" ]; - ccidrv_init=>d [ label="class_create" ]; - ccidrv_init=>e [ label="pci_register_driver" ]; - - cci_pci_probe=>f [ label="create_init_drvdata" ]; - cci_pci_probe=>g [ label="cci_pci_create_feature_devs" ]; - - g=>h [ label="build_info_alloc_and_init" ]; - g=>i [ label="parse_feature_list" ]; - - i=>j [ label="parse_feature" ]; - j=>k [ label="parse_feature_afus" ]; - k=>l [ label="parse_feature_fme" ]; - l=>m [ label="build_info_create_dev" ]; - m=>n [ label="idr_alloc" ]; - k=>o [ label="create_feature_instance" ]; - o=>p [ label="build_info_add_sub_feature" ]; - p=>q [ label="feature_platform_data_add" ]; - - g=>r [ label="parse_ports_from_fme" ]; - g=>s [ label="build_info_commit_dev" ]; -} diff --git a/sw/drv_arch/port_init_flow.mscgen b/sw/drv_arch/port_init_flow.mscgen deleted file mode 100644 index 7394f7291..000000000 --- a/sw/drv_arch/port_init_flow.mscgen +++ /dev/null @@ -1,12 +0,0 @@ -msc { - hscale = "2"; - - afu_probe,afu_dev_init,fpga_dev_feature_init,feature_instance_init,fpga_register_dev_ops; - - afu_probe=>afu_dev_init; - - afu_probe=>fpga_dev_feature_init; - fpga_dev_feature_init=>feature_instance_init; - - afu_probe=>fpga_register_dev_ops; -} diff --git a/sw/drv_arch/port_init_flow.png b/sw/drv_arch/port_init_flow.png deleted file mode 100644 index f21e179daf6f92605bcd7e8d1bb3a4b57bd71b87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4919 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 ZWO5>%4Xu)!1hxX5Gq`xBQ152&zW^>oWPtzx diff --git a/sw/fpga_api/fpga_api/index.html b/sw/fpga_api/fpga_api/index.html deleted file mode 100644 index 8f674d628..000000000 --- a/sw/fpga_api/fpga_api/index.html +++ /dev/null @@ -1,2402 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - OPAE C API Reference - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

OPAE C API Reference

-

The reference documentation for the OPAE C API is grouped into the following sections:

- -

Types

-

The OPAE C API defines a number of types; most prominent are the types fpga_token, fpga_handle, and fpga_properties. All regular types are defined in types.h, while the values of enumeration types are defined in types_enum.h.

-

types.h

-

types.h

-

types_enum.h

-

types_enum.h

-

Enumeration API

-

The OPAE enumeration API allows selective discovery of FPGA resources. When enumerating resources, a list of filter criteria can be passed to the respective function to select a subset of all resources in the system. The fpgaEnumerate() function itself then returns a list of fpga_tokens denoting resources, which can be used in subsequent API calls.

-

Filter criteria are specified using one or more fpga_properties object. These objects need to be created using fpgaGetProperties() (defined in ) before being passed to fpgaEnumerate(). Individual attributes of an fpga_properties object are set using specific accessors, which are also defined in .

-

enum.h

-

enum.h

-

properties.h

-

properties.h

-

Access API

-

The access API provides functions for opening and closing FPGA resources. Opening a resource yields an fpga_handle, which denotes ownership and can be used in subsequent API calls to interact with a specific resource. Ownership can be exclusive or shared.

-

access.h

-

access.h

-

Event API

-

The event API provides functions and types for handling asynchronous events such as errors or accelerator interrupts.

-

To natively support asynchronous event, the driver for the FPGA platform needs to support events natively (in which case the OPAE C library will register the event directly with the driver). For some platforms that do not support interrupt-driven event delivery, you need to run the FPGA Daemon (fpgad) to enable asynchronous OPAE events. fpgad will act as a proxy for the application and deliver asynchronous notifications for registered events.

-

event.h

-

event.h

-

MMIO and Shared Memory APIs

-

These APIs feature functions for mapping and accessing control registers through memory-mapped IO (mmio.h), allocating and sharing system memory buffers with an accelerator (buffer.h), and using low-latency notifications (umsg.h).

-

mmio.h

-

mmio.h

-

buffer.h

-

buffer.h

-

umsg.h

-

umsg.h

-

Management API

-

The management APIs define functions for reconfiguring an FPGA (writing new partial bitstreams) as well as assigning accelerators to host interfaces.

-

manage.h

-

manage.h

-

Metrics API

-

The metrics APIs define functions for discovery/enumeration of metrics information and reading metrics values.

-

metrics.h

-

metrics.h

-

SysObject

-

The SysObject API can be used to get system objects by name. Names used with the SysObject API are driver-specific and may not be compatible across plugins and/or drivers. For example, SysObject names used with the xfpga plugin will apply to the OPAE Linux Kernel driver and refer to sysfs nodes under the sysfs tree for the resource used with the SysObject API.

-

sysobject.h

-

sysobject.h

-

Utilities

-

Functions for mapping fpga_result values to meaningful error strings are provided by the utilities API.

-

utils.h

-

utils.h

-

Samples

-

Code samples demonstrate how to use OPAE C API.

-

hello_fpga.c

-

hello_fpga.c

-

hello_events.c

-

hello_events.c

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_api/fpga_cxx_api/index.html b/sw/fpga_api/fpga_cxx_api/index.html deleted file mode 100644 index 9edbf5b79..000000000 --- a/sw/fpga_api/fpga_cxx_api/index.html +++ /dev/null @@ -1,2255 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - OPAE C++ Core API Reference - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

OPAE C++ Core API Reference

-

The reference documentation for the OPAE C++ Core API is grouped into the following sections:

- -

Overview

-

The OPAE C++ API enables C++ developers with the means to use FPGA resources by integrating the OPAE software stack into C++ applications.

-

Goals

-

Simplicity

-

Keep the API as small and lightweight as possible. Although features such as system validation and orchestration are beyond the scope of this API, using this API for their development should be relatively easy.

-

Extensibility and Interoperability

-

While keeping to the goal of simplicity, the OPAE C++ API is designed to allow for better reuse by either extending the API or by integrating with other languages.

-

Modern C++ Coding Practices

-

The OPAE C++ API uses the C++ 11 standard library and makes use of its features whenever practical. The OPAE C++ API is also designed to require the minimum number of third-party libraries/dependencies.

-

Error Handling

-

The OPAE C++ API is designed to throw exceptions when appropriate. The structure of OPAE C++ exceptions is similar to the error codes in the OPAE C API. This gives users of the API more freedom on error handling while providing better debug information in cases of failure.

-

Coding Style

-

For formatting of the OPAE C++ API complies with most of the recommendations of the Google C++ style. For example, the OPAE C++ API uses:

-
    -
  • opening braces on the same line as their scope definition
  • -
  • spaces instead of tabs for indentation
  • -
  • indentation of two spaces
  • -
-

Fundamental Types

-

Basic types for the OPAE C++ API are found in the opae::fpga::types namespace. They serve as an adapter layer between the OPAE C API and the OPAE C++ layer. Aside from providing a C++ binding to the C fundamental types, these types also:

-
    -
  • manage the lifetime and scope of the corresponding C struct.
  • -
-
-
    -
  • For example a C++ destructor will take care of calling the appropriate C function to release the data structure being wrapped.
  • -
-
-
    -
  • provide a friendly syntax for using the OPAE C type.
  • -
-

Most classes in this namespace have a c_type() method that returns the C data structure being wrapped, making it easy to use the OPAE C++ type with the OPAE C API. Alternatively, most classes in this namespace have implicit conversion operators that enable interoperability with the OPAE C API.

-

Properties

-

C++ class properties wraps fpga_properties and uses pvalue and guid_t to get and set properties stored in an instance of an fpga_properties. pvalue and guid_t are designed to call an accessor method in the OPAE C API to either read property values or write them. Most accessor methods in the OPAE C API share a similar signature, so pvalue generalizes them into common operations that translate into calling the corresponding C API function. guid_t follows similar patterns when reading or assigning values.

-

pvalue.h

-

pvalue.h

-

properties.h

-

properties.h

-

Resource Classes

-

The token, handle, and shared_buffer classes are used to enumerate and access FPGA resources. properties are used to narrow the search space for token's. Before enumerating the accelerator resources in the system, applications can produce one or more properties objects whose values are set to the desired characteristics for the resource. For example, an application may search for an accelerator resource based on its guid.

-

Once one or more token's have been enumerated, the application must choose which token's to request. The token is then converted to a handle by requesting that a handle object be allocated and opened for it.

-

Once a handle has been successfully opened, the application can read and write the associated configuration and status space. Additionally, the application may use the handle to allocate shared_buffer's or to register event's. The shared_buffer and event objects retain a reference to their owning handle so that the handle does not lose scope before freeing the shared_buffer and event objects.

-

token.h

-

token.h

-

handle.h

-

handle.h

-

shared_buffer.h

-

shared_buffer.h

-

errors.h

-

errors.h

-

events.h

-

events.h

-

sysobject.h

-

sysobject.h

-

Exceptions

-

When the OPAE C++ API encounters an error from the OPAE C API, it captures the current source code location and the error code into an object of type except, then throws the except. Applications should implement the appropriate catch blocks required to respond to runtime exceptions.

-

except.h

-

except.h

-

Misc

-

The version class wraps the OPAE C version API.

-

version.h

-

version.h

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_api/fpga_python_api/index.html b/sw/fpga_api/fpga_python_api/index.html deleted file mode 100644 index 0137b6118..000000000 --- a/sw/fpga_api/fpga_python_api/index.html +++ /dev/null @@ -1,1993 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - OPAE Python API Reference - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
- -
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_api/plug_guide/readme/index.html b/sw/fpga_api/plug_guide/readme/index.html deleted file mode 100644 index 7890115e2..000000000 --- a/sw/fpga_api/plug_guide/readme/index.html +++ /dev/null @@ -1,2296 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - OPAE Plugin Developers Guide - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

Plugin Developer's Guide

-

Overview

-

Beginning with OPAE C library version 1.2.0, OPAE implements a plugin-centric -model. This guide serves as a reference to define the makeup of an OPAE C API -plugin and to describe a sequence of steps that one may follow when constructing -an OPAE C API plugin.

-

Plugin Required Functions

-

An OPAE C API plugin is a runtime-loadable shared object library, also known as -a module. On Linux systems, the dl family of APIs from libdl are used to -interact with shared objects. Refer to "man dlopen" and "man dlsym" for examples -of using the libdl API.

-

An OPAE C API plugin implements one required function. This function is required -to have C linkage, so that its name is not mangled.

-
    int opae_plugin_configure(opae_api_adapter_table *table, const char *config);
-
-

During initialization, the OPAE plugin manager component loads each plugin, -searching for its opae_plugin_configure function. If none is found, then -the plugin manager rejects that plugin. When it is found, opae_plugin_configure -is called passing a pointer to a freshly-created opae_api_adapter_table and -a buffer consisting of configuration data for the plugin.

-

The job of the opae_plugin_configure function is to populate the given adapter -table with each of the plugin's API entry points and to consume and comprehend -the given configuration data in preparation for initialization.

-

OPAE API Adapter Table

-

The adapter table is a data structure that contains function pointer entry points -for each of the OPAE APIs implemented by a plugin. In this way, it adapts the -plugin-specific behavior to the more general case of a flat C API. Note that -OPAE applications are only required to link with opae-c. In other words, the -name of the plugin library should not appear on the linker command line. In this -way, plugins are truly decoupled from the OPAE C API, and they are required to -adapt to the strict API specification by populating the adapter table only. No -other linkage is required nor recommended.

-

adapter.h contains the definition of the opae_api_adapter_table. An abbreviated -version is depicted below, along with supporting type opae_plugin:

-
    typedef struct _opae_plugin {
-        char *path;
-        void *dl_handle;
-    } opae_plugin;
-
-    typedef struct _opae_api_adapter_table {
-
-        struct _opae_api_adapater_table *next;
-        opae_plugin plugin;
-
-        fpga_result (*fpgaOpen)(fpga_token token, fpga_handle *handle,
-                                int flags);
-
-        fpga_result (*fpgaClose)(fpga_handle handle);
-
-        ...
-
-        fpga_result (*fpgaEnumerate)(const fpga_properties *filters,
-                                     uint32_t num_filters, fpga_token *tokens,
-                                     uint32_t max_tokens,
-                                     uint32_t *num_matches);
-
-        ...
-
-        // configuration functions
-        int (*initialize)(void);
-        int (*finalize)(void);
-
-        // first-level query
-        bool (*supports_device)(const char *device_type);
-        bool (*supports_host)(const char *hostname);
-
-    } opae_api_adapter_table;
-
-

Some points worth noting are that the adapter tables are organized in memory by -adding them to a linked list data structure. This is the use of the next -structure member. (The list management is handled by the plugin manager.) -The plugin structure member contains the handle to the shared object instance, -as created by dlopen. This handle is used in the plugin's opae_plugin_configure -to load plugin entry points. A plugin need only implement the portion of the -OPAE C API that a target application needs. Any API entry points that are not -supported should be left as NULL pointers (the default) in the adapter table. -When an OPAE API that has no associated entry point in the adapter table is -called, the result for objects associated with that plugin will be -FPGA_NOT_SUPPORTED.

-

The following code illustrates a portion of the opae_plugin_configure for -a theoretical OPAE C API plugin libfoo.so:

-
    /* foo_plugin.c */
-
-    int opae_plugin_configure(opae_api_adapter_table *table, const char *config)
-    {
-        adapter->fpgaOpen = dlsym(adapter->plugin.dl_handle, "foo_fpgaOpen");
-        adapter->fpgaClose =
-                dlsym(adapter->plugin.dl_handle, "foo_fpgaClose");
-
-        ...
-
-        adapter->fpgaEnumerate =
-                dlsym(adapter->plugin.dl_handle, "foo_fpgaEnumerate");
-
-        ...
-
-        return 0;
-    }
-
-

Notice that the implementations of the API entry points for plugin libfoo.so -are prefixed with foo_. This is the recommended practice to avoid name -collisions and to enhance the debugability of the application. Upon successful -configuration, opae_plugin_configure returns 0 to indicate success. A -non-zero return value indicates failure and causes the plugin manager to -reject the plugin from futher consideration.

-

Plugin Optional Functions

-

Once the plugin manager loads and configures each plugin, it uses the adapter -table to call back into the plugin so that it can be made ready for runtime. -This is the job of the opae_plugin_initialize entry point, whose signature -is defined as:

-
    int opae_plugin_initialize(void);
-
-

The function takes no parameters, as the configuration data was already given -to the plugin by opae_plugin_configure. opae_plugin_initialize returns 0 -if no errors were encountered during initialization. A non-zero return code -indicates that plugin initialization failed. A plugin makes its -opae_plugin_initialize available to the plugin manager by populating the -adapter table's initialize entry point as shown:

-
    /* foo_plugin.c */
-
-    int foo_plugin_initialize(void)
-    {
-        ...
-
-        return 0; /* success */
-    }
-
-    int opae_plugin_configure(opae_api_adapter_table *table, const char *config)
-    {
-        ... 
-
-        adapter->initialize =
-                dlsym(adapter->plugin.dl_handle, "foo_plugin_initialize");
-
-        ...
-
-        return 0;
-    }
-
-

If a plugin does not implement an opae_plugin_initialize entry point, then -the initialize member of the adapter table should be left uninitialized. -During plugin initialization, if a plugin has no opae_plugin_initialize -entry in its adapter table, the plugin initialization step will be skipped, -and the plugin will be considered to have initialized successfully.

-

Once plugin initialization is complete for all loaded plugins, the system -is considered to be running and fully functional.

-

During teardown, the plugin manager uses the adapter table to call into each -plugin's opae_plugin_finalize entry point, whose signature is defined as:

-
    int opae_plugin_finalize(void);
-
-

opae_plugin_finalize returns 0 if no errors were encountered during teardown. -A non-zero return code indicates that plugin teardown failed. A plugin makes -its opae_plugin_finalize available to the plugin manager by populating the -adapter table's finalize entry point as shown:

-
    /* foo_plugin.c */
-
-    int foo_plugin_finalize(void)
-    {
-        ...
-
-        return 0; /* success */
-    }
-
-    int opae_plugin_configure(opae_api_adapter_table *table, const char *config)
-    {
-        ... 
-
-        adapter->finalize =
-                dlsym(adapter->plugin.dl_handle, "foo_plugin_finalize");
-
-        ...
-
-        return 0;
-    }
-
-

If a plugin does not implement an opae_plugin_finalize entry point, then -the finalize member of the adapter table should be left uninitialized. -During plugin cleanup, if a plugin has no opae_plugin_finalize entry -point in its adapter table, the plugin finalize step will be skipped, and -the plugin will be considered to have finalized successfully.

-

In addition to initialize and finalize, an OPAE C API plugin has two -further optional entry points that relate to device enumeration. During -enumeration, when a plugin is being considered for a type of device, the -plugin may provide input on that decision by exporting an -opae_plugin_supports_device entry point in the adapter table:

-
    bool opae_plugin_supports_device(const char *device_type);
-
-

opae_plugin_supports_device returns true if the given device type is -supported and false if it is not. A false return value from -opae_plugin_supports_device causes device enumeration to skip the -plugin.

-

Populating the opae_plugin_supports_device is done as:

-
    /* foo_plugin.c */
-
-    bool foo_plugin_supports_device(const char *device_type)
-    {
-        if (/* device_type is supported */)
-            return true;
-
-        ...
-
-        return false;
-    }
-
-    int opae_plugin_configure(opae_api_adapter_table *table, const char *config)
-    {
-        ... 
-
-        adapter->supports_device =
-                dlsym(adapter->plugin.dl_handle, "foo_plugin_supports_device");
-
-        ...
-
-        return 0;
-    }
-
-
.. note::
-    The `opae_plugin_supports_device` mechanism serves as a placeholder only.
-    It is not implemented in the current version of the OPAE C API.
-
-

Similarly to determining whether a plugin supports a type of device, a plugin -may also answer questions about network host support by populating an -opae_plugin_supports_host entry point in the adapter table:

-
    bool opae_plugin_supports_host(const char *hostname);
-
-

opae_plugin_supports_host returns true if the given hostname is supported -and false if it is not. A false return value from opae_plugin_supports_host -causes device enumeration to skip the plugin.

-

Populating the opae_plugin_supports_host is done as:

-
    /* foo_plugin.c */
-
-    bool foo_plugin_supports_host(const char *hostname)
-    {
-        if (/* hostname is supported */)
-            return true;
-
-        ...
-
-        return false;
-    }
-
-    int opae_plugin_configure(opae_api_adapter_table *table, const char *config)
-    {
-        ... 
-
-        adapter->supports_host =
-                dlsym(adapter->plugin.dl_handle, "foo_plugin_supports_host");
-
-        ...
-
-        return 0;
-    }
-
-
.. note::
-    The `opae_plugin_supports_host` mechanism serves as a placeholder only.
-    It is not implemented in the current version of the OPAE C API.
-
-

Plugin Construction

-

The steps required to implement an OPAE C API plugin, libfoo.so, are:

-
    -
  • Create foo_plugin.c: implements opae_plugin_configure, -opae_plugin_initialize, opae_plugin_finalize, opae_plugin_supports_device, -and opae_plugin_supports_host as described in the previous sections.
  • -
  • Create foo_plugin.h: implements function prototypes for each of the -plugin-specific OPAE C APIs.
  • -
-
    /* foo_plugin.h */
-
-    fpga_result foo_fpgaOpen(fpga_token token, fpga_handle *handle,
-                             int flags);
-
-    fpga_result foo_fpgaClose(fpga_handle handle);
-
-    ...
-
-    fpga_result foo_fpgaEnumerate(const fpga_properties *filters,
-                                  uint32_t num_filters, fpga_token *tokens,
-                                  uint32_t max_tokens,
-                                  uint32_t *num_matches);
-    ...
-
-
    -
  • Create foo_types.h: implements plugin-specific types for opaque data -structures.
  • -
-
    /* foo_types.h */
-
-    struct _foo_token {
-        ...
-    };
-
-    struct _foo_handle {
-        ...
-    };
-
-    struct _foo_event_handle {
-        ...
-    };
-
-    struct _foo_object {
-        ...
-    };
-
-
    -
  • Create foo_enum.c: implements foo_fpgaEnumerate, -foo_fpgaCloneToken, and foo_fpgaDestroyToken.
  • -
  • Create foo_open.c: implements foo_fpgaOpen.
  • -
  • Create foo_close.c: implements foo_fpgaClose.
  • -
  • Create foo_props.c: implements foo_fpgaGetProperties, -foo_fpgaGetPropertiesFromHandle, foo_fpgaUpdateProperties
  • -
  • Create foo_mmio.c: implements foo_fpgaMapMMIO, foo_fpgaUnmapMMIO -foo_fpgaWriteMMIO64, foo_fpgaReadMMIO64, foo_fpgaWriteMMIO32, -foo_fpgaReadMMIO32.
  • -
  • Create foo_buff.c: implements foo_fpgaPrepareBuffer, -foo_fpgaReleaseBuffer, foo_fpgaGetIOAddress.
  • -
  • Create foo_error.c: implements foo_fpgaReadError, foo_fpgaClearError, -foo_fpgaClearAllErrors, foo_fpgaGetErrorInfo.
  • -
  • Create foo_event.c: implements foo_fpgaCreateEventHandle, -foo_fpgaDestroyEventHandle, foo_fpgaGetOSObjectFromEventHandle, -foo_fpgaRegisterEvent, foo_fpgaUnregisterEvent.
  • -
  • Create foo_reconf.c: implements foo_fpgaReconfigureSlot.
  • -
  • Create foo_obj.c: implements foo_fpgaTokenGetObject, -foo_fpgaHandleGetObject, foo_fpgaObjectGetObject, -foo_fpgaDestroyObject, foo_fpgaObjectGetSize, foo_fpgaObjectRead, -foo_fpgaObjectRead64, foo_fpgaObjectWrite64.
  • -
  • Create foo_clk.c: implements foo_fpgaSetUserClock, -foo_fpgaGetUserClock.
  • -
- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_api/prog_guide/FPGA-lib-1.png b/sw/fpga_api/prog_guide/FPGA-lib-1.png deleted file mode 100644 index f815ca6ada34aef78cb14b596d3b32fdd95419c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65857 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%0D``88GuUqLorb%xc0JjyrBU4Ae`z4#|rr&j! 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 diff --git a/sw/fpga_api/prog_guide/FPGA-lib-2.png b/sw/fpga_api/prog_guide/FPGA-lib-2.png deleted file mode 100644 index fc92a24661fa3fa72a323b3da446e78df2582f70..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27097 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 I<+(;He-z)`O@eY)d0DeiJTy2i8tLjsk0sfHm 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 - - - - - - - - - - - - - - - - - - - - OPAE C API Programming Guide - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - - - - - -
-
- - - - - - - -

OPAE C API Programming Guide

-

Overview

-

The OPAE C library (libopae-c) is a lightweight user-space library that -provides abstractions for FPGA resources in a compute environment. The OPAE C library -builds on the driver stack that supports the FPGA device, abstracting -hardware- and OS-specific details. It provides access to the underlying FPGA -resources as a set of features available to software programs -running on the host. These features include the acceleration logic -preconfigured on the FPGA and functions to manage and reconfigure -the FPGA. The library enables your applications to -transparently and seamlessly benefit from FPGA-based acceleration.

-

Layered architecture

-

By providing a unified C API, the library supports different FPGA -integration and deployment models, ranging from single-node systems with one or -a few FPGA devices to large-scale FPGA deployments in a data center. -At one end of the spectrum, the API supports a simple application using a PCIe link to reconfigure -the FPGA with different accelerator functions. At the other end of the spectrum, resource -management and orchestration services in a data center can use this API to -discover and select FPGA resources and then allocate them for use by acceleration workloads.

-

OPAE Role

-

The OPAE provides a common base layer for a wide range of -applications without sacrificing performance or efficiency. The abstraction layer limits -the details of the FPGA hardware that software applications must handle.

-

The OPAE provides consistent interfaces to crucial components of the platform. The OPAE does not constrain -frameworks and applications by making optimizations with limited applicability. When the OPAE does -provide convenience functions or optimizations, they are optional.

-

For example, the OPAE provides an interface to allocate physically contiguous -buffers in system memory that user-space software and an accelerator can share. -This interface enables the most basic feature set of -allocating and sharing a large page of memory in one API call. However, it -does not provide a malloc()-like interface backed by a memory pool or slab -allocator. Higher layers of the software stack can make such -domain-specific optimizations.

-

Intel Accelerator Stack Hardware Terminology

-

The following terms define the hardware and hardware processes involved in creating an accelerator function.

-
    -
  • FPGA: Field Programmable Gate Array -is a discrete or integrated device connecting to a host CPU via PCIe or other type of interconnects.
  • -
  • Accelerator Function Unit (AFU): The AFU is the supplied implementation of an accelerator, typically -in HDL. AFUs implement a function such as compression, encryption, or mathematical operations. -The Quartus Prime Pro software synthesizes the RTL logic into a bitstream.
  • -
  • Accelerator Function (AF): The AF is the compiled binary for an AFU. An AF is a raw binary file (.rbf) -bitstream. A tool (fpgaconf) reconfigures the FPGA using an AF bitstream.
  • -
  • Reconfiguration: The process of reprogramming the FPGA with a different AF.
  • -
-

OPAE Software Concepts Reflected in the C API

-

The following OPAE data structures and functions integrate AFUs into the OPAE environment. -The OPAE C API models these data structures and functions. For more information on the object -models refer to the Object model section.

-
    -
  • Accelerator: An accelerator is an allocable accelerator function implemented in an FPGA. -An accelerator tracks the ownership of an AFU (or part of it) for a process that uses it. -Multiple processes can share an accelerator.
  • -
  • Device: The OPAE enumerates and models two device types: the FPGA and the AFU.
  • -
  • Events: Events are asynchronous notifications. The FPGA driver -triggers particular events to indicate error conditions. Accelerator logic can also -define its own events. User applications can choose to be -notified when particular events occur and respond appropriately.
  • -
  • Shared memory buffers: Software allocates shared memory buffers in user process memory -on the host. Shared memory buffers facilitate data transfers between the user process and the -accelerator that it owns.
  • -
-

OPAE Library

-

Linking with this library is straightforward. -Code using the OPAE library should include the header file fpga.h. Taking the GCC -compiler on Linux as an example, here is the simplest compile and link command:

-

gcc myprog.c -I</path/to/fpga.h> -L</path/to/libopae-c.so> -lopae-c -luuid -ljson-c -lpthread

-

.. note::

-
The OPAE library uses the third-party `libuuid` and `libjson-c` libraries that are not distributed with 
-the OPAE library. Make sure to install these libraries.
-
-

Sample Code

-

The library source includes two code samples. Use these samples -to learn how to call functions in the library. Build and run these samples -to determine if your installation and environment are set up properly.

-

Refer to the Running the Hello FPGA Example chapter in the Intel® Acceleration Stack -Quick Start Guide for for Intel Programmable Acceleration Card with Intel Arria® 10 GX FPGA for more information about using the sample code.

-

High-Level Directory Structure

-

Building and installing the OPAE library results in the following directory structure on the Linux OS. -Windows and MacOS have similar directories and files.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory & FilesContents
include/opaeDirectory containing all header files
include/opae/fpga.hTop-level header for user code to include
include/opae/access.hHeader file for accelerator acquire/release, MMIO, memory management, event handling, and so on
include/opae/bitstream.hHeader file for bitstream manipulation functions
include/opae/common.hHeader file for error reporting functions
include/opae/enum.hHeader file for AFU enumeration functions
include/opae/manage.hHeader file for FPGA management functions
include/opae/types.hVarious type definitions
libDirectory containing shared library files
lib/libopae-c.soThe shared dynamic library for linking with the user application
docDirectory containing API documentation
doc/htmlDirectory for documentation of HTML format
doc/latexDirectory for documentation of LaTex format
doc/manDirectory for documentation of Unix man page format
-

Basic Application Flow

-

The figure below shows the basic application flow from the -viewpoint of a user-process.

-

Basic flow

-

API Components

-

The API object model abstracts the physical FPGA device and -available functions. It is a generalized model and extends to -describe any FPGA type.

-

Object Models

-
    -
  • fpga_objtype: An enum type that represents the type of an FPGA resource, either FPGA_DEVICE or FPGA_ACCELERATOR. -An FPGA_DEVICE object corresponds to a physical FPGA device. Only FPGA_DEVICE objects can invoke management functions. -The FPGA_ACCELERATOR represents an instance of an AFU.
  • -
  • fpga_token: An opaque type that represents a resource known to, but not -necessarily owned by, the calling process. The calling process must own a -resource before it can invoke functions of the resource.
  • -
  • fpga_handle: An opaque type that represents a resource owned by the -calling process. The API functions fpgaOpen() and fpgaClose() acquire and release ownership of a resource that an fpga_handle represents. (Refer to the Functions section for more information.)
  • -
  • fpga_properties: An opaque type for a properties object. Your -applications use these properties to query and search for appropriate resources. The -FPGA Resource Properties section documents properties visible to your -applications.
  • -
  • fpga_event_handle: An opaque handle the FPGA driver uses to notify your -application about an event.
  • -
  • fpga_event_type: An enum type that represents the types of events. The following are valid values: -FPGA_EVENT_INTERRUPT, FPGA_EVENT_ERROR, and FPGA_EVENT_POWER_THERMAL. (The Intel Programmable Acceleration Card (PAC) with -Intel Arria 10 GX FPGA does not handle thermal and power events.)
  • -
  • fpga_result: An enum type to represent the result of an API function. If the -function returns successfully the result is FPGA_OK. Otherwise, the result is -the appropriate error codes. Function fpgaErrStr() translates an error code -into human-readable strings.
  • -
-

Functions

-

The table below groups important API calls by their functionality. For more information about each of the functions, refer to the -OPAE C API reference manual.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionalityAPI CallFPGAAcceleratorDescription
EnumerationfpgaEnumerate()YesYesQuery FPGA resources that match certain properties
Enumeration: Propertiesfpga[Get, Update, Clear, Clone, Destroy Properties]()YesYesManage fpga_properties life cycle
fpgaPropertiesGet[Prop]()YesYesGet the specified property Prop, from the FPGA Resource Properties table
fpgaPropertiesSet[Prop]()YesYesSet the specified property Prop, from the FPGA Resource Properties table
Access: Ownershipfpga[Open, Close]()YesYesAcquire/release ownership
Access: ResetfpgaReset()YesYesReset an accelerator
Access: Event handlingfpga[Register, Unregister]Event()YesYesRegister/unregister an event to be notified about
fpga[Create, Destroy]EventHandle()YesYesManage fpga_event_handle life cycle
Access: MMIOfpgaMapMMIO(), fpgaUnMapMMIO()YesYesMap/unmap MMIO space
fpgaGetMMIOInfo()YesYesGet information about the specified MMIO space
fpgaReadMMIO[32, 64]()YesYesRead a 32-bit or 64-bit value from MMIO space
fpgaWriteMMIO[32, 64]()YesYesWrite a 32-bit or 64-bit value to MMIO space
Memory management: Shared memoryfpga[Prepare, Release]Buffer()YesYesManage memory buffer shared between the calling process and an accelerator
fpgaGetIOAddress()YesYesReturn the device I/O address of a shared memory buffer
Management: ReconfigurationfpgaReconfigureSlot()YesNoReplace an existing AFU with a new one
Error reportfpgaErrStr()YesYesMap an error code to a human readable string
-

.. note::

-
The UMsg APIs are not supported for the Intel(R) PAC cards. They will be deprecated in a future release.
-
-

FPGA Resource Properties

-

Applications query resource properties by specifying the property name for Prop in the -fpgaPropertiesGet[Prop]() and fpgaPropertiesSet[Prop]() functions. The FPGA and Accelerator -columns state whether or not the Property is available for the FPGA or Accelerator objects.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PropertyFPGAAcceleratorDescription
ParentNoYesfpga_token of the parent object
ObjectTypeYesYesThe type of the resource: either FPGA_DEVICE or FPGA_ACCELERATOR
BusYesYesThe bus number
DeviceYesYesThe PCI device number
FunctionYesYesThe PCI function number
SocketIdYesYesThe socket ID
DeviceIdYesYesThe device ID
NumSlotsYesNoNumber of AFU slots available on an FPGA_DEVICE resource
BBSIDYesNoThe FPGA Interface Manager (FIM) ID of an FPGA_DEVICE resource
BBSVersionYesNoThe FIM version of an FPGA_DEVICE resource
VendorIdYesNoThe vendor ID of an FPGA_DEVICE resource
GUIDYesYesThe GUID of an FPGA_DEVICE or FPGA_ACCELERATOR resource
NumMMIONoYesThe number of MMIO space of an FPGA_ACCELERATOR resource
NumInterruptsNoYesThe number of interrupts of an FPGA_ACCELERATOR resource
AcceleratorStateNoYesThe state of an FPGA_ACCELERATOR resource: either FPGA_ACCELERATOR_ASSIGNED or FPGA_ACCELERATOR_UNASSIGNED
-

OPAE C API Return Codes

-

The OPAE C library returns a code for every exported public API function. FPGA_OK indicates successful completion -of the requested operation. Any return code other than FPGA_OK indicates an error or unexpected -behavior. When using the OPAE C API, always check the API return codes.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Error CodeDescription
FPGA_OKOperation completed successfully
FPGA_INVALID_PARAMInvalid parameter supplied
FPGA_BUSYResource is busy
FPGA_EXCEPTIONAn exception occurred
FPGA_NOT_FOUNDA required resource was not found
FPGA_NO_MEMORYNot enough memory to complete operation
FPGA_NOT_SUPPORTEDRequested operation is not supported
FPGA_NO_DRIVERDriver is not loaded
FPGA_NO_DAEMONFPGA Daemon (fpgad) is not running
FPGA_NO_ACCESSInsufficient privileges or permissions
FPGA_RECONF_ERRORError while reconfiguring FPGA
-

Usage Models

-

Query and Search for a Resource

-

The user-code first populates an fpga_properties object with the required properties. -Then, fpgaEnumerate() searches for matching resources. fpgaEnumerate() may return more -than one matching resource.

-
#include "fpga/fpga.h"
-
-fpga_guid               guid;
-fpga_properties         filter = NULL;
-fpga_result             res;
-fpga_token              tokens[MAX_NUM_TOKENS];
-uint32_t                num_matches = 0;
-
-/* Start with an empty properties object */
-res = fpgaGetProperties(NULL, &filter);
-
-/* Populate the properties object with required values.
-   In this case, search for accelerators that matches 
-   the specified GUID.
-*/
-uuid_parse(GUID, guid);
-res = fpgaPropertiesSetObjectType(filter, FPGA_ACCELERATOR);
-res = fpgaPropertiesSetGuid(filter, guid);
-
-/* Query the number of matching resources */
-res = fpgaEnumerate(&filter, 1, NULL, 1, &num_matches);
-
-/* Return tokens for all matching resources */
-res = fpgaEnumerate(&filter, 1, tokens, num_matches, &num_matches);
-
-/* Destroy the properties object */
-res = fpgaDestroyProperties(&filter);
-
-/* More code */
-......
-
-/* Destroy tokens */
-for (uint32_t i = 0; i < num_matches; ++i) {
-    res = fpgaDestroyToken(tokens[i]);
-}
-
-

The fpgaEnumerate() function can take multiple fpga_propertiesobjects in an array. In such cases, -the function performs a logical OR of the properties object and returns resources that match any of -the multiple properties. The fpga_token objects that fpgaEnumerate() returns, do not signify -ownership. To acquire ownership of a resource represented by a token, pass the token to fpgaOpen().

-

Acquire and Release a Resource

-

Use fpgaOpen() and fpgaClose() to acquire and release ownership of a resource. -The calling process must own the resource before it can initiate MMIO, access share memory buffers, -and use functions offered by the resource.

-
    #include "fpga/fpga.h"
-
-    fpga_handle             handle;
-    fpga_result             res;
-
-    /* Acquire ownership of a resource that 
-    `fpgaEnumerate()` previously returned as a token */
-
-    res = fpgaOpen(token, &handle);
-
-    /* More code */
-    ......
-
-    /* Release the ownership */
-    res = fpgaClose(handle);
-
-

Shared Memory Buffer

-

This code snippet shows how to prepare a memory buffer to be shared between the -calling process and an accelerator.

-
    #include "fpga/fpga.h"
-
-    fpga_handle             handle;
-    fpga_result             res;
-
-    /* Hint for the virtual address of the buffer */
-    volatile uint64_t       *addr_hint;
-    /* An ID we can use to reference the buffer later */
-    uint32_t                bufid;
-    /* Flag to indicate whether or not the buffer is preallocated */
-    int                     flag = 0;
-
-    /* Allocate (if necessary), pin, and map a buffer to be accessible
-       by an accelerator
-    */
-    res = fpgaPrepareBuffer(handle, BUF_SIZE, (void **) &addr_hint,
-                            &bufid, flag);
-
-    /* The actual address mapped to the buffer */
-    uint64_t                iova;
-    /* Get the IO virtual address for the buffer */
-    res = fpgaGetIOAddress(handle, bufid, &iova);
-
-    /* Inform the accelerator about the virtual address by writing to its mapped
-       register file
-    */
-    ......
-
-    /* More code */
-    ......
-
-    /* Release the shared buffer */
-    res = fpgaReleaseBuffer(handle, bufid);
-
-

.. note::

-
The `flag` variable can take a constant `FPGA_BUF_PREALLOCATED` to
-indicate that the calling process has already allocated the address space
-that `addr_hint` points to.
-
-

MMIO

-

This code snippet shows how to map and unmap the register file of an accelerator into the -calling process's virtual memory space.

-
    #include "fpga/fpga.h"
-
-    fpga_handle             handle;
-    fpga_result             res;
-
-    /* Index of the MMIO space. There might be multiple spaces on an accelerator */
-    uint32_t                mmio_num = 0;
-    /* Mapped address */
-    uint64_t                mmio_addr;
-
-    /* Map MMIO */
-    res = fpgaMapMMIO(handle, mmio_num, &mmio_addr);
-
-    /* Write to a 32-bit value to the mapped register file at a certain byte
-       offset.
-
-       CSR_CTL is the offset in the mapped space to where the value will be
-       written. It's defined elsewhere.
-    */
-    res = fpgaWriteMMIO32(handle, mmio_num, CSR_CTL, value);
-
-    /* More code */
-    ......
-
-    /* Unmap MMIO */
-    res = fpgaUnmapMMIO(handle, mmio_num);
-
-

.. Note::

-
Every AFU has its own register adress space and its own protocol to control operation through 
-the registers. 
-
- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_api/quick_start/readme/index.html b/sw/fpga_api/quick_start/readme/index.html deleted file mode 100644 index 096436e0c..000000000 --- a/sw/fpga_api/quick_start/readme/index.html +++ /dev/null @@ -1,2365 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - Quick Start Guide - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - - - - - -
-
- - - - - - - -

Quick Start Guide

-

Overview

-

The OPAE C library is a lightweight user-space library that provides -an abstraction for FPGA resources in a compute environment. Built on top of the -OPAE Intel® FPGA driver stack that supports Intel® FPGA platforms, the library -abstracts away hardware-specific and OS-specific details and exposes the -underlying FPGA resources as a set of features accessible from within -software programs running on the host.

-

These features include the acceleration logic preconfigured on the -device, as well as functions to manage and reconfigure the -device. Hence, the library can enable user applications to -transparently and seamlessly leverage FPGA-based acceleration.

-

In this document, we will explore the initial steps on how to set up -the required libraries and utilities to use the FPGA devices.

-

If you do not have access to an Intel® Xeon® processor with integrated -FPGA, or a programmable FPGA acceleration card for Intel® Xeon® -processors, you will not be able to run the examples below. However, you can -still make use of the AFU simulation environment (ASE) to develop and test -accelerator RTL with OPAE applications.

-

The source for the OPAE SDK Linux device drivers is available at the -OPAE Linux DFL drivers repository.

-

Build the OPAE Linux device drivers from the source

-

For building the OPAE kernel and kernel driver, the kernel development environment is required. So before you build the kernel, you must install the required packages. Run the following commands (we are using Fedora 32 as an example):

-
sudo yum install gcc gcc-c++ make kernel-headers kernel-devel elfutils-libelf-devel ncurses-devel openssl-devel bison flex
-
-

Download the OPAE upstream kernel tree from GitHub:

-
git clone https://github.com/OPAE/linux-dfl.git -b fpga-upstream-dev-5.8.0
-
-

Configure the kernel:

-
cd linux-dfl
-cp /boot/config-`uname -r` .config
-cat configs/n3000_d5005_defconfig >> .config 
-echo 'CONFIG_LOCALVERSION="-dfl"' >> .config
-echo 'CONFIG_LOCALVERSION_AUTO=y' >> .config
-make olddefconfig
-
-

Compile and install the new kernel:

-
make -j
-sudo make modules_install
-sudo make install
-
-

After the installation finishes, reboot your system. -Log back into the system, and confirm the correct version for the kernel:

-
$ uname -a
-Linux localhost.localdomain 5.8.0-rc1-dfl-g73e16386cda0 #6 SMP Wed Aug 19 08:38:32 EDT 2020 x86_64 x86_64 x86_64 GNU/Linux
-
-

Building and installing the OPAE SDK from the source

-

Download the OPAE SDK source package:

-
    -
  1. Go to the section corresponding to the desired release on -GitHub:
  2. -
  3. Click the Source code (tar.gz) link under the section's Assets.
  4. -
  5. -

    On the command line, go through the following steps to install it:

    -
    # Unpack
    -tar xfvz opae-sdk-<release>.tar.gz
    -# Configure
    -cd opae-sdk-<release>
    -mkdir build
    -cd build
    -# The default installation prefix is `/usr/local`;
    -# You have the option to configure for a different location
    -cmake [-DCMAKE_INSTALL_PREFIX=<prefix>] ..
    -# Compile
    -make
    -# Install: you need system administration privileges (`sudo`)
    -# if you have elected to install in the default location
    -[sudo] make install
    -
    -
  6. -
-

The remainder of this guide assumes you installed into /usr/local.

-

Configuring the FPGA (loading an FPGA AFU)

-

The fpgaconf tool exercises the AFU reconfiguration -functionality. It shows how to read a bitstream from a disk file, -check its validity and compatibility, and then injects it into FPGA to -be configured as a new AFU, which can then be discovered and used by -user applications.

-

For this step, you require a valid green bitstream (GBS) file. To -reconfigure the FPGA slot, you can issue the following command as system -administrator:

-
sudo fpgaconf -b 0x5e <filename>.gbs
-
-

The -b option to fpgaconf indicates the target bus number of the -FPGA slot to be reconfigured. Alternatively, you can also specify the -target socket number of the FPGA using the -s option.

-
$ sudo fpgaconf --help
-Usage:
-        fpgaconf [-hvn] [-b <bus>] [-d <device>] [-f <function>] [-s <socket>] <gbs>
-
-                -h,--help           Print this help
-                -v,--verbose        Increase verbosity
-                -n,--dry-run        Don't actually perform actions
-                -b,--bus            Set target bus number
-                -d,--device         Set target device number
-                -f,--function       Set target function number
-                -s,--socket         Set target socket number
-
-
The sample application on the Building a Sample Application
-section requires loading of an AFU called "Native Loopback
-Adapter" (NLB) on the FPGA. Please refer to the NLB documentation
-for the location of the NLB's green bitstream. You also can verify
-if the NLB green bitstream has already been loaded into the FPGA
-slot by typing the following command and checking the output
-matches the following:
-
-```bash
-$ cat /sys/class/fpga_region/region0/dfl-port.0/afu_id
-d8424dc4a4a3c413f89e433683f9040b
-```
-
-
The fpgaconf tool is not available for the Intel PAC N3000. The NLB is
-already included in the AFU.
-
-

Building a sample application

-

The library source includes code samples. Use these samples to learn -how to call functions in the library. Build and run these samples as -quick sanity checks to determine if your installation and environment -are set up properly.

-

In this guide, we will build hello_fpga.c. This is the "Hello -World!" example of using the library. This code searches for a -predefined and known AFU called "Native Loopback Adapter" on the -FPGA. If found, it acquires ownership and then interacts with the AFU -by sending it a 2MB message and waiting for the message to be echoed -back. This code exercises all major components of the API except for -AFU reconfiguration: AFU search, enumeration, access, MMIO, and memory -management.

-

You can also find the source for hello_fpga in the samples directory of the -OPAE SDK repository on GitHub.

-
    int main(int argc, char *argv[])
-    {
-        fpga_properties    filter = NULL;
-        fpga_token         afu_token;
-        fpga_handle        afu_handle;
-        fpga_guid          guid;
-        uint32_t           num_matches;
-
-        volatile uint64_t *dsm_ptr    = NULL;
-        volatile uint64_t *status_ptr = NULL;
-        volatile uint64_t *input_ptr  = NULL;
-        volatile uint64_t *output_ptr = NULL;
-
-        uint64_t        dsm_wsid;
-        uint64_t        input_wsid;
-        uint64_t        output_wsid;
-        fpga_result     res = FPGA_OK;
-
-        if (uuid_parse(NLB0_AFUID, guid) < 0) {
-            fprintf(stderr, "Error parsing guid '%s'\n", NLB0_AFUID);
-            goto out_exit;
-        }
-
-        /* Look for accelerator by its "afu_id" */
-        res = fpgaGetProperties(NULL, &filter);
-        ON_ERR_GOTO(res, out_exit, "creating properties object");
-
-        res = fpgaPropertiesSetObjectType(filter, FPGA_ACCELERATOR);
-        ON_ERR_GOTO(res, out_destroy_prop, "setting object type");
-
-        res = fpgaPropertiesSetGuid(filter, guid);
-        ON_ERR_GOTO(res, out_destroy_prop, "setting GUID");
-
-        /* TODO: Add selection via BDF / device ID */
-
-        res = fpgaEnumerate(&filter, 1, &afu_token, 1, &num_matches);
-        ON_ERR_GOTO(res, out_destroy_prop, "enumerating accelerators");
-
-        if (num_matches < 1) {
-            fprintf(stderr, "accelerator not found.\n");
-            res = fpgaDestroyProperties(&filter);
-            return FPGA_INVALID_PARAM;
-        }
-
-        /* Open accelerator and map MMIO */
-        res = fpgaOpen(afu_token, &afu_handle, 0);
-        ON_ERR_GOTO(res, out_destroy_tok, "opening accelerator");
-
-        res = fpgaMapMMIO(afu_handle, 0, NULL);
-        ON_ERR_GOTO(res, out_close, "mapping MMIO space");
-
-        /* Allocate buffers */
-        res = fpgaPrepareBuffer(afu_handle, LPBK1_DSM_SIZE,
-                    (void **)&dsm_ptr, &dsm_wsid, 0);
-        ON_ERR_GOTO(res, out_close, "allocating DSM buffer");
-
-        res = fpgaPrepareBuffer(afu_handle, LPBK1_BUFFER_ALLOCATION_SIZE,
-                   (void **)&input_ptr, &input_wsid, 0);
-        ON_ERR_GOTO(res, out_free_dsm, "allocating input buffer");
-
-        res = fpgaPrepareBuffer(afu_handle, LPBK1_BUFFER_ALLOCATION_SIZE,
-                   (void **)&output_ptr, &output_wsid, 0);
-        ON_ERR_GOTO(res, out_free_input, "allocating output buffer");
-
-        printf("Running Test\n");
-
-        /* Initialize buffers */
-        memset((void *)dsm_ptr,    0,    LPBK1_DSM_SIZE);
-        memset((void *)input_ptr,  0xAF, LPBK1_BUFFER_SIZE);
-        memset((void *)output_ptr, 0xBE, LPBK1_BUFFER_SIZE);
-
-        cache_line *cl_ptr = (cache_line *)input_ptr;
-        for (uint32_t i = 0; i < LPBK1_BUFFER_SIZE / CL(1); ++i) {
-            cl_ptr[i].uint[15] = i+1; /* set the last uint in every cacheline */
-        }
-
-        /* Reset accelerator */
-        res = fpgaReset(afu_handle);
-        ON_ERR_GOTO(res, out_free_output, "resetting accelerator");
-
-        /* Program DMA addresses */
-        uint64_t iova;
-        res = fpgaGetIOAddress(afu_handle, dsm_wsid, &iova);
-        ON_ERR_GOTO(res, out_free_output, "getting DSM IOVA");
-
-        res = fpgaWriteMMIO64(afu_handle, 0, CSR_AFU_DSM_BASEL, iova);
-        ON_ERR_GOTO(res, out_free_output, "writing CSR_AFU_DSM_BASEL");
-
-        res = fpgaWriteMMIO32(afu_handle, 0, CSR_CTL, 0);
-        ON_ERR_GOTO(res, out_free_output, "writing CSR_CFG");
-        res = fpgaWriteMMIO32(afu_handle, 0, CSR_CTL, 1);
-        ON_ERR_GOTO(res, out_free_output, "writing CSR_CFG");
-
-        res = fpgaGetIOAddress(afu_handle, input_wsid, &iova);
-        ON_ERR_GOTO(res, out_free_output, "getting input IOVA");
-        res = fpgaWriteMMIO64(afu_handle, 0, CSR_SRC_ADDR, CACHELINE_ALIGNED_ADDR(iova));
-        ON_ERR_GOTO(res, out_free_output, "writing CSR_SRC_ADDR");
-
-        res = fpgaGetIOAddress(afu_handle, output_wsid, &iova);
-        ON_ERR_GOTO(res, out_free_output, "getting output IOVA");
-        res = fpgaWriteMMIO64(afu_handle, 0, CSR_DST_ADDR, CACHELINE_ALIGNED_ADDR(iova));
-        ON_ERR_GOTO(res, out_free_output, "writing CSR_DST_ADDR");
-
-        res = fpgaWriteMMIO32(afu_handle, 0, CSR_NUM_LINES, LPBK1_BUFFER_SIZE / CL(1));
-        ON_ERR_GOTO(res, out_free_output, "writing CSR_NUM_LINES");
-        res = fpgaWriteMMIO32(afu_handle, 0, CSR_CFG, 0x42000);
-        ON_ERR_GOTO(res, out_free_output, "writing CSR_CFG");
-
-        status_ptr = dsm_ptr + DSM_STATUS_TEST_COMPLETE/8;
-
-        /* Start the test */
-        res = fpgaWriteMMIO32(afu_handle, 0, CSR_CTL, 3);
-        ON_ERR_GOTO(res, out_free_output, "writing CSR_CFG");
-
-        /* Wait for test completion */
-        while (0 == ((*status_ptr) & 0x1)) {
-            usleep(100);
-        }
-
-        /* Stop the device */
-        res = fpgaWriteMMIO32(afu_handle, 0, CSR_CTL, 7);
-        ON_ERR_GOTO(res, out_free_output, "writing CSR_CFG");
-
-        /* Check output buffer contents */
-        for (uint32_t i = 0; i < LPBK1_BUFFER_SIZE; i++) {
-            if (((uint8_t*)output_ptr)[i] != ((uint8_t*)input_ptr)[i]) {
-                fprintf(stderr, "Output does NOT match input "
-                    "at offset %i!\n", i);
-                break;
-            }
-        }
-
-        printf("Done Running Test\n");
-
-        /* Release buffers */
-    out_free_output:
-        res = fpgaReleaseBuffer(afu_handle, output_wsid);
-        ON_ERR_GOTO(res, out_free_input, "releasing output buffer");
-    out_free_input:
-        res = fpgaReleaseBuffer(afu_handle, input_wsid);
-        ON_ERR_GOTO(res, out_free_dsm, "releasing input buffer");
-    out_free_dsm:
-        res = fpgaReleaseBuffer(afu_handle, dsm_wsid);
-        ON_ERR_GOTO(res, out_unmap, "releasing DSM buffer");
-
-        /* Unmap MMIO space */
-    out_unmap:
-        res = fpgaUnmapMMIO(afu_handle, 0);
-        ON_ERR_GOTO(res, out_close, "unmapping MMIO space");
-
-        /* Release accelerator */
-    out_close:
-        res = fpgaClose(afu_handle);
-        ON_ERR_GOTO(res, out_destroy_tok, "closing accelerator");
-
-        /* Destroy token */
-    out_destroy_tok:
-        res = fpgaDestroyToken(&afu_token);
-        ON_ERR_GOTO(res, out_destroy_prop, "destroying token");
-
-        /* Destroy properties object */
-    out_destroy_prop:
-        res = fpgaDestroyProperties(&filter);
-        ON_ERR_GOTO(res, out_exit, "destroying properties object");
-
-    out_exit:
-        return res;
-
-    }
-
-

Linking with the OPAE library is straightforward. Code using this library -should include the header file fpga.h. Taking the GCC compiler on -Linux as an example, the minimalist compile and link line should look -like:

-
gcc -std=c99 hello_fpga.c -I/usr/local/include -L/usr/local/lib -lopae-c -luuid -ljson-c -lpthread -o hello_fpga
-
-
The API uses some features from the C99 language standard. The
-`-std=c99` switch is required if the compiler does not support C99 by
-default.
-
-
Third-party library dependency: The library internally uses
-`libuuid` and `libjson-c`. But they are not distributed as part of the
-library. Make sure you have these libraries properly installed.
-
-
The layout of AFU is different between the N3000 card and Rush Creek/Darby Creek.
-In the N3000 card, the NLB and DMA are contained in the AFU, so we need to do
-enumeration again in AFU to discover the NLB.
-To run the hello_fpga application on the N3000 card, it should use the `-c`
-option to support the N3000 card:
-
-```bash
-$ sudo ./hello_fpga -c
-Running Test
-Running on bus 0x08.
-AFU NLB0 found @ 28000
-Done Running Test
-```
-
-

To run the hello_fpga application; just issue:

-
$ sudo ./hello_fpga
-Running Test
-Done
-
-

Setup IOFS Release1 Bitstream on FPGA PCIe card

-

Program IOFS Release1 bitstream on the FPGA D5005 or N6000 cards and reboot the system.

-

Run this command:

-
$ lspci | grep acc
-3b:00.0 Processing accelerators: Intel Corporation Device af00 (rev 01)
-
-

Number of virtual functions supported by bitstream:

-
$ cat /sys/bus/pci/devices/0000:3b:00.0/sriov_totalvfs 
-output: 3
-
-

Enable FPGA virtual functions:

-
sudo sh -c "echo 3 > /sys/bus/pci/devices/0000:3b:00.0/sriov_numvfs"
-
-

List of FPGA PF and VF's:

-
Physical Functions (PFs):
-  3b:00.0 Processing accelerators: Intel Corporation Device af00 (rev 01)
-
-Virtual Functions (VFs).
-  3b:00.1 Processing accelerators: Intel Corporation Device af01 (rev 01)
-  3b:00.2 Processing accelerators: Intel Corporation Device af01 (rev 01)
-  3b:00.3 Processing accelerators: Intel Corporation Device af01 (rev 01)
-
-

Bind vfio-pcie driver to FPGA virtual functions:

-
sudo opaevfio  -i 0000:3b:00.1 -u userid -g groupid
-sudo opaevfio  -i 0000:3b:00.2 -u userid -g groupid
-sudo opaevfio  -i 0000:3b:00.3 -u userid -g groupid
-
-

List of fpga accelerators:

-
$ fpgainfo port
-
-  //****** PORT ******//
-  Object Id                        : 0x600D000000000000
-  PCIe s:b:d.f                     : 0000:3b:00.3
-  Device Id                        : 0xAF00
-  Socket Id                        : 0xFF
-  Accelerator Id                   : 43425ee6-92b2-4742-b03a-bd8d4a533812
-  Accelerator GUID                 : 43425ee6-92b2-4742-b03a-bd8d4a533812
-  //****** PORT ******//
-  Object Id                        : 0x400D000000000000
-  PCIe s:b:d.f                     : 0000:3b:00.2
-  Device Id                        : 0xAF00
-  Socket Id                        : 0xFF
-  Accelerator Id                   : 8568AB4E-6bA5-4616-BB65-2A578330A8EB
-  Accelerator GUID                 : 8568AB4E-6bA5-4616-BB65-2A578330A8EB
-  //****** PORT ******//
-  Object Id                        : 0x200D000000000000
-  PCIe s:b:d.f                     : 0000:3b:00.1
-  Device Id                        : 0xAF00
-  Socket Id                        : 0xFF
-  Accelerator Id                   : 56e203e9-864f-49a7-b94b-12284c31e02b
-  Accelerator GUID                 : 56e203e9-864f-49a7-b94b-12284c31e02b
-
-FPGA VF1/3b:00.1/Host Exerciser Loopback Accelerator GUID: 56E203E9-864F-49A7-B94B-12284C31E02B
-FPGA VF2/3b:00.2/Host Exerciser Memory Accelerator GUID: 8568AB4E-6bA5-4616-BB65-2A578330A8EB
-FPGA VF3/3b:00.3/Host Exerciser HSSI Accelerator GUID: 43425ee6-92b2-4742-b03a-bd8d4a533812
-
-

Unbind pcie-vfio dirver to FPGA virtual functions:

-
sudo opaevfio  -r 0000:3b:00.1
-
-

Host Exerciser Loopback (HE-LBK) AFU can move data between host memory and FPGA:

-
$ host_exerciser lpbk
-
-  [lpbk] [info] starting test run, count of 1
-  Input Config:0
-  Allocate SRC Buffer
-  Allocate DST Buffer
-  Allocate DSM Buffer
-  Start Test
-  Test Completed
-  Host Exerciser swtest msg:0
-  Host Exerciser numReads:32
-  Host Exerciser numWrites:32
-  Host Exerciser numPendReads:0
-  Host Exerciser numPendWrites:0
-  [lpbk] [info] Test lpbk(1): PASS
-
-
  In order to successfully run hello\_fpga, the user needs to configure
-  system hugepage to reserve 2M-hugepages.
-  For example, the command below reserves 20 2M-hugepages:
-
-  ```bash
-  echo 20 | sudo tee /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
-  ```
-
-  For x86_64 architecture CPU, user can use the following command to find out available huge page sizes:
-
-  ```bash
-  $ grep pse /proc/cpuinfo | uniq
-  flags : ... pse ...
-  ```
-
-  If this command returns a non-empty string, 2MB pages are supported:
-
-  ```bash
-  $ grep pse /proc/cpuinfo | uniq
-  flags : ... pdpe1gb ...
-  ```
-
-  If this commands returns a non-empty string, 1GB pages are supported.
-  ````
-
-````{note}
-The default configuration for many Linux distributions currently sets a
-relatively low limit for pinned memory allocations per process 
-(RLIMIT_MEMLOCK, often set to a default of 64kiB).
-
-To run an OPAE application that attempts to share more memory than specified
-by this limit between software and an accelerator, you can either:
-
-* Run the application as root, or
-* Increase the limit for locked memory via `ulimit`:
-
-```bash
-ulimit -l unlimited
-```
-
-See the Installation Guide for how to permanently adjust the memlock limit.
-
- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_dfl_drv/fpga_dfl_drv/index.html b/sw/fpga_dfl_drv/fpga_dfl_drv/index.html deleted file mode 100644 index 717b975cb..000000000 --- a/sw/fpga_dfl_drv/fpga_dfl_drv/index.html +++ /dev/null @@ -1,1796 +0,0 @@ - - - - - - - - - - - - - - - - - - Enable OPAE on FPGA PCIe drivers # - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

Enable OPAE on FPGA PCIe drivers

-
.. toctree::
-.. highlight:: c
-.. highlight:: console
-
-

FPGA PCIe driver for PCIe-based Field-Programmable Gate Array (FPGA) solutions which implement -the Device Feature List (DFL). This driver provides interfaces for user space applications to -configure, enumerate, open and access FPGA accelerators on the FPGA DFL devices. additionally, it -also enables system level management functions such as FPGA partial reconfiguration, power management, -virtualization with DFL framework and DFL feature device drivers.

-

OPAE 1.4.0 release supports both FPGA Intel Linux driver as well as Linux FPGA DFL driver patch set2. -Linux PCIe FPGA DFL driver supports Intel FPGA devices.

-

FPGA DFL Linux driver source code patchset2 available -https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/drivers?h=linux-5.4.y

-

FPGA DFL Linux driver source code patchset1 available -https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/drivers/fpga?h=v4.19.14

-

FPGA PCIe driver Architecture

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_dfl_drv/pcie_dfl_drv_arch.PNG b/sw/fpga_dfl_drv/pcie_dfl_drv_arch.PNG deleted file mode 100644 index 1fab16c477a3dd4428f6e6b19bdc5e94e8701f5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35483 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 Sc}a?UJ8$K1mU8;H>;D6^-zy{l diff --git a/sw/fpga_tools/coreidle/coreidle/index.html b/sw/fpga_tools/coreidle/coreidle/index.html deleted file mode 100644 index dd1f47c3f..000000000 --- a/sw/fpga_tools/coreidle/coreidle/index.html +++ /dev/null @@ -1,1832 +0,0 @@ - - - - - - - - - - - - - - - - - - coreidle # - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

coreidle

-

SYNOPSIS

-

coreidle [-v] [-B <bus>] [-D <device>] [-F <function>] [-S <socket>] [-G <GBS path>]

-

DESCRIPTION

-

coreidle parses the Accelerator Function Unit (AFU) metadata and extracts power information. coreidle calculates -the FPGA power and calculates the number of online and idle cores. It moves threads from idle cores to online cores. -coreidle is only available the Integrated FPGA Platform. You cannot run coreidle on the PCIe Accelerator Card (PAC).

-

EXAMPLES

-

./coreidle -B 0x5e -G /home/lab/gbs/mode0.gbs

-

Idle cores to run online cores at maximum capacity.

-

OPTIONS

-

-v,--version Prints version information and exit.

-

-B,--bus FPGA bus number.

-

-D,--device FPGA device number.

-

-F,--functio FPGA function number.

-

-S,--socket FPGA socket number.

-

-G,--gbs Green bitstream file path.

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/fecmode/fecmode/index.html b/sw/fpga_tools/fecmode/fecmode/index.html deleted file mode 100644 index 287ce1668..000000000 --- a/sw/fpga_tools/fecmode/fecmode/index.html +++ /dev/null @@ -1,1858 +0,0 @@ - - - - - - - - - - - - - - - - - - fecmode (N3000 specific tool) # - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

fecmode (N3000 specific tool)

-

SYNOPSIS

-
fecmode [<mode>][<args>]
-
-

DESCRIPTION

-

Fecmode changes FEC mode of external ethernet PHY, this tool only support on N3000 Card.

-

POSITIONAL ARGUMENTS

-

--segment, -S

-

segment number of the PCIe device.

-

--bus, -B

-

bus number of the PCIe device.

-

--device, -D

-

device number of the PCIe device.

-

--function, -F -function number of the PCIe device

-

--rsu, -r -reboot card only if mode is not configured

-

--debug, -d -output debug information

-

FEC Mode

-

no -no FEC.

-

kr -BaseR FEC (Fire-Code) correction – 4 orders

-

rs -Reed-Solomon FEC correction – 7 orders

-

EXAMPLE

-

This command change FEC mode to “kr”: -

# fecmode -B 0x25 kr
-

-

This command reboot card (no need to specify bus number if there is only one card): -

# fecmode -r
-

-

This command display the current FEC mode: -

# fecmode
-

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/fpgabist/fpgabist/index.html b/sw/fpga_tools/fpgabist/fpgabist/index.html deleted file mode 100644 index 5ef037f5c..000000000 --- a/sw/fpga_tools/fpgabist/fpgabist/index.html +++ /dev/null @@ -1,1864 +0,0 @@ - - - - - - - - - - - - - - - - - - fpgabist # - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

fpgabist

-

SYNOPSIS

-
fpgabist [-h] [-i device_id] [-b bus] [-d device] [-f function] [path_to_gbs1 path_to_gbs2 ...]
-
-

DESCRIPTION

-

The fpgabist tool performs self-diagnostic tests on supported FPGA platforms.

-

The tool accepts one or more Accelerator Function (AF) binaries from a predetermined set of AFs. Depending on the available binaries, -the tool runs appropriate tests and reports hardware issues.

-

fpgabist always uses fpgainfo to report system information before running any hardware tests.

-

Currently, fpgabist accepts the following AFs: - 1. nlb_mode_3: The native loopback (NLB) test implements a loopback from TX to RX. Use it to verify basic functionality - and to measure bandwidth. - 2. dma_afu: The direct memory access (DMA) AFU test transfers data from host memory to FPGA-attached local memory.

-

The installation includes the AF files, but you can also compile the AFs from the source.

-

If there are multiple PCIe® devices, use -b, -d, -f to specify the BDF for the specific PCIe® device.

-

POSITIONAL ARGUMENTS

-

[path_to_gbs1 path_to_gbs2 ...]

-

Paths to Accelerator Function (AF) files.

-

OPTIONAL ARGUMENTS

-

You can use the single letter or the full parameter name for the command line arguments.

-

-h, --help

-

Prints usage information

-

-i device_id, --device-id device_id

-

Device ID for Intel FPGA. Default is: 0x09c4

-

-B bus, --bus bus

-

Bus number for specific FPGA

-

-D device, --device device

-

Device number for specific FPGA

-

-F function, --function function

-

Function number for specific FPGA

-

EXAMPLES

-

fpgabist <path_to_gbs_files>/dma_afu.gbs <path_to_gbs_files>/nlb_3.gbs

-

Runs fpgabist on any platform in the system that matches the default device ID. This command runs both the DMA and - NLB_MODE_3 tests.

-

fpgabist -i 09c4 -b 5 <path to gbs>/dma_afu.gbs

-

Runs fpgabist the DMA test on the PCIe® Endpoint with device_id 09c4 on bus 5.

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/fpgaconf/fpgaconf/index.html b/sw/fpga_tools/fpgaconf/fpgaconf/index.html deleted file mode 100644 index a6c2aa402..000000000 --- a/sw/fpga_tools/fpgaconf/fpgaconf/index.html +++ /dev/null @@ -1,1924 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - fpgaconf - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

fpgaconf

-

SYNOPSIS

-

fpgaconf [-hvVn] [-S <segment>] [-B <bus>] [-D <device>] [-F <function>] [PCI_ADDR] <gbs>

-

DESCRIPTION

-

fpgaconf configures the FPGA with the accelerator function (AF). It also checks the AF for compatibility with -the targeted FPGA and the FPGA Interface Manager (FIM). fpgaconf takes the following arguments:

-

-h, --help

-
Prints usage information.
-
-

-v, --version

-
Prints version information and exits.
-
-

-V, --verbose

-
Prints more verbose messages while enumerating and configuring. Can be
-requested more than once.
-
-

-n, --dry-run

-
Performs enumeration. Skips any operations with side-effects such as the
-actual AF configuration.
-
-

-S, --segment

-
PCIe segment number of the target FPGA.
-
-

-B, --bus

-
PCIe bus number of the target FPGA.
-
-

-D, --device

-
PCIe device number of the target FPGA.
-
-

-F, --function

-
PCIe function number of the target FPGA.
-
-

--force

-
Reconfigure the AFU even if it is in use.
-
-

fpgaconf enumerates available FPGA devices in the system and selects -compatible FPGAs for configuration. If more than one FPGA is -compatible with the AF, fpgaconf exits and asks you to be -more specific in selecting the target FPGAs by specifying a -a PCIe BDF.

-

EXAMPLES

-

fpgaconf my_af.gbs

-
Program "my_af.gbs" to a compatible FPGA.
-
-

fpgaconf -V -B 0x3b my_af.gbs

-
Program "my_af.gbs" to the FPGA in bus 0x3b, if compatible,
-while printing out slightly more verbose information.
-
-

fpgaconf 0000:3b:00.0 my_af.gbs

-
Program "my_af.gbs" to the FPGA at address 0000:3b:00.0.
-
- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/fpgad/fpgad/index.html b/sw/fpga_tools/fpgad/fpgad/index.html deleted file mode 100644 index 297323d7f..000000000 --- a/sw/fpga_tools/fpgad/fpgad/index.html +++ /dev/null @@ -1,1964 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - fpgad - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

fpgad

-

SYNOPSIS

-

fpgad --daemon [--version] [--directory=<dir>] [--logfile=<file>] [--pidfile=<file>] [--umask=<mode>] [--socket=<sock>] [--null-bitstream=<file>] -fpgad [--socket=<sock>] [--null-bitstream=<file>]

-

DESCRIPTION

-

fpgad monitors the device sensors, checking for sensor values that are out of the prescribed range.

-

When any of the sensors is detected to be out of bounds, fpgad will focus on keeping the server from rebooting by masking PCIE AER, and send a message to system administrator. System administrator can take further actions like stop the application and stop the FPGA, but fpgad just focus on monitor the sensors and will not take any cooling actions.

-

Note: fpgad must be running (as root) and actively monitoring devices when a sensor anomaly occurs in order to initiate Graceful Shutdown. If fpgad is not loaded during such a sensor anomaly, the out-of-bounds scenario will not be detected, and the resulting effect on the hardware is undefined.

-

ARGUMENTS

-

-v, --version

-
Prints version information and exits.
-
-

-d, --daemon

-
When specified, fpgad executes as a system daemon process.
-
-

-D, --directory <dir>

-
When running in daemon mode, run from the specified directory.
-If omitted when daemonizing, `fpgad` uses /tmp.
-
-

-l, --logfile <file>

-
When running in daemon mode, send output to file. When not in daemon mode, the output goes to stdout.
-If omitted when daemonizaing, fpgad uses /tmp/fpgad.log.
-
-

-p, --pidfile <file>

-
When running in daemon mode, write the daemon's process id to a file.
-If omitted when daemonizing, fpgad uses /tmp/fpgad.pid.
-
-

-m, --umask <mode>

-
When running in daemon mode, use the mode value as the file mode creation mask passed to umask.
-If omitted when daemonizing, fpgad uses 0.
-
-

-s, --socket <sock>

-
Listen for event API registration requests on the UNIX domain socket on the specified path. 
-The default=/tmp/fpga_event_socket.
-
-

-n, --null-bitstream <file>

-
Specify the NULL bitstream to program when an AP6 event occurs. This option may be specified multiple
-times. The AF, if any, that matches the FPGA's PR interface ID is programmed when an AP6
-event occurs.
-
-

TROUBLESHOOTING

-

If you encounter any issues, you can get debug information in two ways:

-
    -
  1. By examining the log file when in daemon mode.
  2. -
  3. By running in non-daemon mode and viewing stdout.
  4. -
-

EXAMPLES

-

fpgad --daemon --null-bitstream=my_null_bits.gbs

-

This command starts fpgad as a system daemon process: -

sudo systemctl start fpgad
-

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/fpgadiag/index.html b/sw/fpga_tools/fpgadiag/index.html deleted file mode 100644 index 5e05e95cf..000000000 --- a/sw/fpga_tools/fpgadiag/index.html +++ /dev/null @@ -1,2311 +0,0 @@ - - - - - - - - - - - - - - - - - - - - fpgadiag - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - - - - - -
-
- - - - - - - -

fpgadiag

-

SYNOPSIS

-
fpgadiag [-m | --mode=] <mode> [-t | --target=] <target> [options]
-
-

DESCRIPTION

-

Includes several tests to diagnose, test, and report on the FPGA hardware.

-

<mode> chooses which test to run. -<target> specifies the platform that runs the test. -<target> can be either fpga or ase where ase. -<ase> is the abbreviation for Accelerator Simulation Environment.

-

The <mode> selects from the following tests:

-

lpbk1

-

This test runs a loopback test on the number of cachelines specified with -the BEGIN option. fpgadiag sets up source and destination buffers in -main memory. The FPGA then performs a memcpy from a source buffer to the -destination buffer, one cacheline at a time.

-

A cacheline is 64 bytes. When BEGIN = END, the test performs one iteration. When -BEGIN = END + x, the test performs x iterations. The first iteration consists -of copying BEGIN cachelines; the second iteration consists of copying -BEGIN+1 cache lines. The third iteration consists of copying BEGIN+2 -cache lines, and so on.

-

The latency is shown as the number of clock cycles.

-

When you specify MULTI-CL, you copy MULTI-CL cache lines at a time. -The WR-FENCE chooses on which virtual channel the WrFence occurs.

-

If you specify continuous mode with --cont, the program iterates -until the timeout specified in TIMEOUT completes.

-

read

-

This test performs reads. Use this test to measure read bandwidth.

-

write

-

This test performs writes. Use it to measure write bandwidth.

-

trput

-

This test measures both read and write bandwidth by performing 50% read and -50% write tests.

-

sw

-

This is a send-and-respond (ping-pong) test. One side sends data and -waits for response.

-

Each test requires a particular AF. Before running a test, -make sure the required AF is properly configured -on the platform.

-
    -
  • The lpbk1 test requires the nlb mode 0 AF.
  • -
  • The trput test requires the nlb mode 3 AF.
  • -
  • The sw test requires the nlb mode 7 AF. This AF is only available for the integrated FPGA platform. - You cannot run it on the PCIe accelerator card (PAC).
  • -
-

fpgalpbk

-

This enable/disable FPGA loopback.

-

fpgastats

-

This get fpga mac statistics.

-

mactest

-

This compare mac addresses that read from MAC ROM with mac addresses read from Host side.

-

OPTIONS

-

Common options

-

--help, -h

-
Print help information and exit.
-
-

--target=, -t

-
This switch specifies fpga (hardware) or ase (simulation). The default=fpga.
-
-

--mode=, -m

-
The test to run. The valid values are `lpbk1`, `read`,
-`write`, `trput`, and `sw`.
-
-

--config=, -c

-
A configuration file in the JSON format that specifies options for a test.
-If an option is specified both in the configuration file and on the command 
-line, the value in the configuration file takes precedence.
-
-

--dsm-timeout-usec

-
Timeout in microseconds for test completion. The test fails if not completed by 
-specified timeout. The default=1000000.
-
-

--socket-id=, -s

-
Socket ID encoded in FPGA Interface Manager (FIM). The default=0.
-
-

--bus=, -B

-
Bus number of the PCIe device. The default=0.
-
-

--device=, -D

-
Device number of the PCIe device. The default=0.
-
-

--function=, -F

-
Function number of the PCIe device. The default=0.
-
-

--freq=, -T

-
Clock frequency (in Hz) used for bandwidth calculation. The default=400000000 Hz (400 MHz).
-
-

eval_rst -.. note:: - This frequency is used only when the software cannot infer the frequency from the accelerator.

-

--suppress-hdr, -S

-
Suppress column headers for text output. The default=off.
-
-

--csv, -V

-
Comma separated value format. The default=off.
-
-

--suppress-stats

-
Suppress statistics output at the end of test. The default=off.
-
-

lpbk1 test options

-

--guid=, -g

-
AFU ID to enumerate. The default=D8424DC4-A4A3-C413-F89E-433683F9040B.
-
-

--begin=B, -b

-
1 <= B <= 65535. The default=1, B = number of cache lines.
-
-

--end=E, -e

-
1 <= E <= 65535. The default=B, B and E designate number of cache lines.
-
-

--multi-cl=M, -u

-
M can equal 1, 2, or 4. The default=1.
-
-

--cont, -L

-
Continuous mode. The default=off.
-
-

--timeout-usec=, --timeout-msec=, --timeout-sec=, --timeout-min=, --timeout-hour=

-
timeout for --cont mode. The default for all options is 0.
-
-

--cache-policy=, -p

-
Can be wrline-I, wrline-M, or wrpush-I The default=wrline-M.
-
-

--cache-hint=, -i

-
Can be rdline-I or rdline-S. The default=rdline-I.
-
-

--read-vc=, -r

-
Can be auto, vl0, vh0, vh1, random. The default=auto.
-
-

--write-vc=, -w

-
Can be auto, vl0, vh0, vh1, random. The default=auto.
-
-

--wrfence-vc=, -f

-
Can be auto, vl0, vh0, vh1. The default=auto.
-
-

read test options

-

--guid=, -g

-
AFU ID to enumerate. The default=F7DF405C-BD7A-CF72-22F1-44B0B93ACD18.
-
-

--begin=B, -b

-
1 <= B <= 65535. The default=1, B = number of cache lines.
-
-

--end=E, -e

-
1 <= E <= 65535. The default=B, B and E designate number of cache lines.
-
-

--multi-cl=M, -u

-
M can equal 1, 2, or 4. The default=1.
-
-

--strided-access=S, -a

-
1<= S <= 64. The default=1.
-
-

--cont, -L

-
Continuous mode. The default=off.
-
-

--timeout-usec=, --timeout-msec=, --timeout-sec=, --timeout-min=, --timeout-hour=

-
timeout for --cont mode. The default for all options is 0.
-
-

--cache-hint=, -i

-
Can be rdline-I or rdline-S. The default=rdline-I.
-
-

--warm-fpga-cache -H; --cool-fpga-cache -M

-
Try to prime the cache with hits. The default=off. Try to prime the 
-cache with misses. The default=off.
-
-

--cool-cpu-cache, -C

-
Try to prime the cpu cache with misses. The default=off.
-
-

--read-vc=, -r

-
Can be auto, vl0, vh0, vh1, random. The default=auto
-
-

write test options

-

--guid=, -g

-
AFU ID to enumerate. The default=F7DF405C-BD7A-CF72-22F1-44B0B93ACD18
-
-

--begin=B, -b

-
1 <= E <= 65535. The default=B, B and E designate number of cache lines.
-
-

--multi-cl=M, -u

-
M can equal 1, 2, or 4. The default=1.
-
-

--strided-access=S, -a

-
1<= S <= 64. The default=1.
-
-

--cont, -L

-
Continuous mode. The default=off.
-
-

--timeout-usec=, --timeout-msec=, --timeout-sec=, --timeout-min=, --timeout-hour=

-
timeout for --cont mode. The default for all options is 0.
-
-

--cache-policy=, -p

-
Can be wrline-I, wrline-M, or wrpush-I The default=wrline-M
-
-

--warm-fpga-cache -H; --cool-fpga-cache -M

-
Try to prime the cache with hits. The default=off. Try to prime the 
-cache with misses. The default=off.
-
-

--cool-cpu-cache, -C

-
Try to prime the cpu cache with misses. The default=off.
-
-

--write-vc=, -w

-
Can be auto, vl0, vh0, vh1, random. The default=auto.
-
-

--wrfence-vc=, -f

-
Can be auto, vl0, vh0, vh1, random. The default=`WRITE-VC`.
-
-

--alt-wr-pattern, -l

-
Alternate Write Pattern. The default=off.
-
-

trput test options

-

--guid=, -g

-
AFU ID to enumerate. The default=F7DF405C-BD7A-CF72-22F1-44B0B93ACD18.
-
-

--begin=B, -b

-
1 <= B <= 65535. The default=1, B = number of cache lines.
-
-

--end=E, -e

-
1 <= E <= 65535. The default=B, B and E designate number of cache lines.
-
-

--multi-cl=M, -u

-
M can equal 1, 2, or 4. The default=1.
-
-

--strided-access=S, -a

-
1<= S <= 64. The default=1
-
-

--cont, -L

-
Continuous mode. The default=off.
-
-

--timeout-usec=, --timeout-msec=, --timeout-sec=, --timeout-min=, --timeout-hour=

-
timeout for --cont mode. The default for all options is 0.
-
-

--cache-policy=, -p

-
Can be wrline-I, wrline-M, or wrpush-I The default=wrline-M.
-
-

--cache-hint=, -i

-
Can be rdline-I or rdline-S. The default=rdline-I.
-
-

--read-vc=, -r

-
Can be auto, vl0, vh0, vh1, random. The default=auto.
-
-

--write-vc=, -w

-
Can be auto, vl0, vh0, vh1, random. The default=auto.
-
-

--wrfence-vc=, -f

-
Can be  auto, vl0, vh0, vh1. The default=`WRITE-VC`.
-
-

sw test options

-

--guid=, -g

-
AFU ID to enumerate. The default=7BAF4DEA-A57C-E91E-168A-455D9BDA88A3.
-
-

--begin=B, -b

-
1 <= B <= 65535. The default=1, B = number of cache lines.
-
-

--end=E, -e

-
1 <= E <= 65535. The default=B, B and E designate number of cache lines.
-
-

--cache-policy=, -p

-
Can be wrline-I, wrline-M, or wrpush-I. The default=wrline-M.
-
-

--cache-hint= -i

-
Can be rdline-I or rdline-S. The default=rdline-I.
-
-

--read-vc=, -r

-
Can be auto, vl0, vh0, vh1, random The default=auto.
-
-

--write-vc=, -w

-
Can be auto, vl0, vh0, vh1, random The default=auto.
-
-

--wrfence-vc=, -f

-
Can be auto, vl0, vh0, vh1. The default=`WRITE-VC`.
-
-

--notice=, -N

-
Can be poll or csr-write. The default=poll.
-
-

Enable FPGA N3000 Ethernet group VFIO mdev

-

FPGA DFL driver does not support any ioctls to read/write ethernet group info and registers. -Users can read/write eth group registers by enabling VFIO mdev. Unbind the dfl_eth_group driver and bind vfio-mdev-dfl -driver for ethernet group dfl-device; then userspace can take full control of ethernet group feature id 10.

-

Ethernet group must be enabled before running fpgalpbk, mactest tools.

-

Steps to enable/create vfio mdev

-
unbind eth group feature id 10:
-    echo dfl-fme.0.8 > /sys/bus/dfl/drivers/dfl-eth-group/unbind
-    echo dfl-fme.0.7 > /sys/bus/dfl/drivers/dfl-eth-group/unbind
-bind to vfio-mdev-dfl:
-    echo vfio-mdev-dfl > /sys/bus/dfl/devices/dfl-fme.0.7/driver_override
-    echo vfio-mdev-dfl > /sys/bus/dfl/devices/dfl-fme.0.8/driver_override
-load vfio driver:
-    modprobe vfio_pci
-    modprobe vfio_iommu_type1
-    modprobe vfio_mdev
-    modprobe vfio_mdev_dfl
-trigger mdev:
-    echo dfl-fme.0.7 >/sys/bus/dfl/drivers_probe
-    echo dfl-fme.0.8 >/sys/bus/dfl/drivers_probe
-    echo 83b8f4f2-509f-382f-3c1e-e6bfe0fa1001 > /sys/bus/dfl/devices/dfl-fme.0.7/mdev_supported_types/vfio-mdev-dfl-1/create
-    echo 83b8f4f2-509f-382f-3c1e-e6bfe0fa1002 > /sys/bus/dfl/devices/dfl-fme.0.8/mdev_supported_types/vfio-mdev-dfl-1/create
-
-linux kerenl msg after enabling mdev:
-    i40e 0000:b3:00.0 eth1: NIC Link is Down
-    i40e 0000:b1:00.1 eth0: NIC Link is Down
-    vfio-mdev-dfl dfl-fme.2.7: MDEV: Registered
-    vfio-mdev-dfl dfl-fme.2.8: MDEV: Registered
-    vfio_mdev 83b8f4f2-509f-382f-3c1e-e6bfe0fa1005: Adding to iommu group 140
-    vfio_mdev 83b8f4f2-509f-382f-3c1e-e6bfe0fa1005: MDEV: group_id = 140
-    vfio_mdev 83b8f4f2-509f-382f-3c1e-e6bfe0fa1006: Adding to iommu group 141
-    vfio_mdev 83b8f4f2-509f-382f-3c1e-e6bfe0fa1006: MDEV: group_id = 141
-
-

Remove vfio mdev

-
    echo 1 | sudo tee /sys/bus/mdev/devices/83b8f4f2-509f-382f-3c1e-e6bfe0fa1002/remove
-    echo 1 | sudo tee /sys/bus/mdev/devices/83b8f4f2-509f-382f-3c1e-e6bfe0fa1001/remove
-
-    rmmod vfio_mdev_dfl
-    modprobe dfl_eth_group
-
-    echo dfl-fme.0.7 >/sys/bus/dfl/drivers_probe
-    echo dfl-fme.0.8 >/sys/bus/dfl/drivers_probe
-
-    echo dfl-eth-group > /sys/bus/dfl/devices/dfl-fme.0.7/driver_override
-    echo dfl-eth-group > /sys/bus/dfl/devices/dfl-fme.0.8/driver_override
-
-

fpgalpbk test options

-

--enable

-
Enable fpga phy loopback.
-
-

--disable

-
Disable fpga phy loopback.
-
-

--direction

-
Can be local, remote.
-
-

--type

-
Can be serial, precdr, postcdr.
-
-

--side

-
Can be line, host.
-
-

--port

-
0 <= port <= 7, the default is all.
-
-

mactest test options

-

--offset

-
Read mac addresses from an offset, The default=0.
-
-

EXAMPLES

-

This command starts a lpbk1 test for the FPGA on bus 0x5e. The test -copies 57535, 57536, 57537 ... up to 65535 cache lines, one line at a time. -The test prints output in the comma separated values (CSV) format with the -header suppressed. -

./fpgadiag --mode=lpbk1 --target=fpga -V --bus=0x5e --begin=57535
---end=65535 --cache-hint=rdline-I --cache-policy=wrpush-I --multi-cl=1
---write-vc=vl0 --read-vc=vh1 --wrfence-vc=auto
-

-

This command starts a read test on the FPGA located on bus 0xbe. The test -reads 2045 cache lines in the continuous mode with a 15-second timeout period. -The reads use a strided pattern with a 10-byte stride length. -

./fpgadiag --mode=read --target=fpga -V --bus=0xbe --begin=2045 --cont
---timeout-sec=15 --cache-hint=rdline-I --multi-cl=1 -a=10 
---read-vc=auto --wrfence-vc=auto
-

-

This command starts a sw test on the FPGA located on bus 0xbe. The test -signals completion using a CSR write. -

./fpgadiag --mode=sw --target=fpga -V --bus=0xbe --begin=4 --end=8192
---cache-hint=rdline-I --cache-policy=wrline-I --notice=csr-write --write-vc=vl0
---wrfence-vc=auto --read-vc=random 
-

-

This command enable a fpgalpbk on the FPGA located on bus 0xbe. -

./fpgadiag -m fpgalpbk --bus 0xbe --enable --direction local --type postcdr
---side host
-

-

This command show fpgastats on the FPGA located on bus 0xbe. -

./fpgadiag -m fpgastats --bus 0xbe
-

-

TROUBLESHOOTING

-

When a test fails to run or gives errors, check the following:

-
    -
  • Is the Intel FPGA driver properly installed? -See Installation Guide -for driver installation instructions.
  • -
  • Are FPGA port permissions set properly? Check the permission bits of the -port, for example, /dev/intel-fpga-port-0. You need READ and WRITE -permissions to run fpgadiag tests.
  • -
  • Is hugepage properly configured on the system? -See Installation Guide -for hugepage configuration steps. In particular, fpgadiag requires a few 1 GB -pages.
  • -
  • Is the required AFU loaded? See DESCRIPTION for -information about what AFU the test requires.
  • -
  • Are --begin and --end values set properly? --end must be larger -than the --begin. Also, --begin must be a multiple of the ---multi-cl value.
  • -
  • The --warm-fpga-cache and --cool-fpga-cache options in the read -and write tests are mutually exclusive.
  • -
  • The timeout options are only meaningful for the continuous mode -(with the --cont option).
  • -
- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/fpgaflash/fpgaflash/index.html b/sw/fpga_tools/fpgaflash/fpgaflash/index.html deleted file mode 100644 index 931a1003b..000000000 --- a/sw/fpga_tools/fpgaflash/fpgaflash/index.html +++ /dev/null @@ -1,1848 +0,0 @@ - - - - - - - - - - - - - - - - - - fpgaflash # - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

fpgaflash

-

SYNOPSIS

-
fpgaflash [-h] {user,factory} file [bdf]
-
-

DESCRIPTION

-

fpgaflash updates the static FIM image loaded from flash at power-on.

-

If there are multiple devices in the system, fpgaflash must specify a BDF to select the correct device. If no BDF is specified, fpgaflash prints out the BDFs of any compatible devices.

-

POSITIONAL ARGUMENTS

-

{user, factory}

-

Specifies the type of flash programming.

-

user

-

Only reprograms the user image in flash.

-

factory

-

Reprograms the entire flash. A catastrophic failure during a factory update such as a power outage - requires a USB cable and quartus_pgm to recover.

-

file

-

Specifies the Raw Programming Data File (rpd) to program into flash.

-

bdf

-

Specifies the bus, device and function (BDF) of device to program such as 04:00.0 or 0000:04:00.0. This flag -is optional when there is a single device in the system.

-

OPTIONAL ARGUMENTS

-

-h, --help

-

Print usage information.

-

EXAMPLE

-

fpgaflash user new_image.rpd 0000:04:00.0

-

Programs new_image.rpd to flash of device with BDF 0000:04:00.0.

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/fpgaflash/superrsu/index.html b/sw/fpga_tools/fpgaflash/superrsu/index.html deleted file mode 100644 index a212fba36..000000000 --- a/sw/fpga_tools/fpgaflash/superrsu/index.html +++ /dev/null @@ -1,2153 +0,0 @@ - - - - - - - - - - - - - - - - - - super-rsu # - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

super-rsu

-

SYNOPSIS

-
super-rsu [-h] [-n] [--verify] | [ [--log-level {trace,debug,error,warn,info,notset}]
-          [--log-file <filename>] [--rsu-only] [--with-rsu] [--force-flash] ]
-      rsu_config
-
-

DESCRIPTION

-

super-rsu is a tool that can be used for flashing image files and commanding an -Intel PAC device to perform RSU (remote system update - or a board reboot). -Performing an RSU on an Intel PAC device will cause it to reload any firmware -or programmable logic and restart its execution, a requirement for any updated -firmware or programmable logic to take effect.

-

At the core of super-rsu is its configuration file (referred to in this -document as 'rsu_config') which is essentially a manifest file for -identifying both the target device and the binary images (and their versions) -to be flashed.

-

At a high level, the flow of super-rsu should be: -1. Read and parse rsu_config file -2. Use product identifiers (like vendor, device and any additional vendor, device - pairs that may be present in the PCIe bus) to locate all compatible - devices on the PCIe bus. -3. For every device found on the system, update the device using the flash - images defined in the "flash" section in the rsu_config data (or nvmupdate - section). - Each item in the "flash" section is a "flash spec" that contains: - * The flash type ("user", "bmc_fw", "bmc_img", ...) - * The filename of the image to flash. super-rsu will look for this file - first in the same directory of the rsu_config file, and then look in the - current working directory. - * The version of the image. - * An optional "force" indicator - * An optional "requires" indicator - The "nvmupdate" section is used to describe an Ethernet firmware file and - its version. -4. Using the data in the "nvmupdate" and "flash" sections, the update routine - involves: - * If an "nvmupdate" section is present: - 1. Locate the file on the file system to use to flash the Ethernet device. - 2. Call nvmupdate to get an "inventory" of devices matching the vendor and - device id in this section. - 3. Use this data to dynamically generate an nvmupdate compatible - configuration file. - 4. Call nvmupdate with the generated configuration file to flash the - Ethernet interfaces in the Vista Creek card (if version reported by - system does not match the version in this section). - * For each spec in the "flash" section: - 1. Locate the file on the file system to use to flash. - 2. Compare the version listed in the "flash spec" to version reported by - the target component. - 3. Create a task to call fpgaflash if either of the following conditions is - met (and the revision specified is compatible): - * The "force" indicator is present and set to true. - * The version in the spec does not match the version reported by the - system OR the flash type is factory type. - * For each task created from the "flash" section: - 1. Call fpgaflash with the command line arguments that correspond to the - flash type and the file name in the spec used to create the task. - This opens and controls the execution of fpgaflash in another process.

-

NOTE: If the system reports a revision for one of the components -being flashed, this revision must be in the set of revisions listed -in the manifest. -Example: if the system reports 'a' for bmc_img and the manifest includes -'ab', then the image will be flashed.

-

NOTE: Each update routine is run in a thread specific to a device located -on the PCIe bus. Every task in an update routine involves opening a new process -that is controlled and managed by its update routine thread. -If a task includes a timeout and the timeout is reached, a termination request -will be sent to its process and it will be counted as a failure. If a global -timeout is reached in the main thread, a termination request will be sent to each -thread performing the update. Consequently, the update routine will give the -current task extra time before terminating the process. -The RSU operation will only be performed if requested with either --with-rsu -command line argument or with the --rsu-only command line argument. -The former will perform the RSU command upon successful completion of flash -operations. The latter will skip the process of version matching and flashing -images and will only perform the RSU command. It is recommended that super-rsu -be executed again if any flash operation is interrupted.

-

POSITIONAL ARGUMENTS

-

rsu config

-

Specifies the name of the file containing the RSU configuration (in JSON -format)

-

OPTIONAL ARGUMENTS

-

-h, --help

-

Print usage information.

-

--verify

-

Compare versions of flashable components on the system against the manifest. - Return non-zero exit if compatible components are not up to date.

-

-n, --dry-run

-

Don't perform any updates, just a dry run. - This will print out commands that can be executed - in a Linux shell.

-

--log-level {trace,debug,error,warn,info,notset}

-

Log level to use. Default is 'info'.

-

`--log-file (default: /tmp/super-rsu.log)

-

Emit log messages (with DEBUG level) to filename - NOTE: The default log file (/tmp/super-rsu.log) is set to rollover every - time super-rsu is executed. This will create numbered backups before - truncating the log file. The maximum number of backups is 50.

-

--rsu-only

-

Only perform the RSU command.

-

--with-rsu

-

Perform RSU after updating flash components(experimental)

-

--force-flash

-

Flash all images regardless of versions matching or not.

-

CONFIGURATION

-

The following is the JSON schema expected by super-rsu. Any deviance from -this schema may result in errors executing super-rsu.

-
{
-  "definitions": {},
-  "$schema": "http://json-schema.org/draft-07/schema#",
-  "$id": "http://example.com/root.json",
-  "type": "object",
-  "title": "The Root Schema",
-  "required": [
-    "product",
-    "vendor",
-    "device",
-    "flash"
-  ],
-  "optional": [
-    "nvmupdate",
-  ],
-  "properties": {
-    "product": {
-      "$id": "#/properties/product",
-      "type": "string",
-      "title": "The Product Schema",
-      "default": "",
-      "examples": [
-        "n3000"
-      ],
-      "pattern": "^(.*)$"
-    },
-    "vendor": {
-      "$id": "#/properties/vendor",
-      "type": "string",
-      "title": "The Vendor Schema",
-      "default": "",
-      "examples": [
-        "0x8086"
-      ],
-      "pattern": "^((0x)?[A-Fa-f0-9]{4})$"
-    },
-    "device": {
-      "$id": "#/properties/device",
-      "type": "string",
-      "title": "The Device Schema",
-      "default": "",
-      "examples": [
-        "0x0b30"
-      ],
-      "pattern": "^((0x)?[A-Fa-f0-9]{4})$"
-    },
-    "nvmupdate": {
-      "$id": "#/properties/nvmupdate",
-      "type": "object",
-      "title": "The nvmupdate Schema",
-      "required": [
-        "vendor",
-        "device",
-        "filename",
-        "version"
-      ],
-      "optional": [
-        "interfaces"
-      ],
-      "properties": {
-        "vendor": {
-          "$id": "#/properties/nvmupdate/vendor",
-          "type": "string",
-          "title": "The nvmupdate Vendor Schema",
-          "default": "",
-          "examples": [
-             "0x8086"
-          ],
-          "pattern": "^((0x)?[A-Fa-f0-9]{4})$"
-        },
-        "device": {
-          "$id": "#/properties/nvmupdate/device",
-          "type": "string",
-          "title": "The nvmupdate Device Schema",
-          "default": "",
-          "examples": [
-            "0x0d58"
-          ],
-          "pattern": "^((0x)?[A-Fa-f0-9]{4})$"
-        },
-        "interfaces": {
-          "$id": "#/properties/nvmupdate/interfaces",
-          "type": "number",
-          "title": "The nvmupdate Interfaces Schema",
-          "default": "1",
-          "examples": [
-            2, 4
-          ]
-        },
-        "filename": {
-          "$id": "#/properties/nvmupdate/filename",
-          "type": "string",
-          "title": "The nvmupdate Filename Schema",
-          "default": "",
-          "examples": [
-            "PSG_XL710_6p80_XLAUI_NCSI_CFGID2p61_Dual_DID_0D58_800049C6.bin"
-          ],
-          "pattern": "^(.*)$"
-        },
-        "version": {
-          "$id": "#/properties/nvmupdate/version",
-          "type": "string",
-          "title": "The nvmupdate Version Schema",
-          "default": "",
-          "examples": [
-            "800049C6"
-          ],
-          "pattern": "^((0x)?[A-Fa-f0-9]{8})$"
-        },
-        "timeout": {
-          "$id": "#/properties/nvmupdate/timeout",
-          "type": "string",
-          "title": "The Timeout Schema",
-          "default": "",
-          "examples": [
-            "10m"
-          ],
-          "pattern": "^([0-9]+(\\.[0-9]+)?([dhms]))+$"
-        }
-      }
-    },
-    "flash": {
-      "$id": "#/properties/flash",
-      "type": "array",
-      "title": "The Flash Schema",
-      "items": {
-        "$id": "#/properties/flash/items",
-        "type": "object",
-        "title": "The Items Schema",
-        "required": [
-          "filename",
-          "type",
-          "version",
-          "revision"
-        ],
-    "optional": [
-          "enabled",
-          "force",
-      "timeout",
-      "requires"
-    ],
-        "properties": {
-      "enabled": {
-            "$id": "#/properties/flash/items/properties/enabled",
-        "type": "boolean",
-        "title": "The Enabled Schema",
-        "default": "true"
-      },
-          "filename": {
-            "$id": "#/properties/flash/items/properties/filename",
-            "type": "string",
-            "title": "The Filename Schema",
-            "default": "",
-            "examples": [
-              "vista_creek_qspi_xip_v1.0.6.ihex"
-            ],
-            "pattern": "^(.*)$"
-          },
-          "type": {
-            "$id": "#/properties/flash/items/properties/type",
-            "type": "string",
-            "title": "The Type Schema",
-            "default": "",
-            "examples": [
-              "bmc_fw"
-            ],
-            "enum": ["user", "bmc_fw", "bmc_img", "dtb", "factory_only",
-        "phy_eeprom"]
-          },
-          "version": {
-            "$id": "#/properties/flash/items/properties/version",
-            "type": "string",
-            "title": "The Version Schema",
-            "default": "",
-            "examples": [
-              "1.0.6"
-            ],
-            "pattern": "^\\d+\\.\\d+\\.\\d+$"
-          },
-          "force": {
-            "$id": "#/properties/flash/items/properties/force",
-            "type": "boolean",
-            "title": "The Force Schema",
-            "default": false,
-            "examples": [
-              true
-            ]
-          },
-          "revision": {
-            "$id": "#/properties/flash/items/properties/revision",
-            "type": "string",
-            "title": "The Revision Schema",
-            "default": "",
-            "examples": [
-              "C"
-            ],
-            "pattern": "^([A-Za-z])$"
-          },
-          "timeout": {
-            "$id": "#/properties/nvmupdate/timeout",
-            "type": "string",
-            "title": "The Timeout Schema",
-            "default": "",
-            "examples": [
-              "10m"
-            ],
-            "pattern": "^([0-9]+(\.[0-9]+)?([dhms]))+$"
-          },
-          "requires": {
-            "$id": "#/properties/flash/items/properties/requires",
-            "type": "string",
-            "title": "The Requires Schema",
-            "default": "",
-            "examples": [
-              "bmc_img >= 1.0.12"
-            ],
-            "pattern": "^(([a-z_]+) ((<>!=)?=) ([0-9a-z\\.]+)$"
-          }
-        }
-      }
-    }
-  }
-}
-
- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/fpgainfo/fpgainfo/index.html b/sw/fpga_tools/fpgainfo/fpgainfo/index.html deleted file mode 100644 index 6075b2b28..000000000 --- a/sw/fpga_tools/fpgainfo/fpgainfo/index.html +++ /dev/null @@ -1,2087 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - fpgainfo - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

fpgainfo

-

SYNOPSIS

-
   fpgainfo [-h] [-S <segment>] [-B <bus>] [-D <device>] [-F <function>] [PCI_ADDR]
-            {errors,power,temp,fme,port,bmc,mac,phy,security}
-
-

DESCRIPTION

-

fpgainfo displays FPGA information derived from sysfs files. The command argument is one of the following: -errors, power, temp, port, fme, bmc, phy or mac,security,events. -Some commands may also have other arguments or options that control their behavior.

-

For systems with multiple FPGA devices, you can specify the BDF to limit the output to the FPGA resource -with the corresponding PCIe configuration. If not specified, information displays for all resources for -the given command.

-

FPGAINFO COMMANDS

-

errors

-

Show/clear errors of an FPGA resource that the first argument specifies. -fpgainfo displays information in human readable form.

-

power

-

Show total the power in watts that the FPGA hardware consumes.

-

temp

-

Show FPGA temperature values in degrees Celcius.

-

port

-

Show information about the port such as the AFU ID of currently loaded AFU.

-

fme

-

Show information about the FPGA platform including the partial reconfiguration (PR) Interface ID, the OPAE version, -and the FPGA Interface Manager (FIM) ID.

-

bmc

-

Show all Board Management Controller sensor values for the FPGA resource, if available.

-

phy

-

Show information about the PHY integrated in the FPGA, if available.

-

mac

-

Show information about the MAC address in ROM attached to the FPGA, if available.

-

security

-

Show information about the security keys, hashs and flash count, if available.

-

events

-

Show information about events and sensors, if available.

-

OPTIONAL ARGUMENTS

-

--help, -h

-

Prints help information and exit.

-

--version, -v

-

Prints version information and exit.

-

COMMON ARGUMENTS

-

The following arguments are common to all commands and are optional.

-

-S, --segment

-

PCIe segment number of resource.

-

-B, --bus

-

PCIe bus number of resource.

-

-D, --device

-

PCIe device number of resource.

-

-F, --function

-

PCIe function number of resource.

-

ERRORS ARGUMENTS

-

The first argument to the errors command specifies the resource type. It must be one of the following: - fme,port,all

-

fme

-

Show/clear FME errors.

-

port

-

Show/clear PORT errors.

-

all

-

Show/clear errors for all resources.

-

The optional <command-args> arguments are:

-

--clear, -c

-

Clear errors for the given FPGA resource.

-

PHY ARGUMENTS

-

The optional <command-args> argument is:

-

--group, -G

-

Select which PHY group(s) information to show.

-

EVENTS ARGUMENTS

-

The optional <command-args> argument is:

-

--list,-l

-

List boots (implies --all).

-

--boot,-b

-

Boot index to use, i.e: -    0 for current boot (default). -    1 for previous boot, etc.

-

--count,-c

-

Number of events to print.

-

--all,-a

-

Print all events.

-

--sensors,-s

-

Print sensor data too.

-

--bits,-i

-

Print bit values too.

-

--help,-h

-

Print this help.

-

EXAMPLES

-

This command shows the current power telemetry: -

./fpgainfo power
-

-

This command shows the current temperature readings: -

./fpgainfo temp
-

-

This command shows FME resource errors: -

./fpgainfo errors fme
-
-This command clears all errors on all resources: -
./fpgainfo errors all -c
-
-This command shows information of the FME on bus 0x5e -
./fpgainfo fme -B 0x5e
-
-This command shows information of the FPGA security on bus 0x5e -
./fpgainfo security -B 0x5e
-
-This command shows all events and sensors information including sensor bits: -
./fpgainfo events -asi
-

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/fpgamux/fpgamux/index.html b/sw/fpga_tools/fpgamux/fpgamux/index.html deleted file mode 100644 index 3f33edcf2..000000000 --- a/sw/fpga_tools/fpgamux/fpgamux/index.html +++ /dev/null @@ -1,1918 +0,0 @@ - - - - - - - - - - - - - - - - - - fpgamux # - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

fpgamux

-

SYNOPSIS

-
fpgamux [-h] [-S|--socket-id SOCKET_ID] [-B|--bus-number BUS] [-D|--device DEVICE] [-F|--function FUNCTION]
-        [-G|--guid GUID] -m|--muxfile <filepath.json>
-
-

DESCRIPTION

-

fpgamux tests multiple AFUs that are synthesized into a single AFU along with -the CCIP-MUX basic building block (BBB). The CCIP-MUX uses the upper bits in the MMIO addresses to route MMIO -reads and writes to the AFU running on the corresponding CCIP-MUX port. fpgamux uses a configuration file that -lists the software components and correct configuration. fpgamux only runs on the Integrated FPGA Platform. -You cannot run it on the PCIe accelerator card (PAC).

-

.. note::

-
  The OPAE driver discovers only the first AFU. The first software component in the configuration 
-  determines the GUID to use for enumeration. Use the -G|--guid option to override the GUID
-  for the first software component.
-
-

OPTIONS

-

-S SOCKET_ID, --socket-id SOCKET_ID

-

socket id of FPGA resource.

-

-B BUS, --bus BUS

-

bus id of FPGA resource.

-

-D DEVICE, --device DEVICE

-

The device id of FPGA resource.

-

-F FUNCTION, --function FUNCTION

-

The function id of FPGA resource.

-

-G, --guid

-

Specifies the GUID to use for the resource enumeration.

-

-m, --muxfile <filepath.json>

-

The path to the fpgamux configuration file. This file must be in JSON format following the -schema described below.

-

CONFIGURATION

-

fpgamux uses a configuration file (in JSON format) to determine what software components to instantiate and -how to configure them to work with the AFUs. The schema includes the following elements:

-
    [
-        {
-            "app" : "fpga_app",
-            "name" : "String",
-            "config" : "Object"
-        }
-    ]
-
-

EXAMPLES

-

The following example shows a configuration with two components: -

    [
-        {
-            "app" : "nlb0",
-            "name" : "nlb0",
-            "config" :
-            {
-                "begin" : 1,
-                "end" : 1,
-                "multi-cl" : 1,
-                "cont" : false,
-                "cache-policy" : "wrline-M",
-                "cache-hint" : "rdline-I",
-                "read-vc" : "vh0",
-                "write-vc" : "vh1",
-                "wrfence-vc" : "write-vc",
-                "timeout-usec" : 0,
-                "timeout-msec" : 0,
-                "timeout-sec" : 1,
-                "timeout-min" : 0,
-                "timeout-hour" : 0,
-                "freq" : 400000000
-            }
-        },
-        {
-            "app" : "nlb3",
-            "name" : "nlb3",
-            "config" :
-            {
-                "mode" : "read",
-                "begin" : 1,
-                "end" : 1,
-                "multi-cl" : 1,
-                "strided-access" : 1,
-                "cont" : false,
-                "warm-fpga-cache" : false,
-                "cool-fpga-cache" : false,
-                "cool-cpu-cache" : false,
-                "cache-policy" : "wrline-M",
-                "cache-hint" : "rdline-I",
-                "read-vc" : "vh0",
-                "write-vc" : "vh1",
-                "wrfence-vc" : "write-vc",
-                "alt-wr-pattern" : false,
-                "timeout-usec" : 0,
-                "timeout-msec" : 0,
-                "timeout-sec" : 1,
-                "timeout-min" : 0,
-                "timeout-hour" : 0,
-                "freq" : 400000000
-            }
-        }
-    ]
-

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/fpgaport/fpgaport/index.html b/sw/fpga_tools/fpgaport/fpgaport/index.html deleted file mode 100644 index efb76a777..000000000 --- a/sw/fpga_tools/fpgaport/fpgaport/index.html +++ /dev/null @@ -1,1860 +0,0 @@ - - - - - - - - - - - - - - - - - - fpgaport # - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

fpgaport

-

SYNOPSIS

-
fpgaport [-h] [-N NUMVFS] [-X] [--debug] {assign,release} device [port]
-
-

DESCRIPTION

-

The fpgaport enables and disables virtualization. It assigns -and releases control of the port to the virtual function (VF). By default, the driver -assigns the port to the physical function (PF) in the non-virtualization use case.

-

POSITIONAL ARGUMENTS

-

{assign, release}

-
Action to perform.
-
-

device

-
The FPGA device being targeted with this action.
-
-

port

-
The number of the port.
-
-

OPTIONAL ARGUMENTS

-

-N NUMVFS, --numvfs NUMVFS

-
Create NUMVFS virtual functions. The typical value is 1.
-
-

-X, --destroy-vfs

-
Destroy all virtual functions prior to assigning.
-
-

--debug

-
Display additional log information.
-
-

-h, --help

-
Print usage information.
-
-

EXAMPLE

-

fpgaport release /dev/dfl-fme.0 0

-
Release port 0 from physical function control.
-
-

fpgaport assign /dev/dfl-fme.0 0

-
Assign port 0 to physical function control.
-
- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/fpgasupdate/fpgasupdate/index.html b/sw/fpga_tools/fpgasupdate/fpgasupdate/index.html deleted file mode 100644 index 936187ad2..000000000 --- a/sw/fpga_tools/fpgasupdate/fpgasupdate/index.html +++ /dev/null @@ -1,1920 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - fpgasupdate - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

fpgasupdate

-

SYNOPSIS

-

fpgasupdate [--log-level=<level>] file [bdf]

-

DESCRIPTION

-

The fpgasupdate command implements a secure firmware update for the following programmable accelerator cards (PACs): -* Intel® PAC with Intel Arria® 10 GX FPGA -* Intel FPGA PAC D5005 -* Intel PAC N3000

-

--log-level <level>

-
Specifies the `log-level` which is the level of information output to your command tool.
-The following seven levels  are available: `state`, `ioctl`, `debug`, `info`, `warning`,
-`error`, `critical`. Setting `--log-level=state` provides the most verbose output.
-Setting `--log-level=ioctl` provides the second most information, and so on. The default
-level is `info`.
-
-

file

-
Specifies the secure update firmware file to be programmed. This file may be to program a
-static region (SR), programmable region (PR), root entry hash, key cancellation, or other
-device-specific firmware.
-
-

bdf

-
The PCIe&reg; address of the PAC to program. `bdf` is of the form `[ssss:]bb:dd:f`,
-corresponding to PCIe segment, bus, device, function. The segment is optional. If
-you do not specify a segment, the segment defaults to `0000`. If the system has only
-one PAC you can omit the `bdf` and let `fpgasupdate`  determine the address
-automatically.
-
-

TROUBLESHOOTING

-

To gather more debug output, decrease the --log-level parameter.

-

EXAMPLES

-

fpgasupdate firmware.bin
-fpgasupdate firmware.bin 05:00.0
-fpgasupdate firmware.bin 0001:04:02.0 --log-level=ioctl

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/host_exerciser/host_exerciser/index.html b/sw/fpga_tools/host_exerciser/host_exerciser/index.html deleted file mode 100644 index 464d42874..000000000 --- a/sw/fpga_tools/host_exerciser/host_exerciser/index.html +++ /dev/null @@ -1,2076 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - host_exerciser - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

host_exerciser

-

SYNOPSIS

-
Usage: host_exerciser [OPTIONS] SUBCOMMAND
-
-
-Options:
-  -h,--help                   Print this help message and exit
-  -p,--pci-address TEXT       [<domain>:]<bus>:<device>.<function>
-  -l,--log-level TEXT:{trace,debug,info,warning,error,critical,off}=warning
-                              stdout logging level
-  -s,--shared                 open in shared mode, default is off
-  -t,--timeout UINT=60000     test timeout (msec)
-  -m,--mode UINT:value in {lpbk->0,read->1,trput->3,write->2} OR {0,1,3,2}=lpbk
-                              host exerciser mode {lpbk,read, write, trput}
-  --cls UINT:value in {cl_1->0,cl_2->1,cl_4->2,cl_8->3} OR {0,1,2,3}=cl_1
-                              number of CLs per request{cl_1, cl_2, cl_4, cl_8}
-  --continuousmode BOOLEAN=false
-                              test rollover or test termination
-  --atomic UINT:value in {cas_4->9,cas_8->11,fadd_4->1,fadd_8->3,off->0,swap_4->5,swap_8->7} OR {9,11,1,3,0,5,7}=off
-                              atomic requests (only permitted in combination with lpbk/cl_1)
-  --encoding UINT:value in {default->0,dm->1,pu->2,random->3} OR {0,1,2,3}=default
-                              data mover or power user encoding -- random interleaves both in the same stream
-  -d,--delay BOOLEAN=false    Enables random delay insertion between requests
-  --interleave UINT=0         Interleave requests pattern to use in throughput mode {0, 1, 2}
-                              indicating one of the following series of read/write requests:
-                              0: rd-wr-rd-wr
-                              1: rd-rd-wr-wr
-                              2: rd-rd-rd-rd-wr-wr-wr-wr
-  --interrupt UINT:INT in [0 - 3]
-                              The Interrupt Vector Number for the device
-  --contmodetime UINT=1       Continuous mode time in seconds
-  --testall BOOLEAN=false     Run all tests
-  --clock-mhz UINT=0          Clock frequency (MHz) -- when zero, read the frequency from the AFU
-
-Subcommands:
-  lpbk                        run simple loopback test
-  mem                         run simple mem test
-
-

DESCRIPTION

-

The host exerciser used to exercise and characterize the various host-FPGA -interactions eg. MMIO, Data transfer from host to FPGA , PR, host to FPGA memory etc.

-

Host Exerciser Loopback (HE-LBK)

-

HE-LB is responsible for generating traffic with the intention of exercising the -path from the AFU to the Host at full bandwidth. -Host Exerciser Loopback (HE-LBK) AFU can move data between host memory and FPGA.

-

HE-LBK supports: -1. Latency (AFU to Host memory read) -2. MMIO latency (Write+Read) -3. MMIO BW (64B MMIO writes) -4. BW (Read/Write, Read only, Wr only)

-

Host Exerciser Memory (HE-MEM)

-

HE-MEM is used to exercise use of FPGA connected DDR; data read from the host is -written to DDR, and the same data is read from DDR before sending it back to the -host. HE-MEM uses external DDR memory (i.e. EMIF) to store data. It has a customized -version of the AVMM interface to communicate with the EMIF memory controller.

-

Execution of these exercisors requires the user to bind specific VF endpoint to vfio-pci -Bind the correct endpoint for a device with B/D/F 0000:b1:00.0

-

[user@localhost]: sudo opae.io init -d 0000:b1:00.2 user:user

-

HOST EXERCISER SUB COMMANDS

-

lpbk

-

run host exerciser loopback test

-

mem

-

run host exerciser memory test

-

OPTIONAL ARGUMENTS

-

--help, -h

-

Prints help information and exit.

-

COMMON ARGUMENTS / OPTIONS

-

The following arguments are common to all commands and are optional.

-

-p,--pci-address

-

PCIe domain, bus, device, function number of fpga resource.

-

-l,--log-level

-

set host exerciser tool log level, trace, debug, info, warning, error, critical, off

-

-s,--shared

-

open FPGA PCIe resource in shared mode

-

-t,--timeout

-

host exerciser tool time out, by default time out 60000

-

-m,--mode

-

host exerciser test modes are lpbk, read, write, trput

-

--cls

-

Number of cachelines per request 1, 2, 3, 4.

-

--continuousmode

-

Configures test rollover or test termination mode.

-

--atomic

-

atomic requests.

-

--encoding

-

select data mover mode or power user mode or random.

-

-d,--delay

-

Enables random delay insertion between requests.

-

--interleave

-

Enables interleave requests in throughput mode. -Value:3'b000-Rd,Wr,Rd,Wr -Value:3'b001-Rd,Rd,Wr,Wr -Value:3'b010-Rd,Rd,Rd,Rd,Wr,Wr,Wr,Wr -Value:3'b011-Not supported

-

--interrupt

-

Accelerator interrupt vector Number.

-

--contmodetime

-

Continuous mode time in seconds.

-

--testall

-

Run all host exerciser tests.

-

--clock-mhz

-

pcie clock frequency, default value 350Mhz.

-

EXAMPLES

-

This command exerciser Loopback afu: -

host_exerciser lpbk
-

-

This command exerciser memory afu: -

host_exerciser mem
-

-

This command exerciser Loopback afu on pcie 000:3b:00.0: -

host_exerciser --pci-address 000:3b:00.0    lpbk
-

-

This command exerciser Loopback afu on pcie 000:3b:00.0 and run in write mode: -

host_exerciser --pci-address 000:3b:00.0   --mode write lpbl
-

-

This command exerciser Loopback afu on pcie 000:3b:00.0 and run 2 cache lines per request: -

host_exerciser --pci-address 000:3b:00.0   --cls cl_2  lpbk
-

-

This command exerciser Loopback afu on pcie 000:3b:00.0 and run continuous mode for 10 seconds: -

host_exerciser --pci-address 000:3b:00.0   -cls cl_1   -m 0 --continuousmode true --contmodetime 10 lpbk
-

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/hssi/hssi/index.html b/sw/fpga_tools/hssi/hssi/index.html deleted file mode 100644 index ba718ca3d..000000000 --- a/sw/fpga_tools/hssi/hssi/index.html +++ /dev/null @@ -1,1981 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - hssi - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

hssi

-

SYNOPSIS

-

hssi COMMON_OPTIONS MODE MODE_OPTIONS

-

DESCRIPTION

-

The hssi application provides a means of interacting with the 10G and -with the 100G HE-HSSI AFUs. In both 10G and 100G operating modes, the application -initializes the AFU and completes the desired transfer as described by the mode- -specific options.

-

COMMON_OPTIONS - application options common to both 10G and 100G modes.

-

-h, --help

-
Display common command-line help and exit.
-
-

-p, --pci-address ADDR

-
The PCIe address of the desired accelerator in ssss:bb:dd.f format.
-
-

-s, --shared on|off

-
Whether to open the accelerator in shared mode. The default is off.
-
-

-t, --timeout VALUE

-
The application timeout value in milliseconds. The default timeout is 60000 msec.
-
-

MODE - select AFU. Valid values are hssi_10g and hssi_100g.

-

MODE_OPTIONS [hssi_10g] - application options specific to the 10G AFU.

-

-h, --help

-
Display 10G AFU specific command-line help and exit.
-
-

--port PORT

-
Select the QSFP port in the range 0-7. The default is port 0.
-
-

--eth-loopback on|off

-
Whether to enable loopback on the ethernet interface. Valid values are
-on and off. The default is on.
-
-

--num-packets PACKETS

-
The number of packets to transfer. The default is 1 packet.
-
-

--random-length fixed|random

-
Specify packet length randomization. Valid values are fixed and
-random. The default is fixed (no randomization).
-
-

--random-payload incremental|random

-
Specify payload randomization. Valid values are incremental and
-random. The default is incremental.
-
-

--packet-length LENGTH

-
Specify packet length. The default is 64 bytes.
-
-

--src-addr ADDR

-
Specify the source MAC address. The default value is 11:22:33:44:55:66.
-
-

--dest-addr ADDR

-
Specify the destination MAC address. The default value is 77:88:99:aa:bb:cc.
-
-

--rnd-seed0 SEED0

-
Specify the prbs generator bits [31:0]. The default is 1592590336.
-
-

--rnd-seed1 SEED1

-
Specify the prbs generator bits [47:32]. The default is 1592590337.
-
-

--rnd-seed2 SEED2

-
Specify the prbs generator bits [91:64]. The default is 155373.
-
-

MODE_OPTIONS [hssi_100g] - application options specific to the 100G AFU.

-

--port PORT

-
Select the QSFP port in the range 0-7. The default is port 0.
-
-

--eth-loopback on|off

-
Whether to enable loopback on the ethernet interface. Valid values are
-on and off. The default is on.
-
-

--num-packets PACKETS

-
The number of packets to transfer. The default is 1 packet.
-
-

--gap random|none

-
Inter-packet gap. Valid values are random and none. The default is none.
-
-

--pattern random|fixed|increment

-
Pattern mode. Valid values are random, fixed, or increment. The default
-is random.
-
-

--src-addr ADDR

-
Specify the source MAC address. The default value is 11:22:33:44:55:66.
-
-

--dest-addr ADDR

-
Specify the destination MAC address. The default value is 77:88:99:aa:bb:cc.
-
-

--start-size SIZE

-
Specify the packet size in bytes, or the first packet size for --pattern increment.
-
-

--end-size SIZE

-
Specify the end packet size in bytes.
-
-

--end-select pkt_num|gen_idle

-
Specify packet generation end mode.
-
-

MODE_OPTIONS [pkt_filt_10g] - application options specific to the Packet Filter 10G AFU.

-

--dfl-dev DFL_DEV

-
Packet Filter DFL device, eg --dfl-dev dfl_dev.0
-
-

MODE_OPTIONS [pkt_filt_100g] - application options specific to the Packet Filter 100G AFU.

-

--dfl-dev DFL_DEV

-
Packet Filter DFL device, eg --dfl-dev dfl_dev.1
-
-

EXAMPLES

-

hssi -h
-hssi hssi_10g -h
-sudo hssi --pci-address=0000:3b:00.0 hssi_10g --eth-loopback=on --num-packets=500
-sudo hssi --pci-address=0000:3b:00.0 hssi_100g --pattern=increment

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/hssi_config/readme/index.html b/sw/fpga_tools/hssi_config/readme/index.html deleted file mode 100644 index cc35be979..000000000 --- a/sw/fpga_tools/hssi_config/readme/index.html +++ /dev/null @@ -1,2083 +0,0 @@ - - - - - - - - - - - - - - - - - - hssi_config # - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

hssi_config

-

Synopsis

-

hssi_config reads or writes HSSI registers on either on an Intel® FPGA using the -FPGA Interface Manager (FIM) or on an HSSI retimer card attached to the board. -hssi_config is only available for the Integrated FPGA Platform. You cannot run it -on the PCIe accelerator card (PAC).

-

Usage

-

hssi_config [--resource|-r <sysfs resource>] [--socket-id|s 0|1] command [command options]

-

Where command is one of the following:

-
    dump [outfile.csv] [--input-file inputfile.csv]
-    iread instance (0,1) device-addr byte-address byte-count
-    iwrite instance (0,1) device-addr byte-address byte1 [byte2 [byte3...]]
-    load [inputfile.csv] [--c-header]
-    read lane(0-15) reg-address
-    rread device(0x30, 0x32, 0x34, 0x36) channel(0-3) address
-    rwrite device(0x30, 0x32, 0x34, 0x36) channel(0-3) address value
-    test (rd|rw) inputfile.csv [--acktimes] [--repeat N]
-    write lane(0-15) reg-address value
-
-

The first argument is the command and any additional arguments are command arguments. -The following options and commands are available:

-

Options

-

[--resource|-r <sysfs resource path>

-

The resource path in the sysfs pseudo-filesystem. -Example: - /sys/devices/pci0000\:5e/0000\:5e\:00.0/resource0

-

[--socket-id 0|1]

-

The socket id of the target FPGA. -Required on two-socket systems to differentiate between the two possible target FPGAs.

-

Commands

-

dump [outfile.csv] [--input-file inputfile.csv]

-

Dump registers to stdout or to a file, if provided. hssi_config has a built-in set of registers to -dump. The first argument is the path to a file to write. The command dumps to stdout if you do not -specify a file name. Use the --input-file option to specify a different set of registers.

-

load [inputfile.csv] [--c-header]

-

Load a set of register values from either stdin or an input file, if provided. The first argument -is the path to a file containing the registers to load. Loads from stdin if omitted.

-

Use --c-header to generate a C header file with an array of 64-bit numbers to write to the -HSSI_CTRL register. This header file can substitute for the input file. -NOTE: You must perform the acknowledge routine after each write.

-

read lane(0-15) reg-address

-

Read from a single XCVR (transceiver) register. -The first command argument is the XCVR lane. Use -1 to specify a read from all lanes. -The second argument is the XCVR address (offset).

-

write lane(0-15) reg-address value

-

Write to a single XCVR register. -The first argument is the XCVR lane. -The second argument is the XCVR address(offset). -The third argument is the value to write to the register.

-

rread device(0x30, 0x32, 0x34, 0x36) channel(0-3) address

-

Read from a single retimer register. -The first argument is the I2C device address. -The second argument is the channel. -The third argument is the register address (or I2C byte address).

-

rwrite device(0x30, 0x32, 0x34, 0x36) channel(0-3) address value

-

Write to a single retimer register. -The first argument is the I2C device address. -The second argument is the channel. -The third argument is the register address (or I2C byte address). -The fourth argument is the value to write.

-

iread instance (0,1) device-addr byte-address byte-count

-

Read from a device on the I2C bus. -The first argument is the I2C controller instance (0 or 1). -The second argument is the device address to read from. -The third argument is the byte address of the register to read from the device. -The fourth argument is the number of bytes to read.

-

iwrite instance (0,1) device-addr byte-address byte1 [byte2 [byte3...]]

-

Write to a device on the I2C bus. -The first argument is the I2C controller instance (0 or 1). -The second argument is the device address to read from. -The third argument is the byte address of the register to read from the device. -All subsequent arguments are the bytes to write to the device.

-

test (rd|rw) inputfile.csv [--acktimes]

-

Perform built-in test for reading or writing XCVR registers. -The first argument is the path to a file containing the registers to test.

-

Overview

-

The hssi_config utility reads or writes hssi equalization parameters stored in either -the transceiver (XCVR) registers or the registers of the retimer on the I2C bus. To access registers, -the hssi controller writes to the HSSI_CTRL register and reads from the HSSI_STAT -register in the FPGA Management Engine (FME). These two registers implement the HSSI AUX bus -mailbox protocol to access devices on other buses. Because hssi_config maps the FME MMIO -space directly, the FPGA driver is not required.

-

Locating the FME Device

-

The FME reads and writes the HSSI_CTRL and HSSI_STAT registers on the NIOS device. -The FME maps the MMIO address space of the FME identified by its resource in the sysfs psuedo-filesystem -in Linux operating systems. To identify resource paths, use the lspci utility to query for Intel -devices with device id of bcc0.

-

Example:

-

lspci -d 8086:bcc0

-

This command should print out at least one line like the following example:

-

5e:00.0 Processing accelerators: Intel Corporation Device bcc0

-

Use the first three numbers (bus:device.function) to locate the device resource -in the sysfs filesystem:

-

/sys/devices/pci0000\:<bus>/0000\:<bus>\:<device>.<function>/resource0

-

For example, the example above with bus of 5e, device of 00 and function of 0 would -use a resource path as follows:

-

/sys/devices/pci0000\:5e/0000\:5e\:00.0/resource0

-

CSV File Format

-

Any CSV file parsed by hssi_config must meet have at least four columns. The following table provides -the column specifications:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ColumnNameDescription
1Register type.Can be either FPGA_RX, FPGA_TX, RTMR_RX, RTMR_TX (or their corresponding numeric values, 1-4).
2Lane or Channel0-15 for XCVR lanes on FPGA, 0-3 for retimer channels. -1 to designate all lanes or channels.
3Device address (on I2C bus)Only applies to retimer registers. 0 - 3, -1 to designate all devices.
4Register address (or offset)Examples: 0x213, 0x100.
5Register value to writeExamples: 0x1, 1, 0. Applies only when loading or writing registers.
-

Examples of Commands

-

Dumping Registers

-

Dump default register set to stdout:

-

>hssi_config dump

-

Dump default registers to a file, data.csv:

-

>hssi_config dump data.csv

-

Dump to an output file, data.csv, Registers specified in an input file, regspec.csv:

-

>hssi_config dump data.csv --input-file regspec.csv

-

Reading Single Registers

-

Read register from XCVR at 0x2e1 on lane 0:

-

>hssi_config read 0 0x2e1

-

Read register 0x109 from retimer on channel 0, device 0x30, channel 1:

-

>hssi_config rread 0 0x30 0x109

-

Loading Registers

-

Load registers specified in an input file called data.csv:

-

>hssi_config load data.csv

-

Load registers specified from stdin:

-

>hssi_config load

-
FPGA_RX,1,-1,0x213,0
-FPGA_RX,2,-1,0x213,0
-FPGA_RX,3,-1,0x213,0
-<CTRL-D>
-
-

Writing Single Registers

-

Write 1 to XCVR register at 0x2e1 on lane 0:

-

>hssi_config write 0 0x2e1 1

-

Read register 0x109 from retimer on channel 0, device 0x30, channel 1:

-

>hssi_config rread 0 0x30 0x109

-

Testing HSSI Read and Write

-

> test (rd|rw) register-file.csv [--acktimes]

-

rd|wr

-

Specifies either a rd or wr of transceiver registers. For writes, -every register in the file is read from and written to in the following sequence:

-

1. Read the register, save the value - 2. Write 1 to the register - 3. Read the register, verify that the register value is 1 - 4. Write 0 to the register - 5. Read the register, verify that the register value is 0 - 6. Write the original value to the register - 7. Read the register, assert it is the original value

-

register=file.csv

-

Specifies the path to a file containing the set of registers to test.

-

--acktimes

-

Specifies the time spent in the ack routine. When measured, a summary of ack times prints -to stdout. This argument is optional.

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/hssi_ethernet/hssiloopback/index.html b/sw/fpga_tools/hssi_ethernet/hssiloopback/index.html deleted file mode 100644 index 785ac7317..000000000 --- a/sw/fpga_tools/hssi_ethernet/hssiloopback/index.html +++ /dev/null @@ -1,1917 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - HSSI ethernet loopback - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

HSSI ethernet loopback

-

SYNOPSIS

-
hssiloopback [-h] [--pcie-address PCIE_ADDRESS, -P PCIE_ADDRESS] --loopback [{enable,disable}]
-
-

DESCRIPTION

-

The hssiloopback tool enables and disable ethernet loopback.

-

OPTIONAL ARGUMENTS

-

-h, --help

-

Prints usage information

-

--pcie-address PCIE_ADDRESS, -P PCIE_ADDRESS

-

The PCIe address of the desired fpga in ssss:bb:dd.f format. sbdf of device to program (e.g. 04:00.0 or 0000:04:00.0). Optional when one device in system.

-

--loopback [{enable,disable}]

-

Ethernet enable or disable loopback.

-

EXAMPLES

-

hssiloopback --pcie-address 0000:04:00.0 --loopback enable

-

Enables ethernet loopback

-

hssiloopback --pcie-address 0000:04:00.0 --loopback disable

-

Disable ethernet loopback

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/hssi_ethernet/hssimac/index.html b/sw/fpga_tools/hssi_ethernet/hssimac/index.html deleted file mode 100644 index a984c4f95..000000000 --- a/sw/fpga_tools/hssi_ethernet/hssimac/index.html +++ /dev/null @@ -1,1915 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - HSSI ethernet mac - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

HSSI ethernet mac

-

SYNOPSIS

-
hssimac [-h] --pcie-address PCIE_ADDRESS [--port PORT]
-
-

DESCRIPTION

-

The hssimac tool provides Maximum TX and RX frame size.

-

OPTIONAL ARGUMENTS

-

-h, --help

-

Prints usage information

-

--pcie-address PCIE_ADDRESS, -P PCIE_ADDRESS

-

The PCIe address of the desired fpga in ssss:bb:dd.f format. sbdf of device to program (e.g. 04:00.0 or 0000:04:00.0).

-

--port PORT

-

hssi port number.

-

EXAMPLES

-

hssimac --pcie-address 0000:04:00.0 --port 1

-

prints Maximum TX and RX frame size for port 1.

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/hssi_ethernet/hssistats/index.html b/sw/fpga_tools/hssi_ethernet/hssistats/index.html deleted file mode 100644 index dab40eb2d..000000000 --- a/sw/fpga_tools/hssi_ethernet/hssistats/index.html +++ /dev/null @@ -1,1913 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - HSSI ethernet statistics - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

HSSI ethernet statistics

-

SYNOPSIS

-
hssistats [-h] [--pcie-address PCIE_ADDRESS, -P PCIE_ADDRESS]
-
-

DESCRIPTION

-

The hssistats tool provides the MAC statistics.

-

OPTIONAL ARGUMENTS

-

-h, --help

-

Prints usage information

-

--pcie-address PCIE_ADDRESS, -P PCIE_ADDRESS

-

The PCIe address of the desired fpga in ssss:bb:dd.f format. sbdf of device to program (e.g. 04:00.0 or 0000:04:00.0). Optional when one device in system.

-

EXAMPLES

-

hssistats --pcie-address 0000:04:00.0

-

prints the MAC statistics

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/hssi_loopback/readme/index.html b/sw/fpga_tools/hssi_loopback/readme/index.html deleted file mode 100644 index d13ad7dda..000000000 --- a/sw/fpga_tools/hssi_loopback/readme/index.html +++ /dev/null @@ -1,1906 +0,0 @@ - - - - - - - - - - - - - - - - - - hssi_loopback # - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

hssi_loopback

-

NAME

-

hssi_loopback - Software utility to run HSSI loopback tests on FPGA

-

SYNOPSIS

-

hssi_loopback [[--bus|-b <bus number>] [--device | -d <device number>] [--function | -f <function number>]]|[--socket-id <socket-id>] - [--mode|-m auto|e40|e10] - [send [<source port> [<destination port>] [--packet-count|-c <count>] [--packet-delay|-d <delay>] [--packet-length|-l <length>]] |status [clear] | stop | readmacs

-

DESCRIPTION

-

The hssi_loopback utility works in conjunction with a packet generator accelerator function unit (AFU) -to test high-speed serial interface (HSSI) cards. The hssi_loopback utility tests both external and internal loopbacks. -hssi_loopback runs an external loopback test when the command line arguments include both source and destination ports. -hssi_loopback runs an internal loopback test when command line arguments include a single port. hssi_loopback -only runs on the Intel Xeon with Arria 10 FPGA. You cannot run it on the Intel PAC (programmable accelerator card).

-

NOTE: The following limitations apply to the current version of hssi_loopback:

-
    -
  • For the external loopback the two port arguments can be the same. For the e10 design, the ports should be the same.
  • -
  • The hssi_loopback test supports only the e40 and e10 E2E AFUs. The e10 E2E AFU tests HSSI with a retimer card.
  • -
  • The hssi_loopback test uses the control and status registers (CSRs) defined in the AFU.
  • -
-

OPTIONS

-

-S SOCKET_ID, --socket-id SOCKET_ID

-

Socket ID FPGA resource.

-

-B BUS, --bus BUS

-

Bus ID of FPGA resource.

-

-D DEVICE, --device DEVICE

-

Device ID of FPGA resource.

-

-F FUNCTION, --function FUNCTION

-

Function ID of FPGA resource.

-

-G, --guid

-

Specifies guid for the resource enumeration.

-

-m, --mode

-

One of the following: [auto, e40, e10] -auto is the default and indicates that the software runs the mode based on the first accelerator functional -unit it identifies.

-

-t, --timeout

-

Timeout (in seconds) before the application terminates in continuous mode. Continuous mode is the default -when you do not specify the number of packets.

-

-y, --delay

-

Delay (in seconds) between printing out a simple status line. Default is 0.100 seconds (100 milliseconds).

-

-c, --packet-count

-

The number of packets to send.

-

-d, --packet-delay

-

The delay in between packets. This delay is the number of 100 MHz clock cycles, roughly 10 nanoseconds.

-

-s, --packet-size

-

The packet size to send. The minimum is 46 bytes and the maximum is 1500 bytes. The default is 46 bytes.

-

COMMANDS

-

send <source port> [<destination port>] [--packet-count|-c <count>] [--packet-delay|-d <delay>] [--packet-length|-l <length>]

-

Send packets from one port to the other. If the command line does not specify a destination port, the test runs an internal -loopback. Otherwise, the test runs an external loopback from the source port to the destination port.

-

status [clear]

-

Read and interpret the status registers and print to the screen. clear clears the status registers.

-

stop

-

Issue a stop command to all Ethernet controllers in the AFU.

-

readmacs

-

Read and display the port MAC addresses. An EEPROM stores the MAC addresses.

-

EXIT CODES

-

0 Success - Number of packets received are equal to the number of packets sent and no errors - are reported.

-

-1 Loopback failure - Either number of packets does not match or the test detected errors.

-

-2 Errors parsing arguments.

-

EXAMPLES

-

Read the MAC addresses of the AFU loaded on bus 0x5e:

-
>sudo hssi_loopback readmacs -B 0x5e
-
-

Run an external loopback, sending 100 packets from port 0 to port 1. The AFU is on bus 0x5e:

-
>sudo hssi_loopback -B 0x5e send 0 1 -c 100
-
-

Run an internal loopback until a timeout of 5 seconds is reached. The AFU is on bus 0x5e:

-
>sudo hssi_loopback -B 0x5e send 0 -t 5
-
- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/mem_tg/mem_tg/index.html b/sw/fpga_tools/mem_tg/mem_tg/index.html deleted file mode 100644 index d5031faf9..000000000 --- a/sw/fpga_tools/mem_tg/mem_tg/index.html +++ /dev/null @@ -1,1990 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - mem_tg - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

mem_tg

-

SYNOPSIS

-
Usage: mem_tg [OPTIONS] SUBCOMMAND
-
-Options:
-  -h,--help                   Print this help message and exit
-  -g,--guid TEXT=4DADEA34-2C78-48CB-A3DC-5B831F5CECBB
-                              GUID
-  -p,--pci-address TEXT       [<domain>:]<bus>:<device>.<function>
-  -l,--log-level TEXT:{trace,debug,info,warning,error,critical,off}=info
-                              stdout logging level
-  -s,--shared                 open in shared mode, default is off
-  -t,--timeout UINT=60000     test timeout (msec)
-  -m,--mem-channel UINT=0     Target memory bank for test to run on (0 indexed)
-  --loops UINT=1              Number of read/write loops to be run
-  -w,--writes UINT=1          Number of unique write transactions per loop
-  -r,--reads UINT=1           Number of unique read transactions per loop
-  -b,--bls UINT=1             Burst length of each request
-  --stride UINT=1             Address stride for each sequential transaction
-  --data UINT:value in {fixed->0,prbs15->2,prbs31->3,prbs7->1,rot1->3} OR {0,2,3,1,3}=fixed
-                              Memory traffic data pattern: fixed, prbs7, prbs15, prbs31, rot1
-  -f,--mem-frequency UINT=0   Memory traffic clock frequency in MHz
-
-Subcommands:
-  tg_test                     configure & run mem traffic generator test
-
-

DESCRIPTION

-

The memory traffic generator (TG) used to exercise and test available memory channels -with a configurable traffic pattern.

-

Execution of this application requires the user to bind the specific VF endpoint containing the mem_tg AFU id to vfio-pci

-

In the TG, read responses are checked against a specified pattern. If the application is configured to perform a read only test on a region of memory that has not previously been initialized to contain that pattern it will flag a test failure.

-

OPTIONAL ARGUMENTS

-

--help, -h

-

Prints help information and exit.

-

COMMON ARGUMENTS / OPTIONS

-

The following arguments are common to all commands and are optional.

-

-p,--pci-address

-

PCIe domain, bus, device, function number of fpga resource.

-

-l,--log-level

-

set application log level, trace, debug, info, warning, error, critical, off

-

-s,--shared

-

open FPGA PCIe resource in shared mode

-

-t,--timeout

-

mem_tg application time out, by default time out 60000

-

-m,--mem-channel

-

Target memory bank for test to run on (0 indexed) -default: 0

-

--loops

-

Number of read/write loops to be run -default: 1

-

-w,--writes

-

Number of unique write transactions per loop. -default: 1

-

-r,--reads

-

Number of unique read transactions per loop -default: 1

-

-b,--bls

-

AXI4 burst length of each request. Supports 1-256 transfers beginning from 0. -default: 0

-

--stride

-

Address stride for each sequential transaction (>= burst length) -default: 1

-

--data

-

Memory traffic data pattern. -0 = fixed {0xFF, 0x00} -1 = prbs7 -2 = prbs15 -3 = prbs31 -4 = rot1

-

default: fixed

-

-f, --mem-frequency

-

Memory traffic clock frequency in MHz -default: 300 MHz

-

EXAMPLES

-

This command will run a basic read/write test on the channel 0 traffic generator: -

mem_tg tg_test
-

-

This command will run the application for an afu on pcie 000:b1:00.7: -

mem_tg --pci-address 000:b1:00.7 tg_test
-

-

This command will test channel 2 write bandwidth: -

mem_tg -loops 1000 -w 1000 -r 0 -m 2 tg_test
-

-

This command will perform a read bandwidth test with a burst of 16 on channel 1 and perform a data comparison with the prbs7 pattern: -

mem_tg -loops 1000 -w 0 -r 1000 -b 0xF --data prbs7 -m 1 tg_test
-

-

This command will perform a read/write test with 1 MB strided access to channel 0 memory: -

mem_tg -loops 10000 --stride 0x100000 tg_test
-

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/mmlink/mmlink/index.html b/sw/fpga_tools/mmlink/mmlink/index.html deleted file mode 100644 index c2138f03c..000000000 --- a/sw/fpga_tools/mmlink/mmlink/index.html +++ /dev/null @@ -1,1943 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - mmlink - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

mmlink

-

Synopsis

-

mmlink [-v] [-B <bus>] [-D <device>] [-F <function>] [-S <socket>] [-P <TCP port>] [-I <IP Address>]

-

Description

-

The Remote Signal Tap logic analyzer provides real-time hardware debugging for the Accelerator Function Unit (AFU). -It provides a signal trace capability that the Quartus Prime software adds to the AFU. The Remote Signal Tap logic -analyzer provides access to the Remote Signal Tap part of the Port MMIO space and then runs the remote protocol.

-

Examples

-

./mmlink -B 0x5e -P 3333

-

MMLink app starts and listens for connection.

-

Options

-

-v,--version

-

Prints version information and exits.

-

-B,--bus

-

FPGA Bus number.

-

-D,--device

-

FPGA Device number.

-

-F,--function

-

FPGA function number.

-

-S,--socket

-

FPGA socket number.

-

-P,--port

-

TCP port number.

-

-I,--ip

-

IP address of FPGA system.

-

Notes

-

Driver privilege:

-

Change AFU driver privilege to user:

-
$ chmod 777 /dev/intel-fpga-port.0
-
-

Change locked memory size:

-

edit the file /etc/security/limits.conf

-
$ sudo vi /etc/security/limits.conf
-
-user    hard   memlock           10000
-
-user    soft   memlock           10000
-
-

Exit terminal and log into a new terminal.

-

Verify that the locked memory is now set: -``` -$ ulimit -l 10000

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/ofs.uio/ofs.uio/index.html b/sw/fpga_tools/ofs.uio/ofs.uio/index.html deleted file mode 100644 index ad47a7924..000000000 --- a/sw/fpga_tools/ofs.uio/ofs.uio/index.html +++ /dev/null @@ -1,2167 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - ofs.uio - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

ofs.uio

-

SYNOPSIS

-

ofs.uio [-h] [--pcie-address PCIE_ADDRESS] [--uio uiox] [--feature-id FEATURE_ID] [--region-index REGION_INDEX] - [--mailbox-cmdcsr offset] [--bit-size {8,16,32,64}] [--peek offset] [--poke offset value] - [--mailbox-read offset] [--mailbox-dump address size] [--mailbox-write address value]

-

ofs.uio [--uio uiox] [--peek offset]
-ofs.uio [--uio uiox] [--poke offset value]
-ofs.uio [--uio uiox] [--mailbox-read address]
-ofs.uio [--uio uiox] [--mailbox-write address value]
-ofs.uio [--uio uiox] [--mailbox-dump address size]
-ofs.uio [--pcie-address PCIE_ADDRESS] [--feature-id FEATURE_ID] [--peek offset]
-ofs.uio [--pcie-address PCIE_ADDRESS] [--feature-id FEATURE_ID] [--poke offset value]
-ofs.uio [--pcie-address PCIE_ADDRESS] [--feature-id FEATURE_ID] [--mailbox-read address]
-ofs.uio [--pcie-address PCIE_ADDRESS] [--feature-id FEATURE_ID] [--mailbox-write address value]
-ofs.uio [--pcie-address PCIE_ADDRESS] [--feature-id FEATURE_ID] [--mailbox-dump address size]

-

DESCRIPTION

-

ofs.uio is a tool that provides user space access to DFL UIO devices, -command line options like peek, poke, mailbox-read, mailbox-write, mailbox-dump to -access Configuration and Status Registers (CSRs).

-

OPTIONS

-

Peek

-

Peek/Read UIO CSR offset
-ofs.uio [--uio uio] [--peek offset]
-ofs.uio [--pcie-address PCIE_ADDRESS] [--feature-id FEATURE_ID] [--peek offset]

-

Poke

-

Poke/Write value to UIO CSR offset
-ofs.uio [--uio uio] [--poke offset value]
-ofs.uio [--pcie-address PCIE_ADDRESS] [--feature-id FEATURE_ID] [--poke offset value]

-

Mailbox Read

-

Read CSR address using mailbox
-ofs.uio [--uio uio] [--mailbox-read address]
-ofs.uio [--pcie-address PCIE_ADDRESS] [--feature-id FEATURE_ID] [--mailbox-read address]

-

Mailbox Write

-

Write value to CSR address using mailbox
-ofs.uio [--uio uio] [--mailbox-write address value]
-ofs.uio [--pcie-address PCIE_ADDRESS] [--feature-id FEATURE_ID] [--mailbox-write address value]

-

Mailbox Dump

-

Reads/Dumps block size of CSR address using mailbox
-ofs.uio [--uio uio] [--mailbox-dump address size]
-ofs.uio [--pcie-address PCIE_ADDRESS] [--feature-id FEATURE_ID] [--mailbox-dump address size]

-

Bit size

-

Read/Write bit-field 8,16,32,64 sizes
-ofs.uio [--uio uio] --bit-size 8 [--peek offset]
-ofs.uio [--uio uio] --bit-size 32 [--peek offset]

-

PCIe Address

-

PCIE_ADDR PCIe address of FPGA device
-ofs.uio [--pcie-address PCIE_ADDRESS] [--feature-id FEATURE_ID] [--peek offset]

-

UIO region index

-

UIO region index, default region index is 0
-ofs.uio [--uio uio] --region-index 0 [--peek offset]
-ofs.uio [--uio uio] --region-index 1 [--peek offset]

-

Mailbox command status csr offset

-

Mailbox command status csr offset, -default value set to dfl pcie subsystem system feature mailbox command status register offset 0x28
-ofs.uio [--uio uio] --mailbox-cmdcsr 0xa8 [--mailbox-read address]
-ofs.uio [--pcie-address PCIE_ADDRESS] [--feature-id FEATURE_ID] --mailbox-cmdcsr 0xa8 [--mailbox-read address]

-

EXAMPLES

-

Peek/Read -

ofs.uio --uio uio0 --peek 0x0
-peek(0x0): 0x3000000010002015
-
-ofs.uio --uio uio6 --peek 0x0
-peek(0x0): 0x3000000100000020
-
-ofs.uio --pcie-address 0000:b1:00.0 --feature-id 0x15 --peek 0x0
-peek(0x0): 0x3000000010002015
-
-ofs.uio --uio uio0 --peek 0x0 --bit-size 32
-peek(0x0): 0x10002015
-

-

Poke/Write -

ofs.uio --uio uio6 --peek 0x8
-peek(0x8): 0x0
-ofs.uio --uio uio6 --poke  0x8 0xabcdd12345
-poke(0x8):0xabcdd12345
-
-ofs.uio --pcie-address 0000:b1:00.0 --feature-id 0x15 --peek 0x0
-peek(0x8): 0x0
-ofs.uio --pcie-address 0000:b1:00.0 --feature-id 0x15 --poke  0x8 0x1234
-poke(0x8):0x1234
-

-

Mailbox Read -

ofs.uio --uio uio6 --mailbox-read 0x0
-MailboxRead(0x0): 0x1000000
-ofs.uio --uio uio6 --mailbox-read 0x8
-MailboxRead(0x8): 0x110c000
-
-ofs.uio --pcie-address 0000:b1:00.0 --feature-id 0x20 --mailbox-read 0x0
-MailboxRead(0x0): 0x1000000
-ofs.uio --pcie-address 0000:b1:00.0 --feature-id 0x20 --mailbox-read 0x8 
-MailboxRead(0x8): 0x110c000
-

-

Mailbox Write -

ofs.uio --uio uio6 --mailbox-write 0x0 0x1234
-MailboxWrite(0x0):0x1234
-ofs.uio --uio uio6 --mailbox-read 0x0
-MailboxRead(0x0):0x1234
-
-ofs.uio --pcie-address 0000:b1:00.0 --feature-id 0x20 --mailbox-write 0x0 0x1234
-MailboxWrite(0x0):0x1234
-ofs.uio --pcie-address 0000:b1:00.0 --feature-id 0x20 --mailbox-read 0x0 
-MailboxRead(0x0):0x1234
-

-

Mailbox Dump -

ofs.uio --uio uio6 --mailbox-dump 0x0 0x10
-MailboxDump(0x0): 0x1000000
-MailboxDump(0x4): 0x1000000
-MailboxDump(0x8): 0x110c000
-MailboxDump(0xc): 0x110c000
-MailboxDump(0x10): 0x0
-MailboxDump(0x14): 0x0
-MailboxDump(0x18): 0x0
-MailboxDump(0x1c): 0x0
-MailboxDump(0x20): 0x0
-MailboxDump(0x24): 0x0
-MailboxDump(0x28): 0x0
-MailboxDump(0x2c): 0x0
-MailboxDump(0x30): 0x0
-MailboxDump(0x34): 0x0
-MailboxDump(0x38): 0x0
-MailboxDump(0x3c): 0x0
-
-
-
-ofs.uio --pcie-address 0000:b1:00.0 --feature-id 0x20 --mailbox-dump 0x0 0x10
-MailboxDump(0x0): 0x1000000
-MailboxDump(0x4): 0x1000000
-MailboxDump(0x8): 0x110c000
-MailboxDump(0xc): 0x110c000
-MailboxDump(0x10): 0x0
-MailboxDump(0x14): 0x0
-MailboxDump(0x18): 0x0
-MailboxDump(0x1c): 0x0
-MailboxDump(0x20): 0x0
-MailboxDump(0x24): 0x0
-MailboxDump(0x28): 0x0
-MailboxDump(0x2c): 0x0
-MailboxDump(0x30): 0x0
-MailboxDump(0x34): 0x0
-MailboxDump(0x38): 0x0
-MailboxDump(0x3c): 0x0
-

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/opae.io/opae.io/index.html b/sw/fpga_tools/opae.io/opae.io/index.html deleted file mode 100644 index 0e5caf70f..000000000 --- a/sw/fpga_tools/opae.io/opae.io/index.html +++ /dev/null @@ -1,2135 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - opae.io - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

opae.io

-

SYNOPSIS

-

opae.io ls [-v,--viddid VID:DID]
-opae.io init [-d PCI_ADDR USER[:GROUP]]
-opae.io release [-d PCI_ADDR]
-opae.io [-d PCI_ADDR] [-r REGION] walk OFFSET [-u,--show-uuid]
-opae.io [-d PCI_ADDR] [-r REGION] peek OFFSET
-opae.io [-d PCI_ADDR] [-r REGION] poke OFFSET VALUE
-opae.io [-d PCI_ADDR] [-r REGION] SCRIPT ARG1 ARG2 ... ARGN
-opae.io [-d PCI_ADDR] [-r REGION]

-

DESCRIPTION

-

opae.io is an interactive Python environment packaged on top of -libopaevfio.so, which provides user space access to PCIe devices -via the vfio-pci driver. The main feature of opae.io is its built-in -Python command interpreter, along with some Python bindings that provide -a means to access Configuration and Status Registers (CSRs) that reside -on the PCIe device.

-

opae.io has two operating modes: command line mode and interactive -mode.

-

COMMAND LINE MODE

-

To view the accelerator devices that are present on the system, opae.io -provides the ls command option.

-

opae.io ls [-v,--viddid VID:DID]

-

Each accelerator device is listed along with the PCIe address, the -PCIe vendor/device ID, a brief description of the device, and the -driver to which the device is currently bound.

-

opae.io provide an option to initialize a PCIe device for use with -the vfio-pci driver. In order for the device CSRs to be accessed from -user space, the device must first be bound to the vfio-pci driver. This -is the job of the init command option.

-

opae.io init [-d PCI_ADDR USER:[GROUP]]

-

The init command unbinds the specified device from its current -driver and binds it to vfio-pci. This creates a new vfio group under -/dev/vfio. This group path is then used by the libopaevfio.so -library to interact with the device.

-

To release the PCIe device from vfio-pci and return it to use with its -previous driver, the release command option is used.

-

opae.io release [-d PCI_ADDR]

-

The release command option reverses the actions of the last -init command, releasing the device from vfio-pci and binding -it to the driver which was bound at the time the init command -was issued.

-

The walk command option traverses and displays the Device -Feature List of the given region.

-

opae.io walk [-d PCI_ADDR] [-r REGION] [OFFSET] [-u,--show-uuid]

-

The various fields of each Device Feature Header are displayed. The ---show-uuid option additionally displays the GUID for each feature. -OFFSET can be used to specify the beginning of the DFL in the MMIO -region.

-

The peek command option reads and displays a CSR value.

-

opae.io peek [-d PCI_ADDR] [-r REGION] OFFSET

-

The poke command option writes a given value to a CSR.

-

opae.io poke [-d PCI_ADDR] [-r REGION] OFFSET VALUE

-

opae.io can also execute Python scripts from the command line. -These Python scripts may contain calls to the device built-in -functions that are available during an interactive session. Refer -to the description of interactive mode for details.

-

opae.io [-d PCI_ADDR] [-r REGION] myscript.py a b c

-

In order to enter the interactive mode of opae.io, simply -invoke it and optionally pass the desired device address and -MMIO region options.

-

opae.io [-d PCI_ADDR] [-r REGION]

-

INTERACTIVE MODE

-

Upon entering interactive mode, opae.io begins a Python -interpreter session and displays the command prompt shown below:

-

0000:3f:00.0[0]>>

-

The first portion of the prompt shows the address of the active -PCIe device, here 0000:3f:00.0. The part in square brackets shows -the active MMIO region, here [0].

-

The interpreter waits for a valid Python command, then attempts -to execute the given command in the usual way. The only -differences between the traditional Python command intepreter and -opae.io are that opae.io provides 1) the notion of an active -PCIe device and MMIO region and 2) several built-in functions and -objects that allow manipulating the active device and MMIO region.

-

BUILT-IN FUNCTIONS

-

The opae.io built-in functions assume an active device and -MMIO region. Attempting to use the built-in functions without first -opening a device and region will result in errors.

-

peek(OFFSET)

-

The peek built-in function reads and displays a CSR value from -the active device and region, at the offset supplied by its argument.

-

0000:3f:00.0[0]>> peek(0x28)
-0xdeadbeef

-

poke(OFFSET, VALUE)

-

The poke built-in function writes the given VALUE to the current -MMIO region at the given OFFSET.

-

0000:3f:00.0[0]>> poke(0x28, 0xdeadbeef)

-

read_csr(OFFSET)

-

The read_csr built-in function returns the value of the CSR at -the active MMIO region and the given OFFSET.

-

0000:3f:00.0[0]>> print('0x{:0x}'.format(read_csr(0x28)))
-0xdeadbeef

-

write_csr(OFFSET, VALUE)

-

The write_csr built-in function writes the given VALUE to -the current MMIO region at the given OFFSET.

-

0000:3f:00.0[0]>> write_csr(0x28, 0xdeadbeef)

-

device(PCI_ADDR)

-

The device built-in function allows changing the active -PCIe device.

-

0000:3f:00.0[0]>> device('0000:2b:00.0')
-0000:2b:00.0>>

-

region(REGION)

-

The region built-in function allows changing the active -MMIO region.

-

0000:2b:00.0>> region(0)
-0000:2b:00.0[0]>>

-

allocate_buffer(SIZE)

-

The allocate_buffer built-in function creates and returns -a DMA buffer object. The underlying buffer will be SIZE bytes -in length.

-

0000:2b:00.0[0]>> b1 = allocate_buffer(4096)
-0000:2b:00.0[0]>> print(b1.size, '0x{:0x}'.format(b1.address), b1.io_address)
-4096 0x7f9361c66000 0

-

version()

-

The version built-in function returns a tuple containing -the four components used to identify the opae.io version:

-

0000:2b:00.0[0]>> print(version())
-('opae.io', 0, 2, 0)

-

BUILT-IN OBJECTS

-

opae.io interactive mode provides two global objects -corresponding to the current device and that device's current -MMIO region. These objects are referred to by global variables -the_device and the_region, respectively.

-

The device class:

-

the_device.descriptor() : method that returns the integer file -descriptor of the VFIO container.

-

0000:2b:00.0[0]>> print(the_device.descriptor())
-5

-

the_device.repr() : method that is invoked when a device -object is printed.

-

0000:2b:00.0[0]>> print(the_device)
-0000:2b:00.0

-

the_device.allocate(SIZE) : method that allocates and returns a -system_buffer object. The buffer will be mapped into the -DMA space of the_device.

-

0000:2b:00.0[0]>> b1 = the_device.allocate(4096)

-

the_device.pci_address() : read-only property that returns the -PCIe address of the_device.

-

0000:2b:00.0[0]>> print(the_device.pci_address)
-0000:2b:00.0

-

the_device.num_regions : read-only property that returns the -number of MMIO regions in the_device.

-

0000:2b:00.0[0]>> print(the_device.num_regions)
-2

-

the_device.regions : read-only property that returns a list -of the active MMIO regions of the_device:

-

0000:2b:00.0[0]>> print(the_device.regions)
-[0, 2]

-

The region class:

-

the_region.write32(OFFSET, VALUE) : method that writes a -32-bit VALUE to the CSR at OFFSET.

-

the_region.read32(OFFSET) : method that returns a 32-bit -CSR at the given OFFSET.

-

0000:2b:00.0[0]>> the_region.write32(0x28, 0xdeadbeef)
-0000:2b:00.0[0]>> print('0x{:0x}'.format(the_region.read32(0x28)))
-0xdeadbeef

-

the_region.write64(OFFSET, VALUE): method that writes a -64-bit VALUE to the CSR at OFFSET.

-

the_region.read64(OFFSET): method that returns a 64-bit -CSR at the given OFFSET.

-

0000:2b:00.0[0]>> the_region.write64(0x28, 0xbaddecaf)
-0000:2b:00.0[0]>> print('0x{:0x}'.format(the_region.read64(0x28)))
-0xbaddecaf

-

the_region.index(): method that returns the MMIO index -of the_region.

-

0000:2b:00.0[0]>> print(the_region.index())
-0

-

the_region.repr(): method that is invoked when a region -object is printed.

-

0000:2b:00.0[0]>> print(the_region)
-0

-

the_region.len(): method that is invoked to determine the -MMIO region size.

-

0000:2b:00.0[0]>> print(len(the_region))
-524288

-

The allocate_buffer() built-in function and the -device.allocate() method return objects of type system_buffer.

-

The system_buffer class is as follows:

-

buf.size: read-only property that gives the buffer size.

-

0000:2b:00.0[0]>> print(b1.size)
-4096

-

buf.address: read-only property that gives the buffer's -user mode virtual address.

-

0000:2b:00.0[0]>> print('0x{:0x}'.format(b1.address))
-0x7f2c15d8200

-

buf.io_address: read-only property that gives the buffer's -IO address.

-

0000:2b:00.0[0]>> print('0x{:0x}'.format(b1.io_address))
-0x0

-

buf.__getitem__ and buf.__setitem__: indexing get/set -of 64-bit data item.

-

0000:2b:00.0[0]>> b1[0] = 0xdecafbad
-0000:2b:00.0[0]>> print('0x{:0x}'.format(b1[0]))
-0xdecafbad

-

buf.read8(OFFSET)
-buf.read16(OFFSET)
-buf.read32(OFFSET)
-buf.read64(OFFSET) : methods that read the given size -data item from the given buffer OFFSET.

-

buf.fill8(VALUE)
-buf.fill16(VALUE)
-buf.fill32(VALUE)
-buf.fill64(VALUE) : methods that fill the buffer with -the given VALUE, using the given size.

-

b1.compare(b2): method that compares buffers. -The method returns the index of the first byte that miscompares, -or the length of b1.

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/opaeuio/opaeuio/index.html b/sw/fpga_tools/opaeuio/opaeuio/index.html deleted file mode 100644 index 3418bce44..000000000 --- a/sw/fpga_tools/opaeuio/opaeuio/index.html +++ /dev/null @@ -1,1929 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - opaeuio - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

opaeuio

-

SYNOPSIS

-

opaeuio [-h] [-i] [-r] [-d DRIVER] [-u USER] [-g GROUP] [-v] [device]

-

DESCRIPTION

-

The opaeuio command enables the binding/unbinding of a DFL device -to/from the dfl-uio-pdev device driver. -See https://kernel.org/doc/html/v4.14/driver-api/uio-howto.html for a -description of uio.

-

OPTIONS

-

device - The DFL device name, eg dfl_dev.10

-

-h, --help

-
Display command-line help and exit.
-
-

-i, --init

-
Specifies binding mode operation - initialize the given device for uio.
-Used in conjunction with -u, -g, and -d.
-
-

-r, --release

-
Specifies unbinding mode operation - release the given device from uio.
-
-

-d DRIVER, --driver DRIVER

-
Specifies the device driver to bind to when binding to uio.
-The default value is dfl-uio-pdev.
-
-

-u USER, --user USER

-
The user ID to assign when binding to uio. A new device node is created in
-/dev when the device is bound to uio. Use this option to specify
-the new device owner.
-
-

-g GROUP, --group GROUP

-
The group ID to assign when binding to uio. Use this option to specify the
-new device group for the device created in /dev.
-
-

-v, --version

-
Display script version information and exit.
-
-

EXAMPLES

-

opaeuio -h
-opaeuio -v
-sudo opaeuio -i -u lab -g labusers dfl_dev.10
-sudo opaeuio -r dfl_dev.10

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/opaevfio/opaevfio/index.html b/sw/fpga_tools/opaevfio/opaevfio/index.html deleted file mode 100644 index 36d458c3e..000000000 --- a/sw/fpga_tools/opaevfio/opaevfio/index.html +++ /dev/null @@ -1,1935 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - opaevfio - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

opaevfio

-

SYNOPSIS

-

opaevfio [-h] [-i] [-r] [-d DRIVER] [-u USER] [-g GROUP] [-n] [-v] [addr]

-

DESCRIPTION

-

The opaevfio command enables the binding/unbinding of a PCIe device -to/from the vfio-pci device driver. See https://kernel.org/doc/Documentation/vfio.txt -for a description of vfio-pci.

-

OPTIONS

-

addr - The PCIe address of the device in ssss:bb:dd.f format, eg 0000:7f:00.0

-

-h, --help

-
Display command-line help and exit.
-
-

-i, --init

-
Specifies binding mode operation - initialize the given addr for vfio.
-Used in conjunction with -u, -g, and -n.
-
-

-r, --release

-
Specifies unbinding mode operation - release the given addr from vfio.
-Used in conjunction with -d.
-
-

-d DRIVER, --driver DRIVER

-
Specifies the device driver to bind to when releasing from vfio.
-When omitted, the device is not rebound to a driver (default).
-
-

-u USER, --user USER

-
The user ID to assign when binding to vfio. A new device node is created in
-/dev/vfio when the device is bound to vfio-pci. Use this option to specify
-the new device owner.
-
-

-g GROUP, --group GROUP

-
The group ID to assign when binding to vfio. Use this option to specify the
-new device group for the device created in /dev/vfio.
-
-

-n, --no-sriov

-
Do not enable SR-IOV when binding to vfio. The default value for this option
-is FALSE, ie the script should specify SR-IOV functionality when binding to
-the vfio-pci driver. When omitted, the modprobe command which loads the vfio-pci
-driver will contain the `enable_sriov=1` option. When given, it will not.
-
-

-v, --version

-
Display script version information and exit.
-
-

EXAMPLES

-

opaevfio -h
-opaevfio -v
-sudo opaevfio -i -u lab -g labusers 0000:7f:00.0
-sudo opaevfio -r 0000:7f:00.0

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/pac_hssi_config/dcp_hssi_arch.PNG b/sw/fpga_tools/pac_hssi_config/dcp_hssi_arch.PNG deleted file mode 100644 index fbc22fd1f7d7e8a366e1d902997d8eeb33949c73..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27780 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

`4PaUo+}huayvNpJ3t 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 diff --git a/sw/fpga_tools/pac_hssi_config/pac_hssi_config/index.html b/sw/fpga_tools/pac_hssi_config/pac_hssi_config/index.html deleted file mode 100644 index b27d69dcd..000000000 --- a/sw/fpga_tools/pac_hssi_config/pac_hssi_config/index.html +++ /dev/null @@ -1,1941 +0,0 @@ - - - - - - - - - - - - - - - - - - Pac hssi config - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
- -
-
- - - -
-
- - - - - - - -

Pac hssi config

- -
# pac_hssi_config #
-
-## SYNOPSIS ##
-```console
-pac_hssi_config.py [-h] subcommand [subarg] [bdf]
-
-

DESCRIPTION

-

The pac_hssi_config.py tool exercises the Ethernet 10 Gbps (10GbE) and 40GbE transceivers for designs using the -Intel® Programmable Acceleration Card (PAC) with Intel Arria® 10 GX FPGA. This tool does not support the -Intel Xeon® Processor with Integrated FPGA.

-

PAC Ethernet Block Diagram

-

The two required arguments to the pac_hssi_config.py tool specify the subcommand and bus, device, and function (BDF) -for the PCIe device under test. You must provide the BDF parameter for systems with more than one PCIe card.

-
.. note::
-    If you do not provide the BDF when required, the command prints a list of valid BDFs for the system. You can also
-    determine the BDF using the ``lspci`` command.
-
-

For usage help, type the following at a command prompt:

-

pac_hssi_config.py [-h|--help]

-

To configure the network ports, send data, and read statistics, use the following form of the pac_hssi_config.py script:

-

pac_hssi_config.py subcommand [subarg] [bdf]

-

Only a subset of subcommand arguments support subarg.

-

Table 1. General Subcommands

- - - - - - - - - - - - - - - - - - - - -
SubcommandSubargDescription
statN/APrints high speed serial interface (HSSI) controller statistics.
eepromN/AReads the 128-bit unique board ID, MAC address, and board-specific IDs from EEPROM.
-

Table 2. 10/40 GbE Traffic Generation Subcommands

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SubcommandSubargDescription
e10init and e40initN/AInitializes HSSI PHY to 10GbE or 40GbE mode. Clears statistics and enable internal HSSI transceiver loopback.
e10loop and e40loopOn/OffTurns on or off internal HSSI transceiver loopback.
e10reset and e40resetOn/OffAsserts or deasserts AFU reset. Clears packet statistics and disables internal HSSI transceiver loopback.
e10send and e40sendN/ASends 1,000,000 1500-byte packets. For 10GbE sends packets on all four ports. 40GbE has a single port.
e10stat and e40statN/APrints packet statistics.
e10statclr and e40statclrN/AClears packet statistics. Use this command after switching loopback modes to clear any transient statistics accumulated during the mode switch.
-

The transceiver equalization eqwrite and eqread subcommands write and read transceiver equalization settings. -These subcommands require you to specify the transceiver channel, the equalization setting, and the value (for writes). -Use the following form for the eqwrite command:

-

pac_hssi_config.py eqwrite [transceiver channel number] [equalization setting] [equalization value] [bdf]

-

Use the following form for the eqreadcommand:

-

pac_hssi_config.py eqread [transceiver channel number] [equalization setting] [bdf]

-

Table 3. Transceiver Equalization Subcommands

- - - - - - - - - - - - - - - - - - - - - - - -
SubcommandChannel NumberEqualization SettingValue
eqwrite0-30 = Continuous time-linear equalization (CTLE)
1 = Variable gain amplifier (VGA)
2 = DCGAIN
3 = Pre-emphasis first post-tap
4 = Pre-emphasis second post-tap
5 = Pre-emphasis first pre-tap
6 = Pre-emphasis second pre-tap
7 = Differential output voltage (VOD)
Specifies the value for the specified equalization setting.
eqread0-30 = Continuous time-linear equalization (CTLE)
1 = Variable gain amplifier (VGA)
2 = DCGAIN
3 = Pre-emphasis first post-tap
4 = Pre-emphasis second post-tap
5 = Pre-emphasis first pre-tap
6 = Pre-emphasis second pre-tap
7 = Differential output voltage (VOD)
N/A
-

For more information about reconfiguring transceiver analog parameter settings In Arria® 10 devices, refer to "Changing PMA Analog -Parameters" in the -Intel® Arria® 10 Transceiver PHY User Guide.

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/pac_hssi_config/reg_output.PNG b/sw/fpga_tools/pac_hssi_config/reg_output.PNG deleted file mode 100644 index 52a6e4ef14d650445c21b867e1e301089d9389a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18154 zcma&NXIPVKvj$3wK(J6F2ug$)K!OrFf}sckONxj}ZwXSQ21G;>N(7|WCDH>}zy&7s zA_zzcAWcLKAV`&fpmaz=JFok!Z-49C`&`%AKOo8VmgJph=AN1Ro+tLYslhSuDKHBQ z%P}KEy&J%5Bnt~WgzE_KPM+<8Kk&jDaKk{Cg)|_x2z=mh(=pLuVW~*w*>eT~pSk@E ztpiwCj<^5*W9{-SabaP(8fK)YbMt}2&)jzvn@!mJhabeEo~?eA4f&oYS#ELti3MH7 z^h!^6AcE+4!e(k*gg;kfZu6BcpO;d$)6SLVj)fn)VPPKG1)!m$)zIt+h@RpHg8PvR zQZZq>bz!@cUvk^85$GGl!@Z|r^v7ZJUaf;!tpnnBvR{7fAwBt!?x;0Z_TX^K@lZLz zo8ei-N_7rx%iYA}8LXlXcUum34-sLVfx`!j#Dm4dvYnZ8IxaI&Y|g4WuvBc?T`lA& zJ$)*x1;ur)r$J08xx#hf>6$AWEE-#dHCY`i8*0V`&3Ncol_9cIx{Xz6Qvy$*1qsR< zW)WD^+3{fd5KeaSO1r_w$t8Ep{&vLd@);QUDe@O(m;e=lC%CxGs7pC(OVsgSE39Bd zzUw2-r}HpfGbTm}r z|GXJOS-W)R9A3?zB<^XH>IVxQBfa<0@tajiyECou3SD%!B6sisT(L9lzE@m1M5wWu zd2P(TI8pf)wr$x)27&Q;z5CZPzaISTJ6C>LSPhuXxYq2f3%X)x-GtR4KG=hEz#0SE zB_3=RA6|ynq-@zF@LdE=@6Wvv>VGnNF6On=yO|Ngr2QYnP;FyoUjgy+so*$C%wpG;5bK)#(yh^bv#SAS|6$YrGB_?5>RNX*<}CMTPhElHX2cK6`12G?T=gk&aht>}s^k$= z+FEn$9RhR+)w5~x(#!_ZA#qcI0XelAlpxI5{CGH>)&jd`sX|9wRDfLi; z3~q@q#gdRv;vZ>)4Mr~pQ>FTmU3joZI57aHpgvf4mC_yRAiLY~idr#<`?9Qd5V)6w z5a5XIok`IK%O(sj+umf-zYn_?>S3`i3A+8)4QtH2XfDKOQIx018QK^^(}27}2cD8E z{wn_>RjRw=%Jx=ilp)r6P{KzDwqHB%GAZ$h+UH3PJYQ+|b;9c4m=3>*R~j2~NRSc= zzr+I)9768-BYK2w*Y1j|1)aXdp)I!i`-gK8A{oA=X6IsOb0ueGc++}?4Sx2uM_<%M zp26=Sia^f!)U?f3=3_Hws760;+)k>U0DLf!#Q#6!vgz0Gtdk%e<`^+>dqN_Qq|-!yQQO;H>jyGQqR(Z zP}K}>0xU~A&E%sI!l2wQVU*Ub>2x7hmGZ1;+RY1Jxe9K}l&O5^Kz`StLYmH2`@><$ z2e7(P-%O675nrZVmwH!zRFStcV$WmChV%k5uwmzUj`ktQJ9cUA0dRAPbl0Jpwd%2* z%vnKB@i8-_TH#T;)(;oE`1iuJ6l$rik-y2NI+J3k@GZ{@&XsN_U}mmXJfi-RD_oM6 zVC%B4<`b(YUa(>}!-A|CN=R3svd|k{v$56Kj!Ep^3PnL@oRwo^SoFuQYAD-*$Lj0V z*Z=U!P<>up{dX#ULp}FAS6z`%haZKiiJaiCo!YLr$;)WGvTq-bJmt8a@R=Np7c!5N z@un2q8G0M-(h{5xM6WjE)5f!7Dg{nnO7W#go`O9pXy9`(Bi!u<~-V1 z1g`2d(IOK8xj!k^_Fw=skG&xBh>w7}S2jJ#5mnatZoZDC(-bFp-36SaUH(~>-MD!0?_gZalUzUBs|LLBIV zk%n8Fb)acg?yjX;g(x(lAe=tGBC;vtGth&D9tlvle4Z4LKcitALwvvJ%N3`4wzj*& zQs-0gQvjo9Y;V$JSjy>B%Bx1^&WdL~NZo$>OBMSDD$Qc_t&L3=!kPKlWWn}&yzir2 zBK4NqnRlpAE|$z|7Q&O=i-c99af$dpXTlNk264qDv9xcGCo3yhf`B zp}>j3VIiHCc=_E+GyHiOwe9m9r`B>+WqlyxVMz%Z2Gdhr>cUl|*&Ma~V{0-{67%XS zc?Zz0H!cynPD~d`_%1qc%Q&T@G&lqljlZ!>4m9n9-tKQTkQ7h$LFS}dfOI}i%wJ|c z46EL9v869y%5^Kmg|d;PA&ofoVsKleMfl!pXna1XBfrzQkhd3!78#!8L)>H1Nbi~r z_H$C}_R@9MW%d$q>^F6sEDg1hGSwAogDCmQ2V)ARmsKQ-fhy(lL*)&nYY#OTB|!PuymzII*?;vsP_M1p%&J4CGJA|))AUA3MH>FrC; zX&y2>wz1YaO0?e<^WUMZc8hnJ!+)txpZWQV*g=bclXNJGCMYL`a&mmK*SirTa+kP%iJk}etbUNsy&?LO>SSsyIdIhXoid-#L~Qmj#< zn47@Ce4ciF%AF6C6M9QYkjj9_#3v_WyQG^cTs!+`6p7D}?%=MPN64kIU+-(86`u-q#97kKiqMEj`N`HhprPC=Kz&=^1l?oF#cwiJw8#fShaEU} zUp@{{$fonQd+{0<4)6<43GiP1)eS{pRS6B9?5K~G3xa*<&ut7BNx@|Z5rq^=#e_nc zXG=_+m9zr>f=d5sR?+#_oRtszuSW_6}$PWT3)eoYRia3 z+f>Xz7kOCT^w_O^J>XE29h@dzr;+S|> zY-huoyAx48VVZOF5N;|I8CB?gPF27WV6H&vR$ZJ1$&3B_Iovs{ZnrvwQobaL3`*ZxS)gLA@D^qcX?4 z(MY0%O*f+1<*eu0M$E+0{8m=4^49L}aERSrtnq_2Lim2KJtUs(JS4JJ%r8GwkIUjxZRCm`U5`(2Y?94&&sm z$lXf=71zt;J~Y+hQJ1YZn7lBxHJlNU(}D%A&a5dng1~_VueP`uXViYx!li=*GUM|< z_9Z+KGvNLE>5X=XJn?#b(uM>REpW!%Fv$vmGN9z~$Pk)PDxIyGHueS^mZtk9ngT?6 z2SIhWp$v*!;-c-_`{nk6i_{@TdaUj$;R)GT`_>dfFERwO#hUpVM{tg}3Q12qlgO4P8&~Vr*&6jyWwSVD$Qa zm!MU-7M`Y@-vwKP<4%`kt7(|)Y)MKjxPSX%=NE!n@*P5XYZ~aDS8qlO??C9u))Rb& zhw0cey&O94Dl-{_k^5ODshUi_Zq?X*L4&G{JA`gu_W1eWgRevt{pzO@!A6RfW*M!ee6P^l!YX$i^dt zBF!r2mfki~IU;+1eE!%_*}qUJS)ju!{!M39kGSLPJ-AKAV_8`ksYPonTGm)VBcyA4dche15g0d0hDjDFPv=W!_(!)O{jMKboq=Zb1R4bV)DNW0mB zhL({nNn=(ZhZ1-fc=p-_o-GF*(JsVaJAHOE;jaO>1pAFQ*?@P3^c0oB;{UW7zijq( z)NH}*x%}W174&WxdzBE|Gpzgw*|m|le$*B@$?A#P_{k!^7VVDu7yS6ha2@1rE$x+^ z_|mvuK`1Ct0c(EM^$`-)(rR|#l7pSlx=~j%sPPm#37^oaO2}@T3 zE^mgN-(2?Ilmq%n?m8!k7!E8KW48UQP5zg~ucid<;I}aH3p3_z=l&7?AFAcXybQgp z57ujI&&=9UnC*MFzxHt|kWgaQJjYUBl%G%jvULn0peMwdVwD|LU@n&bp?dMeh-by{ z)7yg^v4eFHo<-estdG}Txm1}lbv+Rw&{4d)5SX0O{B}wUE2=~PQet*__4cYa!Lh3U z=QrMdT%sCv!DFRJKG$(9NE&Ezu27{+<2my`LT8+DUIyMiSr>f_U^tm;1uB0P1LYJ{ni zHC_=HkuN}NK*L-FA8lg;Ra>PH!o}+7)i(EDv9Zp}*1yRBH!^D68(`e0TF>s;|PI9iR@^~G%zYw>& z=_S}O7Orl6Z)VPyf2%HSegz1CxSQ!_SVaDH&G?rs65-X01}$K?w`~-OI=Sw70QBi| z7RLqIZO_G{Cou;zY8&ibc#RK#Ex`2Kv91<3w z=-8P;^1h&#BG8i}P)2oTtoWbo5>9M29ZI_m z9(D{&y7NvRzRI^Mb-HZ3gnBeV=x({Hz?~&raJb+~=XqrSDp}jsO?a(URuLn%0}mso zZZzK}{f)qv%O18H0Y2{GAFk;w@+VnVB%%uh9zEopz#I>#^q_X+vW^CAD62Awk zozFlRlH!9C_&7sIsap%}saBiA#|H|tF5bvkh(G24ZKcC8siZ^>Q#r6Ve{YZ42ezR`-x95xBSY^cB%W5ygh$4j>vIAysO+> zk2&QCy+`^erRS*Tb62<*aIrWpQ{)E{a-Xi*J+8HTq%u&!qq1`Cu;~QtyYgkCQ1-K> zpv!?IYRJh(j#SmI#9(%@2G%Y&{q<-QunUm^j}Y!)qZp+aeL4;giq>aKA81&@T&O^Z z`MHcM8$n`_dzq!giY5c-@eO|x6)iXBqOy|*aJrBWY*+!YsI?}M0g+;JE`9@IB>m4J zV1Jnp7MgbP0ciOyVKI>a(oP2w+pjdQIFQ@KnKVEp$8~sqzx-jfw}Jjy zIk*2;m;x!BJ4^^{fJ~~~VYc*mgQnAOPYP>IYsNL4?9e+p)<|4^HqJaY)MWa%LtFz* zQpJ8dRfHsWEII6)|I zS9XSddRwi3Zj`&t`AomJNMb|i^zcIC<4N|7SZ>BVKQ(`;ch}kbn;B{C*D^#8e#2NA zU0yHb1<4}p>M_lXA>X;c$Nz%fh)Gis-GMfI(Wtt{3v<0)kNB~?IMDWq?YZG?ZDaF- zwwm(qHPx}coQBwmJiy~3*;V3A*o<6-j_Fs(Cr~X{`)Z#e?%T^o(QL}}`P>Dl`EB$g z$MIL__tJ6cIljr+eGdmTG1?F=$K4R8<_b@pjaav1Bx_N3)vMs;fn`XC2=41JJrxS3L@$qzQwe-QD`7d%bYzMm4}3J|)LxV8w`O-{)r)sWuz*d-gm zFV(ldNEDe-xERl3JflLmCoDno3@wL1T{IuH$ZUpJ@ryJKA z_0Q?RQ=Wk~jIxF99|;|ZGH&)%OrnkYUzi;j+;TOZ%Fd;|S)@J8J6y)&Bpx@PHI@f$ zalh~Q(&3^|p_uQ>@7)3QAxtcZXi>E>XVyMuSZU7=ubZRVy+BCjF33*@H2Ej4pUL|iw z4KcK=>xfLoL-FgK9hzS#HFk|E$m0P*pFfYt#f$76a4U0Qx3zz!VoTY4Xo-0Wy{p^Vp>S1;nExCS-jVu2?l97mwl``M z^X$Yd7w?Uj1YaS4xG^r1=-C%M@-~UBNdhpiM7ptNtb|U@^|bqGZiTgb>8DhAST_T5 z19;3z(Jtc>zOT=&c*B*ZQ0{@3EoVQd>cK~gCDOBdAOrY^ndzW{6&xi}-TEdD>TMUV z?on#yLApk4I!;q;Qk^oqCi;ME*FLiKjoj*^qqOt<-yQaEKh|SJ*|*H+c={Rg;_mF~ zzpWXj>-j%54`NIBe&K4W=OeS`x@XG}jwo_0cIk<&LRvOdY<|eFGHR_qO#-7iI3b}x zJt&nQ^!zSr(j-Na3MQ8I?B26irT|utG0x0Xi!+>YLyh3h^F1~@gI~_t)9kv~wXJ)U zYz>N-khnJHB|~X?tO2;DZRc6_)=ZFTC5!SQ z5D+*D72*Bpbm_F)JcjFXEVEm;a(a#oYz-dpRgP?(5rk6BImS9d{_=dw19%|rjZvjh zpH%SeDNVP0WH@qAE|S&m=KmJ*C@B;?Z52tp910w!c^(R z>DGzn=9Z`{ga@umS#$UMqr>7Jhx%~FF0Pyq3-IybOm0<9v|dAvvt9WndjHq-1;AED zCHgx-N1|A(U~Z}Jf;+AuSulcU4x7%^9to48lxc5bvOKTlOqpRwMel_zF?CSa zC>0O*{dsnXwIThs1U|&CETB?8q^Hh8D01g|RE%8C(oE(Wsrv$;4ralSA_+rev&K)) z8Tb14-VS&j|H;LeW8W9dqZ&?Q^OyPpKPx+=0%#o0ts-E6_N+{=-soUZN)9^87lPl8 zZtZB}sG7E98eN(oN7RU61#t1Y;HjR1@{!8&EW;iNMJWMeB7-1~+J5U07opBvj;Nt# zqEoHY_YqBm87AerljWT{Xm-fQfAe<#2kG^{O9&vmSA__x7qi#N71`>IplM>lD1BHV zJM2ssF^xfU-5efliLGW016z6>meP?wt-MeSfAMkrR-;FrOqpL{in?!=&H^Jh;bUNJcSPDV@_Sk~& z>n&TLs^H;(PjpBe;n6J=e&$?COEH7*Bh>EiTezrvc^7!u%$cvNh-w9nK^;)O)BAx3 zRoZ#>?+E>y8g1?3mZ*Di0B_wk&nbUWR(nacuEa-i_;y{LkJ(v_`i>|d7J;3nM|RzG zWpv?Rn=vz*P(a?2Ir@{4!--GkR_R^}*v#&DmMo5ZtMc6Hw`f`*48P3dS!mo0$}2o^ zv&H5nvU%p&XFC1E-M*$X$ko(@9h2XB;B@@-q3?Xv3D>UR!VBa#Yhpt-}qi!`DqE zEt@;ixRU#Y@U{g9UE+M9U()nbj1grduI_Wt>4y7E`t$k)jsFr>I~cy@v6Am{2RU@p zL}p9!f=5=*EmEFo$%<_>WjvqsIoJjo+@E9()o%ABq&TN%BwPe|HwW$jF zrZ4Zl?5Q*Tx$C;_z5a9j$FU)?f9f!$$$uoZCPi#i-=fF3;A#W=C*s5lVpT)~)^VPm zKRC-!q_ecSu?f)IbU<@o3swxR2^lyxdqrWZ-8HR=VXT5LICMYRI-a`%`KTO$Tx;*D zFn$w|$6l5iKu%8XEOkNP>$Pl?*s-Nf!;iO`0fuTS+JvC`zCXDAn>1!yUExILwU3FZ zow&$@GqE0Pl?x5WDGfey7w}%Bp4|^8SF>U*w45){zO|RtcNlA6g?{#{{h-sNx-(hrsTrOXBO`E$jph>RDH;I15 z;V=*Al$SkPuS%%VTmulqBLdDdx$I(L{6_FJ3E?ZY_K#IcI@cdEV-FHUS_TA`JH9i= zVrgRN@0YfwyER)6i+53v?hxwPWO7{xeu9u8OG;mHpGAupS%23&8Q`{yesz8TQ4z8s zf)L{94E(xzl+G;NNtgHkI)C4*wiA}GLe=&1o@t=w;c-6rl*)`oaBvp1lGlmYVO}== zwXy5V?f3<;p8X~XG|5+jvMA8&DJ-giUwzZ3ikjVQc*%wy54@R!e7ijXfJWM#G==HS zcj$2aR!Zu&^gAXy_3TR!8;xdB3jIh?54*9F9Ui}wa`S0+Gc8tPa>28${X&FRB~?!E&TqHbiHW=8+VPbZpCQO zaxsS+av>nGnqii>CbrYhx+!8d{n0Hq0Aw_I+gn!*^iVY;^hzcyPA3(}Ma&Ut7CD}n z6Bvkm`iZ1r1b^t5U^=znbIpg20R1Sk3RS7<`z3dWSyO=PKvnbysw24aP4gkd@%b@C z2!N#j0uCUP+oF|m)01nS2Nn#vYR9vQ-qEk-CAFjXZN zeixeNj4;nC67nI)SWC~@i+Uvj!9TlMAqyQ?RGg$Ih_;MbaZ=eSRc45N@_PlHOe=m} zop)>_+AY;O`5LBWn??v;=@nE#lVMD z<7x1TOo(I_BjofcWW9!^=%e5;@}`cCQ+ADh_O0Z&{M}(! z$FS=#ODBNafTtMpvqRFbX_k_#eUtLnQl0yicY`C;c}dkpz2Zuy=a>P;>&-D;r`Fm{ zjaSmusu)CI=~6g|nZ_(e*BWCn9 zS|1>I3JCCMHgqoP{%m7(R$^vc9G1y^_*3?G$SM{178>7t0TEbj&&NOlqe1-hR#3kS zi74rqCKY7N6BUf5?fxA_Ai{q;T$WNd?2c9iS1i^)q2aTcw6WX~B%&Gnpf^UpUs=(2 zTj2iwq1y+yP{>Wa7A5OZpETxoE;CIG90b8Zj&S{UEtev z*TO|xt5Zk3rL=OBc=Yfs83gr6y5qby>?5JbNV48!y694B4aI7L-`WvDk|dQG_N6ay z;Mu>qksjT@WsU$eqd%I3_=$7#IMh{M!ON59tBRY{iOE38)bcMHtC&Y3=(s}F<+cgK zP>d!|z)t9&KKQuCF11blv2dJG4ygU0n_}0k{6PE$UX4m&`hOEr zLvZ94XGMKXoGT^VJh)@Gl@Ennn>4;_cPfy6R#D<{8YyPz~OAJ(W? z(m8;3#g4nqs~f@d^-rR0QgWq|Xf=xhgH{Q{Qq6!f15jb((W-_gn^S}IflFaoO7U$C z22s-m=dF(}ojoM=GY zG|tsGMBF%C8mb_RLLx#TV>52%a@G3%sywujQt$1XKD%bG-}kr`q82FLT3& zs95*~TCB=`xTkx-G1Q_G55+vEDEoDw>#WU~)fK><1I@+wIeL@|4Gj6tjTk=IKpp2s z>%YU?!H9Mqo8-~{DX{rZ@!xFi<}>NrvHNe)_{_oAn7zCpjb zq}t%CRRQ_Lvi0uomCG_rznW$woM;~zRplN|-dGP}jVsVH!1(8HWX^N-a1LJaz{&6idb_n`+90VxZzxTJ%@l&fLf+j zuE@DSyZk~}@!M&ub+c$+u5LY79saZhF@d{nYh9*mh&NHjl{Obkv{8&9zXys*|L9>82HIk zMgjCPTmgdm#@^Lb=R5lW@KW)Ah|_D@#T(!2#NPIP63+nm#eV*Hn@S)oby9n1E=f_ z28xsSZAZ^>#krb?bEI95no`Gm>9(Eb>`Hv9t8gShn8vj!axKScF!1}9x+`%cSUk6p ztrT3Mp)EXa}Rfy+ zS8B#DUqdF_Y=lpRid77=U>S2Er)`ovskhfooq3meOJ14stbVffmoFEOZ&4K6b(}my z$s0BvEO_*W+6aQHc|_4v=+BB+n)(Kd28|Sp+IV|``i?Th*b4n^UbR2K#SF1;7k(G0 zdO(3%MXv!E<*dIM<<&KU6Xz7EP@M>n+1_UolRL*NvCU|$!@d(H>I7O;eKWem z)*$}zYsk>PmcE}UBpL~gR++)j-0iy6x9XB|PmD!c$&C9RP89kZ@(RlEm{rPjEWeUm zV}2ZL`%vsBXz9#F>##T)$C68SpDJb(kfrXWAJ${){f~{FX|PI1o%9mxc|UEBfOWt)f&3GuZqJ{EyR8R}+6G zTNO#?P}N~v#2+2Sfwy^aa`K515=ZpY+Mp_^^#yNp&}w&GFhKHLzYczS{pj*7>6ED1 zZgn|*-7CT(qLT*t0~LZ+8mQ_WoE zPSI-Qb9W&Heoqp*9&Ei>$SvlISo*PRsMbFy#;+Hk^$%6`e+Sb4^+B}b?#aR5;q{awm`|v#Jz8tvgVSg~@j(2D@UUsZ zr5zFgp4`CA@UDLe@8cKCIkHq*9a{Kx>#+0`vyC2Y3jxBf6Vwf%WsW#>4q3_5aX>&Ne-Q*Et1vi^Nx zg{$oWxE&jo!?MiuJBCv@J{!cZQ+bmY7I&3j#tLNwPklyj|5)ai@O?PPOxk7ItvNw7 zjAvf~QVs#J-eT$4YW}!#9BBMwE6c5U<6MRSS)fcJmirkUND$(Y~5w>4zcRu_{!&Fwy`l5a%?a%LQ)57`m_cLD__7{BWYjrb@8na5mR550_v;yP6N5&|&0U*?P9(D<0(Z z3X1c0hxY`;>lS&ypP(?gIpde4!mbyYoy{|-^0S*{i$_)GrhA%bcy@2RRwq$68e`C} zpoZ6V733gR%cJR!`_VS{T1|5!vEGXsm@QlAzN=^BC1C!iNLo$5#3%}J$?IG;%(JTn z(v)QTNunqt;EH8+dBtyOvF zliSoK3HYDt9~Kp9wK(+0fn%d}ydLc*jRznJipg{8#qeQe7aYD`1wVhuAg7{Jt?#5) zjbFjVg)0bZ_mFF<0EtMAwwwLZWNCe#E8Vr_TXihR_gm;#R=Zt#ca!k~#O~`-fKr4y zRryoqcGm28)6-l|5yy~3nGvBga-c_A6-^MD!?QLkO0lmoP5jO)=nr&+OBM@%3D-we z0dMh^*D#;d0~Iu%g>fi^)$RoKyNy!kD_W-uCsXks3(-R&*Dgis`4+_cP9t5Nu-C z)@EQH_rZw5wU&^zRK&Wps!5(5)1G_=>~om?>-tgf5Uv9H;NuSq>ZWLs z%s*BZ*fltw@g0(yN4Q^yA=4}6K3z@Uqu;aLk6ZZ+sG$6T+b1=8?whULPn`>~AD9?! znTdB&Y5S#U1?xnUiJ^~VAf!(779MWTealDvbiW<2-i+U!F}zGPHz z=gG!S4(hK==}0#`x%;DPq!DMD%exv(RX4END$Bhj)S<7fu%+*@=Vi5T&3?WcqyVjgf)7*Fu=tkH<;#zm|ppbNXCLr~62! zfC|cUtA=~f=10BAbOn-Az1D#9Z7cLku0BreM4+?cw_;!$8iONKi3r`z_pEX}TbRVB zI%p!_SuUSek?A%h$1C3gIgpyvOBHT^N!$TLP~O_&yHb^#$KEB{z?hH|3prj)Wsjca z9`<--dl7hP>S4#AddGuKRcBN1)$$j4!7&}XXoqi@w*ykZE}Y2CHjC3rvv1F}(pXKrdu zy&0?I9c0cwbRR#t^He3?{%4%@igWERGc=G6oZw9j@M|3JO8K@_scwtF?yLXUh$G8Y z8x*)p**48-Io)bL`NsawasM}u#@65Rh|6%Lt%T;aF>{W93ZUVM6++Ei(E(0kg&)ME zl8Uk!-(p`7pyohwPuELR8jy>eRca+4gz9{hgB#!sn~>oss>YA_yl3T*PN!*|vwgUg zjvG2wE@!PhN{#ZJ3pv8Tcg;aWGe(&A#P3aj<}m3Vjk!Bv3j&V_bHhIcLOwmk zK!jKor8?X3A6%P*W^d~Bfj0zT<7j!QLyrn!yT@#=SMS&j*=)YKt*@~0Ruo`m)4Z>P zS{r5sW1ibQhwaDk2-XfB$R%lDGbcSo|-Jl&5W9qXpSS(Bis$ zZQq1_edqCB-W0-dZFUq@dtTc3S7{G;3i|AWca}qKmk6H8FY9@#3>7 zJBb%(!%fWXf&9`fC7FIjG8UeU6o^g?&dq58lm54Rh>B%IIw<8c#0{M`XI~_ zy(miHu+ro?3cJ}Dbz~PV9{LBG$%c*fEsPv-W1MHf`q+o$g@6Ecf#XBv>WGox{q%g4 zEg{Rfuwz6$Ibhk1;cvY5!3~807tBwcM+il7Lq%YmhJTW0j4#c?l?50U{ISzb2w?*Z z?}?TwoX`>Z`F&^1(U>P}jo@o7XN~y*zE&SyJ^RQ+qXz^q_3S8!%#eW=lmWPv8{=V^ z5~zLOJ?Hf<7?2cu-bX4^U1Fg)o9v}300A3N|EPTHxZ2)cN_;(9)yP--${^@MgAl1) z`JR2%Qd#}M=Lhl7byZG&uR|$^wY&)4Iu0GXuGQX2-MNJ=a`z3Lxf5ovOqY2JcRuNG z-(yMK`rX1wie?&ABhgUEr}{B`o8krh{3*`d!}nV&!09Q7iq(|+0$Pvs6wNmEZ(5Id zwQ7cm^huyGWt1p8&I9n==+fj9V277CG_KW!dT?}pH*R2t?(z|F1M*Fx9~@^!iF$LK z*5be42-J6g7k_bid3jec)8K4)$C8FDK_%{5VWxrP5qV2u7E}SgAv91$ZIJ~W%-J0{ z)fHJjD%E2Ro6^Ksi7`FQM6v50W?FbfQZqn+=2?=$ECCs$ufQqhMZ*zbKS}YDXnsi} zmI;^(@*n1ssC!OcR&)KT??fxY*WSTBChyE`GcN#L)v}V|vTUXwcJ~iNyteVcr(y4dx__Bu$6RYzDI`IGWw1Q3|OuutR-cllA} zwNY|k8sJHEyOq3V!sWr0HhZuk%^se{evDu)V4Q4+)VSQzq0Ida?7aavRV-bsMz z7Kr4+F%?I}#ABg_!l*n*;=FRD)5@mMuXF!(oG_Q7O$_DdfsN^%7Zjz988`8owHP<4 zWH${z4KZ?z`h5>Vhcp33teoEflnKWwg4!=S$3z}5*!v%`2UOs$wj<-~-;?zW@cS$; zKPO|n7|yx2G>u>R0Ix0x-PzBzs`9@daOpCYN6)Xn}gwaxsq6z2>Zbxax0iU%~=2z!Cz- zl_M01U=*sy+Aax_lt~BhCpW-Jlln9ue1rJ=oWpcy$)0Ls=^ogtHmjs-6u$Ypy+vYM zcP@|F@hq7->i0h&9VQ`!IwpEl2kkv{G$VWyM!zom{G*QezxIv)aHRiT!2kapoJxVx zFP73BtzRA95u)r3ZnsKKf;aZawXl!_(PIq9bVl@HbGtb(-px`0s&uZFb#Di<{G26cm83iJZpwz?Q)A3xeoT7B&_?>QQv88B$TysFRh^VmJ znF_f}2b7KMO##}F6(+Ae+XL7>Nh5Qu$Ne6a6smMW-Gck~p43W8LBZ^hBE5u=YIi5i z>m0G2pIS&#w0hT7o0RQFV3g3Bqrj{UALj)NoWE8m6K7;9zAR{H{=v1aJch|D$zzXA z!WIq;JNr1x(;#S&O5DTETj=UESh{11@U@M$^ z_JsLl%kbp;Vbm#ynxVOpmETjWX>-ZC-!kz(#rAdFgJ@ROZBI^})>`Kqj&9#sUVUa3~SV!8B!#3M=A{^cbM`f`x{7S0pjnzPGyvI*|X*qmpW)=crd25|5lEZ>N|QCm$zVBgR;6dA@iBmEL@H#J@0Cs zwSgEGlAGjfZDeKV;99f`yAxOnW2U6_F{;4#P7}?So5W zEE@RvuRCJ(4noF>vud87Zm(E3dcGGHIV@Sx7~PK^VUN1b(eJi?Tc_Xv_ehD@WeXa@ z{WDcvA^3&p1ze*bgZLBnw;#hi{qvUZWqSh-f4OqkZHKvC6JXcy6n_5zvU)T|k(#Bo zrxZ5mqm$xJtTn#$p}0T)su!vv<{VFlSX}gF;@ug{#<+TZi1+->ck&rUUOJktfQg+T zdeRSTxbMej_zIL;aY1*P0oC;~-3HHDer#p8xYa=otIY!7qX9OktTYgMyvQ{dp*brk z?tj5A30hae2K}Na!E`;&t&0GI%86#Rec(SkYpp~?!{&8_I9w9I8$T{3e(nRP)%3?7P5|Hs)cLGQhOCz1U>? zWSP(9jK^Nxv)|rpaza-_cYDW?D|OHKy(|Cb|J|DeT<Ry zbuL?n}I|UeUPiC6@iq!bEB{InPBWIcGBL1XVe{W2A@H{xyb;*aA z{*4=!2YfvF`pMo}>D{b}hcZ>H6=z;m`*Get%=e(c^T5O)gUFD+bBF!T{95L41^+z+G*9VN*}c8-q1r{X;rq8<;LKXY6CDfA zd7?_(#|7Qa+i2Odl}S zn;g+G|2k;)!0}++@t_7zr;nVM1_cjAzor^)>sXFO;}~oG-wl16S(0M(XW#A+{ruu>SFgtV8J!oDuNWJ)tD7mL)`DlH z8Z zHi(iek?dLP`+LRivvu&Sa2QJCEp?MKBx&aR^lu0eFrV+0G`>>1_K~zDURrq4#tvf( z;-Jm6tTl&12RMC;^C7Y=%Tl7Oaj~_6e#30&iI9W6@q@kI^LzVx6H5>!126U3hq(CN z;2B^i^+V?xjy9PHEb&V*y_+aasTn$WHo9wF(DLX}K&)oF*wIOZ&4i%BXX>9#da6y#B%Q z-S-O@ZLW*L`(}T`i?6zW#$saO>Oy=-5nGw+n^33r;Nvo>aS3wcViWf9S9E;(k1G#{ z?kqNhW~binyKpSH;|e-ZzwthafJ}>-`Wjnha8kb8f8A1FS^-D5feO%tj=jq>`szKn z&|s=sJ6)MD?5DSU0i063<`P0OATobfNZVT-w2%Im9sk3tz0Zh^}CiOBKV@qsc$KerRVe*{T z?uqH-&W{Qo(yFy$zDPu05~^)pyCRkN7hSo=0@@$s@$a*peG5v|`cb_p6f!fFhtr3D z_8Vp#bzPBr5~6P^vQzm(X!|2IL)0{p7B7nVnvNsGX>+BhuGtHMGMuJ02dBM6Q1_+g zHwH>lIel;#55jD0?LbK0Wr5ZKHN66R_NbhTs}B1O68}w?CO(k0*wwP(NWxL2gKVW! zO!1@;fl*i*GGyzs7t-G-A_}nEwc4!YyJE)Bhb_^W52Wt1(oj)^$fmXc9NMrXPNxSXV<=N-zFVo$_KaRzS@4SQqdmfkmg<#Z^x^GA6KZd_}) z=HhG3C*DzSO!ly|@4U&gp8xkjc0Y9H6hwbNDhJHmGW;4{5Ha3uTwcQ?M}$utC+Zr6&qUTAiPvyuWUnr7sjf` z%4c_^+B2M1zSj0<;#+M}yyHzsuLp*=T~|a&YS-P@|6;V&BWHaqvQM%9;v6+Ll)Vm8 zxNgO(FdR}*jjh&7RE6zJ`ki4~#j*V=>Qh|YU(!1Ke4By)OpdKxW(D5EJ!FJHqK$&e z-L4bu`ZA~wiN01u+}?8Lk+`PX$+1-^;W?L`)AGnaa^ZHUD z$F50|O(|2ZZB;vmgtiF?)kM!8v3T}{Hn(`_omDkE{c{w;yZ=n1CBh_~d(C=@ko1xG&8UYAS=$$p8euU$+&9DlJ^>DsJ^o*M;D^d+_1K;upg*E+?QgNgDWZq#T4r)o1JRV~Yf7E6VN z$!;MtM7u(-Cg!?#NuM$1f}RLvu$G5rv+3pDg>H<6ubWkoU8qMv$g`eQ7*-`}D zsB!^ndWt`dGaSl?ozfNNe7mG2u)E;->wTebLRVEFY~l|NN(k8${(M@LYg*fi7plju zNzzdJmfc_3w04Q0*nA{wiNJ?m9=IH;ST?QhO?Er+_d=WOp+v!uwWWi?6TIU`7tZ)6 z+l{{bVTG3Fg?#@gBxnlDJrT9n*dGOrs}7U>>vLTmt;MXUA1N4FZLfS|r|~Msci6Pf z$`4I2sX)xc^+zfE+jaBFn5Q5_*))^`4)PHoTGO^zD&+ry8a2YCgT*aWTEf;D=x#F#)AIVOd8`ge>{Gnk&z9bVizuanx zKX(=g+y!DMVeLkI$YA&bBaZ44F(`-!xqTfDqtNix+WH$%^VLh^P@Sr`e5B%ue)fxa z__t_T=9VRTRX1G-Rh#(l;-d8ms!c$qfn-wT_&Mzdhi!oPOXuconTK~nW-Qu}Xmr)3 z?slx>J_Do#qfs`{szhx<(brvEWF)P{@|Q0##lAZ%u(R|~nTyIRa^4Vrq@2hd6gtm_ z{I~_>lY`q;DXadMGdK{luiG&UDK>s8)>9^9P#E?Pa3tc;wZmRUqnvKZUdo`O-5K$x z6yPTZoFw!yoWJ}*bV~?*t*S7}4GowA{KdTbhef`V*2Ax7Z6~s?7zQciF0Q@4dU&Uz zyVuxII2dDg+K2Wi!lLE0BxE6w{|RU7<(6RRxJ@l*2}o>UL`;(0RUfG~&#LH1YEtqK zyM~yuHhi$&Z&lC&*}7+c8LI5Smg0*8yuw1p0Z^bPg}HNxRpEqoxyRog(aTid-AV!IH(KiGhh0qM~T z5dJP!r@?C04N^;*^>%1P1Xvlb;A)sBeIfpvRFjMN%0c1CMg zO}gk;zd)Yk8Fo7yylF_Q1eWNG*Gd%5?y00!0SoN325qS2>g_dN2JLU6%(um&9qT9g z>#D_<&g^z;q7<4_P?aI;S+q_o&`C(R+9MZnmjdmQBY5}M<6<2x{Q9!wZOhA3Lx+_F zyCc+cjc)fr!(7!$K|kU@2N6Q(>LnoolXt1oBYK^%q$s8lW~dU<6@fMeM~aDYB@THj za94<0S15J5c(MPSe{n(oM{ytz{DG+J-HnaLzXQT+&7KpDS)(+E%;PC!X7AWxE;xhBHz#3JfK_47?5QL`uS0l%E#|j zry?$ZudclJWZCxF4qn_z<6v9bB?2EUf`Zk-G<&9s45agZhg>n#uEN95VVKks!OY0> zPSe>glw$yx+_8)%Q3au=+KQ!6SAP6ytqKX#*h?fqjTlK5hN_8$71NA=WdXgdSd_P3 z*InbuQIi+nm!c~1;^_b0dE#!P%FMHu;O=s{E*&DGrubiRV8Oz^_WBn&rT%^rr zd7IIe4hgxv_`0IiU4*NpZsgFc#vh(_d7j%b93#!bzhUX~j5W5Mp?;!m_;rxpmiVQW32T?Bhc`nOE)mWH$DFsc+4l6BwTxpzZw#h$ zUiZKw)6lWmqvFk7 zS-!;k?tu8~Vfby>xr3f6pv-w}q7U7=T%E(|(L8`e&oo4kRxh-G-xUi!ms;GWzbzRT zo*&sR*s>K2_YRw72P&hbWA>ePgT{V?_CNfa`e?O_ozl>W#S%xV*95+-0)@6z!hMO0 z!x1$X!HlhGQE=aUQeg30ZO2vJ(Q#;Pd+qCIocV$GP3Eqf?(2o~zVL6-w{h-@p8v!s zhCeh})ds4biQhLKzdZ593orUx@RSFk$ldLIBZWPDnoOj2mb{86-xs06pU1?+s*tSy ztj+>TTu7dKk9BbHQ#*s;nmee1u;&-i*ZO}wPR;}0;$1%ykwndZ6v7XO6YHOfE#C}W zFL!cW4Wfl!--R|?WDO9^(94&5G|{WtXLgF+o3H*Ie*xG#vaue6Z73i{{rH@WCz#CK z$I>2}wV2ppp1mwHnGskJkM9p!|M;*JZm!p5eQZDTPKU=6MOft zDh)a7WWMbx(ZmRPRaqw#9hotFN27V$AhE5h@yAK)Dhnt=%Nyj*PVh;kRZ~=1@{dCX zf~FHKBvi+YP8ha$K0+vvCIO<1@#T0z>VEBd*gV*!_=pV`KEB{u>-q;REB4-*QRB8F znTV>ltqDqEq?G;aR~y;YrV+sys{U`+V7GnEA;voUwoa;7D=sp5H>ak9xuyYzKwqV==DptfW&qO$!2VfoR$_yxT%0FvZMMK4}XGPV7>b-)M;= z9TaSv9!%4gFsZ7&zv!2v{YUMhZP^k4uh)xhv^1sHcH}{PD=c|mg+|Hxv$&3{$y%Dh zn|!z~MUP%TED=LcwM>XiBE&UcTN16qGunS2i1&-HensyZK3}Ok3^?h{8dc>Uqf@X= zWy{Zrit8FhTGlK6)Cr}LWLM0O$Nl*O`@~w^*XTa$)-3CmQxhuV(Efp6xZ}PI#GyJQ ze{tKPQMd%iuRp>ZzBZWX1U)w29h6#_(<=%9JYn~0rLfMomkpz+*KX{b?x4aAvY~%C4V7R9 z*C%~0*6E+#SSWvR7a&23?9Rmr=q1296?f72uRlEk?CDY2XL}mg%*Ibwh?`(uod(dQ zWtv$IA4s1iIgIVgeRq$tWkCNBt>HOo;I35hrqJ)s6M*_K0;Tjit7*XnE$^|`coym> z=6cbUt33k^5uVhyn|PepZk1x$d8Y3%TI|%Fz_o8C<^hOp6Z>1x=8NBkjy9bjmQFBt z-+TeA!u|)_0mPn=xBYsXw^9fnR2DR<_J|*DkLLhxyn821F4V5|`^Fm(2?-LngRvQ2Rs?bKyh zK?ENS-UfWm&U|qzx=sM?X}*d;DD0 z*6XwoC+BMP*Lz%a*U8w_7TfpZR#~Bd2ScC3!Z>XW3c_GlLrEZyp(KA%3sxfe4qN}n zOPyc)r*lov>j@$rH?Y+^(|2^?r%D@|q^Kmxs9irNfpP{w4mu2>usOi_HPvXM%%Ww% z#Jz54gEtsg;!X(#5Go|BW3)JCUj)P(u9xSta$IKOb@H_2CFlAfe@PP7Toi%~R(Dth z?6YzhI;&$jAJC;q2)O}WHw!s5#;LdHC_YZ?OCnQ)EdMuE{SU(B|M^Kfa)dr3XpL#T zdpA9Fas5fl$i&gmn5FR$K~K>#w)^K&8wK+2bxo1v9u8L0{TTh0hc}{*FO>>Te?3b> z$g?Y96Q!8n4{^WTsq9aSjWFKqs<*Yj-!4CLb{HO}SEs!@YF_E7AI-@@T;bT!xJ>R2 zNt9$C_e8KK%baT9jc4eCCXx${mp>LB#bO4p>S+D(nm9L|{IfRlE>%^i^#}{;F;?f= z9_1-=f7HlFL0f_Rg8n`+!B1BS=}5 zI<^WB*mvj2FiI;@IW72;mx7kJUMgnNKnB!2oZy@-u6<^@Q2^I?2xsqd%xf%tKS(OE zSNm12D5Z8j;G$pI>Y{5b{Kuh2ZSM#TP3MEMYh!h>;a(bJ#)6SH2Kr{|$*eZ+fvRgx zQ;q(?@u$){xfp9N6?$X`qorKdHPU|ab~xK7`knbmwQzF@s5OS#8pm}c_`tST|9DZH z7m0bK%aZRbNs#N({v%}iVTDVWzlAIk++lAo5~)U?Fwb*&rO1f&oOROOi|=_ju@JcT z{93m1QaD$OWSrxj*8%{Oi$7$(jV%a-&b%c0?OPKh(3>3}G`mc+5+g!HxlxA`t##+d zzuW>iH|<~5=PmT6Avk0=80`3}-_zzaWd9W{Z0kIurOR>en#(S>g)7k@zhdA-%v*Lq zQs1yb31mIzNi{oZ~c6Xi40wV&&x+a<0JT80P)A@`3-<4H!Gah-X;ujm6o1{L@ z?#&#p>;|e*_0A$$UVi&Fw*sZVEQ=35xjHvTQX@~3p@l{Lkq;l)&wsFyg`{XGJHY%m z9%J$MgskAo(#3Eq=QCc~>Btoo4y7vP8gppogI2dTGg-d!_5xK{^#1mR+>z$rU`-WI zrZkRuqIp>z^(9&rZ{B%B@_Zpq5vwXzBDX8Wv4^{5Cp~wRRmX@z0;VO+Bkz}j~n|$LqZ|(9YJa;7R)-wJu zkLn>EAHCz0)u%@{pw0|udxN^+Pm_X|S~69-A_#xo{L**nk=;mPeTxQw5@qgjezHn2 z-wvNSm1#_$u8eV)SWVV?mlPB;CjrT(hC7a6GoR1HIU_tRIA)KF^0|oKN?1um zh@e!Et_7ysebG@_sws-`dtdV;r_|5zbJ$LB>$6p9*f<{TvGotyhzAuyLV;&bb_f%L zL1USxsLMSS8LIr*sAFAtMpW`!+dgrqD(Vp!hOw32&WwAlXg&D5>Pd-dckGJcVv_?ezr=BKP|bGZNZY63Mutiz&8CvSytL^58^fh8R0PD~`q&DaoA z*EH^n3h0?sk7wScx>sEKPw~u4l=PBEt2aHM)&|;m%9y(r=aDjc{^;&?gSyXD1wXI* z;6}#y$(ZnRNb32bO0?k3yJ|6>I(s%rJVj35f(=BW(>4->Mt>Yel76~OqskmwD}hv!kLx&b>Zu-D z9ySjB4IC6I(gJ0Solox zd%1(CM#8R_O2=Syh%v9yJs%4F-l}cJs4)^Uc zxq~8lKL)h8z-CPmZWzAvE=cseL*S3d*pX2P@P|4X8@L$xt!qt$<{ zdyb_)r8-@i-I#Z``~8q_Z|O7AL*LOi7xAH+%*AJ;GaA4-lYa^ud-ePGNwWvP&bOhg zr)9aMCmyl!6 z^sNVs2^bw_XMaA%WGK$1{=5P9hXD!1NWoS<<#Nrv2(v73w=0B62Gux?DwKh_RqgZkq#Vjd0>W6QNTneDm7||Gth+#B4o66l|x_;A}Gbj{D{Q$<2~5 zcXk>Bm%k`^rAbt^L```t+RnQB;p<$x_x~~<6*hM9;rB1tSccK1@9WnE4Wv4|^x4y_ zhIawnMu(a0S%f#ZdIW98}GSDHhC6)9l2sw=v zf6;3JuZF6%x&1J`ZxNW{pQ}4A`5{jXrpKoAABe^*Wnt&nk4uq!W(c3{aZ|7#WT zZ{F`8Qu#z0bveoD$I-y7P(YO3f11n_n%ptzcyr~L>HZVp#kJLeIo+_9{O7c#*6c0o zJN;@`#-Y05TWk;B2+ut8Yl3{8&qHZ+t%C9}2ilmc-G>cE&I1&X_*(_H3TyO?O(#J!joj{f2@*DwY9Dt! z4q*!waOvA!EPNJ!rKTz@$(x%AQi8ZVP1qQ`UD>COwvks|Q8;F310|!Rcxb;L*@}9{ zpt>;iNwaMiGMMwwV|WBH;c1Nfw6{GYz-5j?Z9Mc3h39Yk0Rlqf-E~baS{f?~=T`rr zx-r;~Ka2L)y5BtHA3|(H_`ihMQJSSBPe)E(cU6PO+4h8=xMI?Y>B z0M)ns?rgBuH=uYxqR+9P{+l8B71gdPL;OV+r1jc!j_!~6r%&E`@X^1^H~NIhkB`)D z9PZ24fGCLCS}(FQ%~ql%yX8KKRZqA1lW}jKuGdoy-N^30B(f{xwQ2GNZtk|NttShy)+!6Lv;UcNkw&l0&6A9Y) zbQDc0ayA_If24=<9roR`cG}Sd^T}0b8h0C0Za^?Pq_DH?!ep#e$Vj?td|{voj+yLP zl3)pmr|nrg$H7f=4-_c6DShka^72`F43>EG5l3NfT~_Us8lzEu&&_3Ggti*ToC^@8 zwJ3$8*d_}d;tYCUL475W4kdY?9y>j9Biahg@88`u0T=qQ`p0h8&nyZ(I_g_= zzj0=mxfU*e&pn`ZSaNCO-T82}mDgR(=1ndqxXO|}*0_H1i%h1u zXkDVKx{+4q1};F4GvjsIcV^@DXLer#XmjLxc!H}>{}HUCo~Xj>8SO(_q4JN-6-cUo z(Ebv@UE`l6ZpZGgiMJ$*EOgurS?nMjuJ+B@_HmP(I2a7B#8BW219HihW`juQ!s5{G zn{ohsX9K$c(0?IOTc-{VhqRv8@4AJ)=G2m#$KiO8b6_gDwf^0D%d5mt7gs?VW_5V7 zbAlgA1}9aeDaQs;;5A}Slo@o@r`g8O?{4wWiS?A{7-7o1<+nXVdbQ&da*$eQrxPso zakDp!*Ip*x(k5ur9 zSs&b{?2m`+;HtFqsw>-(Xjf{DAWS;-UJH_bIzxP`<3f_ReATdaWv72geu6iQqBd-= zBRLYaLS6&pcTy}h5EfCyLjF1IHTn~sQY&4TDTmvybNO@}p$;LFo1Ahy;M~tAXRxer%W~cw{*FY8T9rt1ROX!oz-GDC-yvZgnvp(D1 zd`26&b+hWj;+pud0wmN$+QT;LwisjcX@3-3Yf6lNSq=7=rC$owq}M9hLaJ(!J9MJy+76A zFYYYK>^3CbqwHx4&k|I$4>Exd6uFdQrZ>!Rox}=hgxiKe6RJ;db$qK73!h)w{V9mK zMe!8gvv;9i6aiw15#oZ47JsBWA{#lVIVxV7GQDm|IpA(Q1DG((vVqFksalIK2SIt& zGJ9VS|GFduFIMEPl^K)?ZIvCw$_Bp<#7!l57^Y;ltojIwWLQ!-dyU9U2HyvIAZ{!= z@F>=m0xwcf)+S6<^xZ;BiUx1EB9~roXrc&ue-}l=ry>3vL`@>rZg!(G=mbzr@;n`F z&co1D?o{9Ovwpg){pq>zYVzV|RI>#%(^Z&#zNY}!uJI?d&>_`;{(f9Wz3016OzfTI zTF|h^fLFZcp}o3wa78`;Drd;e%};sA(d|g1AZuD|djw~Xytb3toZ_GYuj96Q!6Uwo z@AYPMw}s#6Rv-;KhV#l$F+7U)^Rn*8c0=8KeH{I9{9YoER1{?SlQ+z1dh*Gx-%|PN z%9En2mDgekH%Ds^F3K|jW%nma_hXEdKj!zmj?9EmMS$=z-kfn2HnnG2_*+0@pAIOh z^QVIYjT6y_Kcu0kIKv#~6eo63bQ>D>6PsN(cuRWe%|~xYO12r#A}!oA6;+_+Zns-E z&EsI_x^NRdyw*#-Au<1UmK9TaBxdnEkLMeFg);LEN8k0mu}mDbTd_v_STAbwdYi~l zb}9~l;7$L-Kta$iM0~Js7rrb4cAdvI;2TvQP_pcP(~oHR>mn($fBsWYW10rg45pB1 zocciIet`wXia%>{K@R3a>o$<7h1casd<}@l6y_lbaM^7S7tLnRjFFf>tGI?acH^O~qtjlT`K?2DdBG;*VvytvZiorrZ_u-3nkq({_`csT#Li_7$$#X{c( zZ_4hIDNrZAblWzAS$@yRTt5Okr8j!t184;x2d6YvAXBtzldpv;o7PRHzZ9eoca22& z+=*k0Vc>8a?8uIsgo_MwBG`0&^0vf$FMjEbFZvP4d$>c-bJ{)+Q&DPhurN(r+h~>I z2)BI5vXAR5EYCyw#IJG@X1A9urCcUU+@;FbPXJ^~s!CmHKj#g*ToD)3#D2XvExBpd zM(me-16zCYy~%fU$@+Ylq`lp?7?(b~_hG0BPyj=J>T+ptC8vt!G_6Zs%{$_sl%)*9FB+u7s9DQ(1YEDqvH`l?|naQSGQG`(QTVV6Fd9-@}tDNi%T880MBM28LQwSxo`%N zOX4D)NNp%%vOChaR_Vs{&gv#{oVT8aU_P|o4pF1pxG_cNrW8U0hbX%csaDZZWzbd^c z;@pRIVnieg`n!$Zx|vsykb6LAM^Qp5?$mO&F~st7em;)q3&h^-)t71px`Z=PW~N0h z=FiQ#q;$Y_%P@^Lx5MCDOim376PCWh%1*8KTs>(|;hA9#0OzqR%xH$f1%D%++d9G; zppVAN<{4*P99jD9&W>$RFAy(k|9=2ifFle&JneY%d<#I3?90USgi5}ibiA_CrMTZ{ zXLQh)E9l*s_oAFk@Jnk}G7W?cN4S(oKMG|&%XzKuvYLg5m{CIK`8MZy#I5zad@JxT z-1f6mxomzS#_j;IK)6RH(?@vTZ~sVPCkJGag3{qxjI!xSUc(>pQ<+PhZ@tBK&0eYh z4B**keDWjmnxqMl`!enW+=VAvMq2jzNJm%2hqxrqikpPrz&GwUB^_rAAVg6LZ=;wc zLWpayQz*k0|6O0NsZmfKRBq6ktQAI| znC5SOQ~PxrFL+5v8}`j!ToLFPUM@9K8_TiTE_Sal{7>@kmpz|SeLSrj@bTgdp9SXGZx&=qobx}AaggoY9tSw zH_u$JbTwMBX}KDY26S5W^6xbC`U}jn0YlxX^Q)Dfjh~|tM z-Jc4tPB^uxwQ&_8Lh898t?<4O(mHipQeaohg$?4Km1qsps&RZtBNGA-x!f9jFP1dr z@Z|0|6gKY4k1_x`acI>gKj=cAGhK12g>Pa8v~J#@E95fcxfbkSDzM@M9A?|-BP;76 z-&@tu#B`|TYVGceU*)N6a0DffjT?jZ@B9nODnj%)_k6rI0J3JQexR+vD5R0_3gh{+ z54KX<-Zt*nFac{(`X=j<$3F4g?>+#0gG7R+B*4|@ z4B8Mh91(g{&7B#cl#R&t4$tly_NhB$hQ{CW3UK=qz!vhu^V@5-52`kmK)W8+$=U)s zdrD`5J}L~)HRP;*exgE^u2zb=Z4bGkZ&?+xw$owvtgb(bYxA26J|Vm%xC2w>3H92Z z7)QW5Yo&$xhnu8+_1M%QmpYSTs6pO;SD1kh(eHDv)aKo#`ozt(b-CWZ(&(?FGz|2( z@iOlpT?uk4i3p7UAiI4MV1uAZQ!y>dPNflAzjH}*(nq4Jph;>~Uu@W*g~mT-R{^%J zvu8>!h4>BiGI|fv*$^2rd{R_rTtS7rRC@yoyD7+vvM2!QLBcUs@1am;Ykf!(xnD9O zG^cV)66hvU3zz*pXB_sZlXj=YOc3Ocx?BdePg%Jx-On7Bg^<%p&%Fh!HgBqKDv3=g z!N!Hjr`p__6rtovaKg~sT1BRd#PFi6b0q@c#~AUwelIJCal_3L zSBxiz?oy0X*3991TUo_t_jH#tMHS+5r{}Qo%nG^jljJxg(3L384-C3Ye~!I-Ks?7R z_)jwEmx?tSC)-fA|NYUZMNc^}r*Pj}`)g#Kko9oQtp7O|?TzO^a|)^|aN#EaM`QuP zP!BIDn1p0Qqy0m>@-yl#D()kbR|)=Crv~Xs8H^)J8NUV)pdB4pyh<9l>Y2t`_%~~Q zWx92kWv zzaaMH55N0UN@=7+WT)^b%msnau0Yr7db9ew2m#C%eezmI+1b5!(S;Q&WB~XO9R9&v zmxzL;5{ZbAD5=Ix?C8bGJF9BE3=`&gUW zp){cgohPM$qTLu=HmaXznx~a|l|s-<*w`uZ1%)KGIoj#H5|M_n|2-DwIao*ui&_anvdwSf=6` zL-`ckUX5T!w~ue?}(mW7nR2<|1&iv!k{j|3)@OUlSZnf*7vUIGLb+ zFRn6KlpA#0dF~|y?)f?Hkasnu=R9`%x;!-UZwjmf^EU-HqXW*X7q`qVt=+R&NhRJG zF7ziOM|o=?OJsX1X!DlhAA&yCF@;Ia(CceP$Rc&=HZK#Ue_w|tQ zKIB5sU1|G29GG5L`2TQViYTrQD|`Ax7E<-B>QxCr4K~mAy38N=0KoQ$F<^W}xbq0% zkaw=$X!a`)dWyV@tD#gu3l?*`6+x_s42hf7%1`J&A0)NSsYgGyEt=y=n_zTpj_e5z zY=NX)o(3xdbOC3Zv1@yE5c1Crih(fJNJ}q5TfEn~osiv`UH*FgqlSwXVdggC8eN!~ z9KpH7XWx5xTU~#-JM{dh@nk;;$A6@j!U&05$uw5gi=(#+l9Jt0(o^#aeD|$Ol(qY zO{!L^`AZ{`pQd2uQOPBEQLH^5U9KT%UHJj5WRQ+v7(SkBk@3-(aQz> zfqRX`!RN5`G6K^>m8Kp0P#A8SV~;kj!C@;g(m4BrFK0uy zo|<-SFE)%Hk_gd0x);wD#3-L@qicabQUg<(3Nusd^U^Ny z?Do@1%z%U;_xe1JYg>ez#8&7h}N>_x@%jZt%J?Ve=Ll|JssecE|a_VyFMSXS3 zPi!fCc>9%a`pSa;j}a9GwYnfF2f~d1==30R3jyrrey%~vD~04bi`y_b_%Yc33WW)+ zZVvw{0-p00_HiXx80g~|N&+kf#iu+Ew>RXk@GBbJJ}2z*PK9RHV6gd4as7BrpeW{U zTZ|pQuWN536h$2tD^Y!=xm&N@@{`-ISp!(4t$d!Y=|crXaH}i!M-n&3rZ|vM;`+t& zG81GOA9>1Tn5SU5E1QI0%1i2o*RBo_l@)l^&E(H60xuFy&9fYj&rU*imanMT)Zg_2 zw+C{oy&k@45P$0AYUFB80>G-ur^|^Hen$G>WW!x&l{4ikJ!NFN#CqE=eD6+MnZsUm zAXG6VyEr~1od7r0p)_ z?gwB;jVcM)8@R^)2fezZ-yJf`sa2}-=^eLqA=#ZDn6i=k1_kaq0$)oKe12&1vW7*4 zn00r!-g@ueb2$Nt3qi>$J^K}PZN>6&Mjk^4ym8#*c3F<#P1od@INo>k^=}6!x&a-A zoYjQzr6oBvaaIj)b=+Ra?rL|dR{7;`H#3IaI9qufuVq`a?*emhH4`Q?fvnAvBjK*e z3qOx=*3DVp$QN@%R)~giw&h}I2XDOg*ss0+xP497(-9^=c_CQZv)HMG2Ob=nTV8oqY=)v zxICAnw^HsJCahg-SKtO)A_lpq!i)&WI< zTdK$4ngs>*+5y)bE7p~a6bSVe4BpL&^mO^+Efw%P0jO{I>ND!h?&+;(Cpj!aJN3GX z6WX0?^Xpa$$0HbCk1*UAr`N}pOZ0IL;{X|0<>Z7`ZybhyikI{pRZNQ%lY}vi+=x3v zhoCIa&f-9WP%lP0^)Ieblwky}L@-epR}jXjUA&F0j`fyNIn!B`gY5QX#S;Vs=-N_j z9l(R-Ka|AJL{4?f5@;_X98Y-a#$9%PReV$e|6FBH(8@tVLWkKme_R8$7l4_Mc1tmG zAETtlw3nQ5obKQGQ3KfNZ#meFH-nSjLvJFpqJBcibAQCnI%>qkJ$y;3_n zAO1cWhnFZY)A!dfsqA~s45A1w&+aBU!&|V67dIU-YES;+4bU3^&4D9sd(89O4=EG_ zToP?1d*=;cDzmzL1GexBTl1Y<$ z>T*yUDs9OmODio{lY%3aV(UWZrYq{D^4O!mG!@XUZJ2UBj2(g z%|k2icvnPDe`^O&hH$Q>*i0&`Nz=}_E%nRw!+IV8f$M-P110dk_0Ud{<>c&_$)&3w zsWy$}bybqzBixWqqZCf36I+u+KN`6mlj$Tp(01O8)(Vxh`+oInfL&Y;vh$5pnme}b z1+t?0tLFcq+1$+8v$rQ_wkv?aK-cOTUR#3&6Rkr~@H7ftlrTRM`m)t6IedTQ;D|C? zgQk0%{j1xR{6*w)gjt}1W}Ipy9#efC1ba#E(2VOB^Rk_hqo|HG7~T1K0%+fklE(_^ z{q`WyMA}x8wYGDJgSE!Keih()R*!r^X~I8>B_f2r+8%C zA6j*>ObEXtPO0o3knFUUd;G>pKv=St23}BrS^~08OmhJWAPn zBAWb+`n`R=6G#D;B=m@5<;rvtVfFTpfjQ`7ytZ_3O%g4Fl&!%uwL8%HH7Bka=Q0{a zv4P~7F{W&c86E?}Mr{b`ne!_-(Y3CU3}EIL!JaX1s{2d=I1&6wTLdIBfiosVUKfQa zkY22R;Z&{FiZp@g^k_lkJ7+Q^Df2J*uNWtr$%iXs5`vH4z4aJM!v9!QlZ(sHYgBlK zk4ds*41B61oTym2iV#BSS=5>7#r9F(T1Hd{g&`TR6t2*`Z)?$OwSn37w#Jp(KQ4f+ z*xYo9$QNacR}nkx!bXArZM`%y_5Na%XG35k_&qYR+$mw&KmA{X&P|tF8JeL>FXR9? zsjdP8cO!Rpcl!;01aK^LOn^v_!R>CLFru5w{%KIfA`dXo$~b<@v(D>aV&rU)*M*Wb>SN7q$xhoW>0lzQ1*|io6O-C#4FhASKk`ah&k|+*^ z<5F>6995J2u&#*rwVd5kK=&1nZ?9QA{%D_tt}3mXTdHd;7HAO7gmgsxeuKltKJIn6 z6m~%}td+>6b<||TlX(j-FyPd8I_vl}`crAm0;PS5;#I)Q3qpXRktyG`$cL0pdcnYs z3*sf@H^UtOYZsQ|$uy>{FnV=|wRD=t22R*0ke5=XJVMf>j)5(eEQ>6CR#%()foV>u zzui#lDg65jxxiDvw=mcl2{a^rhc7s`X;3%IeC+e=oR=NcZ`FSZep%nIQu}ksKmD~z z%_u%GU|YpC6aGTUJD##mw>YVp`{>08gDbQ`Tf$OeU+LUJeD4fnibWro=a#5OoYp#~ znujm#KM&eF-@KPiqOFAOXYZ5%eXS{vdyetDO+`fj6Ra;3{xHh#?T3AniVR*UdU zOuySWTu}mxwb^Zn0L0IOUf$U^TQPHcd`P-dRWG@n@|>?V*D}%7%F7O_>c9dydNJCF zWVGYFUH4{fRt$NESdE&t&C~Sj-`|pa(RL(Hq%CO%-aXlf3cY!`1txlz4-Wf-@t>V_8QGj ztaPSAS&)8+F;rK4Y2(4UgIN>f!6warxG_)@+3C>SB)_XK0AH-pt8(`)ZO>D$OC6Aj zA}}_BKi6&wLO+h55=(F487|JF>G^pl8PqKEdc#V#BmvJ3N7%sL7+F=#nDTDQ917*0 zx^386Xfz#JSqE>XtD`sL98}`HBY)f1cy!PQ4}(T9d5v4d$$aW=tJ-OCvT<#h7`Jd# zXm<$rOg&iPYOqV6bg_34)D(C&hN}0ZiPp&A{AeBIpm9>o2Ofr~YTgz)7G6{ZqTo-) zmIU?v%8UQil=drrAwsz^{Wa`9_G^e!#}xdIh*aVJy>Y-{NGB#3cTk2C|Fs>zmtut!MR zZQ`zI@_S95|7!tDqC5`T*WcK*qL1~cfit6L_oMlsky2NdNR~H|DhK0Qog77`990YJ z(pk8^OXK-^*YywD1&&z0KUV}?aom*O9GUoWdqq>f|Efg?pRd@U$&l!GbehuaiLV#U zW!h;BEXSM}=2@)UtngKHNx{!4!p@2gVlunyEd7rKSOAF&+aLX?^ZqkC6*x&saFN-e d`~UydXPg(DIeXGed*Hz@44$rjF6*2UngFbIOb`G7 diff --git a/sw/fpga_tools/packager/packager/index.html b/sw/fpga_tools/packager/packager/index.html deleted file mode 100644 index 66b8e0c77..000000000 --- a/sw/fpga_tools/packager/packager/index.html +++ /dev/null @@ -1,2019 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - packager - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

packager

-

SYNOPSIS

-

packager <cmd> [arguments]

-

Description

-

The packager provides tools that Accelerator Functional Unit (AFU) developers use to create Accelerator Function (AF) -files. The AF file is the programming file for an AFU on Intel® FPGA platforms. The packager tool concatenates -the metadata from the JSON file to a raw binary file (.rbf) that the Intel Quartus® Prime software generates.

-

The packager's only function is to create an AF file. Refer to Packager Command Syntax for more information -about invoking the packager. The packager depends on a JSON file to describe AFU metadata. Refer to -Accelerator Description File for more information about the JSON file.

-

The packager requires Python 2.7.1 and Python 2.7.3. The tool indicates if it is being called with a compatible -of Python.

-

Packager Command Syntax

-

The packager is a command line tool with the following syntax:

-

$ packager <cmd> [arguments]

-

The following table describes the <CMD> arguments:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CommandArgumentsDescription
create-gbs--rbf=<RBF_PATH>
--afu=<AFU_JSON_PATH>
--gbs=<GBS_PATH>
--set-value=<key>.<value>
Creates the AF file. The engineering name for this file is the green bit stream, abbreviated gbs. The --rbf and --afu arguments are required. <RBF_PATH> is the path to the RBF file for the AFU. The Quartus® Prime software generates this RBF by compiling the AFU design. <AFU_JSON_PATH> is the path to the Accelerator Description file. This is a JSON file that describes the metadata that create-gbs appends to the RBF. <GBS_PATH> is the path to the RBF file for the FPGA Interface Manager (FIM) that contains the FPGA interface unit and other interfaces. If you do not specify the --gbs, the command defaults to <rbf_name>.gbs. You can use the optional --set-value=<key>.<value> argument to set values for JSON metadata. To set more than one JSON value, list a series of <key>.<value> pairs.
modify-gbs--gbs=<gbs_PATH>Modifies the AF file. The --input-gbsargument is required. If you do not provide the --output-gbs argument, modify-gbs overwrites the --input-gbs file. Use the --set-value=<key>.<value> argument to set values for JSON metadata. To set more than one JSON value, list a series of <key>.<value> pairs.
gbs-info--input-gbs=<gbs_PATH>Prints information about the AF file. The --input-gbs argument is required.
get-rbf--gbs=<GBS_PATH>
--rbf=<RBF_PATH>
Creates the RBF by extracting it from the AF file. The --gbsargument is required. If you do not specify the --rbf argument, the command defaults to <gbs_name.rbf .
None, or any <CMD>--helpSummarizes the <CMD> options. Typing packager --help gives a list of <CMD> values. Typing packager <CMD> --help provides detailed help for <CMD>
-

Examples

-

To generate an AF file, run:

-

$ packager create-gbs --rbf=<RBF_PATH> --afu=<AFU_JSON_PATH> --gbs=<GBS_PATH>

-

TIP: JSON files are very particular about syntax such as trailing commas. If you are getting errors, use jsonlint.com to -validate that your JSON is formatted correctly.

-

To modify metadata in an existing AF, run the following command:

-

$ packager modify-gbs --input-gbs=<PATH_TO_GBS_TO_BE_MODIFIED> --outputgbs=<NAME_FOR_NEW_GBS> --set-value <key>:<value>

-

You can pass in a number of : pairs with --set-value to update values in an AF.

-

To print the metadata of an existing AF:

-

$ packager get-info --gbs=<GBS_PATH>

-

To extract the RBF from the AF:

-

$ packager get-rbf --gbs=<GBS_PATH> --rbf=<NAME_FOR_RBF>

-

Accelerator Description File

-

The Accelerator Description File is a JSON file that describes the metadata associated with an AFU. -The Open Progammable Accelerator Engine (OPAE) uses this metadata during reconfiguration. Here is an example file:

-

{
-   "version": 1,
-   "platform-name": "DCP",
-   "afu-image": {
-      "magic-no": 488605312,
-      "interface-uuid": "01234567-89AB-CDEF-0123-456789ABCDEF",
-      "power": 0,
-      "accelerator-clusters": [{
-         "name": "dma_test_afu",
-         "total-contexts": 1,   
-         "accelerator-type-uuid": "331DB30C-9885-41EA-9081-F88B8F655CAA"
-      }
-      ]  
-   }
-}
-
-The packager stores these parameter values in the resultant AF. After reprogramming the AFU using partial reconfiguration (PR), the -software driver reconfigures the PLLs by writing the clock-frequency-high and clock-frequency-low values (if present) over the -PCIe® and CCI interfaces.

-

.. note:: -

The JSON file format may change as the architecture evolves. Any changes to the current format trigger an update
-to the version number.  
-

-

CATEGORY | NAME | TYPE | DESCRIPTION | MANDATORY ----------|------|------|-------------|:----------:| -Per-AFU | version | Integer | Version of the metadata format. | Yes -Per-AFU | magic-no (to be deprecated)| Integer | Magic no. Associated with the FPGA Interface Manager. | No -Per-AFU | platform-name | String | Name of the platform for which the metadata is intended. The field value is “DCP” for Intel Acceleration Stack for FPGAs. | No -Per-AFU | interface-uuid | UUID | Interface id associated with the FPGA Interface Manager. | Yes -Per-AFU | power | Integer | Accelerator Function power consumption, in watts. Set to 0 for Intel Acceleration Stack for FPGAs platforms. | Yes -Per-AFU | clock-frequency-low | Float | Clock frequency for 1st PLL (Clock network)1 in MHz. | No -Per-AFU | clock-frequency-high | Float | Clock frequency for 2nd PLL (0 if absent) in MHz. | No -Per-AFC Cluster | total-contexts | Integer | Number of AFCs in this cluster. Always be 1 in current architectures. | Yes -Per-AFC Cluster | afc-type-uuid | UUID | AFC type = AFU ID in current architectures. | Yes -Per-AFC Cluster | name | string | AFC name = AFU name in current architectures. | Yes

- - - - - - - - - - - - - - - -
DateIntel Acceleration Stack VersionChanges Made
2018.05.21DCP 1.1 Beta (works with Quartus Prime Pro 17.1.1)Fixed typos.
- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/pci_device/pci_device/index.html b/sw/fpga_tools/pci_device/pci_device/index.html deleted file mode 100644 index 2aeddbf13..000000000 --- a/sw/fpga_tools/pci_device/pci_device/index.html +++ /dev/null @@ -1,2058 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - pci_device - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

pci_device

-

SYNOPSIS

-

pci_device [-h] [-E] device-filter [{aer,bind,plug,remove,rescan,topology,unbind,unplug,vf}]

-

DESCRIPTION

-

pci_device is a tool to aid in common operations for managing PCIe devices and -drivers.

-

OPTIONS

-

POSITIONAL ARGUMENTS

-
`device filter`
-
-PCIe address of a device or vendor/device ID pair.
-The PCIe address follows the format of [segment:]bus:device.function
-while the vendor/device ID pair follows the format [vendor ID]:[device ID]
-where at least one of these must be present.
-
-`{aer,bind,plug,remove,rescan,topology,unbind,unplug,vf}`
-
-action to perform on device
-
-`aer`
-Perform AER (Advanced Error Reporting) operations.
-The aer action has its own sub-commands which are listed below:
-
-* `dump` sub-command will print out the AER error counters as reported
-   by the sysfs files for the device.
-* `mask` can either print out the current AER mask bits or set them
-  * If `show` or `print` (or nothing) is given after the `mask`
-    command, it will show the current mask bits for AER.
-By default output will be written in stdout but can be written to an
-output file if `-o|--output FILENAME` argument is given.
-  * If `all` is given after the `mask` command, it will mask all bits
-    (by setting the values to 0xffffffff and 0xffffffff).
-  * If `off` is given after the `mask` command, it will unmask all
-    bits (by setting the values to 0x0 and 0x0).
-  * If two numbers are present after the `mask` command, those two
-    numbers will be used to set the mask bits.
-Values for setting the mask can also be read in from an input file if
-`-i|--input FILENAME` argument is given.
-
-_NOTE_: mask related operations require root privileges
-
-`bind`
-
-Associate a device with its driver.
-
-`plug`
-
-Restore a device that was previously given to `pci_device <device> unplug`
-
-`remove`
-
-Remove the pci device from the pci bus
-
-`rescan`
-
-Rescan the bus as identified by the bus component of the PCIe device address
-
-'topology`
-
-Print the PCIe topology from the root port to the PCIe device.
-This shows the PCIe tree rooted at the PCIe root port.
-Each line shows the the PCIe address, vendor ID, and device ID along with
-the driver bound to the device. The indentnation is used to show
-parent/child relationship of devices.
-
-The line listing the target PCIe device as identified by the given PCIe
-address will be highlighted in green while the endpoints will be
-highlighted in cyan.
-
-The example below shows the topology of an N3000 device with eight virtual
-functions created from one of the Ethernet controllers:
-
-```console
-[pci_address(0000:3a:00.0), pci_id(0x8086, 0x2030)] (pcieport)
-    [pci_address(0000:3b:00.0), pci_id(0x10b5, 0x8747)] (pcieport)
-        [pci_address(0000:3c:09.0), pci_id(0x10b5, 0x8747)] (pcieport)
-            [pci_address(0000:3f:00.0), pci_id(0x8086, 0x0b30)] (dfl-pci)
-        [pci_address(0000:3c:11.0), pci_id(0x10b5, 0x8747)] (pcieport)
-            [pci_address(0000:43:00.0), pci_id(0x8086, 0x0b32)] (no driver)
-    [pci_address(0000:3c:08.0), pci_id(0x10b5, 0x8747)] (pcieport)
-            [pci_address(0000:3d:02.0), pci_id(0x8086, 0x154c)] (iavf)
-            [pci_address(0000:3d:00.1), pci_id(0x8086, 0x0d58)] (i40e)
-            [pci_address(0000:3d:02.7), pci_id(0x8086, 0x154c)] (iavf)
-            [pci_address(0000:3d:02.5), pci_id(0x8086, 0x154c)] (iavf)
-            [pci_address(0000:3d:02.3), pci_id(0x8086, 0x154c)] (iavf)
-            [pci_address(0000:3d:02.1), pci_id(0x8086, 0x154c)] (iavf)
-            [pci_address(0000:3d:00.0), pci_id(0x8086, 0x0d58)] (i40e)
-            [pci_address(0000:3d:02.6), pci_id(0x8086, 0x154c)] (iavf)
-            [pci_address(0000:3d:02.4), pci_id(0x8086, 0x154c)] (iavf)
-            [pci_address(0000:3d:02.2), pci_id(0x8086, 0x154c)] (iavf)
-        [pci_address(0000:3c:10.0), pci_id(0x10b5, 0x8747)] (pcieport)
-            [pci_address(0000:41:00.0), pci_id(0x8086, 0x0d58)] (i40e)
-            [pci_address(0000:41:00.1), pci_id(0x8086, 0x0d58)] (i40e)
-
-```
-
-`unbind`
-
-Unbind the driver bound to the device.
-
-`unplug`
-
-Remove device from PCI bus in anticipation of a RSU event by configuring its root port and associated endpoints.
-
-`vf`
-
-Create/destroy VFs (virtual functions) by setting the number here.
-The number given here will be written to sriov_numvfs sysfs file triggering
-the PCIe subsystem to create/destroy VFs so that the current number of VFs
-will be equal to the given number. If the number given is outside of the total VFs supported, an error message will be displayed to indicate this.
-
-

OPTIONAL ARGUMENTS

-
`-h, --help`
-
-show this help message and exit
-
-`-E, --other-endpoints`
-
-perform action on peer PCIe devices
-
-

EXAMPLES

-
pci_device 0000:3d:00.0 remove
-pci_device 0000:3d:00.0 rescan
-pci_device 3d:00.0 topology
-pci_device :0b30 topology
-pci_device :0b30 aer
-pci_device :0b30 aer mask
-pci_device :0b30 aer mask all
-pci_device :0b30 aer mask -o mask.dat
-pci_device :0b30 aer mask -i mask.dat
-
- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/readme/index.html b/sw/fpga_tools/readme/index.html deleted file mode 100644 index 36dfc5783..000000000 --- a/sw/fpga_tools/readme/index.html +++ /dev/null @@ -1,2436 +0,0 @@ - - - - - - - - - - - - - - - - - - fpga_tools # - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

fpga_tools

-

fpgainfo

-

NAME

-

fpgainfo - FPGA information tool

-

SYNOPSIS

-
fpgainfo [-h | --help] [-s | --socket-id] <command> [<args>]
-
-

DESCRIPTION

-

fpgainfo is a tool to show FPGA information derived from sysfs files. The command argument -is one of the following: errors, power, temp and is used to specify what type of information -to report. Some commands may also have other arguments/options that can be used to control the -behavior of that command.

-

COMMON OPTIONS

-

--help, -h

-
Print help information and exit.
-
-

--socket-id, -s

-
Socket ID encoded in BBS. Default=0
-
-

FPGAINFO COMMANDS

-

errors

-
Show/clear errors of an FPGA resource as specified by the first argument.
-Error information is parsed to display in human readable form.
-
-

power

-
Show total power consumed by the FPGA hardware in watts
-
-

temp

-
Show FPGA temperature values in degrees Farenheit
-
-

ERRORS OPTIONS

-

--clear, -c

-
Clear errors for the given FPGA resource
-
-

ERRORS ARGUMENTS

-

The first argument to the errors command is used to specify what kind of -resource to act on. It must be one of the following: -fme,port,first_error,pcie0,pcie1,bbs,gbs,all -More details on the errors reported for the resource can be found below:

-

ERRORS RESOURCES

-

fme

-
Show/clear errors pertaining to the FME
-
-

port

-
Show/clear errors pertaining to the PORT
-
-

first_error

-
Show/clear first errors encountered by the FPGA
-
-

pcie0

-
Show/clear errors pertaining to the PCIE0 lane
-
-

pcie1

-
Show/clear errors pertaining to the PCIE1 lane
-
-

bbs

-
Show/clear errors pertaining to the BBS (blue bitstream)
-
-

gbs

-
Show/clear errors pertaining to the GBS (green bitstream)
-
-

all

-
Show/clear errors for all resources
-
-

EXAMPLES

-

This command shows the current power consumtion: -

./fpgainfo power
-

-

This command shows the current temperature reading: -

./fpgainfo temp
-

-

This command shows the errors for the FME resource: -

./fpgainfo errors fme
-
-This command clears all the errors on all resources: -
./fpgainfo errors all -c
-

-

fpgaconf

-

NAME

-

fpgadiag - Configure a green bitstream to an FPGA

-

SYNOPSIS

-

fpgaconf [-hvn] [-b <bus>] [-d <device>] [-f <function>] [-s <socket>] <gbs>

-

DESCRIPTION

-

fpgaconf writes accelerator configuration bitstreams (also referred to as "green -bitstreams" to an FPGA device recognized by OPAE. In the process, it also checks -the green bitstream file for compatibility with the targeted FPGA and its -current infrastructure bitstream (the "blue bistream"). fpgaconf takes the -following arguments:

-

-h, --help

-
Print usage information
-
-

-v, --verbose

-
Print more verbose messages while enumerating and configuring. Can be
-given more than once
-
-

-n, --dry-run

-
Perform enumeration, but skip any operations with side-effects (like the
-actual configuration of the bitstream
-
-

-b, --bus

-
PCI bus number of the FPGA to target
-
-

-d, --device

-
PCI device number of the FPGA to target
-
-

-f, --function

-
PCI function number of the FPGA to target
-
-

-s, --socket

-
Socket number of the FPGA to target
-
-

fpgaconf will enumerate available FPGA devices in the system and select -compatible FPGAs for configuration. If there are more than one candidate FPGAs -that are compatible with the given green bitstream, fpgaconf will exit and ask -you to be more specific in selecting the target FPGAs (e.g. by specifying a -socket number, or a PCIe bus/device/function).

-

EXAMPLES

-

fpgaconf my_green_bitstream.gbs

-
Program "my_green_bitstream.gbs" to a compatible FPGA
-
-

fpgaconf -v -s 0 my_green_bitstream.gbs

-
Program "my_green_bitstream.gbs" to the FPGA in socket 0, if compatible,
-while printing out slightly more verbose information
-
-

fpgad

-

NAME

-

fpgad - log errors and generate events

-

SYNOPSIS

-

fpgad --daemon [--directory=<dir>] [--logfile=<file>] [--pidfile=<file>] [--umask=<mode>] [--socket=<sock>] [--null-bitstream=<file>] -fpgad [--socket=<sock>] [--null-bitstream=<file>]

-

DESCRIPTION

-

Periodically monitors/reports the error status reflected in the device driver's error status sysfs files. -Establishes the channel by which events are communicated to the OPAE application. Programs a NULL bitstream -in response to AP6 event.

-

fpgad is required to be running before API calls fpgaRegisterEvent and fpgaUnregisterEvent will succeed.

-

Use SIGINT to stop fpgad.

-

-d, --daemon

-
When given, fpgad executes as a system demon process.
-
-

-D, --directory <dir>

-
When running in daemon mode, execute from the given directory.
-If omitted when daemonizing, /tmp is used.
-
-

-l, --logfile <file>

-
When running in daemon mode, send output to file. When not in daemon mode, the output is sent to stdout.
-If omitted when daemonizaing, /tmp/fpgad.log is used.
-
-

-p, --pidfile <file>

-
When running in daemon mode, write the daemon's process id to file.
-If omitted when daemonizing, /tmp/fpgad.pid is used.
-
-

-m, --umask <mode>

-
When running in daemon mode, use the mode value as the file mode creation mask passed to umask.
-If omitted when daemonizing, 0 is used.
-
-

-s, --socket <sock>

-
Listen for event API registration requests on sock. The default socket value used by the API is
-/tmp/fpga_event_socket.
-
-

-n, --null-bitstream <file>

-
Specify the NULL bitstream to program when an AP6 event occurs. This option may be given multiple
-times. The bitstream, if any, that matches the FPGA's PR interface id will be programmed when AP6
-is detected.
-
-

TROUBLESHOOTING

-

If any issues are encountered, try the following for additional debug information:

-
    -
  1. Examine the log file when in daemon mode.
  2. -
  3. Run in non-daemon mode and view stdout.
  4. -
-

EXAMPLES

-

fpgad --daemon --null-bitstream=my_null_bits.gbs

-

SEE ALSO

-

umask

-

fpgadiag

-

NAME

-

fpgadiag - FPGA diagnosis and testing tool.

-

SYNOPSIS

-
fpgadiag [-m | --mode=] <mode> [-t | --target=] <target> [options]
-
-

DESCRIPTION

-

fpgadiag includes several tests to diagnose, test and report on the FPGA hardware.

-

<mode> chooses which test to run. <target> specifies on what platform to -run the test. <target> can be either fpga or ase, where ase stands for -"AFU Simulation Environment".

-

The tests that can be selected by <mode> include:

-

lpbk1

-
The test performs loopback test on the number of cachelines specified with 
-the `BEGIN` option. _fpgadiag_ sets up source and  destination buffers in 
-main memory. The FPGA then performs a memcpy from a source buffer to the 
-destination buffer, one cacheline at a time.
-
-A cacheline is 64 bytes. When `BEGIN = END`, you perform one iteration. When 
-`BEGIN = END + x`, you perform `x` iterations. The first iteration consists 
-of copying `BEGIN` cachelines; the second iteration consists of copying 
-`BEGIN+1` cache lines; the third iteration consists of copying `BEGIN+3` 
-cache lines, etc.
-
-The latency is shown as the number of clock ticks.
-
-When you specify `MULTI-CL`, you copy `MULTI-CL` cache lines at a time.
-There is always a WrFence. `WR-FENCE` chooses what virtual channel the 
-WrFence occurs on.
-
-If you specify continuous mode with `--cont`, the program runs an iteration
-until the timeout specified in `TIMEOUT` completes.
-
-

read

-
This test performs only a read, not a memcpy. It is used to measure read 
-bandwidth.
-
-

write

-
This test is used to measure write bandwidth.
-
-

trput

-
This test measures both read and write bandwidth by performing 50% read and 
-50% write tests.
-
-

sw

-
This is a send-and-respond (ping-pong) test where one side sends data and 
-waits for answer.
-
-

Each test requires presence of one of these bitstreams, as documented below. -Before running a test, make sure its required bitstream is properly configured -on the platform.

-
    -
  • nlb mode 0 for the lpbk1 test.
  • -
  • nlb mode 3 for the trput, read, and write tests.
  • -
  • nlb mode 7 for the sw test.
  • -
-

OPTIONS

-

Common options

-

--help, -h

-
Print help information and exit.
-
-

--target=, -t

-
Values accepted for this switch are fpga or ase. Default=fpga
-
-

--mode=, -m

-
The test to run. Values accepted for this switch are `lpbk1`, `read`,
-`write`, `trput`, `sw`
-
-

--config=, -c

-
A configuration file in the JSON format that specifies options for a test.
-If an option is specified both in the configuration file and on the command 
-line, the value in the configuration file prevails
-
-

--socket-id=, -s

-
Socket ID encoded in BBS. Default=0
-
-

--bus-number=, -B

-
Bus number of the PCIe device. Default=0
-
-

--device=, -D

-
Device number of the PCIe device. Default=0
-
-

--function=, -F

-
Function number of the PCIe device. Default=0
-
-

--freq=, -T

-
Clock frequency in Hz. Default=400 MHz
-
-

--suppress-hdr, -S

-
Suppress column headers for text output. Default=off
-
-

--csv, -V

-
Comma separated value format. Default=off
-
-

lpbk1 test options

-

--guid=, -g

-
Accelerator ID to enumerate. Default=D8424DC4-A4A3-C413-F89E-433683F9040B
-
-

--begin=B, -b

-
1 <= B <= 65535. Default=1, B = number of cache lines
-
-

--end=E, -e

-
1 <= E <= 65535. Default=B, B and E designate number of cache lines
-
-

--multi-cl=M, -U

-
M can equal 1, 2, or 4. Default=1
-
-

--cont, -L

-
Continuous mode. Default=off
-
-

--timeout-usec=, --timeout-msec=, --timeout-sec=, --timeout-min=, --timeout-hour=

-
timeout for --cont mode (microseconds portion default=0; milliseconds 
-portion default=0; seconds portion default=1; minutes portion default=0;
-hours portion default=0)
-
-

--cache-policy=, -p

-
Can be wrline-I, wrline-M, or wrpush-I Default=wrline-M
-
-

--cache-hint=, -i

-
Can be rdline-I or rdline-S. Default=rdline-I
-
-

--read-vc=, -r

-
Can be auto, vl0, vh0, vh1, random. Default=auto
-
-

--write-vc=, -w

-
Can be auto, vl0, vh0, vh1, random. Default=auto
-
-

--wrfence-vc=, -f

-
Can be auto, vl0, vh0, vh1. Default=auto
-
-

read test options

-

--guid=, -g

-
Accelerator ID to enumerate. Default=F7DF405C-BD7A-CF72-22F1-44B0B93ACD18
-
-

--begin=B, -b

-
1 <= B <= 65535. Default=1, B = number of cache lines
-
-

--end=E, -e

-
1 <= E <= 65535. Default=B, B and E designate number of cache lines
-
-

--multi-cl=M, -u

-
M can equal 1, 2, or 4. Default=1
-
-

--strided-access=S, -a

-
1<= S <= 64. Default=1
-
-

--cont, -L

-
Continuous mode. Default=off
-
-

--timeout-usec=, --timeout-msec=, --timeout-sec=, --timeout-min=, --timeout-hour=

-
timeout for --cont mode (microseconds portion default=0; milliseconds 
-portion default=0; seconds portion default=1; minutes portion default=0;
-hours portion default=0)
-
-

--cache-hint=, -i

-
Can be rdline-I or rdline-S. Default=rdline-I
-
-

--warm-fpga-cache -H; --cool-fpga-cache -M

-
Attempt to prime the cache with hits. Default=off, Attempt to prime the 
-cache with misses. Default=off
-
-

--cool-cpu-cache, -C

-
Attempt to prime the cpu cache with misses. Default=off
-
-

--read-vc=, -r

-
Can be auto, vl0, vh0, vh1, random. Default=auto
-
-

write test options

-

--guid=, -g

-
Accelerator ID to enumerate. Default=F7DF405C-BD7A-CF72-22F1-44B0B93ACD18
-
-

--begin=B, -b

-
1 <= E <= 65535. Default=B, B and E designate number of cache lines
-
-

--multi-cl=M, -u

-
M can equal 1, 2, or 4. Default=1
-
-

--strided-access=S, -a

-
1<= S <= 64. Default=1
-
-

--cont, -L

-
Continuous mode. Default=off
-
-

--timeout-usec=, --timeout-msec=, --timeout-sec=, --timeout-min=, --timeout-hour=

-
timeout for --cont mode (microseconds portion default=0; milliseconds 
-portion default=0; seconds portion default=1; minutes portion default=0;
-hours portion default=0)
-
-

--cache-policy=, -p

-
Can be wrline-I, wrline-M, or wrpush-I Default=wrline-M
-
-

--warm-fpga-cache -H; --cool-fpga-cache -M

-
Attempt to prime the cache with hits. Default=off, Attempt to prime the 
-cache with misses. Default=off
-
-

--cool-cpu-cache, -C

-
Attempt to prime the cpu cache with misses. Default=off
-
-

--write-vc=, -w

-
Can be auto, vl0, vh0, vh1, random. Default=auto
-
-

--wrfence-vc=, -f

-
Can be auto, vl0, vh0, vh1, random. Default=`WRITE-VC`
-
-

--alt-wr-pattern, -l

-
Alternate Write Pattern. Default=off
-
-

trput test options

-

--guid=, -g

-
Accelerator ID to enumerate. Default=F7DF405C-BD7A-CF72-22F1-44B0B93ACD18
-
-

--begin=B, -b

-
1 <= B <= 65535. Default=1, B = number of cache lines
-
-

--end=E, -e

-
1 <= E <= 65535. Default=B, B and E designate number of cache lines
-
-

--multi-cl=M, -u

-
M can equal 1, 2, or 4. Default=1
-
-

--strided-access=S, -a

-
1<= S <= 64. Default=1
-
-

--cont, -L

-
Continuous mode. Default=off
-
-

--timeout-usec=, --timeout-msec=, --timeout-sec=, --timeout-min=, --timeout-hour=

-
timeout for --cont mode (microseconds portion default=0; milliseconds 
-portion default=0; seconds portion default=1; minutes portion default=0;
-hours portion default=0)
-
-

--cache-policy=, -p

-
Can be wrline-I, wrline-M, or wrpush-I Default=wrline-M
-
-

--cache-hint=, -i

-
Can be rdline-I or rdline-S. Default=rdline-I
-
-

--read-vc=, -r

-
Can be auto, vl0, vh0, vh1, random. Default=auto
-
-

--write-vc=, -w

-
Can be auto, vl0, vh0, vh1, random. Default=auto
-
-

--wrfence-vc=, -f

-
Can be  auto, vl0, vh0, vh1. Default=`WRITE-VC`
-
-

sw test options

-

--guid=, -g

-
Accelerator ID to enumerate. Default=7BAF4DEA-A57C-E91E-168A-455D9BDA88A3
-
-

--begin=B, -b

-
1 <= B <= 65535. Default=1, B = number of cache lines
-
-

--end=E, -e

-
1 <= E <= 65535. Default=B, B and E designate number of cache lines
-
-

--multi-cl=M, -u

-
M can equal 1, 2, or 4. Default=1
-
-

--strided-access=S, -a

-
1<= S <= 64. Default=1
-
-

--cache-policy=, -p

-
Can be wrline-I, wrline-M, or wrpush-I. Default=wrline-M
-
-

--cache-hint= -i

-
Can be rdline-I or rdline-S. Default=rdline-I
-
-

--read-vc=, -r

-
Can be auto, vl0, vh0, vh1, random Default=auto
-
-

--write-vc=, -w

-
Can be auto, vl0, vh0, vh1, random Default=auto
-
-

--wrfence-vc=, -f

-
Can be auto, vl0, vh0, vh1. Default=`WRITE-VC`
-
-

--notice=, -N

-
Can be poll, csr-write, umsg-data, or umsg-hint. Default=poll
-
-

EXAMPLES

-

This command starts an lpbk1 test on the FPGA on bus 0x5e. The test -copies 57535, 57536, 57537, ..., up to 65535 cache lines, one line at a time. -The test output is printed in the CSV format with header suppressed. -

./fpgadiag --mode=lpbk1 --target=fpga -SV --bus-number=0x5e --begin=57535
---end=65535 --cache-hint=rdline-I --cache-policy=wrpush-I --multi-cl=1
---write-vc=vl0 --read-vc=vh1 --wrfence-vc=auto
-

-

This command starts a read test on the FPGA located on bus 0xbe. The test -reads 2045 cache lines in the continuous mode with a 15-second timeout period. -Data is accessed with a strided pattern with a 10-byte stride length. -

./fpgadiag --mode=read --target=fpga -SV --bus-number=0xbe --begin=2045 --cont
---timeout-sec=15   --cache-hint=rdline-I --multi-cl=1 -a=10 --write-vc=vh1
---read-vc=auto --wrfence-vc=auto
-

-

This command starts an sw test on the FPGA located on bus 0xbe. The test -notifies completion using a CSR write. -

./fpgadiag --mode=sw --target=fpga -SV --bus-number=0xbe --begin=4 --end=8192
---cache-hint=rdline-I --cache-policy=wrline-I --notice=csr-write --write-vc=vl0
---wrfence-vc=auto --read-vc=random 
-

-

TROUBLESHOOTING

-

When a test fails to run or gives errors, check the following:

-
    -
  • Is Intel FPGA driver properly installed? -See Installation Guide -for driver installation instructions.
  • -
  • Are FPGA port permissions set properly? Check the permission bits of the -port, for example, /dev/intel-fpga-port-0. Users need READ and WRITE -permissions to run fpgadiag tests.
  • -
  • Is hugepage properly configured on the system? -See Installation Guide -for hugepage configuration steps.
  • -
  • Is the required bitstream loaded? See DESCRIPTION for -information about what bitstream is required by which test.
  • -
  • Are --begin and --end values set properly? --end must be no -smaller than the --begin. Also, --begin must be a multiple of the ---multi-cl value.
  • -
  • The --warm-fpga-cache and --cool-fpga-cache options in the read -and write tests are mutually exclusive.
  • -
  • The timeout options are only meaningful for the continuous mode -(with the --cont option).
  • -
-

mmlink

-

NAME

-

MMLink - Debugging RTL.

-

SYNOPSIS

-

mmlink [-B <bus>] [-D <device>] [-F <function>] [-S <socket>] [-P <TCP port>] [-I <IP Address>]

-

DESCRIPTION

-

Remote signaltap is software tool used for debug RTL (AFU), effectively a signal trace capability that Quartus places into a green bitstream. -Remote Signal Tap provides access the RST part of the Port MMIO space, and then runs the remote protocol on top.

-

EXAMPLES

-

./mmlink -B 0x5e -P 3333

-

MMLink app starts and listens for connection.

-

OPTIONS

-

-B,--bus FPGA Bus number.

-

-D,--device FPGA Device number.

-

-F,--functio FPGA function number.

-

-S,--socket FPGA socket number.

-

-P,--port TCP port number.

-

-I,--ip IP address of FPGA system.

-

NOTES

-

Driver privilege:

-

Change AFU driver privilege to user .

-

command: chmod 777 /dev/intel-fpga-port.0

-

set memlock:

-

command: ulimit -l 10000

-

coreidle

-

NAME

-

coreidle - idles cores for shared TDP sockets to run online cores at maximum capacity.

-

SYNOPSIS

-

coreidle [-B <bus>] [-D <device>] [-F <function>] [-S <socket>] [-G <GBS path>]

-

DESCRIPTION

-

This tools parses input GBS, extracts power from metadata ,calculates fpga power, number of online and idle cores. -It moves threads from idle cores to online cores.

-

EXAMPLES

-

./coreidle -B 0x5e -G /home/lab/gbs/mode0.gbs

-

Idle cores to run online cores at maximum capacity.

-

OPTIONS

-

-B,--bus FPGA Bus number.

-

-D,--device FPGA Device number.

-

-F,--functio FPGA function number.

-

-S,--socket FPGA socket number.

-

-G,--gbs Green bitstream file path.

-

fpgamux

-

NAME

-
fpgamux - Software MUX for running multiple AFU (accelerator functional unit) tests in one GBS (green bitsream)
-
-

SYNOPSIS

-
fpgamux [-h] [-S|--socket-id SOCKET_ID] [-B|--bus-number BUS] [-D|--device DEVICE] [-F|--function FUNCTION]
-          [-G|--guid GUID] -m|--muxfile MUXFILE.json
-
-

DESCRIPTION

-

fpgamux is a testing tool to interact with multiple AFUs that have been synthesized into one GBS along with -the CCIP-MUX BBB (basic building block). The CCIP-MUX uses upper bits in the MMIO addresses to route MMIO -reads/writes to the AFU running on the corresponding CCIP-MUX port. fpgamux uses a configuration file that -lists the software components and configuration to use.

-

.. note::

-
  Only one (the first) AFU is discoverable by the OPAE driver. Enumerating acceleration on an FPGA will find
-  the accelerator associated with the first AFU only. The first software component in the configuration will
-  be used to determine the GUID to use for enumeration. This can be overridden with the -G|--guid option.
-
-

OPTIONS

-
-S SOCKET_ID, --socket-id SOCKET_ID
-   socket id of FPGA resource
-
--B BUS, --bus BUS
-   bus id of FPGA resource
-
--D DEVICE, --device DEVICE
-   device id of FPGA resource
-
-
--F FUNCTION, --function FUNCTION
-   function id of FPGA resource
-
--G, --guid
-   specify what guid to use for the accelerator enumeration
-
-

CONFIGURATION

-

fpgamux uses a configuration file (in JSON format) to determine what software components to instantiate and -how to configure them for interacting with the AFUs in the GBS. This schema for this is listed below:

-
[
-    {
-        "app" : "fpga_app",
-        "name" : "String",
-        "config" : "Object"
-    }
-]
-
-

EXAMPLES

-

An example configuration with two components is listed below:

-
[
-    {
-        "app" : "nlb0",
-        "name" : "nlb0",
-        "config" :
-        {
-            "begin" : 1,
-            "end" : 1,
-            "multi-cl" : 1,
-            "cont" : false,
-            "cache-policy" : "wrline-M",
-            "cache-hint" : "rdline-I",
-            "read-vc" : "vh0",
-            "write-vc" : "vh1",
-            "wrfence-vc" : "write-vc",
-            "timeout-usec" : 0,
-            "timeout-msec" : 0,
-            "timeout-sec" : 1,
-            "timeout-min" : 0,
-            "timeout-hour" : 0,
-            "freq" : 400000000
-        }
-    },
-    {
-        "app" : "nlb3",
-        "name" : "nlb3",
-        "config" :
-        {
-            "mode" : "read",
-            "begin" : 1,
-            "end" : 1,
-            "multi-cl" : 1,
-            "strided-access" : 1,
-            "cont" : false,
-            "warm-fpga-cache" : false,
-            "cool-fpga-cache" : false,
-            "cool-cpu-cache" : false,
-            "cache-policy" : "wrline-M",
-            "cache-hint" : "rdline-I",
-            "read-vc" : "vh0",
-            "write-vc" : "vh1",
-            "wrfence-vc" : "write-vc",
-            "alt-wr-pattern" : false,
-            "timeout-usec" : 0,
-            "timeout-msec" : 0,
-            "timeout-sec" : 1,
-            "timeout-min" : 0,
-            "timeout-hour" : 0,
-            "freq" : 400000000
-        }
-    }
-]
-
-

userclk

-

NAME

-

userclk - to set afu high and low clock frequency.

-

SYNOPSIS

-

userclk [-B <bus>] [-D <device>] [-F <function>] [-S <socket>] [-P <Port id>] [-H <User clock high frequency>] -L <User clock low frequency>]

-

DESCRIPTION

-

userclk tool used to set high and low clock frequency to acceleration function unit.

-

EXAMPLES

-

./userclk -B 0x5e -H 400 -L 200

-

Sets AFU frequency.

-

OPTIONS

-

-B,--bus FPGA Bus number.

-

-D,--device FPGA Device number.

-

-F,--functio FPGA function number.

-

-S,--socket FPGA socket number.

-

-P,--port Port id.

-

-H,--freq-high User clock high frequency.

-

-L,--freq-low User clock low frequency.

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/rsu/rsu/index.html b/sw/fpga_tools/rsu/rsu/index.html deleted file mode 100644 index 1acd48b30..000000000 --- a/sw/fpga_tools/rsu/rsu/index.html +++ /dev/null @@ -1,2009 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - rsu - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

rsu

-

SYNOPSIS

-
rsu [-h] [-d] {bmc,bmcimg,retimer,fpga,sdm,fpgadefault} [PCIE_ADDR]
-
-

DESCRIPTION

-

Mode 1: RSU

-
rsu bmc --page=(user|factory) [PCIE_ADDR]
-rsu retimer [PCIE_ADDR]
-rsu fpga --page=(user1|user2|factory) [PCIE_ADDR]
-rsu sdm --type=(sr|pr|sr_cancel|pr_cancel) [PCIE_ADDR]
-
-

Perform RSU (remote system update) operation on PAC device -given its PCIe address. -An RSU operation sends an instruction to the device to trigger -a power cycle of the card only. This will force reconfiguration -from flash for either BMC, Retimer, SDM, (on devices that support these) -or the FPGA.

-

Mode 2: Default FPGA Image

-
rsu fpgadefault --page=(user1|user2|factory) --fallback=<csv> [PCIE_ADDR]
-
-

Set the default FPGA boot sequence. The --page option determines -the primary FPGA boot image. The --fallback option allows a comma-separated -list of values to specify fallback images.

-

POSITIONAL ARGUMENTS

-

{bmc,bmcimg,retimer,fpga,sdm,fpgadefault}

-

type of RSU operation or set Default FPGA Image operation.

-

PCIE_ADDR -PCIe address of device to do rsu (e.g. 04:00.0 or 0000:04:00.0)

-

OPTIONAL ARGUMENTS

-

-h, --help -show this help message and exit

-

-d, --debug -log debug statements

-

--force -force rsu operation

-

EXAMPLE

-
# rsu bmc --page=user 25:00.0
-
-

Triggers a boot of the BMC image (user page) for the device with PCIe - address 25:00.0.

-
# rsu bmc --page=factory 25:00.0
-
-

Triggers a factory boot of the BMC image for the device with - PCIe address 25:00.0.

-
# rsu fpga --page=user2 25:00.0
-
-

Triggers a reconfiguration of the FPGA (user2 page) for the - device with PCIe address 25:00.0.

-
# rsu --force fpga --page=user2 25:00.0
-
-

Forces a reconfiguration of the FPGA (user2 page) for the - device with PCIe address 25:00.0. Default behavior is to not perform - the rsu operation if DPC (downstream port containment) is not supported - and AER (advanced error reporting) is also not supported. Using --force - changes this behavior to perform rsu operation regardless but may result - in a surprise removal of pci devices which may cause the Linux kernel - to panic.

-
# rsu fpga --page=factory 25:00.0
-
-

Triggers a factory reconfiguration of the FPGA for the device - with PCIe address 25:00.0.

-
# rsu sdm --type=sr 25:00.0
-
-

Triggers Static Region key programming for the device with - PCIE address 25:00.0.

-
# rsu fpgadefault --page=factory --fallback=user1,user2 25:00.0
-
-

Sets the FPGA boot sequence to factory with fallbacks user1, user2.

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/super-rsu/super-rsu/index.html b/sw/fpga_tools/super-rsu/super-rsu/index.html deleted file mode 100644 index d7aa16cbb..000000000 --- a/sw/fpga_tools/super-rsu/super-rsu/index.html +++ /dev/null @@ -1,1884 +0,0 @@ - - - - - - - - - - - - - - - - - - Super Remote System Update User Guide # - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

Super Remote System Update User Guide

-
.. toctree::
-.. highlight:: c
-.. highlight:: console
-
-

Overview

-

Intel Programmable Acceleration Card (PAC) devices are comprised of multiple processors -and controllers that execute firmware. Maintaining and updating these firmware images -manually is error-prone and does not scale well within the Data Center. The solution -described here is derived with the following goals in mind:

-
    -
  • The ability to update one or more (possibly all) firwmare images with a single package.
  • -
  • The ability to complete all firmware updates within a stipulated time window.
  • -
  • The ability to update each PAC in the server, all servers in a Data Center, and multiple -Data Centers remotely.
  • -
  • The ability to remotely initiate download of the package and its installation with a -single command per server instance.
  • -
  • The ability to roll back firmware to a previous revision.
  • -
-

Implementation

-

A single package containing firmware images for all programmable parts on a PAC is delivered -as an RPM, eg opae-super-rsu-n3000.M.m.p-r.noarch.rpm. The RPM revision will sequentially increase -with every update.

-

Installing or upgrading the RPM invokes the complete update of all programmable parts on all -PAC boards in the system.

-

The standard RPM dependency framework ensures that correct versions of dependecy packages -opae-intel-fpga-driver and fpga-tools-extra are installed on the system.

-

Rolling back is achieved by uninstalling the current version and re-installing a previous -version of the RPM.

-

.. note:: -

Note: once Secure Update is deployed, roll back restrictions shall be implemented to prevent
-rollback attacks.
-

-

RPM management on remote systems is standard practice, requiring no new infrastructure/training.

-

Details

-

The post-install hook of the opae-super-rsu-n3000 RPM is leveraged to call out to the super-rsu -Python script to update all PAC boards. super-rsu uses the manifest file packaged within -opae-super-rsu-n3000 to associate a firmware image with its version. Each of the firmware images -contained in opae-super-rsu-n3000 is placed on the target system in /usr/share/opae/n3000.

-

Algorithm

-
    -
  • Acquire the current firmware versions of all programmable parts.
  • -
  • For each programmable image, if the installed version of firmware does not equal the version -provided in the RPM manifest file, then update the firmware image, and set image_updated to True.
  • -
  • After all updates, if image_updated, then initiate a safe reboot of all boards in the system.
  • -
  • After safe reboot, verify that the reported firmware versions match those of the RPM manifest. -If they do not match, then RPM installation exits with a failing status.
  • -
  • Run board self test. If the self test fails, then the RPM installation exits with a failing status.
  • -
  • If all of the above checks is successful, then RPM installation exits with a success status.
  • -
-

Dependencies

-
    -
  • The standard Python package for the distro (version 2.7).
  • -
  • The opae-intel-fpga-driver RPM. (version determined by opae-super-rsu-n3000)
  • -
  • The opae-tools-extra RPM. (version determined by opae-super-rsu-n3000)
  • -
- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/userclk/userclk/index.html b/sw/fpga_tools/userclk/userclk/index.html deleted file mode 100644 index 557bc5f88..000000000 --- a/sw/fpga_tools/userclk/userclk/index.html +++ /dev/null @@ -1,1926 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - userclk - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

userclk

-

SYNOPSIS

-

userclk [-hv] [-S <segment>] [-B <bus>] [-D <device>] [-F <function>] [PCI_ADDR] [-H <User clock high frequency>] -L <User clock low frequency>]

-

DESCRIPTION

-

userclk sets the frequency range for an AFU.

-

EXAMPLES

-

./userclk -B 0x5e -H 400 -L 200

-

Sets AFU frequency.

-

OPTIONS

-

-v,--version

-

Prints version information and exits.

-

-S,--segment

-

FPGA segment number.

-

-B,--bus

-

FPGA Bus number.

-

-D,--device

-

FPGA Device number.

-

-F,--function

-

FPGA function number.

-

-H,--freq-high

-

User clock high frequency.

-

-L,--freq-low

-

User clock low frequency.

- - - - - - - - - - - - - - - -
DateIntel Acceleration Stack VersionChanges Made
2018.05.21DCP 1.1 Beta (works with Quartus Prime Pro 17.1.1)Fixed typos.
- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/fpga_tools/vabtool/vabtool/index.html b/sw/fpga_tools/vabtool/vabtool/index.html deleted file mode 100644 index 32a33ea98..000000000 --- a/sw/fpga_tools/vabtool/vabtool/index.html +++ /dev/null @@ -1,1928 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - vabtool - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

vabtool

-

SYNOPSIS

-

vabtool [-r RETRIES] [-d] [-y] [-v] <ACTION>

-

Where ACTION is defined as one of the following:

-

vabtool sr_key_provision PCIE_ADDRESS SR_RKH_FILE FPGA_IMG_FILE
-vabtool sr_status PCIE_ADDRESS
-vabtool pr_key_provision PCIE_ADDRESS PR_AUTH_CERT_FILE PR_RKH_FILE
-vabtool pr_status PCIE_ADDRESS
-vabtool sr_key_cancel PCIE_ADDRESS SR_RKH_CANCEL_FILE
-vabtool sr_cancel_status PCIE_ADDRESS
-vabtool pr_key_cancel PCIE_ADDRESS PR_RKH_CANCEL_FILE
-vabtool pr_cancel_status PCIE_ADDRESS

-

DESCRIPTION

-

The vabtool command helps perform Vendor Authenticated Boot -provisioning of Static Region and Partial Reconfiguration Region key -hashes and helps perform SR and PR hash cancellation and status reporting.

-

OPTIONS

-

-r RETRIES, --retries RETRIES

-
Specifies the number of times a failed SR or PR key provision is to be
-retried. The default value for RETRIES is 3.
-
-

-d, --dry-run

-
Don't execute the actual fpgasupdate and rsu commands, but only print
-the commands that would be executed during a normal run of the script.
-
-

-y, --yes

-
The tool will respond with an automatic Yes answer to all confirmation
-prompts posed by the sub-tools.
-
-

-v, --version

-
Display script version information and exit.
-
-

EXAMPLES

-

sudo vabtool -y sr_key_provision 0000:bc:00.0 my_sr_rkh.bin my_fpga.bin
-sudo vabtool sr_status 0000:bc:00.0
-sudo vabtool -y pr_key_provision 0000:bc:00.0 pr_auth_cert.bin my_pr_rkh.bin
-sudo vabtool pr_status 0000:bc:00.0
-sudo vabtool sr_key_cancel 0000:bc:00.0 my_sr_rhk_cancel.bin
-sudo vabtool sr_cancel_status 0000:bc:00.0
-sudo vabtool pr_key_cancel 0000:bc:00.0 my_pr_rhk_cancel.bin
-sudo vabtool pr_cancel_status 0000:bc:00.0

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/include/opae/access.h b/sw/include/opae/access.h deleted file mode 100644 index 6518ccc8f..000000000 --- a/sw/include/opae/access.h +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright(c) 2017, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** - * @file access.h - * @brief Functions to acquire, release, and reset OPAE FPGA resources - */ - -#ifndef __FPGA_ACCESS_H__ -#define __FPGA_ACCESS_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Open an FPGA object - * - * Acquires ownership of the FPGA resource referred to by 'token'. - * - * Most often this will be used to open an accelerator object to directly interact - * with an accelerator function, or to open an FPGA object to perform - * management functions. - * - * @param[in] token Pointer to token identifying resource to acquire - * ownership of - * @param[out] handle Pointer to preallocated memory to place a handle in. - * This handle will be used in subsequent API calls. - * @param[in] flags One of the following flags: - * * FPGA_OPEN_SHARED allows the resource to be opened - * multiple times (not supported in ASE) - * Shared resources (including buffers) are released - * when all associated handles have been closed - * (either explicitly with fpgaClose() or by process - * termination). - * @returns FPGA_OK on success. FPGA_NOT_FOUND if the resource for - * 'token' could not be found. FPGA_INVALID_PARAM if - * 'token' does not refer to a resource that can be - * opened, or if either argument is NULL or invalid. - * FPGA_EXCEPTION if an internal exception occurred while - * creating the handle. FPGA_NO_DRIVER if the driver is - * not loaded. FPGA_BUSY if trying to open a resource that - * has already been opened in exclusive mode. - * FPGA_NO_ACCESS if the current process' privileges are - * not sufficient to open the resource. - */ -fpga_result fpgaOpen(fpga_token token, fpga_handle *handle, - int flags); - -/** - * Close a previously opened FPGA object - * - * Relinquishes ownership of a previously fpgaOpen()ed resource. This enables - * others to acquire ownership if the resource was opened exclusively. - * Also deallocates / unmaps MMIO and UMsg memory areas. - * - * @param[in] handle Handle to previously opened FPGA object - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if handle does - * not refer to an acquired resource, or if handle is NULL. - * FPGA_EXCEPTION if an internal error occurred while - * accessing the handle. - */ -fpga_result fpgaClose(fpga_handle handle); - -/** - * Reset an FPGA object - * - * Performs an accelerator reset. - * - * @param[in] handle Handle to previously opened FPGA object - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if handle does - * not refer to an acquired resource or to a resource that - * cannot be reset. FPGA_EXCEPTION if an internal error - * occurred while trying to access the handle or resetting - * the resource. - */ -fpga_result fpgaReset(fpga_handle handle); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // __FPGA_ACCESS_H__ diff --git a/sw/include/opae/buffer.h b/sw/include/opae/buffer.h deleted file mode 100644 index bd200cfef..000000000 --- a/sw/include/opae/buffer.h +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright(c) 2017, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** - * @file buffer.h - * @brief Functions for allocating and sharing system memory with an FPGA - * accelerator - * - * To share memory between a software application and an FPGA accelerator, - * these functions set up system components (e.g. an IOMMU) to allow - * accelerator access to a provided memory region. - * - * There are a number of restrictions on what memory can be shared, depending - * on platform capabilities. Usually, FPGA accelerators to not have access to - * virtual address mappings of the CPU, so they can only access physical - * addresses. To support this, the OPAE C library on Linux uses hugepages to - * allocate large, contiguous pages of physical memory that can be shared with - * an accelerator. It also supports sharing memory that has already been - * allocated by an application, as long as that memory satisfies the - * requirements of being physically contigous and page-aligned. - */ - -#ifndef __FPGA_BUFFER_H__ -#define __FPGA_BUFFER_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Prepare a shared memory buffer - * - * Prepares a memory buffer for shared access between an accelerator and the calling - * process. This may either include allocation of physical memory, or - * preparation of already allocated memory for sharing. The latter case is - * indicated by supplying the FPGA_BUF_PREALLOCATED flag. - * - * This function will ask the driver to pin the indicated memory (make it - * non-swappable), and program the IOMMU to allow access from the accelerator. If the - * buffer was not pre-allocated (flag FPGA_BUF_PREALLOCATED), the function - * will also allocate physical memory of the requested size and map the - * memory into the caller's process' virtual address space. It returns in - * 'wsid' an fpga_buffer object that can be used to program address registers - * in the accelerator for shared access to the memory. - * - * When using FPGA_BUF_PREALLOCATED, the input len must be a non-zero multiple - * of the page size, else the function returns FPGA_INVALID_PARAM. When not - * using FPGA_BUF_PREALLOCATED, the input len is rounded up to the nearest - * multiple of page size. - * - * @param[in] handle Handle to previously opened accelerator resource - * @param[in] len Length of the buffer to allocate/prepare in bytes - * @param[inout] buf_addr Virtual address of buffer. Contents may be NULL (OS - * will choose mapping) or non-NULL (OS will take - * contents as a hint for the virtual address). - * @param[out] wsid Handle to the allocated/prepared buffer to be used - * with other functions - * @param[in] flags Flags. FPGA_BUF_PREALLOCATED indicates that memory - * pointed at in '*buf_addr' is already allocated an - * mapped into virtual memory. FPGA_BUF_READ_ONLY - * pins pages with only read access from the FPGA. - * @returns FPGA_OK on success. FPGA_NO_MEMORY if the requested memory could - * not be allocated. FPGA_INVALID_PARAM if invalid parameters were provided, or - * if the parameter combination is not valid. FPGA_EXCEPTION if an internal - * exception occurred while trying to access the handle. - * - * @note As a special case, when FPGA_BUF_PREALLOCATED is present in flags, - * if len == 0 and buf_addr == NULL, then the function returns FPGA_OK if - * pre-allocated buffers are supported. In this case, a return value other - * than FPGA_OK indicates that pre-allocated buffers are not supported. - */ -fpga_result fpgaPrepareBuffer(fpga_handle handle, - uint64_t len, - void **buf_addr, uint64_t *wsid, int flags); - -/** - * Release a shared memory buffer - * - * Releases a previously prepared shared buffer. If the buffer was allocated - * using fpgaPrepareBuffer (FPGA_BUF_PREALLOCATED was not specified), this call - * will deallocate/free that memory. Otherwise, it will only be returned to - * it's previous state (pinned/unpinned, cached/non-cached). - * - * @param[in] handle Handle to previously opened accelerator resource - * @param[in] wsid Handle to the allocated/prepared buffer - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if invalid parameters were - * provided, or if the parameter combination is not valid. FPGA_EXCEPTION if an - * internal exception occurred while trying to access the handle. - */ -fpga_result fpgaReleaseBuffer(fpga_handle handle, uint64_t wsid); - -/** - * Retrieve base IO address for buffer - * - * This function is used to acquire the physical base address (on some platforms - * called IO Virtual Address or IOVA) for a shared buffer identified by wsid. - * - * @note This function will disappear once the APIs for secure sharing of - * buffer addresses is implemented. - * - * @param[in] handle Handle to previously opened accelerator resource - * @param[in] wsid Buffer handle / workspace ID referring to the buffer for - * which the IO address is requested - * @param[out] ioaddr Pointer to memory where the IO address will be returned - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if invalid parameters were - * provided, or if the parameter combination is not valid. FPGA_EXCEPTION if an - * internal exception occurred while trying to access the handle. - * FPGA_NOT_FOUND if `wsid` does not refer to a previously shared buffer. - */ -fpga_result fpgaGetIOAddress(fpga_handle handle, uint64_t wsid, - uint64_t *ioaddr); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // __FPGA_BUFFER_H__ diff --git a/sw/include/opae/cxx/core.h b/sw/include/opae/cxx/core.h deleted file mode 100644 index 458c584a8..000000000 --- a/sw/include/opae/cxx/core.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright(c) 2020, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include diff --git a/sw/include/opae/cxx/core/errors.h b/sw/include/opae/cxx/core/errors.h deleted file mode 100644 index 814b8d35b..000000000 --- a/sw/include/opae/cxx/core/errors.h +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright(c) 2018, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -#pragma once - -#include -#include - -#include - -namespace opae { -namespace fpga { -namespace types { - -/** - * @brief An error object represents an error register for a resource. - * This is used to read out the raw value in the register. No parsing is - * done by this class. - */ -class error { - public: - typedef std::shared_ptr ptr_t; - - error(const error &e) = delete; - - error &operator=(const error &e) = delete; - - /** - * @brief Factory function for creating an error object. - * - * @param tok The token object representing a resource. - * @param num The index of the error register. This must be lower than the - * num_errors property of the resource. - * - * @return A shared_ptr containing the error object - */ - static error::ptr_t get(token::ptr_t tok, uint32_t num); - - /** - * @brief Get the error register name. - * - * @return A std::string object set to the error name. - */ - std::string name() { return error_info_.name; } - - /** - * @brief Indicates whether an error register can be cleared. - * - * @return A boolean value indicating if the error register can be cleared. - */ - bool can_clear() { return error_info_.can_clear; } - - /** - * @brief Read the raw value contained in the associated error register. - * - * @return A 64-bit value (unparsed) read from the error register - */ - uint64_t read_value(); - - ~error() {} - - /** - * @brief Get the C data structure - * - * @return The fpga_error_info that contains the name and the can_clear - * boolean. - */ - fpga_error_info c_type() const { return error_info_; } - - private: - error(token::ptr_t token, uint32_t num); - token::ptr_t token_; - fpga_error_info error_info_; - uint32_t error_num_; -}; - -} // end of namespace types -} // end of namespace fpga -} // end of namespace opae diff --git a/sw/include/opae/cxx/core/events.h b/sw/include/opae/cxx/core/events.h deleted file mode 100644 index 481e31ca2..000000000 --- a/sw/include/opae/cxx/core/events.h +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright(c) 2018, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -#pragma once - -#include -#include - -#include - -namespace opae { -namespace fpga { -namespace types { - -/** - * @brief Wraps fpga event routines in OPAE C - */ -class event { - public: - typedef std::shared_ptr ptr_t; - - /** - * @brief Destroy event and associated resources - */ - virtual ~event(); - - /** - * @brief C++ struct that is interchangeable with fpga_event_type enum - */ - struct type_t { - type_t(fpga_event_type c_type) : type_(c_type) {} - - operator fpga_event_type() { return type_; } - - static constexpr fpga_event_type interrupt = FPGA_EVENT_INTERRUPT; - static constexpr fpga_event_type error = FPGA_EVENT_ERROR; - static constexpr fpga_event_type power_thermal = FPGA_EVENT_POWER_THERMAL; - - private: - fpga_event_type type_; - }; - - /** - * @brief Get the fpga_event_handle contained in this object - * - * @return The fpga_event_handle contained in this object - */ - fpga_event_handle get() { return event_handle_; } - - /** - * @brief Coversion operator for converting to fpga_event_handle objects - * - * @return The fpga_event_handle contained in this object - */ - operator fpga_event_handle(); - - /** - * @brief Factory function to create event objects - * - * @param h A shared ptr of a resource handle - * @param t The resource type - * @param flags Event registration flags passed on to fpgaRegisterEvent - * - * @return A shared ptr to an event object - */ - static event::ptr_t register_event(handle::ptr_t h, event::type_t t, - int flags = 0); - - /** - * @brief Get OS Object from the event object - * - * Get an OS specific object from the event which can be used to subscribe for - * events. On Linux, the object corresponds to a file descriptor that can be - * used with select/poll/epoll calls. - * - * @return An integer object representing the OS object - */ - int os_object() const; - - private: - event(handle::ptr_t h, event::type_t t, fpga_event_handle event_h); - handle::ptr_t handle_; - event::type_t type_; - fpga_event_handle event_handle_; - int os_object_; -}; - -} // end of namespace types -} // end of namespace fpga -} // end of namespace opae diff --git a/sw/include/opae/cxx/core/except.h b/sw/include/opae/cxx/core/except.h deleted file mode 100644 index 36e185a29..000000000 --- a/sw/include/opae/cxx/core/except.h +++ /dev/null @@ -1,340 +0,0 @@ -// Copyright(c) 2018, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -#pragma once -#include - -#include -#include - -namespace opae { -namespace fpga { -namespace types { - -/// Identify a particular line in a source file. -class src_location { - public: - /** src_location constructor - * @param[in] file The source file name, typically __FILE__. - * @param[in] fn The current function, typically __func__. - * @param[in] line The current line number, typically __LINE__. - */ - src_location(const char *file, const char *fn, int line) noexcept; - - src_location(const src_location &other) noexcept; - - src_location &operator=(const src_location &other) noexcept; - - /** Retrieve the file name component of the location. - */ - const char *file() const noexcept; - - /** Retrieve the function name component of the location. - */ - const char *fn() const noexcept { return fn_; } - - /** Retrieve the line number component of the location. - */ - int line() const noexcept { return line_; } - - private: - const char *file_; - const char *fn_; - int line_; -}; - -/// Construct a src_location object for the current source line. -#define OPAECXX_HERE \ - opae::fpga::types::src_location(__FILE__, __func__, __LINE__) - -/** Generic OPAE exception - * - * An except tracks the source line of origin - * and an optional fpga_result. If no fpga_result - * is given, then FPGA_EXCEPTION is used. - */ -class except : public std::exception { - public: - static const std::size_t MAX_EXCEPT = 256; - - /** except constructor - * The fpga_result value is FPGA_EXCEPTION. - * - * @param[in] loc Location where the exception was constructed. - */ - except(src_location loc) noexcept; - - /** except constructor - * - * @param[in] res The fpga_result value associated with this exception. - * @param[in] loc Location where the exception was constructed. - */ - except(fpga_result res, src_location loc) noexcept; - - /** except constructor - * - * @param[in] res The fpga_result value associated with this exception. - * @param[in] msg The error message as a string - * @param[in] loc Location where the exception was constructed. - */ - except(fpga_result res, const char *msg, src_location loc) noexcept; - - /** Convert this except to an informative string. - */ - virtual const char *what() const noexcept override; - - /** Convert this except to its fpga_result. - */ - operator fpga_result() const noexcept { return res_; } - - protected: - fpga_result res_; - const char *msg_; - src_location loc_; - mutable char buf_[MAX_EXCEPT]; -}; - -/** invalid_param exception - * - * invalid_param tracks the source line of origin - * for exceptions thrown when the error code - * FPGA_INVALID_PARAM is returned from a call to - * an OPAE C API function - */ -class invalid_param : public except { - public: - /** invalid_param constructor - * - * @param[in] loc Location where the exception was constructed. - */ - invalid_param(src_location loc) noexcept - : except(FPGA_INVALID_PARAM, "failed with return code FPGA_INVALID_PARAM", - loc) {} -}; - -/** busy exception - * - * busy tracks the source line of origin - * for exceptions thrown when the error code - * FPGA_BUSY is returned from a call to - * an OPAE C API function - */ -class busy : public except { - public: - /** busy constructor - * - * @param[in] loc Location where the exception was constructed. - */ - busy(src_location loc) noexcept - : except(FPGA_BUSY, "failed with return code FPGA_BUSY", loc) {} -}; - -/** exception exception - * - * exception tracks the source line of origin - * for exceptions thrown when the error code - * FPGA_EXCEPTION is returned from a call to - * an OPAE C API function - */ -class exception : public except { - public: - /** exception constructor - * - * @param[in] loc Location where the exception was constructed. - */ - exception(src_location loc) noexcept - : except(FPGA_EXCEPTION, "failed with return code FPGA_EXCEPTION", loc) {} -}; - -/** not_found exception - * - * not_found tracks the source line of origin - * for exceptions thrown when the error code - * FPGA_NOT_FOUND is returned from a call to - * an OPAE C API function - */ -class not_found : public except { - public: - /** not_found constructor - * - * @param[in] loc Location where the exception was constructed. - */ - not_found(src_location loc) noexcept - : except(FPGA_NOT_FOUND, "failed with return code FPGA_NOT_FOUND", loc) {} -}; - -/** no_memory exception - * - * no_memory tracks the source line of origin - * for exceptions thrown when the error code - * FPGA_NO_MEMORY is returned from a call to - * an OPAE C API function - */ -class no_memory : public except { - public: - /** no_memory constructor - * - * @param[in] loc Location where the exception was constructed. - */ - no_memory(src_location loc) noexcept - : except(FPGA_NO_MEMORY, "failed with return code FPGA_NO_MEMORY", loc) {} -}; - -/** not_supported exception - * - * not_supported tracks the source line of origin - * for exceptions thrown when the error code - * FPGA_NOT_SUPPORTED is returned from a call to - * an OPAE C API function - */ -class not_supported : public except { - public: - /** not_supported constructor - * - * @param[in] loc Location where the exception was constructed. - */ - not_supported(src_location loc) noexcept - : except(FPGA_NOT_SUPPORTED, "failed with return code FPGA_NOT_SUPPORTED", - loc) {} -}; - -/** no_driver exception - * - * no_driver tracks the source line of origin - * for exceptions thrown when the error code - * FPGA_NO_DRIVER is returned from a call to - * an OPAE C API function - */ -class no_driver : public except { - public: - /** no_driver constructor - * - * @param[in] loc Location where the exception was constructed. - */ - no_driver(src_location loc) noexcept - : except(FPGA_NO_DRIVER, "failed with return code FPGA_NO_DRIVER", loc) {} -}; - -/** no_daemon exception - * - * no_daemon tracks the source line of origin - * for exceptions thrown when the error code - * FPGA_NO_DAEMON is returned from a call to - * an OPAE C API function - */ -class no_daemon : public except { - public: - /** no_daemon constructor - * - * @param[in] loc Location where the exception was constructed. - */ - no_daemon(src_location loc) noexcept - : except(FPGA_NO_DAEMON, "failed with return code FPGA_NO_DAEMON", loc) {} -}; - -/** no_access exception - * - * no_access tracks the source line of origin - * for exceptions thrown when the error code - * FPGA_NO_ACCESS is returned from a call to - * an OPAE C API function - */ -class no_access : public except { - public: - /** no_access constructor - * - * @param[in] loc Location where the exception was constructed. - */ - no_access(src_location loc) noexcept - : except(FPGA_NO_ACCESS, "failed with return code FPGA_NO_ACCESS", loc) {} -}; - -/** reconf_error exception - * - * reconf_error tracks the source line of origin - * for exceptions thrown when the error code - * FPGA_RECONF_ERROR is returned from a call to - * an OPAE C API function - */ -class reconf_error : public except { - public: - /** reconf_error constructor - * - * @param[in] loc Location where the exception was constructed. - */ - reconf_error(src_location loc) noexcept - : except(FPGA_RECONF_ERROR, "failed with return code FPGA_RECONF_ERROR", - loc) {} -}; - -namespace detail { - -/** typedef function pointer that returns bool if result is FPGA_OK - */ -typedef bool (*exception_fn)(fpga_result, - const opae::fpga::types::src_location &loc); - -/** is_ok is a template function that throws an excpetion of its template - * argument type - * if the result code is not FPGA_OK. Otherwise it returns true. - */ -template -constexpr bool is_ok(fpga_result result, - const opae::fpga::types::src_location &loc) { - return result == FPGA_OK ? true : throw T(loc); -} - -static exception_fn opae_exceptions[12] = { - is_ok, - is_ok, - is_ok, - is_ok, - is_ok, - is_ok, - is_ok, - is_ok, - is_ok, - is_ok}; - -static inline void assert_fpga_ok(fpga_result result, - const opae::fpga::types::src_location &loc) { - if (result > FPGA_OK && result <= FPGA_RECONF_ERROR) - // our exception table above starts at invalid_param with index 0 - // but FPGA_INVALID_PARAM is actually enum 1 - let's account for that - opae_exceptions[result - 1](result, loc); -} - -} // end of namespace detail - -/// Macro to check of result is FPGA_OK -/// If not, throw exception that corresponds -/// to the result code -#define ASSERT_FPGA_OK(r) \ - opae::fpga::types::detail::assert_fpga_ok( \ - r, opae::fpga::types::src_location(__FILE__, __func__, __LINE__)); - -} // end of namespace types -} // end of namespace fpga -} // end of namespace opae diff --git a/sw/include/opae/cxx/core/handle.h b/sw/include/opae/cxx/core/handle.h deleted file mode 100644 index 4c5013201..000000000 --- a/sw/include/opae/cxx/core/handle.h +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright(c) 2018-2021, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -#pragma once -#include -#include -#include - -#include -#include - -namespace opae { -namespace fpga { -namespace types { - -/** An allocated accelerator resource - * - * Represents an accelerator resource that has - * been allocated by OPAE. Depending on the type - * of resource, its register space may be - * read/written using a handle object. - */ -class handle { - public: - typedef std::shared_ptr ptr_t; - - handle(const handle &) = delete; - handle &operator=(const handle &) = delete; - - virtual ~handle(); - - /** Retrieve the underlying OPAE handle. - */ - fpga_handle c_type() const { return handle_; } - - /** Retrieve the underlying OPAE handle. - */ - operator fpga_handle() const { return handle_; } - - /** - * @brief Load a bitstream into an FPGA slot - * - * @param slot The slot number to program - * @param bitstream The bitstream binary data - * @param size The size of the bitstream - * @param flags Flags that control behavior of reconfiguration. - * Value of 0 indicates no flags. FPGA_RECONF_FORCE - * indicates that the bitstream is programmed into - * the slot without checking if the resource is - * currently in use. - * - * @throws invalid_param if the handle is not an FPGA device handle - * or if the other parameters are not valid. - * @throws exception if an internal error is encountered. - * @throws busy if the accelerator for the given slot is in use. - * @throws reconf_error if errors are reported by the driver - * (CRC or protocol errors). - */ - void reconfigure(uint32_t slot, const uint8_t *bitstream, size_t size, - int flags); - - /** - * @brief Read 32 bits from a CSR belonging to a resource associated - * with a handle. - * - * @param[in] offset The register offset - * @param[in] csr_space The CSR space to read from. Default is 0. - * - * @return The 32-bit value read from the CSR - */ - uint32_t read_csr32(uint64_t offset, uint32_t csr_space = 0) const; - - /** - * @brief Write 32 bit to a CSR belonging to a resource associated - * with a handle. - * - * @param[in] offset The register offset. - * @param[in] value The 32-bit value to write to the register. - * @param[in] csr_space The CSR space to read from. Default is 0. - * - */ - void write_csr32(uint64_t offset, uint32_t value, uint32_t csr_space = 0); - - /** - * @brief Read 64 bits from a CSR belonging to a resource associated - * with a handle. - * - * @param[in] offset The register offset - * @param[in] csr_space The CSR space to read from. Default is 0. - * - * @return The 64-bit value read from the CSR - */ - uint64_t read_csr64(uint64_t offset, uint32_t csr_space = 0) const; - - /** - * @brief Write 64 bits to a CSR belonging to a resource associated - * with a handle. - * - * @param[in] offset The register offset. - * @param[in] value The 64-bit value to write to the register. - * @param[in] csr_space The CSR space to read from. Default is 0. - * - */ - void write_csr64(uint64_t offset, uint64_t value, uint32_t csr_space = 0); - - /** - * @brief Write 512 bits to a CSR belonging to a resource associated - * with a handle. - * - * @param[in] offset The register offset. - * @param[in] value Pointer to the 512-bit value to write to the register. - * @param[in] csr_space The CSR space to read from. Default is 0. - * - */ - void write_csr512(uint64_t offset, const void *value, uint32_t csr_space = 0); - - /** Retrieve a pointer to the MMIO region. - * @param[in] offset The byte offset to add to MMIO base. - * @param[in] csr_space The desired CSR space. Default is 0. - * @return MMIO base + offset - */ - uint8_t *mmio_ptr(uint64_t offset, uint32_t csr_space = 0) const; - - /** Open an accelerator resource, given a raw fpga_token - * - * @param[in] token A token describing the accelerator - * resource to be allocated. - * - * @param[in] flags The flags parameter to fpgaOpen(). - * - * @return pointer to the mmio base + offset for the given - * csr space - * - */ - static handle::ptr_t open(fpga_token token, int flags); - - /** Open an accelerator resource, given a token object - * - * @param[in] token A token object describing the - * accelerator resource to be allocated. - * - * @param[in] flags The flags parameter to fpgaOpen(). - * - * @return shared ptr to a handle object - */ - static handle::ptr_t open(token::ptr_t token, int flags); - - /** Reset the accelerator identified by this handle - */ - virtual void reset(); - - /** Close an accelerator resource (if opened) - * - * @return fpga_result indication the result of closing the - * handle or FPGA_EXCEPTION if handle is not opened - * - * @note This is available for explicitly closing a handle. - * The destructor for handle will call close. - */ - fpga_result close(); - - /** Retrieve the token corresponding to this handle - * object. - */ - token::ptr_t get_token() const; - - private: - handle(fpga_handle h); - - fpga_handle handle_; - fpga_token token_; -}; - -} // end of namespace types -} // end of namespace fpga -} // end of namespace opae diff --git a/sw/include/opae/cxx/core/properties.h b/sw/include/opae/cxx/core/properties.h deleted file mode 100644 index 17d045098..000000000 --- a/sw/include/opae/cxx/core/properties.h +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright(c) 2018-2022, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -#pragma once -#include -#include - -#include -#include -#include -#include - -namespace opae { -namespace fpga { -namespace types { - -class token; -class handle; -/** Wraps an OPAE fpga_properties object. - * - * properties are information describing an - * accelerator resource that is identified by - * its token. The properties are used during - * enumeration to narrow the search for an - * accelerator resource, and after enumeration - * to provide the configuration of that - * resource. - */ -class properties { - public: - typedef std::shared_ptr ptr_t; - - /** An empty vector of properties. - * Useful for enumerating based on a - * "match all" criteria. - */ - const static std::vector none; - - properties(const properties &p) = delete; - - properties &operator=(const properties &p) = delete; - - ~properties(); - - /** Get the underlying fpga_properties object. - */ - fpga_properties c_type() const { return props_; } - - /** Get the underlying fpga_properties object. - */ - operator fpga_properties() const { return props_; } - - /** Create a new properties object. - * @return A properties smart pointer. - */ - static properties::ptr_t get(); - - /** Create a new properties object from a guid. - * @param guid_in A guid to set in the properties - * @return A properties smart pointer with its guid initialized to guid_in - */ - static properties::ptr_t get(fpga_guid guid_in); - - /** Create a new properties object from an fpga_objtype. - * @param objtype An object type to set in the properties - * @return A properties smart pointer with its object type set to objtype. - */ - static properties::ptr_t get(fpga_objtype objtype); - - /** Retrieve the properties for a given token object. - * @param[in] t A token identifying the accelerator resource. - * @return A properties smart pointer for the given token. - */ - static properties::ptr_t get(std::shared_ptr t); - - /** Retrieve the properties for a given fpga_token. - * @param[in] t An fpga_token identifying the accelerator resource. - * @return A properties smart pointer for the given fpga_token. - */ - static properties::ptr_t get(fpga_token t); - - /** Retrieve the properties for a given handle object. - * @param[in] h A handle identifying the accelerator resource. - * @return A properties smart pointer for the given handle. - */ - static properties::ptr_t get(std::shared_ptr h); - - private: - properties(bool alloc_props = true); - fpga_properties props_; - - public: - pvalue type; - pvalue num_errors; - pvalue segment; - pvalue bus; - pvalue device; - pvalue function; - pvalue socket_id; - pvalue num_slots; - pvalue bbs_id; - pvalue bbs_version; - pvalue vendor_id; - pvalue device_id; - pvalue subsystem_vendor_id; - pvalue subsystem_device_id; - pvalue model; - pvalue local_memory_size; - pvalue capabilities; - pvalue num_mmio; - pvalue num_interrupts; - pvalue accelerator_state; - pvalue object_id; - pvalue parent; - pvalue interface; - guid_t guid; -}; - -} // end of namespace types -} // end of namespace fpga -} // end of namespace opae diff --git a/sw/include/opae/cxx/core/pvalue.h b/sw/include/opae/cxx/core/pvalue.h deleted file mode 100644 index b8fa2f511..000000000 --- a/sw/include/opae/cxx/core/pvalue.h +++ /dev/null @@ -1,278 +0,0 @@ -// Copyright(c) 2018-2020, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -#pragma once -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -namespace opae { -namespace fpga { -namespace types { - -/** Representation of the guid member of a properties object. - */ -struct guid_t { - /** Construct the guid_t given its containing fpga_properties. - */ - guid_t(fpga_properties *p) : props_(p), is_set_(false) {} - - /** Update the local cached copy of the guid. - */ - void update() { - fpga_result res = fpgaPropertiesGetGUID( - *props_, reinterpret_cast(data_.data())); - ASSERT_FPGA_OK(res); - is_set_ = true; - } - - /** Return a raw pointer to the guid. - * @retval nullptr if the guid could not be queried. - */ - operator uint8_t *() { - update(); - return data_.data(); - } - - /** Return a raw pointer to the guid. - */ - const uint8_t *c_type() const { return data_.data(); } - - /** Assign from fpga_guid - * Sets the guid field of the associated properties - * object using the OPAE properties API. - * @param[in] g The given fpga_guid. - * @return a reference to this guid_t. - */ - guid_t &operator=(fpga_guid g) { - is_set_ = false; - ASSERT_FPGA_OK(fpgaPropertiesSetGUID(*props_, g)); - is_set_ = true; - uint8_t *begin = &g[0]; - uint8_t *end = begin + sizeof(fpga_guid); - std::copy(begin, end, data_.begin()); - return *this; - } - - /** Compare contents with an fpga_guid. - * @retval The result of memcmp of the two objects. - */ - bool operator==(const fpga_guid &g) { - return is_set() && (0 == std::memcmp(data_.data(), g, sizeof(fpga_guid))); - } - - /** Convert a string representation of a guid to binary. - * @param[in] str The guid string. - */ - void parse(const char *str) { - is_set_ = false; - if (0 != uuid_parse(str, data_.data())) { - throw except(OPAECXX_HERE); - } - ASSERT_FPGA_OK(fpgaPropertiesSetGUID(*props_, data_.data())); - is_set_ = true; - } - - /** Send the string representation of the guid_t to the given stream. - */ - friend std::ostream &operator<<(std::ostream &ostr, const guid_t &g) { - fpga_properties props = *g.props_; - fpga_guid guid_value; - fpga_result res; - if ((res = fpgaPropertiesGetGUID(props, &guid_value)) == FPGA_OK) { - char guid_str[84]; - uuid_unparse(guid_value, guid_str); - ostr << guid_str; - } else if (FPGA_NOT_FOUND == res) { - std::cerr << "[guid_t::<<] GUID property not set\n"; - } else { - ASSERT_FPGA_OK(res); - } - return ostr; - } - - /** Tracks whether the cached local copy of the guid is valid. - */ - bool is_set() const { return is_set_; } - - /** Invalidate the cached local copy of the guid. - */ - void invalidate() { is_set_ = false; } - - private: - fpga_properties *props_; - bool is_set_; - std::array data_; -}; - -/** - * @brief Wraps OPAE properties defined in the OPAE C API - * by associating an `fpga_properties` reference - * with the getters and setters defined for a property - * - * @tparam T The type of the property value being wrapped - */ -template -struct pvalue { - /** - * @brief Define getter function as getter_t - * For `char*` types, do not use T* as the second argument - * but instead use T - */ - typedef typename std::conditional< - std::is_same::value, fpga_result (*)(fpga_properties, T), - fpga_result (*)(fpga_properties, T *)>::type getter_t; - - /** - * @brief Define the setter function as setter_t - * - */ - typedef fpga_result (*setter_t)(fpga_properties, T); - - /** - * @brief Define the type of our copy variable - * For `char*` types use std::string as the copy - */ - typedef typename std::conditional::value, - typename std::string, T>::type copy_t; - - pvalue() : props_(0), is_set_(false), get_(nullptr), set_(nullptr), copy_() {} - - /** - * @brief pvalue contructor that takes in a reference to fpga_properties - * and corresponding accessor methods for a property - * - * @param p A reference to an fpga_properties - * @param g The getter function - * @param s The setter function - */ - pvalue(fpga_properties *p, getter_t g, setter_t s) - : props_(p), is_set_(false), get_(g), set_(s), copy_() {} - - /** - * @brief Overload of `=` operator that calls the wrapped setter - * - * @param v The value to set - * - * @return A reference to itself - */ - pvalue &operator=(const T &v) { - is_set_ = false; - ASSERT_FPGA_OK(set_(*props_, v)); - is_set_ = true; - copy_ = v; - return *this; - } - - /** - * @brief Compare a property for equality with a value - * - * @param other The value being compared to - * - * @return Whether or not the property is equal to the value - */ - bool operator==(const T &other) { return is_set() && (copy_ == other); } - - void update() { - ASSERT_FPGA_OK(get_(*props_, ©_)); - is_set_ = true; - } - - /** - * @brief Implicit converter operator - calls the wrapped getter - * - * @return The property value after calling the getter or a default - * value of the value type - */ - operator copy_t() { - update(); - return copy_; - } - - // TODO: Remove this once all properties are tested - fpga_result get_value(T &value) const { return get_(*props_, &value); } - - /** - * @brief Stream overalod operator - * - * @param ostr The output stream - * @param p A reference to a pvalue object - * - * @return The stream operator after streaming the property value - */ - friend std::ostream &operator<<(std::ostream &ostr, const pvalue &p) { - T value; - fpga_properties props = *p.props_; - fpga_result res; - if ((res = p.get_(props, &value)) == FPGA_OK) { - ostr << +(value); - } else if (FPGA_NOT_FOUND == res) { - std::cerr << "property getter returned (" << res << ") " - << fpgaErrStr(res); - } else { - ASSERT_FPGA_OK(res); - } - return ostr; - } - - /** Tracks whether the cached local copy of the pvalue is valid. - */ - bool is_set() const { return is_set_; } - - /** Invalidate the cached local copy of the pvalue. - */ - void invalidate() { is_set_ = false; } - - private: - fpga_properties *props_; - bool is_set_; - getter_t get_; - setter_t set_; - copy_t copy_; -}; - -/** - * @brief Template specialization of `char*` type property updater - * - * @return The result of the property getter function. - */ -template <> -inline void pvalue::update() { - char buf[256]; - ASSERT_FPGA_OK(get_(*props_, buf)); - copy_.assign(buf); - is_set_ = true; -} - -} // end of namespace types -} // end of namespace fpga -} // end of namespace opae diff --git a/sw/include/opae/cxx/core/shared_buffer.h b/sw/include/opae/cxx/core/shared_buffer.h deleted file mode 100644 index f3fd17b1f..000000000 --- a/sw/include/opae/cxx/core/shared_buffer.h +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright(c) 2018, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -#pragma once -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace opae { -namespace fpga { -namespace types { - -/** Host/AFU shared memory blocks - * - * shared_buffer abstracts a memory block that may be shared - * between the host cpu and an accelerator. The block may - * be allocated by the shared_buffer class itself (see allocate), - * or it may be allocated elsewhere and then attached to - * a shared_buffer object via attach. - */ -class shared_buffer { - public: - typedef std::size_t size_t; - typedef std::shared_ptr ptr_t; - - shared_buffer(const shared_buffer &) = delete; - shared_buffer &operator=(const shared_buffer &) = delete; - - /** shared_buffer destructor. - */ - virtual ~shared_buffer(); - - /** shared_buffer factory method - allocate a shared_buffer. - * @param[in] handle The handle used to allocate the buffer. - * @param[in] len The length in bytes of the requested buffer. - * @return A valid shared_buffer smart pointer on success, or an - * empty smart pointer on failure. - */ - static shared_buffer::ptr_t allocate(handle::ptr_t handle, size_t len, - bool read_only = false); - - /** Attach a pre-allocated buffer to a shared_buffer object. - * - * @param[in] handle The handle used to attach the buffer. - * @param[in] base The base of the pre-allocated memory. - * @param[in] len The size of the pre-allocated memory, - * which must be a multiple of the page size. - * @return A valid shared_buffer smart pointer on success, or an - * empty smart pointer on failure. - */ - static shared_buffer::ptr_t attach(handle::ptr_t handle, uint8_t *base, - size_t len, bool read_only = false); - - /** - * @brief Disassociate the shared_buffer object from the resource used to - * create it. If the buffer was allocated using the allocate function then - * the buffer is freed. - */ - void release(); - - /** Retrieve the virtual address of the buffer base. - * - * @note Instances of a shared buffer can only be created using either - * 'allocate' or 'attach' static factory function. Because these - * functions return a shared pointer (std::shared_ptr) to the instance, - * references to an instance are counted automatically by design of the - * shared_ptr class. Calling 'c_type()' function is provided to get access - * to the raw data but isn't used in tracking its reference count. - * Assigning this to a variable should be done in limited scopes as this - * variable can be defined in an outer scope and may outlive the - * shared_buffer object. Once the reference count in the shared_ptr reaches - * zero, the shared_buffer object will be released and deallocated, turning - * any variables assigned from a call to 'c_type()' into dangling pointers. - */ - volatile uint8_t *c_type() const { return virt_; } - - /** Retrieve the handle smart pointer associated with - * this buffer. - */ - handle::ptr_t owner() const { return handle_; } - - /** Retrieve the length of the buffer in bytes. - */ - size_t size() const { return len_; } - - /** Retrieve the underlying buffer's workspace id. - */ - uint64_t wsid() const { return wsid_; } - - /** Retrieve the address of the buffer suitable for - * programming into the accelerator device. - */ - uint64_t io_address() const { return io_address_; } - - /** Write c to each byte location in the buffer. - */ - void fill(int c); - - /** Compare this shared_buffer (the first len bytes) - * to that held in other, using memcmp(). - */ - int compare(ptr_t other, size_t len) const; - - /** Read a T-sized block of memory at the given location. - * @param[in] offset The byte offset from the start of the buffer. - * @return A T from buffer base + offset. - */ - template - T read(size_t offset) const { - if ((offset < len_) && (virt_ != nullptr)) { - return *reinterpret_cast(virt_ + offset); - } else if (offset >= len_) { - throw except(OPAECXX_HERE); - } else { - throw except(OPAECXX_HERE); - } - return T(); - } - - /** Write a T-sized block of memory to the given location. - * @param[in] value The value to write. - * @param[in] offset The byte offset from the start of the buffer. - */ - template - void write(const T &value, size_t offset) { - if ((offset < len_) && (virt_ != nullptr)) { - *reinterpret_cast(virt_ + offset) = value; - } else if (offset >= len_) { - throw except(OPAECXX_HERE); - } else { - throw except(OPAECXX_HERE); - } - } - - protected: - shared_buffer(handle::ptr_t handle, size_t len, uint8_t *virt, uint64_t wsid, - uint64_t io_address); - - handle::ptr_t handle_; - size_t len_; - uint8_t *virt_; - uint64_t wsid_; - uint64_t io_address_; -}; - -} // end of namespace types -} // end of namespace fpga -} // end of namespace opae diff --git a/sw/include/opae/cxx/core/sysobject.h b/sw/include/opae/cxx/core/sysobject.h deleted file mode 100644 index 83316947f..000000000 --- a/sw/include/opae/cxx/core/sysobject.h +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright(c) 2018, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -#pragma once -#include -#include -#include - -#include -#include - -namespace opae { -namespace fpga { -namespace types { - -/** Wraps the OPAE fpga_object primitive. - * sysobject's are created from a call to fpgaTokenGetObject, - * fpgaHandleGetObject, or fpgaObjectGetObject - */ -class sysobject { - public: - typedef std::shared_ptr ptr_t; - - sysobject() = delete; - - sysobject(const sysobject &o) = delete; - - sysobject &operator=(const sysobject &o) = delete; - - /** - * @brief Get a sysobject from a token. This will be read-only. - * - * @param[in] t Token object representing a resource. - * @param[in] name An identifier representing an object belonging to a - * resource represented by the token. - * @param[in] flags Control behavior of object identification and creation. - * FPGA_OBJECT_GLOB is used to indicate that the name should be treated as a - * globbing expression. FPGA_OBJECT_RECURSE_ONE indicates that subobjects be - * created for objects one level down from the object identified by name. - * FPGA_OBJECT_RECURSE_ALL indicates that subobjects be created for all - * objects below the current object identified by name. - * - * @return A shared_ptr to a sysobject instance. - */ - static sysobject::ptr_t get(token::ptr_t t, const std::string &name, - int flags = 0); - - /** - * @brief Get a sysobject from a handle. This will be read-write. - * - * @param[in] h Handle object representing an open resource. - * @param[in] name An identifier representing an object belonging to a - * resource represented by the handle. - * @param[in] flags Control behavior of object identification and creation. - * FPGA_OBJECT_GLOB is used to indicate that the name should be treated as a - * globbing expression. FPGA_OBJECT_RECURSE_ONE indicates that subobjects be - * created for objects one level down from the object identified by name. - * FPGA_OBJECT_RECURSE_ALL indicates that subobjects be created for all - * objects below the current object identified by name. - * - * @return A shared_ptr to a sysobject instance. - */ - static sysobject::ptr_t get(handle::ptr_t h, const std::string &name, - int flags = 0); - - /** - * @brief Get a sysobject from an object. This will be read-write if its - * parent was created from a handle.. - * - * @param[in] name An identifier representing an object belonging to this - * object. - * @param[in] flags Control behavior of object identification and creation. - * FPGA_OBJECT_GLOB is used to indicate that the name should be treated as a - * globbing expression. FPGA_OBJECT_RECURSE_ONE indicates that subobjects be - * created for objects one level down from the object identified by name. - * FPGA_OBJECT_RECURSE_ALL indicates that subobjects be created for all - * objects. Flags are defaulted to 0 meaning no flags. - * - * @return A shared_ptr to a sysobject instance. - */ - sysobject::ptr_t get(const std::string &name, int flags = 0); - - /** - * @brief Get a sysobject from a container object. This will be read-write if - * its parent was created from a handle.. - * - * @param[in] index An index number to get. - * - * @return A shared_ptr to a sysobject instance. - */ - sysobject::ptr_t get(int index); - - virtual ~sysobject(); - - /** - * @brief Get the size (in bytes) of the object. - * - * @return The number of bytes that the object occupies in memory. - */ - uint32_t size() const; - - /** - * @brief Read a 64-bit value from an FPGA object. - * The value is assumed to be in string format and will be parsed. See flags - * below for changing that behavior. - * - * @param[in] flags Flags that control how the object is read - * If FPGA_OBJECT_SYNC is used then object will update its buffered copy - * before retrieving the data. If FPGA_OBJECT_RAW is used, then the data - * will be read as raw bytes into the uint64_t pointer variable. Flags - * are defaulted to 0 meaning no flags. - * - * @return A 64-bit value from the object. - */ - uint64_t read64(int flags = 0) const; - - /** - * @brief Write 64-bit value to an FPGA object. - * The value will be converted to string before writing. See flags below for - * changing that behavior. - * - * @param[in] value The value to write to the object. - * @param[in] flags Flags that control how the object is written - * If FPGA_OBJECT_RAW is used, then the value will be written as raw bytes. - * Flags are defaulted to 0 meaning no flags. - * - * @note This operation will force a sync operation to update its cached - * buffer - */ - void write64(uint64_t value, int flags = 0) const; - - /** - * @brief Get all raw bytes from the object. - * - * @param[in] flags Flags that control how object is read - * If FPGA_OBJECT_SYNC is used then object will update its buffered copy - * before retrieving the data. - * - * @return A vector of all bytes in the object. - */ - std::vector bytes(int flags = 0) const; - - /** - * @brief Get a subset of raw bytes from the object. - * - * @param[in] offset The bytes offset for the start of the returned vector. - * @param[in] size The number of bytes for the returned vector. - * @param[in] flags Flags that control how object is read - * If FPGA_OBJECT_SYNC is used then object will update its buffered copy - * before retrieving the data. - * - * @return A vector of size bytes in the object starting at offset. - */ - std::vector bytes(uint32_t offset, uint32_t size, - int flags = 0) const; - - /** Get the object type (attribute or container) - */ - enum fpga_sysobject_type type() const; - - /** Retrieve the underlying fpga_object primitive. - */ - fpga_object c_type() const { return sysobject_; } - - /** Retrieve the underlying fpga_object primitive. - */ - operator fpga_object() const { return sysobject_; } - - private: - sysobject(fpga_object sysobj, token::ptr_t token, handle::ptr_t hnd); - fpga_object sysobject_; - token::ptr_t token_; - handle::ptr_t handle_; -}; - -} // end of namespace types -} // end of namespace fpga -} // end of namespace opae diff --git a/sw/include/opae/cxx/core/token.h b/sw/include/opae/cxx/core/token.h deleted file mode 100644 index a456e5f4f..000000000 --- a/sw/include/opae/cxx/core/token.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright(c) 2018-2021, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -#pragma once -#include -#include -#include -#include - -#include -#include - -namespace opae { -namespace fpga { -namespace types { - -/** Wraps the OPAE fpga_token primitive. - * token's are created from an enumeration operation - * that uses properties describing an accelerator resource - * as search criteria. - */ -class token { - public: - typedef std::shared_ptr ptr_t; - - /** Obtain a vector of token smart pointers - * for given search criteria. - * @param[in] props The search criteria. - * @return A set of known tokens that match the search. - */ - static std::vector enumerate( - const std::vector& props); - - ~token(); - - /** Retrieve the underlying fpga_token primitive. - */ - fpga_token c_type() const { return token_; } - - /** Retrieve the underlying fpga_token primitive. - */ - operator fpga_token() const { return token_; } - - /** Retrieve the parent token, or an empty pointer - * if there is none. - */ - ptr_t get_parent() const; - - private: - token(fpga_token tok); - - fpga_token token_; - - friend class handle; -}; - -} // end of namespace types -} // end of namespace fpga -} // end of namespace opae diff --git a/sw/include/opae/cxx/core/version.h b/sw/include/opae/cxx/core/version.h deleted file mode 100644 index 4c938e151..000000000 --- a/sw/include/opae/cxx/core/version.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright(c) 2018, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -#pragma once -#include - -#include - -namespace opae { -namespace fpga { -namespace types { - -class version { - public: - /// @brief Get the package version information as a struct - /// - /// @return The package version as an `fpga_version` struct - static fpga_version as_struct(); - - /// @brief Get the package version information as a string - /// - /// @return The package version as an `std::string` object - static std::string as_string(); - - /// @brief Get the package build information as a string - /// - /// @return The package build as an `std::string` object - static std::string build(); -}; - -} // end of namespace types -} // end of namespace fpga -} // end of namespace opae diff --git a/sw/include/opae/enum.h b/sw/include/opae/enum.h deleted file mode 100644 index fd3426f84..000000000 --- a/sw/include/opae/enum.h +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright(c) 2017, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** - * @file enum.h - * @brief APIs for resource enumeration and managing tokens - * - * These APIs are the first step for any application using OPAE to discover - * resources that are present on the system. They allow selective enumeration - * (i.e. getting a list of resources that match a given list of criteria) and - * methods to manage the lifecycle of tokens generated by fpgaEnumerate(). - */ - -#ifndef __FPGA_ENUM_H__ -#define __FPGA_ENUM_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Enumerate FPGA resources present in the system - * - * This call allows the user to query the system for FPGA resources that match - * a certain set of criteria, e.g. all accelerators that are assigned to a host - * interface and available, all FPGAs of a specific type, etc. - * - * fpgaEnumerate() will create a number of `fpga_token`s to represent the - * matching resources and populate the array `tokens` with these tokens. The - * `max_tokens` argument can be used to limit the number of tokens - * allocated/returned by fpgaEnumerate(); i.e., the number of tokens in the - * returned `tokens` array will be either `max_tokens` or `num_matches` (the - * number of resources matching the filter), whichever is smaller. Use - * fpgaDestroyToken() to destroy tokens that are no longer needed. - * - * To query the number of matches for a particular set of filters (e.g. to - * allocate a `tokens` array of the appropriate size), call fpgaEnumerate() - * with the parameter `tokens` set to NULL; this will only return the number of - * matches in `num_matches`. - * - * @note fpgaEnumerate() will allocate memory for the created tokens returned - * in `tokens`. It is the responsibility of the using application to free this - * memory after use by calling fpgaDestroyToken() for each of the returned - * tokens. - * - * @param[in] filters Array of `fpga_properties` objects describing the - * properties of the objects that should be returned. A - * resource is considered matching if its properties - * match any one of the supplied filters. To match all - * FPGA resources, pass an empty filters object (one - * without any filter criteria set) or pass a NULL - * filters parameter with num_filters set to 0. - * @param[in] num_filters Number of entries in the `filters` array, or 0 to - * match all FPGA resources when `filters` is NULL. - * @param[out] tokens Pointer to an array of fpga_token variables to be - * populated. If NULL is supplied, fpgaEnumerate() will - * not create any tokens, but it will return the - * number of possible matches in `num_match`. - * @param[in] max_tokens Maximum number of tokens that fpgaEnumerate() shall - * return (length of `tokens` array). There may be more - * or fewer matches than this number; `num_matches` is - * set to the number of actual matches. - * @param[out] num_matches Number of resources matching the `filter` criteria. - * This number can be higher than the number of tokens - * returned in the `tokens` array (depending on the - * value of `max_tokens`). - * @returns FPGA_OK on success. - * FPGA_INVALID_PARAM if invalid pointers or objects - * are passed into the function. - * FPGA_NO_DRIVER if OPAE can't find the respective - * enumeration data structures usually provided by the - * driver. - * FPGA_NO_MEMORY if there was not enough memory to - * create tokens. - */ -fpga_result fpgaEnumerate(const fpga_properties *filters, - uint32_t num_filters, fpga_token *tokens, - uint32_t max_tokens, uint32_t *num_matches); - -/** - * Clone a fpga_token object - * - * Creates a copy of an fpga_token object. - * - * @note This call creates a new token object and allocates memory for it. It - * is the responsibility of the using application to free this memory after use - * by calling fpgaDestroyToken() for the cloned token. - * - * @param[in] src fpga_token object to copy - * @param[out] dst New fpga_token object cloned from 'src' - * @returns FPGA_OK on success - */ -fpga_result fpgaCloneToken(fpga_token src, fpga_token *dst); - -/** - * Destroy a Token - * - * This function destroys a token created by fpgaEnumerate() and frees the - * associated memory. - * - * @note fpgaDestroyToken() requires the address of an fpga_token as - * previously created by fpgaEnumerate() or fpgaCloneToken(). Passing - * any other value results in undefined behavior. - * - * @param[in] token fpga_token to destroy - * @returns FPGA_OK on success - */ -fpga_result fpgaDestroyToken(fpga_token *token); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // __FPGA_ENUM_H__ - diff --git a/sw/include/opae/error.h b/sw/include/opae/error.h deleted file mode 100644 index 7802a576f..000000000 --- a/sw/include/opae/error.h +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright(c) 2018, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** - * @file error.h - * @brief Functions for reading and clearing errors in resources - * - * Many FPGA resources have the ability to track the occurrence of errors. - * This file provides functions to retrieve information about errors within - * resources. - */ - -#ifndef __FPGA_ERROR_H__ -#define __FPGA_ERROR_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * Read error value - * - * This function will read the value of error register `error_num` of - * the resource referenced by `token` into the memory location pointed to - * by `value`. - * - * @param[in] token Token to accelerator resource to query - * @param[in] error_num Number of error register to read - * @param[out] value Pointer to memory to store error value into (64 bit) - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if any of the supplied - * parameters is invalid. FPGA_EXCEPTION if an internal exception occurred - * while trying to access the token. - */ -fpga_result fpgaReadError(fpga_token token, uint32_t error_num, uint64_t *value); - -/** - * Clear error register - * - * This function will clear the error register `error_num` of the resource - * referenced by `token`. - * - * @param[in] token Token to accelerator resource to query - * @param[in] error_num Number of error register to clear - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if any of the supplied - * parameters is invalid. FPGA_EXCEPTION if an internal exception occurred - * while trying to access the token, and FPGA_BUSY if error could not be - * cleared. - */ -fpga_result fpgaClearError(fpga_token token, uint32_t error_num); - -/** - * Clear all error registers of a particular resource - * - * This function will clear all error registers of the resource referenced by - * `token`, observing the necessary order of clearing errors, if any. - * - * @param[in] token Token to accelerator resource to query - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if any of the supplied - * parameters is invalid. FPGA_EXCEPTION if an internal exception occurred - * while trying to access the token, and FPGA_BUSY if error could not be - * cleared. - */ -fpga_result fpgaClearAllErrors(fpga_token token); - -/** - * Get information about a particular error register - * - * This function will populate a `fpga_error_info` struct with information - * about error number `error_num` of the resource referenced by `token`. - * - * @param[in] token Token to accelerator resource to query - * @param[in] error_num Error register to retrieve information about - * @param[out] error_info Pointer to memory to store information into - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if any of the supplied - * parameters is invalid. FPGA_EXCEPTION if an internal exception occurred - * while trying to access the token. - */ -fpga_result fpgaGetErrorInfo(fpga_token token, - uint32_t error_num, - struct fpga_error_info *error_info); - - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // __FPGA_ERROR_H__ diff --git a/sw/include/opae/event.h b/sw/include/opae/event.h deleted file mode 100644 index f755c61df..000000000 --- a/sw/include/opae/event.h +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright(c) 2017, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** - * @file event.h - * @brief Functions for registering events and managing the lifecycle for - * `fpga_event_handle`s. - * - * OPAE provides an interface to asynchronous events that can be generated by - * different FPGA resources. The event API provides functions to register for - * these events; associated with every event a process has registered for is an - * fpga_event_handle, which encapsulates the OS-specific data structure for - * event objects. On Linux, an fpga_event_handle can be used as a file - * descriptor and passed to select(), poll(), epoll() and similar functions to - * wait for asynchronous events. - */ - -#ifndef __FPGA_EVENT_H__ -#define __FPGA_EVENT_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Initialize an event_handle - * - * Platform independent way to initialize an event_handle used for - * notifications from the driver to application. For Linux, this function - * creates an eventfd and returns the eventfd file descriptor in - * `*event_handle`. - * - * @param[out] event_handle Pointer to event handle variable. - * - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if `event_handle` is NULL. - * FPGA_NOT_SUPPORTED if platform does not support events. - */ -fpga_result fpgaCreateEventHandle(fpga_event_handle *event_handle); - -/** - * Destroy an event_handle - * - * Destroy handle and free resources. On Linux this corresponds - * to closing the file descriptor pointed to by handle - * - * @note fpgaDestroyEventHandle() requires the address of an - * event_handle as created by fpgaCreateEventHandle(). Passing - * any other value results in undefined behavior. - * - * @param[in] event_handle Pointer to handle to be destroyed - * - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if `event_handle` is NULL. - */ -fpga_result fpgaDestroyEventHandle(fpga_event_handle *event_handle); - - -/** - * Get OS object from event handle - * - * Check validity of event handle, and get the OS object used to - * subscribe and unsubscribe to events. On Linux, the object corresponds - * to a file descriptor. - * - * @param[in] eh Event handle to get the descriptor value from - * @param[out] fd integer to store the descriptor value - * - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if `event_handle` is invalid. - */ -fpga_result fpgaGetOSObjectFromEventHandle(const fpga_event_handle eh, int *fd); - -/** - * Register an FPGA event - * - * This function tells the driver that the caller is interested in notification - * for the event specified by the type and flags pair. - * - * The event_handle points to an OS specific mechanism for event notification. - * An event_handle is associated with only a single event. - * - * In case of user interrupts, the flags parameter will be used to specify - * the vector ID. The value of the flags parameter indicates the vector ID, - * no bit encoding is used. - * - * @todo define if calling fpgaRegisterEvent multiple times with the - * same event_handle is an error condition or if it is silently ignored. - * - * @param[in] handle Handle to previously opened FPGA resource. - * @param[in] event_type Type of event - * @param[in] event_handle Handle to previously opened resource for event - * notification. - * @param[in] flags Optional argument for specifying additional - * information about event. For example irq number - * for interrupt events. - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if handle does not refer to - * a resource supporting the requested event, or if event_handle is not valid. - * FPGA_EXCEPTION if an internal exception occurred while accessing the handle - * or the event_handle. On Linux: FPGA_NO_DAEMON if the driver does not support - * the requested event and there is no FPGA Daemon (fpgad) running to proxy it. - */ -fpga_result fpgaRegisterEvent(fpga_handle handle, - fpga_event_type event_type, - fpga_event_handle event_handle, - uint32_t flags); - -/** - * Unregister an FPGA event - * - * This function tells the driver that the caller is no longer interested in - * notification for the event associated with the event_handle - * - * The event_handle points to an OS specific mechanism for event notification. - * An event_handle is associated with only a single event. - * - * @todo define if calling fpgaUnregisterEvent multiple times with the - * same event_handle is an error condition or if it is silently ignored. - * - * @param[in] handle Handle to previously opened FPGA resource. - * @param[in] event_type Type of event to unregister. - * @param[in] event_handle Handle to previously registered resource for event - * notification. - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if handle does - * not refer to a resource supporting the requested event, - * or if event_handle is not valid. FPGA_EXCEPTION if an - * internal error occurred accessing the handle or the - * event_handle. - */ -fpga_result fpgaUnregisterEvent(fpga_handle handle, - fpga_event_type event_type, - fpga_event_handle event_handle); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // __FPGA_EVENT_H__ diff --git a/sw/include/opae/fpga.h b/sw/include/opae/fpga.h deleted file mode 100644 index 2b020325a..000000000 --- a/sw/include/opae/fpga.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright(c) 2017, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** - * \file fpga.h - * \brief FPGA API - * - * This conveniently includes all APIs that a part of the OPAE release (base and - * extensions). - */ - -#ifndef __FPGA_FPGA_H__ -#define __FPGA_FPGA_H__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif // __FPGA_FPGA_H__ - diff --git a/sw/include/opae/hash_map.h b/sw/include/opae/hash_map.h deleted file mode 100644 index 414e98eac..000000000 --- a/sw/include/opae/hash_map.h +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright(c) 2022-2023, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** - * @file opae/hash_map.h - * @brief A general-purpose hybrid array/list hash map implementation. - * - * Presents a generic interface for mapping key objects to value objects. - * Both keys and values may be arbitrary data structures. The user supplies - * the means by which the hash of values is generated and by which the - * keys are compared to each other. - */ - -#ifndef __OPAE_HASH_MAP_H__ -#define __OPAE_HASH_MAP_H__ -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -/** Flags used to initialize a hash map. - * - * OPAE_HASH_MAP_UNIQUE_KEYSPACE says that the user provides - * a guarantee that the key space is truly unique. In other words, when - * the provided hash function for keys A and B returns the same bucket - * index, the key comparison function when comparing A and B will never - * return a result saying that the keys are equal in value. This is helpful - * in situations where the key space is guaranteed to produce unique values, - * for example a memory allocator. When the key space is guaranteed to be - * unique, opae_hash_map_add() can implement a small performance improvement. - */ -typedef enum _opae_hash_map_flags { - OPAE_HASH_MAP_UNIQUE_KEYSPACE = (1u << 0) -} opae_hash_map_flags; - -/** - * List link item. - * - * This structure provides the association between key and value. - * When the supplied hash function for keys A and B returns the same - * bucket index, both A and B can co-exist on the same list rooted - * at the bucket index. - */ -typedef struct _opae_hash_map_item { - void *key; - void *value; - struct _opae_hash_map_item *next; -} opae_hash_map_item; - -/** - * Hash map object. - * - * This structure defines the internals of the hash map. Each of the - * parameters supplied to opae_hash_map_init() is stored in the structure. - * All parameters are required, except key_cleanup and value_cleanup, - * which may optionally be NULL. - */ -typedef struct _opae_hash_map { - uint32_t num_buckets; - uint32_t hash_seed; - opae_hash_map_item **buckets; - int flags; - void *cleanup_context; ///< Optional second parameter to key_cleanup and value_cleanup - uint32_t (*key_hash)(uint32_t num_buckets, ///< (required) - uint32_t hash_seed, - void *key); - int (*key_compare)(void *keya, void *keyb); ///< (required) - void (*key_cleanup)(void *key, void *context); ///< (optional) - void (*value_cleanup)(void *value, void *context); ///< (optional) -} opae_hash_map; - -/** - * Initialize a hash map - * - * Populates the hash map data structure and allocates the buckets - * array. - * - * @param[out] hm A pointer to the storage for the hash map object. - * @param[in] num_buckets The desired size of the buckets array. Each array - * entry may be empty (NULL), or may contain a list - * of opae_hash_map_item structures for which the given - * key_hash function returned the same key hash value. - * @param[in] hash_seed A seed value used during key hash computation. This - * value will be the hash_seed parameter to the key hash - * function. - * @param[in] flags Initialization flags. See opae_hash_map_flags. - * @param[in] key_hash A pointer to a function that produces the hash value, - * given the number of buckets, the hash seed, and the key. - * Valid values are between 0 and num_buckets - 1, inclusively. - * @param[in] key_compare A pointer to a function that compares two keys. The return - * value is similar to that of strcmp(), where a negative value - * means that keya < keyb, 0 means that keya == keyb, and a positive - * values means that keya > keyb. - * @param[in] key_cleanup A pointer to a function that is called when a key is being - * removed from the map. This function is optional and may be - * NULL. When supplied, the function is responsible for freeing - * any resources allocated when the key was created. - * @param[in] value_cleanup A pointer to a function that is called when a value is - * being removed from the map. This function is optional and may - * be NULL. When supplied, the function is responsible for freeing - * any resources allocated when the value was created. - * @returns FPGA_OK on success, FPGA_INVALID_PARAM if any of the required parameters are - * NULL, or FPGA_NO_MEMORY if the bucket array could not be allocated. - */ -fpga_result opae_hash_map_init(opae_hash_map *hm, - uint32_t num_buckets, - uint32_t hash_seed, - int flags, - uint32_t (*key_hash)(uint32_t num_buckets, - uint32_t hash_seed, - void *key), - int (*key_compare)(void *keya, void *keyb), - void (*key_cleanup)(void *key, void *context), - void (*value_cleanup)(void *value, void *context)); - -/** - * Map a key to a value - * - * Inserts a mapping from key to value in the given hash map object. - * Subsequent calls to opae_hash_map_find() that are given the key - * will retrieve the value. - * - * @param[in, out] hm A pointer to the storage for the hash map object. - * @param[in] key The hash map key. - * @param[in] value The hash map value. - * @returns FPGA_OK on success, FPGA_INVALID_PARAM if hm is NULL, FPGA_NO_MEMORY - * if malloc() fails when allocating the list item, or FPGA_INVALID_PARAM - * if the key hash produced by key_hash is out of bounds. - */ -fpga_result opae_hash_map_add(opae_hash_map *hm, - void *key, - void *value); - -/** - * Retrieve the value for a given key - * - * Given a key that was previously passed to opae_hash_map_add(), retrieve - * its associated value. - * - * @param[in] hm A pointer to the storage for the hash map object. - * @param[in] key The hash map key. - * @param[in] value A pointer to receive the hash map value. - * @returns FPGA_OK on success, FPGA_INVALID_PARAM if hm is NULL or if the - * key hash produced by key_hash is out of bounds, or FPGA_NOT_FOUND - * if the given key was not found in the hash map. - */ -fpga_result opae_hash_map_find(opae_hash_map *hm, - void *key, - void **value); - -/** - * Remove a key/value association - * - * Given a key that was previously passed to opae_hash_map_add(), remove the - * key and its associated value, calling the cleanup functions as needed. - * - * @param[in, out] hm A pointer to the storage for the hash map object. - * @param[in] key The hash map key. - * @returns FPGA_OK on success, FPGA_INVALID_PARAM when hm is NULL or when the - * key hash produced by key_hash is out of bounds, or FPGA_NOT_FOUND if - * the key is not found in the hash map. - */ -fpga_result opae_hash_map_remove(opae_hash_map *hm, - void *key); - -/** - * Tear down a hash map - * - * Given a hash map that was previously initialized by opae_hash_map_init(), - * destroy the hash map, releasing all keys, values, and the bucket array. - * - * @param[in, out] hm A pointer to the storage for the hash map object. - * @returns FPGA_OK on success or FPGA_INVALID_PARAM is hm is NULL. - */ -fpga_result opae_hash_map_destroy(opae_hash_map *hm); - -/** - * Determine whether a hash map is empty - * - * @param[in] hm A pointer to the storage for the hash map object. - * @returns true if there are no key/value mappings present, false - * otherwise. - */ -bool opae_hash_map_is_empty(opae_hash_map *hm); - -/** - * Convenience hash function for arbitrary pointers/64-bit values. - * - * Simply converts the key to a uint64_t and then performs the - * modulus operation with the configured num_buckets. hash_seed is - * unused. - */ -uint32_t opae_u64_key_hash(uint32_t num_buckets, - uint32_t hash_seed, - void *key); - -/** - * Convenience key comparison function for 64-bit values. - * - * Simply converts the key pointers to uint64_t's and performs - * unsigned integer comparison. - */ -int opae_u64_key_compare(void *keya, void *keyb); - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __OPAE_HASH_MAP_H__ diff --git a/sw/include/opae/init.h b/sw/include/opae/init.h deleted file mode 100644 index 9f45d05ac..000000000 --- a/sw/include/opae/init.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright(c) 2018, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** - * \file init.h - * \brief Initialization routine. - */ - -#ifndef __FPGA_INIT_H__ -#define __FPGA_INIT_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Initialize the OPAE library. - * - * Initialize OPAE using the given configuration file path, or - * perform default initialization if config_file is NULL. - * - * @param[in] config_file Path to OPAE configuration file. - * @returns Whether OPAE initialized successfully. - */ -fpga_result fpgaInitialize(const char *config_file); - -/** - * Finalize the OPAE library. - * - * @returns Whether OPAE finalized successfully. - */ -fpga_result fpgaFinalize(void); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // __FPGA_INIT_H__ - diff --git a/sw/include/opae/log.h b/sw/include/opae/log.h deleted file mode 100644 index 1b4ab5199..000000000 --- a/sw/include/opae/log.h +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright(c) 2018-2021, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#ifndef __OPAE_LOG_H__ -#define __OPAE_LOG_H__ - -#include -#include -#include -#include - -#include - -/* -* Convenience macros for printing messages and errors. -*/ -#ifdef __SHORT_FILE__ -#undef __SHORT_FILE__ -#endif // __SHORT_FILE__ -#define __SHORT_FILE__ \ - ({ \ - const char *file = __FILE__; \ - const char *p = file; \ - while (*p) \ - ++p; \ - while ((p > file) && ('/' != *p) && ('\\' != *p)) \ - --p; \ - if (p > file) \ - ++p; \ - p; \ - }) - -#ifdef OPAE_MSG -#undef OPAE_MSG -#endif // OPAE_MSG -#define OPAE_MSG(format, ...) \ - opae_print(OPAE_LOG_MESSAGE, "%s:%u:%s() : " format "\n", \ - __SHORT_FILE__, __LINE__, __func__, ##__VA_ARGS__) - -#ifdef OPAE_ERR -#undef OPAE_ERR -#endif // OPAE_ERR -#define OPAE_ERR(format, ...) \ - opae_print(OPAE_LOG_ERROR, \ - "%s:%u:%s() **ERROR** : " format "\n", \ - __SHORT_FILE__, __LINE__, __func__, ##__VA_ARGS__) - -#ifdef OPAE_DBG -#undef OPAE_DBG -#endif // OPAE_DBG -#ifdef LIBOPAE_DEBUG -#define OPAE_DBG(format, ...) \ - opae_print(OPAE_LOG_DEBUG, \ - "%s:%u:%s() *DEBUG* : " format "\n", \ - __SHORT_FILE__, __LINE__, __func__, ##__VA_ARGS__) -#else -#define OPAE_DBG(format, ...) \ -{ } -#endif // LIBOPAE_DEBUG - -/* -* Logging functions -*/ -enum opae_loglevel { - OPAE_LOG_ERROR = 0, /* critical errors (always print) */ - OPAE_LOG_MESSAGE, /* information (i.e. explain return code */ - OPAE_LOG_DEBUG /* debugging (also needs #define DEBUG 1) */ -}; - -#define OPAE_DEFAULT_LOGLEVEL OPAE_LOG_ERROR - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -void opae_print(int loglevel, const char *fmt, ...); - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __OPAE_LOG_H__ diff --git a/sw/include/opae/manage.h b/sw/include/opae/manage.h deleted file mode 100644 index 12ae211ec..000000000 --- a/sw/include/opae/manage.h +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright(c) 2017, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** - * @file manage.h - * @brief Functions for managing FPGA configurations - * - * FPGA accelerators can be reprogrammed at run time by providing new partial - * bitstreams ("green bitstreams"). This file defines API functions for - * programming green bitstreams as well as for assigning accelerators to host - * interfaces for more complex deployment setups, such as virtualized systems. - */ - -#ifndef __FPGA_MANAGE_H__ -#define __FPGA_MANAGE_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** -* Assign Port to a host interface. -* -* This function assign Port to a host interface for subsequent use. Only -* Port that have been assigned to a host interface can be opened by -* fpgaOpen(). -* -* @param[in] fpga Handle to an FPGA object previously opened that -* both the host interface and the slot belong to -* @param[in] interface_num Host interface number -* @param[in] slot_num Slot number -* @param[in] flags Flags (to be defined) -* @returns FPGA_OK on success -* FPGA_INVALID_PARAM if input parameter combination -* is not valid. -* FPGA_EXCEPTION if an exception occcurred accessing -* the `fpga` handle. -* FPGA_NOT_SUPPORTED if driver does not support -* assignment. -*/ -fpga_result fpgaAssignPortToInterface(fpga_handle fpga, - uint32_t interface_num, - uint32_t slot_num, - int flags); - -/** - * Assign an accelerator to a host interface - * - * This function assigns an accelerator to a host interface for subsequent use. Only - * accelerators that have been assigned to a host interface can be opened by - * fpgaOpen(). - * - * @note This function is currently not supported. - * - * @param[in] fpga Handle to an FPGA object previously opened that - * both the host interface and the accelerator belong to - * @param[in] accelerator accelerator to assign - * @param[in] host_interface Host interface to assign accelerator to - * @param[in] flags Flags (to be defined) - * @returns FPGA_OK on success - */ -fpga_result fpgaAssignToInterface(fpga_handle fpga, - fpga_token accelerator, - uint32_t host_interface, - int flags); - -/** - * Unassign a previously assigned accelerator - * - * This function removes the assignment of an accelerator to an host interface (e.g. to - * be later assigned to a different host interface). As a consequence, the accelerator - * referred to by token 'accelerator' will be reset during the course of this function. - * - * @note This function is currently not supported. - * - * @param[in] fpga Handle to an FPGA object previously opened that - * both the host interface and the accelerator belong to - * @param[in] accelerator accelerator to unassign/release - * @returns FPGA_OK on success - */ -fpga_result fpgaReleaseFromInterface(fpga_handle fpga, - fpga_token accelerator); - -/** - * Reconfigure a slot - * - * Sends a green bitstream file to an FPGA to reconfigure a specific slot. This - * call, if successful, will overwrite the currently programmed AFU in that - * slot with the AFU in the provided bitstream. - * - * As part of the reconfiguration flow, all accelerators associated with this slot will - * be unassigned and reset. - * - * @param[in] fpga Handle to an FPGA object previously opened - * @param[in] slot Token identifying the slot to reconfigure - * @param[in] bitstream Pointer to memory holding the bitstream - * @param[in] bitstream_len Length of the bitstream in bytes - * @param[in] flags Flags that control behavior of reconfiguration. - * Value of 0 indicates no flags. FPGA_RECONF_FORCE - * indicates that the bitstream is programmed into - * the slot without checking if the resource is - * currently in use. - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if the provided parameters - * are not valid. FPGA_EXCEPTION if an internal error occurred accessing the - * handle or while sending the bitstream data to the driver. FPGA_BUSY if the - * accelerator for the given slot is in use. FPGA_RECONF_ERROR on errors - * reported by the driver (such as CRC or protocol errors). - * - * @note By default, fpgaReconfigureSlot will not allow reconfiguring a slot - * with an accelerator in use. Add the flag FPGA_RECONF_FORCE to force - * reconfiguration without checking for accelerators in use. - */ -fpga_result fpgaReconfigureSlot(fpga_handle fpga, - uint32_t slot, - const uint8_t *bitstream, - size_t bitstream_len, int flags); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // __FPGA_MANAGE_H__ - diff --git a/sw/include/opae/mem_alloc.h b/sw/include/opae/mem_alloc.h deleted file mode 100644 index 5b53db648..000000000 --- a/sw/include/opae/mem_alloc.h +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright(c) 2020, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -#ifndef __OPAE_MEM_ALLOC_H__ -#define __OPAE_MEM_ALLOC_H__ - -/** -* Provides an API for allocating/freeing a logical address space. There -* is no interaction with any OS memory allocation infrastructure, whether -* malloc, mmap, etc. The "address ranges" tracked by this allocator are -* arbitrary 64-bit integers. The allocator simply provides the bookeeping -* logic that ensures that a unique address with the appropriate size is -* returned for each allocation request, and that an allocation can be freed, -* ie released back to the available pool of logical address space for future -* allocations. The memory backing the allocator's internal data structures -* is managed by malloc()/free(). -*/ - -#include - -struct mem_link { - uint64_t address; - uint64_t size; - struct mem_link *prev; - struct mem_link *next; -}; - -struct mem_alloc { - struct mem_link free; - struct mem_link allocated; -}; - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -/** - * Initialize a memory allocator object - * - * After the call, the allocator is initialized but "empty". To add - * allocatable memory regions, further initialize the allocator with - * mem_alloc_add_free(). - * - * @param[out] m The address of the memory allocator to initialize. - */ -void mem_alloc_init(struct mem_alloc *m); - -/** - * Destroy a memory allocator object - * - * Frees all of the allocator's internal resources. - * - * @param[in] m The address of the memory allocator to destroy. - */ -void mem_alloc_destroy(struct mem_alloc *m); - -/** - * Add a memory region to an allocator. - * - * The memory region is added to the allocatable space and is - * immediately ready for allocation. - * - * @param[in, out] m The memory allocator object. - * @param[in] address The beginning address of the memory region. - * @param[in] size The size of the memory region. - * @returns Non-zero on error. Zero on success. - * - * Example - * @code{.c} - * struct mem_alloc m; - * - * mem_alloc_init(&m); - * - * if (mem_alloc_add_free(&m, 0x4000, 4096)) { - * // handle error - * } - * @endcode - */ -int mem_alloc_add_free(struct mem_alloc *m, - uint64_t address, - uint64_t size); - -/** Allocate memory - * - * Retrieve an available memory address for a free block - * that is at least size bytes. - * - * @param[in, out] m The memory allocator object. - * @param[out] address The retrieved address for the allocation. - * @param[in] size The request size in bytes. - * @returns Non-zero on error. Zero on success. - * - * Example - * @code{.c} - * struct mem_alloc m; - * uint64_t addr = 0; - * - * mem_alloc_init(&m); - * - * if (mem_alloc_add_free(&m, 0x4000, 4096)) { - * // handle error - * } - * - * ... - * - * if (mem_alloc_get(&m, &addr, 4096)) { - * // handle allocation error - * } - * @endcode - */ -int mem_alloc_get(struct mem_alloc *m, - uint64_t *address, - uint64_t size); - -/** Free memory - * - * Release a previously-allocated memory block. - * - * @param[in, out] m The memory allocator object. - * @param[in] address The address to free. - * @returns Non-zero on error. Zero on success. - * - * Example - * @code{.c} - * struct mem_alloc m; - * uint64_t addr = 0; - * - * mem_alloc_init(&m); - * - * if (mem_alloc_add_free(&m, 0x4000, 4096)) { - * // handle error - * } - * - * ... - * - * if (mem_alloc_get(&m, &addr, 4096)) { - * // handle allocation error - * } - * - * ... - * - * if (mem_alloc_put(&m, addr)) { - * // handle free error - * } - * @endcode - */ -int mem_alloc_put(struct mem_alloc *m, - uint64_t address); - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __OPAE_MEM_ALLOC_H__ diff --git a/sw/include/opae/metrics.h b/sw/include/opae/metrics.h deleted file mode 100644 index c83d3278b..000000000 --- a/sw/include/opae/metrics.h +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright(c) 2018, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** -* @file metrics.h -* @brief Functions for Discover/ Enumerates metrics and retrieves values -* -* -* -* -*/ - -#ifndef __FPGA_METRICS_H__ -#define __FPGA_METRICS_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Enumerates number of metrics - * - * @param[in] handle Handle to previously opened fpga resource - * @param[inout] num_metrics Number of metrics are discovered in - * fpga resource - * - * @returns FPGA_OK on success. FPGA_NOT_FOUND if the Metrics are not - * discovered - * - */ -fpga_result fpgaGetNumMetrics(fpga_handle handle, - uint64_t *num_metrics); - -/** - * Retrieve metrics information - * - * @param[in] handle Handle to previously opened fpga resource - * @param[inout] metric_info Pointer to array of metric info struct - * user allocates metrics info array - * - * @param[inout] num_metrics Size of metric info array - * - * @returns FPGA_OK on success. FPGA_NOT_FOUND if the Metrics are not - * found. FPGA_NO_MEMORY if there was not enough memory to enumerates - * metrics. - * - */ -fpga_result fpgaGetMetricsInfo(fpga_handle handle, - fpga_metric_info *metric_info, - uint64_t *num_metrics); - -/** - * Retrieve metrics values by index - * - * @param[in] handle Handle to previously opened fpga resource - * @param[inout] metric_num Pointer to array of metric index - * user allocates metric array - * @param[inout] num_metric_indexes Size of metric array - * @param[inout] metrics pointer to array of metric struct - * - * @returns FPGA_OK on success. FPGA_NOT_FOUND if the Metrics are not - * found. FPGA_NO_MEMORY if there was not enough memory to enumerates - * metrics. - * - */ -fpga_result fpgaGetMetricsByIndex(fpga_handle handle, - uint64_t *metric_num, - uint64_t num_metric_indexes, - fpga_metric *metrics); - -/** - * Retrieve metric values by names - * - * @param[in] handle Handle to previously opened fpga resource - * @param[inout] metrics_names Pointer to array of metrics name - * user allocates metrics name array - * @param[inout] num_metric_names Size of metric name array - * @param[inout] metrics Pointer to array of metric struct - * - * @returns FPGA_OK on success. FPGA_NOT_FOUND if the Metrics are not - * found - * - */ -fpga_result fpgaGetMetricsByName(fpga_handle handle, - char **metrics_names, - uint64_t num_metric_names, - fpga_metric *metrics); - - -/** - * Retrieve metrics / sendor threshold information and values - * - * @param[in] handle Handle to previously opened fpga resource - * @param[inout] metrics_threshold pointer to array of metric thresholds - * user allocates threshold array memory - * Number of thresholds returns enumerated thresholds if user pass - * NULL metrics_thresholds - * @param[inout] num_thresholds number of thresholds - * - * - * @returns FPGA_OK on success. FPGA_NOT_FOUND if the Metrics are not - * found. FPGA_NO_MEMORY if there was not enough memory to enumerates - * metrics. - * - */ -fpga_result fpgaGetMetricsThresholdInfo(fpga_handle handle, - struct metric_threshold *metric_thresholds, - uint32_t *num_thresholds); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // __FPGA_METRICS_H__ diff --git a/sw/include/opae/mmio.h b/sw/include/opae/mmio.h deleted file mode 100644 index fc45da9e7..000000000 --- a/sw/include/opae/mmio.h +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright(c) 2017, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** - * @file mmio.h - * @brief Functions for mapping and accessing MMIO space - * - * Most FPGA accelerators provide access to control registers through - * memory-mappable address spaces, commonly referred to as "MMIO spaces". This - * file provides functions to map, unmap, read, and write MMIO spaces. - * - * Note that an accelerator may have multiple MMIO spaces, denoted by the - * `mmio_num` argument of the APIs below. The meaning and properties of each - * MMIO space are up to the accelerator designer. - */ - -#ifndef __FPGA_MMIO_H__ -#define __FPGA_MMIO_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Write 64 bit value to MMIO space - * - * This function will write to MMIO space of the target object at a specified - * offset. - * - * @param[in] handle Handle to previously opened accelerator resource - * @param[in] mmio_num Number of MMIO space to access - * @param[in] offset Byte offset into MMIO space - * @param[in] value Value to write (64 bit) - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if any of the supplied - * parameters is invalid. FPGA_EXCEPTION if an internal exception occurred - * while trying to access the handle. - */ -fpga_result fpgaWriteMMIO64(fpga_handle handle, - uint32_t mmio_num, uint64_t offset, - uint64_t value); - -/** - * Read 64 bit value from MMIO space - * - * This function will read from MMIO space of the target object at a specified - * offset. - * - * @param[in] handle Handle to previously opened accelerator resource - * @param[in] mmio_num Number of MMIO space to access - * @param[in] offset Byte offset into MMIO space - * @param[out] value Pointer to memory where read value is returned (64 bit) - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if any of the supplied - * parameters is invalid. FPGA_EXCEPTION if an internal exception occurred - * while trying to access the handle. - */ -fpga_result fpgaReadMMIO64(fpga_handle handle, - uint32_t mmio_num, - uint64_t offset, uint64_t *value); - -/** - * Write 32 bit value to MMIO space - * - * This function will write to MMIO space of the target object at a specified - * offset. - * - * @param[in] handle Handle to previously opened accelerator resource - * @param[in] mmio_num Number of MMIO space to access - * @param[in] offset Byte offset into MMIO space - * @param[in] value Value to write (32 bit) - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if any of the supplied - * parameters is invalid. FPGA_EXCEPTION if an internal exception occurred - * while trying to access the handle. - */ -fpga_result fpgaWriteMMIO32(fpga_handle handle, - uint32_t mmio_num, uint64_t offset, - uint32_t value); - -/** - * Read 32 bit value from MMIO space - * - * This function will read from MMIO space of the target object at a specified - * offset. - * - * @param[in] handle Handle to previously opened accelerator resource - * @param[in] mmio_num Number of MMIO space to access - * @param[in] offset Byte offset into MMIO space - * @param[out] value Pointer to memory where read value is returned (32 bit) - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if any of the supplied - * parameters is invalid. FPGA_EXCEPTION if an internal exception occurred - * while trying to access the handle. - */ -fpga_result fpgaReadMMIO32(fpga_handle handle, - uint32_t mmio_num, - uint64_t offset, uint32_t *value); - -/** - * Write 512 bit value to MMIO space - * - * 512 bit MMIO writes may not be supported on all platforms. - * - * This function will write to MMIO space of the target object at a specified - * offset. - * - * @param[in] handle Handle to previously opened accelerator resource - * @param[in] mmio_num Number of MMIO space to access - * @param[in] offset Byte offset into MMIO space - * @param[in] value Pointer to memory holding value to write (512 bits) - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if any of the supplied - * parameters is invalid. FPGA_EXCEPTION if an internal exception occurred - * while trying to access the handle. - */ -fpga_result fpgaWriteMMIO512(fpga_handle handle, - uint32_t mmio_num, uint64_t offset, - const void *value); - -/** - * Map MMIO space - * - * This function will return a pointer to the specified MMIO space of the - * target object in process virtual memory, if supported by the target. Some - * MMIO spaces may be restricted to privileged processes, depending on the used - * handle and type. - * - * After mapping the respective MMIO space, you can access it through direct - * pointer operations (observing supported access sizes and alignments of the - * target platform and accelerator). - * - * @note Some targets (such as the ASE simulator) do not support memory-mapping - * of IO register spaces and will not return a pointer to an actually mapped - * space. Instead, they will return `FPGA_NOT_SUPPORTED`. Usually, these - * platforms still allow the application to issue MMIO operations using - * fpgaReadMMIO32(), fpgaWriteMMIO32(), fpgeReadMMIO64(), and - * fpgaWriteMMIO64(). - * - * If the caller passes in NULL for mmio_ptr, no mapping will be performed, and - * no virtual address will be returned, though the call will return `FPGA_OK`. - * This implies that all accesses will be performed through fpgaReadMMIO32(), - * fpgaWriteMMIO32(), fpgeReadMMIO64(), and fpgaWriteMMIO64(). This is the only - * supported case for ASE. - * - * The number of available MMIO spaces can be retrieved through the num_mmio - * property (fpgaPropertyGetNumMMIO()). - * - * @param[in] handle Handle to previously opened resource - * @param[in] mmio_num Number of MMIO space to access - * @param[out] mmio_ptr Pointer to memory where a pointer to the MMIO space - * will be returned. May be NULL, in which case no pointer - * is returned. Returned address may be NULL if underlying - * platform does not support memory mapping for register - * access. - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if any of the supplied - * parameters is invalid. FPGA_EXCEPTION if an internal exception occurred - * while trying to access the handle. FPGA_NO_ACCESS if the process' - * permissions are not sufficient to map the requested MMIO space. - * FPGA_NOT_SUPPORTED if platform does not support memory mapped IO. - */ -fpga_result fpgaMapMMIO(fpga_handle handle, - uint32_t mmio_num, uint64_t **mmio_ptr); - -/** - * Unmap MMIO space - * - * This function will unmap a previously mapped MMIO space of the target object, - * rendering any pointers to it invalid. - * - * @note This call is only supported by hardware targets, not by ASE - * simulation. - * - * @param[in] handle Handle to previously opened resource - * @param[in] mmio_num Number of MMIO space to access - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if any of the supplied - * parameters is invalid. FPGA_EXCEPTION if an internal exception occurred - * while trying to access the handle. - */ -fpga_result fpgaUnmapMMIO(fpga_handle handle, - uint32_t mmio_num); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // __FPGA_MMIO_H__ diff --git a/sw/include/opae/properties.h b/sw/include/opae/properties.h deleted file mode 100644 index 41d2eb05a..000000000 --- a/sw/include/opae/properties.h +++ /dev/null @@ -1,825 +0,0 @@ -// Copyright(c) 2017-2021, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** - * @file opae/properties.h - * @brief Functions for examining and manipulating `fpga_properties` objects - * - * In OPAE, `fpga_properties` objects are used both for obtaining information - * about resources and for selectively enumerating resources based on their - * properties. This file provides accessor functions (get/set) to allow reading - * and writing individual items of an `fpga_properties` object. Generally, not - * all object types supported by OPAE carry all properties. If you call a - * property accessor method on a `fpga_properties` object that does not support - * this particular property, it will return FPGA_INVALID_PARAM. - * - * # Accessor Return Values - * In addition to the return values specified in the documentation below, all - * accessor functions return FPGA_OK on success, FPGA_INVALID_PARAM if you pass - * NULL or invalid parameters (i.e. non-initialized properties objects), - * FPGA_EXCEPTION if an internal exception occurred trying to access the - * properties object, FPGA_NOT_FOUND if the requested property is not part of - * the supplied properties object. - */ - -#ifndef __FPGA_PROPERTIES_H__ -#define __FPGA_PROPERTIES_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Create a fpga_properties object - * - * Initializes the memory pointed at by `prop` to represent a properties - * object, and populates it with the properties of the resource referred to by - * `handle`. Individual properties can then be queried using fpgaPropertiesGet*() - * accessor functions. - * - * @note fpgaGetPropertiesFromHandle() will allocate memory for the created properties - * object returned in `prop`. It is the responsibility of the caller - * to free this memory after use by calling fpgaDestroyProperties(). - * - * @param[in] handle Open handle to get properties for. - * @param[out] prop Pointer to a variable of type fpga_properties - * @returns FPGA_OK on success. FPGA_NO_MEMORY if no memory could be allocated - * to create the `fpga_properties` object. FPGA_EXCEPTION if an exception - * happend while initializing the `fpga_properties` object. - */ -fpga_result fpgaGetPropertiesFromHandle(fpga_handle handle, fpga_properties *prop); - -/** - * Create a fpga_properties object - * - * Initializes the memory pointed at by `prop` to represent a properties - * object, and populates it with the properties of the resource referred to by - * `token`. Individual properties can then be queried using fpgaPropertiesGet*() - * accessor functions. - * - * If `token` is NULL, an "empty" properties object is created to be used as a - * filter for fpgaEnumerate(). All individual fields are set to `don`t care`, - * which implies that the fpga_properties object would match all FPGA resources - * if used for an fpgaEnumerate() query. The matching criteria can be further - * refined by using fpgaSet* functions on the properties object, or the - * object can be populated with the actual properties of a resource by using - * fpgaUpdateProperties(). - * - * @note fpgaGetProperties() will allocate memory for the created properties - * object returned in `prop`. It is the responsibility of the caller - * to free this memory after use by calling fpgaDestroyProperties(). - * - * @param[in] token Token to get properties for. Can be NULL, which will - * create an empty properties object to be used as a - * filter for fpgaEnumerate(). - * @param[out] prop Pointer to a variable of type fpga_properties - * @returns FPGA_OK on success. FPGA_NO_MEMORY if no memory could be allocated - * to create the `fpga_properties` object. FPGA_EXCEPTION if an exception - * happend while initializing the `fpga_properties` object. - */ -fpga_result fpgaGetProperties(fpga_token token, fpga_properties *prop); - -/** - * Update a fpga_properties object - * - * Populates the properties object 'prop' with properties of the resource - * referred to by 'token'. Unlike fpgaGetProperties(), this call will not create - * a new properties object or allocate memory for it, but use a previously - * created properties object. - * - * @param[in] token Token to retrieve properties for - * @param[in] prop fpga_properties object to update - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if `token` or `prop` are not - * valid objects. FPGA_NOT_FOUND if the resource referred to by `token` was - * not found. FPGA_NO_DRIVER if not driver is loaded. FPGA_EXCEPTION if an - * internal exception occured when trying to update `prop`. - */ -fpga_result fpgaUpdateProperties(fpga_token token, fpga_properties prop); - -/** - * Clear a fpga_properties object - * - * Sets all fields of the properties object pointed at by 'prop' to 'don't - * care', which implies that the fpga_properties object would match all FPGA - * resources if used for an fpgaEnumerate() query. The matching criteria can be - * further refined by using fpgaSet* functions on the properties object. - * - * Instead of creating a new fpga_properties object every time, this function - * can be used to re-use fpga_properties objects from previous queries. - * - * @param[in] prop fpga_properties object to clear - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if `prop` is not a valid - * object. FPGA_EXCEPTION if an * internal exception occured when trying to - * access `prop`. - */ -fpga_result fpgaClearProperties(fpga_properties prop); - -/** - * Clone a fpga_properties object - * - * Creates a copy of an fpga_properties object. - * - * @note This call creates a new properties object and allocates memory for it. - * Both the 'src' and the newly created 'dst' objects will eventually need to be - * destroyed using fpgaDestroyProperties(). - * - * @param[in] src fpga_properties object to copy - * @param[out] dst New fpga_properties object cloned from 'src' - * @returns FPGA_OK on success. FPGA_INVALID_PARAM if `src` is not a valid - * object, or if `dst` is NULL. FPGA_NO_MEMORY if there was not enough memory - * to allocate an `fpga_properties` object for `dst`. FPGA_EXCEPTION if an - * internal exception occurred either accessing `src` or updating `dst`. - */ -fpga_result fpgaCloneProperties(fpga_properties src, fpga_properties *dst); - -/** - * Destroy a fpga_properties object - * - * Destroys an existing fpga_properties object that the caller has previously - * created using fpgaGetProperties() or fpgaCloneProperties(). - * - * @note fpgaDestroyProperties() requires the address of an fpga_properties - * object, similar to fpgaGetPropertiesFromHandle(), fpgaGetProperties(), - * and fpgaCloneProperties(). Passing any other value results in undefined - * behavior. - * - * @param[inout] prop Pointer to the fpga_properties object to destroy - * @returns FPGA_OK on success. FPGA_INVALID_PARAM is `prop` is not a valid - * object. FPGA_EXCEPTION if an internal exception occurrred while trying to - * access `prop`. - */ -fpga_result fpgaDestroyProperties(fpga_properties *prop); - -/** - * Get the token of the parent object - * - * Returns the token of the parent of the queried resource in '*parent'. - * - * @param[in] prop Properties object to query - * @param[out] parent Pointer to a token variable of the resource 'prop' is - * associated with - * @returns FPGA_NOT_FOUND if resource does not have a - * parent (e.g. an FPGA_DEVICE resource does not have parents). Also see - * "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesGetParent(const fpga_properties prop, - fpga_token *parent); - -/** - * Set the token of the parent object - * - * @param[in] prop Properties object to modify - * @param[out] parent Pointer to a token variable of the resource 'prop' is - * associated with - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesSetParent(fpga_properties prop, - fpga_token parent); -/** - * Get the object type of a resource - * - * Returns the object type of the queried resource. - * - * @param[in] prop Properties object to query - * @param[out] objtype Pointer to an object type variable of the resource - * 'prop' is associated with - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesGetObjectType(const fpga_properties prop, - fpga_objtype *objtype); - -/** - * Set the object type of a resource - * - * Sets the object type of the resource. * Currently supported object types are - * FPGA_DEVICE and FPGA_ACCELERATOR. - * - * @param[in] prop Properties object to modify - * @param[out] objtype Object type of the resource 'prop' is associated with - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesSetObjectType(fpga_properties prop, - fpga_objtype objtype); -/** - * Get the PCI segment number of a resource - * - * Returns the segment number of the queried resource. - * - * @param[in] prop Properties object to query - * @param[out] segment Pointer to a PCI segment variable of the resource 'prop' - * is associated with - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesGetSegment(const fpga_properties prop, uint16_t *segment); - -/** - * Set the PCI segment number of a resource - * - * @param[in] prop Properties object to modify - * @param[in] segment PCI segment number of the resource 'prop' is associated with - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesSetSegment(fpga_properties prop, uint16_t segment); - -/** - * Get the PCI bus number of a resource - * - * Returns the bus number the queried resource. - * - * @param[in] prop Properties object to query - * @param[out] bus Pointer to a PCI bus variable of the resource 'prop' - * is associated with - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesGetBus(const fpga_properties prop, uint8_t *bus); - -/** - * Set the PCI bus number of a resource - * - * @param[in] prop Properties object to modify - * @param[in] bus PCI bus number of the resource 'prop' is associated with - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesSetBus(fpga_properties prop, uint8_t bus); - -/** - * Get the PCI device number of a resource - * - * Returns the device number the queried resource. - * - * @param[in] prop Properties object to query - * @param[out] device Pointer to a PCI device variable of the resource 'prop' - * is associated with - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesGetDevice(const fpga_properties prop, - uint8_t *device); - -/** - * Set the PCI device number of a resource - * - * Enforces the limitation on the number of devices as specified in the - * PCI spec. - * - * @param[in] prop Properties object to modify - * @param[in] device PCI device number of the resource 'prop' is associated - * with - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesSetDevice(fpga_properties prop, - uint8_t device); - -/** - * Get the PCI function number of a resource - * - * Returns the function number the queried resource. - * - * @param[in] prop Properties object to query - * @param[out] function Pointer to PCI function variable of the - * resource 'prop' is associated with - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesGetFunction(const fpga_properties prop, - uint8_t *function); - -/** - * Set the PCI function number of a resource - * - * Enforces the limitation on the number of functions as specified in the - * PCI spec. - * - * @param[in] prop Properties object to modify - * @param[in] function PCI function number of the resource 'prop' is - * associated with - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesSetFunction(fpga_properties prop, - uint8_t function); - -/** - * Get the socket id of a resource - * - * Returns the socket id of the queried resource. - * - * @param[in] prop Properties object to query - * @param[out] socket_id Pointer to a socket id variable of the - * resource 'prop' - * is associated with - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - * See also "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesGetSocketID(const fpga_properties prop, - uint8_t *socket_id); - -/** - * Set the socket id of the resource - * - * @param[in] prop Properties object to modify - * @param[in] socket_id Socket id of the resource 'prop' is - * associated with - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesSetSocketID(fpga_properties prop, - uint8_t socket_id); - -/** - * Get the device id of the resource - * - * @param[in] prop Properties object to query - * @param[out] device_id Pointer to a device id variable of the - * resource 'prop' is associated with - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesGetDeviceID(const fpga_properties prop, - uint16_t *device_id); - -/** - * Set the device id of the resource - * - * @param[in] prop Properties object to modify - * @param[in] device_id Device id of the resource 'prop' is associated with - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesSetDeviceID(fpga_properties prop, - uint16_t device_id); - -/** - * Get the number of slots of an FPGA resource property - * - * Returns the number of slots present in an FPGA. - * - * @param[in] prop Properties object to query - must be of type FPGA_DEVICE - * @param[out] num_slots Pointer to number of slots variable of the FPGA - * @returns FPGA_INVALID_PARAM if object type is not FPGA_DEVICE. See also - * "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesGetNumSlots(const fpga_properties prop, - uint32_t *num_slots); - -/** - * Set the number of slots of an FPGA resource property - * - * @param[in] prop Properties object to modify - must be of type - * FPGA_DEVICE - * @param[in] num_slots Number of slots of the FPGA - * @returns FPGA_INVALID_PARAM if object type is not FPGA_DEVICE. See also - * "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesSetNumSlots(fpga_properties prop, - uint32_t num_slots); - -/** - * Get the BBS ID of an FPGA resource property - * - * Returns the blue bitstream id of an FPGA. - * - * @param[in] prop Properties object to query - must be of type FPGA_DEVICE - * @param[out] bbs_id Pointer to a bbs id variable of the FPGA - * @returns FPGA_INVALID_PARAM if object type is not FPGA_DEVICE. See also - * "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesGetBBSID(const fpga_properties prop, - uint64_t *bbs_id); - - -/** - * Set the BBS ID of an FPGA resource property - * - * @param[in] prop Properties object to modify - must be of type - * FPGA_DEVICE - * @param[in] bbs_id Blue bitstream id of the FPGA resource - * @returns FPGA_INVALID_PARAM if object type is not FPGA_DEVICE. See also - * "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesSetBBSID(fpga_properties prop, - uint64_t bbs_id); - - -/** - * Get the BBS Version of an FPGA resource property - * - * Returns the blue bitstream version of an FPGA. - * - * @param[in] prop Properties object to query - must be of type - * FPGA_DEVICE - * @param[out] bbs_version Pointer to a bbs version variable of the FPGA - * @returns FPGA_INVALID_PARAM if object type is not FPGA_DEVICE. See also - * "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesGetBBSVersion(const fpga_properties prop, - fpga_version *bbs_version); - -/** - * Set the BBS Version of an FPGA resource property - * - * @param[in] prop Properties object to modify - must be of type - * FPGA_DEVICE - * @param[in] version Blue bitstream version of the FPGA resource - * @returns FPGA_INVALID_PARAM if object type is not FPGA_DEVICE. See also - * "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesSetBBSVersion(fpga_properties prop, - fpga_version version); - - -/** - * Get the vendor id of an FPGA resource property - * - * Returns the vendor id of an FPGA. - * - * @param[in] prop Properties object to query - must be of type FPGA_DEVICE - * @param[out] vendor_id Pointer to a vendor id variable of the FPGA - * @returns FPGA_INVALID_PARAM if object type is not FPGA_DEVICE. See also - * "Accessor Return Values" in [properties.h](#properties-h). - * - * @note This API is not currently supported. - */ -fpga_result fpgaPropertiesGetVendorID(const fpga_properties prop, - uint16_t *vendor_id); - - -/** - * Set the vendor id of an FPGA resource property - * - * @param[in] prop Properties object to modify - must be of type FPGA_DEVICE - * @param[in] vendor_id Vendor id of the FPGA resource - * @returns FPGA_INVALID_PARAM if object type is not FPGA_DEVICE. See also - * "Accessor Return Values" in [properties.h](#properties-h). - * - * @note This API is not currently supported. - */ -fpga_result fpgaPropertiesSetVendorID(fpga_properties prop, - uint16_t vendor_id); - -/** - * Get the model of an FPGA resource property - * - * Returns the model of an FPGA. - * - * @param[in] prop Properties object to query - must be of type FPGA_DEVICE - * @param[in] model Model of the FPGA resource (string of minimum - * FPGA_MODEL_LENGTH length - * @returns FPGA_INVALID_PARAM if object type is not FPGA_DEVICE. See also - * "Accessor Return Values" in [properties.h](#properties-h). - * - * @note This API is not currently supported. - */ -fpga_result fpgaPropertiesGetModel(const fpga_properties prop, - char *model); - - -/** - * Set the model of an FPGA resource property - * - * @param[in] prop Properties object to modify - must be of type FPGA_DEVICE - * @param[in] model Model of the FPGA resource (string of maximum - * FPGA_MODEL_LENGTH length - * @returns FPGA_INVALID_PARAM if object type is not FPGA_DEVICE. See also - * "Accessor Return Values" in [properties.h](#properties-h). - * - * @note This API is not currently supported. - */ -fpga_result fpgaPropertiesSetModel(fpga_properties prop, - char *model); - - -/** - * Get the local memory size of an FPGA resource property - * - * Returns the local memory size of an FPGA. - * - * @param[in] prop Properties object to query - must be of type FPGA_DEVICE - * @param[out] lms Pointer to a memory size variable of the FPGA - * @returns FPGA_INVALID_PARAM if object type is not FPGA_DEVICE. See also - * "Accessor Return Values" in [properties.h](#properties-h). - * - * @note This API is not currently supported. - */ -fpga_result fpgaPropertiesGetLocalMemorySize(const fpga_properties prop, - uint64_t *lms); - - -/** - * Set the local memory size of an FPGA resource property - * - * @param[in] prop Properties object to modify - must be of type FPGA_DEVICE - * @param[in] lms Local memory size of the FPGA resource - * @returns FPGA_INVALID_PARAM if object type is not FPGA_DEVICE. See also - * "Accessor Return Values" in [properties.h](#properties-h). - * - * @note This API is not currently supported. - */ -fpga_result fpgaPropertiesSetLocalMemorySize(fpga_properties prop, - uint64_t lms); - -/** - * Get the capabilities FPGA resource property - * - * Returns the capabilities of an FPGA. - * Capabilities is a bitfield value - * - * @param[in] prop Properties object to query - must be of type - * FPGA_DEVICE - * @param[out] capabilities Pointer to a capabilities variable of the FPGA - * @returns FPGA_INVALID_PARAM if object type is not FPGA_DEVICE. See also - * "Accessor Return Values" in [properties.h](#properties-h). - * - * @note This API is not currently supported. - */ -fpga_result fpgaPropertiesGetCapabilities(const fpga_properties prop, - uint64_t *capabilities); - - -/** - * Set the capabilities of an FPGA resource property - * - * Capabilities is a bitfield value - * - * @param[in] prop Properties object to modify - must be of type - * FPGA_DEVICE - * @param[in] capabilities Capabilities of the FPGA resource - * @returns FPGA_INVALID_PARAM if object type is not FPGA_DEVICE. See also - * "Accessor Return Values" in [properties.h](#properties-h). - * - * @note This API is not currently supported. - */ -fpga_result fpgaPropertiesSetCapabilities(fpga_properties prop, - uint64_t capabilities); - -/** - * Get the GUID of a resource - * - * Returns the GUID of an FPGA or accelerator object. - * - * For an accelerator, the GUID uniquely identifies a specific accelerator context type, - * i.e. different accelerators will have different GUIDs. For an FPGA, the GUID - * is used to identify a certain instance of an FPGA, e.g. to determine whether - * a given bitstream would be compatible. - * - * @param[in] prop Properties object to query - * @param[out] guid Pointer to a GUID of the slot variable - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesGetGUID(const fpga_properties prop, - fpga_guid *guid); - -/** - * Set the GUID of a resource - * - * Sets the GUID of an FPGA or accelerator object. - * - * For an accelerator, the GUID uniquely identifies a specific accelerator context type, - * i.e. different accelerators will have different GUIDs. For an FPGA, the GUID - * is used to identify a certain instance of an FPGA, e.g. to determine whether - * a given bitstream would be compatible. - * - * @param[in] prop Properties object to modify - * @param[out] guid Pointer to a GUID of the slot variable - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesSetGUID(fpga_properties prop, fpga_guid guid); - -/** - * Get the number of mmio spaces - * - * Returns the number of mmio spaces of an AFU properties structure. - * - * @param[in] prop Properties object to query - must be of type FPGA_ACCELERATOR - * @param[out] mmio_spaces Pointer to a variable for number of mmio spaces - * @returns FPGA_INVALID_PARAM if object type is not FPGA_ACCELERATOR. See also - * "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesGetNumMMIO(const fpga_properties prop, - uint32_t *mmio_spaces); - -/** - * Set the number of mmio spaces - * - * Sets the number of mmio spaces of an AFU properties structure. - * - * @param[in] prop Properties object to modify - must be of type FPGA_ACCELERATOR - * @param[in] mmio_spaces Number of MMIO spaces of the accelerator - * @returns FPGA_INVALID_PARAM if object type is not FPGA_ACCELERATOR. See also - * "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesSetNumMMIO(fpga_properties prop, - uint32_t mmio_spaces); - -/** - * Get the number of interrupts - * - * Returns the number of interrupts of an accelerator properties structure. - * - * @param[in] prop Properties object to query - must be of type - * FPGA_ACCELERATOR - * @param[out] num_interrupts Pointer to a variable for number of interrupts - * @returns FPGA_INVALID_PARAM if object type is not FPGA_ACCELERATOR. See also - * "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesGetNumInterrupts(const fpga_properties prop, - uint32_t *num_interrupts); - -/** - * Set the number of interrupts - * - * Sets the number of interrupts of an accelerator properties structure. - * - * @param[in] prop Properties object to modify - must be of type - * FPGA_ACCELERATOR - * @param[in] num_interrupts Number of interrupts of the accelerator - * @returns FPGA_INVALID_PARAM if object type is not FPGA_ACCELERATOR. See also - * "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesSetNumInterrupts(fpga_properties prop, - uint32_t num_interrupts); - -/** - * Get the state of a accelerator resource property - * - * Returns the accelerator state of a accelerator. - * - * @param[in] prop Properties object to query - must be of type FPGA_ACCELERATOR - * @param[out] state Pointer to a accelerator state variable of the accelerator - * @returns FPGA_INVALID_PARAM if object type is not FPGA_ACCELERATOR. See also - * "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesGetAcceleratorState(const fpga_properties prop, - fpga_accelerator_state *state); - - -/** - * Set the state of an accelerator resource property - * - * @param[in] prop Properties object to modify - must be of type FPGA_ACCELERATOR - * @param[in] state accelerator state of the accelerator resource - * @returns FPGA_INVALID_PARAM if object type is not FPGA_ACCELERATOR. See also - * "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesSetAcceleratorState(fpga_properties prop, - fpga_accelerator_state state); - -/** - * Get the object ID of a resource - * - * Returns the object ID of a resource. The object ID is a 64 bit identifier - * that is unique within a single node or system. It represents a similar - * concept as the token, but can be used across processes (e.g. passed on the - * command line). - * - * @param[in] prop Properties object to query - * @param[out] object_id Pointer to a 64bit memory location to store the object - * ID in - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesGetObjectID(const fpga_properties prop, - uint64_t *object_id); - - -/** - * Set the object ID of a resource - * - * Sets the object ID of a resource. The object ID is a 64 bit identifier - * that is unique within a single node or system. It represents a similar - * concept as the token, but can be used across processes (e.g. passed on the - * command line). - * - * @param[in] prop Properties object to query - * @param[in] object_id A 64bit value to use as the object ID - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesSetObjectID(const fpga_properties prop, - uint64_t object_id); - - -/** - * Get the number of errors that can be reported by a resource - * - * Returns the number of error registers understood by a resource. - * - * @param[in] prop Properties object to query - * @param[out] num_errors Pointer to a 32 bit memory location to store the - * number of supported errors in - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesGetNumErrors(const fpga_properties prop, - uint32_t *num_errors); - - -/** - * Set the number of error registers - * - * Set the number of error registers understood by a resource to enumerate. - * - * @param[in] prop Properties object to query - * @param[in] num_errors Number of errors - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesSetNumErrors(const fpga_properties prop, - uint32_t num_errors); - -/** - * Get the OPAE plugin interface implemented by a resource - * - * Returns the plugin interface enumerator. - * - * @param[in] prop Properties object to query - * @param[out] interface Pointer to an fpga_interface location to store the - * interface in - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesGetInterface(const fpga_properties prop, - fpga_interface *interface); - -/** - * Set the OPAE plugin interface implemented by a resource - * - * Set the plugin interface enumerator. - * - * @param[in] prop Properties object to query - * @param[in] interface The interface enumerator to set - * @returns See "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesSetInterface(const fpga_properties prop, - fpga_interface interface); - -/** - * Get the subsystem vendor id of an FPGA resource property - * - * Returns the subsystem vendor id of an FPGA. - * - * @param[in] prop Properties object to query - * @param[out] subsystem_vendor_id Pointer to a vendor id variable of the FPGA - * @returns FPGA_OK on success. See also - * "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesGetSubsystemVendorID(const fpga_properties prop, - uint16_t *subsystem_vendor_id); - - -/** - * Set the subsystem vendor id of an FPGA resource property - * - * @param[in] prop Properties object to modify - * @param[in] subsystem_vendor_id Subsystem Vendor id of the FPGA resource - * @returns FPGA_OK on success. See also - * "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesSetSubsystemVendorID(fpga_properties prop, - uint16_t subsystem_vendor_id); - -/** - * Get the subsystem device id of an FPGA resource property - * - * Returns the subsystem device id of an FPGA. - * - * @param[in] prop Properties object to query - * @param[out] subsystem_device_id Pointer to a device id variable of the FPGA - * @returns FPGA_OK on success. See also - * "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesGetSubsystemDeviceID(const fpga_properties prop, - uint16_t *subsystem_device_id); - - -/** - * Set the subsystem device id of an FPGA resource property - * - * @param[in] prop Properties object to modify - * @param[in] subsystem_device_id Subsystem Device id of the FPGA resource - * @returns FPGA_OK on success. See also - * "Accessor Return Values" in [properties.h](#properties-h). - */ -fpga_result fpgaPropertiesSetSubsystemDeviceID(fpga_properties prop, - uint16_t subsystem_device_id); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // __FPGA_PROPERTIES_H__ - diff --git a/sw/include/opae/sysobject.h b/sw/include/opae/sysobject.h deleted file mode 100644 index b0872180d..000000000 --- a/sw/include/opae/sysobject.h +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright(c) 2017-2018, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** - * @file opae/sysobject.h - * @brief Functions to read/write from system objects. - * On Linux systems with the OPAE kernel driver, this is used to access sysfs - * nodes created by the driver. - */ -#ifndef __FPGA_SYSOBJECT_H__ -#define __FPGA_SYSOBJECT_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Create an `fpga_object` data structures. An `fpga_object` - * is a handle to an FPGA resource which can be an attribute, register or - * a container. This object is read-only. - * - * @param[in] token Token identifying a resource (accelerator or device) - * @param[in] name A key identifying an object belonging to a resource. - * @param[out] object Pointer to memory to store the object in - * @param[in] flags Control behavior of object identification and creation. - * FPGA_OBJECT_GLOB is used to indicate that the name should be treated as a - * globbing expression. FPGA_OBJECT_RECURSE_ONE indicates that subobjects be - * created for objects one level down from the object identified by name. - * FPGA_OBJECT_RECURSE_ALL indicates that subobjects be created for all objects - * below the current object identified by name. - * - * @return FPGA_OK on success. FPGA_INVALID_PARAM if any of the supplied - * parameters is invalid. FPGA_NOT_FOUND if an object cannot be found with the - * given key. FPGA_NOT_SUPPORTED if this function is not supported by the - * current implementation of this API. - * - * @note Names that begin with '.' or '/' or contain '..' are not allowed and - * result in FPGA_INVALID_PARAM being returned - * - */ -fpga_result fpgaTokenGetObject(fpga_token token, const char *name, - fpga_object *object, int flags); - -/** - * @brief Create an `fpga_object` data structure from a handle. - * An `fpga_object` is a handle to an FPGA resource which can be an attribute, - * register, or container. This object has read/write access.. - * - * @param[in] handle Handle identifying a resource (accelerator or device) - * @param[in] name A key identifying an object belonging to a resource. - * @param[out] object Pointer to memory to store the object in - * @param[in] flags Control behavior of object identification and creation - * FPGA_OBJECT_GLOB is used to indicate that the name should be treated as a - * globbing expression. FPGA_OBJECT_RECURSE_ONE indicates that subobjects be - * created for objects one level down from the object identified by name. - * FPGA_OBJECT_RECURSE_ALL indicates that subobjects be created for all objects - * below the current object identified by name. - * - * @return FPGA_OK on success. FPGA_INVALID_PARAM if any of the supplied - * parameters is invalid. FPGA_NOT_FOUND if an object cannot be found with the - * given key. FPGA_NOT_SUPPORTED if this function is not supported by the - * current implementation of this API. - * - * @note Names that begin with '.' or '/' or contain '..' are not allowed and - * result in FPGA_INVALID_PARAM being returned - * - */ -fpga_result fpgaHandleGetObject(fpga_handle handle, const char *name, - fpga_object *object, int flags); - -/** - * @brief Create an `fpga_object` data structure from a parent object. An - * `fpga_object` is a handle to an FPGA resource which can be an attribute, - * register, or container. If the parent object was created with a handle, - * then the new object will inherit the handle allowing it to have read-write - * access to the object data. - * - * @param[in] parent A parent container `fpga_object`. - * @param[in] name A key identifying a sub-object of the parent container. - * @param[out] object Pointer to memory to store the object in. - * @param[in] flags Control behavior of object identification and creation. - * FPGA_OBJECT_GLOB is used to indicate that the name should be treated as a - * globbing expression. FPGA_OBJECT_RECURSE_ONE indicates that subobjects be - * created for objects one level down from the object identified by name. - * FPGA_OBJECT_RECURSE_ALL indicates that subobjects be created for all objects - * below the current object identified by name. - * - * @return FPGA_OK on success. FPGA_INVALID_PARAM if any of the supplied - * parameters is invalid - this includes a parent object that is not a - * container object. FPGA_NOT_FOUND if an object cannot be found with the given - * key. FPGA_NOT_SUPPORTED if this function is not supported by the current - * implementation of this API. - * - * @note Names that begin with '.' or '/' or contain '..' are not allowed and - * result in FPGA_INVALID_PARAM being returned - * - */ -fpga_result fpgaObjectGetObject(fpga_object parent, const char *name, - fpga_object *object, int flags); - -/** - * @brief Create an `fpga_object` data structure from a parent object using a - * given index. An `fpga_object` is a handle to an FPGA resource which can be - * an attribute, register, or container. If the parent object was created with - * a handle, then the new object will inherit the handle allowing it to have - * read-write access to the object data. - * - * @param[in] parent A parent container 'fpga_object' - * @param[in] idx A positive index less than the size reported by the parent. - * @param[out] object Pointer to memory to store the object in. - * - * @return FPGA_OK on success. FPGA_INVALID_PARAM if any of the supplied - * parameters is invalid - this includes a parent object that is not a - * container object. FPGA_NOT_FOUND if an object cannot be found with the given - * key. FPGA_NOT_SUPPORTED if this function is not supported by the current - * implementation of this API. - */ -fpga_result fpgaObjectGetObjectAt(fpga_object parent, size_t idx, - fpga_object *object); -/** - * @brief Get the sysobject type (container or attribute) - * - * @param[in] obj An fpga_object instance - * @param[out] type The type of object (FPGA_OBJECT_CONTAINER or - * FPGA_OBJECT_ATTRIBUTE) - * - * @return FPGA_OK on success, FPGA_INVALID_PARAM if any of the supplied - * parameters are null or invalid - */ -fpga_result fpgaObjectGetType(fpga_object obj, enum fpga_sysobject_type *type); - -/** - * @brief Free memory used for the fpga_object data structure - * - * @note fpgaDestroyObject() requires the address of an fpga_object - * as created by fpgaTokenGetObject(), fpgaHandleGetObject(), - * or fpgaObjectGetObject(). Passing any other value results in - * undefind behavior. - * - * @param obj Pointer to the fpga_object instance to destroy - * - * @return FPGA_OK on success, FPGA_INVALID_PARAM if the object is NULL, - * FPGA_EXCEPTION if an internal error is encountered. - */ -fpga_result fpgaDestroyObject(fpga_object *obj); - -/** - * @brief Retrieve the size of the object. - * - * @param[in] obj An fpga_object instance. - * @param[out] value Pointer to variable to store size in. - * @param[in] flags Flags that control how the object is read - * If FPGA_OBJECT_SYNC is used then object will update its buffered copy before - * retrieving the size. - * - * @return FPGA_OK on success. FPGA_INVALID_PARAM if any of supplied parameters - * is invalid. FPGA_EXCEPTION if error occurred. - */ -fpga_result fpgaObjectGetSize(fpga_object obj, uint32_t *value, int flags); - -/** - * @brief Read bytes from an FPGA object - * - * @param[in] obj An fpga_object instance. - * @param[out] buffer Pointer to a buffer to read bytes into. - * @param[in] offset Byte offset relative to objects internal buffer where to - * begin reading bytes from. - * @param[in] len The length, in bytes, to read from the object. - * @param[in] flags Flags that control how object is read - * If FPGA_OBJECT_SYNC is used then object will update its buffered copy before - * retrieving the data. - * - * @return FPGA_OK on success, FPGA_INVALID_PARAM if any of the supplied - * parameters is invalid - */ -fpga_result fpgaObjectRead(fpga_object obj, uint8_t *buffer, size_t offset, - size_t len, int flags); - -/** - * @brief Read a 64-bit value from an FPGA object. - * The value is assumed to be in string format and will be parsed. See flags - * below for changing that behavior. - * - * @param[in] obj An fpga_object instance - * @param[out] value Pointer to a 64-bit variable to store the value in - * @param[in] flags Flags that control how the object is read - * If FPGA_OBJECT_SYNC is used then object will update its buffered copy before - * retrieving the data. If FPGA_OBJECT_RAW is used, then the data will be read - * as raw bytes into the uint64_t pointer variable. - * - * @return FPGA_OK on success, FPGA_INVALID_PARAM if any of the supplied - * parameters is invalid - */ -fpga_result fpgaObjectRead64(fpga_object obj, uint64_t *value, int flags); - -/** - * @brief Write 64-bit value to an FPGA object. - * The value will be converted to string before writing. See flags below for - * changing that behavior. - * - * @param[in] obj An fpga_object instance. - * @param[in] value The value to write to the object - * @param[in] flags Flags that control how the object is written - * If FPGA_OBJECT_RAW is used, then the value will be written as raw bytes. - * - * @return FPGA_OK on success, FPGA_INVALID_PARAM if any of the supplied - * parameters is invalid - * - * @note The object must have been created using a handle to a resource. - */ -fpga_result fpgaObjectWrite64(fpga_object obj, uint64_t value, int flags); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif /* !__FPGA_SYSOBJECT_H__ */ diff --git a/sw/include/opae/types.h b/sw/include/opae/types.h deleted file mode 100644 index f947d244c..000000000 --- a/sw/include/opae/types.h +++ /dev/null @@ -1,295 +0,0 @@ -// Copyright(c) 2018-2022, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** - * @file types.h - * @brief Type definitions for FPGA API - * - * OPAE uses the three opaque types fpga_properties, fpga_token, and - * fpga_handle to create a hierarchy of objects that can be used to enumerate, - * reference, acquire, and query FPGA resources. This object model is designed - * to be extensible to account for different FPGA architectures and platforms. - * - * Initialization - * -------------- - * OPAEs management of the opaque types `fpga_properties`, - * `fpga_token`, and `fpga_handle` relies on the proper initialization of - * variables of these types. In other words, before doing anything with a - * variable of one of these opaque types, you need to first initialize them. - * - * The respective functions that initialize opaque types are: - * - * * fpgaGetProperties() and fpgaCloneProperties() for `fpga_properties` - * * fpgaEnumerate() and fpgaCloneToken() for `fpga_token` - * * fpgaOpen() for `fpga_handle` - * - * This should intuitively make sense - fpgaGetProperties() creates - * `fpga_properties` objects, fpgaEnumerate() creates `fpga_token` objects, - * fpgaOpen() creates `fpga_handle` objects, and fpgaCloneProperties() and - * fpgaCloneToken() clone (create) `fpga_properties` and `fpga_token` objects, - * respectively. - * - * Since these opaque types are interpreted as pointers (they are typedef'd to - * a `void *`), passing an uninitialized opaque type into any function except - * the respective initailzation function will result in undefined behaviour, - * because OPAE will try to follow an invalid pointer. Undefined behaviour in - * this case may include an unexpected error code, or an application crash. - * - */ - -#ifndef __FPGA_TYPES_H__ -#define __FPGA_TYPES_H__ - -#include -#include -#include -#include - -/** - * Object for expressing FPGA resource properties - * - * `fpga_properties` objects encapsulate all enumerable information about an - * FPGA resources. They can be used for two purposes: selective enumeration - * (discovery) and querying information about existing resources. - * - * For selective enumeration, usually an empty `fpga_properties` object is - * created (using fpgaGetProperties()) and then populated with the desired - * criteria for enumeration. An array of `fpga_properties` can then be passed - * to fpgaEnumerate(), which will return a list of `fpga_token` objects - * matching these criteria. - * - * For querying properties of existing FPGA resources, fpgaGetProperties() can - * also take an `fpga_token` and will return an `fpga_properties` object - * populated with information about the resource referenced by that token. - * - * After use, `fpga_properties` objects should be destroyed using - * fpga_destroyProperties() to free backing memory used by the - * `fpga_properties` object. - */ -typedef void *fpga_properties; - -/** - * Token for referencing FPGA resources - * - * An `fpga_token` serves as a reference to a specific FPGA resource present in - * the system. Holding an `fpga_token` does not constitute ownership of the - * FPGA resource - it merely allows the user to query further information about - * a resource, or to use fpgaOpen() to acquire ownership. - * - * `fpga_token`s are usually returned by fpgaEnumerate() or - * fpgaPropertiesGetParent(), and used by fpgaOpen() to acquire ownership and - * yield a handle to the resource. Some API calls also take `fpga_token`s as - * arguments if they don't require ownership of the resource in question. - */ -typedef void *fpga_token; - -/** - * Handle to an FPGA resource - * - * A valid `fpga_handle` object, as populated by fpgaOpen(), denotes ownership - * of an FPGA resource. Note that ownership can be exclusive or shared, - * depending on the flags used in fpgaOpen(). Ownership can be released by - * calling fpgaClose(), which will render the underlying handle invalid. - * - * Many OPAE C API functions require a valid token (which is synonymous with - * ownership of the resource). - */ -typedef void *fpga_handle; - -/** - * Globally unique identifier (GUID) - * - * GUIDs are used widely within OPAE for helping identify FPGA resources. For - * example, every FPGA resource has a `guid` property, which can be (and in the - * case of FPGA_ACCELERATOR resource primarily is) used for enumerating a resource of a - * specific type. - * - * `fpga_guid` is compatible with libuuid's uuid_t, so users can use libuuid - * functions like uuid_parse() to create and work with GUIDs. - */ -typedef uint8_t fpga_guid[16]; - -/** - * Semantic version - * - * Data structure for expressing version identifiers following the semantic - * versioning scheme. Used in various properties for tracking component - * versions. - */ -typedef struct { - uint8_t major; /**< Major version */ - uint8_t minor; /**< Minor version */ - uint16_t patch; /**< Revision or patchlevel */ -} fpga_version; - -/** Handle to an event object - * - * OPAE provides an interface to asynchronous events that can be generated by - * different FPGA resources. The event API provides functions to register for - * these events; associated with every event a process has registered for is an - * `fpga_event_handle`, which encapsulates the OS-specific data structure for - * event objects. - * - * After use, `fpga_event_handle` objects should be destroyed using - * fpgaDestroyEventHandle() to free backing memory used by the - * `fpga_event_handle` object. - */ -typedef void *fpga_event_handle; - -/** Information about an error register - * - * This data structure captures information about an error register exposed by - * an accelerator resource. The error API provides functions to retrieve these - * information structures from a particular resource. - */ -#define FPGA_ERROR_NAME_MAX 64 -struct fpga_error_info { - char name[FPGA_ERROR_NAME_MAX]; /** name of the error */ - bool can_clear; /** whether error can be cleared */ -}; - -/** Object pertaining to an FPGA resource as identified by a unique name - * - * An `fpga_object` represents either a device attribute or a container of - * attributes. Similar to filesystems, a '/' may be used to seperate objects in - * an object hierarchy. Once on object is acquired, it may be used to read or - * write data in a resource attribute or to query sub-objects if the object is - * a container object. The data in an object is buffered and will be kept - * around until the object is destroyed. Additionally, the data in an attribute - * can by synchronized from the owning resource using the FPGA_OBJECT_SYNC flag - * during read operations. The name identifying the object is unique with - * respect to the resource that owns it. A parent resource may be identified by - * an `fpga_token` object, by an `fpga_handle` object, or another `fpga_object` - * object. If a handle object is used when opening the object, then the object - * is opened with read-write access. Otherwise, the object is read-only. - */ -typedef void *fpga_object; - -/** FPGA Metric string size - * - * - */ -#define FPGA_METRIC_STR_SIZE 256 -/** Metric value union - * - * - */ -typedef union { - uint64_t ivalue; // Metric integer value - double dvalue; // Metric double value - float fvalue; // Metric float value - bool bvalue; // Metric bool value -} metric_value; - - -/** Metric info struct - * - * - */ -typedef struct fpga_metric_info { - uint64_t metric_num; // Metric index num - fpga_guid metric_guid; // Metric guid - char qualifier_name[FPGA_METRIC_STR_SIZE]; // Metric full name - char group_name[FPGA_METRIC_STR_SIZE]; // Metric group name - char metric_name[FPGA_METRIC_STR_SIZE]; // Metric name - char metric_units[FPGA_METRIC_STR_SIZE]; // Metric units - enum fpga_metric_datatype metric_datatype; // Metric data type - enum fpga_metric_type metric_type; // Metric group type -} fpga_metric_info; - -/** Metric struct - * - * - */ -typedef struct fpga_metric { - uint64_t metric_num; // Metric index num - metric_value value; // Metric value - bool isvalid; // Metric value is valid -} fpga_metric; - - -/** Threshold struct - * - * - */ -typedef struct threshold { - char threshold_name[FPGA_METRIC_STR_SIZE]; // Threshold name - uint32_t is_valid; // Threshold is valid - double value; // Threshold value -} threshold; - -typedef struct metric_threshold { - char metric_name[FPGA_METRIC_STR_SIZE]; // Metric Threshold name - threshold upper_nr_threshold; // Upper Non-Recoverable Threshold - threshold upper_c_threshold; // Upper Critical Threshold - threshold upper_nc_threshold; // Upper Non-Critical Threshold - threshold lower_nr_threshold; // Lower Non-Recoverable Threshold - threshold lower_c_threshold; // Lower Critical Threshold - threshold lower_nc_threshold; // Lower Non-Critical Threshold - threshold hysteresis; // Hysteresis -} metric_threshold; - -/** Internal token type header - * - * Each plugin (dfl: libxfpga.so, vfio: libopae-v.so) implements its own - * proprietary token type. This header _must_ appear at offset zero within - * that structure. - * - * eg, see lib/plugins/xfpga/types_int.h:struct _fpga_token and - * lib/plugins/vfio/opae_vfio.h:struct _vfio_token. - */ -typedef struct _fpga_token_header { - uint64_t magic; - uint16_t vendor_id; - uint16_t device_id; - uint16_t segment; - uint8_t bus; - uint8_t device; - uint8_t function; - fpga_interface interface; - fpga_objtype objtype; - uint64_t object_id; - fpga_guid guid; - uint16_t subsystem_vendor_id; - uint16_t subsystem_device_id; -} fpga_token_header; - -/** Determine token parent/child relationship - * - * Given pointers to two fpga_token_header structs, determine - * whether the first is the parent of the second. A parent will - * have objtype == FPGA_DEVICE. A child will have objtype == - * FPGA_ACCELERATOR. The PCIe address of the two headers will - * match in all but the function fields. - */ -#define fpga_is_parent_child(__parent_hdr, __child_hdr) \ -(((__parent_hdr)->objtype == FPGA_DEVICE) && \ - ((__child_hdr)->objtype == FPGA_ACCELERATOR) && \ - ((__parent_hdr)->segment == (__child_hdr)->segment) && \ - ((__parent_hdr)->bus == (__child_hdr)->bus) && \ - ((__parent_hdr)->device == (__child_hdr)->device)) - -#endif // __FPGA_TYPES_H__ diff --git a/sw/include/opae/types_enum.h b/sw/include/opae/types_enum.h deleted file mode 100644 index e8173f02c..000000000 --- a/sw/include/opae/types_enum.h +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright(c) 2017-2022, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** - * @file types_enum.h - * @brief Definitions of enumerated types for the OPAE C API - * - * This file defines return and error codes, event and object types, states, - * and flags as used or reported by OPAE C API functions. - */ - -#ifndef __FPGA_TYPES_ENUM_H__ -#define __FPGA_TYPES_ENUM_H__ - -/** - * OPAE C API function return codes - * - * Every public API function exported by the OPAE C library will return one of - * these codes. Usually, FPGA_OK denotes successful completion of the requested - * operation, while any return code *other* than FPGA_OK indicates an error or - * other deviation from the expected behavior. Users of the OPAE C API should - * always check the return codes of the APIs they call, and not use output - * parameters of functions that did not execute successfully. - - * The fpgaErrStr() function converts error codes into printable messages. - * - * OPAE also has a logging mechanism that allows a developer to get more - * information about why a particular call failed with a specific message. If - * enabled, any function that returns an error code different from FPGA_OK will - * also print out a message with further details. This mechanism can be enabled - * by setting the environment variable `LIBOPAE_LOG` to 1 before running the - * respective application. - */ -typedef enum { - FPGA_OK = 0, /**< Operation completed successfully */ - FPGA_INVALID_PARAM, /**< Invalid parameter supplied */ - FPGA_BUSY, /**< Resource is busy */ - FPGA_EXCEPTION, /**< An exception occurred */ - FPGA_NOT_FOUND, /**< A required resource was not found */ - FPGA_NO_MEMORY, /**< Not enough memory to complete operation */ - FPGA_NOT_SUPPORTED, /**< Requested operation is not supported */ - FPGA_NO_DRIVER, /**< Driver is not loaded */ - FPGA_NO_DAEMON, /**< FPGA Daemon (fpgad) is not running */ - FPGA_NO_ACCESS, /**< Insufficient privileges or permissions */ - FPGA_RECONF_ERROR /**< Error while reconfiguring FPGA */ -} fpga_result; - -/** - * FPGA events - * - * OPAE currently defines the following event types that applications can - * register for. Note that not all FPGA resources and target platforms may - * support all event types. - */ -typedef enum { - FPGA_EVENT_INTERRUPT = 0, /**< Interrupt generated by an accelerator */ - FPGA_EVENT_ERROR, /**< Infrastructure error event */ - FPGA_EVENT_POWER_THERMAL /**< Infrastructure thermal event */ -} fpga_event_type; - -/* TODO: consider adding lifecycle events in the future - * to help with orchestration. Need a complete specification - * before including them in the API. Proposed events: - * FPGA_EVENT_APPEAR - * FPGA_EVENT_DISAPPEAR - * FPGA_EVENT_CHANGE - */ - -/** accelerator state */ -typedef enum { - /** accelerator is opened exclusively by another process */ - FPGA_ACCELERATOR_ASSIGNED = 0, - /** accelerator is free to be opened */ - FPGA_ACCELERATOR_UNASSIGNED -} fpga_accelerator_state; - -/** - * OPAE FPGA resources (objects) - * - * These are the FPGA resources currently supported by the OPAE object model. - */ -typedef enum { - /** FPGA_DEVICE objects represent FPGA devices and their management functionality. - * These objects can be opened (typically requires a certain privilege level or - * access permissions) and used for management functions like fpgaReconfigreSlot(). */ - FPGA_DEVICE = 0, - /** FPGA_ACCELERATOR objects represent allocatable units for accessing - * accelerated functions on the FPGA. They are frequently opened for - * interacting via control registers (MMIO), shared memory, or other, - * possibly platform-specific functions. */ - FPGA_ACCELERATOR -} fpga_objtype; - -/** - * OPAE plugin interface - * - * These are the supported plugin interfaces. - */ -typedef enum { - /** FPGA_IFC_DFL indicates that the plugin interface is the - * Device Feature List driver suite. */ - FPGA_IFC_DFL = 0, - /** FPGA_IFC_VFIO indicates that the plugin interface is the - * vfio-pci driver. */ - FPGA_IFC_VFIO, - /** FPGA_IFC_SIM_DFL indicates that the plugin interface is the - * AFU Simulation Environment simulating DFL drivers. */ - FPGA_IFC_SIM_DFL, - /** FPGA_IFC_SIM_VFIO indicates that the plugin interface is the - * AFU Simulation Environment simulating vfio-pci. */ - FPGA_IFC_SIM_VFIO, - /** FPGA_IFC_UIO indicates that the plugin interface is the - * uio-dfl driver. */ - FPGA_IFC_UIO, -} fpga_interface; - -/** - * Buffer flags - * - * These flags can be passed to the fpgaPrepareBuffer() function. - */ -enum fpga_buffer_flags { - FPGA_BUF_PREALLOCATED = (1u << 0), /**< Use existing buffer */ - FPGA_BUF_QUIET = (1u << 1), /**< Suppress error messages */ - FPGA_BUF_READ_ONLY = (1u << 2) /**< Buffer is read-only */ -}; - -/** - * Open flags - * - * These flags can be passed to the fpgaOpen() function. - */ -enum fpga_open_flags { - /** Open FPGA resource for shared access */ - FPGA_OPEN_SHARED = (1u << 0) -}; - -/** - * Reconfiguration flags - * - * These flags can be passed to the fpgaReconfigureSlot() function. - */ -enum fpga_reconf_flags { - /** Reconfigure the slot without checking if it is in use */ - FPGA_RECONF_FORCE = (1u << 0), - /** Don't configure AFU user clocks as part of PR */ - FPGA_RECONF_SKIP_USRCLK = (1u << 1) -}; - -enum fpga_sysobject_flags { - FPGA_OBJECT_SYNC = (1u << 0), /**< Synchronize data from driver */ - FPGA_OBJECT_GLOB = (1u << 1), /**< Treat names as glob expressions */ - FPGA_OBJECT_RAW = - (1u << 2), /**< Read or write object data as raw bytes */ - FPGA_OBJECT_RECURSE_ONE = - (1u - << 3), /**< Create subobjects one level down from containers */ - FPGA_OBJECT_RECURSE_ALL = - (1u - << 4) /**< Create subobjects all levels from from containers */ -}; - -enum fpga_sysobject_type { - FPGA_OBJECT_CONTAINER = - (1u << 0), /**< Represents a group of objects */ - FPGA_OBJECT_ATTRIBUTE = - (1u << 1) /**< An object with an attribute value that can be - read/written */ -}; - -/** fpga metrics types -* opae defines power,thermal, performance counter -* and afu metric types -*/ -enum fpga_metric_type { - FPGA_METRIC_TYPE_POWER, // Metric power - FPGA_METRIC_TYPE_THERMAL, // Metric Thermal - FPGA_METRIC_TYPE_PERFORMANCE_CTR, // Metric Performance counter - FPGA_METRIC_TYPE_AFU, // Metric AFU - FPGA_METRIC_TYPE_UNKNOWN // Unknown -}; - -/** Metrics data type -* -* -*/ -enum fpga_metric_datatype { - FPGA_METRIC_DATATYPE_INT, // Metric datatype integer - FPGA_METRIC_DATATYPE_FLOAT, // Metric datatype float - FPGA_METRIC_DATATYPE_DOUBLE, // Metric datatype double - FPGA_METRIC_DATATYPE_BOOL, // Metric datatype bool - FPGA_METRIC_DATATYPE_UNKNOWN // Metric datatype unknown -}; - -#endif // __FPGA_TYPES_ENUM_H__ diff --git a/sw/include/opae/uio.h b/sw/include/opae/uio.h deleted file mode 100644 index 8e3be20f2..000000000 --- a/sw/include/opae/uio.h +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright(c) 2020, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** - * @file opae/uio.h - * @brief APIs to manage a PCIe device via UIO. - * - * Presents a simple interface for interacting with a DFL device that is - * bound to its UIO driver. - * See https://kernel.org/doc/html/v4.14/driver-api/uio-howto.html for a - * description of UIO. - * - * Provides APIs for opening/closing the device and for querying info about - * the MMIO regions of the device. - */ - -#ifndef __OPAE_UIO_H__ -#define __OPAE_UIO_H__ - -#include -#include - -#define OPAE_UIO_PATH_MAX 256 - -/** - * MMIO region info - * - * Describes a range of mappable MMIO. - */ -struct opae_uio_device_region { - uint32_t region_index; - uint8_t *region_ptr; - size_t region_page_offset; - size_t region_size; - struct opae_uio_device_region *next; -}; - -/** - * OPAE UIO device abstraction - * - * This structure is used to interact with the OPAE UIO API. - * Each UIO device has a file descriptor that is used to mmap its regions - * into user address space. Each device also has one or more MMIO regions. - */ -struct opae_uio { - char device_path[OPAE_UIO_PATH_MAX]; - int device_fd; - struct opae_uio_device_region *regions; -}; - - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Open and populate a UIO device - * - * Opens the Device Feature List device corresponding to the device name - * given in dfl_device, eg "dfl_dev.10". The device must be bound to the - * dfl-uio-pdev driver prior to opening it. The data structures corresponding - * to the MMIO regions are initialized. - * - * @param[out] u Storage for the device. May be stack-resident. - * @param[in] dfl_device The name of the desired DFL device. - * @returns Non-zero on error. Zero on success. - * - * Example - * @code{.sh} - * $ sudo opaeuio -i -u lab -g lab dfl_dev.10 - * @endcode - * - * Example - * @code{.c} - * struct opae_uio u; - * - * if (opae_uio_open(&u, "dfl_dev.10")) { - * // handle error - * } - * @endcode - */ -int opae_uio_open(struct opae_uio *u, - const char *dfl_device); - -/** - * Query device MMIO region - * - * Retrieves info describing the MMIO region with the given region index. - * The device structure u must have been previously opened by a call to - * opae_uio_open. - * - * @param[in] u The open OPAE UIO device. - * @param[in] index The zero-based index of the desired MMIO region. - * @param[out] ptr Optional pointer to receive the virtual address for - * the region. Pass NULL to ignore. - * @param[out] size Optional pointer to receive the size of the MMIO region. - * Pass NULL to ignore. - * @returns Non-zero on error (including index out-of-range). Zero on success. - * - * Example - * @code{.c} - * struct opae_uio u; - * - * uint8_t *virt = NULL; - * size_t size = 0; - * - * if (opae_uio_open(&u, "dfl_dev.10")) { - * // handle error - * } else { - * opae_uio_region_get(&u, 0, &virt, &size); - * } - * @endcode - */ -int opae_uio_region_get(struct opae_uio *u, - uint32_t index, - uint8_t **ptr, - size_t *size); - -/** - * Release and close a UIO device - * - * The given device pointer must have been previously initialized by - * opae_uio_open. Releases all data structures. - * - * @param[in] u Storage for the device info. May be stack-resident. - * - * Example - * @code{.c} - * struct opae_uio u; - * - * if (opae_uio_open(&u, "dfl_dev.10")) { - * // handle error - * } else { - * // interact with the device - * ... - * // free the device - * opae_uio_close(&u); - * } - * @endcode - * - * Example - * @code{.sh} - * $ sudo opaeuio -r dfl_dev.10 - * @endcode - */ -void opae_uio_close(struct opae_uio *u); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // __OPAE_UIO_H__ diff --git a/sw/include/opae/umsg.h b/sw/include/opae/umsg.h deleted file mode 100644 index 043d8f5ee..000000000 --- a/sw/include/opae/umsg.h +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright(c) 2017, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** - * \file umsg.h - * \brief FPGA UMsg API - */ - -#ifndef __FPGA_UMSG_H__ -#define __FPGA_UMSG_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Get number of Umsgs - * - * Retuns number of umsg supported by AFU. - * - * - * @param[in] handle Handle to previously opened accelerator resource - * @param[out] value Returns number of UMsgs - * @returns FPGA_OK on success. - * FPGA_INVALID_PARAM if input parameter combination - * is not valid. - * FPGA_EXCEPTION if input parameter fpga handle is not - * valid. - */ -fpga_result fpgaGetNumUmsg(fpga_handle handle, uint64_t *value); - -/** - * Sets Umsg hint - * - * Writes usmg hint bit. - * - * - * @param[in] handle Handle to previously opened accelerator resource - * @param[in] value Value to use for UMsg hint, Umsg hit is N wide bitvector - * where N = number of Umsgs. - * @returns FPGA_OK on success. - * FPGA_INVALID_PARAM if input parameter combination - * is not valid. - * FPGA_EXCEPTION if input parameter fpga handle is not - * valid. - */ -fpga_result fpgaSetUmsgAttributes(fpga_handle handle, - uint64_t value); - -/** - * Trigger Umsg - * - * Writes a 64-bit value to trigger low-latency accelerator notification mechanism - * (UMsgs). - * - * @param[in] handle Handle to previously opened accelerator resource - * @param[in] value Value to use for UMsg - * @returns FPGA_OK on success. - * FPGA_INVALID_PARAM if input parameter combination - * is not valid. - * FPGA_EXCEPTION if input parameter fpga handle is not - * valid. - */ -fpga_result fpgaTriggerUmsg(fpga_handle handle, uint64_t value); - -/** - * Access UMsg memory directly - * - * This function will return a pointer to the memory allocated for low latency - * accelerator notifications (UMsgs). - * - * @param[in] handle Handle to previously opened accelerator resource - * @param[out] umsg_ptr Pointer to memory where a pointer to the virtual - * address space will be returned - * @returns FPGA_OK on success. - * FPGA_INVALID_PARAM if input parameter combination - * is not valid. - * FPGA_EXCEPTION if input parameter fpga handle is not - * valid. - * FPGA_NO_MEMORY if memory allocation fails or system - * doesn't configure huge pages. - */ -fpga_result fpgaGetUmsgPtr(fpga_handle handle, uint64_t **umsg_ptr); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // __FPGA_UMSG_H__ diff --git a/sw/include/opae/userclk.h b/sw/include/opae/userclk.h deleted file mode 100644 index 3a1879731..000000000 --- a/sw/include/opae/userclk.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright(c) 2018, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** - * @file userclk.h - * @brief Functions for setting and get afu user clock -*/ - -#ifndef __FPGA_AFU_USER_CLOCK_H__ -#define __FPGA_AFU_USER_CLOCK_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * set afu user clock high and low - * @param[in] handle Handle to previously opened accelerator resource. - * @param[in] high_clk AFU High user clock frequency in MHz. - * @param[in] low_clk AFU Low user clock frequency in MHz. - * @param[in] flags Flags Reserved. - * -.*@returns FPGA_OK on success. FPGA_INVALID_PARAM if invalid parameters were provided, or - * if the parameter combination is not valid. FPGA_EXCEPTION if an internal - * exception occurred while trying to access the handle. - */ -fpga_result fpgaSetUserClock(fpga_handle handle, - uint64_t high_clk, uint64_t low_clk, int flags); - -/** - * Get afu user clock high and low - * @param[in] handle Handle to previously opened accelerator resource. - * @param[out] high_clk AFU High user clock frequency in MHz. - * @param[out] low_clk AFU Low user clock frequency in MHz. - * @param[in] flags Flags Reserved. - * - .*@returns FPGA_OK on success. FPGA_INVALID_PARAM if invalid parameters were provided, or - * if the parameter combination is not valid. FPGA_EXCEPTION if an internal - * exception occurred while trying to access the handle. - */ -fpga_result fpgaGetUserClock(fpga_handle handle, - uint64_t *high_clk, uint64_t *low_clk, int flags); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // __FPGA_AFU_USER_CLOCK_H__ diff --git a/sw/include/opae/utils.h b/sw/include/opae/utils.h deleted file mode 100644 index 2675233ab..000000000 --- a/sw/include/opae/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright(c) 2017, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** - * \file utils.h - * \brief Utility functions and macros for the FPGA API - */ - -#ifndef __FPGA_UTILS_H__ -#define __FPGA_UTILS_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Return human-readable error message - * - * Returns a pointer to a human-readable error message corresponding to the - * provided fpga_error error code. - * - * @param[in] e Error code (as returned by another FPGA API function - * @returns Pointer to a descriptive error message string - */ -const char *fpgaErrStr(fpga_result e); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // __FPGA_UTILS_H__ - diff --git a/sw/include/opae/version.h b/sw/include/opae/version.h deleted file mode 100644 index 5f96ecc13..000000000 --- a/sw/include/opae/version.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright(c) 2017, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#ifndef __FPGA_VERSION_H__ -#define __FPGA_VERSION_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Get version information about the OPAE library - * - * Retrieve major version, minor version, and revision information about the - * OPAE library. - * - * @param[out] version FPGA version - * @returns FPGA_INVALID_PARAM if any of the output parameters is NULL, FPGA_OK - * otherwise. - */ -fpga_result fpgaGetOPAECVersion(fpga_version *version); - -/** - * Get version information about the OPAE library as a string - * - * Retrieve major version, minor version, and revision information about the - * OPAE library, encoded in a human-readable string (e.g. "1.0.0"). - * - * @param[out] version_str String to copy version information into - * @param[in] len Length of `version_str` - * @returns FPGA_INVALID_PARAM if `version_str` is NULL, FPGA_EXCEPTION if the - * version string cannot be copied into `version_str`, FPGA_OK otherwise. - */ -fpga_result fpgaGetOPAECVersionString(char *version_str, size_t len); -#define FPGA_VERSION_STR_MAX 10 - -/** - * Get build information about the OPAE library as a string - * - * Retrieve the build identifier of the OPAE library. - * - * @param[out] build_str String to copy build information into - * @param[in] len Length of `build_str` - * @returns FPGA_INVALID_PARAM if `build_str` is NULL, FPGA_EXCEPTION if the - * version string cannot be copied into `build_str`, FPGA_OK otherwise. - */ -fpga_result fpgaGetOPAECBuildString(char *build_str, size_t len); -#define FPGA_BUILD_STR_MAX 41 - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // __FPGA_VERSION_H__ diff --git a/sw/include/opae/vfio.h b/sw/include/opae/vfio.h deleted file mode 100644 index b5f617d9b..000000000 --- a/sw/include/opae/vfio.h +++ /dev/null @@ -1,542 +0,0 @@ -// Copyright(c) 2020-2023, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** - * @file opae/vfio.h - * @brief APIs to manage a PCIe device via vfio-pci. - * - * Presents a simple interface for interacting with a PCIe device that is - * bound to the vfio-pci driver. - * See https://kernel.org/doc/Documentation/vfio.txt for a description of - * vfio-pci. - * - * Provides APIs for opening/closing the device, querying info about the - * MMIO regions of the device, and allocating/mapping and freeing/unmapping - * DMA buffers. - */ - -#ifndef __OPAE_VFIO_H__ -#define __OPAE_VFIO_H__ - -#include -#include -#include - -#include -#include -#include - -/** - * IO Virtual Address Range - * - * A range of allocatable IOVA offsets. Used for mapping DMA buffers. - */ -struct opae_vfio_iova_range { - uint64_t start; /**< Start of this range of offsets. */ - uint64_t end; /**< End of this range of offsets. */ - struct opae_vfio_iova_range *next; /**< Pointer to next in list. */ -}; - -/** - * VFIO group - * - * Each device managed by vfio-pci belongs to a VFIO group rooted at - * /dev/vfio/N, where N is the group number. - */ -struct opae_vfio_group { - char *group_device; /**< Full path to the group device. */ - int group_fd; /**< File descriptor for the group device. */ -}; - -/** - * MMIO sparse-mappable region info - * - * Describes a range of sparse-mappable MMIO, for MMIO ranges that have - * non-contiguous addresses. - */ -struct opae_vfio_sparse_info { - uint32_t index; /**< Region index, from 0. */ - uint32_t offset; /**< Offset of sparse region. */ - uint32_t size; /**< Size of sparse region. */ - uint8_t *ptr; /**< Virtual address of sparse region. */ - struct opae_vfio_sparse_info *next; /**< Pointer to next in list. */ -}; - -/** - * MMIO region info - * - * Describes a range of mappable MMIO. - */ -struct opae_vfio_device_region { - uint32_t region_index; /**< Region index, from 0. */ - uint8_t *region_ptr; /**< Virtual address of region. */ - size_t region_size; /**< Size of region. */ - struct opae_vfio_sparse_info *region_sparse; /**< For sparse regions. */ - struct opae_vfio_device_region *next; /**< Pointer to next in list. */ -}; - -/** - * Interrupt info - * - * Describes an interrupt capability. - */ -struct opae_vfio_device_irq { - uint32_t flags; /**< Flags. See struct vfio_irq_info. */ - uint32_t index; /**< The IRQ index. */ - uint32_t count; /**< Number of IRQs at this index. */ - int32_t *event_fds; /**< Event file descriptors. */ - int32_t *masks; /**< IRQ masks. */ - struct opae_vfio_device_irq *next; /**< Pointer to next in list. */ -}; - -/** - * VFIO device - * - * Each VFIO device has a file descriptor that is used to query - * information about the device MMIO regions and config space. - */ -struct opae_vfio_device { - int device_fd; /**< Device file descriptor. */ - uint64_t device_config_offset; /**< Offset of PCIe config space. */ - uint32_t device_num_regions; /**< Total MMIO region count. */ - struct opae_vfio_device_region *regions; /**< Region list pointer. */ - uint32_t device_num_irqs; /**< IRQ index count. */ - struct opae_vfio_device_irq *irqs; /**< IRQ list pointer. */ -}; - -/** - * System DMA buffer - * - * Describes a system memory address space that is capable of DMA. - */ -struct opae_vfio_buffer { - uint8_t *buffer_ptr; /**< Buffer virtual address. */ - size_t buffer_size; /**< Buffer size. */ - uint64_t buffer_iova; /**< Buffer IOVA address. */ - int flags; /**< See opae_vfio_buffer_flags. */ -}; - -/** - * OPAE VFIO device abstraction - * - * This structure is used to interact with the OPAE VFIO API. It tracks - * data related to the VFIO container, group, and device. A mutex is - * provided for thread safety. - */ -struct opae_vfio { - pthread_mutex_t lock; /**< For thread safety. */ - char *cont_device; /**< "/dev/vfio/vfio" */ - char *cont_pciaddr; /**< PCIe address, eg 0000:00:00.0 */ - int cont_fd; /**< Container file descriptor. */ - struct opae_vfio_iova_range *cont_ranges; /**< List of IOVA ranges. */ - struct mem_alloc iova_alloc; /**< Allocator for IOVA space. */ - struct opae_vfio_group group; /**< The VFIO device group. */ - struct opae_vfio_device device; /**< The VFIO device. */ - opae_hash_map cont_buffers; /**< Map of allocated DMA buffers. */ -}; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Open and populate a VFIO device - * - * Opens the PCIe device corresponding to the address given in pciaddr. - * The device must be bound to the vfio-pci driver prior to opening it. - * The data structures corresponding to IOVA space, MMIO regions, - * and DMA buffers are initialized. - * - * @param[out] v Storage for the device info. May be stack-resident. - * @param[in] pciaddr The PCIe address of the requested device. - * @returns Non-zero on error. Zero on success. - * - * Example - * @code{.sh} - * $ sudo opaevfio -i 0000:00:00.0 -u user -g group - * @endcode - * - * Example - * @code{.c} - * opae_vfio v; - * - * if (opae_vfio_open(&v, "0000:00:00.0")) { - * // handle error - * } - * @endcode - */ -int opae_vfio_open(struct opae_vfio *v, - const char *pciaddr); - -/** - * Open and populate a VFIO device - * - * Opens the PCIe device corresponding to the address given in pciaddr, - * using the VF token (GUID) given in token. - * The device must be bound to the vfio-pci driver prior to opening it. - * The data structures corresponding to IOVA space, MMIO regions, - * and DMA buffers are initialized. - * - * @param[out] v Storage for the device info. May be stack-resident. - * @param[in] pciaddr The PCIe address of the requested device. - * @param[in] token The GUID representing the VF token. - * @returns Non-zero on error. Zero on success. - * - * Example - * @code{.sh} - * $ sudo opaevfio -i 0000:00:00.0 -u user -g group - * @endcode - * - * Example - * @code{.c} - * opae_vfio v; - * - * if (opae_vfio_secure_open(&v, "0000:00:00.0", - * "00f5ad6b-2edd-422e-9d1e-34124c686fec")) { - * // handle error - * } - * @endcode - */ -int opae_vfio_secure_open(struct opae_vfio *v, - const char *pciaddr, - const char *token); - -/** - * Query device MMIO region - * - * Retrieves info describing the MMIO region with the given region index. - * The device structure v must have been previously opened by a call - * to opae_vfio_open. - * - * @param[in] v The open OPAE VFIO device. - * @param[in] index The zero-based index of the desired MMIO region. - * @param[out] ptr Optional pointer to receive the virtual address - * for the region. Pass NULL to ignore. - * @param[out] size Optional pointer to receive the size of the MMIO - * region. Pass NULL to ignore. - * @returns Non-zero on error (including index out-of-range). Zero on success. - * - * Example - * @code{.c} - * opae_vfio v; - * - * uint8_t *fme_virt = NULL; - * uint8_t *port_virt = NULL; - * size_t fme_size = 0; - * size_t port_size = 0; - * - * if (opae_vfio_open(&v, "0000:00:00.0")) { - * // handle error - * } else { - * opae_vfio_region_get(&v, 0, &fme_virt, &fme_size); - * opae_vfio_region_get(&v, 2, &port_virt, &port_size); - * } - * @endcode - */ -int opae_vfio_region_get(struct opae_vfio *v, - uint32_t index, - uint8_t **ptr, - size_t *size); - -/** - * Allocate and map system buffer - * - * Allocate, map, and retrieve info for a system buffer capable of - * DMA. Saves an entry in the v->cont_buffers list. If the buffer - * is not explicitly freed by opae_vfio_buffer_free, it will be - * freed during opae_vfio_close. - * - * mmap is used for the allocation. If the size is greater than 2MB, - * then the allocation request is fulfilled by a 1GB huge page. Else, - * if the size is greater than 4096, then the request is fulfilled by - * a 2MB huge page. Else, the request is fulfilled by the non-huge - * page pool. - * - * @note Allocations from the huge page pool require that huge pages - * be configured on the system. Huge pages may be configured on the - * kernel boot command prompt. - * Example - * default_hugepagesz=1G hugepagesz=1G hugepages=2 hugepagesz=2M hugepages=8 - * - * @note Huge pages may also be configured at runtime. - * Example - * sudo sh -c 'echo 8 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages' - * sudo sh -c 'echo 2 > /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages' - * - * @note Be sure that the IOMMU is also enabled using the follow kernel - * boot command: intel_iommu=on - * - * @param[in, out] v The open OPAE VFIO device. - * @param[in, out] size A pointer to the requested size. The size - * may be rounded to the next page size prior - * to return from the function. - * @param[out] buf Optional pointer to receive the virtual address - * for the buffer. Pass NULL to ignore. - * @param[out] iova Optional pointer to receive the IOVA address - * for the buffer. Pass NULL to ignore. - * @returns Non-zero on error. Zero on success. - * - * Example - * @code{.c} - * opae_vfio v; - * - * size_t sz; - * uint8_t *buf_2m_virt = NULL; - * uint8_t *buf_1g_virt = NULL; - * uint64_t buf_2m_iova = 0; - * uint64_t buf_1g_iova = 0; - * - * if (opae_vfio_open(&v, "0000:00:00.0")) { - * // handle error - * } else { - * sz = 2 * 1024 * 1024; - * if (opae_vfio_buffer_allocate(&v, - * &sz, - * &buf_2m_virt, - * &buf_2m_iova)) { - * // handle allocation error - * } - * - * sz = 1024 * 1024 * 1024; - * if (opae_vfio_buffer_allocate(&v, - * &sz, - * &buf_1g_virt, - * &buf_1g_iova)) { - * // handle allocation error - * } - * } - * @endcode - */ -int opae_vfio_buffer_allocate(struct opae_vfio *v, - size_t *size, - uint8_t **buf, - uint64_t *iova); - -/** Flags for opae_vfio_buffer_allocate_ex(). - */ -enum opae_vfio_buffer_flags { - OPAE_VFIO_BUF_PREALLOCATED = 1, /**< Use existing buffer */ -}; - -/** - * Allocate and map system buffer (extended w/ flags) - * - * Allocate, map, and retrieve info for a system buffer capable of - * DMA. Saves an entry in the v->cont_buffers list. If the buffer - * is not explicitly freed by opae_vfio_buffer_free, it will be - * freed during opae_vfio_close, unless OPAE_VFIO_BUF_PREALLOCATED - * is used in which case the buffer is not freed by this library. - * - * When not using OPAE_VFIO_BUF_PREALLOCATED, mmap is used for the - * allocation. If the size is greater than 2MB, then the allocation - * request is fulfilled by a 1GB huge page. Else, if the size is - * greater than 4096, then the request is fulfilled by a 2MB huge - * page. Else, the request is fulfilled by the non-huge page pool. - * - * @param[in, out] v The open OPAE VFIO device. - * @param[in, out] size A pointer to the requested size. The size - * may be rounded to the next page size prior - * to return from the function. - * @param[out] buf Optional pointer to receive the virtual address - * for the buffer/input buffer pointer when - * using OPAE_VFIO_BUF_PREALLOCATED. Pass NULL - * to ignore. - * @param[out] iova Optional pointer to receive the IOVA address - * for the buffer. Pass NULL to ignore. - * @returns Non-zero on error. Zero on success. - * - * Example - * @code{.c} - * opae_vfio v; - * - * size_t sz = MY_BUF_SIZE; - * uint8_t *prealloc_virt = NULL; - * uint64_t iova = 0; - * - * prealloc_virt = allocate_my_buffer(sz); - * - * if (opae_vfio_open(&v, "0000:00:00.0")) { - * // handle error - * } else { - * if (opae_vfio_buffer_allocate_ex(&v, - * &sz, - * &prealloc_virt, - * &iova, - * OPAE_VFIO_BUF_PREALLOCATED)) { - * // handle allocation error - * } - * } - * @endcode - */ -int opae_vfio_buffer_allocate_ex(struct opae_vfio *v, - size_t *size, - uint8_t **buf, - uint64_t *iova, - int flags); - -/** - * Extract the internal data structure pointer for the given vaddr - * - * The virtual address vaddr must correspond to a buffer previously - * allocated by opae_vfio_buffer_allocate() or - * opae_vfio_buffer_allocate_ex(). - * - * @param[in] v The open OPAE VFIO device. - * @param[in] vaddr The user virtual address of the desired buffer - * info struct. - * @returns NULL on lookup error. - */ -struct opae_vfio_buffer *opae_vfio_buffer_info(struct opae_vfio *v, - uint8_t *vaddr); - -/** - * Unmap and free a system buffer - * - * The buffer corresponding to buf must have been created by a - * previous call to opae_vfio_buffer_allocate. - * - * @param[in, out] v The open OPAE VFIO device. - * @param[in] buf The virtual address corresponding to - * the buffer to be freed. - * @returns Non-zero on error. Zero on success. - * - * Example - * @code{.c} - * size_t sz; - * uint8_t *buf_2m_virt = NULL; - * uint64_t buf_2m_iova = 0; - * - * sz = 2 * 1024 * 1024; - * if (opae_vfio_buffer_allocate(&v, - * &sz, - * &buf_2m_virt, - * &buf_2m_iova)) { - * // handle allocation error - * } else { - * // use the buffer - * - * if (opae_vfio_buffer_free(&v, buf_2m_virt)) { - * // handle free error - * } - * } - * @endcode - */ -int opae_vfio_buffer_free(struct opae_vfio *v, - uint8_t *buf); - -/** - * Enable an IRQ - * - * @param[in, out] v The open OPAE VFIO device. - * @param[in] index The IRQ category. For MSI-X, - * use VFIO_PCI_MSIX_IRQ_INDEX. - * @param[in] subindex The IRQ to enable. - * @param[in] event_fd The file descriptor, created - * by eventfd(). Interrupts will - * result in this event_fd being - * signaled. - * @returns Non-zero on error. Zero on success. - */ -int opae_vfio_irq_enable(struct opae_vfio *v, - uint32_t index, - uint32_t subindex, - int event_fd); - -/** - * Unmask an IRQ - * - * @param[in, out] v The open OPAE VFIO device. - * @param[in] index The IRQ category. For MSI-X, - * use VFIO_PCI_MSIX_IRQ_INDEX. - * @param[in] subindex The IRQ to unmask. - * @returns Non-zero on error. Zero on success. - */ -int opae_vfio_irq_unmask(struct opae_vfio *v, - uint32_t index, - uint32_t subindex); - -/** - * Mask an IRQ - * - * @param[in, out] v The open OPAE VFIO device. - * @param[in] index The IRQ category. For MSI-X, - * use VFIO_PCI_MSIX_IRQ_INDEX. - * @param[in] subindex The IRQ to mask. - * @returns Non-zero on error. Zero on success. - */ -int opae_vfio_irq_mask(struct opae_vfio *v, - uint32_t index, - uint32_t subindex); - -/** - * Disable an IRQ - * - * @param[in, out] v The open OPAE VFIO device. - * @param[in] index The IRQ category. For MSI-X, - * use VFIO_PCI_MSIX_IRQ_INDEX. - * @param[in] subindex The IRQ to disable. - * @returns Non-zero on error. Zero on success. - */ -int opae_vfio_irq_disable(struct opae_vfio *v, - uint32_t index, - uint32_t subindex); - -/** - * Release and close a VFIO device - * - * The given device pointer must have been previously initialized by - * opae_vfio_open. Releases all data structures, including any DMA - * buffer allocations that have not be explicitly freed by - * opae_vfio_buffer_free. - * - * @param[in] v Storage for the device info. May be stack-resident. - * - * Example - * @code{.c} - * opae_vfio v; - * - * if (opae_vfio_open(&v, "0000:00:00.0")) { - * // handle error - * } else { - * // interact with the device - * ... - * // free the device - * opae_vfio_close(&v); - * } - * @endcode - * - * Example - * @code{.sh} - * $ sudo opaevfio -r 0000:00:00.0 - * @endcode - */ -void opae_vfio_close(struct opae_vfio *v); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // __OPAE_VFIO_H__ diff --git a/sw/install_guide/installation_guide/index.html b/sw/install_guide/installation_guide/index.html deleted file mode 100644 index 3f75038ae..000000000 --- a/sw/install_guide/installation_guide/index.html +++ /dev/null @@ -1,2452 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - OPAE Installation Guide - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - - - - - -
-
- - - - - - - -

OPAE Installation Guide

-

How to download the OPAE SDK

-

OPAE SDK releases are available on GitHub. -Source code for the OPAE DFL device driver for Linux is also available on GitHub.

-

Install the Fedora

-

Download the Fedora (x86_64 version) installation file in fedora, and install the Fedora in yourserver. You can choose Fedora Workstation or Fedora server.

-

Build the kernel and DFL drivers

-

For building the OPAE kernel and kernel driver, the kernel development environment is required. So before you build the kernel, you must install the required packages. Run the following commands:

-
subscription-manager release --set=8.6
-sudo dnf update
-
-# If you require the use of a proxy, add it to DNF using by editing the following file
-sudo nano /etc/dnf/dnf.conf
-# Include your proxy by adding the following line, replacing the URL with your proxy's URL
-# proxy=http://proxy.server.com:port
-sudo dnf update
-subscription-manager repos --enable codeready-builder-for-rhel-8-x86_64-rpms
-sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
-
-sudo dnf install -y python3 python3-pip python3-devel \
-gdb vim git gcc gcc-c++ make cmake libuuid-devel rpm-build systemd-devel nmap \
-python3-jsonschema json-c-devel tbb-devel rpmdevtools libcap-devel \
-python3-pyyaml hwloc-devel libedit-devel git kernel-headers kernel-devel elfutils-libelf-devel ncurses-devel openssl-devel bison flex cli11-devel spdlog-devel
-
-python3 -m pip install --user jsonschema virtualenv pudb pyyaml
-
-sudo pip3 uninstall setuptools
-
-sudo pip3 install Pybind11==2.10.0 --proxy http://yourproxy:xxx
-
-sudo pip3 install setuptools==59.6.0 --prefix=/usr --proxy http://yourproxy:xxx
-
-wget http://ftp.pbone.net/mirror/archive.fedoraproject.org/epel/8.4/Everything/x86_64/Packages/p/pybind11-devel-2.4.3-2.el8.x86_64.rpm
-
-wget http://ftp.pbone.net/mirror/archive.fedoraproject.org/epel/8.4/Everything/x86_64/Packages/p/python3-pybind11-2.4.3-2.el8.x86_64.rpm
-
-sudo dnf localinstall ./python3-pybind11-2.4.3-2.el8.x86_64.rpm ./pybind11-devel-2.4.3-2.el8.x86_64.rpm -y
-
-

Download the OPAE upstream kernel tree from github, for example download from fpga-ofs-dev-5.15-lts branch. -

git clone https://github.com/OFS/linux-dfl
-cd linux-dfl
-git checkout tags/ofs-2023.1-6.1-1
-

-

Note: The linux-dfl repository is roughly 5 GB in size

-

Building and Installing the OFS DFL Kernel Drivers from Source

-
    -
  1. The following set of instructions walk you through copying an existing kernel configuration file on your machine and changing the minimal required configuration settings:
  2. -
-
cd linux-dfl
-cp /boot/config-`uname -r` .config
-cat configs/dfl-config >> .config
-echo 'CONFIG_LOCALVERSION="-dfl"' >> .config
-echo 'CONFIG_LOCALVERSION_AUTO=y' >> .config
-sed -i -r 's/CONFIG_SYSTEM_TRUSTED_KEYS=.*/CONFIG_SYSTEM_TRUSTED_KEYS=""/' .config
-sed -i '/^CONFIG_DEBUG_INFO_BTF/ s/./#&/' .config
-echo 'CONFIG_DEBUG_ATOMIC_SLEEP=y' >> .config
-make olddefconfig
-
-
-

Note: The above command may report errors resembling symbol value 'm' invalid for CHELSIO_IPSEC_INLINE. These errors indicate that the nature of the config has changed between the currently executing kernel and the kernel being built. The option "m" for a particular kernel module is no longer a valid option, and the default behavior is to simply turn the option off. However the option can likely be turned back on by setting it to 'y'. If the user wants to turn the option back on, change it to 'y' and re-run "make olddefconfig":

-
cd /home/OFS/linux-dfl
-echo 'CONFIG_CHELSIO_IPSEC_INLINE=y' >> .config
-make olddefconfig
-
-

(Optional) To use the built-in GUI menu for editing kernel configuration parameters, you can opt to run make menuconfig.

-
-

2. Linux kernel builds take advantage of multiple processors to parallelize the build process. Display how many processors are available with the nproc command, and then specify how many make threads to utilize with the -j option. Note that number of threads can exceed the number of processors. In this case, the number of threads are set to the number of processors in the system

-
$ make -j $(nproc)
-$ sudo make modules_install -j $(nproc)
-$ sudo make install
-
-

Build linux DFL Kernel instructions please also refer to: https://github.com/OPAE/linux-dfl/wiki/Build-the-linux-dfl-kernel

-

Locally building a set of RPM/DEP packages.

-
    -
  1. -

    This first flow will directly install the kernel and kernel module files without the need to create a package first:

    -
    cd /<your_path>/linux-dfl
    -make INSTALL_MOD_STRIP=1 binrpm-pkg
    -
    -
  2. -
  3. -

    By default a directory is created in your home directory called rpmbuild. This directory will house all of the kernel packages which have been built. You need to navigate to the newly built kernel packages and install them. The following files were generated using the build command executed in the previous step:

    -
    cd ~/rpmbuild/RPMS/x86_64
    -ls
    -kernel-${{ env.DFL_KERNEL_NAME }}.x86_64.rpm  kernel-headers-${{ env.DFL_KERNEL_NAME }}.x86_64.rpm
    -sudo dnf localinstall kernel*.rpm
    -
    -
  4. -
  5. -

    When install finished, reboot your system. - When the system login again, verify the kernel version is correct. For example:

    -
  6. -
-
[figo@localhost linux-dfl]$ uname -r
-${{ env.DFL_KERNEL_NAME }}
-
-

And also you can check the OPAE dfl drivers have auto-loaded. -

[figo@localhost linux-dfl]$ lsmod | grep fpga
-ifpga_sec_mgr          20480  1 intel_m10_bmc_secure
-fpga_region            20480  3 dfl_fme_region,dfl_fme,dfl
-fpga_bridge            24576  4 dfl_fme_region,fpga_region,dfl_fme,dfl_fme_br
-fpga_mgr               16384  4 dfl_fme_region,fpga_region,dfl_fme_mgr,dfl_fme
-[figo@localhost linux-dfl]$ lsmod | grep dfl
-dfl_eth_group          36864  0
-dfl_fme_region         20480  0
-dfl_emif               16384  0
-dfl_n3000_nios         20480  0
-dfl_fme_br             16384  0
-dfl_fme_mgr            20480  1
-dfl_fme                49152  0
-dfl_afu                36864  0
-dfl_pci                20480  0
-dfl                    40960  7 dfl_pci,dfl_fme,dfl_fme_br,dfl_eth_group,dfl_n3000_nios,dfl_afu,dfl_emif
-fpga_region            20480  3 dfl_fme_region,dfl_fme,dfl
-fpga_bridge            24576  4 dfl_fme_region,fpga_region,dfl_fme,dfl_fme_br
-fpga_mgr               16384  4 dfl_fme_region,fpga_region,dfl_fme_mgr,dfl_fme
-

-
    -
  1. Two kernel parameters must be added to the boot commandline for the newly installed kernel. First, open the file grub:
  2. -
-
sudo vim /etc/default/grub
-
-
    -
  1. In the variable GRUB_CMDLINE_LINUX add the following parameters in bold: GRUB_CMDLINE_LINUX="crashkernel=auto resume=/dev/mapper/cl-swap rd.lvm.lv=cl/root rd.lvm.lv=cl/swap rhgb quiet intel_iommu=on pcie=realloc hugepagesz=2M hugepages=200"
  2. -
-

Note: If you wish to instead set hugepages on a per session bassis, you can perform the following steps. These settings will be lost on reboot.

-
mkdir -p /mnt/huge 
-mount -t hugetlbfs nodev /mnt/huge 
-echo 2048 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages 
-echo 2048 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages 
-
-
    -
  1. Save your edits, then apply them to the GRUB2 configuration file.
  2. -
-
sudo grub2-mkconfig
-
-
    -
  1. Warm reboot. Your kernel parameter changes should have taken affect.
  2. -
-
cat /proc/cmdline
-BOOT_IMAGE=(hd1,gpt2)/vmlinuz-${{ env.DFL_KERNEL_NAME }} root=/dev/mapper/cl-root ro crashkernel=auto resume=/dev/mapper/cl-swap rd.lvm.lv=cl/root rd.lvm.lv=cl/swap intel_iommu=on pcie=realloc hugepagesz=2M hugepages=200 rhgb quiet
-
-

Build the OPAE-SDK

-

Before you build the OPAE SDK, you must install the required packages. Run the following commands:

-

Rocky Linux 8.5

-
dnf install -y 'dnf-command(config-manager)'
-dnf config-manager --set-enabled powertools
-dnf install -y epel-release
-dnf check-update
-dnf upgrade -y
-dnf install -y python3 python3-pip python3-devel python3-jsonschema python3-pyyaml python3-pybind11 git gcc gcc-c++ make cmake libuuid-devel json-c-devel hwloc-devel tbb-devel cli11-devel spdlog-devel libedit-devel systemd-devel rpm-build rpmdevtools pybind11-devel yaml-cpp-devel libudev-devel linuxptp rsync 
-python3 -m pip install jsonschema virtualenv pyyaml
-
-

Fedora

-
dnf check-update
-dnf upgrade -y
-dnf install -y python3 python3-pip python3-devel python3-jsonschema python3-pyyaml python3-pybind11 git gcc g++ make cmake libuuid-devel json-c-devel hwloc-devel tbb-devel libedit-devel rpm-build rpmdevtools pybind11-devel yaml-cpp-devel libudev-devel cli11-devel spdlog-devel linuxptp rsync
-pip3 install jsonschema virtualenv pyyaml
-
-

Ubuntu 20.04

-
apt-get update
-apt-get upgrade -y
-apt-get install -y python3 python3-pip python3-dev git gcc g++ make cmake uuid-dev libjson-c-dev libhwloc-dev libtbb-dev libedit-dev libudev-dev linuxptp pandoc devscripts debhelper doxygen rsync
-pip3 install jsonschema virtualenv pyyaml pybind11
-
-

RHEL 8.2

-

Register and enable Red Hat subscription to install any packages on the system.

-
subscription-manager register --proxy=PROXY --username=USER --password=PASSWORD --auto-attach
-
-

Set the RHEL version and install packages. Set proxy name and port number.

-
# If you require the use of a proxy, add it to DNF using by editing the following file
-sudo nano /etc/dnf/dnf.conf
-# Include your proxy by adding the following line, replacing the URL with your proxy's URL
-# proxy=http://proxy.server.com:port
-sudo dnf update
-subscription-manager release --set=8.2 --proxy proxy-name.com:port number
-subscription-manager repos --enable codeready-builder-for-rhel-8-x86_64-rpms
-sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
-
-sudo dnf install -y python3 python3-pip python3-devel \
-gdb vim git gcc gcc-c++ make cmake libuuid-devel rpm-build systemd-devel nmap \
-python3-jsonschema json-c-devel tbb-devel rpmdevtools libcap-devel \
-python3-pyyaml hwloc-devel libedit-devel git kernel-headers kernel-devel elfutils-libelf-devel ncurses-devel openssl-devel bison flex cli11-devel spdlog-devel
-
-python3 -m pip install --user jsonschema virtualenv pudb pyyaml
-
-sudo pip3 uninstall setuptools
-
-sudo pip3 install Pybind11==2.10.0 --proxy http://yourproxy:xxx
-
-sudo pip3 install setuptools==59.6.0 --prefix=/usr --proxy http://yourproxy:xxx
-
-wget http://ftp.pbone.net/mirror/archive.fedoraproject.org/epel/8.4/Everything/x86_64/Packages/p/pybind11-devel-2.4.3-2.el8.x86_64.rpm
-
-wget http://ftp.pbone.net/mirror/archive.fedoraproject.org/epel/8.4/Everything/x86_64/Packages/p/python3-pybind11-2.4.3-2.el8.x86_64.rpm
-
-sudo dnf localinstall ./python3-pybind11-2.4.3-2.el8.x86_64.rpm ./pybind11-devel-2.4.3-2.el8.x86_64.rpm -y
-
-

Install the latest version of cmake on top of the outdated cmake package from the package manager.

-
# cd cmake-3.25.1/
-# ./bootstrap --prefix=/usr
-# make
-# make install
-# which cmake
-/usr/bin/cmake
-
-

Create opae-sdk packages

-

Download the OPAE-SDK source code from github. For example, download from Master branch.

-
$ git clone https://github.com/OPAE/opae-sdk.git
-$ cd opae-sdk
-$ git checkout tags/2.5.0-3
-
-

Compile and build the OPAE-SDK RPMs (Fedora, Rocky, RHEL 8.2). -

$ cd opae-sdk/packaging/opae/rpm
-$ ./create fedora
-

-

OPAE Package Description

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Package NameDescription
opaeOPAE SDK is a collection of libraries and tools to facilitate the development of software applications and accelerators using OPAE. It provides a library implementing the OPAE C API for presenting a streamlined and easy-to-use interface for software applications to discover, access, and manage FPGA devices and accelerators using the OPAE software stack.
opae-debuginfoThis package provides debug information for package opae. Debug information is useful when developing applications that use this package or when debugging this package.
opae-debugsourceThis package provides debug sources for package opae. Debug sources are useful when developing applications that use this package or when debugging this package.
opae-develOPAE headers, tools, sample source, and documentation
opae-devel-debuginfoThis package provides debug information for package opae-devel. Debug information is useful when developing applications that use this package or when debugging this package.
opae-toolsThis package contains OPAE base tools binaries
opae-extra-toolsAdditional OPAE tools
opae-extra-tools-debuginfoThis package provides debug information for package opae-extra-tools. Debug information is useful when developing applications that use this package or when debugging this package.
-

Note that if you find that your distribution has changed package names such that there is a conflict -when building RPMs, you can install all of the build dependencies so that the SDK compiles and then -build the RPMs in unrestricted mode:

-
$ cd opae-sdk/packaging/opae/rpm
-$ ./create unrestricted
-
-

After a successful compile, there are 3 rpm packages generated (Fedora, Rocky, RHEL8.2). For example: -

opae-2.5.0-3.fc34.x86_64.rpm
-opae-devel-2.5.0-3.fc34.x86_64.rpm
-opae-extra-tools-2.5.0-3.fc34.x86_64.rpm
-

-

Compile and build the OPAE-SDK deb packages (Ubuntu 22.04). -

$ cd opae-sdk/packaging/opae/deb
-$ ./create
-

-

After a successful compile, there are 3 deb packages generated (Ubuntu 22.04). For example: -

opae_2.5.0-3_amd64.deb  
-opae-devel_2.5.0-3_amd64.deb  
-opae-extra-tools_2.5.0-3_amd64.deb
-

-

OPAE SDK installation with rpm/deb packages

-

The rpm packages generated in the previous step can be installed using these commands:

-
rm -rf opae-2.5.0-3.el8.src.rpm
-sudo dnf localinstall -y opae*.rpm
-
-

Check that all packages have been installed:

-
[user@localhost opae-sdk]# rpm -qa | grep opae
-opae-packager-2.5.0-3.x86_64
-opae-devel-2.5.0-3.x86_64
-opae-PACSign-2.5.0-3.x86_64
-opae-tools-extra-2.5.0-3.x86_64
-opae-2.5.0-3.x86_64
-opae-tools-2.5.0-3.x86_64
-opae-libs-2.5.0-3.x86_64
-opae-opae.admin-2.5.0-3.x86_64
-opae-tests-2.5.0-3.x86_64
-
-

The deb packages generated in the previous step can be installed using these commands:

-
rm -rf opae-2.5.0-3_amd64.deb
-sudo dpkg -i  ./*.deb
-
-

When you installed the rpms, you can run fpgainfo command to check the FPGA FME infomation. For example: -

[figo@localhost install_guide]$ fpgainfo fme
-Board Management Controller, xxxx NIOS FW version: xxxxxx
-Board Management Controller, xxxx Build version: xxxxx
-//****** FME ******//
-Object Id                        : 0xEF00000
-PCIe s:b:d.f                     : 0000:08:00.0
-Device Id                        : 0x0B30
-Socket Id                        : 0x00
-Ports Num                        : 01
-Bitstream Id                     : 0x2300011001030F
-Bitstream Version                : 0.2.3
-Pr Interface Id                  : f3c99413-5081-4aad-bced-07eb84a6d0bb
-Boot Page                        : user
-

-

To uninstall the OPAE rpms, you can use this commands -

$ dnf list installed | grep opae
-$ sudo dnf remove opae*.x86_64
-

-

To uninstall the OPAE deb, you can use this commands -

$ dpkg -l  | grep opae
-$ dpkg -r opae-extra-tools:amd64
-$ dpkg -r opae-devel:amd64
-$ dpkg -r opae
-

-

FPGA Device Access Permissions

-

Access to FPGA accelerators and devices is controlled using file access permissions on the -Intel® FPGA device files, /dev/dfl-fme.* and /dev/dfl-port.*, as well as to the files reachable through /sys/class/fpga_region/.

-

In order to allow regular (non-root) users to access accelerators, you need to grant them read and write permissions on /dev/dfl-port.* (with * denoting the respective socket, i.e. 0 or 1). E.g.:

-
$ sudo chmod a+rw /dev/dfl-port.0
-
-

Memlock limit

-

Depending on the requirements of your application, you may also want to -increase the maximum amount of memory a user process is allowed to lock. The -exact way to do this depends on your Linux distribution.

-

You can check the current memlock limit using

-
$ ulimit -l
-
-

A way to permanently remove the limit for locked memory for a regular user is -to add the following lines to your /etc/security/limits.conf:

-
user1    hard   memlock           unlimited
-user1    soft   memlock           unlimited
-
-

This removes the limit on locked memory for user user1. To remove it for -all users, you can replace user1 with *:

-
*    hard   memlock           unlimited
-*    soft   memlock           unlimited
-
-

Note that settings in the /etc/security/limits.conf file don't apply to -services. To increase the locked memory limit for a service you need to -modify the application's systemd service file and add the line:

-
[Service]
-LimitMEMLOCK=infinity
-
-

Hugepage Settings

-

Users need to configure system hugepages to reserve 2MB-hugepages or -1GB-hugepages. For example, the 'hello_fpga' sample requires several -2MB-hugepages. And the fpgadiag tool requires several 1GB-hugepages.

-

The command below reserves 20 2M-hugepages:

-
$ sudo sh -c 'echo 20 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages'
-
-

The command below reserves 4 1GB-hugepages:

-
$ sudo sh -c 'echo 4 > /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages'
-
-

For x86_64 architecture processors, user can use following command to find out avaiable hugepage sizes:

-
$ grep pse /proc/cpuinfo | uniq
-flags : ... pse ...
-
-

If this commands returns a non-empty string, 2MB pages are supported.

-
$ grep pse /proc/cpuinfo | uniq
-flags : ... pdpe1gb ...
-
-

If this commands returns a non-empty string, 1GB pages are supported.

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/pyopae/python_bindings/index.html b/sw/pyopae/python_bindings/index.html deleted file mode 100644 index 7356f71e5..000000000 --- a/sw/pyopae/python_bindings/index.html +++ /dev/null @@ -1,2034 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - OPAE Python Bindings - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

OPAE Python Bindings

-

OPAE (Open Programmable Acceleration Engine) now includes Python bindings for interacting with FPGA resources. The OPAE Python API is built on top of the OPAE C++ Core API and its object model. Because of this, developing OPAE applications in Python is very similar to developing OPAE applications in C++ which significantly reduces the learning curve required to adapt to the Python API. While the object model remains the same, some static factory functions in the OPAE C++ Core API have been moved to module level methods in the OPAE Python API with the exception of the properties class. The goal of the OPAE Python API is to enable fast prototyping, test automation, infrastructure managment, and an easy to use framework for FPGA resource interactions that don’t rely on software algorithms with a high runtime complexity.

-

Currently, the only Python package that is part of OPAE is opae.fpga

-

Implementation

-

The OPAE Python API is implemented by creating a Python extension using pybind11 <http://pybind11.readthedocs.io/en/stable>. This extension is created by using the pybind11 API which relies mostly on macros and compile time introspection to define the module initialization point as well as type converters between OPAE C++ Core types and OPAE Python types.

-

Benefits

-

The major benefits of using pybind11 for developing the OPAE Python API include, but are not limited to, the following features of pybind11:

-
    -
  • Uses C++ 11 standard library although it can use C++ 14 or C++17.
  • -
  • Automatic conversions of shared_ptr types
  • -
  • Built-in support for numpy and Eigen numerical libraries
  • -
  • Interoperable with the Python C API
  • -
-

Runtime Requirements

-

Because opae.fpga is built on top of the opae-cxx-core API, it does require that the runtime libraries for both opae-cxx-core and opae-c be installed on the system (as well as any other libraries they depend on). Those libraries can be installed using the opae-libs package (from either RPM or DEB format - depending on your Linux distribution).

-

Installation

-

Python Wheels

-

The preferred method of installation is to use a binary wheel package for your version of Python.

-

The following table lists example names for different Python versions and platforms.

-

| Python Version | Python ABI | Linux Platform | Package Name | |—————-|—————–|—————-|————–| | 2.7 | CPython w/ UCS4 | x86_64 | opae.fpga.-cp27-cp27mu-linux_x86_64.whl | | 3.4 | CPython w/ UCS4 | x86_64 | opae.fpga.-cp34-cp34mu-linux_x86_64.whl | | 3.6 | CPython w/ UCS4 | x86_64 | opae.fpga.-cp36-cp36mu-linux_x86_64.whl |

-

opae.fpga is currently not available in the Python Package Index but once it does become available, one should be able to install using pip by simply typing the following:

-
> pip install --user opae.fpga
-
-

Installing From Source

-

In addition to the runtime libraries mentioned above, installing from source does require that the OPAE header files be installed as well as those header files for pybind11. The former can be installed with the opae-devel package and the latter can be installed by installing pybind11 Python module.

-

Example Installation

-

The following example shows how to build from source by installing the prerequisites before running the setup.py file.

-
>sudo yum install opae-libs-<release>.x86_64.rpm
->sudo yum install opae-devel-<release>.x86_64.rpm
->pip install --user pybind11
->pip install --user opae.fpga-<release>.tar.gz
-
-

NOTE: The pip examples above use the --user flag to avoid requiring root permissions. Those packages will be installed in the user’s site-packages directory found in the user’s .local directory.

-

Example Scripts

-

The following example is an implementation of the sample, hello_fpga.c, which is designed to configure the NLB0 diagnostic accelerator for a simple loopback.

-
import time
-from opae import fpga
-
-NLB0 = "d8424dc4-a4a3-c413-f89e-433683f9040b"
-CTL = 0x138
-CFG = 0x140
-NUM_LINES = 0x130
-SRC_ADDR = 0x0120
-DST_ADDR = 0x0128
-DSM_ADDR = 0x0110
-DSM_STATUS = 0x40
-
-def cl_align(addr):
-    return addr >> 6
-
-tokens = fpga.enumerate(type=fpga.ACCELERATOR, guid=NLB0)
-assert tokens, "Could not enumerate accelerator: {}".format(NlB0)
-
-with fpga.open(tokens[0], fpga.OPEN_SHARED) as handle:
-    src = fpga.allocate_shared_buffer(handle, 4096)
-    dst = fpga.allocate_shared_buffer(handle, 4096)
-    dsm = fpga.allocate_shared_buffer(handle, 4096)
-    handle.write_csr32(CTL, 0)
-    handle.write_csr32(CTL, 1)
-    handle.write_csr64(DSM_ADDR, dsm.io_address())
-    handle.write_csr64(SRC_ADDR, cl_align(src.io_address())) # cacheline-aligned
-    handle.write_csr64(DST_ADDR, cl_align(dst.io_address())) # cacheline-aligned
-    handle.write_csr32(CFG, 0x42000)
-    handle.write_csr32(NUM_LINES, 4096/64)
-    handle.write_csr32(CTL, 3)
-    while dsm[DSM_STATUS] & 0x1 == 0:
-        time.sleep(0.001)
-    handle.write_csr32(CTL, 7)
-
-

This example shows how one might reprogram (Partial Reconfiguration) an accelerator on a given bus, 0x5e, using a bitstream file, m0.gbs.

-
from opae import fpga
-
-BUS = 0x5e
-GBS = 'm0.gbs'
-tokens = fpga.enumerate(type=fpga.DEVICE, bus=BUS)
-assert tokens, "Could not enumerate device on bus: {}".format(BUS)
-with open(GBS, 'rb') as fd, fpga.open(tokens[0]) as device:
-    device.reconfigure(0, fd)
-
- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/sw/samples/hello_events/CMakeLists.txt b/sw/samples/hello_events/CMakeLists.txt deleted file mode 100644 index fdee8994c..000000000 --- a/sw/samples/hello_events/CMakeLists.txt +++ /dev/null @@ -1,46 +0,0 @@ -## Copyright(c) 2014-2023, Intel Corporation -## -## Redistribution and use in source and binary forms, with or without -## modification, are permitted provided that the following conditions are met: -## -## * Redistributions of source code must retain the above copyright notice, -## this list of conditions and the following disclaimer. -## * Redistributions in binary form must reproduce the above copyright notice, -## this list of conditions and the following disclaimer in the documentation -## and/or other materials provided with the distribution. -## * Neither the name of Intel Corporation nor the names of its contributors -## may be used to endorse or promote products derived from this software -## without specific prior written permission. -## -## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -## ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -## LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -## POSSIBILITY OF SUCH DAMAGE. - -opae_add_executable(TARGET hello_events - SOURCE - hello_events.c - ${opae-test_ROOT}/framework/mock/opae_std.c - LIBS - argsfilter - opae-c - ${json-c_LIBRARIES} - ${uuid_LIBRARIES} - COMPONENT samplebin -) - -target_include_directories(hello_events - PRIVATE - ${OPAE_LIB_SOURCE}/argsfilter -) - -install(FILES hello_events.c - DESTINATION src/opae/samples/hello_events - COMPONENT samplesrc) diff --git a/sw/samples/hello_events/hello_events.c b/sw/samples/hello_events/hello_events.c deleted file mode 100644 index e8b0cf29c..000000000 --- a/sw/samples/hello_events/hello_events.c +++ /dev/null @@ -1,345 +0,0 @@ -// Copyright(c) 2017-2021, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** - * @file hello_events.c - * @brief A code sample of using OPAE event API. - * - * This sample starts two processes. One process injects an artificial fatal - * error to sysfs; while the other tries to asynchronously capture and handle - * the event. This - * sample code exercises all major functions of the event API, including - * creating and destroying event handles, register and unregister events, - * polling on event file descriptor, and getting the OS object associated with - * an event. For a full discussion of OPAE event API, refer to event.h. - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif // HAVE_CONFIG_H -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "mock/opae_std.h" - -int usleep(unsigned); - -#define FME_SYSFS_INJECT_ERROR "errors/inject_errors" - -#define ON_ERR_GOTO(res, label, desc) \ - do { \ - if ((res) != FPGA_OK) { \ - print_err((desc), (res)); \ - goto label; \ - } \ - } while (0) - -void print_err(const char *s, fpga_result res) -{ - fprintf(stderr, "Error %s: %s\n", s, fpgaErrStr(res)); -} - -// RAS Error Inject CSR -struct ras_inject_error { - union { - uint64_t csr; - struct { - /* Catastrophic error */ - uint64_t catastrophicr_error : 1; - /* Fatal error */ - uint64_t fatal_error : 1; - /* Non-fatal error */ - uint64_t nonfatal_error : 1; - /* Reserved */ - uint64_t rsvd : 61; - }; - }; -}; - -fpga_result inject_ras_fatal_error(fpga_token fme_token, uint8_t err) -{ - fpga_result res1 = FPGA_OK; - fpga_result res2 = FPGA_OK; - fpga_handle fme_handle = NULL; - struct ras_inject_error inj_error = { {0} }; - fpga_object inj_err_object; - - res1 = fpgaOpen(fme_token, &fme_handle, FPGA_OPEN_SHARED); - if (res1 != FPGA_OK) { - OPAE_ERR("Failed to open FPGA"); - return res1; - } - - res1 = fpgaHandleGetObject(fme_handle, FME_SYSFS_INJECT_ERROR, &inj_err_object, 0); - ON_ERR_GOTO(res1, out_close, "Failed to get Handle Object"); - - // Inject fatal error - inj_error.fatal_error = err; - - res1 = fpgaObjectWrite64(inj_err_object, inj_error.csr, 0); - ON_ERR_GOTO(res1, out_destroy_obj, "Failed to Read Object"); - -out_destroy_obj: - res2 = fpgaDestroyObject(&inj_err_object); - ON_ERR_GOTO(res2, out_close, "Failed to Destroy Object"); -out_close: - res2 = fpgaClose(fme_handle); - if (res2 != FPGA_OK) { - OPAE_ERR("Failed to close FPGA"); - } - - return res1 != FPGA_OK ? res1 : res2; -} - -void *error_thread(void *arg) -{ - fpga_token token = (fpga_token) arg; - fpga_result res; - - usleep(5000000); - printf("injecting error\n"); - res = inject_ras_fatal_error(token, 1); - if (res != FPGA_OK) - print_err("setting inject error register", res); - - usleep(5000000); - printf("clearing error\n"); - res = inject_ras_fatal_error(token, 0); - if (res != FPGA_OK) - print_err("clearing inject error register", res); - - return NULL; -} - -void help(void) -{ - printf("\n" - "hello_events\n" - "OPAE Events API sample\n" - "\n" - "Usage:\n" - " hello_events [-hv] [-S ] [-B ] [-D ] [-F ] [PCI_ADDR]\n" - "\n" - " -h,--help Print this help\n" - " -v,--version Print version info and exit\n" - "\n"); -} - -/* - * Parse command line arguments - */ -#define GETOPT_STRING "hv" -fpga_result parse_args(int argc, char *argv[]) -{ - struct option longopts[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'v' }, - { NULL, 0, NULL, 0 } - }; - - int getopt_ret; - int option_index; - - while (-1 != (getopt_ret = getopt_long(argc, argv, GETOPT_STRING, longopts, &option_index))) { - const char *tmp_optarg = optarg; - /* checks to see if optarg is null and if not goes to value of optarg */ - if ((optarg) && ('=' == *tmp_optarg)) { - ++tmp_optarg; - } - - switch (getopt_ret) { - case 'h': /* help */ - help(); - return -1; - - case 'v': /* version */ - printf("hello_events %s %s%s\n", - OPAE_VERSION, - OPAE_GIT_COMMIT_HASH, - OPAE_GIT_SRC_TREE_DIRTY ? "*":""); - return -1; - - default: /* invalid option */ - fprintf(stderr, "Invalid cmdline options\n"); - return FPGA_EXCEPTION; - } - } - - return FPGA_OK; -} - -fpga_result find_fpga(fpga_properties device_filter, - fpga_token *fpga, - uint32_t *num_matches) -{ - fpga_properties filter = NULL; - fpga_result res = FPGA_OK; - fpga_result dres = FPGA_OK; - - res = fpgaCloneProperties(device_filter, &filter); - ON_ERR_GOTO(res, out, "cloning properties object"); - - res = fpgaPropertiesSetObjectType(filter, FPGA_DEVICE); - ON_ERR_GOTO(res, out_destroy, "setting interface ID"); - - res = fpgaEnumerate(&filter, 1, fpga, 1, num_matches); - ON_ERR_GOTO(res, out_destroy, "enumerating FPGAs"); - -out_destroy: - dres = fpgaDestroyProperties(&filter); - ON_ERR_GOTO(dres, out, "destroying properties object"); -out: - return (res == FPGA_OK) ? dres : res; -} - -int main(int argc, char *argv[]) -{ - fpga_token fpga_device_token = NULL; - fpga_handle fpga_device_handle = NULL; - uint32_t num_matches = 1; - fpga_result res1 = FPGA_OK; - fpga_result res2 = FPGA_OK; - fpga_event_handle eh; - uint64_t count = 0; - int res; - struct pollfd pfd; - int timeout = 10000; - int poll_ret = 0; - ssize_t bytes_read = 0; - pthread_t errthr; - fpga_properties device_filter = NULL; - - res1 = fpgaGetProperties(NULL, &device_filter); - if (res1) { - print_err("failed to alloc properties", res1); - return res1; - } - - if (opae_set_properties_from_args(device_filter, - &res1, - &argc, - argv)) { - print_err("failed arg parse", res1); - res1 = FPGA_EXCEPTION; - goto out_exit; - } else if (res1) { - print_err("failed to set properties", res1); - goto out_exit; - } - - res1 = parse_args(argc, argv); - if ((int)res1 < 0) - goto out_exit; - ON_ERR_GOTO(res1, out_exit, "parsing arguments"); - - res1 = find_fpga(device_filter, &fpga_device_token, &num_matches); - ON_ERR_GOTO(res1, out_exit, "finding FPGA accelerator"); - - if (num_matches < 1) { - fprintf(stderr, "No matches for address provided.\n"); - res1 = FPGA_NOT_FOUND; - goto out_exit; - } - - if (num_matches > 1) { - fprintf(stderr, "Found more than one suitable slot.\n"); - } - - res1 = fpgaOpen(fpga_device_token, &fpga_device_handle, FPGA_OPEN_SHARED); - ON_ERR_GOTO(res1, out_destroy_tok, "opening accelerator"); - - res1 = fpgaCreateEventHandle(&eh); - ON_ERR_GOTO(res1, out_close, "creating event handle"); - - res1 = fpgaRegisterEvent(fpga_device_handle, FPGA_EVENT_ERROR, eh, 0); - ON_ERR_GOTO(res1, out_destroy_eh, "registering an FME event"); - - printf("Waiting for interrupts now...\n"); - - res = pthread_create(&errthr, NULL, error_thread, fpga_device_token); - if (res) { - printf("Failed to create error_thread.\n"); - res1 = FPGA_EXCEPTION; - goto out_destroy_eh; - } - - - res1 = fpgaGetOSObjectFromEventHandle(eh, &pfd.fd); - ON_ERR_GOTO(res1, out_join, "getting file descriptor"); - - pfd.events = POLLIN; - poll_ret = poll(&pfd, 1, timeout); - - if (poll_ret < 0) { - printf("Poll error errno = %s\n", strerror(errno)); - res1 = FPGA_EXCEPTION; - goto out_join; - } else if (poll_ret == 0) { - printf("Poll timeout occurred\n"); - res1 = FPGA_EXCEPTION; - goto out_join; - } else { - printf("FME Interrupt occurred\n"); - bytes_read = opae_read(pfd.fd, &count, sizeof(count)); - if (bytes_read <= 0) - printf("WARNING: error reading from poll fd: %s\n", - bytes_read < 0 ? strerror(errno) : "zero bytes read"); - } - - res1 = fpgaUnregisterEvent(fpga_device_handle, FPGA_EVENT_ERROR, eh); - ON_ERR_GOTO(res1, out_join, "unregistering an FME event"); - - printf("Successfully tested Register/Unregister for FME events!\n"); - -out_join: - pthread_join(errthr, NULL); - -out_destroy_eh: - res2 = fpgaDestroyEventHandle(&eh); - ON_ERR_GOTO(res2, out_close, "deleting event handle"); - -out_close: - res2 = fpgaClose(fpga_device_handle); - ON_ERR_GOTO(res2, out_destroy_tok, "closing accelerator"); - -out_destroy_tok: - res2 = fpgaDestroyToken(&fpga_device_token); - ON_ERR_GOTO(res2, out_exit, "destroying token"); - -out_exit: - fpgaDestroyProperties(&device_filter); - return res1 != FPGA_OK ? res1 : res2; -} diff --git a/sw/samples/hello_fpga/CMakeLists.txt b/sw/samples/hello_fpga/CMakeLists.txt deleted file mode 100644 index bfc985d17..000000000 --- a/sw/samples/hello_fpga/CMakeLists.txt +++ /dev/null @@ -1,46 +0,0 @@ -## Copyright(c) 2014-2023, Intel Corporation -## -## Redistribution and use in source and binary forms, with or without -## modification, are permitted provided that the following conditions are met: -## -## * Redistributions of source code must retain the above copyright notice, -## this list of conditions and the following disclaimer. -## * Redistributions in binary form must reproduce the above copyright notice, -## this list of conditions and the following disclaimer in the documentation -## and/or other materials provided with the distribution. -## * Neither the name of Intel Corporation nor the names of its contributors -## may be used to endorse or promote products derived from this software -## without specific prior written permission. -## -## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -## ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -## LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -## POSSIBILITY OF SUCH DAMAGE. - -opae_add_executable(TARGET hello_fpga - SOURCE - hello_fpga.c - ${opae-test_ROOT}/framework/mock/opae_std.c - LIBS - argsfilter - opae-c - ${json-c_LIBRARIES} - ${uuid_LIBRARIES} - COMPONENT samplebin -) - -target_include_directories(hello_fpga - PRIVATE - ${OPAE_LIB_SOURCE}/argsfilter -) - -install(FILES hello_fpga.c - DESTINATION src/opae/samples/hello_fpga - COMPONENT samplesrc) diff --git a/sw/samples/hello_fpga/hello_fpga.c b/sw/samples/hello_fpga/hello_fpga.c deleted file mode 100644 index d017eca23..000000000 --- a/sw/samples/hello_fpga/hello_fpga.c +++ /dev/null @@ -1,544 +0,0 @@ -// Copyright(c) 2017-2022, Intel Corporation -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Intel Corporation nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -/** - * @file hello_fpga.c - * @brief A code sample illustrates the basic usage of the OPAE C API. - * - * The sample is a host application that demonstrates the basic steps of - * interacting with FPGA using the OPAE library. These steps include: - * - * - FPGA enumeration - * - Resource acquiring and releasing - * - Managing shared memory buffer - * - MMIO read and write - * - * The sample also demonstrates OPAE's object model, such as tokens, handles, - * and properties. - * - * The sample requires a native loopback mode (NLB) test image to be loaded on - * the FPGA. Refer to - * Quick - * Start Guide for full instructions on building, configuring, and running - * this code sample. - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif // HAVE_CONFIG_H -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "mock/opae_std.h" - -int usleep(unsigned); - -#ifndef TEST_TIMEOUT -#define TEST_TIMEOUT 30000 -#endif // TEST_TIMEOUT - -#ifndef CL -# define CL(x) ((x) * 64) -#endif // CL -#ifndef LOG2_CL -# define LOG2_CL 6 -#endif // LOG2_CL -#ifndef MB -# define MB(x) ((x) * 1024 * 1024) -#endif // MB - -#define CACHELINE_ALIGNED_ADDR(p) ((p) >> LOG2_CL) - -#define LPBK1_BUFFER_SIZE MB(1) -#define LPBK1_BUFFER_ALLOCATION_SIZE MB(2) -#define LPBK1_DSM_SIZE MB(2) -#define CSR_SRC_ADDR 0x0120 -#define CSR_DST_ADDR 0x0128 -#define CSR_CTL 0x0138 -#define CSR_STATUS1 0x0168 -#define CSR_CFG 0x0140 -#define CSR_NUM_LINES 0x0130 -#define DSM_STATUS_TEST_COMPLETE 0x40 -#define CSR_AFU_DSM_BASEL 0x0110 - -/* NLB0 AFU_ID */ -#define NLB0_AFUID "D8424DC4-A4A3-C413-F89E-433683F9040B" - -/* NLB0 AFU_ID for N3000 */ -#define N3000_AFUID "9AEFFE5F-8457-0612-C000-C9660D824272" -#define FPGA_NLB0_UUID_H 0xd8424dc4a4a3c413 -#define FPGA_NLB0_UUID_L 0xf89e433683f9040b - - -/* - * macro to check return codes, print error message, and goto cleanup label - * NOTE: this changes the program flow (uses goto)! - */ -#define ON_ERR_GOTO(res, label, desc) \ - do { \ - if ((res) != FPGA_OK) { \ - print_err((desc), (res)); \ - goto label; \ - } \ - } while (0) - -/* Type definitions */ -typedef struct { - uint32_t uint[16]; -} cache_line; - -void print_err(const char *s, fpga_result res) -{ - fprintf(stderr, "Error %s: %s\n", s, fpgaErrStr(res)); -} - -/* - * Global configuration of bus, set during parse_args() - * */ -struct config { - int open_flags; - int run_n3000; -} - -config = { - .open_flags = 0, - .run_n3000 = 0 -}; - -void help(void) -{ - printf("\n" - "hello_fpga\n" - "OPAE Native Loopback 0 (NLB0) sample\n" - "\n" - "Usage:\n" - " hello_fpga [-schv] [-S ] [-B ] [-D ] [-F ] [PCI_ADDR]\n" - "\n" - " -s,--shared Open accelerator in shared mode\n" - " -c,--n3000 Assume N3000 MMIO layout\n" - " -h,--help Print this help\n" - " -v,--version Print version info and exit\n" - "\n"); -} - -#define GETOPT_STRING "hscv" -fpga_result parse_args(int argc, char *argv[]) -{ - struct option longopts[] = { - { "help", no_argument, NULL, 'h' }, - { "shared", no_argument, NULL, 's' }, - { "n3000", no_argument, NULL, 'c' }, - { "version", no_argument, NULL, 'v' }, - { NULL, 0, NULL, 0 } - }; - - int getopt_ret; - int option_index; - - char version[32]; - char build[32]; - - while (-1 != (getopt_ret = getopt_long(argc, argv, GETOPT_STRING, - longopts, &option_index))) { - const char *tmp_optarg = optarg; - /* Checks to see if optarg is null and if not it goes to value of optarg */ - if ((optarg) && ('=' == *tmp_optarg)) { - ++tmp_optarg; - } - - switch (getopt_ret) { - case 'h': - help(); - return -1; - case 's': - config.open_flags |= FPGA_OPEN_SHARED; - break; - case 'c': - config.run_n3000 = 1; - break; - case 'v': - fpgaGetOPAECVersionString(version, sizeof(version)); - fpgaGetOPAECBuildString(build, sizeof(build)); - printf("hello_fpga %s %s\n", - version, build); - return -1; - - default: /* invalid option */ - fprintf(stderr, "Invalid cmdline option \n"); - return FPGA_EXCEPTION; - } - } - - return FPGA_OK; -} - -fpga_result find_fpga(fpga_properties device_filter, - fpga_guid afu_guid, - fpga_token *accelerator_token, - uint32_t *num_matches_accelerators) -{ - fpga_properties filter = NULL; - fpga_result res1; - fpga_result res2 = FPGA_OK; - - res1 = fpgaCloneProperties(device_filter, &filter); - ON_ERR_GOTO(res1, out, "cloning properties object"); - - res1 = fpgaPropertiesSetObjectType(filter, FPGA_ACCELERATOR); - ON_ERR_GOTO(res1, out_destroy, "setting object type"); - - res1 = fpgaPropertiesSetGUID(filter, afu_guid); - ON_ERR_GOTO(res1, out_destroy, "setting GUID"); - - res1 = fpgaEnumerate(&filter, 1, accelerator_token, 1, num_matches_accelerators); - ON_ERR_GOTO(res1, out_destroy, "enumerating accelerators"); - -out_destroy: - res2 = fpgaDestroyProperties(&filter); - ON_ERR_GOTO(res2, out, "destroying properties object"); -out: - return res1 != FPGA_OK ? res1 : res2; -} - -/* Is the FPGA simulated with ASE? */ -bool probe_for_ase(void) -{ - fpga_result r = FPGA_OK; - uint16_t device_id = 0; - fpga_properties filter = NULL; - uint32_t num_matches = 1; - fpga_token fme_token; - - /* Connect to the FPGA management engine */ - fpgaGetProperties(NULL, &filter); - fpgaPropertiesSetObjectType(filter, FPGA_DEVICE); - - /* Connecting to one is sufficient to find ASE */ - fpgaEnumerate(&filter, 1, &fme_token, 1, &num_matches); - if (0 != num_matches) { - /* Retrieve the device ID of the FME */ - fpgaDestroyProperties(&filter); - fpgaGetProperties(fme_token, &filter); - r = fpgaPropertiesGetDeviceID(filter, &device_id); - fpgaDestroyToken(&fme_token); - } - fpgaDestroyProperties(&filter); - - /* ASE's device ID is 0xa5e */ - return ((FPGA_OK == r) && (0xa5e == device_id)); -} - -fpga_result find_nlb_n3000(fpga_handle accelerator_handle, - uint64_t *afu_baddr) -{ - - fpga_result res1 = FPGA_OK; - int end_of_list = 0; - int nlb0_found = 0; - uint64_t header = 0; - uint64_t uuid_hi = 0; - uint64_t uuid_lo = 0; - uint64_t next_offset = 0; - uint64_t nlb0_offset = 0; - - /* find NLB0 in AFU */ - do { - // Read the next feature header - res1 = fpgaReadMMIO64(accelerator_handle, 0, nlb0_offset, &header); - ON_ERR_GOTO(res1, out_exit, "fpgaReadMMIO64"); - res1 = fpgaReadMMIO64(accelerator_handle, 0, nlb0_offset+8, &uuid_lo); - ON_ERR_GOTO(res1, out_exit, "fpgaReadMMIO64"); - res1 = fpgaReadMMIO64(accelerator_handle, 0, nlb0_offset+16, &uuid_hi); - ON_ERR_GOTO(res1, out_exit, "fpgaReadMMIO64"); - // printf("%zx: %zx %zx %zx\n", nlb0_offset, header, uuid_lo, uuid_hi); - if ((((header >> 60) & 0xf) == 0x1) && - (uuid_lo == FPGA_NLB0_UUID_L) && (uuid_hi == FPGA_NLB0_UUID_H)) { - nlb0_found = 1; - break; - } - // End of the list flag - end_of_list = (header >> 40) & 1; - // Move to the next feature header - next_offset = (header >> 16) & 0xffffff; - if ((next_offset == 0xffff) || (next_offset == 0)) { - nlb0_found = 0; - break; - } - nlb0_offset = nlb0_offset + next_offset; - } while (!end_of_list); - - if (!nlb0_found) { - printf("AFU NLB0 not found\n"); - return FPGA_EXCEPTION; - } - - printf("AFU NLB0 found @ %zx\n", nlb0_offset); - *afu_baddr = nlb0_offset; - return FPGA_OK; - -out_exit: - return FPGA_EXCEPTION; -} - -int main(int argc, char *argv[]) -{ - fpga_token accelerator_token; - fpga_handle accelerator_handle; - fpga_guid guid; - uint32_t num_matches_accelerators = 0; - uint32_t use_ase; - - volatile uint64_t *dsm_ptr = NULL; - volatile uint64_t *status_ptr = NULL; - volatile uint64_t *input_ptr = NULL; - volatile uint64_t *output_ptr = NULL; - - uint64_t dsm_wsid; - uint64_t input_wsid; - uint64_t output_wsid; - uint32_t i; - uint32_t timeout; - fpga_result res1 = FPGA_OK; - fpga_result res2 = FPGA_OK; - fpga_properties device_filter = NULL; - - res1 = fpgaGetProperties(NULL, &device_filter); - if (res1 != FPGA_OK) { - print_err("failed to allocate properties.\n", res1); - return 1; - } - - if (opae_set_properties_from_args(device_filter, - &res1, - &argc, - argv)) { - print_err("failed arg parse.\n", res1); - res1 = FPGA_EXCEPTION; - goto out_exit; - } else if (res1) { - print_err("failed to set properties.\n", res1); - goto out_exit; - } - - res1 = parse_args(argc, argv); - if ((int)res1 < 0) - goto out_exit; - ON_ERR_GOTO(res1, out_exit, "parsing arguments"); - - if (config.run_n3000) { - if (uuid_parse(N3000_AFUID, guid) < 0) - res1 = FPGA_EXCEPTION; - } else { - if (uuid_parse(NLB0_AFUID, guid) < 0) - res1 = FPGA_EXCEPTION; - } - - ON_ERR_GOTO(res1, out_exit, "parsing guid"); - - use_ase = probe_for_ase(); - if (use_ase) { - printf("Running in ASE mode\n"); - } - - /* Look for accelerator with NLB0_AFUID */ - res1 = find_fpga(device_filter, - guid, - &accelerator_token, - &num_matches_accelerators); - ON_ERR_GOTO(res1, out_exit, "finding FPGA accelerator"); - - if (num_matches_accelerators == 0) { - res1 = FPGA_NOT_FOUND; - } - ON_ERR_GOTO(res1, out_exit, "no matching accelerator"); - - if (num_matches_accelerators > 1) { - printf("Found more than one suitable accelerator. "); - } - - - /* Open accelerator and map MMIO */ - res1 = fpgaOpen(accelerator_token, &accelerator_handle, config.open_flags); - ON_ERR_GOTO(res1, out_destroy_tok, "opening accelerator"); - - res1 = fpgaMapMMIO(accelerator_handle, 0, NULL); - ON_ERR_GOTO(res1, out_close, "mapping MMIO space"); - - - /* Allocate buffers */ - res1 = fpgaPrepareBuffer(accelerator_handle, LPBK1_DSM_SIZE, - (void **)&dsm_ptr, &dsm_wsid, 0); - ON_ERR_GOTO(res1, out_close, "allocating DSM buffer"); - - res1 = fpgaPrepareBuffer(accelerator_handle, LPBK1_BUFFER_ALLOCATION_SIZE, - (void **)&input_ptr, &input_wsid, 0); - ON_ERR_GOTO(res1, out_free_dsm, "allocating input buffer"); - - res1 = fpgaPrepareBuffer(accelerator_handle, LPBK1_BUFFER_ALLOCATION_SIZE, - (void **)&output_ptr, &output_wsid, 0); - ON_ERR_GOTO(res1, out_free_input, "allocating output buffer"); - - printf("Running Test\n"); - - /* Initialize buffers */ - memset((void *)dsm_ptr, 0, LPBK1_DSM_SIZE); - memset((void *)input_ptr, 0xAF, LPBK1_BUFFER_SIZE); - memset((void *)output_ptr, 0xBE, LPBK1_BUFFER_SIZE); - - cache_line *cl_ptr = (cache_line *)input_ptr; - for (i = 0; i < LPBK1_BUFFER_SIZE / CL(1); ++i) { - cl_ptr[i].uint[15] = i+1; /* set the last uint in every cacheline */ - } - - - /* Reset accelerator */ - res1 = fpgaReset(accelerator_handle); - ON_ERR_GOTO(res1, out_free_output, "resetting accelerator"); - - uint64_t nlb_base_addr = 0; - - if (config.run_n3000) { - res1 = find_nlb_n3000(accelerator_handle, &nlb_base_addr); - ON_ERR_GOTO(res1, out_free_output, "finding nlb in AFU"); - } - - /* Program DMA addresses */ - uint64_t iova = 0; - res1 = fpgaGetIOAddress(accelerator_handle, dsm_wsid, &iova); - ON_ERR_GOTO(res1, out_free_output, "getting DSM IOVA"); - - res1 = fpgaWriteMMIO64(accelerator_handle, 0, nlb_base_addr + CSR_AFU_DSM_BASEL, iova); - ON_ERR_GOTO(res1, out_free_output, "writing CSR_AFU_DSM_BASEL"); - - res1 = fpgaWriteMMIO32(accelerator_handle, 0, nlb_base_addr + CSR_CTL, 0); - ON_ERR_GOTO(res1, out_free_output, "writing CSR_CFG"); - res1 = fpgaWriteMMIO32(accelerator_handle, 0, nlb_base_addr + CSR_CTL, 1); - ON_ERR_GOTO(res1, out_free_output, "writing CSR_CFG"); - - res1 = fpgaGetIOAddress(accelerator_handle, input_wsid, &iova); - ON_ERR_GOTO(res1, out_free_output, "getting input IOVA"); - res1 = fpgaWriteMMIO64(accelerator_handle, 0, nlb_base_addr + CSR_SRC_ADDR, CACHELINE_ALIGNED_ADDR(iova)); - ON_ERR_GOTO(res1, out_free_output, "writing CSR_SRC_ADDR"); - - res1 = fpgaGetIOAddress(accelerator_handle, output_wsid, &iova); - ON_ERR_GOTO(res1, out_free_output, "getting output IOVA"); - res1 = fpgaWriteMMIO64(accelerator_handle, 0, nlb_base_addr + CSR_DST_ADDR, CACHELINE_ALIGNED_ADDR(iova)); - ON_ERR_GOTO(res1, out_free_output, "writing CSR_DST_ADDR"); - - res1 = fpgaWriteMMIO32(accelerator_handle, 0, nlb_base_addr + CSR_NUM_LINES, LPBK1_BUFFER_SIZE / CL(1)); - ON_ERR_GOTO(res1, out_free_output, "writing CSR_NUM_LINES"); - res1 = fpgaWriteMMIO32(accelerator_handle, 0, nlb_base_addr + CSR_CFG, 0x42000); - ON_ERR_GOTO(res1, out_free_output, "writing CSR_CFG"); - - status_ptr = dsm_ptr + DSM_STATUS_TEST_COMPLETE/sizeof(uint64_t); - - - /* Start the test */ - res1 = fpgaWriteMMIO32(accelerator_handle, 0, nlb_base_addr + CSR_CTL, 3); - ON_ERR_GOTO(res1, out_free_output, "writing CSR_CFG"); - - /* Wait for test completion */ - timeout = TEST_TIMEOUT; - while (0 == ((*status_ptr) & 0x1)) { - usleep(100); - if (!use_ase && (--timeout == 0)) { - res1 = FPGA_EXCEPTION; - ON_ERR_GOTO(res1, out_free_output, "test timed out"); - } - } - - /* Stop the device */ - res1 = fpgaWriteMMIO32(accelerator_handle, 0, nlb_base_addr + CSR_CTL, 7); - ON_ERR_GOTO(res1, out_free_output, "writing CSR_CFG"); - - /* Wait for the AFU's read/write traffic to complete */ - uint32_t afu_traffic_trips = 0; - while (afu_traffic_trips < 100) { - /* - * CSR_STATUS1 holds two 32 bit values: num pending reads and writes. - * Wait for it to be 0. - */ - uint64_t s1; - res1 = fpgaReadMMIO64(accelerator_handle, 0, nlb_base_addr + CSR_STATUS1, &s1); - ON_ERR_GOTO(res1, out_free_output, "reading CSR_STATUS1"); - if (s1 == 0) { - break; - } - - afu_traffic_trips += 1; - usleep(1000); - } - - /* Check output buffer contents */ - for (i = 0; i < LPBK1_BUFFER_SIZE; i++) { - if (((uint8_t *)output_ptr)[i] != ((uint8_t *)input_ptr)[i]) { - fprintf(stderr, "Output does NOT match input " - "at offset %i!\n", i); - break; - } - } - - printf("Done Running Test\n"); - - - /* Release buffers */ -out_free_output: - res2 = fpgaReleaseBuffer(accelerator_handle, output_wsid); - ON_ERR_GOTO(res2, out_free_input, "releasing output buffer"); -out_free_input: - res2 = fpgaReleaseBuffer(accelerator_handle, input_wsid); - ON_ERR_GOTO(res2, out_free_dsm, "releasing input buffer"); -out_free_dsm: - res2 = fpgaReleaseBuffer(accelerator_handle, dsm_wsid); - ON_ERR_GOTO(res2, out_unmap, "releasing DSM buffer"); - - /* Unmap MMIO space */ -out_unmap: - res2 = fpgaUnmapMMIO(accelerator_handle, 0); - ON_ERR_GOTO(res2, out_close, "unmapping MMIO space"); - - /* Release accelerator */ -out_close: - res2 = fpgaClose(accelerator_handle); - ON_ERR_GOTO(res2, out_destroy_tok, "closing accelerator"); - - /* Destroy token */ -out_destroy_tok: - res2 = fpgaDestroyToken(&accelerator_token); - ON_ERR_GOTO(res2, out_exit, "destroying token"); - -out_exit: - fpgaDestroyProperties(&device_filter); - return res1 != FPGA_OK ? res1 : res2; -} diff --git a/sw/tod/tod/index.html b/sw/tod/tod/index.html deleted file mode 100644 index f400b6ba9..000000000 --- a/sw/tod/tod/index.html +++ /dev/null @@ -1,2012 +0,0 @@ - - - - - - - - - - - - - - - - - - Time of Day (ToD) # - OFS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

Time of Day (ToD)

-

SYNOPSIS

-

The Intel FPGA ToD driver in the kernel space exposes ToD IP as PHC (PTP Hardware Clock) device to the Linux PTP (Precision Time Protocol) stack to synchronize the system clock to its ToD information. -The phc2sys utility of Linux PTP stack is used to access ToD information and synchronize the system clock.

-

Install the Linux PTP utilities: -

# sudo yum install linuxptp
-

-

phc_ctl and phc2sys utilities (linuxptp package) are used to control the PHC device and synchronize the system clock to its ToD information.

-

phc_ctl: directly controls PHC device clock. -

Usage: phc_ctl [options] <device> -- [command]
-
-    device         ethernet or ptp clock device
-
-Options:
-    -l [num]       set the logging level to 'num'
-    -q             do not print messages to the syslog
-    -Q             do not print messages to stdout
-    -v             prints the software version and exits
-    -h             prints this message and exits
-
-Commands:
- specify commands with arguments. Can specify multiple commands to be executed in order. 
- Seconds are read as double precision floating point values.
-
-    set  [seconds]  set PHC time (defaults to time on CLOCK_REALTIME)
-    get             get PHC time
-    adj  <seconds>  adjust PHC time by offset
-    freq [ppb]      adjust PHC frequency (default returns current offset)
-    cmp             compare PHC offset to CLOCK_REALTIME
-    caps            display device capabilities (default if no command given)
-    wait <seconds>  pause between commands
-                    This command may be useful for sanity checking whether the PHC clock is
-                    running as expected.
-                    The arguments specified in seconds are read as double precision floating point
-                    values, and will scale to nanoseconds. This means providing a value of 5.5 means 5
-                    and one half seconds. This allows specifying fairly precise values for time.
-

-

phc2sys: synchronize two clocks. -

Usage: phc2sys [options]
-
-Automatic configuration:
-    -a             turn on autoconfiguration
-    -r             synchronize system (realtime) clock
-                   repeat -r to consider it also as a time source
-
-Manual configuration:
-    -c [dev|name]  slave clock (CLOCK_REALTIME)
-    -d [dev]       master PPS device
-    -s [dev|name]  master clock
-    -O [offset]    slave-master time offset (0)
-    -w             wait for ptp4l
-
-Options:
-    -f [file]      configuration file
-    -E [pi|linreg] clock servo (pi)
-    -P [kp]        proportional constant (0.7)
-    -I [ki]        integration constant (0.3)
-    -S [step]      step threshold (disabled)
-    -F [step]      step threshold only on start (0.00002)
-    -R [rate]      slave clock update rate in HZ (1.0)
-    -N [num]       number of master clock readings per update (5)
-    -L [limit]     sanity frequency limit in ppb (200000000)
-    -M [num]       NTP SHM segment number (0)
-    -u [num]       number of clock updates in summary stats (0)
-    -n [num]       domain number (0)
-    -x             apply leap seconds by servo instead of kernel
-    -z [path]      server address for UDS (/var/run/ptp4l)
-    -l [num]       set the logging level to 'num' (6)
-    -t [tag]       add tag to log messages
-    -m             print messages to stdout
-    -q             do not print messages to the syslog
-    -v             prints the software version and exits
-    -h             prints this message and exits
-

-

DESCRIPTION

-

The phc2sys utility is used to synchronize the system clock to the PTP Hardware Clock (PHC) or ToD clock. The phc_ctl utility is used to directly control PHC clock device.

-

Configuring the PTP service

-
    -
  1. Install the linuxptp package: -
    # sudo yum install linuxptp
    -
  2. -
  3. Check PTP device is created successfully by the ToD driver.
  4. -
-

ToD driver registering as PHC device (clock_name: dfl_tod) to the Linux PTP stack and exposing to the Linux kernel to synchronize the system clock to its ToD information. -

# cat /sys/class/ptp/ptp0/clock_name
-dfl_tod
-

-
    -
  1. Configure phc2sys service on a system:
  2. -
-

The phc2sys service is configured in the /etc/sysconfig/phc2sys configuration file. Define start-up option for phc2sys daemon in /etc/sysconfig/phc2sys. -The master clock is /dev/ptp0 device and the slave clock is system clock/CLOCK_REALTIME: -

 OPTIONS="-s /dev/ptp0 -c CLOCK_REALTIME -r -O 0 -R 16"
-

-
    -
  1. -

    Start phc2sys service: -

    # service phc2sys start
    -

    -
  2. -
  3. -

    Stop phc2sys service: -

    # service phc2sys stop
    -

    -
  4. -
-

Examples

-

using phc_ctl utility

-

Read the current clock time from the PHC clock device: -

# sudo phc_ctl /dev/ptp0 get
-

-

Set the PHC clock time to CLOCK_REALTIME: -

# sudo phc_ctl /dev/ptp0 set
-

-

Set PHC clock time to 0: -

# sudo phc_ctl /dev/ptp0 set 0.0
-

-

Set PHC clock time to 0 and wait for 10 sec and read the clock time: -

# sudo phc_ctl /dev/ptp0 set 0.0 wait 10.0 get
-

-

Set and compare PHC clock time to CLOCK_REALTIME: -

# sudo phc_ctl /dev/ptp0 set cmp
-

-

Read the PHC device capabilities: -

# sudo phc_ctl /dev/ptp0 caps
-

-

using phc2sys utility

-

To synchronize the system clock to the PHC clock: -

# sudo phc2sys -s /dev/ptp0 -c CLOCK_REALTIME -r -O 0 -R 16 -m
-phc2sys[7896.789]: CLOCK_REALTIME phc offset  -1259509 s0 freq  -31462 delay   1338
-phc2sys[7896.852]: CLOCK_REALTIME phc offset  -1261498 s1 freq  -63144 delay   1328
-phc2sys[7896.914]: CLOCK_REALTIME phc offset       -15 s2 freq  -63159 delay   1328
-phc2sys[7896.977]: CLOCK_REALTIME phc offset       -19 s2 freq  -63167 delay   1327
-phc2sys[7897.039]: CLOCK_REALTIME phc offset       -35 s2 freq  -63189 delay   1328
-phc2sys[7897.102]: CLOCK_REALTIME phc offset       -37 s2 freq  -63201 delay   1331
-phc2sys[7897.165]: CLOCK_REALTIME phc offset       -30 s2 freq  -63205 delay   1328
-phc2sys[7897.227]: CLOCK_REALTIME phc offset       -50 s2 freq  -63234 delay   1331
-phc2sys[7897.290]: CLOCK_REALTIME phc offset       -50 s2 freq  -63249 delay   1329
-phc2sys[7897.353]: CLOCK_REALTIME phc offset       -62 s2 freq  -63276 delay   1334
-phc2sys[7897.415]: CLOCK_REALTIME phc offset       -53 s2 freq  -63286 delay   1335
-phc2sys[7897.478]: CLOCK_REALTIME phc offset       -46 s2 freq  -63295 delay   1325
-phc2sys[7897.541]: CLOCK_REALTIME phc offset       -57 s2 freq  -63320 delay   1334
-phc2sys[7897.603]: CLOCK_REALTIME phc offset       -39 s2 freq  -63319 delay   1327
-phc2sys[7897.666]: CLOCK_REALTIME phc offset       -31 s2 freq  -63323 delay   1328
-phc2sys[7897.728]: CLOCK_REALTIME phc offset       -48 s2 freq  -63349 delay   1327
-phc2sys[7897.791]: CLOCK_REALTIME phc offset       -42 s2 freq  -63357 delay   1323
-phc2sys[7897.854]: CLOCK_REALTIME phc offset       -41 s2 freq  -63369 delay   1324
-phc2sys[7897.916]: CLOCK_REALTIME phc offset       -44 s2 freq  -63384 delay   1328
-phc2sys[7897.979]: CLOCK_REALTIME phc offset       -13 s2 freq  -63366 delay   1327
-phc2sys[7898.042]: CLOCK_REALTIME phc offset       -16 s2 freq  -63373 delay   1327
-phc2sys[7898.104]: CLOCK_REALTIME phc offset       -19 s2 freq  -63381 delay   1328
-phc2sys[7898.167]: CLOCK_REALTIME phc offset       -16 s2 freq  -63384 delay   1327
-phc2sys[7898.229]: CLOCK_REALTIME phc offset         3 s2 freq  -63370 delay   1327
-phc2sys[7898.292]: CLOCK_REALTIME phc offset        16 s2 freq  -63356 delay   1325
-phc2sys[7898.355]: CLOCK_REALTIME phc offset        10 s2 freq  -63357 delay   1319
-phc2sys[7898.417]: CLOCK_REALTIME phc offset        23 s2 freq  -63341 delay   1327
-phc2sys[7898.480]: CLOCK_REALTIME phc offset        13 s2 freq  -63344 delay   1335
-phc2sys[7898.543]: CLOCK_REALTIME phc offset        23 s2 freq  -63330 delay   1323
-phc2sys[7898.605]: CLOCK_REALTIME phc offset        29 s2 freq  -63317 delay   1312
-phc2sys[7898.668]: CLOCK_REALTIME phc offset        22 s2 freq  -63315 delay   1324
-phc2sys[7898.730]: CLOCK_REALTIME phc offset        42 s2 freq  -63289 delay   1325
-phc2sys[7898.793]: CLOCK_REALTIME phc offset        29 s2 freq  -63289 delay   1333
-phc2sys[7898.856]: CLOCK_REALTIME phc offset        34 s2 freq  -63276 delay   1327
-phc2sys[7898.918]: CLOCK_REALTIME phc offset        21 s2 freq  -63278 delay   1331
-phc2sys[7898.981]: CLOCK_REALTIME phc offset        22 s2 freq  -63271 delay   1335
-phc2sys[7899.044]: CLOCK_REALTIME phc offset        30 s2 freq  -63256 delay   1327
-phc2sys[7899.106]: CLOCK_REALTIME phc offset        30 s2 freq  -63247 delay   1328
-phc2sys[7899.169]: CLOCK_REALTIME phc offset        37 s2 freq  -63231 delay   1333
-phc2sys[7899.232]: CLOCK_REALTIME phc offset        29 s2 freq  -63228 delay   1331
-phc2sys[7899.294]: CLOCK_REALTIME phc offset        24 s2 freq  -63225 delay   1330
-

- - - - - - -
-
- - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file