testbench code visual improvements

This commit is contained in:
Limnanthes Serafini 2023-04-13 19:06:09 -07:00
parent 38349e6a4f
commit 0862688168

View File

@ -52,29 +52,29 @@ module testbench;
string tests[]; string tests[];
logic [3:0] dummy; logic [3:0] dummy;
logic [`AHBW-1:0] HRDATAEXT; logic [`AHBW-1:0] HRDATAEXT;
logic HREADYEXT, HRESPEXT; logic HREADYEXT, HRESPEXT;
logic [`PA_BITS-1:0] HADDR; logic [`PA_BITS-1:0] HADDR;
logic [`AHBW-1:0] HWDATA; logic [`AHBW-1:0] HWDATA;
logic [`XLEN/8-1:0] HWSTRB; logic [`XLEN/8-1:0] HWSTRB;
logic HWRITE; logic HWRITE;
logic [2:0] HSIZE; logic [2:0] HSIZE;
logic [2:0] HBURST; logic [2:0] HBURST;
logic [3:0] HPROT; logic [3:0] HPROT;
logic [1:0] HTRANS; logic [1:0] HTRANS;
logic HMASTLOCK; logic HMASTLOCK;
logic HCLK, HRESETn; logic HCLK, HRESETn;
logic [`XLEN-1:0] PCW; logic [`XLEN-1:0] PCW;
string ProgramAddrMapFile, ProgramLabelMapFile; string ProgramAddrMapFile, ProgramLabelMapFile;
integer ProgramAddrLabelArray [string] = '{ "begin_signature" : 0, "tohost" : 0 }; integer ProgramAddrLabelArray [string] = '{ "begin_signature" : 0, "tohost" : 0 };
logic DCacheFlushDone, DCacheFlushStart; logic DCacheFlushDone, DCacheFlushStart;
logic riscofTest; logic riscofTest;
logic StartSample, EndSample; logic StartSample, EndSample;
flopenr #(`XLEN) PCWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.PCM, PCW); flopenr #(`XLEN) PCWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.PCM, PCW);
flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.InstrM, InstrW); flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.InstrM, InstrW);
// check assertions for a legal configuration // check assertions for a legal configuration
riscvassertions riscvassertions(); riscvassertions riscvassertions();
@ -149,7 +149,7 @@ module testbench;
end end
end end
string signame, memfilename, pathname, objdumpfilename, adrstr, outputfile; string signame, memfilename, pathname, objdumpfilename, adrstr, outputfile;
integer outputFilePointer; integer outputFilePointer;
logic [31:0] GPIOIN, GPIOOUT, GPIOEN; logic [31:0] GPIOIN, GPIOOUT, GPIOEN;
@ -160,16 +160,16 @@ module testbench;
logic SDCCmdOut; logic SDCCmdOut;
logic SDCCmdOE; logic SDCCmdOE;
logic [3:0] SDCDatIn; logic [3:0] SDCDatIn;
tri1 [3:0] SDCDat; tri1 [3:0] SDCDat;
tri1 SDCCmd; tri1 SDCCmd;
logic HREADY; logic HREADY;
logic HSELEXT; logic HSELEXT;
logic InitializingMemories; logic InitializingMemories;
integer ResetCount, ResetThreshold; integer ResetCount, ResetThreshold;
logic InReset; logic InReset;
logic Begin; logic BeginSample;
// instantiate device to be tested // instantiate device to be tested
assign GPIOIN = 0; assign GPIOIN = 0;
@ -225,13 +225,14 @@ module testbench;
totalerrors = 0; totalerrors = 0;
testadr = 0; testadr = 0;
testadrNoBase = 0; testadrNoBase = 0;
// riscof tests have a different signature, tests[0] == "1" refers to RiscvArchTests and tests[0] == "2" refers to WallyRiscvArchTests // riscof tests have a different signature, tests[0] == "1" refers to RiscvArchTests
// and tests[0] == "2" refers to WallyRiscvArchTests
riscofTest = tests[0] == "1" | tests[0] == "2"; riscofTest = tests[0] == "1" | tests[0] == "2";
// fill memory with defined values to reduce Xs in simulation // fill memory with defined values to reduce Xs in simulation
// Quick note the memory will need to be initialized. The C library does not // Quick note the memory will need to be initialized. The C library does not
// guarantee the initialized reads. For example a strcmp can read 6 byte // guarantee the initialized reads. For example a strcmp can read 6 byte
// strings, but uses a load double to read them in. If the last 2 bytes are // strings, but uses a load double to read them in. If the last 2 bytes are
// not initialized the compare results in an 'x' which propagates through // not initialized the compare results in an 'x' which propagates through
// the design. // the design.
if (TEST == "coremark") if (TEST == "coremark")
for (i=MemStartAddr; i<MemEndAddr; i = i+1) for (i=MemStartAddr; i<MemEndAddr; i = i+1)
@ -243,7 +244,7 @@ module testbench;
pathname = tvpaths[0]; pathname = tvpaths[0];
else pathname = tvpaths[1]; */ else pathname = tvpaths[1]; */
if (riscofTest) memfilename = {pathname, tests[test], "/ref/ref.elf.memfile"}; if (riscofTest) memfilename = {pathname, tests[test], "/ref/ref.elf.memfile"};
else memfilename = {pathname, tests[test], ".elf.memfile"}; else memfilename = {pathname, tests[test], ".elf.memfile"};
if (`FPGA) begin if (`FPGA) begin
string romfilename, sdcfilename; string romfilename, sdcfilename;
romfilename = {"../tests/custom/fpga-test-sdc/bin/fpga-test-sdc.memfile"}; romfilename = {"../tests/custom/fpga-test-sdc/bin/fpga-test-sdc.memfile"};
@ -253,9 +254,9 @@ module testbench;
// force sdc timers // force sdc timers
force dut.uncore.uncore.sdc.SDC.LimitTimers = 1; force dut.uncore.uncore.sdc.SDC.LimitTimers = 1;
end else begin end else begin
if (`IROM_SUPPORTED) $readmemh(memfilename, dut.core.ifu.irom.irom.rom.ROM); if (`IROM_SUPPORTED) $readmemh(memfilename, dut.core.ifu.irom.irom.rom.ROM);
else if (`BUS_SUPPORTED) $readmemh(memfilename, dut.uncore.uncore.ram.ram.memory.RAM); else if (`BUS_SUPPORTED) $readmemh(memfilename, dut.uncore.uncore.ram.ram.memory.RAM);
if (`DTIM_SUPPORTED) $readmemh(memfilename, dut.core.lsu.dtim.dtim.ram.RAM); if (`DTIM_SUPPORTED) $readmemh(memfilename, dut.core.lsu.dtim.dtim.ram.RAM);
end end
if (riscofTest) begin if (riscofTest) begin
@ -265,8 +266,9 @@ module testbench;
ProgramAddrMapFile = {pathname, tests[test], ".elf.objdump.addr"}; ProgramAddrMapFile = {pathname, tests[test], ".elf.objdump.addr"};
ProgramLabelMapFile = {pathname, tests[test], ".elf.objdump.lab"}; ProgramLabelMapFile = {pathname, tests[test], ".elf.objdump.lab"};
end end
// declare memory labels that interest us, the updateProgramAddrLabelArray task will find the addr of each label and fill the array // declare memory labels that interest us, the updateProgramAddrLabelArray task will find
// to expand, add more elements to this array and initialize them to zero (also initilaize them to zero at the start of the next test) // the addr of each label and fill the array. To expand, add more elements to this array
// and initialize them to zero (also initilaize them to zero at the start of the next test)
if(!`FPGA) begin if(!`FPGA) begin
updateProgramAddrLabelArray(ProgramAddrMapFile, ProgramLabelMapFile, ProgramAddrLabelArray); updateProgramAddrLabelArray(ProgramAddrMapFile, ProgramLabelMapFile, ProgramAddrLabelArray);
$display("Read memfile %s", memfilename); $display("Read memfile %s", memfilename);
@ -294,99 +296,99 @@ module testbench;
ResetCount = 0; ResetCount = 0;
end end
end else begin end else begin
if (TEST == "coremark") if (TEST == "coremark")
if (dut.core.priv.priv.EcallFaultM) begin if (dut.core.priv.priv.EcallFaultM) begin
$display("Benchmark: coremark is done."); $display("Benchmark: coremark is done.");
$stop; $stop;
end end
// Termination condition (i.e. we finished running current test) // Termination condition (i.e. we finished running current test)
if (DCacheFlushDone) begin if (DCacheFlushDone) begin
integer begin_signature_addr; integer begin_signature_addr;
InReset = 1; InReset = 1;
begin_signature_addr = ProgramAddrLabelArray["begin_signature"]; begin_signature_addr = ProgramAddrLabelArray["begin_signature"];
if (!begin_signature_addr) if (!begin_signature_addr)
$display("begin_signature addr not found in %s", ProgramLabelMapFile); $display("begin_signature addr not found in %s", ProgramLabelMapFile);
testadr = ($unsigned(begin_signature_addr))/(`XLEN/8); testadr = ($unsigned(begin_signature_addr))/(`XLEN/8);
testadrNoBase = (begin_signature_addr - `UNCORE_RAM_BASE)/(`XLEN/8); testadrNoBase = (begin_signature_addr - `UNCORE_RAM_BASE)/(`XLEN/8);
#600; // give time for instructions in pipeline to finish #600; // give time for instructions in pipeline to finish
if (TEST == "embench") begin if (TEST == "embench") begin
// Writes contents of begin_signature to .sim.output file // Writes contents of begin_signature to .sim.output file
// this contains instret and cycles for start and end of test run, used by embench python speed script to calculate embench speed score // this contains instret and cycles for start and end of test run, used by embench
// also begin_signature contains the results of the self checking mechanism, which will be read by the python script for error checking // python speed script to calculate embench speed score.
// also, begin_signature contains the results of the self checking mechanism,
// which will be read by the python script for error checking
$display("Embench Benchmark: %s is done.", tests[test]); $display("Embench Benchmark: %s is done.", tests[test]);
if (riscofTest) outputfile = {pathname, tests[test], "/ref/ref.sim.output"}; if (riscofTest) outputfile = {pathname, tests[test], "/ref/ref.sim.output"};
else outputfile = {pathname, tests[test], ".sim.output"}; else outputfile = {pathname, tests[test], ".sim.output"};
outputFilePointer = $fopen(outputfile); outputFilePointer = $fopen(outputfile);
i = 0; i = 0;
while ($unsigned(i) < $unsigned(5'd5)) begin while ($unsigned(i) < $unsigned(5'd5)) begin
$fdisplayh(outputFilePointer, DCacheFlushFSM.ShadowRAM[testadr+i]); $fdisplayh(outputFilePointer, DCacheFlushFSM.ShadowRAM[testadr+i]);
i = i + 1; i = i + 1;
end end
$fclose(outputFilePointer); $fclose(outputFilePointer);
$display("Embench Benchmark: created output file: %s", outputfile); $display("Embench Benchmark: created output file: %s", outputfile);
end else if (TEST == "coverage64gc") begin end else if (TEST == "coverage64gc") begin
$display("Coverage tests don't get checked"); $display("Coverage tests don't get checked");
end else begin end else begin
// for tests with no self checking mechanism, read .signature.output file and compare to check for errors // for tests with no self checking mechanism, read .signature.output file and compare to check for errors
// clear signature to prevent contamination from previous tests // clear signature to prevent contamination from previous tests
for(i=0; i<SIGNATURESIZE; i=i+1) begin for(i=0; i<SIGNATURESIZE; i=i+1) begin
sig32[i] = 'bx; sig32[i] = 'bx;
end end
if (riscofTest) signame = {pathname, tests[test], "/ref/Reference-sail_c_simulator.signature"}; if (riscofTest) signame = {pathname, tests[test], "/ref/Reference-sail_c_simulator.signature"};
else signame = {pathname, tests[test], ".signature.output"}; else signame = {pathname, tests[test], ".signature.output"};
// read signature, reformat in 64 bits if necessary // read signature, reformat in 64 bits if necessary
$readmemh(signame, sig32); $readmemh(signame, sig32);
i = 0; i = 0;
while (i < SIGNATURESIZE) begin while (i < SIGNATURESIZE) begin
if (`XLEN == 32) begin if (`XLEN == 32) begin
signature[i] = sig32[i]; signature[i] = sig32[i];
i = i+1; i = i+1;
end else begin end else begin
signature[i/2] = {sig32[i+1], sig32[i]}; signature[i/2] = {sig32[i+1], sig32[i]};
i = i + 2; i = i + 2;
end end
if (i >= 4 & sig32[i-4] === 'bx) begin if (i >= 4 & sig32[i-4] === 'bx) begin
if (i == 4) begin if (i == 4) begin
i = SIGNATURESIZE+1; // flag empty file i = SIGNATURESIZE+1; // flag empty file
$display(" Error: empty test file"); $display(" Error: empty test file");
end else i = SIGNATURESIZE; // skip over the rest of the x's for efficiency end else i = SIGNATURESIZE; // skip over the rest of the x's for efficiency
end end
end end
// Check errors // Check errors
errors = (i == SIGNATURESIZE+1); // error if file is empty errors = (i == SIGNATURESIZE+1); // error if file is empty
i = 0; i = 0;
/* verilator lint_off INFINITELOOP */ /* verilator lint_off INFINITELOOP */
while (signature[i] !== 'bx) begin while (signature[i] !== 'bx) begin
logic [`XLEN-1:0] sig; logic [`XLEN-1:0] sig;
if (`DTIM_SUPPORTED) sig = dut.core.lsu.dtim.dtim.ram.RAM[testadrNoBase+i]; if (`DTIM_SUPPORTED) sig = dut.core.lsu.dtim.dtim.ram.RAM[testadrNoBase+i];
else if (`UNCORE_RAM_SUPPORTED) sig = dut.uncore.uncore.ram.ram.memory.RAM[testadrNoBase+i]; else if (`UNCORE_RAM_SUPPORTED) sig = dut.uncore.uncore.ram.ram.memory.RAM[testadrNoBase+i];
//$display("signature[%h] = %h sig = %h", i, signature[i], sig); //$display("signature[%h] = %h sig = %h", i, signature[i], sig);
if (signature[i] !== sig & (signature[i] !== DCacheFlushFSM.ShadowRAM[testadr+i])) begin if (signature[i] !== sig & (signature[i] !== DCacheFlushFSM.ShadowRAM[testadr+i])) begin
errors = errors+1; errors = errors+1;
$display(" Error on test %s result %d: adr = %h sim (D$) %h sim (DTIM_SUPPORTED) = %h, signature = %h", $display(" Error on test %s result %d: adr = %h sim (D$) %h sim (DTIM_SUPPORTED) = %h, signature = %h",
tests[test], i, (testadr+i)*(`XLEN/8), DCacheFlushFSM.ShadowRAM[testadr+i], sig, signature[i]); tests[test], i, (testadr+i)*(`XLEN/8), DCacheFlushFSM.ShadowRAM[testadr+i], sig, signature[i]);
$stop;//***debug $stop; //***debug
end end
i = i + 1; i = i + 1;
end end
/* verilator lint_on INFINITELOOP */ /* verilator lint_on INFINITELOOP */
if (errors == 0) begin if (errors == 0) begin
$display("%s succeeded. Brilliant!!!", tests[test]); $display("%s succeeded. Brilliant!!!", tests[test]);
end end else begin
else begin
$display("%s failed with %d errors. :(", tests[test], errors); $display("%s failed with %d errors. :(", tests[test], errors);
totalerrors = totalerrors+1; totalerrors = totalerrors+1;
end end
end end
// move onto the next test, check to see if we're done // move onto the next test, check to see if we're done
test = test + 1; test = test + 1;
if (test == tests.size()) begin if (test == tests.size()) begin
if (totalerrors == 0) $display("SUCCESS! All tests ran without failures."); if (totalerrors == 0) $display("SUCCESS! All tests ran without failures.");
else $display("FAIL: %d test programs had errors", totalerrors); else $display("FAIL: %d test programs had errors", totalerrors);
$stop; $stop;
end end else begin
else begin
InitializingMemories = 1; InitializingMemories = 1;
// If there are still additional tests to run, read in information for the next test // If there are still additional tests to run, read in information for the next test
//pathname = tvpaths[tests[0]]; //pathname = tvpaths[tests[0]];
@ -394,7 +396,7 @@ module testbench;
else memfilename = {pathname, tests[test], ".elf.memfile"}; else memfilename = {pathname, tests[test], ".elf.memfile"};
//$readmemh(memfilename, dut.uncore.uncore.ram.ram.memory.RAM); //$readmemh(memfilename, dut.uncore.uncore.ram.ram.memory.RAM);
if (`IROM_SUPPORTED) $readmemh(memfilename, dut.core.ifu.irom.irom.rom.ROM); if (`IROM_SUPPORTED) $readmemh(memfilename, dut.core.ifu.irom.irom.rom.ROM);
else if (`UNCORE_RAM_SUPPORTED) $readmemh(memfilename, dut.uncore.uncore.ram.ram.memory.RAM); else if (`UNCORE_RAM_SUPPORTED) $readmemh(memfilename, dut.uncore.uncore.ram.ram.memory.RAM);
if (`DTIM_SUPPORTED) $readmemh(memfilename, dut.core.lsu.dtim.dtim.ram.RAM); if (`DTIM_SUPPORTED) $readmemh(memfilename, dut.core.lsu.dtim.dtim.ram.RAM);
if (riscofTest) begin if (riscofTest) begin
@ -405,22 +407,22 @@ module testbench;
ProgramLabelMapFile = {pathname, tests[test], ".elf.objdump.lab"}; ProgramLabelMapFile = {pathname, tests[test], ".elf.objdump.lab"};
end end
ProgramAddrLabelArray = '{ "begin_signature" : 0, "tohost" : 0 }; ProgramAddrLabelArray = '{ "begin_signature" : 0, "tohost" : 0 };
if(!`FPGA) begin if(!`FPGA) begin
updateProgramAddrLabelArray(ProgramAddrMapFile, ProgramLabelMapFile, ProgramAddrLabelArray); updateProgramAddrLabelArray(ProgramAddrMapFile, ProgramLabelMapFile, ProgramAddrLabelArray);
$display("Read memfile %s", memfilename); $display("Read memfile %s", memfilename);
end end
end end
end // if (DCacheFlushDone) end // if (DCacheFlushDone)
end end
end // always @ (negedge clk) end // always @ (negedge clk)
if(`PrintHPMCounters & `ZICOUNTERS_SUPPORTED) begin : HPMCSample if(`PrintHPMCounters & `ZICOUNTERS_SUPPORTED) begin : HPMCSample
integer HPMCindex; integer HPMCindex;
logic StartSampleFirst; logic StartSampleFirst;
logic StartSampleDelayed, BeginDelayed; logic StartSampleDelayed, BeginDelayed;
logic EndSampleFirst, EndSampleDelayed; logic EndSampleFirst, EndSampleDelayed;
logic [`XLEN-1:0] InitialHPMCOUNTERH[`COUNTERS-1:0]; logic [`XLEN-1:0] InitialHPMCOUNTERH[`COUNTERS-1:0];
string HPMCnames[] = '{"Mcycle", string HPMCnames[] = '{"Mcycle",
"------", "------",
@ -433,8 +435,8 @@ module testbench;
"BP Target Wrong", "BP Target Wrong",
"RAS Wrong", "RAS Wrong",
"Instr Class Wrong", "Instr Class Wrong",
"Load Stall", "Load Stall",
"Store Stall", "Store Stall",
"D Cache Access", "D Cache Access",
"D Cache Miss", "D Cache Miss",
"D Cache Cycles", "D Cache Cycles",
@ -447,56 +449,55 @@ module testbench;
"Interrupt", "Interrupt",
"Exception", "Exception",
"Divide Cycles" "Divide Cycles"
}; };
if(TEST == "embench") begin if(TEST == "embench") begin
// embench runs warmup then runs start_trigger // embench runs warmup then runs start_trigger
// embench end with stop_trigger. // embench end with stop_trigger.
assign StartSampleFirst = FunctionName.FunctionName.FunctionName == "start_trigger"; assign StartSampleFirst = FunctionName.FunctionName.FunctionName == "start_trigger";
flopr #(1) StartSampleReg(clk, reset, StartSampleFirst, StartSampleDelayed); flopr #(1) StartSampleReg(clk, reset, StartSampleFirst, StartSampleDelayed);
assign StartSample = StartSampleFirst & ~ StartSampleDelayed; assign StartSample = StartSampleFirst & ~ StartSampleDelayed;
assign EndSampleFirst = FunctionName.FunctionName.FunctionName == "stop_trigger"; assign EndSampleFirst = FunctionName.FunctionName.FunctionName == "stop_trigger";
flopr #(1) EndSampleReg(clk, reset, EndSampleFirst, EndSampleDelayed); flopr #(1) EndSampleReg(clk, reset, EndSampleFirst, EndSampleDelayed);
assign EndSample = EndSampleFirst & ~ EndSampleDelayed; assign EndSample = EndSampleFirst & ~ EndSampleDelayed;
end else if(TEST == "coremark") begin end else if(TEST == "coremark") begin
// embench runs warmup then runs start_trigger // embench runs warmup then runs start_trigger
// embench end with stop_trigger. // embench end with stop_trigger.
assign StartSampleFirst = FunctionName.FunctionName.FunctionName == "start_time"; assign StartSampleFirst = FunctionName.FunctionName.FunctionName == "start_time";
flopr #(1) StartSampleReg(clk, reset, StartSampleFirst, StartSampleDelayed); flopr #(1) StartSampleReg(clk, reset, StartSampleFirst, StartSampleDelayed);
assign StartSample = StartSampleFirst & ~ StartSampleDelayed; assign StartSample = StartSampleFirst & ~ StartSampleDelayed;
assign EndSampleFirst = FunctionName.FunctionName.FunctionName == "stop_time"; assign EndSampleFirst = FunctionName.FunctionName.FunctionName == "stop_time";
flopr #(1) EndSampleReg(clk, reset, EndSampleFirst, EndSampleDelayed); flopr #(1) EndSampleReg(clk, reset, EndSampleFirst, EndSampleDelayed);
assign EndSample = EndSampleFirst & ~ EndSampleDelayed; assign EndSample = EndSampleFirst & ~ EndSampleDelayed;
end else begin end else begin
// default start condiction is reset // default start condiction is reset
// default end condiction is end of test (DCacheFlushDone) // default end condiction is end of test (DCacheFlushDone)
assign StartSampleFirst = InReset; assign StartSampleFirst = InReset;
flopr #(1) StartSampleReg(clk, reset, StartSampleFirst, StartSampleDelayed); flopr #(1) StartSampleReg(clk, reset, StartSampleFirst, StartSampleDelayed);
assign StartSample = StartSampleFirst & ~ StartSampleDelayed; assign StartSample = StartSampleFirst & ~ StartSampleDelayed;
assign EndSample = DCacheFlushStart & ~DCacheFlushDone; assign EndSample = DCacheFlushStart & ~DCacheFlushDone;
flop #(1) BeginReg(clk, StartSampleFirst, BeginDelayed); flop #(1) BeginReg(clk, StartSampleFirst, BeginDelayed);
assign Begin = StartSampleFirst & ~BeginDelayed; assign BeginSample = StartSampleFirst & ~BeginDelayed;
end end
always @(negedge clk) begin always @(negedge clk) begin
if(StartSample) begin if(StartSample) begin
for(HPMCindex = 0; HPMCindex < 32; HPMCindex += 1) begin for(HPMCindex = 0; HPMCindex < 32; HPMCindex += 1) begin
InitialHPMCOUNTERH[HPMCindex] <= dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[HPMCindex]; InitialHPMCOUNTERH[HPMCindex] <= dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[HPMCindex];
end end
end end
if(EndSample) begin if(EndSample) begin
for(HPMCindex = 0; HPMCindex < HPMCnames.size(); HPMCindex += 1) begin for(HPMCindex = 0; HPMCindex < HPMCnames.size(); HPMCindex += 1) begin
// unlikely to have more than 10M in any counter. // unlikely to have more than 10M in any counter.
$display("Cnt[%2d] = %7d %s", HPMCindex, dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[HPMCindex] - InitialHPMCOUNTERH[HPMCindex], HPMCnames[HPMCindex]); $display("Cnt[%2d] = %7d %s", HPMCindex, dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[HPMCindex] - InitialHPMCOUNTERH[HPMCindex], HPMCnames[HPMCindex]);
end end
end end
end end
end end
@ -535,24 +536,24 @@ module testbench;
if (`BPRED_SUPPORTED) begin if (`BPRED_SUPPORTED) begin
integer adrindex; integer adrindex;
always @(*) begin always @(*) begin
if(reset) begin if(reset) begin
for(adrindex = 0; adrindex < 2**`BTB_SIZE; adrindex++) begin for(adrindex = 0; adrindex < 2**`BTB_SIZE; adrindex++) begin
force dut.core.ifu.bpred.bpred.TargetPredictor.memory.mem[adrindex] = 0; force dut.core.ifu.bpred.bpred.TargetPredictor.memory.mem[adrindex] = 0;
end end
for(adrindex = 0; adrindex < 2**`BPRED_SIZE; adrindex++) begin for(adrindex = 0; adrindex < 2**`BPRED_SIZE; adrindex++) begin
force dut.core.ifu.bpred.bpred.Predictor.DirPredictor.PHT.mem[adrindex] = 0; force dut.core.ifu.bpred.bpred.Predictor.DirPredictor.PHT.mem[adrindex] = 0;
end end
#1; #1;
for(adrindex = 0; adrindex < 2**`BTB_SIZE; adrindex++) begin for(adrindex = 0; adrindex < 2**`BTB_SIZE; adrindex++) begin
release dut.core.ifu.bpred.bpred.TargetPredictor.memory.mem[adrindex]; release dut.core.ifu.bpred.bpred.TargetPredictor.memory.mem[adrindex];
end end
for(adrindex = 0; adrindex < 2**`BPRED_SIZE; adrindex++) begin for(adrindex = 0; adrindex < 2**`BPRED_SIZE; adrindex++) begin
release dut.core.ifu.bpred.bpred.Predictor.DirPredictor.PHT.mem[adrindex]; release dut.core.ifu.bpred.bpred.Predictor.DirPredictor.PHT.mem[adrindex];
end end
end end
end end
end end
if (`ICACHE_SUPPORTED && `I_CACHE_ADDR_LOGGER) begin : ICacheLogger if (`ICACHE_SUPPORTED && `I_CACHE_ADDR_LOGGER) begin : ICacheLogger
@ -565,28 +566,28 @@ end
dut.core.ifu.immu.immu.pmachecker.Cacheable & dut.core.ifu.immu.immu.pmachecker.Cacheable &
~dut.core.ifu.bus.icache.icache.cachefsm.FlushStage & ~dut.core.ifu.bus.icache.icache.cachefsm.FlushStage &
~reset; ~reset;
flop #(1) ResetDReg(clk, reset, resetD); flop #(1) ResetDReg(clk, reset, resetD);
assign resetEdge = ~reset & resetD; assign resetEdge = ~reset & resetD;
flop #(1) InvalReg(clk, dut.core.ifu.InvalidateICacheM, InvalDelayed); flop #(1) InvalReg(clk, dut.core.ifu.InvalidateICacheM, InvalDelayed);
assign InvalEdge = dut.core.ifu.InvalidateICacheM & ~InvalDelayed; assign InvalEdge = dut.core.ifu.InvalidateICacheM & ~InvalDelayed;
initial begin initial begin
LogFile = $psprintf("ICache.log"); LogFile = $psprintf("ICache.log");
file = $fopen(LogFile, "w"); file = $fopen(LogFile, "w");
$fwrite(file, "BEGIN %s\n", memfilename); $fwrite(file, "BEGIN %s\n", memfilename);
end end
string AccessTypeString, HitMissString; string AccessTypeString, HitMissString;
assign HitMissString = dut.core.ifu.bus.icache.icache.CacheHit ? "H" : assign HitMissString = dut.core.ifu.bus.icache.icache.CacheHit ? "H" :
dut.core.ifu.bus.icache.icache.vict.cacheLRU.AllValid ? "E" : "M"; dut.core.ifu.bus.icache.icache.vict.cacheLRU.AllValid ? "E" : "M";
always @(posedge clk) begin always @(posedge clk) begin
if(resetEdge) $fwrite(file, "TRAIN\n"); if(resetEdge) $fwrite(file, "TRAIN\n");
if(Begin) $fwrite(file, "BEGIN %s\n", memfilename); if(BeginSample) $fwrite(file, "BEGIN %s\n", memfilename);
if(Enable) begin // only log i cache reads if(Enable) begin // only log i cache reads
$fwrite(file, "%h R %s\n", dut.core.ifu.PCPF, HitMissString); $fwrite(file, "%h R %s\n", dut.core.ifu.PCPF, HitMissString);
end end
if(InvalEdge) $fwrite(file, "0 I X\n"); if(InvalEdge) $fwrite(file, "0 I X\n");
if(EndSample) $fwrite(file, "END %s\n", memfilename); if(EndSample) $fwrite(file, "END %s\n", memfilename);
end end
end end
@ -615,18 +616,18 @@ end
(AccessTypeString != "NULL"); (AccessTypeString != "NULL");
initial begin initial begin
LogFile = $psprintf("DCache.log"); LogFile = $psprintf("DCache.log");
file = $fopen(LogFile, "w"); file = $fopen(LogFile, "w");
$fwrite(file, "BEGIN %s\n", memfilename); $fwrite(file, "BEGIN %s\n", memfilename);
end end
always @(posedge clk) begin always @(posedge clk) begin
if(resetEdge) $fwrite(file, "TRAIN\n"); if(resetEdge) $fwrite(file, "TRAIN\n");
if(Begin) $fwrite(file, "BEGIN %s\n", memfilename); if(BeginSample) $fwrite(file, "BEGIN %s\n", memfilename);
if(Enabled) begin if(Enabled) begin
$fwrite(file, "%h %s %s\n", dut.core.lsu.PAdrM, AccessTypeString, HitMissString); $fwrite(file, "%h %s %s\n", dut.core.lsu.PAdrM, AccessTypeString, HitMissString);
end end
if(dut.core.lsu.bus.dcache.dcache.cachefsm.FlushFlag) $fwrite(file, "0 F X\n"); if(dut.core.lsu.bus.dcache.dcache.cachefsm.FlushFlag) $fwrite(file, "0 F X\n");
if(EndSample) $fwrite(file, "END %s\n", memfilename); if(EndSample) $fwrite(file, "END %s\n", memfilename);
end end
end end
@ -634,45 +635,45 @@ end
if (`BPRED_LOGGER) begin if (`BPRED_LOGGER) begin
string direction; string direction;
int file; int file;
logic PCSrcM; logic PCSrcM;
string LogFile; string LogFile;
logic resetD, resetEdge; logic resetD, resetEdge;
flopenrc #(1) PCSrcMReg(clk, reset, dut.core.FlushM, ~dut.core.StallM, dut.core.ifu.bpred.bpred.Predictor.DirPredictor.PCSrcE, PCSrcM); flopenrc #(1) PCSrcMReg(clk, reset, dut.core.FlushM, ~dut.core.StallM, dut.core.ifu.bpred.bpred.Predictor.DirPredictor.PCSrcE, PCSrcM);
flop #(1) ResetDReg(clk, reset, resetD); flop #(1) ResetDReg(clk, reset, resetD);
assign resetEdge = ~reset & resetD; assign resetEdge = ~reset & resetD;
initial begin initial begin
LogFile = $psprintf("branch_%s%0d.log", `BPRED_TYPE, `BPRED_SIZE); LogFile = $psprintf("branch_%s%0d.log", `BPRED_TYPE, `BPRED_SIZE);
file = $fopen(LogFile, "w"); file = $fopen(LogFile, "w");
end end
always @(posedge clk) begin always @(posedge clk) begin
if(resetEdge) $fwrite(file, "TRAIN\n"); if(resetEdge) $fwrite(file, "TRAIN\n");
if(StartSample) $fwrite(file, "BEGIN %s\n", memfilename); if(StartSample) $fwrite(file, "BEGIN %s\n", memfilename);
if(dut.core.ifu.InstrClassM[0] & ~dut.core.StallW & ~dut.core.FlushW & dut.core.InstrValidM) begin if(dut.core.ifu.InstrClassM[0] & ~dut.core.StallW & ~dut.core.FlushW & dut.core.InstrValidM) begin
direction = PCSrcM ? "t" : "n"; direction = PCSrcM ? "t" : "n";
$fwrite(file, "%h %s\n", dut.core.PCM, direction); $fwrite(file, "%h %s\n", dut.core.PCM, direction);
end end
if(EndSample) $fwrite(file, "END %s\n", memfilename); if(EndSample) $fwrite(file, "END %s\n", memfilename);
end end
end end
end end
// check for hange up. // check for hang up.
logic [`XLEN-1:0] OldPCW; logic [`XLEN-1:0] OldPCW;
integer WatchDogTimerCount; integer WatchDogTimerCount;
localparam WatchDogTimerThreshold = 1000000; localparam WatchDogTimerThreshold = 1000000;
logic WatchDogTimeOut; logic WatchDogTimeOut;
always_ff @(posedge clk) begin always_ff @(posedge clk) begin
OldPCW <= PCW; OldPCW <= PCW;
if(OldPCW == PCW) WatchDogTimerCount = WatchDogTimerCount + 1'b1; if(OldPCW == PCW) WatchDogTimerCount = WatchDogTimerCount + 1'b1;
else WatchDogTimerCount = '0; else WatchDogTimerCount = '0;
end end
always_comb begin always_comb begin
WatchDogTimeOut = WatchDogTimerCount >= WatchDogTimerThreshold; WatchDogTimeOut = WatchDogTimerCount >= WatchDogTimerThreshold;
if(WatchDogTimeOut) begin if(WatchDogTimeOut) begin
$display("FAILURE: Watch Dog Time Out triggered. PCW stuck at %x for more than %d cycles", PCW, WatchDogTimerCount); $display("FAILURE: Watch Dog Time Out triggered. PCW stuck at %x for more than %d cycles", PCW, WatchDogTimerCount);
$stop; $stop;
end end
end end
endmodule endmodule
@ -690,34 +691,34 @@ module DCacheFlushFSM
logic [`XLEN-1:0] ShadowRAM[`UNCORE_RAM_BASE>>(1+`XLEN/32):(`UNCORE_RAM_RANGE+`UNCORE_RAM_BASE)>>1+(`XLEN/32)]; logic [`XLEN-1:0] ShadowRAM[`UNCORE_RAM_BASE>>(1+`XLEN/32):(`UNCORE_RAM_RANGE+`UNCORE_RAM_BASE)>>1+(`XLEN/32)];
if(`DCACHE_SUPPORTED) begin if(`DCACHE_SUPPORTED) begin
localparam numlines = testbench.dut.core.lsu.bus.dcache.dcache.NUMLINES; localparam numlines = testbench.dut.core.lsu.bus.dcache.dcache.NUMLINES;
localparam numways = testbench.dut.core.lsu.bus.dcache.dcache.NUMWAYS; localparam numways = testbench.dut.core.lsu.bus.dcache.dcache.NUMWAYS;
localparam linebytelen = testbench.dut.core.lsu.bus.dcache.dcache.LINEBYTELEN; localparam linebytelen = testbench.dut.core.lsu.bus.dcache.dcache.LINEBYTELEN;
localparam linelen = testbench.dut.core.lsu.bus.dcache.dcache.LINELEN; localparam linelen = testbench.dut.core.lsu.bus.dcache.dcache.LINELEN;
localparam sramlen = testbench.dut.core.lsu.bus.dcache.dcache.CacheWays[0].SRAMLEN; localparam sramlen = testbench.dut.core.lsu.bus.dcache.dcache.CacheWays[0].SRAMLEN;
localparam cachesramwords = testbench.dut.core.lsu.bus.dcache.dcache.CacheWays[0].NUMSRAM; localparam cachesramwords = testbench.dut.core.lsu.bus.dcache.dcache.CacheWays[0].NUMSRAM;
localparam numwords = sramlen/`XLEN; localparam numwords = sramlen/`XLEN;
localparam lognumlines = $clog2(numlines); localparam lognumlines = $clog2(numlines);
localparam loglinebytelen = $clog2(linebytelen); localparam loglinebytelen = $clog2(linebytelen);
localparam lognumways = $clog2(numways); localparam lognumways = $clog2(numways);
localparam tagstart = lognumlines + loglinebytelen; localparam tagstart = lognumlines + loglinebytelen;
genvar index, way, cacheWord; genvar index, way, cacheWord;
logic [sramlen-1:0] CacheData [numways-1:0] [numlines-1:0] [cachesramwords-1:0]; logic [sramlen-1:0] CacheData [numways-1:0] [numlines-1:0] [cachesramwords-1:0];
logic [sramlen-1:0] cacheline; logic [sramlen-1:0] cacheline;
logic [`XLEN-1:0] CacheTag [numways-1:0] [numlines-1:0] [cachesramwords-1:0]; logic [`XLEN-1:0] CacheTag [numways-1:0] [numlines-1:0] [cachesramwords-1:0];
logic CacheValid [numways-1:0] [numlines-1:0] [cachesramwords-1:0]; logic CacheValid [numways-1:0] [numlines-1:0] [cachesramwords-1:0];
logic CacheDirty [numways-1:0] [numlines-1:0] [cachesramwords-1:0]; logic CacheDirty [numways-1:0] [numlines-1:0] [cachesramwords-1:0];
logic [`PA_BITS-1:0] CacheAdr [numways-1:0] [numlines-1:0] [cachesramwords-1:0]; logic [`PA_BITS-1:0] CacheAdr [numways-1:0] [numlines-1:0] [cachesramwords-1:0];
for(index = 0; index < numlines; index++) begin for(index = 0; index < numlines; index++) begin
for(way = 0; way < numways; way++) begin for(way = 0; way < numways; way++) begin
for(cacheWord = 0; cacheWord < cachesramwords; cacheWord++) begin for(cacheWord = 0; cacheWord < cachesramwords; cacheWord++) begin
copyShadow #(.tagstart(tagstart), copyShadow #(.tagstart(tagstart),
.loglinebytelen(loglinebytelen), .sramlen(sramlen)) .loglinebytelen(loglinebytelen), .sramlen(sramlen))
copyShadow(.clk, copyShadow(.clk,
.start, .start,
.tag(testbench.dut.core.lsu.bus.dcache.dcache.CacheWays[way].CacheTagMem.RAM[index][`PA_BITS-1-tagstart:0]), .tag(testbench.dut.core.lsu.bus.dcache.dcache.CacheWays[way].CacheTagMem.RAM[index][`PA_BITS-1-tagstart:0]),
.valid(testbench.dut.core.lsu.bus.dcache.dcache.CacheWays[way].ValidBits[index]), .valid(testbench.dut.core.lsu.bus.dcache.dcache.CacheWays[way].ValidBits[index]),
@ -766,18 +767,18 @@ endmodule
module copyShadow module copyShadow
#(parameter tagstart, loglinebytelen, sramlen) #(parameter tagstart, loglinebytelen, sramlen)
(input logic clk, (input logic clk,
input logic start, input logic start,
input logic [`PA_BITS-1:tagstart] tag, input logic [`PA_BITS-1:tagstart] tag,
input logic valid, dirty, input logic valid, dirty,
input logic [sramlen-1:0] data, input logic [sramlen-1:0] data,
input logic [32-1:0] index, input logic [32-1:0] index,
input logic [32-1:0] cacheWord, input logic [32-1:0] cacheWord,
output logic [sramlen-1:0] CacheData, output logic [sramlen-1:0] CacheData,
output logic [`PA_BITS-1:0] CacheAdr, output logic [`PA_BITS-1:0] CacheAdr,
output logic [`XLEN-1:0] CacheTag, output logic [`XLEN-1:0] CacheTag,
output logic CacheValid, output logic CacheValid,
output logic CacheDirty); output logic CacheDirty);
always_ff @(posedge clk) begin always_ff @(posedge clk) begin
@ -806,8 +807,7 @@ task automatic updateProgramAddrLabelArray;
integer returncode; integer returncode;
returncode = $fscanf(ProgramLabelMapFP, "%s\n", label); returncode = $fscanf(ProgramLabelMapFP, "%s\n", label);
returncode = $fscanf(ProgramAddrMapFP, "%s\n", adrstr); returncode = $fscanf(ProgramAddrMapFP, "%s\n", adrstr);
if (ProgramAddrLabelArray.exists(label)) if (ProgramAddrLabelArray.exists(label)) ProgramAddrLabelArray[label] = adrstr.atohex();
ProgramAddrLabelArray[label] = adrstr.atohex();
end end
end end
$fclose(ProgramLabelMapFP); $fclose(ProgramLabelMapFP);