From 2acbc95b727c4d4d89b2ac6a160306fe2f86b355 Mon Sep 17 00:00:00 2001 From: Rose Thompson Date: Wed, 7 Feb 2024 15:38:18 -0600 Subject: [PATCH] Partially got linux imperas boot working in the main testbench. --- sim/run-imperas-linux.sh | 6 +- sim/wally-batch.do | 11 ++- sim/wally-linux-imperas.do | 83 ++---------------- testbench/testbench.sv | 167 +++++++++++++++++++++++++++++++++++++ 4 files changed, 185 insertions(+), 82 deletions(-) diff --git a/sim/run-imperas-linux.sh b/sim/run-imperas-linux.sh index 6a49f46e9..86e6d1f64 100755 --- a/sim/run-imperas-linux.sh +++ b/sim/run-imperas-linux.sh @@ -3,8 +3,8 @@ #export RISCV=/scratch/moore/RISCV export IMPERAS_TOOLS=$(pwd)/imperas.ic -export OTHERFLAGS="+TRACE2LOG_ENABLE=1" +export OTHERFLAGS="+TRACE2LOG_ENABLE=1 +TRACE2LOG_AFTER=100" #export OTHERFLAGS="+TRACE2LOG_ENABLE=1 +TRACE2LOG_AFTER=10500000" -export OTHERFLAGS="" +#export OTHERFLAGS="" -vsim -c -do "do wally-linux-imperas.do buildroot buildroot-no-trace $::env(RISCV) 0 0 0" +vsim -do "do wally-linux-imperas.do buildroot buildroot $::env(RISCV) 0 0 0" diff --git a/sim/wally-batch.do b/sim/wally-batch.do index 6a334b103..c07e6b15b 100644 --- a/sim/wally-batch.do +++ b/sim/wally-batch.do @@ -33,6 +33,9 @@ mkdir -p cov # if the do file isd called from questa sim directly. This chunk of code uses the $4 through $n # variables and compacts into a single list for passing to vopt. set coverage 0 +set CoverageVoptArg "" +set CoverageVsimArg "" + set configOptions "" set from 4 set step 1 @@ -47,6 +50,8 @@ for {set i 0} true {incr i} { if {$argc >= 3} { if {$3 eq "-coverage" || ($argc >= 7 && $7 eq "-coverage")} { set coverage 1 + set CoverageVoptArg "+cover=sbecf" + set CoverageVsimArg "-coverage" } elseif {$3 eq "configOptions"} { set configOptions $lst puts $configOptions @@ -66,8 +71,9 @@ vlog -lint -work wkdir/work_${1}_${2} +incdir+../config/$1 +incdir+../config/der # remove +acc flag for faster sim during regressions if there is no need to access internal signals if {$coverage} { # vopt wkdir/work_${1}_${2}.testbench -work wkdir/work_${1}_${2} -G TEST=$2 -o testbenchopt +cover=sbectf - vopt wkdir/work_${1}_${2}.testbench -work wkdir/work_${1}_${2} -G TEST=$2 -o testbenchopt +cover=sbecf - vsim -lib wkdir/work_${1}_${2} testbenchopt -fatal 7 -suppress 3829 -coverage + puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + vopt wkdir/work_${1}_${2}.testbench -work wkdir/work_${1}_${2} -G TEST=$2 -o testbenchopt ${CoverageVoptArg} + vsim -lib wkdir/work_${1}_${2} testbenchopt -fatal 7 -suppress 3829 ${CoverageVsimArg} } else { vopt wkdir/work_${1}_${2}.testbench -work wkdir/work_${1}_${2} -G TEST=$2 ${configOptions} -o testbenchopt vsim -lib wkdir/work_${1}_${2} testbenchopt -fatal 7 -suppress 3829 @@ -80,6 +86,7 @@ run -all if {$coverage} { + puts "???????????????????????????" echo "Saving coverage to ${1}_${2}.ucdb" do coverage-exclusions-rv64gc.do # beware: this assumes testing the rv64gc configuration coverage save -instance /testbench/dut/core cov/${1}_${2}.ucdb diff --git a/sim/wally-linux-imperas.do b/sim/wally-linux-imperas.do index e9bad30d5..bdaaacfdc 100644 --- a/sim/wally-linux-imperas.do +++ b/sim/wally-linux-imperas.do @@ -32,25 +32,10 @@ vlib work # start and run simulation # remove +acc flag for faster sim during regressions if there is no need to access internal signals -if {$2 eq "buildroot" || $2 eq "buildroot-checkpoint"} { - vlog -lint -work work_${1}_${2} +incdir+../config/$1 +incdir+../config/shared ../src/cvw.sv ../testbench/testbench-linux.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583 - # start and run simulation - vopt work_${1}_${2}.testbench -work work_${1}_${2} -G RISCV_DIR=$3 -G INSTR_LIMIT=$4 -G INSTR_WAVEON=$5 -G CHECKPOINT=$6 -G NO_SPOOFING=0 -o testbenchopt - vsim -lib work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3829,13286 -fatal 7 - - #-- Run the Simulation - #run -all - run 7000 ms - add log -recursive /* - do linux-wave.do - run -all - - exec ./slack-notifier/slack-notifier.py - -} elseif {$2 eq "buildroot-no-trace"} { +if {$2 eq "buildroot"} { vlog -lint -work work_${1}_${2} \ +define+USE_IMPERAS_DV \ - +incdir+../config/$1 \ + +incdir+../config/deriv/$1 \ +incdir+../config/shared \ +incdir+$env(IMPERAS_HOME)/ImpPublic/include/host \ +incdir+$env(IMPERAS_HOME)/ImpProprietary/include/host \ @@ -64,7 +49,7 @@ if {$2 eq "buildroot" || $2 eq "buildroot-checkpoint"} { $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2cov.sv \ $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2bin.sv \ ../src/cvw.sv \ - ../testbench/testbench-linux-imperas.sv \ + ../testbench/testbench.sv \ ../testbench/common/*.sv ../src/*/*.sv \ ../src/*/*/*.sv -suppress 2583 @@ -75,8 +60,8 @@ if {$2 eq "buildroot" || $2 eq "buildroot-checkpoint"} { # vsim -fprofile+perf # visualizer -fprofile+perf+dir=fprofile # - eval vopt +acc work_${1}_${2}.testbench -work work_${1}_${2} -G RISCV_DIR=$3 \ - -G INSTR_LIMIT=0 -G INSTR_WAVEON=0 -G CHECKPOINT=0 -G NO_SPOOFING=1 -o testbenchopt + eval vopt work_${1}_${2}.testbench -work work_${1}_${2} -G RISCV_DIR=$3 \ + -G INSTR_LIMIT=1000000 -G TEST=$2 -G INSTR_WAVEON=0 -G CHECKPOINT=0 -G NO_SPOOFING=1 -o testbenchopt eval vsim -lib work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3829,13286 -fatal 7 \ -sv_lib $env(IMPERAS_HOME)/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model \ $env(OTHERFLAGS) @@ -88,68 +73,12 @@ if {$2 eq "buildroot" || $2 eq "buildroot-checkpoint"} { #run 100 ns #force -deposit testbench/dut/core/priv/priv/csr/csri/IE_REGW 16'h2aa #force -deposit testbench/dut/uncore/uncore/clint/clint/MTIMECMP 64'h1000 - run 9800 ms add log -recursive /testbench/dut/* do wave.do + run 9800 ms run 200 ms #run -all exec ./slack-notifier/slack-notifier.py -} elseif {$2 eq "fpga"} { - echo "hello" - vlog -work work +incdir+../config/fpga +incdir+../config/shared ../src/cvw.sv ../testbench/testbench.sv ../testbench/sdc/*.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv ../../fpga/sim/*.sv -suppress 8852,12070,3084,3829,2583,7063,13286 - vopt +acc work.testbench -G TEST=$2 -G DEBUG=0 -o workopt - vsim workopt +nowarn3829 -fatal 7 - - do fpga-wave.do - add log -r /* - run 20 ms - -} else { - if {$2 eq "ahb"} { - vlog +incdir+../config/$1 +incdir+../config/shared ../src/cvw.sv ../testbench/testbench.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583,13286 -suppress 7063 +define+RAM_LATENCY=$3 +define+BURST_EN=$4 - } else { - # *** modelsim won't take `PA_BITS, but will take other defines for the lengths of DTIM_RANGE and IROM_LEN. For now just live with the warnings. - vlog +incdir+../config/$1 +incdir+../config/shared ../src/cvw.sv ../testbench/testbench.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583,13286 -suppress 7063 - } - vopt +acc work.testbench -G TEST=$2 -G DEBUG=1 -o workopt - - vsim workopt +nowarn3829 -fatal 7 - - view wave - #-- display input and output signals as hexidecimal values - #do ./wave-dos/peripheral-waves.do - add log -recursive /* - do wave.do - #do wave-bus.do - - # power add generates the logging necessary for saif generation. - #power add -r /dut/core/* - #-- Run the Simulation - - run -all - #power off -r /dut/core/* - #power report -all -bsaif power.saif - noview ../testbench/testbench.sv - view wave } - - - -#elseif {$2 eq "buildroot-no-trace""} { -# vlog -lint -work work_${1}_${2} +incdir+../config/$1 +incdir+../config/shared ../testbench/testbench-linux.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583 - # start and run simulation -# vopt +acc work_${1}_${2}.testbench -work work_${1}_${2} -G RISCV_DIR=$3 -G INSTR_LIMIT=470350800 -G INSTR_WAVEON=470350800 -G CHECKPOINT=470350800 -G DEBUG_TRACE=0 -o testbenchopt -# vsim -lib work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3829 - - #-- Run the Simulation -# run 100 ns -# force -deposit testbench/dut/core/priv/priv/csr/csri/IE_REGW 16'h2aa -# force -deposit testbench/dut/uncore/uncore/clint/clint/MTIMECMP 64'h1000 -# add log -recursive /* -# do linux-wave.do -# run -all - -# exec ./slack-notifier/slack-notifier.py -#} diff --git a/testbench/testbench.sv b/testbench/testbench.sv index 3d1836613..80f4115fd 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -29,6 +29,10 @@ `include "tests.vh" `include "BranchPredictorType.vh" +`ifdef USE_IMPERAS_DV + `include "idv/idv.svh" +`endif + import cvw::*; module testbench; @@ -43,6 +47,12 @@ module testbench; parameter RISCV_DIR = "/opt/riscv"; parameter INSTR_LIMIT = 0; + `ifdef USE_IMPERAS_DV + import idvPkg::*; + import rvviApiPkg::*; + import idvApiPkg::*; + `endif + `include "parameter-defs.vh" logic clk; @@ -547,8 +557,165 @@ module testbench; if((Minstret != 0) && (Minstret % 'd100000 == 0)) $display("Reached %d instructions", Minstret); if((Minstret == INSTR_LIMIT) & (INSTR_LIMIT!=0)) begin $stop; $stop; end end +end + + //////////////////////////////////////////////////////////////////////////////// + // ImperasDV Co-simulator hooks + //////////////////////////////////////////////////////////////////////////////// +`ifdef USE_IMPERAS_DV + + rvviTrace #(.XLEN(P.XLEN), .FLEN(P.FLEN)) rvvi(); + wallyTracer #(P) wallyTracer(rvvi); + + trace2log idv_trace2log(rvvi); + // trace2cov idv_trace2cov(rvvi); + + // enabling of comparison types + trace2api #(.CMP_PC (1), + .CMP_INS (1), + .CMP_GPR (1), + .CMP_FPR (1), + .CMP_VR (0), + .CMP_CSR (1) + ) idv_trace2api(rvvi); + + initial begin + int iter; + #1; + IDV_MAX_ERRORS = 3; + + // Initialize REF (do this before initializing the DUT) + if (!rvviVersionCheck(RVVI_API_VERSION)) begin + $display($sformatf("%m @ t=%0t: Expecting RVVI API version %0d.", $time, RVVI_API_VERSION)); + $fatal; + end + + void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_VENDOR, "riscv.ovpworld.org")); + void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_NAME, "riscv")); + void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_VARIANT, "RV64GC")); + void'(rvviRefConfigSetInt(IDV_CONFIG_MODEL_ADDRESS_BUS_WIDTH, 56)); + void'(rvviRefConfigSetInt(IDV_CONFIG_MAX_NET_LATENCY_RETIREMENTS, 6)); + + if (!rvviRefInit("")) begin + $display($sformatf("%m @ t=%0t: rvviRefInit failed", $time)); + $fatal; + end + + // Volatile CSRs + void'(rvviRefCsrSetVolatile(0, 32'hC00)); // CYCLE + void'(rvviRefCsrSetVolatile(0, 32'hB00)); // MCYCLE + void'(rvviRefCsrSetVolatile(0, 32'hC02)); // INSTRET + void'(rvviRefCsrSetVolatile(0, 32'hB02)); // MINSTRET + void'(rvviRefCsrSetVolatile(0, 32'hC01)); // TIME + + // User HPMCOUNTER3 - HPMCOUNTER31 + for (iter='hC03; iter<='hC1F; iter++) begin + void'(rvviRefCsrSetVolatile(0, iter)); // HPMCOUNTERx + end + + // Machine MHPMCOUNTER3 - MHPMCOUNTER31 + for (iter='hB03; iter<='hB1F; iter++) begin + void'(rvviRefCsrSetVolatile(0, iter)); // MHPMCOUNTERx + end + + // cannot predict this register due to latency between + // pending and taken + void'(rvviRefCsrSetVolatile(0, 32'h344)); // MIP + void'(rvviRefCsrSetVolatile(0, 32'h144)); // SIP + + // Privileges for PMA are set in the imperas.ic + // volatile (IO) regions are defined here + // only real ROM/RAM areas are BOOTROM and UNCORE_RAM + if (P.CLINT_SUPPORTED) begin + void'(rvviRefMemorySetVolatile(P.CLINT_BASE, (P.CLINT_BASE + P.CLINT_RANGE))); + end + if (P.GPIO_SUPPORTED) begin + void'(rvviRefMemorySetVolatile(P.GPIO_BASE, (P.GPIO_BASE + P.GPIO_RANGE))); + end + if (P.UART_SUPPORTED) begin + void'(rvviRefMemorySetVolatile(P.UART_BASE, (P.UART_BASE + P.UART_RANGE))); + end + if (P.PLIC_SUPPORTED) begin + void'(rvviRefMemorySetVolatile(P.PLIC_BASE, (P.PLIC_BASE + P.PLIC_RANGE))); + end + if (P.SDC_SUPPORTED) begin + void'(rvviRefMemorySetVolatile(P.SDC_BASE, (P.SDC_BASE + P.SDC_RANGE))); + end + if (P.SPI_SUPPORTED) begin + void'(rvviRefMemorySetVolatile(P.SPI_BASE, (P.SPI_BASE + P.SPI_RANGE))); + end + + if(P.XLEN==32) begin + void'(rvviRefCsrSetVolatile(0, 32'hC80)); // CYCLEH + void'(rvviRefCsrSetVolatile(0, 32'hB80)); // MCYCLEH + void'(rvviRefCsrSetVolatile(0, 32'hC82)); // INSTRETH + void'(rvviRefCsrSetVolatile(0, 32'hB82)); // MINSTRETH + end + + void'(rvviRefCsrSetVolatile(0, 32'h104)); // SIE - Temporary!!!! + + // Load memory + begin + longint x64; + int x32[2]; + longint index; + string memfilenameImperasDV, bootmemfilenameImperasDV; + + memfilenameImperasDV = {RISCV_DIR, "/linux-testvectors/ram.bin"}; + bootmemfilenameImperasDV = {RISCV_DIR, "/linux-testvectors/bootmem.bin"}; + + $display("RVVI Loading bootmem.bin"); + memFile = $fopen(bootmemfilenameImperasDV, "rb"); + index = 'h1000 - 8; + while(!$feof(memFile)) begin + index+=8; + readResult = $fread(x64, memFile); + if (x64 == 0) continue; + x32[0] = x64 & 'hffffffff; + x32[1] = x64 >> 32; + rvviRefMemoryWrite(0, index+0, x32[0], 4); + rvviRefMemoryWrite(0, index+4, x32[1], 4); + //$display("boot %08X x32[0]=%08X x32[1]=%08X", index, x32[0], x32[1]); + end + $fclose(memFile); + + $display("RVVI Loading ram.bin"); + memFile = $fopen(memfilenameImperasDV, "rb"); + index = 'h80000000 - 8; + while(!$feof(memFile)) begin + index+=8; + readResult = $fread(x64, memFile); + if (x64 == 0) continue; + x32[0] = x64 & 'hffffffff; + x32[1] = x64 >> 32; + rvviRefMemoryWrite(0, index+0, x32[0], 4); + rvviRefMemoryWrite(0, index+4, x32[1], 4); + //$display("ram %08X x32[0]=%08X x32[1]=%08X", index, x32[0], x32[1]); + end + $fclose(memFile); + + $display("RVVI Loading Complete"); + + void'(rvviRefPcSet(0, 'h1000)); // set BOOTROM address + end end + always @(dut.core.priv.priv.csr.csri.MIP_REGW[7]) void'(rvvi.net_push("MTimerInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[7])); + always @(dut.core.priv.priv.csr.csri.MIP_REGW[11]) void'(rvvi.net_push("MExternalInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[11])); + always @(dut.core.priv.priv.csr.csri.MIP_REGW[9]) void'(rvvi.net_push("SExternalInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[9])); + always @(dut.core.priv.priv.csr.csri.MIP_REGW[3]) void'(rvvi.net_push("MSWInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[3])); + always @(dut.core.priv.priv.csr.csri.MIP_REGW[1]) void'(rvvi.net_push("SSWInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[1])); + always @(dut.core.priv.priv.csr.csri.MIP_REGW[5]) void'(rvvi.net_push("STimerInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[5])); + + final begin + void'(rvviRefShutdown()); + end + +`endif + //////////////////////////////////////////////////////////////////////////////// + // END of ImperasDV Co-simulator hooks + //////////////////////////////////////////////////////////////////////////////// + task automatic CheckSignature; // This task must be declared inside this module as it needs access to parameter P. There is // no way to pass P to the task unless we convert it to a module.