Split calls to compile-generated-tests.py

This also involves a bit of file renaming, which makes the stuff
downstream a bit easier.
This commit is contained in:
Rupert Swarbrick 2022-04-19 17:41:39 +01:00 committed by Rupert Swarbrick
parent b06f30b8a0
commit b4f5f17e4d
5 changed files with 155 additions and 113 deletions

View file

@ -323,20 +323,28 @@ instr_gen_run: $(metadata)/.instr_gen.run.stamp
#
# We don't explicitly track dependencies on the RISCV toolchain, so this
# doesn't depend on anything more than the instr_gen stage did.
$(metadata)/.instr_gen.compile_tests.stamp: \
#
# Note that the compilation step generates a .o file and then uses
# objcopy to create a .bin. The ISS run uses the .o and the RTL run
# uses the .bin. In the Makefile, we just track the .bin to represent
# both.
test-bins := $(foreach ts,$(tests-and-seeds),$(OUT-SEED)/instr_gen/$(ts).bin)
$(test-bins): \
$(OUT-SEED)/instr_gen/%.bin: \
$(metadata)/.instr_gen.run.stamp \
scripts/compile-generated-tests.py
$(verb)scripts/compile-generated-tests.py \
$(verb-arg) \
--output $(OUT-SEED)/instr_gen \
--isa $(ISA) \
--test $(TEST) \
--start-seed $(SEED) \
--iterations $(ITERATIONS)
touch $@
scripts/compile-generated-test.py
$(verb)scripts/compile-generated-test.py \
$(verb-arg) \
--output $@ \
--isa $(ISA) \
--input-dir $(OUT-SEED)/instr_gen/asm_test \
--test-dot-seed $* \
--start-seed $(SEED)
.PHONY: instr_gen_compile
instr_gen_compile: $(metadata)/.instr_gen.compile_tests.stamp
instr_gen_compile: $(test-bins)
###############################################################################
# Run the instruction set simulator
@ -350,15 +358,13 @@ iss-sim-logs := $(foreach ts,$(tests-and-seeds),$(OUT-SEED)/$(ISS)/$(ts).log)
$(iss-sim-logs): \
$(OUT-SEED)/$(ISS)/%.log: \
$(metadata)/.instr_gen.compile_tests.stamp \
$(OUT-SEED)/instr_gen/%.bin \
$(TESTLIST) scripts/run-iss.py | $(OUT-SEED)/$(ISS)
$(verb)scripts/run-iss.py \
$(verb-arg) \
--iss=$(ISS) \
--test-dot-seed $* \
--start-seed $(SEED) \
--gen-dir=$(OUT-SEED)/instr_gen \
--run-dir=$(@D) \
--input=$(OUT-SEED)/instr_gen/$*.o \
--output=$@ \
--isa=$(ISA_ISS)
.PHONY: iss_run
@ -435,20 +441,19 @@ rtl-sim-dirs := $(addprefix $(OUT-SEED)/rtl_sim/,$(tests-and-seeds))
rtl-sim-logs := $(addsuffix /sim.log,$(rtl-sim-dirs))
$(rtl-sim-logs): \
%/sim.log: \
$(OUT-SEED)/rtl_sim/%/sim.log: \
$(metadata)/.rtl.tb_compile.stamp \
$(metadata)/.instr_gen.compile_tests.stamp \
$(OUT-SEED)/instr_gen/%.bin \
scripts/run-rtl.py
@echo Running RTL simulation at $@
$(verb)mkdir -p $(@D)
$(verb)scripts/run-rtl.py \
--simulator $(SIMULATOR) \
$(cov-arg) $(wave-arg) \
--start-seed $(SEED) \
--signature-addr $(SIGNATURE_ADDR) \
--test-dot-seed $(notdir $*) \
--bin-dir $(OUT-SEED)/instr_gen/asm_test \
--rtl-sim-dir $(OUT-SEED)/rtl_sim \
$(verb)scripts/run-rtl.py \
--simulator $(SIMULATOR) \
$(cov-arg) $(wave-arg) \
--signature-addr $(SIGNATURE_ADDR) \
--test-dot-seed $* \
--binary $(OUT-SEED)/instr_gen/$*.bin \
--rtl-sim-dir $(OUT-SEED)/rtl_sim \
--sim-opts "$(SIM_OPTS)"
.PHONY: rtl_sim_run

View file

