Skip to content

Part 3: Deploy your bitstreams

Estimated reading time: 26 minutes

This part of the tutorial refers primarily to bitstream developers who are willing to distribute their FPGA accelerators. By deploying their bitstreams their implemented accelerators will be available to easily get invoked by any application through Coral API. If you won't be writing your own bitstreams you may want to skip this section and move on to Part 4 to learn how to invoke prebuilt accelerators in your applications.

In this section, we walk you through the process of installing an FPGA bitstream binary either locally or remotely. We will teach you how to create bitstream artifacts and how to encrypt and deploy them to a local or a remote repository.

Bitstream Development (Optional)-

In this section, we provide the "Hello World" accelerator example for bitstream development comprised of a simple vector addition and subtraction. To elucidate, the first kernel receives as input two float arrays and adds their respective elements in an output array. The second kernel performs a similar operation where instead of addition, an element-wise subtraction operation is performed.

Since those kernels are considered trivial, we will not include the implementation in this tutorial. However you can download the source code from our Bitbucket repository.

Build instructions for AWS-

  1. Launch an FPGA Developer AMI instance.

  2. Install the AWS FPGA development toolkit.

    git clone https://github.com/aws/aws-fpga.git
    source aws-fpga/sdaccel_setup.sh
    
  3. Clone our demo repository and compile the included FPGA kernels.

    git clone https://bitbucket.org/inaccel/demo.git && cd demo
    make -C device
    

    Warning

    FPGA binary compilation is a very slow process. You can still skip this part and use our prebuild FPGA binary.

  4. Create an Amazon FPGA Image (AFI).

    ${SDACCEL_DIR}/tools/create_sdaccel_afi.sh -xclbin=device/binary/demo.xclbin -o=device/binary/demo -s3_bucket=inaccel -s3_dcp_key=demo_dcp -s3_logs_key=demo_logs
    

For more details on the full AWS F1 development lifecycle please refer to this SDAccel Quick Start Guide.

Bitstream Packaging-

We assume that you have already implemented and compiled a simple bitstream comprised of the two kernels mentioned above. In case you didn't complete the above steps for AWS, you can still download the prebuilt bitstream binary (demo.awsxclbin) from InAccel Store.

At this point, we are ready to move on to the next stage and describe our generated bistream, creating the specification file (bitstream.json or bitstream.xml) that will accompany the bitstream artifact.

Describe your FPGA binary-

As mentioned before, each bitstream artifact contains a descriptive JSON (or XML) file that defines all the details required to thoroughly describe the compiled bitstream. These information include target platform, bitstream kernels, version and other metadata.

Below we present a verbose, yet simple bitstream.json file for our bitstream:

