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