mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 04:47:25 -04:00
Add a wrapper script for building the core_ibex UVM testbench
This kind of existed already, but this tweaks things so that it's the same shape as the other scripts we're adding and (hopefully) the Python gets a bit cleaner.
This commit is contained in:
parent
014b5443b8
commit
8fd1a0df50
4 changed files with 92 additions and 59 deletions
|
@ -396,14 +396,13 @@ cosim-arg := $(if $(call equal,$(COSIM),1),--en_cosim,)
|
|||
|
||||
$(OUT-DIR)rtl_sim/.rtl.tb_compile.stamp: \
|
||||
$(tb-compile-vars-prereq) $(all-verilog) $(risc-dv-files) \
|
||||
sim.py yaml/rtl_simulation.yaml \
|
||||
scripts/compile-tb.py yaml/rtl_simulation.yaml \
|
||||
| $(OUT-DIR)rtl_sim
|
||||
$(verb)./sim.py \
|
||||
--o=$(OUT-DIR) \
|
||||
--steps=compile \
|
||||
${COMMON_OPTS} \
|
||||
--simulator="${SIMULATOR}" \
|
||||
$(cov-arg) $(wave-arg) $(cosim-arg)
|
||||
$(verb)scripts/compile-tb.py \
|
||||
$(verb-arg) \
|
||||
--output=$(OUT-DIR) \
|
||||
--simulator=$(SIMULATOR) \
|
||||
$(cov-arg) $(wave-arg) $(cosim-arg)
|
||||
$(call dump-vars,$(OUT-DIR)rtl_sim/.rtl.tb_compile.vars.mk,comp,$(tb-compile-var-deps))
|
||||
@touch $@
|
||||
|
||||
|
|
58
dv/uvm/core_ibex/scripts/compile-tb.py
Executable file
58
dv/uvm/core_ibex/scripts/compile-tb.py
Executable file
|
@ -0,0 +1,58 @@
|
|||
#!/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
|
||||
import sys
|
||||
|
||||
|
||||
from scripts_lib import run_one
|
||||
from sim_cmd import get_simulator_cmd
|
||||
|
||||
|
||||
def subst_vars(string, var_dict):
|
||||
'''Apply substitutions in var_dict to string
|
||||
|
||||
If var_dict[K] = V, then <K> will be replaced with V in string.'''
|
||||
for key, value in var_dict.items():
|
||||
string = string.replace('<{}>'.format(key), value)
|
||||
return string
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--verbose', action='store_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')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
output_dir = os.path.join(args.output, 'rtl_sim')
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
enables = {
|
||||
'cov_opts': args.en_cov,
|
||||
'wave_opts': args.en_wave,
|
||||
'cosim_opts': args.en_cosim
|
||||
}
|
||||
compile_cmds, _ = get_simulator_cmd(args.simulator, enables)
|
||||
|
||||
for pre_cmd in compile_cmds:
|
||||
cmd = subst_vars(pre_cmd, {'out': output_dir})
|
||||
retcode = run_one(args.verbose, ['sh', '-c', cmd],
|
||||
discard_stdstreams=True)
|
||||
if retcode:
|
||||
return retcode
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
|
@ -15,16 +15,37 @@ RISCV_DV_ROOT = os.path.normpath(os.path.join(IBEX_ROOT,
|
|||
'vendor/google_riscv-dv'))
|
||||
|
||||
|
||||
def run_one(verbose: bool, cmd: List[str]) -> int:
|
||||
def run_one(verbose: bool,
|
||||
cmd: List[str],
|
||||
discard_stdstreams: bool = False) -> int:
|
||||
'''Run a command, returning its return code
|
||||
|
||||
If verbose is true, print the command to stderr first (a bit like bash -x).
|
||||
|
||||
If discard_stdstreams is true, redirect stdout and stderr in the subprocess
|
||||
to /dev/null. This seems a bit crazy, but makes sense for EDA tools that
|
||||
have a '-l' argument that takes a path to which they write a copy of
|
||||
everything that was going out on stdout/stderr.
|
||||
|
||||
'''
|
||||
stdstream_dest = None
|
||||
shell_redirection = ''
|
||||
if discard_stdstreams:
|
||||
stdstream_dest = subprocess.DEVNULL
|
||||
shell_redirection = ' >/dev/null 2>&1'
|
||||
|
||||
if verbose:
|
||||
# The equivalent of bash -x
|
||||
print('+ ' + ' '.join(shlex.quote(w) for w in cmd),
|
||||
file=sys.stderr)
|
||||
cmd_str = ' '.join(shlex.quote(w) for w in cmd) + shell_redirection
|
||||
print('+ ' + cmd_str, file=sys.stderr)
|
||||
|
||||
# Passing close_fds=False ensures that if cmd is a call to Make then we'll
|
||||
# pass through the jobserver fds. If you don't do this, you get a warning
|
||||
# starting "warning: jobserver unavailable".
|
||||
return subprocess.run(cmd, close_fds=False).returncode
|
||||
return subprocess.run(cmd,
|
||||
stdout=stdstream_dest,
|
||||
stderr=stdstream_dest,
|
||||
close_fds=False).returncode
|
||||
|
||||
|
||||
def start_riscv_dv_run_cmd(verbose: bool):
|
||||
|
|
|
@ -22,8 +22,6 @@ import os
|
|||
import subprocess
|
||||
import sys
|
||||
|
||||
from scripts.sim_cmd import get_simulator_cmd
|
||||
|
||||
_CORE_IBEX = os.path.normpath(os.path.join(os.path.dirname(__file__)))
|
||||
_IBEX_ROOT = os.path.normpath(os.path.join(_CORE_IBEX, '../../..'))
|
||||
_RISCV_DV_ROOT = os.path.join(_IBEX_ROOT, 'vendor/google_riscv-dv')
|
||||
|
@ -45,44 +43,6 @@ finally:
|
|||
sys.path = _OLD_SYS_PATH
|
||||
|
||||
|
||||
def subst_vars(string, var_dict):
|
||||
'''Apply substitutions in var_dict to string
|
||||
|
||||
If var_dict[K] = V, then <K> will be replaced with V in string.'''
|
||||
for key, value in var_dict.items():
|
||||
string = string.replace('<{}>'.format(key), value)
|
||||
return string
|
||||
|
||||
|
||||
def rtl_compile(compile_cmds, output_dir, lsf_cmd):
|
||||
"""Compile the testbench RTL
|
||||
|
||||
compile_cmds is a list of commands (each a string), which will have <out>
|
||||
substituted. Running them in sequence should compile the testbench.
|
||||
|
||||
output_dir is the directory in which to generate the testbench (usually
|
||||
something like 'out/rtl_sim'). This will be substituted for <out> in the
|
||||
commands.
|
||||
|
||||
If lsf_cmd is not None, it should be a string to prefix onto commands to
|
||||
run them through LSF. Here, this is not used for parallelism, but might
|
||||
still be needed for licence servers.
|
||||
|
||||
"""
|
||||
logging.info("Compiling TB")
|
||||
for cmd in compile_cmds:
|
||||
cmd = subst_vars(cmd, {'out': output_dir})
|
||||
|
||||
if lsf_cmd is not None:
|
||||
cmd = lsf_cmd + ' ' + cmd
|
||||
|
||||
logging.debug("Compile command: %s" % cmd)
|
||||
|
||||
# Note that we don't use run_parallel_cmd here: the commands in
|
||||
# compile_cmds need to be run serially.
|
||||
run_cmd(cmd)
|
||||
|
||||
|
||||
#TODO(udinator) - support DSim, and Riviera
|
||||
def gen_cov(base_dir, simulator, lsf_cmd):
|
||||
"""Generate a merged coverage directory.
|
||||
|
@ -203,14 +163,9 @@ def main():
|
|||
|
||||
# Compile TB
|
||||
if steps['compile']:
|
||||
enables = {
|
||||
'cov_opts': args.en_cov,
|
||||
'wave_opts': args.en_wave,
|
||||
'cosim_opts': args.en_cosim
|
||||
}
|
||||
compile_cmds, sim_cmd = get_simulator_cmd(args.simulator, enables)
|
||||
|
||||
rtl_compile(compile_cmds, output_dir, args.lsf_cmd)
|
||||
raise RuntimeError('TB compilation is no longer supported by this '
|
||||
'script: use compile-tb.py.')
|
||||
exit(1)
|
||||
|
||||
# Generate merged coverage directory and load it into appropriate GUI
|
||||
if steps['cov']:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue