Blame doc/src/fpga_api/quick_start/readme.md

Packit 534379
# Quick Start Guide #
Packit 534379
Packit 534379
```eval_rst
Packit 534379
.. toctree::
Packit 534379
```
Packit 534379
Packit 534379
## Overview ##
Packit 534379
The OPAE C library is a lightweight user-space library that provides
Packit 534379
abstraction for FPGA resources in a compute environment. Built on top of the
Packit 534379
OPAE Intel® FPGA driver stack that supports Intel® FPGA platforms, the library
Packit 534379
abstracts away hardware specific and OS specific details and exposes the
Packit 534379
underlying FPGA resources as a set of features accessible from within
Packit 534379
software programs running on the host.
Packit 534379
Packit 534379
These features include the acceleration logic preconfigured on the
Packit 534379
device, as well as functions to manage and reconfigure the
Packit 534379
device. Hence, the library is able to enalbe user applications to
Packit 534379
transparently and seamlessly leverage FPGA-based acceleration.
Packit 534379
Packit 534379
In this document, we will explore the initial steps on how to setup
Packit 534379
the required libraries and utilities to use the FPGA devices.
Packit 534379
Packit 534379
## Installing the OPAE Intel® FPGA drivers ##
Packit 534379
Packit 534379
If you do not have access to an Intel® Xeon® processor with integrated
Packit 534379
FPGA, or a programmable FPGA acceleration card for Intel® Xeon®
Packit 534379
processors, you will not be able to run the examples below. However, you can
Packit 534379
still make use of the AFU simulation environment (ASE) to develop and test
Packit 534379
accelerator RTL with OPAE applications.
Packit 534379
Packit 534379
For more information about ASE, see the [OPAE AFU Simulation Environment
Packit 534379
(ASE) User Guide](../../ase_userguide/ase_userguide.html).
Packit 534379
Packit 534379
As part of the OPAE SDK release, we provide DKMS-based RPM and DEB packages for
Packit 534379
distributions using RPM (e.g. Redhat, Fedora, Centos) and DEB (eg. Ubuntu) package managers.
Packit 534379
Download these package from the respective [release page on
Packit 534379
GitHub](https://github.com/OPAE/opae-sdk/releases) - they are named
Packit 534379
`opae-intel-fpga-driver-x.y.z-r.x86_64.rpm` and `opae-intel-fpga-driver_x.y.z-r_amd64.deb`, with `x.y.z-r` being the respective OPAE
Packit 534379
release's version number.
Packit 534379
Packit 534379
```eval_rst
Packit 534379
.. note::
Packit 534379
    The packages require that the DKMS (Dynamic Kernel Module System)
Packit 534379
    package, version greater than 2.2, is already installed.
Packit 534379
```
Packit 534379
Packit 534379
For RPM-based distributions:
Packit 534379
```console
Packit 534379
$ sudo yum install opae-intel-fpga-driver-<release>.x86_64.rpm
Packit 534379
```
Packit 534379
Packit 534379
For DEB-based distributions:
Packit 534379
```console
Packit 534379
$ sudo dpkg -i opae-intel-fpga-driver_<release>_amd64.deb
Packit 534379
```
Packit 534379
## Installing the OPAE SDK from rpm or deb packages ##
Packit 534379
See the [OPAE Installation Guide](/fpga-doc/docs/fpga_api/install_guide/installation_guide.html)
Packit 534379
for information about OPAE RPM and DEB packages.
Packit 534379
Assuming the packages are already downloaded and exist in the current folder,
Packit 534379
then use the commands below to install the OPAE library, tools, and development
Packit 534379
headers.
Packit 534379
Packit 534379
For rpm packages:
Packit 534379
Packit 534379
```console
Packit 534379
$ sudo yum install opae-libs-<release>.x86_64.rpm
Packit 534379
$ sudo yum install opae-tools-<release>.x86_64.rpm
Packit 534379
$ sudo yum install opae-tools-extra-<release>.x86_64.rpm
Packit 534379
$ sudo yum install opae-devel-<release>.x86_64.rpm
Packit 534379
$ sudo yum install opae-ase-<release>.x86_64.rpm
Packit 534379
```
Packit 534379
Packit 534379
For deb packages:
Packit 534379
Packit 534379
```console
Packit 534379
$ sudo dpkg -i opae-libs-<release>.x86_64.deb
Packit 534379
$ sudo dpkg -i opae-tools-<release>.x86_64.deb
Packit 534379
$ sudo dpkg -i opae-tools-extra-<release>.x86_64.deb
Packit 534379
$ sudo dpkg -i opae-devel-<release>.x86_64.deb
Packit 534379
$ sudo dpkg -i opae-ase-<release>.x86_64.deb
Packit 534379
```
Packit 534379
Packit 534379
To use OPAE in the simulation environment, you also need to install the AFU
Packit 534379
Simulation Environment (ASE) package:
Packit 534379
Packit 534379
rpm:
Packit 534379
Packit 534379
```console
Packit 534379
$ sudo yum install opae-ase-<release>.x86_64.rpm
Packit 534379
```
Packit 534379
deb:
Packit 534379
Packit 534379
```console
Packit 534379
$ sudo dpkg -i opae-<release>.x86_64-ase.deb
Packit 534379
```
Packit 534379
Packit 534379
```eval_rst
Packit 534379
.. note:
Packit 534379
    If you want to install all the packages, you can also do:
Packit 534379
    rpm: $ sudo yum install opae-*.rpm
Packit 534379
    deb: $ sudo dpkg -i opae-*.deb
Packit 534379
```
Packit 534379
Packit 534379
## Building and installing the OPAE SDK from source ##
Packit 534379
Download the OPAE SDK source package from the respective [release page on
Packit 534379
GitHub](https://github.com/OPAE/opae-sdk/releases) - click the `Source code
Packit 534379
(tar.gz)` link under "Downloads".
Packit 534379
Packit 534379
After downloading the source, unpack, configure, and compile it:
Packit 534379
Packit 534379
```console
Packit 534379
    tar xfvz opae-sdk-<release>.tar.gz
Packit 534379
    cd opae-sdk-<release>
Packit 534379
    mkdir build
Packit 534379
    cd build
Packit 534379
    cmake .. -DOPAE_BUILD_SIM=ON
Packit 534379
    make
Packit 534379
```
Packit 534379
Packit 534379
By default, the OPAE SDK will install into `/usr/local` if you also issue the following:
Packit 534379
Packit 534379
```console
Packit 534379
    make install
Packit 534379
```
Packit 534379
Packit 534379
You can change this installation prefix from `/usr/local` into something else
Packit 534379
by adding `-DCMAKE_INSTALL_PREFIX=<new prefix>` to the `cmake` command above.
Packit 534379
The remainder of this guide assumes you installed into `/usr/local`.
Packit 534379
Packit 534379
## Configuring the FPGA (loading an FPGA AFU)##
Packit 534379
Packit 534379
The *fpgaconf* tool exercises the AFU reconfiguration
Packit 534379
functionality. It shows how to read a bitstream from a disk file,
Packit 534379
check its validity and compatability, and then injects it into FPGA to
Packit 534379
be configured as a new AFU, which can then be discovered and used by
Packit 534379
user applications.
Packit 534379
Packit 534379
For this step you require a valid green bitstream (GBS) file. To
Packit 534379
reconfigure the FPGA slot, you can issue following command as system
Packit 534379
administrator (*root*):
Packit 534379
Packit 534379
```console
Packit 534379
$ sudo fpgaconf -b 0x5e <filename>.gbs
Packit 534379
```
Packit 534379
Packit 534379
The `-b` parameter to *fpgaconf* indicates the *target bus number* of the
Packit 534379
FPGA slot to be reconfigured. Alternatively, you can also specify the
Packit 534379
*target socket number* of the FPGA using the `-s` parameter.
Packit 534379
Packit 534379
```console
Packit 534379
$ sudo fpgaconf --help
Packit 534379
Usage:
Packit 534379
        fpgaconf [-hvn] [-b <bus>] [-d <device>] [-f <function>] [-s <socket>] <gbs>
Packit 534379
Packit 534379
                -h,--help           Print this help
Packit 534379
                -v,--verbose        Increase verbosity
Packit 534379
                -n,--dry-run        Don't actually perform actions
Packit 534379
                -b,--bus            Set target bus number
Packit 534379
                -d,--device         Set target device number
Packit 534379
                -f,--function       Set target function number
Packit 534379
                -s,--socket         Set target socket number
Packit 534379
```
Packit 534379
Packit 534379
Packit 534379
```eval_rst
Packit 534379
.. note::
Packit 534379
    The sample application on the Building a Sample Application
Packit 534379
    section requires loading of an AFU called "Native Loopback
Packit 534379
    Adapter" (NLB) on the FPGA. Please refer to the NLB documentation
Packit 534379
    for the location of the NLB's green bitstream. You also can verify
Packit 534379
    if the NLB green bitstream has already been loaded into the FPGA
Packit 534379
    slot by typing the following command and checking the output
Packit 534379
    matches the following:
Packit 534379
Packit 534379
    $ cat /sys/class/fpga/intel-fpga-dev.0/intel-fpga-port.0/afu_id
Packit 534379
Packit 534379
    d8424dc4a4a3c413f89e433683f9040b
Packit 534379
```
Packit 534379
Packit 534379
## Building a sample application ##
Packit 534379
The library source include code samples. Use these samples to learn
Packit 534379
how to call functions in the library. Build and run these samples as
Packit 534379
quick sanity checks to determine if your installation and environment
Packit 534379
are set up properly.
Packit 534379
Packit 534379
In this guide, we will build *hello\_fpga.c*. This is the "Hello
Packit 534379
World!" example of using the library.  This code searches for a
Packit 534379
predefined and known AFU called "Native Loopback Adapter" on the
Packit 534379
FPGA. If found, it acquires ownership and then interacts with the AFU
Packit 534379
by sending it a 2MB message and waiting for the message being echoed
Packit 534379
back. This coe exercises all major components of the API except for
Packit 534379
AFU reconfiguration: AFU search, enumeration, access, MMIO, and memory
Packit 534379
management.
Packit 534379
Packit 534379
You can also find the source for `hello\_fpga` in the `samples` directory of the
Packit 534379
OPAE SDK repository on github.
Packit 534379
Packit 534379
```c
Packit 534379
    int main(int argc, char *argv[])
Packit 534379
    {
Packit 534379
        fpga_properties    filter = NULL;
Packit 534379
        fpga_token         afu_token;
Packit 534379
        fpga_handle        afu_handle;
Packit 534379
        fpga_guid          guid;
Packit 534379
        uint32_t           num_matches;
Packit 534379
Packit 534379
        volatile uint64_t *dsm_ptr    = NULL;
Packit 534379
        volatile uint64_t *status_ptr = NULL;
Packit 534379
        volatile uint64_t *input_ptr  = NULL;
Packit 534379
        volatile uint64_t *output_ptr = NULL;
Packit 534379
Packit 534379
        uint64_t        dsm_wsid;
Packit 534379
        uint64_t        input_wsid;
Packit 534379
        uint64_t        output_wsid;
Packit 534379
        fpga_result     res = FPGA_OK;
Packit 534379
Packit 534379
        if (uuid_parse(NLB0_AFUID, guid) < 0) {
Packit 534379
            fprintf(stderr, "Error parsing guid '%s'\n", NLB0_AFUID);
Packit 534379
            goto out_exit;
Packit 534379
        }
Packit 534379
Packit 534379
        /* Look for accelerator by its "afu_id" */
Packit 534379
        res = fpgaGetProperties(NULL, &filter);
Packit 534379
        ON_ERR_GOTO(res, out_exit, "creating properties object");
Packit 534379
Packit 534379
        res = fpgaPropertiesSetObjectType(filter, FPGA_ACCELERATOR);
Packit 534379
        ON_ERR_GOTO(res, out_destroy_prop, "setting object type");
Packit 534379
Packit 534379
        res = fpgaPropertiesSetGuid(filter, guid);
Packit 534379
        ON_ERR_GOTO(res, out_destroy_prop, "setting GUID");
Packit 534379
Packit 534379
        /* TODO: Add selection via BDF / device ID */
Packit 534379
Packit 534379
        res = fpgaEnumerate(&filter, 1, &afu_token, 1, &num_matches);
Packit 534379
        ON_ERR_GOTO(res, out_destroy_prop, "enumerating accelerators");
Packit 534379
Packit 534379
        if (num_matches < 1) {
Packit 534379
            fprintf(stderr, "accelerator not found.\n");
Packit 534379
            res = fpgaDestroyProperties(&filter);
Packit 534379
            return FPGA_INVALID_PARAM;
Packit 534379
        }
Packit 534379
Packit 534379
        /* Open accelerator and map MMIO */
Packit 534379
        res = fpgaOpen(afu_token, &afu_handle, 0);
Packit 534379
        ON_ERR_GOTO(res, out_destroy_tok, "opening accelerator");
Packit 534379
Packit 534379
        res = fpgaMapMMIO(afu_handle, 0, NULL);
Packit 534379
        ON_ERR_GOTO(res, out_close, "mapping MMIO space");
Packit 534379
Packit 534379
        /* Allocate buffers */
Packit 534379
        res = fpgaPrepareBuffer(afu_handle, LPBK1_DSM_SIZE,
Packit 534379
                    (void **)&dsm_ptr, &dsm_wsid, 0);
Packit 534379
        ON_ERR_GOTO(res, out_close, "allocating DSM buffer");
Packit 534379
Packit 534379
        res = fpgaPrepareBuffer(afu_handle, LPBK1_BUFFER_ALLOCATION_SIZE,
Packit 534379
                   (void **)&input_ptr, &input_wsid, 0);
Packit 534379
        ON_ERR_GOTO(res, out_free_dsm, "allocating input buffer");
Packit 534379
Packit 534379
        res = fpgaPrepareBuffer(afu_handle, LPBK1_BUFFER_ALLOCATION_SIZE,
Packit 534379
                   (void **)&output_ptr, &output_wsid, 0);
Packit 534379
        ON_ERR_GOTO(res, out_free_input, "allocating output buffer");
Packit 534379
Packit 534379
        printf("Running Test\n");
Packit 534379
Packit 534379
        /* Initialize buffers */
Packit 534379
        memset((void *)dsm_ptr,    0,    LPBK1_DSM_SIZE);
Packit 534379
        memset((void *)input_ptr,  0xAF, LPBK1_BUFFER_SIZE);
Packit 534379
        memset((void *)output_ptr, 0xBE, LPBK1_BUFFER_SIZE);
Packit 534379
Packit 534379
        cache_line *cl_ptr = (cache_line *)input_ptr;
Packit 534379
        for (uint32_t i = 0; i < LPBK1_BUFFER_SIZE / CL(1); ++i) {
Packit 534379
            cl_ptr[i].uint[15] = i+1; /* set the last uint in every cacheline */
Packit 534379
        }
Packit 534379
Packit 534379
        /* Reset accelerator */
Packit 534379
        res = fpgaReset(afu_handle);
Packit 534379
        ON_ERR_GOTO(res, out_free_output, "resetting accelerator");
Packit 534379
Packit 534379
        /* Program DMA addresses */
Packit 534379
        uint64_t iova;
Packit 534379
        res = fpgaGetIOAddress(afu_handle, dsm_wsid, &iova);
Packit 534379
        ON_ERR_GOTO(res, out_free_output, "getting DSM IOVA");
Packit 534379
Packit 534379
        res = fpgaWriteMMIO64(afu_handle, 0, CSR_AFU_DSM_BASEL, iova);
Packit 534379
        ON_ERR_GOTO(res, out_free_output, "writing CSR_AFU_DSM_BASEL");
Packit 534379
Packit 534379
        res = fpgaWriteMMIO32(afu_handle, 0, CSR_CTL, 0);
Packit 534379
        ON_ERR_GOTO(res, out_free_output, "writing CSR_CFG");
Packit 534379
        res = fpgaWriteMMIO32(afu_handle, 0, CSR_CTL, 1);
Packit 534379
        ON_ERR_GOTO(res, out_free_output, "writing CSR_CFG");
Packit 534379
Packit 534379
        res = fpgaGetIOAddress(afu_handle, input_wsid, &iova);
Packit 534379
        ON_ERR_GOTO(res, out_free_output, "getting input IOVA");
Packit 534379
        res = fpgaWriteMMIO64(afu_handle, 0, CSR_SRC_ADDR, CACHELINE_ALIGNED_ADDR(iova));
Packit 534379
        ON_ERR_GOTO(res, out_free_output, "writing CSR_SRC_ADDR");
Packit 534379
Packit 534379
        res = fpgaGetIOAddress(afu_handle, output_wsid, &iova);
Packit 534379
        ON_ERR_GOTO(res, out_free_output, "getting output IOVA");
Packit 534379
        res = fpgaWriteMMIO64(afu_handle, 0, CSR_DST_ADDR, CACHELINE_ALIGNED_ADDR(iova));
Packit 534379
        ON_ERR_GOTO(res, out_free_output, "writing CSR_DST_ADDR");
Packit 534379
Packit 534379
        res = fpgaWriteMMIO32(afu_handle, 0, CSR_NUM_LINES, LPBK1_BUFFER_SIZE / CL(1));
Packit 534379
        ON_ERR_GOTO(res, out_free_output, "writing CSR_NUM_LINES");
Packit 534379
        res = fpgaWriteMMIO32(afu_handle, 0, CSR_CFG, 0x42000);
Packit 534379
        ON_ERR_GOTO(res, out_free_output, "writing CSR_CFG");
Packit 534379
Packit 534379
        status_ptr = dsm_ptr + DSM_STATUS_TEST_COMPLETE/8;
Packit 534379
Packit 534379
        /* Start the test */
Packit 534379
        res = fpgaWriteMMIO32(afu_handle, 0, CSR_CTL, 3);
Packit 534379
        ON_ERR_GOTO(res, out_free_output, "writing CSR_CFG");
Packit 534379
Packit 534379
        /* Wait for test completion */
Packit 534379
        while (0 == ((*status_ptr) & 0x1)) {
Packit 534379
            usleep(100);
Packit 534379
        }
Packit 534379
Packit 534379
        /* Stop the device */
Packit 534379
        res = fpgaWriteMMIO32(afu_handle, 0, CSR_CTL, 7);
Packit 534379
        ON_ERR_GOTO(res, out_free_output, "writing CSR_CFG");
Packit 534379
Packit 534379
        /* Check output buffer contents */
Packit 534379
        for (uint32_t i = 0; i < LPBK1_BUFFER_SIZE; i++) {
Packit 534379
            if (((uint8_t*)output_ptr)[i] != ((uint8_t*)input_ptr)[i]) {
Packit 534379
                fprintf(stderr, "Output does NOT match input "
Packit 534379
                    "at offset %i!\n", i);
Packit 534379
                break;
Packit 534379
            }
Packit 534379
        }
Packit 534379
Packit 534379
        printf("Done Running Test\n");
Packit 534379
Packit 534379
        /* Release buffers */
Packit 534379
    out_free_output:
Packit 534379
        res = fpgaReleaseBuffer(afu_handle, output_wsid);
Packit 534379
        ON_ERR_GOTO(res, out_free_input, "releasing output buffer");
Packit 534379
    out_free_input:
Packit 534379
        res = fpgaReleaseBuffer(afu_handle, input_wsid);
Packit 534379
        ON_ERR_GOTO(res, out_free_dsm, "releasing input buffer");
Packit 534379
    out_free_dsm:
Packit 534379
        res = fpgaReleaseBuffer(afu_handle, dsm_wsid);
Packit 534379
        ON_ERR_GOTO(res, out_unmap, "releasing DSM buffer");
Packit 534379
Packit 534379
        /* Unmap MMIO space */
Packit 534379
    out_unmap:
Packit 534379
        res = fpgaUnmapMMIO(afu_handle, 0);
Packit 534379
        ON_ERR_GOTO(res, out_close, "unmapping MMIO space");
Packit 534379
Packit 534379
        /* Release accelerator */
Packit 534379
    out_close:
Packit 534379
        res = fpgaClose(afu_handle);
Packit 534379
        ON_ERR_GOTO(res, out_destroy_tok, "closing accelerator");
Packit 534379
Packit 534379
        /* Destroy token */
Packit 534379
    out_destroy_tok:
Packit 534379
        res = fpgaDestroyToken(&afu_token);
Packit 534379
        ON_ERR_GOTO(res, out_destroy_prop, "destroying token");
Packit 534379
Packit 534379
        /* Destroy properties object */
Packit 534379
    out_destroy_prop:
Packit 534379
        res = fpgaDestroyProperties(&filter);
Packit 534379
        ON_ERR_GOTO(res, out_exit, "destroying properties object");
Packit 534379
Packit 534379
    out_exit:
Packit 534379
        return res;
Packit 534379
Packit 534379
    }
Packit 534379
```
Packit 534379
Packit 534379
Linking with the OPAE library is straightforward.  Code using this library
Packit 534379
should include the header file `fpga.h`. Taking the GCC compiler on
Packit 534379
Linux as an example, the minimalist compile and link line should look
Packit 534379
like:
Packit 534379
Packit 534379
```console
Packit 534379
$ gcc -std=c99 hello_fpga.c -I/usr/local/include -L/usr/local/lib -lopae-c -luuid -ljson-c -lpthread -o hello_fpga
Packit 534379
```
Packit 534379
Packit 534379
Packit 534379
```eval_rst
Packit 534379
.. note:
Packit 534379
    The API uses some features from the C99 language standard. The
Packit 534379
    `-std=c99` switch is required if the compiler does not support C99 by
Packit 534379
    default.
Packit 534379
```
Packit 534379
Packit 534379
Packit 534379
```eval_rst
Packit 534379
.. note::
Packit 534379
    Third-party library dependency: The library internally uses
Packit 534379
    `libuuid` and `libjson-c`. But they are not distributed as part of the
Packit 534379
    library. Make sure you have these libraries properly installed.
Packit 534379
```
Packit 534379
To run the *hello_fpga* application; just issue:
Packit 534379
Packit 534379
```console
Packit 534379
$ sudo ./hello_fpga
Packit 534379
Packit 534379
Running Test
Packit 534379
Done
Packit 534379
Packit 534379
```
Packit 534379
Packit 534379
Packit 534379
```eval_rst
Packit 534379
.. note::
Packit 534379
  In order to successfully run hello\_fpga, user need to configure system hugepage to reserve 2M-hugepages.
Packit 534379
  For example, the command below reserves 20 2M-hugepages:
Packit 534379
Packit 534379
  $ echo 20 | sudo tee /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
Packit 534379
Packit 534379
  For x86_64 architecture CPU, user can use following command to find out avaiable huge page sizes:
Packit 534379
Packit 534379
  $ grep pse /proc/cpuinfo | uniq
Packit 534379
  flags : ... pse ...
Packit 534379
Packit 534379
  If this commands returns a non-empty string, 2MB pages are supported:
Packit 534379
Packit 534379
  $ grep pse /proc/cpuinfo | uniq
Packit 534379
  flags : ... pdpe1gb ...
Packit 534379
Packit 534379
  If this commands returns a non-empty string, 1GB pages are supported:
Packit 534379
Packit 534379
```
Packit 534379
Packit 534379
```eval_rst
Packit 534379
.. note::
Packit 534379
  The default configuration for many Linux distribution currently sets a relatively low limit for pinned memory allocations per process (RLIMIT_MEMLOCK, often set to a default of 64kiB).
Packit 534379
  To run an OPAE application which attempts to share more memory than specified by this limit between software and an accelerator, you can either:
Packit 534379
Packit 534379
     * Run the application as root, or
Packit 534379
     * Increase the limit for locked memory via ulimit:
Packit 534379
Packit 534379
     $ ulimit -l unlimited
Packit 534379
Packit 534379
  See the Installation Guide for how to permanently adjust the memlock limit.
Packit 534379
Packit 534379
```