| #!/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"""Stopgap script to generate some cores for the englishbreakfast toplevel. | |
| All output files are written to $REPO_TOP/build/$TOPNAME-autogen/. | |
| """ | |
| import argparse | |
| import sys | |
| import yaml | |
| import shutil | |
| import subprocess | |
| import os | |
| try: | |
| from yaml import CSafeDumper as YamlDumper | |
| except ImportError: | |
| from yaml import SafeDumper as YamlDumper | |
| 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(): | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument('--files-root', required=True) | |
| parser.add_argument('--topname', required=True) | |
| args = parser.parse_args() | |
| topname = args.topname | |
| files_root = args.files_root | |
| # Call topgen. | |
| files_data = files_root + "/hw/" + topname + "/data/" | |
| files_out = os.path.abspath(files_root + "/build/" + topname + "-autogen/") | |
| shutil.rmtree(files_out, ignore_errors=True) | |
| os.makedirs(files_out, exist_ok=False) | |
| cmd = [files_root + "/util/topgen.py", # "--verbose", | |
| "-t", files_data + topname + ".hjson", | |
| "-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)) | |
| print(e.stdout) | |
| 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. | |
| reg_top_suffix = { | |
| 'clkmgr': '', | |
| 'flash_ctrl': '_core', | |
| 'pinmux': '', | |
| 'pwrmgr': '', | |
| 'rstmgr': '', | |
| } | |
| # reg-only | |
| for ip in ['clkmgr', 'flash_ctrl', 'pinmux', 'pwrmgr', 'rstmgr']: | |
| core_filepath = os.path.abspath(os.path.join(files_out, '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 + reg_top_suffix[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) | |
| # topgen | |
| nameparts = topname.split('_') | |
| if nameparts[0] == 'top' and len(nameparts) > 1: | |
| chipname = 'chip_' + '_'.join(nameparts[1:]) | |
| else: | |
| chipname = topname | |
| core_filepath = os.path.abspath(os.path.join(files_out, 'generated-topgen.core')) | |
| generated_core = { | |
| 'name': "lowrisc:systems:generated-topgen", | |
| 'filesets': { | |
| 'files_rtl': { | |
| 'depend': [ | |
| # Ibex and OTBN constants | |
| 'lowrisc:ibex:ibex_pkg', | |
| 'lowrisc:ip:otbn_pkg', | |
| # 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', | |
| 'lowrisc:ip:clkmgr_components', | |
| # Top | |
| # ast and sensor_ctrl not auto-generated, re-used from top_earlgrey | |
| 'lowrisc:systems:sensor_ctrl', | |
| 'lowrisc:systems:ast_pkg', | |
| # TODO: absorb this into AST longerm | |
| 'lowrisc:systems:clkgen_xil7series', | |
| ], | |
| 'files': [ | |
| # IPs | |
| 'ip/clkmgr/rtl/autogen/clkmgr.sv', | |
| 'ip/flash_ctrl/rtl/autogen/flash_ctrl_pkg.sv', | |
| 'ip/flash_ctrl/rtl/autogen/flash_ctrl.sv', | |
| 'ip/flash_ctrl/rtl/autogen/flash_ctrl_region_cfg.sv', | |
| 'ip/rstmgr/rtl/autogen/rstmgr_pkg.sv', | |
| 'ip/rstmgr/rtl/autogen/rstmgr.sv', | |
| # Top | |
| 'rtl/autogen/%s_rnd_cnst_pkg.sv' % topname, | |
| 'rtl/autogen/%s_pkg.sv' % topname, | |
| 'rtl/autogen/%s.sv' % topname, | |
| # TODO: this is not ideal. we should extract | |
| # this info from the target configuration and | |
| # possibly generate separate core files for this. | |
| 'rtl/autogen/%s_cw305.sv' % chipname, | |
| ], | |
| 'file_type': 'systemVerilogSource' | |
| }, | |
| }, | |
| 'targets': { | |
| 'default': { | |
| 'filesets': [ | |
| 'files_rtl', | |
| ], | |
| }, | |
| }, | |
| } | |
| write_core(core_filepath, generated_core) | |
| return 0 | |
| if __name__ == "__main__": | |
| main() |