|
Packit |
534379 |
// Copyright(c) 2017-2020, Intel Corporation
|
|
Packit |
534379 |
//
|
|
Packit |
534379 |
// Redistribution and use in source and binary forms, with or without
|
|
Packit |
534379 |
// modification, are permitted provided that the following conditions are met:
|
|
Packit |
534379 |
//
|
|
Packit |
534379 |
// * Redistributions of source code must retain the above copyright notice,
|
|
Packit |
534379 |
// this list of conditions and the following disclaimer.
|
|
Packit |
534379 |
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
Packit |
534379 |
// this list of conditions and the following disclaimer in the documentation
|
|
Packit |
534379 |
// and/or other materials provided with the distribution.
|
|
Packit |
534379 |
// * Neither the name of Intel Corporation nor the names of its contributors
|
|
Packit |
534379 |
// may be used to endorse or promote products derived from this software
|
|
Packit |
534379 |
// without specific prior written permission.
|
|
Packit |
534379 |
//
|
|
Packit |
534379 |
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
Packit |
534379 |
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit |
534379 |
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
Packit |
534379 |
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
Packit |
534379 |
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
Packit |
534379 |
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
Packit |
534379 |
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
Packit |
534379 |
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
Packit |
534379 |
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
Packit |
534379 |
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
Packit |
534379 |
// POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/**
|
|
Packit |
534379 |
* @file hello_fpga.c
|
|
Packit |
534379 |
* @brief A code sample illustrates the basic usage of the OPAE C API.
|
|
Packit |
534379 |
*
|
|
Packit |
534379 |
* The sample is a host application that demonstrates the basic steps of
|
|
Packit |
534379 |
* interacting with FPGA using the OPAE library. These steps include:
|
|
Packit |
534379 |
*
|
|
Packit |
534379 |
* - FPGA enumeration
|
|
Packit |
534379 |
* - Resource acquiring and releasing
|
|
Packit |
534379 |
* - Managing shared memory buffer
|
|
Packit |
534379 |
* - MMIO read and write
|
|
Packit |
534379 |
*
|
|
Packit |
534379 |
* The sample also demonstrates OPAE's object model, such as tokens, handles,
|
|
Packit |
534379 |
* and properties.
|
|
Packit |
534379 |
*
|
|
Packit |
534379 |
* The sample requires a native loopback mode (NLB) test image to be loaded on
|
|
Packit |
534379 |
* the FPGA. Refer to
|
|
Packit |
534379 |
* Quick
|
|
Packit |
534379 |
* Start Guide for full instructions on building, configuring, and running
|
|
Packit |
534379 |
* this code sample.
|
|
Packit |
534379 |
*
|
|
Packit |
534379 |
*/
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
534379 |
#include <config.h>
|
|
Packit |
534379 |
#endif // HAVE_CONFIG_H
|
|
Packit |
534379 |
#include <stdio.h>
|
|
Packit |
534379 |
#include <stdlib.h>
|
|
Packit |
534379 |
#include <string.h>
|
|
Packit |
534379 |
#include <stdint.h>
|
|
Packit |
534379 |
#include <getopt.h>
|
|
Packit |
534379 |
#include <unistd.h>
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#include <uuid/uuid.h>
|
|
Packit |
534379 |
#include <opae/fpga.h>
|
|
Packit |
534379 |
|
|
Packit |
534379 |
int usleep(unsigned);
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#ifndef TEST_TIMEOUT
|
|
Packit |
534379 |
#define TEST_TIMEOUT 30000
|
|
Packit |
534379 |
#endif // TEST_TIMEOUT
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#ifndef CL
|
|
Packit |
534379 |
# define CL(x) ((x) * 64)
|
|
Packit |
534379 |
#endif // CL
|
|
Packit |
534379 |
#ifndef LOG2_CL
|
|
Packit |
534379 |
# define LOG2_CL 6
|
|
Packit |
534379 |
#endif // LOG2_CL
|
|
Packit |
534379 |
#ifndef MB
|
|
Packit |
534379 |
# define MB(x) ((x) * 1024 * 1024)
|
|
Packit |
534379 |
#endif // MB
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#define CACHELINE_ALIGNED_ADDR(p) ((p) >> LOG2_CL)
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#define LPBK1_BUFFER_SIZE MB(1)
|
|
Packit |
534379 |
#define LPBK1_BUFFER_ALLOCATION_SIZE MB(2)
|
|
Packit |
534379 |
#define LPBK1_DSM_SIZE MB(2)
|
|
Packit |
534379 |
#define CSR_SRC_ADDR 0x0120
|
|
Packit |
534379 |
#define CSR_DST_ADDR 0x0128
|
|
Packit |
534379 |
#define CSR_CTL 0x0138
|
|
Packit |
534379 |
#define CSR_STATUS1 0x0168
|
|
Packit |
534379 |
#define CSR_CFG 0x0140
|
|
Packit |
534379 |
#define CSR_NUM_LINES 0x0130
|
|
Packit |
534379 |
#define DSM_STATUS_TEST_COMPLETE 0x40
|
|
Packit |
534379 |
#define CSR_AFU_DSM_BASEL 0x0110
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* NLB0 AFU_ID */
|
|
Packit |
534379 |
#define NLB0_AFUID "D8424DC4-A4A3-C413-F89E-433683F9040B"
|
|
Packit |
534379 |
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/*
|
|
Packit |
534379 |
* macro to check return codes, print error message, and goto cleanup label
|
|
Packit |
534379 |
* NOTE: this changes the program flow (uses goto)!
|
|
Packit |
534379 |
*/
|
|
Packit |
534379 |
#define ON_ERR_GOTO(res, label, desc) \
|
|
Packit |
534379 |
do { \
|
|
Packit |
534379 |
if ((res) != FPGA_OK) { \
|
|
Packit |
534379 |
print_err((desc), (res)); \
|
|
Packit |
534379 |
goto label; \
|
|
Packit |
534379 |
} \
|
|
Packit |
534379 |
} while (0)
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* Type definitions */
|
|
Packit |
534379 |
typedef struct {
|
|
Packit |
534379 |
uint32_t uint[16];
|
|
Packit |
534379 |
} cache_line;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
void print_err(const char *s, fpga_result res)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
fprintf(stderr, "Error %s: %s\n", s, fpgaErrStr(res));
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/*
|
|
Packit |
534379 |
* Global configuration of bus, set during parse_args()
|
|
Packit |
534379 |
* */
|
|
Packit |
534379 |
struct config {
|
|
Packit |
534379 |
struct target {
|
|
Packit |
534379 |
int bus;
|
|
Packit |
534379 |
} target;
|
|
Packit |
534379 |
int open_flags;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
config = {
|
|
Packit |
534379 |
.target = {
|
|
Packit |
534379 |
.bus = -1,
|
|
Packit |
534379 |
},
|
|
Packit |
534379 |
.open_flags = 0
|
|
Packit |
534379 |
};
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#define GETOPT_STRING "B:sv"
|
|
Packit |
534379 |
fpga_result parse_args(int argc, char *argv[])
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
struct option longopts[] = {
|
|
Packit |
534379 |
{ "bus", required_argument, NULL, 'B' },
|
|
Packit |
534379 |
{ "shared", no_argument, NULL, 's' },
|
|
Packit |
534379 |
{ "version", no_argument, NULL, 'v' },
|
|
Packit |
534379 |
{ NULL, 0, NULL, 0 }
|
|
Packit |
534379 |
};
|
|
Packit |
534379 |
|
|
Packit |
534379 |
int getopt_ret;
|
|
Packit |
534379 |
int option_index;
|
|
Packit |
534379 |
char *endptr = NULL;
|
|
Packit |
534379 |
char version[32];
|
|
Packit |
534379 |
char build[32];
|
|
Packit |
534379 |
|
|
Packit |
534379 |
while (-1 != (getopt_ret = getopt_long(argc, argv, GETOPT_STRING,
|
|
Packit |
534379 |
longopts, &option_index))) {
|
|
Packit |
534379 |
const char *tmp_optarg = optarg;
|
|
Packit |
534379 |
/* Checks to see if optarg is null and if not it goes to value of optarg */
|
|
Packit |
534379 |
if ((optarg) && ('=' == *tmp_optarg)) {
|
|
Packit |
534379 |
++tmp_optarg;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
switch (getopt_ret) {
|
|
Packit |
534379 |
case 'B': /* bus */
|
|
Packit |
534379 |
if (NULL == tmp_optarg) {
|
|
Packit |
534379 |
return FPGA_EXCEPTION;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
endptr = NULL;
|
|
Packit |
534379 |
config.target.bus = (int) strtoul(tmp_optarg, &endptr, 0);
|
|
Packit |
534379 |
if (endptr != tmp_optarg + strnlen(tmp_optarg, 100)) {
|
|
Packit |
534379 |
fprintf(stderr, "invalid bus: %s\n", tmp_optarg);
|
|
Packit |
534379 |
return FPGA_EXCEPTION;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
case 's':
|
|
Packit |
534379 |
config.open_flags |= FPGA_OPEN_SHARED;
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
case 'v':
|
|
Packit |
534379 |
fpgaGetOPAECVersionString(version, sizeof(version));
|
|
Packit |
534379 |
fpgaGetOPAECBuildString(build, sizeof(build));
|
|
Packit |
534379 |
printf("hello_fpga %s %s\n",
|
|
Packit |
534379 |
version, build);
|
|
Packit |
534379 |
return -1;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
default: /* invalid option */
|
|
Packit |
534379 |
fprintf(stderr, "Invalid cmdline option \n");
|
|
Packit |
534379 |
return FPGA_EXCEPTION;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return FPGA_OK;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
fpga_result find_fpga(fpga_guid afu_guid,
|
|
Packit |
534379 |
fpga_token *accelerator_token,
|
|
Packit |
534379 |
uint32_t *num_matches_accelerators)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
fpga_properties filter = NULL;
|
|
Packit |
534379 |
fpga_result res1;
|
|
Packit |
534379 |
fpga_result res2 = FPGA_OK;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res1 = fpgaGetProperties(NULL, &filter);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out, "creating properties object");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res1 = fpgaPropertiesSetObjectType(filter, FPGA_ACCELERATOR);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_destroy, "setting object type");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res1 = fpgaPropertiesSetGUID(filter, afu_guid);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_destroy, "setting GUID");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (-1 != config.target.bus) {
|
|
Packit |
534379 |
res1 = fpgaPropertiesSetBus(filter, config.target.bus);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_destroy, "setting bus");
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res1 = fpgaEnumerate(&filter, 1, accelerator_token, 1, num_matches_accelerators);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_destroy, "enumerating accelerators");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
out_destroy:
|
|
Packit |
534379 |
res2 = fpgaDestroyProperties(&filter);
|
|
Packit |
534379 |
ON_ERR_GOTO(res2, out, "destroying properties object");
|
|
Packit |
534379 |
out:
|
|
Packit |
534379 |
return res1 != FPGA_OK ? res1 : res2;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* function to get the bus number when there are multiple accelerators */
|
|
Packit |
534379 |
fpga_result get_bus(fpga_token tok, uint8_t *bus)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
fpga_result res1;
|
|
Packit |
534379 |
fpga_result res2 = FPGA_OK;
|
|
Packit |
534379 |
fpga_properties props = NULL;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res1 = fpgaGetProperties(tok, &props;;
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out, "reading properties from Token");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res1 = fpgaPropertiesGetBus(props, bus);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_destroy, "Reading bus from properties");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
out_destroy:
|
|
Packit |
534379 |
res2 = fpgaDestroyProperties(&props;;
|
|
Packit |
534379 |
ON_ERR_GOTO(res2, out, "fpgaDestroyProps");
|
|
Packit |
534379 |
out:
|
|
Packit |
534379 |
return res1 != FPGA_OK ? res1 : res2;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* Is the FPGA simulated with ASE? */
|
|
Packit |
534379 |
bool probe_for_ase(void)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
fpga_result r = FPGA_OK;
|
|
Packit |
534379 |
uint16_t device_id = 0;
|
|
Packit |
534379 |
fpga_properties filter = NULL;
|
|
Packit |
534379 |
uint32_t num_matches = 1;
|
|
Packit |
534379 |
fpga_token fme_token;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* Connect to the FPGA management engine */
|
|
Packit |
534379 |
fpgaGetProperties(NULL, &filter);
|
|
Packit |
534379 |
fpgaPropertiesSetObjectType(filter, FPGA_DEVICE);
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* Connecting to one is sufficient to find ASE */
|
|
Packit |
534379 |
fpgaEnumerate(&filter, 1, &fme_token, 1, &num_matches);
|
|
Packit |
534379 |
if (0 != num_matches) {
|
|
Packit |
534379 |
/* Retrieve the device ID of the FME */
|
|
Packit |
534379 |
fpgaDestroyProperties(&filter);
|
|
Packit |
534379 |
fpgaGetProperties(fme_token, &filter);
|
|
Packit |
534379 |
r = fpgaPropertiesGetDeviceID(filter, &device_id);
|
|
Packit |
534379 |
fpgaDestroyToken(&fme_token);
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
fpgaDestroyProperties(&filter);
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* ASE's device ID is 0xa5e */
|
|
Packit |
534379 |
return ((FPGA_OK == r) && (0xa5e == device_id));
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
int main(int argc, char *argv[])
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
fpga_token accelerator_token;
|
|
Packit |
534379 |
fpga_handle accelerator_handle;
|
|
Packit |
534379 |
fpga_guid guid;
|
|
Packit |
534379 |
uint32_t num_matches_accelerators = 0;
|
|
Packit |
534379 |
uint32_t use_ase;
|
|
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 |
uint8_t bus = 0xff;
|
|
Packit |
534379 |
uint32_t i;
|
|
Packit |
534379 |
uint32_t timeout;
|
|
Packit |
534379 |
fpga_result res1 = FPGA_OK;
|
|
Packit |
534379 |
fpga_result res2 = FPGA_OK;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res1 = parse_args(argc, argv);
|
|
Packit |
534379 |
if ((int)res1 < 0)
|
|
Packit |
534379 |
goto out_exit;
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_exit, "parsing arguments");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (uuid_parse(NLB0_AFUID, guid) < 0) {
|
|
Packit |
534379 |
res1 = FPGA_EXCEPTION;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_exit, "parsing guid");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
use_ase = probe_for_ase();
|
|
Packit |
534379 |
if (use_ase) {
|
|
Packit |
534379 |
printf("Running in ASE mode\n");
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* Look for accelerator with NLB0_AFUID */
|
|
Packit |
534379 |
res1 = find_fpga(guid, &accelerator_token, &num_matches_accelerators);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_exit, "finding FPGA accelerator");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (num_matches_accelerators <= 0) {
|
|
Packit |
534379 |
res1 = FPGA_NOT_FOUND;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_exit, "no matching accelerator");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (num_matches_accelerators > 1) {
|
|
Packit |
534379 |
printf("Found more than one suitable accelerator. ");
|
|
Packit |
534379 |
res1 = get_bus(accelerator_token, &bus;;
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_exit, "getting bus num");
|
|
Packit |
534379 |
printf("Running on bus 0x%02x.\n", bus);
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* Open accelerator and map MMIO */
|
|
Packit |
534379 |
res1 = fpgaOpen(accelerator_token, &accelerator_handle, config.open_flags);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_destroy_tok, "opening accelerator");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res1 = fpgaMapMMIO(accelerator_handle, 0, NULL);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_close, "mapping MMIO space");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* Allocate buffers */
|
|
Packit |
534379 |
res1 = fpgaPrepareBuffer(accelerator_handle, LPBK1_DSM_SIZE,
|
|
Packit |
534379 |
(void **)&dsm_ptr, &dsm_wsid, 0);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_close, "allocating DSM buffer");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res1 = fpgaPrepareBuffer(accelerator_handle, LPBK1_BUFFER_ALLOCATION_SIZE,
|
|
Packit |
534379 |
(void **)&input_ptr, &input_wsid, 0);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_free_dsm, "allocating input buffer");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res1 = fpgaPrepareBuffer(accelerator_handle, LPBK1_BUFFER_ALLOCATION_SIZE,
|
|
Packit |
534379 |
(void **)&output_ptr, &output_wsid, 0);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_free_input, "allocating output buffer");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
printf("Running Test\n");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
bus = 0xff;
|
|
Packit |
534379 |
res1 = get_bus(accelerator_token, &bus;;
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_free_output, "getting bus num");
|
|
Packit |
534379 |
printf("Running on bus 0x%02x.\n", bus);
|
|
Packit |
534379 |
|
|
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 (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 |
|
|
Packit |
534379 |
/* Reset accelerator */
|
|
Packit |
534379 |
res1 = fpgaReset(accelerator_handle);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_free_output, "resetting accelerator");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* Program DMA addresses */
|
|
Packit |
534379 |
uint64_t iova = 0;
|
|
Packit |
534379 |
res1 = fpgaGetIOAddress(accelerator_handle, dsm_wsid, &iova);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_free_output, "getting DSM IOVA");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res1 = fpgaWriteMMIO64(accelerator_handle, 0, CSR_AFU_DSM_BASEL, iova);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_free_output, "writing CSR_AFU_DSM_BASEL");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res1 = fpgaWriteMMIO32(accelerator_handle, 0, CSR_CTL, 0);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_free_output, "writing CSR_CFG");
|
|
Packit |
534379 |
res1 = fpgaWriteMMIO32(accelerator_handle, 0, CSR_CTL, 1);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_free_output, "writing CSR_CFG");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res1 = fpgaGetIOAddress(accelerator_handle, input_wsid, &iova);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_free_output, "getting input IOVA");
|
|
Packit |
534379 |
res1 = fpgaWriteMMIO64(accelerator_handle, 0, CSR_SRC_ADDR, CACHELINE_ALIGNED_ADDR(iova));
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_free_output, "writing CSR_SRC_ADDR");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res1 = fpgaGetIOAddress(accelerator_handle, output_wsid, &iova);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_free_output, "getting output IOVA");
|
|
Packit |
534379 |
res1 = fpgaWriteMMIO64(accelerator_handle, 0, CSR_DST_ADDR, CACHELINE_ALIGNED_ADDR(iova));
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_free_output, "writing CSR_DST_ADDR");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res1 = fpgaWriteMMIO32(accelerator_handle, 0, CSR_NUM_LINES, LPBK1_BUFFER_SIZE / CL(1));
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_free_output, "writing CSR_NUM_LINES");
|
|
Packit |
534379 |
res1 = fpgaWriteMMIO32(accelerator_handle, 0, CSR_CFG, 0x42000);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_free_output, "writing CSR_CFG");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
status_ptr = dsm_ptr + DSM_STATUS_TEST_COMPLETE/sizeof(uint64_t);
|
|
Packit |
534379 |
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* Start the test */
|
|
Packit |
534379 |
res1 = fpgaWriteMMIO32(accelerator_handle, 0, CSR_CTL, 3);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_free_output, "writing CSR_CFG");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* Wait for test completion */
|
|
Packit |
534379 |
timeout = TEST_TIMEOUT;
|
|
Packit |
534379 |
while (0 == ((*status_ptr) & 0x1)) {
|
|
Packit |
534379 |
usleep(100);
|
|
Packit |
534379 |
if (!use_ase && (--timeout == 0)) {
|
|
Packit |
534379 |
res1 = FPGA_EXCEPTION;
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_free_output, "test timed out");
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* Stop the device */
|
|
Packit |
534379 |
res1 = fpgaWriteMMIO32(accelerator_handle, 0, CSR_CTL, 7);
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_free_output, "writing CSR_CFG");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* Wait for the AFU's read/write traffic to complete */
|
|
Packit |
534379 |
uint32_t afu_traffic_trips = 0;
|
|
Packit |
534379 |
while (afu_traffic_trips < 100) {
|
|
Packit |
534379 |
/*
|
|
Packit |
534379 |
* CSR_STATUS1 holds two 32 bit values: num pending reads and writes.
|
|
Packit |
534379 |
* Wait for it to be 0.
|
|
Packit |
534379 |
*/
|
|
Packit |
534379 |
uint64_t s1;
|
|
Packit |
534379 |
res1 = fpgaReadMMIO64(accelerator_handle, 0, CSR_STATUS1, &s1;;
|
|
Packit |
534379 |
ON_ERR_GOTO(res1, out_free_output, "reading CSR_STATUS1");
|
|
Packit |
534379 |
if (s1 == 0) {
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
afu_traffic_trips += 1;
|
|
Packit |
534379 |
usleep(1000);
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* Check output buffer contents */
|
|
Packit |
534379 |
for (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 |
|
|
Packit |
534379 |
/* Release buffers */
|
|
Packit |
534379 |
out_free_output:
|
|
Packit |
534379 |
res2 = fpgaReleaseBuffer(accelerator_handle, output_wsid);
|
|
Packit |
534379 |
ON_ERR_GOTO(res2, out_free_input, "releasing output buffer");
|
|
Packit |
534379 |
out_free_input:
|
|
Packit |
534379 |
res2 = fpgaReleaseBuffer(accelerator_handle, input_wsid);
|
|
Packit |
534379 |
ON_ERR_GOTO(res2, out_free_dsm, "releasing input buffer");
|
|
Packit |
534379 |
out_free_dsm:
|
|
Packit |
534379 |
res2 = fpgaReleaseBuffer(accelerator_handle, dsm_wsid);
|
|
Packit |
534379 |
ON_ERR_GOTO(res2, out_unmap, "releasing DSM buffer");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* Unmap MMIO space */
|
|
Packit |
534379 |
out_unmap:
|
|
Packit |
534379 |
res2 = fpgaUnmapMMIO(accelerator_handle, 0);
|
|
Packit |
534379 |
ON_ERR_GOTO(res2, out_close, "unmapping MMIO space");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* Release accelerator */
|
|
Packit |
534379 |
out_close:
|
|
Packit |
534379 |
res2 = fpgaClose(accelerator_handle);
|
|
Packit |
534379 |
ON_ERR_GOTO(res2, out_destroy_tok, "closing accelerator");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* Destroy token */
|
|
Packit |
534379 |
out_destroy_tok:
|
|
Packit |
534379 |
res2 = fpgaDestroyToken(&accelerator_token);
|
|
Packit |
534379 |
ON_ERR_GOTO(res2, out_exit, "destroying token");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
out_exit:
|
|
Packit |
534379 |
return res1 != FPGA_OK ? res1 : res2;
|
|
Packit |
534379 |
}
|