@ -0,0 +1,109 @@
#!/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 shlex
import sys
import tempfile
from scripts_lib import read_test_dot_seed, start_riscv_dv_run_cmd, run_one
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument('--verbose', action='store_true')
parser.add_argument('--output', required=True)
parser.add_argument('--isa', required=True)
parser.add_argument('--input-dir', required=True)
parser.add_argument('--test-dot-seed',
type=read_test_dot_seed, required=True)
parser.add_argument('--start-seed', type=int, required=True)
args = parser.parse_args()
if args.start_seed < 0:
raise RuntimeError('Invalid start seed: {}'.format(args.start_seed))
testname, seed = args.test_dot_seed
if seed < args.start_seed:
raise RuntimeError('Start seed is greater than test seed '
f'({args.start_seed} > {seed}).')
iteration = seed - args.start_seed
if not args.output.endswith('.bin'):
raise RuntimeError("Output argument must end with .bin: "
f"got {args.output!r}")
out_base = args.output[:-4]
out_riscv_dv_path = out_base + '.riscv-dv.log'
out_obj_path = out_base + '.o'
src_file = os.path.join(args.input_dir, f'{testname}_{iteration}.S')
if not os.path.exists(src_file):
raise RuntimeError(f'No such input file: {src_file!r}.')
# Run riscv-dv to get a list of commands that it would run to try to
# compile and convert the files in question. These will need some massaging
# to match our paths, but we can't generate the commands by hand because
# there are several test-specific options that might appear.
with tempfile.TemporaryDirectory() as td:
placeholder = os.path.join(td, '@@PLACEHOLDER@@')
orig_list = os.path.join(td, 'orig-cmds.list')
dv_ret = run_one(False,
start_riscv_dv_run_cmd(args.verbose) +
['--verbose',
'--output', placeholder,
'--steps=gcc_compile',
'--test', testname,
'--start_seed', str(seed),
'--iterations', '1',
'--isa', args.isa,
'--debug', orig_list],
redirect_stdstreams=out_riscv_dv_path)
if dv_ret:
return dv_ret
orig_cmds = []
with open(orig_list) as orig_file:
for line in orig_file:
line = line.strip()
if not line:
continue
orig_cmds.append(shlex.split(line))
# Do the massaging. We intentionally used "@@PLACEHOLDER@@" as a path in
# our call to riscv-dv, which should let us find all the things that matter
# easily.
rewrites = [
(f"{placeholder}/asm_test/{testname}_0.S", src_file),
(f"{placeholder}/asm_test/{testname}_0.o", out_obj_path),
(f"{placeholder}/asm_test/{testname}_0.bin", args.output)
]
new_cmds = []
for cmd in orig_cmds:
new_cmd = []
for word in cmd:
for old, new in rewrites:
word = word.replace(old, new)
if placeholder in word:
raise RuntimeError("Couldn't replace every copy of "
f"placeholder in {cmd}")
new_cmd.append(word)
new_cmds.append(new_cmd)
# Finally, run all the commands
for cmd in new_cmds:
ret = run_one(args.verbose, cmd)
if ret != 0:
return ret
if __name__ == '__main__':
sys.exit(main())

View file

@ -1,39 +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 sys
from scripts_lib import start_riscv_dv_run_cmd, run_one
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument('--verbose', action='store_true')
parser.add_argument('--output', required=True)
parser.add_argument('--isa', required=True)
parser.add_argument('--test', required=True)
parser.add_argument('--start-seed', type=int, required=True)
parser.add_argument('--iterations', type=int, required=True)
args = parser.parse_args()
cmd = (start_riscv_dv_run_cmd(args.verbose) +
['--output', args.output,
'--steps=gcc_compile',
'--test', args.test,
'--start_seed', str(args.start_seed),
'--iterations', str(args.iterations),
'--isa', args.isa])
if args.verbose:
cmd.append('--verbose')
return run_one(args.verbose, cmd)
if __name__ == '__main__':
sys.exit(main())

View file

@ -8,34 +8,19 @@ import argparse
import os
import sys
from scripts_lib import read_test_dot_seed, run_one
from scripts_lib import run_one
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument('--verbose', action='store_true')
parser.add_argument('--iss', required=True)
parser.add_argument('--test-dot-seed',
type=read_test_dot_seed, required=True)
parser.add_argument('--gen-dir', required=True)
parser.add_argument('--run-dir', required=True)
parser.add_argument('--input', required=True)
parser.add_argument('--output', required=True)
parser.add_argument('--isa', required=True)
parser.add_argument('--start-seed', type=int, required=True)
args = parser.parse_args()
testname, seed = args.test_dot_seed
if args.start_seed < 0:
raise RuntimeError('Invalid start seed: {}'.format(args.start_seed))
testname, seed = args.test_dot_seed
if seed < args.start_seed:
raise RuntimeError('Start seed is greater than test seed '
f'({args.start_seed} > {seed}).')
iteration = seed - args.start_seed
# riscv-dv knows how to run an ISS simulation (see yaml/iss.yaml in the
# vendored directory), but it has definite (and inconvenient!) opinions
# about where files should end up. Rather than fight with it, let's just
@ -48,21 +33,16 @@ def main() -> int:
if args.iss != 'spike':
raise RuntimeError(f'Unsupported ISS: {args.iss}')
object_name = f'{testname}_{iteration}.o'
log_name = os.path.join(args.run_dir, f'{testname}.{seed}.log')
spike_dir = os.getenv('SPIKE_PATH')
if spike_dir is not None:
spike = os.path.join(spike_dir, 'spike')
else:
spike = 'spike'
cmd = [spike, '--log-commits',
'--isa', args.isa,
'-l', os.path.join(args.gen_dir, 'asm_test', object_name)]
cmd = [spike, '--log-commits', '--isa', args.isa, '-l', args.input]
return run_one(args.verbose,
cmd,
redirect_stdstreams=log_name)
redirect_stdstreams=args.output)
if __name__ == '__main__':

