|
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 fpgaconf.c
|
|
Packit |
534379 |
*
|
|
Packit |
534379 |
* @brief FPGA configure command line tool
|
|
Packit |
534379 |
*
|
|
Packit |
534379 |
* fpgaconf allows you to program green bitstream files to an FPGA supported by
|
|
Packit |
534379 |
* the intel-fpga driver and API.
|
|
Packit |
534379 |
*
|
|
Packit |
534379 |
* Features:
|
|
Packit |
534379 |
* * Auto-discovery of compatible slots for supplied bitstream
|
|
Packit |
534379 |
* * Dry-run mode ("what would happen if...?")
|
|
Packit |
534379 |
*/
|
|
Packit |
534379 |
#define _GNU_SOURCE
|
|
Packit |
534379 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
534379 |
#include <config.h>
|
|
Packit |
534379 |
#endif // HAVE_CONFIG_H
|
|
Packit |
534379 |
#include <errno.h>
|
|
Packit |
534379 |
#include <getopt.h>
|
|
Packit |
534379 |
#include <stdio.h>
|
|
Packit |
534379 |
#include <stdlib.h>
|
|
Packit |
534379 |
#include <string.h>
|
|
Packit |
534379 |
#include <stdbool.h>
|
|
Packit |
534379 |
#include <sys/stat.h>
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#include <uuid/uuid.h>
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#include <opae/fpga.h>
|
|
Packit |
534379 |
#include <libbitstream/bitstream.h>
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/*
|
|
Packit |
534379 |
* macro to check FPGA 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 |
* Global configuration, set during parse_args()
|
|
Packit |
534379 |
*/
|
|
Packit |
534379 |
#define MAX_FILENAME_LEN 256
|
|
Packit |
534379 |
struct config {
|
|
Packit |
534379 |
unsigned int verbosity;
|
|
Packit |
534379 |
bool dry_run;
|
|
Packit |
534379 |
enum { INTERACTIVE, /* ask if ambiguous */
|
|
Packit |
534379 |
NORMAL, /* stop if ambiguous */
|
|
Packit |
534379 |
AUTOMATIC /* choose if ambiguous */
|
|
Packit |
534379 |
} mode;
|
|
Packit |
534379 |
int flags;
|
|
Packit |
534379 |
struct target {
|
|
Packit |
534379 |
int segment;
|
|
Packit |
534379 |
int bus;
|
|
Packit |
534379 |
int device;
|
|
Packit |
534379 |
int function;
|
|
Packit |
534379 |
int socket;
|
|
Packit |
534379 |
} target;
|
|
Packit |
534379 |
char *filename;
|
|
Packit |
534379 |
} config = {.verbosity = 0,
|
|
Packit |
534379 |
.dry_run = false,
|
|
Packit |
534379 |
.mode = NORMAL,
|
|
Packit |
534379 |
.flags = 0,
|
|
Packit |
534379 |
.target = {.segment = -1, .bus = -1, .device = -1, .function = -1, .socket = -1},
|
|
Packit |
534379 |
.filename = NULL };
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/*
|
|
Packit |
534379 |
* Print readable error message for fpga_results
|
|
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 |
* Print message depending on verbosity
|
|
Packit |
534379 |
*/
|
|
Packit |
534379 |
void print_msg(unsigned int verbosity, const char *s)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
if (config.verbosity >= verbosity)
|
|
Packit |
534379 |
printf("%s\n", s);
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/*
|
|
Packit |
534379 |
* Print help
|
|
Packit |
534379 |
* TODO: uncomment options as they are implemented
|
|
Packit |
534379 |
*/
|
|
Packit |
534379 |
void help(void)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
printf("\n"
|
|
Packit |
534379 |
"fpgaconf\n"
|
|
Packit |
534379 |
"FPGA configuration utility\n"
|
|
Packit |
534379 |
"\n"
|
|
Packit |
534379 |
"Usage:\n"
|
|
Packit |
534379 |
//" fpgaconf [-hvnAIQ] [-B <bus>] [-D <device>] [-F
|
|
Packit |
534379 |
//<function>] [-S <socket-id>] <gbs>\n"
|
|
Packit |
534379 |
" fpgaconf [-hvn] [-B <bus>] [-D <device>] [-F <function>] [-S <socket-id>] <gbs>\n"
|
|
Packit |
534379 |
"\n"
|
|
Packit |
534379 |
" -h,--help Print this help\n"
|
|
Packit |
534379 |
" -V,--verbose Increase verbosity\n"
|
|
Packit |
534379 |
" -n,--dry-run Don't actually perform actions\n"
|
|
Packit |
534379 |
" --force Don't try to open accelerator resource\n"
|
|
Packit |
534379 |
" --segment Set target segment number\n"
|
|
Packit |
534379 |
" -B,--bus Set target bus number\n"
|
|
Packit |
534379 |
" -D,--device Set target device number\n"
|
|
Packit |
534379 |
" -F,--function Set target function number\n"
|
|
Packit |
534379 |
" -S,--socket-id Set target socket number\n"
|
|
Packit |
534379 |
" -v,--version Print version info and exit\n"
|
|
Packit |
534379 |
/* " -A,--auto Automatically choose
|
|
Packit |
534379 |
target slot if\n" */
|
|
Packit |
534379 |
/* " multiple valid slots are
|
|
Packit |
534379 |
available\n" */
|
|
Packit |
534379 |
/* " -I,--interactive Prompt user to choose
|
|
Packit |
534379 |
target slot if\n" */
|
|
Packit |
534379 |
/* " multiple valid slots are
|
|
Packit |
534379 |
available\n" */
|
|
Packit |
534379 |
/* " -Q,--quiet Don't print any messages
|
|
Packit |
534379 |
except errors\n" */
|
|
Packit |
534379 |
"\n");
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/*
|
|
Packit |
534379 |
* Parse command line arguments
|
|
Packit |
534379 |
* TODO: uncomment options as they are implemented
|
|
Packit |
534379 |
*/
|
|
Packit |
534379 |
#define GETOPT_STRING ":hVnB:D:F:S:AIQv"
|
|
Packit |
534379 |
int parse_args(int argc, char *argv[])
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
struct option longopts[] = {
|
|
Packit |
534379 |
{"help", no_argument, NULL, 'h'},
|
|
Packit |
534379 |
{"verbose", no_argument, NULL, 'V'},
|
|
Packit |
534379 |
{"dry-run", no_argument, NULL, 'n'},
|
|
Packit |
534379 |
{"segment", required_argument, NULL, 0xe},
|
|
Packit |
534379 |
{"bus", required_argument, NULL, 'B'},
|
|
Packit |
534379 |
{"device", required_argument, NULL, 'D'},
|
|
Packit |
534379 |
{"function", required_argument, NULL, 'F'},
|
|
Packit |
534379 |
{"socket-id", required_argument, NULL, 'S'},
|
|
Packit |
534379 |
{"force", no_argument, NULL, 0xf},
|
|
Packit |
534379 |
{"version", no_argument, NULL, 'v'},
|
|
Packit |
534379 |
/* {"auto", no_argument, NULL, 'A'}, */
|
|
Packit |
534379 |
/* {"interactive", no_argument, NULL, 'I'}, */
|
|
Packit |
534379 |
/* {"quiet", no_argument, NULL, 'Q'}, */
|
|
Packit |
534379 |
{0, 0, 0, 0} };
|
|
Packit |
534379 |
|
|
Packit |
534379 |
int getopt_ret;
|
|
Packit |
534379 |
int option_index;
|
|
Packit |
534379 |
char *endptr = NULL;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
while (-1
|
|
Packit |
534379 |
!= (getopt_ret = getopt_long(argc, argv, GETOPT_STRING, longopts,
|
|
Packit |
534379 |
&option_index))) {
|
|
Packit |
534379 |
const char *tmp_optarg = optarg;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if ((optarg) && ('=' == *tmp_optarg)) {
|
|
Packit |
534379 |
++tmp_optarg;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
switch (getopt_ret) {
|
|
Packit |
534379 |
case 'h': /* help */
|
|
Packit |
534379 |
help();
|
|
Packit |
534379 |
return -1;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
case 'V': /* verbose */
|
|
Packit |
534379 |
config.verbosity++;
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
case 'n': /* dry-run */
|
|
Packit |
534379 |
config.dry_run = true;
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
case 0xf: /* force */
|
|
Packit |
534379 |
config.flags |= FPGA_RECONF_FORCE;
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
case 0xe: /* segment */
|
|
Packit |
534379 |
if (NULL == tmp_optarg)
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
endptr = NULL;
|
|
Packit |
534379 |
config.target.segment =
|
|
Packit |
534379 |
(int)strtoul(tmp_optarg, &endptr, 0);
|
|
Packit |
534379 |
if (endptr != tmp_optarg + strlen(tmp_optarg)) {
|
|
Packit |
534379 |
fprintf(stderr, "invalid segment: %s\n",
|
|
Packit |
534379 |
tmp_optarg);
|
|
Packit |
534379 |
return -1;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
case 'B': /* bus */
|
|
Packit |
534379 |
if (NULL == tmp_optarg)
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
endptr = NULL;
|
|
Packit |
534379 |
config.target.bus =
|
|
Packit |
534379 |
(int)strtoul(tmp_optarg, &endptr, 0);
|
|
Packit |
534379 |
if (endptr != tmp_optarg + strlen(tmp_optarg)) {
|
|
Packit |
534379 |
fprintf(stderr, "invalid bus: %s\n",
|
|
Packit |
534379 |
tmp_optarg);
|
|
Packit |
534379 |
return -1;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
case 'D': /* device */
|
|
Packit |
534379 |
if (NULL == tmp_optarg)
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
endptr = NULL;
|
|
Packit |
534379 |
config.target.device =
|
|
Packit |
534379 |
(int)strtoul(tmp_optarg, &endptr, 0);
|
|
Packit |
534379 |
if (endptr != tmp_optarg + strlen(tmp_optarg)) {
|
|
Packit |
534379 |
fprintf(stderr, "invalid device: %s\n",
|
|
Packit |
534379 |
tmp_optarg);
|
|
Packit |
534379 |
return -1;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
case 'F': /* function */
|
|
Packit |
534379 |
if (NULL == tmp_optarg)
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
endptr = NULL;
|
|
Packit |
534379 |
config.target.function =
|
|
Packit |
534379 |
(int)strtoul(tmp_optarg, &endptr, 0);
|
|
Packit |
534379 |
if (endptr != tmp_optarg + strlen(tmp_optarg)) {
|
|
Packit |
534379 |
fprintf(stderr, "invalid function: %s\n",
|
|
Packit |
534379 |
tmp_optarg);
|
|
Packit |
534379 |
return -1;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
case 'S': /* socket */
|
|
Packit |
534379 |
if (NULL == tmp_optarg)
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
endptr = NULL;
|
|
Packit |
534379 |
config.target.socket =
|
|
Packit |
534379 |
(int)strtoul(tmp_optarg, &endptr, 0);
|
|
Packit |
534379 |
if (endptr != tmp_optarg + strlen(tmp_optarg)) {
|
|
Packit |
534379 |
fprintf(stderr, "invalid socket: %s\n",
|
|
Packit |
534379 |
tmp_optarg);
|
|
Packit |
534379 |
return -1;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
case 'A': /* auto */
|
|
Packit |
534379 |
config.mode = AUTOMATIC;
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
case 'I': /* interactive */
|
|
Packit |
534379 |
config.mode = INTERACTIVE;
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
case 'Q': /* quiet */
|
|
Packit |
534379 |
config.verbosity = 0;
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
case 'v': /* version */
|
|
Packit |
534379 |
fprintf(stdout, "fpgaconf %s %s%s\n",
|
|
Packit |
534379 |
OPAE_VERSION,
|
|
Packit |
534379 |
OPAE_GIT_COMMIT_HASH,
|
|
Packit |
534379 |
OPAE_GIT_SRC_TREE_DIRTY ? "*":"");
|
|
Packit |
534379 |
return -1;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
case ':': /* missing option argument */
|
|
Packit |
534379 |
fprintf(stderr, "Missing option argument\n");
|
|
Packit |
534379 |
return -1;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
case '?':
|
|
Packit |
534379 |
default: /* invalid option */
|
|
Packit |
534379 |
fprintf(stderr, "Invalid cmdline options\n");
|
|
Packit |
534379 |
return -1;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* use first non-option argument as GBS filename */
|
|
Packit |
534379 |
if (optind == argc) {
|
|
Packit |
534379 |
fprintf(stderr, "No GBS file\n");
|
|
Packit |
534379 |
return -1;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
config.filename = canonicalize_file_name(argv[optind]);
|
|
Packit |
534379 |
if (config.filename) {
|
|
Packit |
534379 |
return 0;
|
|
Packit |
534379 |
} else {
|
|
Packit |
534379 |
fprintf(stderr, "Error locating GBS file specified: \"%s\"\n", strerror(errno));
|
|
Packit |
534379 |
return -1;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
fpga_result get_fpga_interface_id(fpga_token token, fpga_guid interface_id)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
fpga_result result = FPGA_OK;
|
|
Packit |
534379 |
fpga_result resval = FPGA_OK;
|
|
Packit |
534379 |
fpga_properties filter = NULL;
|
|
Packit |
534379 |
fpga_objtype objtype;
|
|
Packit |
534379 |
fpga_guid guid;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
result = fpgaGetProperties(token, &filter);
|
|
Packit |
534379 |
if (result != FPGA_OK) {
|
|
Packit |
534379 |
OPAE_ERR("Failed to get Token Properties Object");
|
|
Packit |
534379 |
goto out;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
result = fpgaPropertiesGetObjectType(filter, &objtype);
|
|
Packit |
534379 |
if (result != FPGA_OK) {
|
|
Packit |
534379 |
OPAE_ERR("Failed to get Token Properties Object");
|
|
Packit |
534379 |
goto out_destroy;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (objtype != FPGA_DEVICE) {
|
|
Packit |
534379 |
OPAE_ERR("Invalid FPGA object type");
|
|
Packit |
534379 |
result = FPGA_EXCEPTION;
|
|
Packit |
534379 |
goto out_destroy;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
result = fpgaPropertiesGetGUID(filter, &guid);
|
|
Packit |
534379 |
if (result != FPGA_OK) {
|
|
Packit |
534379 |
OPAE_ERR("Failed to get PR guid");
|
|
Packit |
534379 |
goto out_destroy;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
memcpy(interface_id, guid, sizeof(fpga_guid));
|
|
Packit |
534379 |
|
|
Packit |
534379 |
out_destroy:
|
|
Packit |
534379 |
resval = (result != FPGA_OK) ? result : resval;
|
|
Packit |
534379 |
result = fpgaDestroyProperties(&filter);
|
|
Packit |
534379 |
if (result != FPGA_OK) {
|
|
Packit |
534379 |
OPAE_ERR("Failed to destroy properties");
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
out:
|
|
Packit |
534379 |
resval = (result != FPGA_OK) ? result : resval;
|
|
Packit |
534379 |
return resval;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/*
|
|
Packit |
534379 |
* Prints Actual and Expected Interface id
|
|
Packit |
534379 |
*/
|
|
Packit |
534379 |
int print_interface_id(fpga_guid actual_interface_id)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
fpga_properties filter = NULL;
|
|
Packit |
534379 |
uint32_t num_matches = 0;
|
|
Packit |
534379 |
int retval = -1;
|
|
Packit |
534379 |
fpga_handle fpga_handle = NULL;
|
|
Packit |
534379 |
fpga_result res = -1;
|
|
Packit |
534379 |
fpga_token fpga_token = NULL;
|
|
Packit |
534379 |
fpga_guid expt_interface_id = {0};
|
|
Packit |
534379 |
char guid_str[37] = {0};
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res = fpgaGetProperties(NULL, &filter);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_err, "creating properties object");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res = fpgaPropertiesSetObjectType(filter, FPGA_DEVICE);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_destroy, "setting object type");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (-1 != config.target.segment) {
|
|
Packit |
534379 |
res = fpgaPropertiesSetSegment(filter, config.target.segment);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_destroy, "setting segment");
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (-1 != config.target.bus) {
|
|
Packit |
534379 |
res = fpgaPropertiesSetBus(filter, config.target.bus);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_destroy, "setting bus");
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (-1 != config.target.device) {
|
|
Packit |
534379 |
res = fpgaPropertiesSetDevice(filter, config.target.device);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_destroy, "setting device");
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (-1 != config.target.function) {
|
|
Packit |
534379 |
res = fpgaPropertiesSetFunction(filter, config.target.function);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_destroy, "setting function");
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (-1 != config.target.socket) {
|
|
Packit |
534379 |
res = fpgaPropertiesSetSocketID(filter, config.target.socket);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_destroy, "setting socket id");
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res = fpgaEnumerate(&filter, 1, &fpga_token, 1, &num_matches);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_destroy, "enumerating FPGAs");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (num_matches > 0) {
|
|
Packit |
534379 |
retval = (int)num_matches; /* FPGA found */
|
|
Packit |
534379 |
} else {
|
|
Packit |
534379 |
retval = 0; /* no FPGA found */
|
|
Packit |
534379 |
goto out_destroy;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res = fpgaOpen(fpga_token, &fpga_handle, 0);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_destroy, "opening fpga");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res = get_fpga_interface_id(fpga_token, expt_interface_id);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_close, "interfaceid get");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
uuid_unparse(expt_interface_id, guid_str);
|
|
Packit |
534379 |
printf("Expected Interface id: %s\n", guid_str);
|
|
Packit |
534379 |
|
|
Packit |
534379 |
uuid_unparse(actual_interface_id, guid_str);
|
|
Packit |
534379 |
printf("Actual Interface id: %s\n", guid_str);
|
|
Packit |
534379 |
|
|
Packit |
534379 |
|
|
Packit |
534379 |
out_close:
|
|
Packit |
534379 |
res = fpgaClose(fpga_handle);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_destroy, "closing fme");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
out_destroy:
|
|
Packit |
534379 |
if (fpga_token)
|
|
Packit |
534379 |
fpgaDestroyToken(&fpga_token);
|
|
Packit |
534379 |
res = fpgaDestroyProperties(&filter); /* not needed anymore */
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_err, "destroying properties object");
|
|
Packit |
534379 |
out_err:
|
|
Packit |
534379 |
return retval;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/*
|
|
Packit |
534379 |
* Find first FPGA matching the interface ID of the GBS
|
|
Packit |
534379 |
*
|
|
Packit |
534379 |
* @returns the total number of FPGAs matching the interface ID
|
|
Packit |
534379 |
*/
|
|
Packit |
534379 |
int find_fpga(fpga_guid interface_id, fpga_token *fpga)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
fpga_properties filter = NULL;
|
|
Packit |
534379 |
uint32_t num_matches;
|
|
Packit |
534379 |
fpga_result res;
|
|
Packit |
534379 |
int retval = -1;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* Get number of FPGAs in system */
|
|
Packit |
534379 |
res = fpgaGetProperties(NULL, &filter);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_err, "creating properties object");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res = fpgaPropertiesSetObjectType(filter, FPGA_DEVICE);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_destroy, "setting object type");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res = fpgaPropertiesSetGUID(filter, interface_id);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_destroy, "setting interface ID");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (-1 != config.target.segment) {
|
|
Packit |
534379 |
res = fpgaPropertiesSetSegment(filter, config.target.segment);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_destroy, "setting segment");
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (-1 != config.target.bus) {
|
|
Packit |
534379 |
res = fpgaPropertiesSetBus(filter, config.target.bus);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_destroy, "setting bus");
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (-1 != config.target.device) {
|
|
Packit |
534379 |
res = fpgaPropertiesSetDevice(filter, config.target.device);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_destroy, "setting device");
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (-1 != config.target.function) {
|
|
Packit |
534379 |
res = fpgaPropertiesSetFunction(filter, config.target.function);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_destroy, "setting function");
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (-1 != config.target.socket) {
|
|
Packit |
534379 |
res = fpgaPropertiesSetSocketID(filter, config.target.socket);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_destroy, "setting socket id");
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res = fpgaEnumerate(&filter, 1, fpga, 1, &num_matches);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_destroy, "enumerating FPGAs");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (num_matches > 0) {
|
|
Packit |
534379 |
retval = (int)num_matches; /* FPGA found */
|
|
Packit |
534379 |
} else {
|
|
Packit |
534379 |
retval = 0; /* no FPGA found */
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
out_destroy:
|
|
Packit |
534379 |
res = fpgaDestroyProperties(&filter); /* not needed anymore */
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_err, "destroying properties object");
|
|
Packit |
534379 |
out_err:
|
|
Packit |
534379 |
return retval;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
int program_bitstream(fpga_token token, uint32_t slot_num,
|
|
Packit |
534379 |
opae_bitstream_info *info, int flags)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
fpga_handle handle;
|
|
Packit |
534379 |
fpga_result res;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
print_msg(2, "Opening FPGA");
|
|
Packit |
534379 |
res = fpgaOpen(token, &handle, 0);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_err, "opening FPGA");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
print_msg(1, "Writing bitstream");
|
|
Packit |
534379 |
if (config.dry_run) {
|
|
Packit |
534379 |
print_msg(1, "[--dry-run] Skipping reconfiguration");
|
|
Packit |
534379 |
} else {
|
|
Packit |
534379 |
res = fpgaReconfigureSlot(handle, slot_num, info->data,
|
|
Packit |
534379 |
info->data_len, flags);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_close, "writing bitstream to FPGA");
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
print_msg(2, "Closing FPGA");
|
|
Packit |
534379 |
res = fpgaClose(handle);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_err, "closing FPGA");
|
|
Packit |
534379 |
return 1;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
out_close:
|
|
Packit |
534379 |
res = fpgaClose(handle);
|
|
Packit |
534379 |
ON_ERR_GOTO(res, out_err, "closing FPGA");
|
|
Packit |
534379 |
out_err:
|
|
Packit |
534379 |
return -1;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
|
|
Packit |
534379 |
int main(int argc, char *argv[])
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
int res;
|
|
Packit |
534379 |
fpga_result result;
|
|
Packit |
534379 |
int retval = 0;
|
|
Packit |
534379 |
opae_bitstream_info info;
|
|
Packit |
534379 |
fpga_token token;
|
|
Packit |
534379 |
uint32_t slot_num = 0; /* currently, we don't support multiple slots */
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* parse command line arguments */
|
|
Packit |
534379 |
res = parse_args(argc, argv);
|
|
Packit |
534379 |
if (res < 0) {
|
|
Packit |
534379 |
retval = 1;
|
|
Packit |
534379 |
goto out_exit;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (config.dry_run)
|
|
Packit |
534379 |
printf("--dry-run is set\n");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* allocate memory and read bitstream data */
|
|
Packit |
534379 |
print_msg(1, "Reading bitstream");
|
|
Packit |
534379 |
result = opae_load_bitstream(config.filename, &info;;
|
|
Packit |
534379 |
if (result != FPGA_OK) {
|
|
Packit |
534379 |
retval = 2;
|
|
Packit |
534379 |
goto out_exit;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* find suitable slot */
|
|
Packit |
534379 |
print_msg(1, "Looking for slot");
|
|
Packit |
534379 |
res = find_fpga(info.pr_interface_id, &token);
|
|
Packit |
534379 |
if (res < 0) {
|
|
Packit |
534379 |
retval = 3;
|
|
Packit |
534379 |
goto out_free;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
if (res == 0) {
|
|
Packit |
534379 |
fprintf(stderr, "No suitable slots found.\n");
|
|
Packit |
534379 |
retval = 4;
|
|
Packit |
534379 |
if (config.verbosity > 0)
|
|
Packit |
534379 |
print_interface_id(info.pr_interface_id);
|
|
Packit |
534379 |
goto out_free;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
if (res > 1) {
|
|
Packit |
534379 |
fprintf(stderr,
|
|
Packit |
534379 |
"Found more than one suitable slot, please be more specific.\n");
|
|
Packit |
534379 |
retval = 5;
|
|
Packit |
534379 |
goto out_destroy;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
print_msg(1, "Found slot");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* program bitstream */
|
|
Packit |
534379 |
print_msg(1, "Programming bitstream");
|
|
Packit |
534379 |
res = program_bitstream(token, slot_num, &info, config.flags);
|
|
Packit |
534379 |
if (res < 0) {
|
|
Packit |
534379 |
retval = 5;
|
|
Packit |
534379 |
goto out_destroy;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
print_msg(1, "Done");
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* clean up */
|
|
Packit |
534379 |
out_destroy:
|
|
Packit |
534379 |
fpgaDestroyToken(&token);
|
|
Packit |
534379 |
out_free:
|
|
Packit |
534379 |
opae_unload_bitstream(&info;;
|
|
Packit |
534379 |
out_exit:
|
|
Packit |
534379 |
if (config.filename) {
|
|
Packit |
534379 |
free(config.filename);
|
|
Packit |
534379 |
config.filename = NULL;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
return retval;
|
|
Packit |
534379 |
}
|