#!/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 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 # 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` }