Skip to content
Snippets Groups Projects

Use any_error_string() to detect errors (including fatal) in log string. Make...

Merged Eric Kooistra requested to merge RTSD-186 into master
1 file
+ 64
38
Compare changes
  • Side-by-side
  • Inline
@@ -49,7 +49,8 @@
Usage:
- running this script direct from a terminal:
> modelsim_regression_test_vhdl.py unb2b -p 3 # run regressiontest for all test benches in unb2b using 3 worker processes
# run regressiontest for all test benches in unb2b using 3 worker processes
> modelsim_regression_test_vhdl.py unb2b -p 3
--libnames:
The --libnames specifies which HDL libraries are used. If --libnames is not specified
@@ -107,7 +108,13 @@ def main(args, time_ordered_tb_dict):
workers = []
for i in range(n_proc):
worker_id = i + 1
worker = TestBenchWorker(worker_id, control_queue[i], task_queue, response_queue, MK_TIMEOUT, SIM_TIMEOUT, modelsim_log_path)
worker = TestBenchWorker(worker_id,
control_queue[i],
task_queue,
response_queue,
MK_TIMEOUT,
SIM_TIMEOUT,
modelsim_log_path)
workers.append(worker)
worker.start()
@@ -142,7 +149,11 @@ def main(args, time_ordered_tb_dict):
control_queue[i].put("awake")
# simulate libs using all processes
tb_passed, tb_failed, tb_sim_errors = simulate_all_tb(task_info, task_queue, response_queue, time_ordered_tb_dict, mk_failed)
tb_passed, tb_failed, tb_sim_errors = simulate_all_tb(task_info,
task_queue,
response_queue,
time_ordered_tb_dict,
mk_failed)
run_time = time() - run_start_time
logger.info("regressiontest done")
@@ -162,7 +173,8 @@ def main(args, time_ordered_tb_dict):
def generate_task_info_dict(buildset, buildset_file, lib_names):
# Read the dictionary info from all HDL tool and library configuration files in the current directory and the sub directories
# Read the dictionary info from all HDL tool and library configuration files
# in the current directory and the sub directories
msim = ModelsimConfig(
toolRootDir=os.path.expandvars("$RADIOHDL_CONFIG"),
buildsetFile=buildset_file,
@@ -490,7 +502,7 @@ class TestBenchWorker(multiprocessing.Process):
if os.path.exists(sim_dir): # delete old sim data
rmtree(sim_dir, ignore_errors=True)
os.mkdir(sim_dir)
os.environ["HDL_IOFILE_SIM_DIR"] = sim_dir
# logger.debug("%s", str(os.environ))
@@ -633,7 +645,7 @@ class TestBenchWorker(multiprocessing.Process):
do_pathname = os.path.join(self.do_path, do_name)
try:
# rm <mpf_path>/regression_test_vhdl/<lib_name>_mk_all.do
os.remove(do_pathname)
os.remove(do_pathname)
logger.debug("%s: remove '%s'", self.lib_name, do_pathname)
except FileNotFoundError:
pass
@@ -673,7 +685,7 @@ class TestBenchWorker(multiprocessing.Process):
do_pathname = os.path.join(self.do_path, do_name)
try:
# rm <mpf_path>/regression_test_vhdl/<lib_name>_simulate.do
os.remove(do_pathname)
os.remove(do_pathname)
logger.debug("%s: remove '%s'", self.lib_name, do_pathname)
except FileNotFoundError:
pass
@@ -682,6 +694,18 @@ class TestBenchWorker(multiprocessing.Process):
fp.write(do_file)
return
def any_error_string(self, do_log):
"""Return True if any of the error strings exists in do_log.
The do_log is a string containing e.g. the transcipt output.
- For make (mk) the error string is 'Error:'
- For simulation there are several error strings.
"""
if "Fatal:" in do_log or "Error:" in do_log or "Failure:" in do_log:
return True
else:
return False
def run_mk_all(self):
"""
Run mk all on all libs
@@ -717,8 +741,8 @@ class TestBenchWorker(multiprocessing.Process):
else:
n_errors = 10
logger.debug("%s: mk_all ended", self.lib_name)
# if there is a Error or Failure add transcipt file to the log
if "Error:" in do_log: # or 'Failure:' in do_log:
# if there is any error, then add transcipt file to the log
if self.any_error_string(do_log):
logger.debug("worker %d found Errors: in do logging", self._id)
errors = self.get_test_errors(do_log, n_errors)
self.mk_errors.append([self.lib_name, errors]) # get first 10 errors
@@ -757,11 +781,13 @@ class TestBenchWorker(multiprocessing.Process):
Remarks on Modelsim simulation control:
. Google search: modelsim stop simulation vhdl
. How to stop the simulation in VHDL TB
1) The easiest way is to use an assert: assert false report "Simulation Finished" severity failure;
2) The "recommended" way to end a simulation when everything has gone correctly, is to halt all stimulus. This will be stopping
the clock like, but also putting any input processes into a never ending wait if they do not use the generated clock.
3) In VHDL 2008, they have introduced and new package called env to the std library, with procedures called stop and finish,
that act like $finish in verilog. This works, but is not used because the scheme with tb_end suffices:
1) The easiest way is to use an assert: assert false report "Simulation Finished" severity failure;
2) The "recommended" way to end a simulation when everything has gone correctly, is to halt all stimulus.
This will be stopping the clock like, but also putting any input processes into a never ending wait
if they do not use the generated clock.
3) In VHDL 2008, they have introduced and new package called env to the std library, with procedures
called stop and finish, that act like $finish in verilog. This works, but is not used because the
scheme with tb_end suffices:
library std;
use std.env.all;
.......
@@ -809,8 +835,8 @@ class TestBenchWorker(multiprocessing.Process):
if ">>> SIMULATION END" in do_log:
logger.debug(f"{self.tb_name}: simulation ended")
# if there is a Error or Failure add (part) of transcipt file to the log
if "Error:" in do_log: # or 'Failure:' in do_log:
# if there is any error, then add (part) of transcipt file to the log
if self.any_error_string(do_log):
logger.debug(f"worker {self._id} found Errors: in do logging")
errors = self.get_test_errors(do_log, n_errors)
self.sim_errors.append([self.tb_name, errors]) # get first 10 errors
@@ -855,7 +881,7 @@ class TestBenchWorker(multiprocessing.Process):
p1 = do_log.find(find_str)
p2 = do_log.find("\n", p1)
if p1 > -1 and p2 > p1:
exitcode = int(do_log[p1 + len(find_str) : p2], 10)
exitcode = int(do_log[p1 + len(find_str): p2], 10)
else:
exitcode = None
return exitcode
@@ -878,8 +904,8 @@ class TestBenchWorker(multiprocessing.Process):
"""
errors = []
for line in do_log.splitlines():
if "Error:" in line:
errors.append(line[line.find("Error:") :])
if self.any_error_string(line):
errors.append(line)
if len(errors) == n_errors:
break
return errors
@@ -901,27 +927,28 @@ class ModelsimConfig(HdlLibrariesWizard):
- buildsetFile : Default HDL tools configuration file name
- libFileName : Default HDL library configuration file name
The libRootDir is defined in the hdl_buildset_<buildset>.cfg file and is the root directory from where the hdllib.cfg
files are searched for.
The libRootDir is defined in the hdl_buildset_<buildset>.cfg file and is the root directory from where
the hdllib.cfg files are searched for.
Files:
- hdl_buildset_<buildset>.cfg : HDL tool configuration dictionary file. One central file per buildset.
- hdllib.cfg : HDL library configuration dictionary file. One file for each HDL library.
- modelsim_project_files.txt
The modelsim_project_files.txt file is a dictionary file with the list the Modelsim project files for all HDL
libraries that were found in the libRootDir. The keys are the library names and the values are the paths to the
corresponding modelsim project files. The modelsim_project_files.txt file is created by
create_modelsim_project_files_file() and is read by the TCL commands.do file in Modelsim. Creating the file in
Python and then reading this in TCL makes the commands.do much simpler.
The modelsim_project_files.txt file is a dictionary file with the list the Modelsim project files for
all HDL libraries that were found in the libRootDir. The keys are the library names and the values
are the paths to the corresponding modelsim project files. The modelsim_project_files.txt file is
created by create_modelsim_project_files_file() and is read by the TCL commands.do file in Modelsim.
Creating the file in Python and then reading this in TCL makes the commands.do much simpler.
- <lib_name>.mpf : Modelsim project file for a certain HDL library based on the hdllib.cfg. The file is created by
create_modelsim_project_file().
- <lib_name>.mpf : Modelsim project file for a certain HDL library based on the hdllib.cfg. The file
is created by create_modelsim_project_file().
- <lib_name>_lib_order.txt
The <lib_name>_lib_order.txt file contains the library compile order for a certain HDL library. The files are
created by create_lib_order_files() in the same build directory as where the Modelsim project file is stored.
The <lib_name>_lib_order.txt files are read by the TCL commands.do file in Modelsim. Creating the files in Python
and then reading them in TCL makes the commands.do much simpler.
The <lib_name>_lib_order.txt file contains the library compile order for a certain HDL library. The
files are created by create_lib_order_files() in the same build directory as where the Modelsim project
file is stored.
The <lib_name>_lib_order.txt files are read by the TCL commands.do file in Modelsim. Creating the files\
in Python and then reading them in TCL makes the commands.do much simpler.
"""
logger.debug("start ModelsimConfig.__init__()")
libFileSections = ["modelsim_project_file"]
@@ -956,7 +983,8 @@ class ModelsimConfig(HdlLibrariesWizard):
otherargs = ""
otherargs = "+nowarn8684 +nowarn8683 -quiet"
otherargs = "+nowarn8684 +nowarn8683"
otherargs = "+nowarn8684 +nowarn8683 +nowarnTFMPC +nowarnPCDPC" # nowarn on verilog IP connection mismatch warnings
# nowarn on verilog IP connection mismatch warnings
otherargs = "+nowarn8684 +nowarn8683 +nowarnTFMPC +nowarnPCDPC"
if list_mode:
project_sim_p_otherargs = otherargs.split()
else:
@@ -974,10 +1002,8 @@ def str2time(timestr):
return (int(tm[0]) * 60 * 60) + (int(tm[1]) * 60) + float(tm[2])
"""
The timing file is used to order the tests, the longer test will be done first.
This speeds up the regressiontes if running on multiple worker.
"""
# The timing file is used to order the tests, the longer test will be done first.
# This speeds up the regressiontest if running on multiple worker.
def read_timing_file(log_path):
ordered_tb_dict = OrderedDict()
@@ -1011,7 +1037,7 @@ def write_timing_file(log_path, ordered_tb_dict):
timing[ll[7].replace("'", "")] = str2time(ll[10].replace("'", ""))
# sort on simulation time, in revered order
sorted_timing = sorted(timing.items(), key=lambda x:x[1], reverse=True)
sorted_timing = sorted(timing.items(), key=lambda x: x[1], reverse=True)
# write timing to file for next run
timingfile = os.path.join(log_path, "simulation_time.txt")
Loading