mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
This is crazy. I'm merging testbench.sv into testbench-imperas.sv to find the point when it stops working. But each logical point where it would stop working it keeps working. For example moving readmemh from initial to always block.
This commit is contained in:
parent
a885240fbd
commit
d9807bb909
@ -26,59 +26,66 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "config.vh"
|
||||
|
||||
|
||||
// This is set from the command line script
|
||||
// `define USE_IMPERAS_DV
|
||||
`include "tests.vh"
|
||||
`include "BranchPredictorType.vh"
|
||||
|
||||
`ifdef USE_IMPERAS_DV
|
||||
`include "idv/idv.svh"
|
||||
`endif
|
||||
|
||||
|
||||
import cvw::*;
|
||||
|
||||
module testbench;
|
||||
/* verilator lint_off WIDTHTRUNC */
|
||||
/* verilator lint_off WIDTHEXPAND */
|
||||
parameter DEBUG=0;
|
||||
parameter PrintHPMCounters=0;
|
||||
parameter BPRED_LOGGER=0;
|
||||
parameter I_CACHE_ADDR_LOGGER=0;
|
||||
parameter D_CACHE_ADDR_LOGGER=0;
|
||||
|
||||
`ifdef USE_IMPERAS_DV
|
||||
import idvPkg::*;
|
||||
import rvviApiPkg::*;
|
||||
import idvApiPkg::*;
|
||||
`endif
|
||||
`ifdef USE_IMPERAS_DV
|
||||
import idvPkg::*;
|
||||
import rvviApiPkg::*;
|
||||
import idvApiPkg::*;
|
||||
`endif
|
||||
|
||||
`ifdef VERILATOR
|
||||
import "DPI-C" function string getenvval(input string env_name);
|
||||
string RISCV_DIR = getenvval("RISCV"); // "/opt/riscv";
|
||||
`elsif SIM_VCS
|
||||
import "DPI-C" function string getenv(input string env_name);
|
||||
string RISCV_DIR = getenv("RISCV"); // "/opt/riscv";
|
||||
`else
|
||||
string RISCV_DIR = "$RISCV"; // "/opt/riscv";
|
||||
`endif
|
||||
|
||||
`include "parameter-defs.vh"
|
||||
|
||||
logic clk;
|
||||
logic reset_ext, reset;
|
||||
logic ResetMem;
|
||||
|
||||
// Variables that can be overwritten with $value$plusargs at start of simulation
|
||||
string TEST;
|
||||
string ElfFile;
|
||||
integer INSTR_LIMIT;
|
||||
|
||||
logic [P.XLEN-1:0] testadr, testadrNoBase;
|
||||
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
|
||||
logic [31:0] InstrW;
|
||||
|
||||
logic [3:0] dummy;
|
||||
|
||||
logic [P.AHBW-1:0] HRDATAEXT;
|
||||
logic HREADYEXT, HRESPEXT;
|
||||
logic HSELEXTSDC;
|
||||
// DUT signals
|
||||
logic [P.AHBW-1:0] HRDATAEXT;
|
||||
logic HREADYEXT, HRESPEXT;
|
||||
logic HSELEXTSDC;
|
||||
logic [P.PA_BITS-1:0] HADDR;
|
||||
logic [P.AHBW-1:0] HWDATA;
|
||||
logic [P.XLEN/8-1:0] HWSTRB;
|
||||
logic HWRITE;
|
||||
logic [2:0] HSIZE;
|
||||
logic [2:0] HBURST;
|
||||
logic [3:0] HPROT;
|
||||
logic [1:0] HTRANS;
|
||||
logic HMASTLOCK;
|
||||
logic HCLK, HRESETn;
|
||||
logic [P.XLEN-1:0] PCW;
|
||||
logic [31:0] NextInstrE, InstrM;
|
||||
|
||||
string ProgramAddrMapFile, ProgramLabelMapFile;
|
||||
integer ProgramAddrLabelArray [string] = '{ "begin_signature" : 0, "tohost" : 0 };
|
||||
logic DCacheFlushDone, DCacheFlushStart;
|
||||
string testName;
|
||||
string memfilename, testDir, adrstr, elffilename;
|
||||
logic [P.AHBW-1:0] HWDATA;
|
||||
logic [P.XLEN/8-1:0] HWSTRB;
|
||||
logic HWRITE;
|
||||
logic [2:0] HSIZE;
|
||||
logic [2:0] HBURST;
|
||||
logic [3:0] HPROT;
|
||||
logic [1:0] HTRANS;
|
||||
logic HMASTLOCK;
|
||||
logic HCLK, HRESETn;
|
||||
|
||||
logic [31:0] GPIOIN, GPIOOUT, GPIOEN;
|
||||
logic UARTSin, UARTSout;
|
||||
@ -88,10 +95,275 @@ module testbench;
|
||||
|
||||
logic HREADY;
|
||||
logic HSELEXT;
|
||||
|
||||
string ProgramAddrMapFile, ProgramLabelMapFile;
|
||||
integer ProgramAddrLabelArray [string];
|
||||
|
||||
int test, i, errors, totalerrors;
|
||||
|
||||
string outputfile;
|
||||
integer outputFilePointer;
|
||||
|
||||
string tests[];
|
||||
logic DCacheFlushDone, DCacheFlushStart;
|
||||
logic riscofTest;
|
||||
logic Validate;
|
||||
logic SelectTest;
|
||||
logic TestComplete;
|
||||
|
||||
initial begin
|
||||
// look for arguments passed to simulation, or use defaults
|
||||
if (!$value$plusargs("TEST=%s", TEST))
|
||||
TEST = "none";
|
||||
if (!$value$plusargs("ElfFile=%s", ElfFile))
|
||||
ElfFile = "none";
|
||||
else begin
|
||||
end
|
||||
if (!$value$plusargs("INSTR_LIMIT=%d", INSTR_LIMIT))
|
||||
INSTR_LIMIT = 0;
|
||||
ElfFile = "/home/rose/repos/active/cvw2/cvw/tests/riscof/work/riscv-arch-test/rv64i_m/I/src/add-01.S/ref/ref.elf";
|
||||
|
||||
// pick tests based on modes supported
|
||||
//tests = '{};
|
||||
if (P.XLEN == 64) begin // RV64
|
||||
case (TEST)
|
||||
"arch64i": tests = arch64i;
|
||||
"arch64priv": tests = arch64priv;
|
||||
"arch64c": if (P.C_SUPPORTED)
|
||||
if (P.ZICSR_SUPPORTED) tests = {arch64c, arch64cpriv};
|
||||
else tests = {arch64c};
|
||||
"arch64m": if (P.M_SUPPORTED) tests = arch64m;
|
||||
"arch64a_amo": if (P.A_SUPPORTED | P.ZAAMO_SUPPORTED) tests = arch64a_amo;
|
||||
"arch64f": if (P.F_SUPPORTED) tests = arch64f;
|
||||
"arch64d": if (P.D_SUPPORTED) tests = arch64d;
|
||||
"arch64f_fma": if (P.F_SUPPORTED) tests = arch64f_fma;
|
||||
"arch64d_fma": if (P.D_SUPPORTED) tests = arch64d_fma;
|
||||
"arch64f_divsqrt": if (P.F_SUPPORTED) tests = arch64f_divsqrt;
|
||||
"arch64d_divsqrt": if (P.D_SUPPORTED) tests = arch64d_divsqrt;
|
||||
"arch64zifencei": if (P.ZIFENCEI_SUPPORTED) tests = arch64zifencei;
|
||||
"arch64zicond": if (P.ZICOND_SUPPORTED) tests = arch64zicond;
|
||||
"imperas64i": tests = imperas64i;
|
||||
"imperas64f": if (P.F_SUPPORTED) tests = imperas64f;
|
||||
"imperas64d": if (P.D_SUPPORTED) tests = imperas64d;
|
||||
"imperas64m": if (P.M_SUPPORTED) tests = imperas64m;
|
||||
"wally64q": if (P.Q_SUPPORTED) tests = wally64q;
|
||||
"wally64a_lrsc": if (P.A_SUPPORTED | P.ZALRSC_SUPPORTED) tests = wally64a_lrsc;
|
||||
"imperas64c": if (P.C_SUPPORTED) tests = imperas64c;
|
||||
else tests = imperas64iNOc;
|
||||
"custom": tests = custom;
|
||||
"wally64i": tests = wally64i;
|
||||
"wally64priv": tests = wally64priv;
|
||||
"wally64periph": tests = wally64periph;
|
||||
"coremark": tests = coremark;
|
||||
"fpga": tests = fpga;
|
||||
"ahb64" : tests = ahb64;
|
||||
"coverage64gc" : tests = coverage64gc;
|
||||
"arch64zba": if (P.ZBA_SUPPORTED) tests = arch64zba;
|
||||
"arch64zbb": if (P.ZBB_SUPPORTED) tests = arch64zbb;
|
||||
"arch64zbc": if (P.ZBC_SUPPORTED) tests = arch64zbc;
|
||||
"arch64zbs": if (P.ZBS_SUPPORTED) tests = arch64zbs;
|
||||
"arch64zicboz": if (P.ZICBOZ_SUPPORTED) tests = arch64zicboz;
|
||||
"arch64zcb": if (P.ZCB_SUPPORTED) tests = arch64zcb;
|
||||
"arch64zfh": if (P.ZFH_SUPPORTED) tests = arch64zfh;
|
||||
"arch64zfh_fma": if (P.ZFH_SUPPORTED) tests = arch64zfh_fma;
|
||||
"arch64zfh_divsqrt": if (P.ZFH_SUPPORTED) tests = arch64zfh_divsqrt;
|
||||
"arch64zfaf": if (P.ZFA_SUPPORTED) tests = arch64zfaf;
|
||||
"arch64zfad": if (P.ZFA_SUPPORTED & P.D_SUPPORTED) tests = arch64zfad;
|
||||
"buildroot": tests = buildroot;
|
||||
"arch64zbkb": if (P.ZBKB_SUPPORTED) tests = arch64zbkb;
|
||||
"arch64zbkc": if (P.ZBKC_SUPPORTED) tests = arch64zbkc;
|
||||
"arch64zbkx": if (P.ZBKX_SUPPORTED) tests = arch64zbkx;
|
||||
"arch64zknd": if (P.ZKND_SUPPORTED) tests = arch64zknd;
|
||||
"arch64zkne": if (P.ZKNE_SUPPORTED) tests = arch64zkne;
|
||||
"arch64zknh": if (P.ZKNH_SUPPORTED) tests = arch64zknh;
|
||||
endcase
|
||||
end else begin // RV32
|
||||
case (TEST)
|
||||
"arch32e": tests = arch32e;
|
||||
"arch32i": tests = arch32i;
|
||||
"arch32priv": tests = arch32priv;
|
||||
"arch32c": if (P.C_SUPPORTED)
|
||||
if (P.ZICSR_SUPPORTED) tests = {arch32c, arch32cpriv};
|
||||
else tests = {arch32c};
|
||||
"arch32m": if (P.M_SUPPORTED) tests = arch32m;
|
||||
"arch32a_amo": if (P.A_SUPPORTED | P.ZAAMO_SUPPORTED) tests = arch32a_amo;
|
||||
"arch32f": if (P.F_SUPPORTED) tests = arch32f;
|
||||
"arch32d": if (P.D_SUPPORTED) tests = arch32d;
|
||||
"arch32f_fma": if (P.F_SUPPORTED) tests = arch32f_fma;
|
||||
"arch32d_fma": if (P.D_SUPPORTED) tests = arch32d_fma;
|
||||
"arch32f_divsqrt": if (P.F_SUPPORTED) tests = arch32f_divsqrt;
|
||||
"arch32d_divsqrt": if (P.D_SUPPORTED) tests = arch32d_divsqrt;
|
||||
"arch32zifencei": if (P.ZIFENCEI_SUPPORTED) tests = arch32zifencei;
|
||||
"arch32zicond": if (P.ZICOND_SUPPORTED) tests = arch32zicond;
|
||||
"imperas32i": tests = imperas32i;
|
||||
"imperas32f": if (P.F_SUPPORTED) tests = imperas32f;
|
||||
"imperas32m": if (P.M_SUPPORTED) tests = imperas32m;
|
||||
"wally32a_lrsc": if (P.A_SUPPORTED | P.ZALRSC_SUPPORTED) tests = wally32a_lrsc;
|
||||
"imperas32c": if (P.C_SUPPORTED) tests = imperas32c;
|
||||
else tests = imperas32iNOc;
|
||||
"wally32i": tests = wally32i;
|
||||
"wally32priv": tests = wally32priv;
|
||||
"wally32periph": tests = wally32periph;
|
||||
"ahb32" : tests = ahb32;
|
||||
"embench": tests = embench;
|
||||
"coremark": tests = coremark;
|
||||
"arch32zba": if (P.ZBA_SUPPORTED) tests = arch32zba;
|
||||
"arch32zbb": if (P.ZBB_SUPPORTED) tests = arch32zbb;
|
||||
"arch32zbc": if (P.ZBC_SUPPORTED) tests = arch32zbc;
|
||||
"arch32zbs": if (P.ZBS_SUPPORTED) tests = arch32zbs;
|
||||
"arch32zicboz": if (P.ZICBOZ_SUPPORTED) tests = arch32zicboz;
|
||||
"arch32zcb": if (P.ZCB_SUPPORTED) tests = arch32zcb;
|
||||
"arch32zfh": if (P.ZFH_SUPPORTED) tests = arch32zfh;
|
||||
"arch32zfh_fma": if (P.ZFH_SUPPORTED) tests = arch32zfh_fma;
|
||||
"arch32zfh_divsqrt": if (P.ZFH_SUPPORTED) tests = arch32zfh_divsqrt;
|
||||
"arch32zfaf": if (P.ZFA_SUPPORTED) tests = arch32zfaf;
|
||||
"arch32zfad": if (P.ZFA_SUPPORTED & P.D_SUPPORTED) tests = arch32zfad;
|
||||
"arch32zbkb": if (P.ZBKB_SUPPORTED) tests = arch32zbkb;
|
||||
"arch32zbkc": if (P.ZBKC_SUPPORTED) tests = arch32zbkc;
|
||||
"arch32zbkx": if (P.ZBKX_SUPPORTED) tests = arch32zbkx;
|
||||
"arch32zknd": if (P.ZKND_SUPPORTED) tests = arch32zknd;
|
||||
"arch32zkne": if (P.ZKNE_SUPPORTED) tests = arch32zkne;
|
||||
"arch32zknh": if (P.ZKNH_SUPPORTED) tests = arch32zknh;
|
||||
endcase
|
||||
end
|
||||
if (tests.size() == 0 & ElfFile == "none") begin
|
||||
if (tests.size() == 0) begin
|
||||
$display("TEST %s not supported in this configuration", TEST);
|
||||
end else if(ElfFile == "none") begin
|
||||
$display("ElfFile %s not found", ElfFile);
|
||||
end
|
||||
$finish;
|
||||
end
|
||||
`ifdef MAKEVCD
|
||||
$dumpfile("testbench.vcd");
|
||||
$dumpvars;
|
||||
`endif
|
||||
end // initial begin
|
||||
|
||||
typedef enum logic [3:0]{STATE_TESTBENCH_RESET,
|
||||
STATE_INIT_TEST,
|
||||
STATE_RESET_MEMORIES,
|
||||
STATE_RESET_MEMORIES2,
|
||||
STATE_LOAD_MEMORIES,
|
||||
STATE_RESET_TEST,
|
||||
STATE_RUN_TEST,
|
||||
STATE_COPY_RAM,
|
||||
STATE_CHECK_TEST,
|
||||
STATE_CHECK_TEST_WAIT,
|
||||
STATE_VALIDATE,
|
||||
STATE_INCR_TEST} statetype;
|
||||
statetype CurrState, NextState;
|
||||
logic TestBenchReset;
|
||||
logic [2:0] ResetCountNew, ResetThresholdNew;
|
||||
logic LoadMem;
|
||||
logic ResetCntEn;
|
||||
logic ResetCntRst;
|
||||
logic CopyRAM;
|
||||
|
||||
string signame, bootmemfilename, uartoutfilename, pathname;
|
||||
integer begin_signature_addr, end_signature_addr, signature_size;
|
||||
integer uartoutfile;
|
||||
logic reset_extNew;
|
||||
logic DCacheFlushStartNew;
|
||||
|
||||
|
||||
logic [P.XLEN-1:0] testadr, testadrNoBase;
|
||||
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
|
||||
logic [31:0] InstrW;
|
||||
|
||||
|
||||
|
||||
logic [P.XLEN-1:0] PCW;
|
||||
logic [31:0] NextInstrE, InstrM;
|
||||
|
||||
string testName;
|
||||
string memfilename, testDir, adrstr, elffilename;
|
||||
|
||||
|
||||
logic InitializingMemories;
|
||||
integer ResetCount, ResetThreshold;
|
||||
logic InReset;
|
||||
integer memFile;
|
||||
integer readResult;
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// load memories with program image
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
integer ShadowIndex;
|
||||
integer LogXLEN;
|
||||
integer StartIndex;
|
||||
integer EndIndex;
|
||||
integer BaseIndex;
|
||||
if (P.SDC_SUPPORTED) begin
|
||||
always @(posedge clk) begin
|
||||
if (LoadMem) begin
|
||||
string romfilename, sdcfilename;
|
||||
romfilename = {"../tests/custom/fpga-test-sdc/bin/fpga-test-sdc.memfile"};
|
||||
sdcfilename = {"../testbench/sdc/ramdisk2.hex"};
|
||||
//$readmemh(romfilename, dut.uncoregen.uncore.bootrom.bootrom.memory.ROM);
|
||||
//$readmemh(sdcfilename, sdcard.sdcard.FLASHmem);
|
||||
// shorten sdc timers for simulation
|
||||
//dut.uncoregen.uncore.sdc.SDC.LimitTimers = 1;
|
||||
end
|
||||
end
|
||||
end else if (P.IROM_SUPPORTED) begin
|
||||
always @(posedge clk) begin
|
||||
if (LoadMem) begin
|
||||
$readmemh(memfilename, dut.core.ifu.irom.irom.rom.ROM);
|
||||
end
|
||||
end
|
||||
end else if (P.BUS_SUPPORTED) begin : bus_supported
|
||||
always @(posedge clk) begin
|
||||
if (LoadMem) begin
|
||||
if (TEST == "buildroot") begin
|
||||
memFile = $fopen(bootmemfilename, "rb");
|
||||
readResult = $fread(dut.uncoregen.uncore.bootrom.bootrom.memory.ROM, memFile);
|
||||
$fclose(memFile);
|
||||
memFile = $fopen(memfilename, "rb");
|
||||
readResult = $fread(dut.uncoregen.uncore.ram.ram.memory.RAM, memFile);
|
||||
$fclose(memFile);
|
||||
end else
|
||||
$readmemh(memfilename, dut.uncoregen.uncore.ram.ram.memory.RAM);
|
||||
if (TEST == "embench") $display("Read memfile %s", memfilename);
|
||||
end
|
||||
if (CopyRAM) begin
|
||||
LogXLEN = (1 + P.XLEN/32); // 2 for rv32 and 3 for rv64
|
||||
StartIndex = begin_signature_addr >> LogXLEN;
|
||||
EndIndex = (end_signature_addr >> LogXLEN) + 8;
|
||||
BaseIndex = P.UNCORE_RAM_BASE >> LogXLEN;
|
||||
for(ShadowIndex = StartIndex; ShadowIndex <= EndIndex; ShadowIndex++) begin
|
||||
testbench.DCacheFlushFSM.ShadowRAM[ShadowIndex] = dut.uncoregen.uncore.ram.ram.memory.RAM[ShadowIndex - BaseIndex];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if (P.DTIM_SUPPORTED) begin
|
||||
always @(posedge clk) begin
|
||||
if (LoadMem) begin
|
||||
$readmemh(memfilename, dut.core.lsu.dtim.dtim.ram.RAM);
|
||||
$display("Read memfile %s", memfilename);
|
||||
end
|
||||
if (CopyRAM) begin
|
||||
LogXLEN = (1 + P.XLEN/32); // 2 for rv32 and 3 for rv64
|
||||
StartIndex = begin_signature_addr >> LogXLEN;
|
||||
EndIndex = (end_signature_addr >> LogXLEN) + 8;
|
||||
BaseIndex = P.UNCORE_RAM_BASE >> LogXLEN;
|
||||
for(ShadowIndex = StartIndex; ShadowIndex <= EndIndex; ShadowIndex++) begin
|
||||
testbench.DCacheFlushFSM.ShadowRAM[ShadowIndex] = dut.core.lsu.dtim.dtim.ram.RAM[ShadowIndex - BaseIndex];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
integer adrindex;
|
||||
if (P.UNCORE_RAM_SUPPORTED)
|
||||
always @(posedge clk)
|
||||
if (ResetMem) // program memory is sometimes reset (e.g. for CoreMark, which needs zeroed memory)
|
||||
for (adrindex=0; adrindex<(P.UNCORE_RAM_RANGE>>1+(P.XLEN/32)); adrindex = adrindex+1)
|
||||
dut.uncoregen.uncore.ram.ram.memory.RAM[adrindex] = '0;
|
||||
|
||||
// Imperas look here.
|
||||
initial
|
||||
@ -110,8 +382,7 @@ module testbench;
|
||||
$error("Must specify test directory using plusarg testDir");
|
||||
end
|
||||
|
||||
if (P.BUS_SUPPORTED) $readmemh(memfilename, dut.uncoregen.uncore.ram.ram.memory.RAM);
|
||||
else $error("Imperas test bench requires BUS.");
|
||||
#130;
|
||||
|
||||
ProgramAddrMapFile = {testDir, "/ref/ref.elf.objdump.addr"};
|
||||
ProgramLabelMapFile = {testDir, "/ref/ref.elf.objdump.lab"};
|
||||
@ -123,98 +394,224 @@ module testbench;
|
||||
|
||||
end
|
||||
|
||||
// Model the testbench as an fsm.
|
||||
// Do this in parts so it easier to verify
|
||||
// part 1: build a version which echos the same behavior as the below code, but does not drive anything
|
||||
// part 2: drive some of the controls
|
||||
// part 3: drive all logic and remove old inital and always @ negedge clk block
|
||||
|
||||
|
||||
assign ResetThresholdNew = 3'd5;
|
||||
|
||||
initial begin
|
||||
TestBenchReset = 1'b1;
|
||||
# 100;
|
||||
TestBenchReset = 1'b0;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk)
|
||||
if (TestBenchReset) CurrState <= STATE_TESTBENCH_RESET;
|
||||
else CurrState <= NextState;
|
||||
|
||||
// fsm next state logic
|
||||
always_comb begin
|
||||
// riscof tests have a different signature, tests[0] == "1" refers to RiscvArchTests
|
||||
// and tests[0] == "2" refers to WallyRiscvArchTests
|
||||
//pathname = tvpaths[tests[0].atoi()];
|
||||
|
||||
case(CurrState)
|
||||
STATE_TESTBENCH_RESET: NextState = STATE_INIT_TEST;
|
||||
STATE_INIT_TEST: NextState = STATE_RESET_MEMORIES;
|
||||
STATE_RESET_MEMORIES: NextState = STATE_RESET_MEMORIES2;
|
||||
STATE_RESET_MEMORIES2: NextState = STATE_LOAD_MEMORIES; // Give the reset enough time to ensure the bus is reset before loading the memories.
|
||||
STATE_LOAD_MEMORIES: NextState = STATE_RESET_TEST;
|
||||
STATE_RESET_TEST: if(ResetCountNew < ResetThresholdNew) NextState = STATE_RESET_TEST;
|
||||
else NextState = STATE_RUN_TEST;
|
||||
STATE_RUN_TEST: if(TestComplete) NextState = STATE_COPY_RAM;
|
||||
else NextState = STATE_RUN_TEST;
|
||||
STATE_COPY_RAM: NextState = STATE_CHECK_TEST;
|
||||
STATE_CHECK_TEST: if (DCacheFlushDone) NextState = STATE_VALIDATE;
|
||||
else NextState = STATE_CHECK_TEST_WAIT;
|
||||
STATE_CHECK_TEST_WAIT: if(DCacheFlushDone) NextState = STATE_VALIDATE;
|
||||
else NextState = STATE_CHECK_TEST_WAIT;
|
||||
STATE_VALIDATE: NextState = STATE_INIT_TEST;
|
||||
STATE_INCR_TEST: NextState = STATE_INIT_TEST;
|
||||
default: NextState = STATE_TESTBENCH_RESET;
|
||||
endcase
|
||||
end // always_comb
|
||||
// fsm output control logic
|
||||
assign reset_extNew = CurrState == STATE_TESTBENCH_RESET | CurrState == STATE_INIT_TEST |
|
||||
CurrState == STATE_RESET_MEMORIES | CurrState == STATE_RESET_MEMORIES2 |
|
||||
CurrState == STATE_LOAD_MEMORIES | CurrState ==STATE_RESET_TEST;
|
||||
// this initialization is very expensive, only do it for coremark.
|
||||
assign ResetMem = (CurrState == STATE_RESET_MEMORIES | CurrState == STATE_RESET_MEMORIES2);
|
||||
assign LoadMem = CurrState == STATE_LOAD_MEMORIES;
|
||||
assign ResetCntRst = CurrState == STATE_INIT_TEST;
|
||||
assign ResetCntEn = CurrState == STATE_RESET_TEST;
|
||||
assign Validate = CurrState == STATE_VALIDATE;
|
||||
assign SelectTest = CurrState == STATE_INIT_TEST;
|
||||
assign CopyRAM = TestComplete & CurrState == STATE_RUN_TEST;
|
||||
assign DCacheFlushStartNew = CurrState == STATE_COPY_RAM;
|
||||
|
||||
// fsm reset counter
|
||||
counter #(3) RstCounter(clk, ResetCntRst, ResetCntEn, ResetCountNew);
|
||||
|
||||
|
||||
`ifdef USE_IMPERAS_DV
|
||||
|
||||
rvviTrace #(.XLEN(P.XLEN), .FLEN(P.FLEN)) rvvi();
|
||||
wallyTracer #(P) wallyTracer(rvvi);
|
||||
rvviTrace #(.XLEN(P.XLEN), .FLEN(P.FLEN)) rvvi();
|
||||
wallyTracer #(P) wallyTracer(rvvi);
|
||||
|
||||
trace2log idv_trace2log(rvvi);
|
||||
trace2cov idv_trace2cov(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);
|
||||
// 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
|
||||
|
||||
IDV_MAX_ERRORS = 3;
|
||||
string filename;
|
||||
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, 39));
|
||||
void'(rvviRefConfigSetInt(IDV_CONFIG_MAX_NET_LATENCY_RETIREMENTS, 6));
|
||||
// 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(elffilename)) 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
|
||||
|
||||
// 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!!!!
|
||||
|
||||
if(elffilename == "buildroot") filename = "";
|
||||
else filename = elffilename;
|
||||
|
||||
if (!rvviRefInit(filename)) begin
|
||||
$display($sformatf("%m @ t=%0t: rvviRefInit failed", $time));
|
||||
$fatal;
|
||||
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]));
|
||||
// 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
|
||||
|
||||
final begin
|
||||
void'(rvviRefShutdown());
|
||||
// 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
|
||||
// *** RT: This section can probably be moved into the same chunk of code which
|
||||
// loads the memories. However I'm not sure that ImperasDV supports reloading
|
||||
// the memories without relaunching the simulator.
|
||||
if(elffilename == "buildroot") 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, P.RESET_VECTOR)); // 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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user