|
Packit |
534379 |
#!/usr/bin/env python
|
|
Packit |
534379 |
# Copyright(c) 2017, 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 |
import os
|
|
Packit |
534379 |
import sys
|
|
Packit |
534379 |
import argparse
|
|
Packit |
534379 |
import re
|
|
Packit |
534379 |
import json
|
|
Packit |
534379 |
import zipfile
|
|
Packit |
534379 |
import uuid
|
|
Packit |
534379 |
from afu import AFU
|
|
Packit |
534379 |
|
|
Packit |
534379 |
AFU_JSON_MGR_EXEC = "afu_json_mgr"
|
|
Packit |
534379 |
DESCRIPTION = 'Intel FPGA AFU JSON Manager'
|
|
Packit |
534379 |
|
|
Packit |
534379 |
USAGE = """
|
|
Packit |
534379 |
{0}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
{1} <cmd> [options]
|
|
Packit |
534379 |
|
|
Packit |
534379 |
The following values for <cmd> are currently supported:
|
|
Packit |
534379 |
\t help - displays this message
|
|
Packit |
534379 |
\t create-json - creates a minimal JSON file describing an AFU
|
|
Packit |
534379 |
\t json-info - extract information from JSON file for use in C or Verilog
|
|
Packit |
534379 |
|
|
Packit |
534379 |
{1} <cmd> --h will give command specific help
|
|
Packit |
534379 |
""".format(DESCRIPTION, AFU_JSON_MGR_EXEC)
|
|
Packit |
534379 |
|
|
Packit |
534379 |
|
|
Packit |
534379 |
# Create an AFU JSON file, filling in a few key fields.
|
|
Packit |
534379 |
def create_json(subargs):
|
|
Packit |
534379 |
# Read the template JSON file
|
|
Packit |
534379 |
filepath = os.path.dirname(os.path.realpath(__file__))
|
|
Packit |
534379 |
template_path = "schema/afu_template.json"
|
|
Packit |
534379 |
afu = AFU()
|
|
Packit |
534379 |
if (zipfile.is_zipfile(filepath)):
|
|
Packit |
534379 |
archive = zipfile.ZipFile(filepath, 'r')
|
|
Packit |
534379 |
afu.load_afu_desc_file_hdl(archive.open(template_path, "r"))
|
|
Packit |
534379 |
else:
|
|
Packit |
534379 |
afu.load_afu_desc_file_hdl(open(os.path.join(filepath,
|
|
Packit |
534379 |
template_path), "r"))
|
|
Packit |
534379 |
|
|
Packit |
534379 |
accel = afu.afu_json['afu-image']['accelerator-clusters'][0]
|
|
Packit |
534379 |
accel['name'] = subargs.name
|
|
Packit |
534379 |
|
|
Packit |
534379 |
# Top-level interface specified?
|
|
Packit |
534379 |
if (subargs.top_ifc):
|
|
Packit |
534379 |
afu.update_afu_json(['afu-image/afu-top-interface/class:' +
|
|
Packit |
534379 |
subargs.top_ifc])
|
|
Packit |
534379 |
|
|
Packit |
534379 |
# Either set the specified UUID or pick one
|
|
Packit |
534379 |
if (subargs.uuid):
|
|
Packit |
534379 |
accel['accelerator-type-uuid'] = subargs.uuid
|
|
Packit |
534379 |
else:
|
|
Packit |
534379 |
accel['accelerator-type-uuid'] = str(uuid.uuid1())
|
|
Packit |
534379 |
|
|
Packit |
534379 |
# The output file name is either the AFU name or a specified file path
|
|
Packit |
534379 |
json_path = subargs.name + '.json'
|
|
Packit |
534379 |
if (subargs.afu_json):
|
|
Packit |
534379 |
json_path = subargs.afu_json
|
|
Packit |
534379 |
print("Writing {0}".format(json_path))
|
|
Packit |
534379 |
with open(json_path, 'w') as a:
|
|
Packit |
534379 |
a.write(afu.dumps() + '\n')
|
|
Packit |
534379 |
|
|
Packit |
534379 |
|
|
Packit |
534379 |
def emit_header_comment(f, src):
|
|
Packit |
534379 |
f.write('''//
|
|
Packit |
534379 |
// Generated by afu_json_mgr from {0}
|
|
Packit |
534379 |
//
|
|
Packit |
534379 |
|
|
Packit |
534379 |
'''.format(src))
|
|
Packit |
534379 |
|
|
Packit |
534379 |
|
|
Packit |
534379 |
# Flatten JSON into a simple, single level dictionary to emit as header files
|
|
Packit |
534379 |
def flatten_json(subargs):
|
|
Packit |
534379 |
afu = AFU(subargs.afu_json)
|
|
Packit |
534379 |
|
|
Packit |
534379 |
entries = dict()
|
|
Packit |
534379 |
|
|
Packit |
534379 |
emit_types = (int, bool, str, str, float)
|
|
Packit |
534379 |
# Don't emit some keys. For example, user clock frequency may not be
|
|
Packit |
534379 |
# known at compile time, so avoid emitting potentially false information.
|
|
Packit |
534379 |
skip_keys = ['clock-frequency-low', 'clock-frequency-high']
|
|
Packit |
534379 |
|
|
Packit |
534379 |
# Flattan all entries in afu-image that are of type emit_types
|
|
Packit |
534379 |
image = afu.afu_json['afu-image']
|
|
Packit |
534379 |
for k in sorted(image.keys()):
|
|
Packit |
534379 |
if (isinstance(image[k], emit_types) and k not in skip_keys):
|
|
Packit |
534379 |
tag = str(k).replace('-', '_')
|
|
Packit |
534379 |
v = image[k]
|
|
Packit |
534379 |
# Does it look like a number?
|
|
Packit |
534379 |
if (not re.match('^[0-9.]+$', str(v))):
|
|
Packit |
534379 |
v = '"' + str(v) + '"'
|
|
Packit |
534379 |
entries['afu_image_' + tag] = v
|
|
Packit |
534379 |
|
|
Packit |
534379 |
# Some special names, taken from other levels
|
|
Packit |
534379 |
accel = image['accelerator-clusters'][0]
|
|
Packit |
534379 |
entries['afu_accel_name'] = '"' + accel['name'] + '"'
|
|
Packit |
534379 |
entries['afu_accel_uuid'] = accel['accelerator-type-uuid']
|
|
Packit |
534379 |
try:
|
|
Packit |
534379 |
# May not be present. (Will become required eventually.)
|
|
Packit |
534379 |
entries['afu_top_ifc'] = '"' + \
|
|
Packit |
534379 |
afu.afu_json['afu-image']['afu-top-interface']['class'] + '"'
|
|
Packit |
534379 |
except Exception:
|
|
Packit |
534379 |
None
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return entries
|
|
Packit |
534379 |
|
|
Packit |
534379 |
|
|
Packit |
534379 |
# Emit C or Verilog header files based on an AFU JSON file
|
|
Packit |
534379 |
def json_info(entries, subargs):
|
|
Packit |
534379 |
afu = AFU(subargs.afu_json)
|
|
Packit |
534379 |
|
|
Packit |
534379 |
# C header
|
|
Packit |
534379 |
if (subargs.c_hdr):
|
|
Packit |
534379 |
print("Writing {0}".format(subargs.c_hdr))
|
|
Packit |
534379 |
with open(subargs.c_hdr, 'w') as p:
|
|
Packit |
534379 |
emit_header_comment(p, subargs.afu_json)
|
|
Packit |
534379 |
p.write('#ifndef __AFU_JSON_INFO__\n')
|
|
Packit |
534379 |
p.write('#define __AFU_JSON_INFO__\n\n')
|
|
Packit |
534379 |
for k in sorted(entries.keys()):
|
|
Packit |
534379 |
v = entries[k]
|
|
Packit |
534379 |
if (k == 'afu_accel_uuid'):
|
|
Packit |
534379 |
v = '"' + v.upper() + '"'
|
|
Packit |
534379 |
p.write('#define {0} {1}\n'.format(k.upper(), v))
|
|
Packit |
534379 |
p.write('\n#endif // __AFU_JSON_INFO__\n')
|
|
Packit |
534379 |
|
|
Packit |
534379 |
# Verilog header
|
|
Packit |
534379 |
if (subargs.verilog_hdr):
|
|
Packit |
534379 |
print("Writing {0}".format(subargs.verilog_hdr))
|
|
Packit |
534379 |
with open(subargs.verilog_hdr, 'w') as p:
|
|
Packit |
534379 |
emit_header_comment(p, subargs.afu_json)
|
|
Packit |
534379 |
p.write('`ifndef __AFU_JSON_INFO__\n')
|
|
Packit |
534379 |
p.write('`define __AFU_JSON_INFO__\n\n')
|
|
Packit |
534379 |
for k in sorted(entries.keys()):
|
|
Packit |
534379 |
v = entries[k]
|
|
Packit |
534379 |
if (k == 'afu_accel_uuid'):
|
|
Packit |
534379 |
v = "128'h" + entries[k].replace('-', '_')
|
|
Packit |
534379 |
p.write('`define {0} {1}\n'.format(k.upper(), v))
|
|
Packit |
534379 |
p.write('\n`endif // __AFU_JSON_INFO__\n')
|
|
Packit |
534379 |
|
|
Packit |
534379 |
|
|
Packit |
534379 |
def run_afu_json_mgr():
|
|
Packit |
534379 |
parser = argparse.ArgumentParser(usage=USAGE, add_help=False)
|
|
Packit |
534379 |
parser.add_argument("cmd", nargs="?")
|
|
Packit |
534379 |
parser.add_argument("remain_args", nargs=argparse.REMAINDER)
|
|
Packit |
534379 |
args = parser.parse_args(sys.argv[1:])
|
|
Packit |
534379 |
cmd_description = "{0} {1}".format(AFU_JSON_MGR_EXEC, args.cmd)
|
|
Packit |
534379 |
subparser = argparse.ArgumentParser(description=cmd_description)
|
|
Packit |
534379 |
subparser._optionals.title = 'Options'
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if args.cmd == "help" or not args.cmd:
|
|
Packit |
534379 |
print(USAGE)
|
|
Packit |
534379 |
|
|
Packit |
534379 |
elif args.cmd == "create-json":
|
|
Packit |
534379 |
subparser.usage = "\n" + cmd_description + \
|
|
Packit |
534379 |
" --name=<AFU_NAME> --top-ifc=<TOP_INTERFACE_CLASS>"\
|
|
Packit |
534379 |
" --uuid=<AFU_UUID> --afu-json=<OUTPUT_JSON>\n"
|
|
Packit |
534379 |
subparser.add_argument('--name', required=True,
|
|
Packit |
534379 |
help='AFU name (REQUIRED)')
|
|
Packit |
534379 |
subparser.add_argument('--top-ifc', required=False,
|
|
Packit |
534379 |
default='ccip_std_afu',
|
|
Packit |
534379 |
help='Top-level interface class name. '
|
|
Packit |
534379 |
'Default is ccip_std_afu. See the output of '
|
|
Packit |
534379 |
'"afu_platform_config --help" for a list of '
|
|
Packit |
534379 |
'top-level interface classes.')
|
|
Packit |
534379 |
subparser.add_argument('--uuid', required=False,
|
|
Packit |
534379 |
help='Accelerator UUID (default: chosen at '
|
|
Packit |
534379 |
'random)')
|
|
Packit |
534379 |
subparser.add_argument('--afu-json', required=False,
|
|
Packit |
534379 |
help='Output path for JSON file '
|
|
Packit |
534379 |
'(default <afu_name>.json)')
|
|
Packit |
534379 |
subargs = subparser.parse_args(args.remain_args)
|
|
Packit |
534379 |
create_json(subargs)
|
|
Packit |
534379 |
|
|
Packit |
534379 |
elif args.cmd == "json-info":
|
|
Packit |
534379 |
subparser.usage = "\n" + cmd_description + \
|
|
Packit |
534379 |
" --afu-json=<INPUT_JSON>"\
|
|
Packit |
534379 |
" --c-hdr=<OUTPUT_C_HDR_PATH>"\
|
|
Packit |
534379 |
" --verilog-hdr=<OUTPUT_VERILOG_HDR_PATH>\n"
|
|
Packit |
534379 |
subparser.add_argument('--afu-json', required=True,
|
|
Packit |
534379 |
help='Input path of JSON file. ')
|
|
Packit |
534379 |
subparser.add_argument('--c-hdr', required=False,
|
|
Packit |
534379 |
help='Path of generated C header file. ')
|
|
Packit |
534379 |
subparser.add_argument('--verilog-hdr', required=False,
|
|
Packit |
534379 |
help='Path of generated Verilog header file. ')
|
|
Packit |
534379 |
subargs = subparser.parse_args(args.remain_args)
|
|
Packit |
534379 |
entries = flatten_json(subargs)
|
|
Packit |
534379 |
json_info(entries, subargs)
|
|
Packit |
534379 |
|
|
Packit |
534379 |
else:
|
|
Packit |
534379 |
raise Exception("{0} is not a command for {1}!".format(
|
|
Packit |
534379 |
args.cmd, DESCRIPTION))
|
|
Packit |
534379 |
|
|
Packit |
534379 |
|
|
Packit |
534379 |
def main():
|
|
Packit |
534379 |
try:
|
|
Packit |
534379 |
sys.exit(run_afu_json_mgr())
|
|
Packit |
534379 |
except Exception as e:
|
|
Packit |
534379 |
print("ERROR: {0}".format(e.__str__()))
|
|
Packit |
534379 |
sys.exit(1)
|
|
Packit |
534379 |
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if __name__ == '__main__':
|
|
Packit |
534379 |
main()
|