{
    "name": "demo.awsxclbin",
    "bitstreamId": "com.inaccel.math.vector",
    "version": "0.1",
    "description": "vector operations",
    "platform": {
        "vendor": "xilinx",
        "name": "aws-vu9p-f1-04261818",
        "version": "dynamic_5.0"
    },
    "kernels": [
        {
            "name": "vadd_kernel_0",
            "kernelId": "addition",
            "arguments": [
                {
                    "type": "float16*",
                    "name": "input1",
                    "memory": ["0"],
                    "access": "r"
                },
                {
                    "type": "float16*",
                    "name": "input2",
                    "memory": ["0"],
                    "access": "r"
                },
                {
                    "type": "float16*",
                    "name": "output",
                    "memory": ["0"],
                    "access": "w"
                },
                {
                    "type": "int",
                    "name": "size"
                }
            ]
        },
        {
            "name": "vadd_kernel_1",
            "kernelId": "addition",
            "arguments": [
                {
                    "type": "float16*",
                    "name": "input1",
                    "memory": ["1"],
                    "access": "r"
                },
                {
                    "type": "float16*",
                    "name": "input2",
                    "memory": ["1"],
                    "access": "r"
                },
                {
                    "type": "float16*",
                    "name": "output",
                    "memory": ["1"],
                    "access": "w"
                },
                {
                    "type": "int",
                    "name": "size"
                }
            ]
        },
        {
            "name": "vsub_kernel_0",
            "kernelId": "subtraction",
            "arguments": [
                {
                    "type": "float16*",
                    "name": "input1",
                    "memory": ["2"],
                    "access": "r"
                },
                {
                    "type": "float16*",
                    "name": "input2",
                    "memory": ["2"],
                    "access": "r"
                },
                {
                    "type": "float16*",
                    "name": "output",
                    "memory": ["2"],
                    "access": "w"
                },
                {
                    "type": "int",
                    "name": "size"
                }
            ]
        },
        {
            "name": "vsub_kernel_1",
            "kernelId": "subtraction",
            "arguments": [
                {
                    "type": "float16*",
                    "name": "input1",
                    "memory": ["3"],
                    "access": "r"
                },
                {
                    "type": "float16*",
                    "name": "input2",
                    "memory": ["3"],
                    "access": "r"
                },
                {
                    "type": "float16*",
                    "name": "output",
                    "memory": ["3"],
                    "access": "w"
                },
                {
                    "type": "int",
                    "name": "size"
                }
            ]
        }
    ]
}

As you can notice, we designed bitstream specification file to contain fields which are self-descriptive to reduce the documentation lookup overhead. However, we will make a brief description for most of the fields with the risk of being redundant, to make you comfortable on creating your own.

Let's explore the fields we used in our specification file:

  • name - Bitstream name should match the FPGA binary name
  • bitstreamId - Prefix to be used by applications to invoke kernels in this bitstream
  • version - Bitstream version
  • description - Bitstream description
  • platform
    • vendor - FPGA vendor
    • name - FPGA board name
    • version - FPGA board version

Now it's time to declare your bitstream kernels. Those are declared inside the specification file as an array named kernels. Each kernel is represented as an object with the following fields:

  • name - Actual name of the kernel function inside the bitstream
  • kernelId - Alias name to invoke the specific kernel in your applications
  • arguments - An array specifying all the kernel arguments
    • type - Data type (a star '*' indicates that the argument is an array)
    • name - Descriptive argument name
    • memory - Memory bank identifier (only for arrays, not for scalars)
    • access - Access permissions (only for arrays, not for scalars)

You are now ready to deploy your first bitstream artifact. For a more detailed overview of the metadata supported by the bitstream specification file check out the detailed Bitstream Reference.

Bitstream Deployment-

Once you have created a bitstream artifact by providing a complete bitstream specification file along with your bitstream binary, you can easily deploy it through InAccel's CLI. Refer to Command Line Interface Reference for extensive CLI usage.

The Bitstream binary and its specification file must reside in the same directory.

Local deployment-

Below, we present a typical workflow of deploying your bitstream artifact to your local repository. When you deploy locally, your bitstreams are stored in your local machine and become available to Coral running on your machine immediately. Follow the steps below to get started:

Step 1: (recommended)

Encrypt your bitstream by running the following command. The path should point to the bitstream binary file.

$ inaccel bitstream encrypt /path/to/bitstream-binary

Step 2:

Deploy the bitstream artifact to your local repository. The path given as argument should contain both the binary and the specification file.

$ inaccel bitstream install /path/to/bitstream-directory

Step 3:

Verify that your bitstream is properly installed to your local repository by issuing the command below.

$ inaccel bitstream list
CHECKSUM        BITSTREAM ID                VERSION     PLATFORM                                    KERNEL IDS
9b65d0d622eb    com.inaccel.math.vector     0.1         aws-vu9p-f1-04261818 (xilinx dynamic_5.0)   [addition subtraction]

If the output of the command matches the one presented above then you have successfully installed the demo bitstream artifact to your local repository. After installing the bitstream artifact to your local repository, you can expect that all kernels of the corresponding bitstream will be easily and securely accesible from every application requesting accelerators from Coral.

