Simplify Makefile flow by removing sim_makefrag_gen.py

This used to work by dumping a Makefile fragment, reading it back in,
and then passing the relevant options through to the RTL compile and
run scripts.

This commit switches things around so that the RTL compile and run
scripts just look up the options when they need them.
This commit is contained in:
Rupert Swarbrick 2022-04-20 11:59:09 +01:00 committed by hcallahan-lowrisc
parent 14c400c1e7
commit c2bead628a
5 changed files with 94 additions and 186 deletions

View file

@ -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)

View file

@ -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')

View file

@ -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')

View file

@ -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,

View file

@ -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()