fpga: tools: Fix issues in run_testbenches.py
This commit addresses several issues that can occur with different simulators. It changes the following: - Update documentation - Ignore testbenches in build-ip folders - Tolerate extra lines in the testbench results regular expression - Match numbers using \d instead of + to avoid ValueError exceptions - Only fetch the start_time if it exists - Allow any simulator make target (don't limit it to specific choices) Original-commit: 81ccd8cb5154e85636cddd86c466daffb4ab4ebe
This commit is contained in:
committed by
Jörg Hofrichter
parent
6b19ec030c
commit
c499cad53d
@@ -5,6 +5,14 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
#
|
||||
|
||||
"""Batch testbench execution script
|
||||
|
||||
This script searches the locations that you specify for testbenches and then
|
||||
executes them using the desired simulator. Work is automatically grouped into
|
||||
jobs for parallel execution and the results are printed to the console.
|
||||
Testbenches are identified by the presence of the viv_sim_preamble in the
|
||||
Makefile."""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
@@ -97,6 +105,10 @@ def find_sims_on_fs(basedir, excludes):
|
||||
"""
|
||||
sims = {}
|
||||
for root, _, files in os.walk(basedir):
|
||||
if "/build-ip/" in root:
|
||||
# Exclude any testbenches in the IP build outputs, since these are
|
||||
# duplicates.
|
||||
continue
|
||||
name = os.path.relpath(root, basedir)
|
||||
if "Makefile" in files:
|
||||
with open(os.path.join(root, "Makefile"), "r") as mfile:
|
||||
@@ -158,25 +170,30 @@ def parse_output(simout):
|
||||
tfm = re.match(rb"# End time:.*, Elapsed time: (.+)", line)
|
||||
if tfm is not None:
|
||||
results["wall_time"] = str(tfm.group(1), "ascii")
|
||||
|
||||
# Parse testbench results
|
||||
#
|
||||
# We have two possible formats to parse because we have two simulation
|
||||
# test executors.
|
||||
#
|
||||
# ModelSim and Questa print "# " at the start of each line. In some cases,
|
||||
# Questa Base will print an extra line with "# " between the actual lines.
|
||||
tb_match_fmt0 = [
|
||||
b".*TESTBENCH FINISHED: (.+)\n",
|
||||
b"(?:# )? - Time elapsed: (.+) ns.*\n",
|
||||
b"(?:# )? - Tests Expected: (.+)\n",
|
||||
b"(?:# )? - Tests Run: (.+)\n",
|
||||
b"(?:# )? - Tests Passed: (.+)\n",
|
||||
b"(?:# )?Result: (PASSED|FAILED).*",
|
||||
b"(?:# \n)?(?:# )? - Time elapsed: (\\d+) ns.*\n",
|
||||
b"(?:# \n)?(?:# )? - Tests Expected: (\\d+)\n",
|
||||
b"(?:# \n)?(?:# )? - Tests Run: (\\d+)\n",
|
||||
b"(?:# \n)?(?:# )? - Tests Passed: (\\d+)\n",
|
||||
b"(?:# \n)?(?:# )?Result: (PASSED|FAILED).*",
|
||||
]
|
||||
m_fmt0 = re.match(b"".join(tb_match_fmt0), simout, re.DOTALL)
|
||||
tb_match_fmt1 = [
|
||||
b".*TESTBENCH FINISHED: (.*)\n",
|
||||
b"(?:# )? - Time elapsed: (.+) ns.*\n",
|
||||
b"(?:# )? - Tests Run: (.+)\n",
|
||||
b"(?:# )? - Tests Passed: (.+)\n",
|
||||
b"(?:# )? - Tests Failed: (.+)\n",
|
||||
b"(?:# )?Result: (PASSED|FAILED).*",
|
||||
b"(?:# \n)?(?:# )? - Time elapsed: (\\d+) ns.*\n",
|
||||
b"(?:# \n)?(?:# )? - Tests Run: (\\d+)\n",
|
||||
b"(?:# \n)?(?:# )? - Tests Passed: (\\d+)\n",
|
||||
b"(?:# \n)?(?:# )? - Tests Failed: (\\d+)\n",
|
||||
b"(?:# \n)?(?:# )?Result: (PASSED|FAILED).*",
|
||||
]
|
||||
m_fmt1 = re.match(b"".join(tb_match_fmt1), simout, re.DOTALL)
|
||||
|
||||
@@ -427,8 +444,10 @@ def do_cleanup(args):
|
||||
excludes = read_excludes_file(args.excludes)
|
||||
for (name, path) in gather_target_sims(args.basedir, args.target, excludes):
|
||||
_LOG.info("Cleaning up %s", name)
|
||||
os.chdir(os.path.join(args.basedir, path))
|
||||
old_path = os.getcwd()
|
||||
os.chdir(path)
|
||||
subprocess.Popen("{setupenv} make cleanall".format(setupenv=setupenv), shell=True).wait()
|
||||
os.chdir(old_path)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -454,6 +473,7 @@ def do_report_csv(args, results):
|
||||
line["module"] = str(name)
|
||||
line["retcode"] = retcode_to_str(result["retcode"])
|
||||
line["status"] = "ERROR"
|
||||
if "start_time" in result:
|
||||
line["start_time"] = result["start_time"]
|
||||
else:
|
||||
line = result
|
||||
@@ -517,7 +537,9 @@ def do_report(args, results=None):
|
||||
|
||||
# Parse command line options
|
||||
def get_options():
|
||||
parser = argparse.ArgumentParser(description="Batch testbench execution script")
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__, formatter_class=argparse.RawTextHelpFormatter
|
||||
)
|
||||
parser.add_argument(
|
||||
"-d",
|
||||
"--basedir",
|
||||
@@ -527,9 +549,8 @@ def get_options():
|
||||
parser.add_argument(
|
||||
"-s",
|
||||
"--simulator",
|
||||
choices=["xsim", "vsim", "modelsim"],
|
||||
default="xsim",
|
||||
help="Simulator name",
|
||||
help="Simulator make target (e.g., xsim, vsim, etc.)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-e",
|
||||
@@ -555,17 +576,34 @@ def get_options():
|
||||
help="Output is logged, so don't show per-second timer",
|
||||
)
|
||||
parser.add_argument(
|
||||
"action", choices=["run", "cleanup", "list", "report"], default="list", help="What to do?"
|
||||
"action",
|
||||
choices=["run", "cleanup", "list", "report"],
|
||||
default="list",
|
||||
help=(
|
||||
"Action to perform, which may be one of:\n"
|
||||
" run: Run the testbenches\n"
|
||||
" cleanup: Run 'make cleanall' for each testbench\n"
|
||||
" list: List all the testbenches found\n"
|
||||
" report: Generate a report from the last run"
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"target", nargs="*", default=".*", help="Space separated simulation target regexes"
|
||||
"target",
|
||||
nargs="*",
|
||||
default=".*",
|
||||
help="Space-separated list of regular expressions for the testbenches to run",
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def main():
|
||||
args = get_options()
|
||||
actions = {"list": do_list, "run": do_run, "cleanup": do_cleanup, "report": do_report}
|
||||
actions = {
|
||||
"list": do_list,
|
||||
"run": do_run,
|
||||
"cleanup": do_cleanup,
|
||||
"report": do_report,
|
||||
}
|
||||
return actions[args.action](args)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user