View file

@ -12,17 +12,16 @@ from test_entry import get_test_entry
_CORE_IBEX = os.path.normpath(os.path.join(os.path.dirname(__file__), '..'))
def get_test_sim_cmd(base_cmd, test, idx, seed, sim_dir, bin_dir, lsf_cmd):
def get_test_sim_cmd(base_cmd, test, binary, seed, sim_dir, lsf_cmd):
'''Generate the command that runs a test iteration in the simulator
base_cmd is the command to use before any test-specific substitutions. test
is a dictionary describing the test (originally read from the testlist YAML
file). idx is the test iteration (an integer) and seed is the corresponding
seed.
file). binary is the path to the binary for the test. seed is the seed to
use.
sim_dir is the directory to which the test results will be written. bin_dir
is the directory containing compiled binaries. lsf_cmd (if not None) is a
string that runs bsub to submit the task on LSF.
sim_dir is the directory to which the test results will be written. lsf_cmd
(if not None) is a string that runs bsub to submit the task on LSF.
Returns the command to run.
@ -34,8 +33,6 @@ def get_test_sim_cmd(base_cmd, test, idx, seed, sim_dir, bin_dir, lsf_cmd):
test_name = test['test']
binary = os.path.join(bin_dir, '{}_{}.bin'.format(test_name, idx))
# Do final interpolation into the test command for variables that depend on
# the test name or iteration number.
sim_cmd = subst_vars(sim_cmd,
@ -44,14 +41,13 @@ def get_test_sim_cmd(base_cmd, test, idx, seed, sim_dir, bin_dir, lsf_cmd):
'rtl_test': test['rtl_test'],
'binary': binary,
'test_name': test_name,
'iteration': str(idx)
})
if not os.path.exists(binary):
raise RuntimeError('When computing simulation command for running '
'iteration {} of test {}, cannot find the '
'seed {} of test {}, cannot find the '
'expected binary at {!r}.'
.format(idx, test_name, binary))
.format(seed, test_name, binary))
if lsf_cmd is not None:
sim_cmd = lsf_cmd + ' ' + sim_cmd
@ -65,26 +61,17 @@ def main() -> int:
parser.add_argument("--en_cov", action='store_true')
parser.add_argument("--en_wave", action='store_true')
parser.add_argument('--signature-addr', required=True)
parser.add_argument('--start-seed', type=int, required=True)
parser.add_argument('--test-dot-seed',
type=read_test_dot_seed,
required=True)
parser.add_argument('--lsf-cmd')
parser.add_argument('--bin-dir', required=True)
parser.add_argument('--binary', required=True)
parser.add_argument('--rtl-sim-dir', required=True)
parser.add_argument('--sim-opts')
args = parser.parse_args()
if args.start_seed < 0:
raise RuntimeError('Invalid start seed: {}'.format(args.start_seed))
testname, seed = args.test_dot_seed
if seed < args.start_seed:
raise RuntimeError('Start seed is greater than test seed '
f'({args.start_seed} > {seed}).')
iteration = seed - args.start_seed
entry = get_test_entry(testname)
# Look up how to run the simulator in general
@ -109,8 +96,8 @@ def main() -> int:
# Specialize base_cmd for this specific test
test_sim_dir = os.path.join(args.rtl_sim_dir,
'{}.{}'.format(testname, seed))
test_cmd = get_test_sim_cmd(sim_cmd, entry, iteration, seed,
test_sim_dir, args.bin_dir, args.lsf_cmd)
test_cmd = get_test_sim_cmd(sim_cmd, entry, args.binary, seed,
test_sim_dir, args.lsf_cmd)
# Run test_cmd (it's a string, so we have to call out to the shell to do
# so). Note that we don't capture the success or failure of the subprocess: