diff --git a/dv/uvm/core_ibex/Makefile b/dv/uvm/core_ibex/Makefile index e5d9a371..0c08fe69 100644 --- a/dv/uvm/core_ibex/Makefile +++ b/dv/uvm/core_ibex/Makefile @@ -40,10 +40,6 @@ OUT-SEED := $(OUT)/seed-$(SEED) export dv_root := $(realpath ../../../vendor/lowrisc_ip/dv) export DUT_TOP := dut -# Compile time options for ibex RTL simulation -COMPILE_OPTS += -# Run time options for ibex RTL simulation -SIM_OPTS := # Enable waveform dumping WAVES := 1 # Enable coverage dump @@ -140,31 +136,6 @@ gen-dirs := \ $(gen-dirs): %: mkdir -p $@ -# sim-cfg-mk is a makefile fragment that sets-up anything simulator specific, it -# is generated by sim_makefrag_gen.py -sim-cfg-mk = $(OUT-DIR).sim-cfg.mk - -# The include of $(sim-cfg-mk) below tells Make that it should ensure the file -# exists. This rule tells Make how to build it. We also want to ensure it's -# built on every run. Declaring the rule to be .PHONY doesn't work because it -# causes Make to no longer think the rule actually generates the file. If you -# do that, the file gets re-built, but Make doesn't read the new contents. So -# instead we depend on FORCE (a phony target). This ensures a rebuild, but also -# causes an infinite recursion: when we re-read this file to include the new -# contents of $(sim-cfg-mk), we run the rule again. To avoid that, we check for -# MAKE_RESTARTS, which is defined on re-runs. Phew! -ifndef MAKE_RESTARTS -$(sim-cfg-mk): FORCE | $(OUT-DIR) - @./sim_makefrag_gen.py $(SIMULATOR) $(IBEX_CONFIG) $(PRJ_DIR) $@ -endif - -include $(sim-cfg-mk) - -.PHONY: test-cfg -test-cfg: - @echo "COMPILE_OPTS" $(COMPILE_OPTS) - @echo "SIM_OPTS" $(SIM_OPTS) - ############################################################################### # Utility functions. # @@ -389,7 +360,7 @@ all-verilog = \ $(shell find ../../../rtl -name '*.v' -o -name '*.sv' -o -name '*.svh') \ $(shell find ../.. -name '*.v' -o -name '*.sv' -o -name '*.svh') -tb-compile-var-deps := COMMON_OPTS SIMULATOR COV WAVES COMPILE_OPTS COSIM +tb-compile-var-deps := COMMON_OPTS SIMULATOR COV WAVES COSIM -include $(OUT-DIR)rtl_sim/.rtl.tb_compile.vars.mk tb-compile-vars-prereq = $(call vars-prereq,comp,compiling TB,$(tb-compile-var-deps)) @@ -405,10 +376,10 @@ $(OUT-DIR)rtl_sim/.rtl.tb_compile.stamp: \ | $(OUT-DIR)rtl_sim $(verb)scripts/compile-tb.py \ $(verb-arg) \ + --ibex-config $(IBEX_CONFIG) \ --output=$(OUT-DIR) \ --simulator=$(SIMULATOR) \ - $(cov-arg) $(wave-arg) $(cosim-arg) \ - --compile-opts="$(COMPILE_OPTS)" + $(cov-arg) $(wave-arg) $(cosim-arg) $(call dump-vars,$(OUT-DIR)rtl_sim/.rtl.tb_compile.vars.mk,comp,$(tb-compile-var-deps)) @touch $@ @@ -429,14 +400,14 @@ $(rtl-sim-logs): \ @echo Running RTL simulation at $@ $(verb)mkdir -p $(@D) $(verb)scripts/run-rtl.py \ + --ibex-config $(IBEX_CONFIG) \ --simulator $(SIMULATOR) \ $(cov-arg) $(wave-arg) \ --signature-addr $(SIGNATURE_ADDR) \ --test-dot-seed $* \ --binary $(OUT-SEED)/instr_gen/$*.bin \ --rtl-sim-dir $(OUT-DIR)rtl_sim \ - --out-dir $(OUT-SEED)/rtl_sim/$* \ - --sim-opts "$(SIM_OPTS)" + --out-dir $(OUT-SEED)/rtl_sim/$* .PHONY: rtl_sim_run rtl_sim_run: $(rtl-sim-logs) diff --git a/dv/uvm/core_ibex/scripts/compile-tb.py b/dv/uvm/core_ibex/scripts/compile-tb.py index 5c3a36ba..19706a7b 100755 --- a/dv/uvm/core_ibex/scripts/compile-tb.py +++ b/dv/uvm/core_ibex/scripts/compile-tb.py @@ -8,6 +8,7 @@ import argparse import os import sys +from ibex_cmd import get_compile_opts from scripts_lib import run_one, subst_vars from sim_cmd import get_simulator_cmd @@ -16,12 +17,12 @@ def main() -> int: parser = argparse.ArgumentParser() parser.add_argument('--verbose', action='store_true') + parser.add_argument('--ibex-config', required=True) parser.add_argument('--output', required=True) parser.add_argument('--simulator', required=True) parser.add_argument('--en_cov', action='store_true') parser.add_argument('--en_wave', action='store_true') parser.add_argument('--en_cosim', action='store_true') - parser.add_argument('--compile-opts', default='') args = parser.parse_args() @@ -39,7 +40,8 @@ def main() -> int: cmd = subst_vars(pre_cmd, { 'out': output_dir, - 'cmp_opts': args.compile_opts + 'cmp_opts': get_compile_opts(args.ibex_config, + args.simulator) }) retcode = run_one(args.verbose, ['sh', '-c', cmd], redirect_stdstreams='/dev/null') diff --git a/dv/uvm/core_ibex/scripts/ibex_cmd.py b/dv/uvm/core_ibex/scripts/ibex_cmd.py new file mode 100644 index 00000000..06d572ed --- /dev/null +++ b/dv/uvm/core_ibex/scripts/ibex_cmd.py @@ -0,0 +1,81 @@ +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +import os +import subprocess + +_THIS_DIR = os.path.normpath(os.path.join(os.path.dirname(__file__))) +_IBEX_ROOT = os.path.normpath(os.path.join(_THIS_DIR, 4 * '../')) + +# For each simulator, a tuple +# +# (needs_compile_opts, needs_sim_opts) +# +SIM_CFGS = { + 'vcs': (True, False), + 'riviera': (True, True), + 'questa': (True, True), + 'xlm': (True, False), + 'dsim': (True, False) +} + + +class GenError(Exception): + pass + + +def run_ibex_config(config_name: str, output_type: str) -> str: + script_path = os.path.join(_IBEX_ROOT, 'util', 'ibex_config.py') + yaml_path = os.path.join(_IBEX_ROOT, 'ibex_configs.yaml') + + ibex_config_cmd = [ + script_path, + '--config_filename', yaml_path, + config_name, + output_type, + '--ins_hier_path', 'core_ibex_tb_top', + '--string_define_prefix', 'IBEX_CFG_' + ] + proc = subprocess.run(ibex_config_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True) + + if proc.returncode != 0: + raise GenError("Error running {0} got:\n{1}\n{2}" + .format(script_path, proc.stdout, proc.stderr)) + + return proc.stdout.strip() + + +def get_x_opts(config_name: str, simulator: str, stage: str) -> str: + try: + needs_compile_opts, needs_sim_opts = SIM_CFGS[simulator] + except KeyError: + raise ValueError(f'Unsupported simulator: {simulator}.') + + specify_which_opts = needs_compile_opts and needs_sim_opts + + if stage == 'compile': + needs_opts = needs_compile_opts + elif stage == 'sim': + needs_opts = needs_sim_opts + else: + assert 0 + + if not needs_opts: + return '' + + output_type = (f'{simulator}_{stage}_opts' + if specify_which_opts else f'{simulator}_opts') + + return run_ibex_config(config_name, output_type) + + +def get_compile_opts(config_name: str, simulator: str) -> str: + return get_x_opts(config_name, simulator, 'compile') + + +def get_sim_opts(config_name: str, simulator: str) -> str: + return get_x_opts(config_name, simulator, 'sim') diff --git a/dv/uvm/core_ibex/scripts/run-rtl.py b/dv/uvm/core_ibex/scripts/run-rtl.py index 4c064650..2c58b491 100755 --- a/dv/uvm/core_ibex/scripts/run-rtl.py +++ b/dv/uvm/core_ibex/scripts/run-rtl.py @@ -5,6 +5,7 @@ import os import subprocess import sys +from ibex_cmd import get_sim_opts from sim_cmd import get_simulator_cmd from scripts_lib import read_test_dot_seed, subst_vars from test_entry import get_test_entry @@ -53,6 +54,7 @@ def get_test_sim_cmd(base_cmd, test, binary, seed, sim_dir): def main() -> int: parser = argparse.ArgumentParser() + parser.add_argument('--ibex-config', required=True) parser.add_argument('--simulator', required=True) parser.add_argument("--en_cov", action='store_true') parser.add_argument("--en_wave", action='store_true') @@ -63,7 +65,6 @@ def main() -> int: parser.add_argument('--binary', required=True) parser.add_argument('--rtl-sim-dir', required=True) parser.add_argument('--out-dir', required=True) - parser.add_argument('--sim-opts') args = parser.parse_args() @@ -77,9 +78,8 @@ def main() -> int: } _, base_cmd = get_simulator_cmd(args.simulator, enables) - sim_opts = f'+signature_addr={args.signature_addr}' - if args.sim_opts: - sim_opts += ' ' + args.sim_opts + sim_opts = (f'+signature_addr={args.signature_addr} ' + + get_sim_opts(args.ibex_config, args.simulator)) # Specialize base_cmd with the right directories and simulator options sim_cmd = subst_vars(base_cmd, diff --git a/dv/uvm/core_ibex/sim_makefrag_gen.py b/dv/uvm/core_ibex/sim_makefrag_gen.py deleted file mode 100755 index 86e31185..00000000 --- a/dv/uvm/core_ibex/sim_makefrag_gen.py +++ /dev/null @@ -1,146 +0,0 @@ -#!/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 - -import argparse -import os.path -import subprocess -import sys - -ibex_config_path = '' -ibex_config_name = '' -ibex_config_filename = '' - - -class GenError(Exception): - pass - - -def run_ibex_config(output_type, extra_args=None): - ibex_config_cmd = [ - ibex_config_path, - ibex_config_name, - '--config_filename', ibex_config_filename, - output_type - ] - - if extra_args: - ibex_config_cmd += extra_args - - result = subprocess.run(ibex_config_cmd, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - - if result.returncode != 0: - raise GenError("Error running {0} got:\n{1}\n{2}".format( - ibex_config_path, str(result.stdout, 'utf-8'), - str(result.stderr, 'utf-8'))) - - return str(result.stdout, 'utf-8') - - -def gen_vcs_makefrag(): - vcs_compile_opts = run_ibex_config('vcs_opts', [ - '--ins_hier_path', 'core_ibex_tb_top', - '--string_define_prefix', 'IBEX_CFG_' - ]) - - return 'COMPILE_OPTS += {0}'.format(vcs_compile_opts) - - -def gen_riviera_makefrag(): - riviera_compile_opts = run_ibex_config('riviera_compile_opts', [ - '--ins_hier_path', 'core_ibex_tb_top', - '--string_define_prefix', 'IBEX_CFG_' - ]) - - riviera_sim_opts = run_ibex_config('riviera_sim_opts', [ - '--ins_hier_path', 'core_ibex_tb_top', - '--string_define_prefix', 'IBEX_CFG_' - ]) - - return ('COMPILE_OPTS += {0}' - 'SIM_OPTS += {1}').format(riviera_compile_opts, riviera_sim_opts) - - -def gen_questa_makefrag(): - questa_compile_opts = run_ibex_config('questa_compile_opts', [ - '--ins_hier_path', 'core_ibex_tb_top', - '--string_define_prefix', 'IBEX_CFG_' - ]) - - questa_sim_opts = run_ibex_config('questa_sim_opts', [ - '--ins_hier_path', 'core_ibex_tb_top', - '--string_define_prefix', 'IBEX_CFG_' - ]) - - return ('COMPILE_OPTS += {0}' - 'SIM_OPTS += {1}').format(questa_compile_opts, questa_sim_opts) - - -def gen_xlm_makefrag(): - xlm_compile_opts = run_ibex_config('xlm_opts', [ - '--ins_hier_path', 'core_ibex_tb_top', - '--string_define_prefix', 'IBEX_CFG_' - ]) - - return 'COMPILE_OPTS += {0}'.format(xlm_compile_opts) - -def gen_dsim_makefrag(): - dsim_compile_opts = run_ibex_config('dsim_compile_opts', [ - '--ins_hier_path', 'core_ibex_tb_top', - '--string_define_prefix', 'IBEX_CFG_' - ]) - - return 'COMPILE_OPTS += {0}'.format(gen_dsim_makefrag) - - -def main(): - argparser = argparse.ArgumentParser(description=( - 'Generates a makefile fragment for use with the Ibex DV makefile that ' - 'sets up sim specific variables')) - - sim_fns = { - 'vcs': gen_vcs_makefrag, - 'riviera': gen_riviera_makefrag, - 'xlm': gen_xlm_makefrag, - 'questa': gen_questa_makefrag, - 'dsim': gen_dsim_makefrag - } - - argparser.add_argument('sim', - help='Name of the simulator', - choices=sim_fns.keys()) - - argparser.add_argument( - 'config', help='Ibex config to generate makefile fragment for') - - argparser.add_argument('ibex_top', - help='Path to the top of an ibex repository') - - argparser.add_argument('makefrag_name', - help='Filename of the makefile fragment to write') - - args = argparser.parse_args() - - global ibex_config_path - global ibex_config_name - global ibex_config_filename - - ibex_config_path = os.path.join(args.ibex_top, 'util/ibex_config.py') - ibex_config_name = args.config - ibex_config_filename = os.path.join(args.ibex_top, 'ibex_configs.yaml') - - try: - with open(args.makefrag_name, 'w') as makefrag: - makefrag.write(sim_fns[args.sim]()) - except GenError as e: - print('Failure generating simulation options for', args.sim) - print(e) - sys.exit(1) - - -if __name__ == "__main__": - main()