As a bonus, to list the available accelerators of your recently deployed bitstream along with their function prototypes, you simply have to list them using your bitstream's checksum value:

$ inaccel bitstream list 9b65d0d622eb
VERSION         0.1
PLATFORM        aws-vu9p-f1-04261818 (xilinx dynamic_5.0)
ACCELERATORS    com.inaccel.math.vector.addition (float16* input1, float16* input2, float16* output, int size)
                com.inaccel.math.vector.subtraction (float16* input1, float16* input2, float16* output, int size)

Remote deployment (Optional)-

Apart from deploying your bitstream to a local repository, you may wish to have your bitstreams also deployed remotely. Follow the steps below to explore remote repository capabilities:

Step 1:

Start tracking your remote repository through inaccel config command. For this tutorial, we will enter some dummy credentials where you can fill in your own according to your needs.

inaccel config repository --user inaccel --password rocks --url https://demo.inaccel.com/bistreams demo-repo

Notice that demo-repo serves as an id for your remote repository.

Step 2:

Verify successful tracking of your remote repository by inspecting ~/.inaccel/settings.xml file and search for the output presented below:

<repository>
    <id>demo-repo</id>
    <user>inaccel</user>
    <password>rocks</password>
    <url>https://demo.inaccel.com/bitstreams</url>
</repository>

Step 3:

Deploy the bitstream artifact to the demo-repo repository. Again the path given as argument should contain your bitstream binary and specification files.

$ inaccel bitstream install --repository demo-repo /path/to/bitstream-directory

Step 4:

Verify that your bitstream was properly installed to your remote repository by running:

$ inaccel bitstream list --repository demo-repo
CHECKSUM        BITSTREAM ID                VERSION     PLATFORM                                    KERNEL IDS
9b65d0d622eb    com.inaccel.math.vector     0.1         aws-vu9p-f1-04261818 (xilinx dynamic_5.0)   [addition subtraction]

Assuming you are presented with a similar output you are ready to start leveraging your accelerators in your applications.

Bitstream Resolution-

InAccel offers a fully-fledged bitstream repository with various bitstreams available according to whether you own a Community Edition (CE) or an Enterprise Edition (EE) license.

For this tutorial we need to resolve the demo bitstream that contains the kernels we will need for our application.

inaccel bitstream install https://store.inaccel.com/artifactory/bitstreams/com/inaccel/math/vector/0.1/xilinx/aws-vu9p-f1-04261818/dynamic_5.0/addition_subtraction

Finally, you can explore the available bitstreams on our repository, or host your own repository and collaborate with your peers.

Discover available accelerators-

As an application developer, you would like to explore the available accelerators in your bitstream repository. Since you may have not deployed those bitstreams yourself, simply issue inaccel bitstream list command to get an overview of the deployed bitstreams in your system along with their description and available accelerators:

$ inaccel bitstream list
CHECKSUM        BITSTREAM ID                VERSION     PLATFORM                                    KERNEL IDS
9b65d0d622eb    com.inaccel.math.vector     0.1         aws-vu9p-f1-04261818 (xilinx dynamic_5.0)   [addition subtraction]

From the above output, we notice that our repository contains one deployed bitstream with two accelerators suitable for our goals (i.e addition and subtraction). Our next step is to inspect the bitstream of interest to list its available accelerators as function prototypes to get a notion of how to invoke them on our application. We simply issue the following command:

$ inaccel bitstream list 9b65d0d622eb
VERSION         0.1
PLATFORM        aws-vu9p-f1-04261818 (xilinx dynamic_5.0)
ACCELERATORS    com.inaccel.math.vector.addition (float16* input1, float16* input2, float16* output, int size)
                com.inaccel.math.vector.subtraction (float16* input1, float16* input2, float16* output, int size)

That's it! You are now ready to move to Part 4: Accelerate your app, to invoke your accelerators from your applications.