sv2v/test/lib/functions.sh

214 lines
6.1 KiB
Bash

#!/bin/bash
SCRIPT_DIR=`dirname "${BASH_SOURCE[0]}"`
SV2V="$SCRIPT_DIR/../../bin/sv2v +RTS -N1 -RTS"
# USAGE: simulate <vcd-file> <log-file> <file> [<file> ...]
simulate() {
# arguments
sim_vcd=$1
sim_log=$2
shift 2
# compile the files
sim_vcd_tmp=$SHUNIT_TMPDIR/simvcdtmp
sim_prog=$SHUNIT_TMPDIR/simprog.exe
iv_output=`iverilog \
-Wall \
-Wno-portbind \
-o $sim_prog \
-g2005 \
-gstrict-expr-width \
-DTEST_VCD=\"$sim_vcd_tmp\" \
"$@" \
$SCRIPT_DIR/tb_dumper.v \
2>&1`
if [ $? -ne 0 ]; then
fail "iverilog on $1 failed:\n$iv_output"
return
elif [ "$EXPECT_IVERILOG_WARNINGS" != "0" ]; then
assertNull "iverilog on $1 emitted warnings:\n$iv_output" "$iv_output"
else
assertNotNull "iverilog on $1 did not emit any warnings" "$iv_output"
fi
# run the simulation
$sim_prog -no-date > $sim_log
assertTrue "simulating $1 failed" $?
# remove parameters from the VCD if present
if grep -E "var parameter| _sv2v_0 " $sim_vcd_tmp > /dev/null; then
$SCRIPT_DIR/clean_vcd.py < $sim_vcd_tmp > $sim_vcd
elif [ $sim_vcd != "/dev/null" ]; then
mv -f $sim_vcd_tmp $sim_vcd
fi
}
assertConverts() {
ac_file=$1
ac_tmpa=$SHUNIT_TMPDIR/ac-conv-tmpa.v
convert "1st conversion of $ac_file" $ac_tmpa $ac_file
# check for un/expected output in the converted result
ac_pats=$ac_file.pat
if [ -f $ac_pats ]; then
while read line; do
rule=${line:0:6}
pattern=${line:7}
grep -F "$pattern" < $ac_tmpa > /dev/null
matches=$?
if [ $rule == "affirm" ]; then
assertTrue "conversion of $ac_file does not contain $pattern" $matches
elif [ $rule == "reject" ]; then
assertFalse "conversion of $ac_file contains $pattern" $matches
else
fail "unknown rule type: '$rule'"
fi
done < $ac_pats
fi
ac_tmpb=$SHUNIT_TMPDIR/ac-conv-tmpb.v
convert "2nd conversion of $ac_file" $ac_tmpb $ac_tmpa
diff $ac_tmpa $ac_tmpb > /dev/null
assertTrue "conversion of $ac_file not stable after the first iteration" $?
ac_tmpc=$SHUNIT_TMPDIR/ac-conv-tmpc.v
convert "pass through of $ac_file" $ac_tmpc --pass-through $ac_file
ac_tmpd=$SHUNIT_TMPDIR/ac-conv-tmpd.v
convert "conversion of pass through of $ac_file" $ac_tmpd $ac_tmpc
# remove source locations when checking the --pass-through invariant
removeSourceLocation $ac_file $ac_tmpa
removeSourceLocation $ac_tmpc $ac_tmpd
diff $ac_tmpa $ac_tmpd > /dev/null
assertTrue "pass through then conversion differs for $ac_file" $?
# using sed to remove quoted strings
filtered=`sed -E 's/"([^"]|\")+"//g' $ac_tmpa`
# check for various things iverilog accepts which we don't want to output
prefix="conversion of $ac_file still contains"
assertNotMatch "$prefix dimension queries" "$filtered" \
'\$bits|\$dimensions|\$unpacked_dimensions|\$left|\$right|\$low|\$high|\$increment|\$size'
assertNotMatch "$prefix SystemVerilog types" "$filtered" \
'[[:space:]](int|bit|logic|byte|struct|enum|longint|shortint)[[:space:]]'
assertNotMatch "$prefix unsigned keyword" "$filtered" \
'[^\$a-zA-Z_]unsigned'
}
extractFlag() {
raw_line=`grep -m1 "^// $1: " $2`
to_drop=$((${#1}+5))
flag="${raw_line:to_drop}"
}
assertMatch() {
if [[ ! "$2" =~ $3 ]]; then
fail "$1 doesn't match\nexpected: $3\nactual: $2"
fi
}
assertNotMatch() {
if [[ "$2" =~ $3 ]]; then
fail "$1"
fi
}
# convert SystemVerilog source file(s)
convert() {
description=$1
out_file=$2
shift 2
$SV2V "$@" 2> $SHUNIT_TMPDIR/stderr > $out_file
assertTrue "$description failed" $?
if [ -s $SHUNIT_TMPDIR/stderr ]; then
fail "$description emitted warnings:"
cat $SHUNIT_TMPDIR/stderr
fi
}
simpleTest() {
sv=$1
ve=$2
tb=$3
assertConverts $sv
# some tests use inputs compatible with iverilog directly and so omit the
# reference manually converted file
if [ ! -f $ve ]; then
ve=$sv
else
assertConverts $ve
fi
# some tests don't have a separate testbench, instead having the top-level
# module defined in both of the input files
if [ ! -f $tb ]; then
tb=$SCRIPT_DIR/empty.v
else
assertConverts $tb
fi
cs=$SHUNIT_TMPDIR/cs.v
convert "standard conversion" $cs $sv
cv=$SHUNIT_TMPDIR/cv.v
convert "verbose conversion" $cv $sv -v
simulateAndCompare $ve $cs $cv $tb
}
simulateAndCompare() {
ve=$1 # reference verilog
cs=$2 # converted succinct
cv=$3 # converted verbose
tb=$4 # testbench
ref_vcd=$SHUNIT_TMPDIR/ref.vcd
cvs_vcd=$SHUNIT_TMPDIR/cvs.vcd
cvv_vcd=$SHUNIT_TMPDIR/cvv.vcd
ref_log=$SHUNIT_TMPDIR/ref.log
cvs_log=$SHUNIT_TMPDIR/cvs.log
cvv_log=$SHUNIT_TMPDIR/cvv.log
# simulate the three files
simulate $ref_vcd $ref_log $ve $tb
simulate $cvs_vcd $cvs_log $cs $tb
simulate $cvv_vcd $cvv_log $cv $tb
# clean log files by source locations
removeSourceLocation $ve $ref_log
removeSourceLocation $cs $cvs_log
removeSourceLocation $cv $cvv_log
# compare reference verilog to converted succinct
output=`diff $ref_vcd $cvs_vcd`
assertTrue "VE/CS VCDs are different:\n$output" $?
output=`diff $ref_log $cvs_log`
assertTrue "VE/CS simulation outputs differ:\n$output" $?
# compare converted verbose to converted succinct
output=`diff $cvv_vcd $cvs_vcd`
assertTrue "CV/CS VCDs are different:\n$output" $?
output=`diff $cvv_log $cvs_log`
assertTrue "CV/CS simulation outputs differ:\n$output" $?
rm -f $ref_vcd $cvs_vcd $cvv_vcd $ref_log $cvs_log $cvv_log
}
runTest() {
test=$1
simpleTest "${test}.sv" "${test}.v" "${test}_tb.v"
}
runAndCapture() {
$SV2V "$@" > "$SHUNIT_TMPDIR/stdout" 2> "$SHUNIT_TMPDIR/stderr"
result=$?
stdout=`cat $SHUNIT_TMPDIR/stdout`
stderr=`cat $SHUNIT_TMPDIR/stderr`
}
removeSourceLocation() {
sed -i.bak -E 's#'$1':[0-9]+(:[0-9]+)?#<removed_source_location>#g' $2
}