ivtests: Add support for vlog95 tests

This adds the "normal-vlog95" test type, because we need to run a different
set of commands for this to work so a new test type makes sense. This also
moves a few of the existing tests to the new format in order to test the
new test rig.
This commit is contained in:
Stephen Williams 2023-02-26 19:13:00 -08:00
parent a4aade5d1a
commit 564304d20c
35 changed files with 172 additions and 78 deletions

View File

@ -54,6 +54,11 @@ This describes the kind of test to run. The valid values are:
that succeeds execute it using the vvp command. If there is no gold file
specified, then look for an output line with the "PASSED" string.
* **normal-vlog95** - This is similar to the normal case, but uses
the -tvlog95 target in a first pass to generate simplified verilog, then a
regular iverilog command with the -tvvp target to generate the actual
executable. This tests the -tvlog95 target.
* **NI** - Mark the test as not implemented. The test will be skipped without
running or reporting an error.

View File

@ -0,0 +1 @@
ivltests/br_gh13a.v:7: warning: Unsized expression (('sd1)<<(~(40'b0000000000000000000000000000000000000000))) expanded beyond and was clipped to 65568 bits. Try using sized operands.

View File

@ -0,0 +1 @@
ivltests/br_gh13a.v:7: warning: Unsized expression (('sd1)<<(~(40'b0000000000000000000000000000000000000000))) expanded beyond and was clipped to 65568 bits. Try using sized operands.

View File

@ -0,0 +1,2 @@
0
PASSED

View File

View File

@ -0,0 +1,2 @@
0
PASSED

View File

@ -1,3 +0,0 @@
./ivltests/br_gh13a.v:7: warning: Unsized expression (('sd1)<<(~(40'b0000000000000000000000000000000000000000))) expanded beyond and was clipped to 65568 bits. Try using sized operands.
0
PASSED

View File

View File

@ -1,4 +1,4 @@
1001
001
1001
0101
01
101

View File

@ -68,19 +68,6 @@
# gold or diff commands.
#
#------------------------------------------------------------------------------
# Differences when iverilog is run without -gstrict-expr-width
#------------------------------------------------------------------------------
# The standard requires oversized unsized constant numbers to be truncated.
# These tests are specifically testing that such numbers aren't truncated.
pr903 normal ivltests
pr1388974 normal ivltests
# The standard doesn't support lossless expressions.
br_gh13a normal ivltests gold=br_gh13a.gold
param-width normal ivltests gold=param-width-ivl.gold
#------------------------------------------------------------------------------
# Differences when vvp is run without -compatible
#------------------------------------------------------------------------------

View File

@ -726,7 +726,6 @@ onehot normal contrib # one hot design
p_monta normal ivltests
par_mismatch CE,-gspecify ivltests
param-extend normal ivltests
param-width normal ivltests gold=param-width.gold
param_add normal ivltests # Addition in param declar
param_and normal ivltests # bitwise &
param_and2 normal ivltests # logical && in param declar

View File

@ -3,6 +3,8 @@
# describes the test.
array_packed_write_read vvp_tests/array_packed_write_read.json
br_gh13a vvp_tests/br_gh13a.json
br_gh13a-vlog95 vvp_tests/br_gh13a-vlog95.json
case1 vvp_tests/case1.json
case2 vvp_tests/case2.json
case2-S vvp_tests/case2-S.json
@ -23,5 +25,11 @@ dffsynth11 vvp_tests/dffsynth11.json
dumpfile vvp_tests/dumpfile.json
macro_str_esc vvp_tests/macro_str_esc.json
memsynth1 vvp_tests/memsynth1.json
param-width vvp_tests/param-width.json
param-width-vlog95 vvp_tests/param-width-vlog95.json
pr1388974 vvp_tests/pr1388974.json
pr1388974-vlog95 vvp_tests/pr1388974-vlog95.json
pr903 vvp_tests/pr903.json
pr903-vlog95 vvp_tests/pr903-vlog95.json
struct_packed_write_read vvp_tests/struct_packed_write_read.json
struct_packed_write_read2 vvp_tests/struct_packed_write_read2.json

View File

