2019-08-04 05:08:26 +02:00
|
|
|
#!/bin/bash
|
|
|
|
|
|
|
|
|
|
SCRIPT_DIR=`dirname "${BASH_SOURCE[0]}"`
|
|
|
|
|
SV2V="$SCRIPT_DIR/../../bin/sv2v"
|
|
|
|
|
|
|
|
|
|
assertExists() {
|
|
|
|
|
file=$1
|
|
|
|
|
[ -f "$file" ]
|
|
|
|
|
assertTrue "$file does not exist" $?
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# USAGE: simulate <vcd-file> <log-file> <top-module> <file> [<file> ...]
|
|
|
|
|
simulate() {
|
|
|
|
|
# arguments
|
2019-10-03 05:26:48 +02:00
|
|
|
sim_vcd=$1
|
|
|
|
|
sim_log=$2
|
|
|
|
|
sim_top=$3
|
|
|
|
|
shift 3
|
2019-08-04 05:08:26 +02:00
|
|
|
# compile the files
|
2019-10-03 05:26:48 +02:00
|
|
|
sim_prog=$SHUNIT_TMPDIR/simprog.exe
|
2019-08-04 05:08:26 +02:00
|
|
|
iv_output=`iverilog \
|
|
|
|
|
-Wall \
|
|
|
|
|
-Wno-select-range \
|
2019-09-21 19:36:33 +02:00
|
|
|
-Wno-anachronisms \
|
2019-10-03 05:26:48 +02:00
|
|
|
-o $sim_prog \
|
2019-08-04 05:08:26 +02:00
|
|
|
-g2005 \
|
|
|
|
|
-DTEST_VCD="\"$sim_vcd\"" \
|
|
|
|
|
-DTEST_TOP=$sim_top \
|
2019-10-03 05:26:48 +02:00
|
|
|
$SCRIPT_DIR/tb_dumper.v \
|
2019-08-04 05:08:26 +02:00
|
|
|
"$@" 2>&1`
|
|
|
|
|
assertTrue "iverilog on $1 failed" $?
|
2019-10-03 05:26:48 +02:00
|
|
|
if [ -n "$iv_output" ]; then
|
|
|
|
|
assertNull "iverilog emitted warnings:" "$iv_output"
|
2019-08-04 05:08:26 +02:00
|
|
|
echo "$iv_output"
|
|
|
|
|
fi
|
|
|
|
|
# run the simulation
|
2019-10-03 05:26:48 +02:00
|
|
|
$sim_prog > $sim_log.temp
|
2019-08-04 05:08:26 +02:00
|
|
|
assertTrue "simulating $1 failed" $?
|
2019-10-03 05:26:48 +02:00
|
|
|
assertExists $sim_vcd
|
2019-08-04 05:08:26 +02:00
|
|
|
# remove the date from the VCD
|
2019-10-03 05:26:48 +02:00
|
|
|
sed -i.orig -e "1,3d" $sim_vcd
|
2019-09-09 23:37:54 +02:00
|
|
|
# remove extraneous log lines
|
2019-10-03 05:26:48 +02:00
|
|
|
cat $sim_log.temp | grep -v "VCD info: dumpfile" > $sim_log
|
2019-08-04 05:08:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assertConverts() {
|
2019-10-03 05:26:48 +02:00
|
|
|
ac_file=$1
|
|
|
|
|
ac_tmpa=$SHUNIT_TMPDIR/ac-conv-tmpa.v
|
|
|
|
|
$SV2V $ac_file 2> /dev/null > $ac_tmpa
|
2019-08-04 05:08:26 +02:00
|
|
|
assertTrue "1st conversion of $ac_file failed" $?
|
2019-10-03 05:26:48 +02:00
|
|
|
ac_tmpb=$SHUNIT_TMPDIR/ac-conv-tmpb.v
|
|
|
|
|
$SV2V $ac_tmpa 2> /dev/null > $ac_tmpb
|
2019-08-04 05:08:26 +02:00
|
|
|
assertTrue "2nd conversion of $ac_file failed" $?
|
2019-10-03 05:26:48 +02:00
|
|
|
if [ -n "$(diff $ac_tmpa $ac_tmpb)" ]; then
|
|
|
|
|
ac_tmpc=$SHUNIT_TMPDIR/ac-conv-tmpc.v
|
|
|
|
|
$SV2V $ac_tmpb 2> /dev/null > $ac_tmpc
|
|
|
|
|
assertTrue "3rd conversion of $ac_file failed" $?
|
|
|
|
|
diff $ac_tmpb $ac_tmpc > /dev/null
|
|
|
|
|
assertTrue "conversion of $ac_file not stable after the second iteration" $?
|
|
|
|
|
fi
|
2019-08-04 05:08:26 +02:00
|
|
|
# using sed to remove quoted strings
|
2019-10-03 05:26:48 +02:00
|
|
|
filtered=`sed -E 's/"([^"]|\")+"//g' $ac_tmpa`
|
2019-09-25 05:35:06 +02:00
|
|
|
# check for various things iverilog accepts which we don't want to output
|
|
|
|
|
PATTERNS="\$bits\|\$dimensions\|\$unpacked_dimensions\|\$left\|\$right\|\$low\|\$high\|\$increment\|\$size"
|
|
|
|
|
echo "$filtered" | grep "$PATTERNS" > /dev/null
|
|
|
|
|
assertFalse "conversion of $ac_file still contains dimension queries" $?
|
2019-08-04 05:08:26 +02:00
|
|
|
echo "$filtered" | egrep "\s(int\|bit\|logic\|byte\|struct\|enum\|longint\|shortint)\s"
|
|
|
|
|
assertFalse "conversion of $ac_file still contains SV types" $?
|
2020-06-07 03:26:14 +02:00
|
|
|
echo "$filtered" | grep "[^\$a-zA-Z_]unsigned" > /dev/null
|
2019-09-25 05:35:06 +02:00
|
|
|
assertFalse "conversion of $ac_file still contains unsigned keyword" $?
|
2019-08-04 05:08:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# convert SystemVerilog source file(s)
|
|
|
|
|
convert() {
|
2019-10-03 05:26:48 +02:00
|
|
|
out_file=$1; shift
|
|
|
|
|
$SV2V "$@" 2> /dev/null > $out_file
|
2019-08-04 05:08:26 +02:00
|
|
|
assertTrue "conversion failed" $?
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
simpleTest() {
|
2019-10-03 05:26:48 +02:00
|
|
|
sv=$1
|
|
|
|
|
ve=$2
|
|
|
|
|
tb=$3
|
2019-08-04 05:08:26 +02:00
|
|
|
|
2019-10-03 05:26:48 +02:00
|
|
|
assertConverts $sv
|
|
|
|
|
assertConverts $ve
|
2019-08-04 05:08:26 +02:00
|
|
|
|
|
|
|
|
# some tests don't have a separate testbench, instead having the top-level
|
|
|
|
|
# module defined in both of the input files
|
2019-10-03 05:26:48 +02:00
|
|
|
if [ ! -f $tb ]; then
|
|
|
|
|
tb=$SCRIPT_DIR/empty.v
|
|
|
|
|
else
|
|
|
|
|
assertConverts $tb
|
2019-08-04 05:08:26 +02:00
|
|
|
fi
|
|
|
|
|
|
2019-10-03 05:26:48 +02:00
|
|
|
cv=$SHUNIT_TMPDIR/conv.v
|
|
|
|
|
convert $cv $sv
|
2019-08-04 05:08:26 +02:00
|
|
|
|
2019-10-03 05:26:48 +02:00
|
|
|
simulateAndCompare $ve $cv $tb
|
2019-08-04 05:08:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
simulateAndCompare() {
|
2019-10-03 05:26:48 +02:00
|
|
|
ve=$1
|
|
|
|
|
cv=$2
|
|
|
|
|
tb=$3
|
2019-08-04 05:08:26 +02:00
|
|
|
|
2019-10-03 05:26:48 +02:00
|
|
|
ref_vcd=$SHUNIT_TMPDIR/ref.vcd
|
|
|
|
|
gen_vcd=$SHUNIT_TMPDIR/gen.vcd
|
|
|
|
|
ref_log=$SHUNIT_TMPDIR/ref.log
|
|
|
|
|
gen_log=$SHUNIT_TMPDIR/gen.log
|
2019-08-04 05:08:26 +02:00
|
|
|
|
|
|
|
|
# simulate and compare the two files
|
2019-10-03 05:26:48 +02:00
|
|
|
simulate $ref_vcd $ref_log top $ve $tb
|
|
|
|
|
simulate $gen_vcd $gen_log top $cv $tb
|
|
|
|
|
output=`diff $ref_vcd $gen_vcd`
|
2019-09-15 21:49:21 +02:00
|
|
|
assertTrue "VCDs are different:\n$output" $?
|
2019-10-03 05:26:48 +02:00
|
|
|
output=`diff $ref_log $gen_log`
|
2019-08-04 05:08:26 +02:00
|
|
|
assertTrue "Simulation outputs differ:\n$output" $?
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
runTest() {
|
2019-10-03 05:26:48 +02:00
|
|
|
test=$1
|
2019-08-04 05:08:26 +02:00
|
|
|
simpleTest "${test}.sv" "${test}.v" "${test}_tb.v"
|
|
|
|
|
}
|