|  | #!/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() |