@ -8,8 +8,8 @@ import os
import sys
import re
def assemble_iverilog_cmd(source: str, it_dir: str, args: list) -> list:
res = ["iverilog", "-o", os.path.join("work", "a.out")]
def assemble_iverilog_cmd(source: str, it_dir: str, args: list, outfile = "a.out") -> list:
res = ["iverilog", "-o", os.path.join("work", outfile)]
res += ["-D__ICARUS_UNSIZED__"]
res += args
src = os.path.join(it_dir, source)
@ -44,7 +44,9 @@ def build_runtime(it_key: str) -> None:
This is called in front of tests to make sure that the directory
structure is correct, and common temp files that might linger from
a previous run are removed.'''
a previous run are removed. We need to make sure that the directories
"work" and "log" are present, and the log files related to this key
are removed.'''
try:
os.mkdir("log")
@ -122,71 +124,28 @@ def run_CE(options : dict) -> list:
else:
return [0, "Passed - CE"]
def check_run_outputs(options : dict, expected_fail : bool, it_stdout : str, log_list : list) -> list:
'''Check the output files, and return success for failed.
def do_run_normal(options : dict, expected_fail : bool) -> list:
'''Run the iverilog and vvp commands.
In this case, run the compiler to generate a vvp output file, and
run the vvp command to actually execute the simulation. Collect
the results and look for a "PASSED" string.'''
This function takes an options dictionary that describes the settings, and
the output from the final command. This also takes a list of log files to check
there there are gold files present.'''
# Get the options this step needs...
it_key = options['key']
it_dir = options['directory']
it_iverilog_args = options['iverilog_args']
it_vvp_args = options['vvp_args']
it_vvp_args_extended = options['vvp_args_extended']
it_gold = options['gold']
it_diff = options['diff']
build_runtime(it_key)
# Run the iverilog command
ivl_cmd = assemble_iverilog_cmd(options['source'], it_dir, it_iverilog_args)
ivl_res = subprocess.run(ivl_cmd, capture_output=True)
log_results(it_key, "iverilog", ivl_res)
if ivl_res.returncode != 0:
return [1, "Failed - Compile failed"]
# run the vvp command
vvp_cmd = assemble_vvp_cmd(it_vvp_args, it_vvp_args_extended)
vvp_res = subprocess.run(vvp_cmd, capture_output=True)
log_results(it_key, "vvp", vvp_res);
if vvp_res.returncode != 0:
return [1, "Failed - Vvp execution failed"]
it_stdout = vvp_res.stdout.decode('ascii')
# If there is a gold file configured, the test result depends on
# the outputs matching the gold file.
if it_gold is not None:
compared = True
log_path = os.path.join("log", f"{it_key}-iverilog-stdout.log")
gold_path = os.path.join("gold", f"{it_gold}-iverilog-stdout.gold")
compared_ivl_stdout = compare_files(log_path, gold_path)
compared = compared and compared_ivl_stdout
log_path = os.path.join("log", f"{it_key}-iverilog-stderr.log")
gold_path = os.path.join("gold", f"{it_gold}-iverilog-stderr.gold")
compared_ivl_stderr = compare_files(log_path, gold_path)
compared = compared and compared_ivl_stderr
log_path = os.path.join("log", f"{it_key}-vvp-stdout.log")
gold_path = os.path.join("gold", f"{it_gold}-vvp-stdout.gold")
compared_vvp_stdout = compare_files(log_path, gold_path)
compared = compared and compared_vvp_stdout
log_path = os.path.join("log", f"{it_key}-vvp-stderr.log")
gold_path = os.path.join("gold", f"{it_gold}-vvp-stderr.gold")
compared_vvp_stderr = compare_files(log_path, gold_path)
compared = compared and compared_vvp_stderr
for log_name in log_list:
log_path = os.path.join("log", f"{it_key}-{log_name}.log")
gold_path = os.path.join("gold", f"{it_gold}-{log_name}.gold")
compared = compared and compare_files(log_path, gold_path)
if expected_fail:
if compared:
return [1, "Failed - Passed, but expected failure"]
return [1, "Failed = Passed, but expected failure"]
else:
return [0, "Passed - Expected fail"]
else:
@ -195,7 +154,6 @@ def do_run_normal(options : dict, expected_fail : bool) -> list:
else:
return [1, "Failed - Gold output doesn't match actual output."]
# If there is a diff description, then compare named files instead of
# the log and a gold file.
if it_diff is not None:
@ -224,6 +182,7 @@ def do_run_normal(options : dict, expected_fail : bool) -> list:
else:
return [1, f"Failed - Files {diff_name1} and {diff_name2} differ."]
# Otherwise, look for the PASSED output string in stdout.
for line in it_stdout.splitlines():
if line == "PASSED":
@ -240,8 +199,99 @@ def do_run_normal(options : dict, expected_fail : bool) -> list:
return [1, "Failed - No PASSED output, and no gold file"]
def do_run_normal_vlog95(options : dict, expected_fail : bool) -> list:
'''Run the iverilog and vvp commands.
In this case, run the compiler with the -tvlog95 flag to generate
an intermediate verilog file, then run the compiler again to generate
a vvp out. Run that vvp output to test the simulation results. Collect
the results and look for a "PASSED" string.'''
it_key = options['key']
it_dir = options['directory']
it_iverilog_args = ["-tvlog95"] + options['iverilog_args']
it_vvp_args = options['vvp_args']
it_vvp_args_extended = options['vvp_args_extended']
build_runtime(it_key)
# Run the first iverilog command, to generate the intermediate verilog
ivl1_cmd = assemble_iverilog_cmd(options['source'], it_dir, it_iverilog_args, "a.out.v")
ivl1_res = subprocess.run(ivl1_cmd, capture_output=True)
log_results(it_key, "iverilog", ivl1_res)
if ivl1_res.returncode != 0:
return [1, "Failed - Compile failed"]
# Run another iverilog command to compile the code generated from the first step.
ivl2_cmd = assemble_iverilog_cmd("a.out.v", "work", [ ], "a.out")
ivl2_res = subprocess.run(ivl2_cmd, capture_output=True)
log_results(it_key, "iverilog-vlog95", ivl2_res)
if ivl2_res.returncode != 0:
return [1, "Failed - Compile of generated code failed"]
# Run the vvp command
vvp_cmd = assemble_vvp_cmd(it_vvp_args, it_vvp_args_extended)
vvp_res = subprocess.run(vvp_cmd, capture_output=True)
log_results(it_key, "vvp", vvp_res);
if vvp_res.returncode != 0:
return [1, "Failed - Vvp execution failed"]
it_stdout = vvp_res.stdout.decode('ascii')
log_list = ["iverilog-stdout", "iverilog-stderr",
"iverilog-vlog95-stdout", "iverilog-vlog95-stderr",
"vvp-stdout", "vvp-stderr"]
return check_run_outputs(options, expected_fail, it_stdout, log_list)
def do_run_normal(options : dict, expected_fail : bool) -> list:
'''Run the iverilog and vvp commands.
In this case, run the compiler to generate a vvp output file, and
run the vvp command to actually execute the simulation. Collect
the results and look for a "PASSED" string.'''
it_key = options['key']
it_dir = options['directory']
it_iverilog_args = options['iverilog_args']
it_vvp_args = options['vvp_args']
it_vvp_args_extended = options['vvp_args_extended']
build_runtime(it_key)
# Run the iverilog command
ivl_cmd = assemble_iverilog_cmd(options['source'], it_dir, it_iverilog_args)
ivl_res = subprocess.run(ivl_cmd, capture_output=True)
log_results(it_key, "iverilog", ivl_res)
if ivl_res.returncode != 0:
return [1, "Failed - Compile failed"]
# run the vvp command
vvp_cmd = assemble_vvp_cmd(it_vvp_args, it_vvp_args_extended)
vvp_res = subprocess.run(vvp_cmd, capture_output=True)
log_results(it_key, "vvp", vvp_res);
if vvp_res.returncode != 0:
return [1, "Failed - Vvp execution failed"]
it_stdout = vvp_res.stdout.decode('ascii')
log_list = ["iverilog-stdout", "iverilog-stderr",
"vvp-stdout", "vvp-stderr"]
return check_run_outputs(options, expected_fail, it_stdout, log_list)
def run_normal(options : dict) -> list:
return do_run_normal(options, False)
def run_EF(options : dict) -> list:
return do_run_normal(options, True)
def run_normal_vlog95(options : dict) -> list:
return do_run_normal_vlog95(options, False)
def run_EF_vlog95(options : dict) -> list:
return do_run_normal_vlog95(options, True)

