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

Packit 534379
# OPAE C API Programming Guide #
Packit 534379
Packit 534379
.. toctree::
Packit 534379
Packit 534379
## Overview ##
Packit 534379
The OPAE C library (*libopae-c*) is a lightweight user-space library that
Packit 534379
provides abstractions for FPGA resources in a compute environment. The OPAE C library 
Packit 534379
builds on the driver stack that supports the FPGA device, abstracting 
Packit 534379
hardware- and OS-specific details. It provides access to the underlying FPGA
Packit 534379
resources as a set of features available to software programs
Packit 534379
running on the host. These features include the acceleration logic
Packit 534379
preconfigured on the FPGA and functions to manage and reconfigure
Packit 534379
the FPGA. The library enables your applications to
Packit 534379
transparently and seamlessly benefit from FPGA-based acceleration.
Packit 534379
Packit 534379
![Layered architecture](./FPGA-lib-1.png "A user space library built on top of FPGA driver stack")
Packit 534379
Packit 534379
Packit 534379
By providing a unified C API, the library supports different FPGA
Packit 534379
integration and deployment models, ranging from single-node systems with one or
Packit 534379
a few FPGA devices to large-scale FPGA deployments in a data center.
Packit 534379
At one end of the spectrum, the API supports a simple application using a PCIe link to reconfigure 
Packit 534379
the FPGA with different accelerator functions. At the other end of the spectrum, resource
Packit 534379
management and orchestration services in a data center can use this API to
Packit 534379
discover and select FPGA resources and then allocate them for use by acceleration workloads.
Packit 534379
Packit 534379
## OPAE Role ##
Packit 534379
Packit 534379
The OPAE provides a common base layer for a wide range of
Packit 534379
applications without sacrificing performance or efficiency. The abstraction layer limits 
Packit 534379
the details of the FPGA hardware that software applications must handle. 
Packit 534379
Packit 534379
The OPAE provides consistent interfaces to crucial components of the platform. The  OPAE does not constrain
Packit 534379
frameworks and applications by making optimizations with limited applicability. When the OPAE does
Packit 534379
provide convenience functions or optimizations, they are optional.
Packit 534379
Packit 534379
For example, the OPAE provides an interface to allocate physically contiguous
Packit 534379
buffers in system memory that user-space software and an accelerator can share. 
Packit 534379
This interface enables the most basic feature set of
Packit 534379
allocating and sharing a large page of memory in one API call. However, it 
Packit 534379
does *not* provide a malloc()-like interface backed by a memory pool or slab
Packit 534379
allocator. Higher layers of the software stack can make such
Packit 534379
domain-specific optimizations.
Packit 534379
Packit 534379
Packit 534379
## Intel Accelerator Stack Hardware Terminology ##
Packit 534379
Packit 534379
The following terms define the hardware and hardware processes involved in creating an accelerator function. 
Packit 534379
Packit 534379
* FPGA: [Field Programmable Gate Array](https://en.wikipedia.org/wiki/Field-programmable_gate_array) 
Packit 534379
is a discrete or integrated device connecting to a host CPU via PCIe or other type of interconnects.
Packit 534379
* Accelerator Function Unit (AFU): The AFU is the supplied implementation of an accelerator, typically
Packit 534379
in HDL. AFUs implement a function such as compression, encryption, or mathematical operations.
Packit 534379
The Quartus Prime Pro software synthesizes the RTL logic into a bitstream. 
Packit 534379
* Accelerator Function (AF): The AF is the compiled binary for an AFU. An AF is a raw binary file (.rbf)
Packit 534379
bitstream. A tool (_fpgaconf_) reconfigures the FPGA using an AF bitstream.
Packit 534379
* Reconfiguration: The process of reprogramming the FPGA with a different AF.
Packit 534379
Packit 534379
## OPAE Software Concepts Reflected in the C API ##
Packit 534379
Packit 534379
The following OPAE data structures and functions integrate AFUs into the OPAE environment. 
Packit 534379
The OPAE C API models these data structures and functions. For more information on the object 
Packit 534379
models refer to the [Object model](#object-models) section.
Packit 534379
Packit 534379
* Accelerator: An accelerator is an allocable accelerator function implemented in an FPGA. 
Packit 534379
An accelerator tracks the  _ownership_ of an AFU (or part of it) for a process that uses it.
Packit 534379
Multiple processes can share an accelerator.
Packit 534379
* Device: The OPAE enumerates and models two device types: the FPGA and the AFU.
Packit 534379
* Events: Events are asynchronous notifications. The FPGA driver
Packit 534379
triggers particular events to indicate error conditions. Accelerator logic can also
Packit 534379
define its own events. User applications can choose to be
Packit 534379
notified when particular events occur and respond appropriately.
Packit 534379
* Shared memory buffers: Software allocates shared memory buffers in user process memory
Packit 534379
on the host. Shared memory buffers facilitate data transfers between the user process and the 
Packit 534379
accelerator that it owns.
Packit 534379
Packit 534379
## OPAE Library ##
Packit 534379
Linking with this library is straightforward.
Packit 534379
Code using the  OPAE library should include the header file `fpga.h`. Taking the GCC
Packit 534379
compiler on Linux as an example, here is the simplest compile and link command:
Packit 534379
Packit 534379
`gcc myprog.c -I</path/to/fpga.h> -L</path/to/libopae-c.so> -lopae-c -luuid -ljson-c -lpthread`
Packit 534379
Packit 534379
.. note::
Packit 534379
Packit 534379
```
Packit 534379
The OPAE library uses the third-party `libuuid` and `libjson-c` libraries that are not distributed with 
Packit 534379
the OPAE library. Make sure to install these libraries.
Packit 534379
```
Packit 534379
Packit 534379
## Sample Code ##
Packit 534379
The library source includes two code samples. Use these samples
Packit 534379
to learn how to call functions in the library. Build and run these samples
Packit 534379
to determine if your installation and environment are set up properly. 
Packit 534379
Packit 534379
Refer to the [Running the Hello FPGA Example](https://www.altera.com/content/altera-www/global/en_us/index/documentation/dnv1485190478614.html#vks1498593668425) chapter in the _Intel® Acceleration Stack
Packit 534379
Quick Start Guide for for Intel Programmable Acceleration Card with Intel Arria® 10 GX FPGA_ for more information about using the sample code.  
Packit 534379
Packit 534379
Packit 534379
## High-Level Directory Structure ##
Packit 534379
Building and installing the OPAE library results in the following directory structure on the Linux OS.
Packit 534379
Windows and MacOS have similar directories and files.
Packit 534379
Packit 534379
|Directory & Files |Contents |
Packit 534379
|------------------|---------|
Packit 534379
|include/opae      |Directory containing all header files|
Packit 534379
|include/opae/fpga.h |Top-level header for user code to include|
Packit 534379
|include/opae/access.h |Header file for accelerator acquire/release, MMIO, memory management, event handling, and so on |
Packit 534379
|include/opae/bitstream.h |Header file for bitstream manipulation functions |
Packit 534379
|include/opae/common.h |Header file for error reporting functions |
Packit 534379
|include/opae/enum.h |Header file for AFU enumeration functions |
Packit 534379
|include/opae/manage.h |Header file for FPGA management functions |
Packit 534379
|include/opae/types.h |Various type definitions |
Packit 534379
|lib               |Directory containing shared library files |
Packit 534379
|lib/libopae-c.so    |The shared dynamic library for linking with the user application |
Packit 534379
|doc               |Directory containing API documentation |
Packit 534379
|doc/html          |Directory for documentation of HTML format
Packit 534379
|doc/latex         |Directory for documentation of LaTex format
Packit 534379
|doc/man           |Directory for documentation of Unix man page format
Packit 534379
Packit 534379
## Basic Application Flow ##
Packit 534379
The figure below shows the basic application flow from the
Packit 534379
viewpoint of a user-process. 
Packit 534379
Packit 534379
![Basic flow](./FPGA-lib-3.PNG "Basic application flow")
Packit 534379
Packit 534379
## API Components ##
Packit 534379
The API object model abstracts the physical FPGA device and
Packit 534379
available functions. It is a generalized model and extends to 
Packit 534379
describe any FPGA type. 
Packit 534379
Packit 534379
### Object Models ###
Packit 534379
* `fpga_objtype`: An enum type that represents the type of an FPGA resource, either `FPGA_DEVICE` or `FPGA_ACCELERATOR`. 
Packit 534379
An `FPGA_DEVICE` object corresponds to a physical FPGA device. Only `FPGA_DEVICE` objects can invoke management functions.
Packit 534379
The `FPGA_ACCELERATOR` represents an instance of an AFU. 
Packit 534379
* `fpga_token`: An opaque type that represents a resource known to, but not
Packit 534379
necessarily owned by, the calling process. The calling process must own a
Packit 534379
resource before it can invoke functions of the resource.
Packit 534379
* `fpga_handle`: An opaque type that represents a resource owned by the
Packit 534379
calling process. The API functions `fpgaOpen()` and `fpgaClose()` acquire and release ownership of a resource that an `fpga_handle` represents. (Refer to the [Functions](#functions) section for more information.)
Packit 534379
* `fpga_properties`: An opaque type for a properties object. Your
Packit 534379
applications use these properties to query and search for appropriate resources. The 
Packit 534379
[FPGA Resource Properties](#fpga-resource-properties) section documents properties visible to your
Packit 534379
applications.
Packit 534379
* `fpga_event_handle`: An opaque handle the FPGA driver uses to notify your
Packit 534379
application about an event. 
Packit 534379
* `fpga_event_type`: An enum type that represents the types of events. The following are valid values: 
Packit 534379
`FPGA_EVENT_INTERRUPT`, `FPGA_EVENT_ERROR`, and `FPGA_EVENT_POWER_THERMAL`. (The Intel Programmable Acceleration Card (PAC) with
Packit 534379
Intel Arria 10 GX FPGA does not handle thermal and power events.)
Packit 534379
* `fpga_result`: An enum type to represent the result of an API function. If the
Packit 534379
function returns successfully the result is `FPGA_OK`. Otherwise, the result is
Packit 534379
the appropriate error codes. Function `fpgaErrStr()` translates an error code
Packit 534379
into human-readable strings.
Packit 534379
Packit 534379
### Functions ###
Packit 534379
The table below groups important API calls by their functionality. For more information about each of the functions, refer to the 
Packit 534379
[OPAE C API reference manual](https://opae.github.io/0.13.0/docs/fpga_api/fpga_api.html).
Packit 534379
Packit 534379
|Functionality |API Call |FPGA |Accelerator|Description |
Packit 534379
|:--------|:----------|:-----:|:-----:|:-----------------------|
Packit 534379
|Enumeration | ```fpgaEnumerate()``` |Yes| Yes| Query FPGA resources that match certain properties |
Packit 534379
|Enumeration: Properties | ```fpga[Get, Update, Clear, Clone, Destroy Properties]()``` |Yes| Yes| Manage ```fpga_properties``` life cycle |
Packit 534379
|           | ```fpgaPropertiesGet[Prop]()``` | Yes| Yes|Get the specified property *Prop*, from the [FPGA Resource Properties](#fpga-resource-properties) table |
Packit 534379
|           | ```fpgaPropertiesSet[Prop]()``` | Yes| Yes|Set the specified property *Prop*, from the [FPGA Resource Properties](#fpga-resource-properties) table |
Packit 534379
|Access: Ownership  | ```fpga[Open, Close]()``` | Yes| Yes|Acquire/release ownership |
Packit 534379
|Access: Reset      | ```fpgaReset()``` |Yes| Yes| Reset an accelerator |
Packit 534379
|Access: Event handling | ```fpga[Register, Unregister]Event()``` |Yes| Yes| Register/unregister an event to be notified about |
Packit 534379
|               | ```fpga[Create, Destroy]EventHandle()```|Yes| Yes| Manage ```fpga_event_handle``` life cycle |
Packit 534379
|Access: UMsg           | ```fpgaGetNumUmsg()```, ```fpgaSetUmsgAttributes()```, ```fpgaTriggerUmsg()```, ```fpgaGetUmsgPtr()``` | No|Yes| Low-latency accelerator notification mechanism.|
Packit 534379
|Access: MMIO       | ```fpgaMapMMIO()```, ```fpgaUnMapMMIO()``` |Yes| Yes| Map/unmap MMIO space |
Packit 534379
|           | ```fpgaGetMMIOInfo()``` |Yes| Yes| Get information about the specified MMIO space |
Packit 534379
|           | ```fpgaReadMMIO[32, 64]()``` | Yes| Yes|Read a 32-bit or 64-bit value from MMIO space |
Packit 534379
|           | ```fpgaWriteMMIO[32, 64]()``` |Yes| Yes| Write a 32-bit or 64-bit value to MMIO space |
Packit 534379
|Memory management: Shared memory | ```fpga[Prepare, Release]Buffer()``` |Yes| Yes| Manage memory buffer shared between the calling process and an accelerator |
Packit 534379
|              | ```fpgaGetIOAddress()``` | Yes| Yes|Return the device I/O address of a shared memory buffer |
Packit 534379
|Management: Reconfiguration | ```fpgaReconfigureSlot()``` | Yes | No | Replace an existing AFU with a new one |
Packit 534379
|Error report | ```fpgaErrStr()``` | Yes| Yes|Map an error code to a human readable string |
Packit 534379
Packit 534379
### FPGA Resource Properties ###
Packit 534379
Applications query resource properties by specifying the property name for `Prop` in the 
Packit 534379
`fpgaPropertiesGet[Prop]()` and `fpgaPropertiesSet[Prop]()` functions. The FPGA and Accelerator
Packit 534379
columns state whether or not the Property is available for the FPGA or Accelerator objects.
Packit 534379
Packit 534379
|Property |FPGA |Accelerator |Description |
Packit 534379
|:---------|:-----:|:----:|:-----|
Packit 534379
|Parent |No |Yes |`fpga_token` of the parent object |
Packit 534379
|ObjectType |Yes |Yes |The type of the resource: either `FPGA_DEVICE` or `FPGA_ACCELERATOR` |
Packit 534379
|Bus |Yes |Yes |The bus number |
Packit 534379
|Device |Yes |Yes |The PCI device number |
Packit 534379
|Function |Yes |Yes |The PCI function number |
Packit 534379
|SocketId |Yes |Yes |The socket ID |
Packit 534379
|DeviceId |Yes |Yes |The device ID |
Packit 534379
|NumSlots |Yes |No |Number of AFU slots available on an `FPGA_DEVICE` resource |
Packit 534379
|BBSID |Yes |No |The FPGA Interface Manager (FIM) ID of an `FPGA_DEVICE` resource |
Packit 534379
|BBSVersion |Yes |No |The FIM version of an `FPGA_DEVICE` resource |
Packit 534379
|VendorId |Yes |No |The vendor ID of an `FPGA_DEVICE` resource |
Packit 534379
|Model |Yes |No |The model of an `FPGA_DEVICE` resource |
Packit 534379
|LocalMemorySize |Yes |No |The local memory size of an `FPGA_DEVICE` resource |
Packit 534379
|Capabilities |Yes |No |The capabilities of an `FPGA_DEVICE` resource |
Packit 534379
|GUID |Yes |Yes |The GUID of an `FPGA_DEVICE` or `FPGA_ACCELERATOR` resource |
Packit 534379
|NumMMIO |No |Yes |The number of MMIO space of an `FPGA_ACCELERATOR` resource |
Packit 534379
|NumInterrupts |No |Yes |The number of interrupts of an `FPGA_ACCELERATOR` resource |
Packit 534379
|AcceleratorState |No |Yes |The state of an `FPGA_ACCELERATOR` resource: either `FPGA_ACCELERATOR_ASSIGNED` or `FPGA_ACCELERATOR_UNASSIGNED`|
Packit 534379
Packit 534379
## OPAE C API Return Codes ##
Packit 534379
The OPAE C library returns a code for every exported public API function.  `FPGA_OK` indicates successful completion
Packit 534379
of the requested operation. Any return code other than `FPGA_OK` indicates an error or unexpected
Packit 534379
behavior. When using the OPAE C API, always check the API return codes. 
Packit 534379
Packit 534379
|Error Code|Description|
Packit 534379
|----------|-----------|
Packit 534379
|`FPGA_OK`|Operation completed successfully|
Packit 534379
|`FPGA_INVALID_PARAM`|Invalid parameter supplied|
Packit 534379
|`FPGA_BUSY`|Resource is busy|
Packit 534379
|`FPGA_EXCEPTION`|An exception occurred|
Packit 534379
|`FPGA_NOT_FOUND`|A required resource was not found|
Packit 534379
|`FPGA_NO_MEMORY`|Not enough memory to complete operation|
Packit 534379
|`FPGA_NOT_SUPPORTED`|Requested operation is not supported|
Packit 534379
|`FPGA_NO_DRIVER`|Driver is not loaded|
Packit 534379
|`FPGA_NO_DAEMON`|FPGA Daemon (`fpgad`) is not running|
Packit 534379
|`FPGA_NO_ACCESS`|Insufficient privileges or permissions|
Packit 534379
|`FPGA_RECONF_ERROR`|Error while reconfiguring FPGA|
Packit 534379
Packit 534379
## Usage Models ##
Packit 534379
Packit 534379
Packit 534379
### Query and Search for a Resource ###
Packit 534379
The user-code first populates an `fpga_properties` object with the required properties.
Packit 534379
Then, `fpgaEnumerate()` searches for matching resources. `fpgaEnumerate()` may return more
Packit 534379
than one matching resource.
Packit 534379
Packit 534379
    #include "fpga/fpga.h"
Packit 534379
Packit 534379
    fpga_guid               guid;
Packit 534379
    fpga_properties         filter = NULL;
Packit 534379
    fpga_result             res;
Packit 534379
    fpga_token              tokens[MAX_NUM_TOKENS];
Packit 534379
    uint32_t                num_matches = 0;
Packit 534379
Packit 534379
    /* Start with an empty properties object */
Packit 534379
    res = fpgaGetProperties(NULL, &filter);
Packit 534379
Packit 534379
    /* Populate the properties object with required values.
Packit 534379
       In this case, search for accelerators that matches 
Packit 534379
       the specified GUID.
Packit 534379
    */
Packit 534379
    uuid_parse(GUID, guid);
Packit 534379
    res = fpgaPropertiesSetObjectType(filter, FPGA_ACCELERATOR);
Packit 534379
    res = fpgaPropertiesSetGuid(filter, guid);
Packit 534379
Packit 534379
    /* Query the number of matching resources */
Packit 534379
    res = fpgaEnumerate(&filter, 1, NULL, 1, &num_matches);
Packit 534379
Packit 534379
    /* Return tokens for all matching resources */
Packit 534379
    res = fpgaEnumerate(&filter, 1, tokens, num_matches, &num_matches);
Packit 534379
Packit 534379
    /* Destroy the properties object */
Packit 534379
    res = fpgaDestroyProperties(&filter);
Packit 534379
Packit 534379
    /* More code */
Packit 534379
    ......
Packit 534379
Packit 534379
    /* Destroy tokens */
Packit 534379
    for (uint32_t i = 0; i < num_matches; ++i) {
Packit 534379
        res = fpgaDestroyToken(tokens[i]);
Packit 534379
    }
Packit 534379
Packit 534379
Packit 534379
Packit 534379
The ```fpgaEnumerate()``` function can take multiple ```fpga_properties```objects in an array. In such cases,
Packit 534379
the function performs a logical OR of  the properties object and returns resources that match any of 
Packit 534379
the multiple properties. The  ```fpga_token``` objects that ```fpgaEnumerate()``` returns, do not signify
Packit 534379
ownership. To acquire ownership of a resource represented by a token, pass the token to `fpgaOpen()`.
Packit 534379
Packit 534379
Packit 534379
### Acquire and Release a Resource ###
Packit 534379
Use `fpgaOpen()` and `fpgaClose()` to acquire and release ownership of a resource. 
Packit 534379
The calling process must own the resource before it can initiate MMIO, access share memory buffers, 
Packit 534379
and use functions offered by the resource.
Packit 534379
Packit 534379
```c
Packit 534379
    #include "fpga/fpga.h"
Packit 534379
Packit 534379
    fpga_handle             handle;
Packit 534379
    fpga_result             res;
Packit 534379
Packit 534379
    /* Acquire ownership of a resource that 
Packit 534379
    `fpgaEnumerate()` previously returned as a token */
Packit 534379
     
Packit 534379
    res = fpgaOpen(token, &handle);
Packit 534379
Packit 534379
    /* More code */
Packit 534379
    ......
Packit 534379
Packit 534379
    /* Release the ownership */
Packit 534379
    res = fpgaClose(handle);
Packit 534379
```
Packit 534379
Packit 534379
### Shared Memory Buffer ###
Packit 534379
This code snippet shows how to prepare a memory buffer to be shared between the
Packit 534379
calling process and an accelerator.
Packit 534379
Packit 534379
```c
Packit 534379
    #include "fpga/fpga.h"
Packit 534379
Packit 534379
    fpga_handle             handle;
Packit 534379
    fpga_result             res;
Packit 534379
Packit 534379
    /* Hint for the virtual address of the buffer */
Packit 534379
    volatile uint64_t       *addr_hint;
Packit 534379
    /* An ID we can use to reference the buffer later */
Packit 534379
    uint32_t                bufid;
Packit 534379
    /* Flag to indicate whether or not the buffer is preallocated */
Packit 534379
    int                     flag = 0;
Packit 534379
Packit 534379
    /* Allocate (if necessary), pin, and map a buffer to be accessible
Packit 534379
       by an accelerator
Packit 534379
    */
Packit 534379
    res = fpgaPrepareBuffer(handle, BUF_SIZE, (void **) &addr_hint,
Packit 534379
                            &bufid, flag);
Packit 534379
Packit 534379
    /* The actual address mapped to the buffer */
Packit 534379
    uint64_t                iova;
Packit 534379
    /* Get the IO virtual address for the buffer */
Packit 534379
    res = fpgaGetIOAddress(handle, bufid, &iova);
Packit 534379
Packit 534379
    /* Inform the accelerator about the virtual address by writing to its mapped
Packit 534379
       register file
Packit 534379
    */
Packit 534379
    ......
Packit 534379
Packit 534379
    /* More code */
Packit 534379
    ......
Packit 534379
Packit 534379
    /* Release the shared buffer */
Packit 534379
    res = fpgaReleaseBuffer(handle, bufid);
Packit 534379
```
Packit 534379
Packit 534379
.. note::
Packit 534379
Packit 534379
```
Packit 534379
The `flag` variable can take a constant `FPGA_BUF_PREALLOCATED` to
Packit 534379
indicate that the calling process has already allocated the address space
Packit 534379
that `addr_hint` points to.
Packit 534379
```
Packit 534379
Packit 534379
### MMIO ###
Packit 534379
This code snippet shows how to map and unmap the register file of an accelerator into the
Packit 534379
calling process's virtual memory space.
Packit 534379
Packit 534379
```c
Packit 534379
    #include "fpga/fpga.h"
Packit 534379
Packit 534379
    fpga_handle             handle;
Packit 534379
    fpga_result             res;
Packit 534379
Packit 534379
    /* Index of the MMIO space. There might be multiple spaces on an accelerator */
Packit 534379
    uint32_t                mmio_num = 0;
Packit 534379
    /* Mapped address */
Packit 534379
    uint64_t                mmio_addr;
Packit 534379
Packit 534379
    /* Map MMIO */
Packit 534379
    res = fpgaMapMMIO(handle, mmio_num, &mmio_addr);
Packit 534379
Packit 534379
    /* Write to a 32-bit value to the mapped register file at a certain byte
Packit 534379
       offset.
Packit 534379
Packit 534379
       CSR_CTL is the offset in the mapped space to where the value will be
Packit 534379
       written. It's defined elsewhere.
Packit 534379
    */
Packit 534379
    res = fpgaWriteMMIO32(handle, mmio_num, CSR_CTL, value);
Packit 534379
Packit 534379
    /* More code */
Packit 534379
    ......
Packit 534379
Packit 534379
    /* Unmap MMIO */
Packit 534379
    res = fpgaUnmapMMIO(handle, mmio_num);
Packit 534379
```
Packit 534379
Packit 534379
.. Note::
Packit 534379
Packit 534379
```
Packit 534379
Every AFU has its own register adress space and its own protocol to control operation through 
Packit 534379
the registers. 
Packit 534379
```
Packit 534379