blob: ba2936b88b2f087939d3a7a6540c12f3da1c8a1b [file] [log] [blame]
#!/usr/bin/env python3
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
r"""FuseSoC wrapper for Top Module Generator
This wrapper is called by FuseSoC. It extracts the arguments for topgen from the auto-generated
GAPI file and creates a core file for the generated sources.
"""
import sys
import yaml
import subprocess
import os
try:
from yaml import CSafeLoader as YamlLoader, CSafeDumper as YamlDumper
except ImportError:
from yaml import SafeLoader as YamlLoader, SafeDumper as YamlDumper
def _check_gapi(gapi):
if 'cores' not in gapi:
print("Key 'cores' not found in GAPI structure. "
"Install a compatible version with "
"'pip3 install --user -r python-requirements.txt'.")
return False
return True
def write_core(core_filepath, generated_core):
with open(core_filepath, 'w') as f:
# FuseSoC requires this line to appear first in the YAML file.
# Inserting this line through the YAML serializer requires ordered dicts
# to be used everywhere, which is annoying syntax-wise on Python <3.7,
# where native dicts are not sorted.
f.write('CAPI=2:\n')
yaml.dump(generated_core,
f,
encoding="utf-8",
Dumper=YamlDumper)
print("Core file written to %s" % (core_filepath, ))
def main():
# Extract arguments from GAPI file.
gapi_filepath = sys.argv[1]
with open(gapi_filepath) as f:
gapi = yaml.load(f, Loader=YamlLoader)
if not _check_gapi(gapi):
sys.exit(1)
files_root = ""
if 'files_root' in gapi:
files_root = gapi['files_root']
topname = ""
if 'parameters' in gapi and 'topname' in gapi['parameters']:
topname = gapi['parameters']['topname']
reg_only = ""
if 'parameters' in gapi and 'reg-only' in gapi['parameters']:
reg_only = gapi['parameters']['reg-only']
# Call topgen.
files_data = files_root + "/hw/" + topname + "/data/"
files_out = os.getcwd()
cmd = [files_root + "/util/topgen.py", # "--verbose",
"-t", files_data + topname + ".hjson",
"-c", files_data,
"-o", files_out]
try:
print("Running topgen.")
subprocess.run(cmd,
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
universal_newlines=True)
except subprocess.CalledProcessError as e:
print("topgen failed: " + str(e))
sys.exit(1)
# Create core files.
print("Creating core files.")
# For some cores such IP package files, we need a separate dependency for the register file.
# Combining this with the generated topgen core file below leads to cyclic dependencies. For
# example, flash_ctrl depends on topgen but also on pwrmgr_pkg which depends on
# pwrmgr_reg_pkg generated by topgen.
if reg_only:
for ip in ['alert_handler', 'clkmgr', 'flash_ctrl', 'pinmux', 'pwrmgr',
'rstmgr', 'rv_plic']:
core_filepath = os.path.abspath('generated-%s.core' % ip)
name = 'lowrisc:ip:%s_reggen' % ip,
files = ['ip/%s/rtl/autogen/%s_reg_pkg.sv' % (ip, ip),
'ip/%s/rtl/autogen/%s_reg_top.sv' % (ip, ip)]
generated_core = {
'name': '%s' % name,
'filesets': {
'files_rtl': {
'depend': [
'lowrisc:ip:tlul',
],
'files': files,
'file_type': 'systemVerilogSource'
},
},
'targets': {
'default': {
'filesets': [
'files_rtl',
],
},
},
}
write_core(core_filepath, generated_core)
else:
core_filepath = os.path.abspath('generated-topgen.core')
generated_core = {
'name': "lowrisc:systems:generated-topgen",
'filesets': {
'files_rtl': {
'depend': [
# flash_ctrl
'lowrisc:constants:top_pkg',
'lowrisc:prim:util',
'lowrisc:ip:lc_ctrl_pkg',
'lowrisc:ip:pwrmgr_pkg',
# rstmgr
'lowrisc:prim:clock_mux2',
# clkmgr
'lowrisc:prim:all',
'lowrisc:prim:clock_gating',
'lowrisc:prim:clock_buf',
'lowrisc:prim:clock_div',
# Top
# ast and sensor_ctrl not auto-generated, re-used from top_earlgrey
'lowrisc:systems:sensor_ctrl',
'lowrisc:systems:ast_pkg',
],
'files': [
# IPs
'ip/clkmgr/rtl/autogen/clkmgr_pkg.sv',
'ip/clkmgr/rtl/autogen/clkmgr.sv',
'ip/flash_ctrl/rtl/autogen/flash_ctrl_pkg.sv',
'ip/flash_ctrl/rtl/autogen/flash_ctrl.sv',
'ip/rstmgr/rtl/autogen/rstmgr_pkg.sv',
'ip/rstmgr/rtl/autogen/rstmgr.sv',
'ip/rv_plic/rtl/autogen/rv_plic.sv',
# Top
'rtl/autogen/%s_rnd_cnst_pkg.sv' % topname,
'rtl/autogen/%s_pkg.sv' % topname,
'rtl/autogen/%s.sv' % topname,
],
'file_type': 'systemVerilogSource'
},
},
'targets': {
'default': {
'filesets': [
'files_rtl',
],
},
},
}
write_core(core_filepath, generated_core)
return 0
if __name__ == "__main__":
main()