View File

@ -56,12 +56,18 @@ def process_test(item: list) -> str:
elif it_type == "normal":
res = run_ivl.run_normal(it_options)
elif it_type == "normal-vlog95":
res = run_ivl.run_normal_vlog95(it_options)
elif it_type == "CE":
res = run_ivl.run_CE(it_options)
elif it_type == "EF":
res = run_ivl.run_EF(it_options)
elif it_type == "EF-vlog95":
res = run_ivl.run_EF_vlog95(it_options)
else:
res = f"{it_key}: I don't understand the test type ({it_type})."
raise Exception(res)

View File

@ -0,0 +1,5 @@
{
"type" : "normal-vlog95",
"source" : "br_gh13a.v",
"gold" : "br_gh13a-vlog95"
}

View File

@ -0,0 +1,5 @@
{
"type" : "normal",
"source" : "br_gh13a.v",
"gold" : "br_gh13a"
}

View File

@ -0,0 +1,5 @@
{
"type" : "normal-vlog95",
"source" : "param-width.v",
"gold" : "param-width-vlog95"
}

View File

@ -0,0 +1,5 @@
{
"type" : "normal",
"source" : "param-width.v",
"gold" : "param-width"
}

View File

@ -0,0 +1,4 @@
{
"type" : "normal-vlog95",
"source" : "pr1388974.v"
}

View File

@ -0,0 +1,4 @@
{
"type" : "normal",
"source" : "pr1388974.v"
}

View File

@ -0,0 +1,4 @@
{
"type" : "normal-vlog95",
"source" : "pr903.v"
}

View File

@ -0,0 +1,4 @@
{
"type" : "normal",
"source" : "pr903.v"
}