This commit is contained in:
David Harris 2021-04-14 23:41:23 -04:00
commit 6e298962e9
17 changed files with 141 additions and 466 deletions

View File

@ -61,7 +61,7 @@ module pagetablewalker (
output logic MMUTranslationComplete, output logic MMUTranslationComplete,
// Faults // Faults
output logic InstrPageFaultM, LoadPageFaultM, StorePageFaultM output logic InstrPageFaultF, LoadPageFaultM, StorePageFaultM
); );
// Internal signals // Internal signals
@ -138,7 +138,6 @@ module pagetablewalker (
localparam LEVEL0 = 3'h2; localparam LEVEL0 = 3'h2;
localparam LEAF = 3'h3; localparam LEAF = 3'h3;
localparam FAULT = 3'h4; localparam FAULT = 3'h4;
localparam LEVEL2 = 3'h5;
logic [2:0] WalkerState, NextWalkerState; logic [2:0] WalkerState, NextWalkerState;
@ -160,7 +159,8 @@ module pagetablewalker (
// else if (~ValidPTE || (LeafPTE && BadMegapage)) // else if (~ValidPTE || (LeafPTE && BadMegapage))
// NextWalkerState = FAULT; // NextWalkerState = FAULT;
// *** Leave megapage implementation for later // *** Leave megapage implementation for later
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** need to check if megapage valid/aligned
else if (ValidPTE && LeafPTE) NextWalkerState = LEAF;
else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL0; else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL0;
else NextWalkerState = FAULT; else NextWalkerState = FAULT;
LEVEL0: if (~MMUReady) NextWalkerState = LEVEL0; LEVEL0: if (~MMUReady) NextWalkerState = LEVEL0;
@ -171,6 +171,8 @@ module pagetablewalker (
else NextWalkerState = IDLE; else NextWalkerState = IDLE;
FAULT: if (MMUTranslate) NextWalkerState = LEVEL1; FAULT: if (MMUTranslate) NextWalkerState = LEVEL1;
else NextWalkerState = IDLE; else NextWalkerState = IDLE;
// Default case should never happen, but is included for linter.
default: NextWalkerState = IDLE;
endcase endcase
end end
@ -191,7 +193,7 @@ module pagetablewalker (
MMUTranslationComplete = '0; MMUTranslationComplete = '0;
DTLBWriteM = '0; DTLBWriteM = '0;
ITLBWriteF = '0; ITLBWriteF = '0;
InstrPageFaultM = '0; InstrPageFaultF = '0;
LoadPageFaultM = '0; LoadPageFaultM = '0;
StorePageFaultM = '0; StorePageFaultM = '0;
@ -214,10 +216,13 @@ module pagetablewalker (
FAULT: begin FAULT: begin
TranslationPAdr = {CurrentPPN, VPN0, 2'b00}; TranslationPAdr = {CurrentPPN, VPN0, 2'b00};
MMUTranslationComplete = '1; MMUTranslationComplete = '1;
InstrPageFaultM = ~DTLBMissM; InstrPageFaultF = ~DTLBMissM;
LoadPageFaultM = DTLBMissM && ~MemStore; LoadPageFaultM = DTLBMissM && ~MemStore;
StorePageFaultM = DTLBMissM && MemStore; StorePageFaultM = DTLBMissM && MemStore;
end end
default: begin
// nothing
end
endcase endcase
end end
@ -232,6 +237,8 @@ module pagetablewalker (
assign MMUPAdr = TranslationPAdr[31:0]; assign MMUPAdr = TranslationPAdr[31:0];
end else begin end else begin
localparam LEVEL2 = 3'h5;
assign SvMode = SATP_REGW[63]; assign SvMode = SATP_REGW[63];
logic [8:0] VPN2, VPN1, VPN0; logic [8:0] VPN2, VPN1, VPN0;
@ -246,13 +253,14 @@ module pagetablewalker (
IDLE: if (MMUTranslate) NextWalkerState = LEVEL2; IDLE: if (MMUTranslate) NextWalkerState = LEVEL2;
else NextWalkerState = IDLE; else NextWalkerState = IDLE;
LEVEL2: if (~MMUReady) NextWalkerState = LEVEL2; LEVEL2: if (~MMUReady) NextWalkerState = LEVEL2;
else if (ValidPTE && LeafPTE) NextWalkerState = LEAF;
else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL1; else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL1;
else NextWalkerState = FAULT; else NextWalkerState = FAULT;
LEVEL1: if (~MMUReady) NextWalkerState = LEVEL1; LEVEL1: if (~MMUReady) NextWalkerState = LEVEL1;
// else if (~ValidPTE || (LeafPTE && BadMegapage)) // else if (~ValidPTE || (LeafPTE && BadMegapage))
// NextWalkerState = FAULT; // NextWalkerState = FAULT;
// *** Leave megapage implementation for later // *** Leave megapage implementation for later
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; else if (ValidPTE && LeafPTE) NextWalkerState = LEAF;
else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL0; else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL0;
else NextWalkerState = FAULT; else NextWalkerState = FAULT;
LEVEL0: if (~MMUReady) NextWalkerState = LEVEL0; LEVEL0: if (~MMUReady) NextWalkerState = LEVEL0;
@ -263,6 +271,8 @@ module pagetablewalker (
else NextWalkerState = IDLE; else NextWalkerState = IDLE;
FAULT: if (MMUTranslate) NextWalkerState = LEVEL2; FAULT: if (MMUTranslate) NextWalkerState = LEVEL2;
else NextWalkerState = IDLE; else NextWalkerState = IDLE;
// Default case should never happen, but is included for linter.
default: NextWalkerState = IDLE;
endcase endcase
end end
@ -288,7 +298,7 @@ module pagetablewalker (
MMUTranslationComplete = '0; MMUTranslationComplete = '0;
DTLBWriteM = '0; DTLBWriteM = '0;
ITLBWriteF = '0; ITLBWriteF = '0;
InstrPageFaultM = '0; InstrPageFaultF = '0;
LoadPageFaultM = '0; LoadPageFaultM = '0;
StorePageFaultM = '0; StorePageFaultM = '0;
@ -315,10 +325,13 @@ module pagetablewalker (
FAULT: begin FAULT: begin
TranslationPAdr = {CurrentPPN, VPN0, 3'b000}; TranslationPAdr = {CurrentPPN, VPN0, 3'b000};
MMUTranslationComplete = '1; MMUTranslationComplete = '1;
InstrPageFaultM = ~DTLBMissM; InstrPageFaultF = ~DTLBMissM;
LoadPageFaultM = DTLBMissM && ~MemStore; LoadPageFaultM = DTLBMissM && ~MemStore;
StorePageFaultM = DTLBMissM && MemStore; StorePageFaultM = DTLBMissM && MemStore;
end end
default: begin
// nothing
end
endcase endcase
end end

View File

@ -71,6 +71,6 @@ module cam_line #(parameter KEY_BITS = 20,
// should automatically match. // should automatically match.
page_number_mixer #(KEY_BITS, HIGH_SEGMENT_BITS) mixer(VirtualPageNumber, Key, PageType, VirtualPageNumberQuery); page_number_mixer #(KEY_BITS, HIGH_SEGMENT_BITS) mixer(VirtualPageNumber, Key, PageType, VirtualPageNumberQuery);
assign Match = ({1'b1, VirtualPageNumberQuery} == Key); assign Match = ({1'b1, VirtualPageNumberQuery} == {Valid, Key});
endmodule endmodule

View File

@ -4,7 +4,7 @@
// Written: jtorrey@hmc.edu 16 February 2021 // Written: jtorrey@hmc.edu 16 February 2021
// Modified: // Modified:
// //
// Purpose: Example translation lookaside buffer // Purpose: Translation lookaside buffer
// Cache of virtural-to-physical address translations // Cache of virtural-to-physical address translations
// //
// A component of the Wally configurable RISC-V project. // A component of the Wally configurable RISC-V project.
@ -127,7 +127,8 @@ module tlb #(parameter ENTRY_BITS = 3) (
assign PageOffset = VirtualAddress[11:0]; assign PageOffset = VirtualAddress[11:0];
// Currently use random replacement algorithm // Currently use random replacement algorithm
tlb_rand rdm(.*); // tlb_rand rdm(.*);
tlb_lru lru(.*);
tlb_ram #(ENTRY_BITS) ram(.*); tlb_ram #(ENTRY_BITS) ram(.*);
tlb_cam #(ENTRY_BITS, `VPN_BITS, `VPN_SEGMENT_BITS) cam(.*); tlb_cam #(ENTRY_BITS, `VPN_BITS, `VPN_SEGMENT_BITS) cam(.*);

View File

@ -64,6 +64,8 @@ module tlb_cam #(parameter ENTRY_BITS = 3,
endgenerate endgenerate
// In case there are multiple matches in the CAM, select only one // In case there are multiple matches in the CAM, select only one
// *** it might be guaranteed that the CAM will never have multiple matches.
// If so, this is just an encoder
priority_encoder #(ENTRY_BITS) match_priority(Matches, VPNIndex); priority_encoder #(ENTRY_BITS) match_priority(Matches, VPNIndex);
assign CAMHit = |Matches & ~TLBFlush; assign CAMHit = |Matches & ~TLBFlush;

View File

@ -0,0 +1,69 @@
///////////////////////////////////////////
// tlb_lru.sv
//
// Written: tfleming@hmc.edu & jtorrey@hmc.edu 16 February 2021
// Modified:
//
// Purpose: Implementation of bit pseudo least-recently-used algorithm for
// cache evictions. Outputs the index of the next entry to be written.
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
module tlb_lru #(parameter ENTRY_BITS = 3) (
input clk, reset,
input TLBWrite,
input TLBFlush,
input [ENTRY_BITS-1:0] VPNIndex,
input CAMHit,
output [ENTRY_BITS-1:0] WriteIndex
);
localparam NENTRIES = 2**ENTRY_BITS;
// Keep a "recently-used" record for each TLB entry. On access, set to 1
logic [NENTRIES-1:0] RUBits, RUBitsNext, RUBitsAccessed;
// One-hot encodings of which line is being accessed
logic [NENTRIES-1:0] ReadLineOneHot, WriteLineOneHot, AccessLineOneHot;
// High if the next access causes all RU bits to be 1
logic AllUsed;
// Convert indices to one-hot encodings
decoder #(ENTRY_BITS) read_decoder(VPNIndex, ReadLineOneHot);
// *** should output writelineonehot so we don't have to decode WriteIndex outside
decoder #(ENTRY_BITS) write_decoder(WriteIndex, WriteLineOneHot);
// Find the first line not recently used
priority_encoder #(ENTRY_BITS) first_nru(~RUBits, WriteIndex);
// Access either the hit line or written line
assign AccessLineOneHot = (TLBWrite) ? WriteLineOneHot : ReadLineOneHot;
// Raise the bit of the recently accessed line
assign RUBitsAccessed = AccessLineOneHot | RUBits;
// Determine whether we need to reset the RU bits to all zeroes
assign AllUsed = &(RUBitsAccessed);
assign RUBitsNext = (AllUsed) ? AccessLineOneHot : RUBitsAccessed;
// Update LRU state on any TLB hit or write
flopenrc #(NENTRIES) lru_state(clk, reset, TLBFlush, (CAMHit || TLBWrite),
RUBitsNext, RUBits);
endmodule

View File

@ -49,8 +49,8 @@ module csri #(parameter
// assumes no N-mode user interrupts // assumes no N-mode user interrupts
always_comb begin always_comb begin
IntInM = 0; // *** does this really work IntInM = 0; // *** does this overwriting technique really synthesize
IntInM[11] = ExtIntM & ~MIDELEG_REGW[9]; // MEIP IP_REGW[11] = ExtIntM & ~MIDELEG_REGW[9]; // MEIP
IntInM[9] = ExtIntM & MIDELEG_REGW[9]; // SEIP IntInM[9] = ExtIntM & MIDELEG_REGW[9]; // SEIP
IntInM[7] = TimerIntM & ~MIDELEG_REGW[5]; // MTIP IntInM[7] = TimerIntM & ~MIDELEG_REGW[5]; // MTIP
IntInM[5] = TimerIntM & MIDELEG_REGW[5]; // STIP IntInM[5] = TimerIntM & MIDELEG_REGW[5]; // STIP
@ -77,11 +77,11 @@ module csri #(parameter
assign SIP_WRITE_MASK = 12'h000; assign SIP_WRITE_MASK = 12'h000;
end end
always @(posedge clk, posedge reset) begin always @(posedge clk, posedge reset) begin
if (reset) IP_REGW <= 12'b0; if (reset) IP_REGW[9:0] <= 10'b0;
else if (WriteMIPM) IP_REGW <= (CSRWriteValM & MIP_WRITE_MASK) | IntInM; // MTIP unclearable else if (WriteMIPM) IP_REGW[9:0] <= (CSRWriteValM[9:0] & MIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable
else if (WriteSIPM) IP_REGW <= (CSRWriteValM & SIP_WRITE_MASK) | IntInM; // MTIP unclearable else if (WriteSIPM) IP_REGW[9:0] <= (CSRWriteValM[9:0] & SIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable
// else if (WriteUIPM) IP_REGW = (CSRWriteValM & 12'hBBB) | (NextIPM & 12'h080); // MTIP unclearable // else if (WriteUIPM) IP_REGW = (CSRWriteValM & 12'hBBB) | (NextIPM & 12'h080); // MTIP unclearable
else IP_REGW <= IP_REGW | IntInM; // *** check this turns off interrupts properly even when MIDELEG changes else IP_REGW[9:0] <= IP_REGW[9:0] | IntInM[9:0]; // *** check this turns off interrupts properly even when MIDELEG changes
end end
always @(posedge clk, posedge reset) begin always @(posedge clk, posedge reset) begin
if (reset) IE_REGW <= 12'b0; if (reset) IE_REGW <= 12'b0;

View File

@ -40,7 +40,7 @@ module privileged (
input logic InstrValidW, FloatRegWriteW, LoadStallD, BPPredWrongM, input logic InstrValidW, FloatRegWriteW, LoadStallD, BPPredWrongM,
input logic [3:0] InstrClassM, input logic [3:0] InstrClassM,
input logic PrivilegedM, input logic PrivilegedM,
input logic InstrPageFaultM, LoadPageFaultM, StorePageFaultM, input logic InstrPageFaultF, LoadPageFaultM, StorePageFaultM,
input logic InstrMisalignedFaultM, InstrAccessFaultF, IllegalIEUInstrFaultD, input logic InstrMisalignedFaultM, InstrAccessFaultF, IllegalIEUInstrFaultD,
input logic LoadMisalignedFaultM, LoadAccessFaultM, input logic LoadMisalignedFaultM, LoadAccessFaultM,
input logic StoreMisalignedFaultM, StoreAccessFaultM, input logic StoreMisalignedFaultM, StoreAccessFaultM,
@ -63,6 +63,7 @@ module privileged (
logic uretM, sretM, mretM, ecallM, ebreakM, wfiM, sfencevmaM; logic uretM, sretM, mretM, ecallM, ebreakM, wfiM, sfencevmaM;
logic IllegalCSRAccessM; logic IllegalCSRAccessM;
logic IllegalIEUInstrFaultE, IllegalIEUInstrFaultM; logic IllegalIEUInstrFaultE, IllegalIEUInstrFaultM;
logic InstrPageFaultD, InstrPageFaultE, InstrPageFaultM;
logic InstrAccessFaultD, InstrAccessFaultE, InstrAccessFaultM; logic InstrAccessFaultD, InstrAccessFaultE, InstrAccessFaultM;
logic IllegalInstrFaultM; logic IllegalInstrFaultM;
@ -129,13 +130,15 @@ module privileged (
// assign StorePageFaultM = 0; // assign StorePageFaultM = 0;
// pipeline fault signals // pipeline fault signals
flopenrc #(1) faultregD(clk, reset, FlushD, ~StallD, InstrAccessFaultF, InstrAccessFaultD); flopenrc #(2) faultregD(clk, reset, FlushD, ~StallD,
flopenrc #(2) faultregE(clk, reset, FlushE, ~StallE, {InstrPageFaultF, InstrAccessFaultF},
{IllegalIEUInstrFaultD, InstrAccessFaultD}, // ** vs IllegalInstrFaultInD {InstrPageFaultD, InstrAccessFaultD});
{IllegalIEUInstrFaultE, InstrAccessFaultE}); flopenrc #(3) faultregE(clk, reset, FlushE, ~StallE,
flopenrc #(2) faultregM(clk, reset, FlushM, ~StallM, {IllegalIEUInstrFaultD, InstrPageFaultD, InstrAccessFaultD}, // ** vs IllegalInstrFaultInD
{IllegalIEUInstrFaultE, InstrAccessFaultE}, {IllegalIEUInstrFaultE, InstrPageFaultE, InstrAccessFaultE});
{IllegalIEUInstrFaultM, InstrAccessFaultM}); flopenrc #(3) faultregM(clk, reset, FlushM, ~StallM,
{IllegalIEUInstrFaultE, InstrPageFaultE, InstrAccessFaultE},
{IllegalIEUInstrFaultM, InstrPageFaultM, InstrAccessFaultM});
trap trap(.*); trap trap(.*);

View File

@ -49,7 +49,7 @@ module trap (
logic InterruptM; logic InterruptM;
// Determine pending enabled interrupts // Determine pending enabled interrupts
assign MIntGlobalEnM = (PrivilegeModeW != `M_MODE) || STATUS_MIE; // if M ints enabled or lower priv 3.1.9 assign MIntGlobalEnM = {12{(PrivilegeModeW != `M_MODE) || STATUS_MIE}}; // if M ints enabled or lower priv 3.1.9
assign SIntGlobalEnM = (PrivilegeModeW == `U_MODE) || STATUS_SIE; // if S ints enabled or lower priv 3.1.9 assign SIntGlobalEnM = (PrivilegeModeW == `U_MODE) || STATUS_SIE; // if S ints enabled or lower priv 3.1.9
assign PendingIntsM = (MIP_REGW & MIE_REGW) & ((MIntGlobalEnM & 12'h888) | (SIntGlobalEnM & 12'h222)); assign PendingIntsM = (MIP_REGW & MIE_REGW) & ((MIntGlobalEnM & 12'h888) | (SIntGlobalEnM & 12'h222));
assign InterruptM = |PendingIntsM; // interrupt if any sources are pending assign InterruptM = |PendingIntsM; // interrupt if any sources are pending

View File

@ -41,13 +41,15 @@ module uart (
// UART interface signals // UART interface signals
logic [2:0] A; logic [2:0] A;
logic MEMRb, MEMWb; logic MEMRb, MEMWb, memread, memwrite;
logic [7:0] Din, Dout; logic [7:0] Din, Dout;
// rename processor interface signals to match PC16550D and provide one-byte interface // rename processor interface signals to match PC16550D and provide one-byte interface
flopr #(1) memreadreg(HCLK, ~HRESETn, ~(HSELUART & ~HWRITE), MEMRb); flopr #(1) memreadreg(HCLK, ~HRESETn, (HSELUART & ~HWRITE), memread);
flopr #(1) memwritereg(HCLK, ~HRESETn, ~(HSELUART & HWRITE), MEMWb); flopr #(1) memwritereg(HCLK, ~HRESETn, (HSELUART & HWRITE), memwrite);
flopr #(3) haddrreg(HCLK, ~HRESETn, HADDR[2:0], A); flopr #(3) haddrreg(HCLK, ~HRESETn, HADDR[2:0], A);
assign MEMRb = ~memread;
assign MEMWb = ~memwrite;
assign HRESPUART = 0; // OK assign HRESPUART = 0; // OK
assign HREADYUART = 1; // should idle high during address phase and respond high when done; will need to be modified if UART ever needs more than 1 cycle to do something assign HREADYUART = 1; // should idle high during address phase and respond high when done; will need to be modified if UART ever needs more than 1 cycle to do something

View File

@ -77,7 +77,7 @@ module wallypipelinedhart (
logic InstrMisalignedFaultM; logic InstrMisalignedFaultM;
logic DataMisalignedM; logic DataMisalignedM;
logic IllegalBaseInstrFaultD, IllegalIEUInstrFaultD; logic IllegalBaseInstrFaultD, IllegalIEUInstrFaultD;
logic InstrPageFaultM, LoadPageFaultM, StorePageFaultM; logic InstrPageFaultF, LoadPageFaultM, StorePageFaultM;
logic LoadMisalignedFaultM, LoadAccessFaultM; logic LoadMisalignedFaultM, LoadAccessFaultM;
logic StoreMisalignedFaultM, StoreAccessFaultM; logic StoreMisalignedFaultM, StoreAccessFaultM;
logic [`XLEN-1:0] InstrMisalignedAdrM; logic [`XLEN-1:0] InstrMisalignedAdrM;

View File

@ -72,6 +72,9 @@ module wallypipelinedsoc (
// instantiate processor and memories // instantiate processor and memories
wallypipelinedhart hart(.*); wallypipelinedhart hart(.*);
imem imem(.AdrF(PCF[`XLEN-1:1]), .*); // temporary until uncore memory is finished*** // *** Temporary driving of access fault to low until PMA checker is complete
assign InstrAccessFaultF = '0;
// instructions now come from uncore memory. This line can be removed at any time.
// imem imem(.AdrF(PCF[`XLEN-1:1]), .*); // temporary until uncore memory is finished***
uncore uncore(.HWDATAIN(HWDATA), .*); uncore uncore(.HWDATAIN(HWDATA), .*);
endmodule endmodule

View File

@ -99,8 +99,6 @@ module testbench_busybear();
initial begin initial begin
$readmemh("/courses/e190ax/busybear_boot_new/bootmem.txt", dut.uncore.bootdtim.RAM, 'h1000 >> 3); $readmemh("/courses/e190ax/busybear_boot_new/bootmem.txt", dut.uncore.bootdtim.RAM, 'h1000 >> 3);
$readmemh("/courses/e190ax/busybear_boot_new/ram.txt", dut.uncore.dtim.RAM); $readmemh("/courses/e190ax/busybear_boot_new/ram.txt", dut.uncore.dtim.RAM);
$readmemh("/courses/e190ax/busybear_boot_new/bootmem.txt", dut.imem.bootram, 'h1000 >> 3);
$readmemh("/courses/e190ax/busybear_boot_new/ram.txt", dut.imem.RAM);
$readmemb(`TWO_BIT_PRELOAD, dut.hart.ifu.bpred.Predictor.DirPredictor.PHT.memory); $readmemb(`TWO_BIT_PRELOAD, dut.hart.ifu.bpred.Predictor.DirPredictor.PHT.memory);
$readmemb(`BTB_PRELOAD, dut.hart.ifu.bpred.TargetPredictor.memory.memory); $readmemb(`BTB_PRELOAD, dut.hart.ifu.bpred.TargetPredictor.memory.memory);
end end
@ -279,14 +277,15 @@ module testbench_busybear();
end end
end end
string sepc_lit = "SEPC";
`define CHECK_CSR2(CSR, PATH) \ `define CHECK_CSR2(CSR, PATH) \
string CSR; \ string CSR; \
logic [63:0] expected``CSR``; \ logic [63:0] expected``CSR``; \
//CSR checking \ //CSR checking \
always @(``PATH``.``CSR``_REGW) begin \ always @(``PATH``.``CSR``_REGW) begin \
if ($time > 1) begin \ if ($time > 1) begin \
if (sepc_lit.icompare(`"CSR`")) begin #1; end \ if ("SEPC" == `"CSR`") begin #1; end \
if ("SCAUSE" == `"CSR`") begin #2; end \
if ("SSTATUS" == `"CSR`") begin #3; end \
scan_file_csr = $fscanf(data_file_csr, "%s\n", CSR); \ scan_file_csr = $fscanf(data_file_csr, "%s\n", CSR); \
scan_file_csr = $fscanf(data_file_csr, "%x\n", expected``CSR``); \ scan_file_csr = $fscanf(data_file_csr, "%x\n", expected``CSR``); \
if(CSR.icompare(`"CSR`")) begin \ if(CSR.icompare(`"CSR`")) begin \
@ -463,8 +462,10 @@ module testbench_busybear();
32'bXXXXXXXXXXXXXXXX111XXXXXXXXXXX01, // C.BNEZ 32'bXXXXXXXXXXXXXXXX111XXXXXXXXXXX01, // C.BNEZ
32'bXXXXXXXXXXXXXXXX101XXXXXXXXXXX01: // C.J 32'bXXXXXXXXXXXXXXXX101XXXXXXXXXXX01: // C.J
speculative = 1; speculative = 1;
32'bXXXXXXXXXXXXXXXX1001000000000010: // C.EBREAK: 32'bXXXXXXXXXXXXXXXX1001000000000010, // C.EBREAK:
32'bXXXXXXXXXXXXXXXXX000XXXXX1110011: // Something that's not CSRR*
speculative = 0; // tbh don't really know what should happen here speculative = 0; // tbh don't really know what should happen here
32'b000110000000XXXXXXXXXXXXX1110011, // CSR* SATP, *
32'bXXXXXXXXXXXXXXXX1000XXXXX0000010, // C.JR 32'bXXXXXXXXXXXXXXXX1000XXXXX0000010, // C.JR
32'bXXXXXXXXXXXXXXXX1001XXXXX0000010: // C.JALR //this is RV64 only so no C.JAL 32'bXXXXXXXXXXXXXXXX1001XXXXX0000010: // C.JALR //this is RV64 only so no C.JAL
speculative = 1; speculative = 1;

View File

@ -78,7 +78,6 @@ module testbench();
totalerrors = 0; totalerrors = 0;
// read test vectors into memory // read test vectors into memory
memfilename = tests[0]; memfilename = tests[0];
$readmemh(memfilename, dut.imem.RAM);
$readmemh(memfilename, dut.uncore.dtim.RAM); $readmemh(memfilename, dut.uncore.dtim.RAM);
for(j=18710; j < 65535; j = j+1) for(j=18710; j < 65535; j = j+1)
dut.uncore.dtim.RAM[j] = 64'b0; dut.uncore.dtim.RAM[j] = 64'b0;

View File

@ -80,7 +80,6 @@ module testbench();
totalerrors = 0; totalerrors = 0;
// read test vectors into memory // read test vectors into memory
memfilename = tests[0]; memfilename = tests[0];
$readmemh(memfilename, dut.imem.RAM);
$readmemh(memfilename, dut.uncore.dtim.RAM); $readmemh(memfilename, dut.uncore.dtim.RAM);
for(j=268437702; j < 268566528; j = j+1) for(j=268437702; j < 268566528; j = j+1)
dut.uncore.dtim.RAM[j] = 64'b0; dut.uncore.dtim.RAM[j] = 64'b0;

View File

@ -352,7 +352,7 @@ module testbench();
}; };
string tests64periph[] = '{ string tests64periph[] = '{
"rv64i-periph/WALLY-PLIC", "2000" "rv64i-periph/WALLY-PLIC", "2080"
}; };
string tests32periph[] = '{ string tests32periph[] = '{
@ -402,7 +402,7 @@ module testbench();
if (TESTSPERIPH) begin if (TESTSPERIPH) begin
tests = tests32periph; tests = tests32periph;
end else begin end else begin
tests = {tests32i,tests32periph}; tests = {tests32i};//,tests32periph}; *** broken at the moment
if (`C_SUPPORTED % 2 == 1) tests = {tests, tests32ic}; if (`C_SUPPORTED % 2 == 1) tests = {tests, tests32ic};
else tests = {tests, tests32iNOc}; else tests = {tests, tests32iNOc};
if (`M_SUPPORTED % 2 == 1) tests = {tests, tests32m}; if (`M_SUPPORTED % 2 == 1) tests = {tests, tests32m};
@ -450,7 +450,6 @@ module testbench();
end end
// read test vectors into memory // read test vectors into memory
memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"}; memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"};
$readmemh(memfilename, dut.imem.RAM);
$readmemh(memfilename, dut.uncore.dtim.RAM); $readmemh(memfilename, dut.uncore.dtim.RAM);
ProgramAddrMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.addr"}; ProgramAddrMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.addr"};
ProgramLabelMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.lab"}; ProgramLabelMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.lab"};
@ -525,7 +524,6 @@ module testbench();
end end
else begin else begin
memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"}; memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"};
$readmemh(memfilename, dut.imem.RAM);
$readmemh(memfilename, dut.uncore.dtim.RAM); $readmemh(memfilename, dut.uncore.dtim.RAM);
$display("Read memfile %s", memfilename); $display("Read memfile %s", memfilename);
ProgramAddrMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.addr"}; ProgramAddrMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.addr"};

View File

@ -1,413 +0,0 @@
///////////////////////////////////////////
// testbench-imperas.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Wally Testbench and helper modules
// Applies test programs from the Imperas suite
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
`include "wally-config.vh"
module testbench();
parameter DEBUG = 0;
parameter TESTSBP = 0;
logic clk;
logic reset;
int test, i, errors, totalerrors;
logic [31:0] sig32[0:10000];
logic [`XLEN-1:0] signature[0:10000];
logic [`XLEN-1:0] testadr;
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
logic [31:0] InstrW;
logic [`XLEN-1:0] meminit;
string tests64i[] = {
"peripherals/WALLY-PLIC", "2000"
//"peripherals/WALLY-UART", "2000"
};
string tests64ic[] = {
};
string tests64iNOc[] = {
};
string tests64m[] = {
};
string tests64a[] = {
};
string tests32a[] = {
};
string tests32m[] = {
};
string tests32ic[] = {
};
string tests32iNOc[] = {
};
string tests32i[] = {
};
string testsBP64[] = {
};
string tests64p[] = {
};
string tests[];
string ProgramAddrMapFile, ProgramLabelMapFile;
logic [`AHBW-1:0] HRDATAEXT;
logic HREADYEXT, HRESPEXT;
logic [31:0] HADDR;
logic [`AHBW-1:0] HWDATA;
logic HWRITE;
logic [2:0] HSIZE;
logic [2:0] HBURST;
logic [3:0] HPROT;
logic [1:0] HTRANS;
logic HMASTLOCK;
logic HCLK, HRESETn;
logic [`XLEN-1:0] PCW;
flopenr #(`XLEN) PCWReg(clk, reset, ~dut.hart.ieu.dp.StallW, dut.hart.ifu.PCM, PCW);
flopenr #(32) InstrWReg(clk, reset, ~dut.hart.ieu.dp.StallW, dut.hart.ifu.InstrM, InstrW);
// pick tests based on modes supported
initial begin
if (`XLEN == 64) begin // RV64
if (TESTSBP) begin
tests = testsBP64;
end else begin
tests = {tests64i};
if (`C_SUPPORTED) tests = {tests, tests64ic};
else tests = {tests, tests64iNOc};
if (`M_SUPPORTED) tests = {tests, tests64m};
// if (`F_SUPPORTED) tests = {tests64f, tests};
// if (`D_SUPPORTED) tests = {tests64d, tests};
if (`A_SUPPORTED) tests = {tests, tests64a};
end
// tests = {tests64a, tests};
tests = {tests, tests64p};
end else begin // RV32
// *** add the 32 bit bp tests
tests = {tests32i};
if (`C_SUPPORTED % 2 == 1) tests = {tests, tests32ic};
else tests = {tests, tests32iNOc};
if (`M_SUPPORTED % 2 == 1) tests = {tests, tests32m};
// if (`F_SUPPORTED) tests = {tests32f, tests};
if (`A_SUPPORTED) tests = {tests, tests32a};
end
// tests = tests64p;
end
string signame, memfilename;
logic [31:0] GPIOPinsIn, GPIOPinsOut, GPIOPinsEn;
logic UARTSin, UARTSout;
// instantiate device to be tested
assign GPIOPinsIn = 0;
assign UARTSin = 1;
assign HREADYEXT = 1;
assign HRESPEXT = 0;
assign HRDATAEXT = 0;
wallypipelinedsoc dut(.*);
// Track names of instructions
instrTrackerTB it(clk, reset, dut.hart.ieu.dp.FlushE,
dut.hart.ifu.ic.InstrF, dut.hart.ifu.InstrD, dut.hart.ifu.InstrE,
dut.hart.ifu.InstrM, InstrW, InstrFName, InstrDName,
InstrEName, InstrMName, InstrWName);
// initialize tests
initial
begin
test = 0;
totalerrors = 0;
testadr = 0;
// fill memory with defined values to reduce Xs in simulation
if (`XLEN == 32) meminit = 32'hFEDC0123;
else meminit = 64'hFEDCBA9876543210;
for (i=0; i<=65535; i = i+1) begin
//dut.imem.RAM[i] = meminit;
// dut.uncore.RAM[i] = meminit;
end
// read test vectors into memory
memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"};
$readmemh(memfilename, dut.imem.RAM);
$readmemh(memfilename, dut.uncore.dtim.RAM);
ProgramAddrMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.addr"};
ProgramLabelMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.lab"};
$display("Read memfile %s", memfilename);
reset = 1; # 42; reset = 0;
end
// generate clock to sequence tests
always
begin
clk = 1; # 5; clk = 0; # 5;
end
// check results
always @(negedge clk)
begin
if (dut.hart.priv.EcallFaultM &&
(dut.hart.ieu.dp.regf.rf[3] == 1 || (dut.hart.ieu.dp.regf.we3 && dut.hart.ieu.dp.regf.a3 == 3 && dut.hart.ieu.dp.regf.wd3 == 1))) begin
$display("Code ended with ecall with gp = 1");
#60; // give time for instructions in pipeline to finish
// clear signature to prevent contamination from previous tests
for(i=0; i<10000; i=i+1) begin
sig32[i] = 'bx;
end
// read signature, reformat in 64 bits if necessary
signame = {"../../imperas-riscv-tests/work/", tests[test], ".signature.output"};
$readmemh(signame, sig32);
i = 0;
while (i < 10000) begin
if (`XLEN == 32) begin
signature[i] = sig32[i];
i = i+1;
end else begin
signature[i/2] = {sig32[i+1], sig32[i]};
i = i + 2;
end
end
// Check errors
i = 0;
errors = 0;
if (`XLEN == 32)
testadr = (`TIMBASE+tests[test+1].atohex())/4;
else
testadr = (`TIMBASE+tests[test+1].atohex())/8;
/* verilator lint_off INFINITELOOP */
while (signature[i] !== 'bx) begin
//$display("signature[%h] = %h", i, signature[i]);
if (signature[i] !== dut.uncore.dtim.RAM[testadr+i]) begin
if (signature[i+4] !== 'bx || signature[i] !== 32'hFFFFFFFF) begin
// report errors unless they are garbage at the end of the sim
// kind of hacky test for garbage right now
errors = errors+1;
$display(" Error on test %s result %d: adr = %h sim = %h, signature = %h",
tests[test], i, (testadr+i)*`XLEN/8, dut.uncore.dtim.RAM[testadr+i], signature[i]);
end
end
i = i + 1;
end
/* verilator lint_on INFINITELOOP */
if (errors == 0) $display("%s succeeded. Brilliant!!!", tests[test]);
else begin
$display("%s failed with %d errors. :(", tests[test], errors);
totalerrors = totalerrors+1;
end
test = test + 2;
if (test == tests.size()) begin
if (totalerrors == 0) $display("SUCCESS! All tests ran without failures.");
else $display("FAIL: %d test programs had errors", totalerrors);
$stop;
end
else begin
memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"};
$readmemh(memfilename, dut.imem.RAM);
$readmemh(memfilename, dut.uncore.dtim.RAM);
$display("Read memfile %s", memfilename);
ProgramAddrMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.addr"};
ProgramLabelMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.lab"};
reset = 1; # 17; reset = 0;
end
end
end // always @ (negedge clk)
// track the current function or global label
if (DEBUG == 1) begin : functionRadix
function_radix function_radix(.reset(reset),
.ProgramAddrMapFile(ProgramAddrMapFile),
.ProgramLabelMapFile(ProgramLabelMapFile));
end
// initialize the branch predictor
initial begin
$readmemb(`TWO_BIT_PRELOAD, dut.hart.ifu.bpred.Predictor.DirPredictor.PHT.memory);
$readmemb(`BTB_PRELOAD, dut.hart.ifu.bpred.TargetPredictor.memory.memory);
end
endmodule
/* verilator lint_on STMTDLY */
/* verilator lint_on WIDTH */
module instrTrackerTB(
input logic clk, reset, FlushE,
input logic [31:0] InstrF, InstrD,
input logic [31:0] InstrE, InstrM,
input logic [31:0] InstrW,
// output logic [31:0] InstrW,
output string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
// stage Instr to Writeback for visualization
// flopr #(32) InstrWReg(clk, reset, InstrM, InstrW);
instrNameDecTB fdec(InstrF, InstrFName);
instrNameDecTB ddec(InstrD, InstrDName);
instrNameDecTB edec(InstrE, InstrEName);
instrNameDecTB mdec(InstrM, InstrMName);
instrNameDecTB wdec(InstrW, InstrWName);
endmodule
// decode the instruction name, to help the test bench
module instrNameDecTB(
input logic [31:0] instr,
output string name);
logic [6:0] op;
logic [2:0] funct3;
logic [6:0] funct7;
logic [11:0] imm;
assign op = instr[6:0];
assign funct3 = instr[14:12];
assign funct7 = instr[31:25];
assign imm = instr[31:20];
// it would be nice to add the operands to the name
// create another variable called decoded
always_comb
casez({op, funct3})
10'b0000000_000: name = "BAD";
10'b0000011_000: name = "LB";
10'b0000011_001: name = "LH";
10'b0000011_010: name = "LW";
10'b0000011_011: name = "LD";
10'b0000011_100: name = "LBU";
10'b0000011_101: name = "LHU";
10'b0000011_110: name = "LWU";
10'b0010011_000: if (instr[31:15] == 0 && instr[11:7] ==0) name = "NOP/FLUSH";
else name = "ADDI";
10'b0010011_001: if (funct7[6:1] == 6'b000000) name = "SLLI";
else name = "ILLEGAL";
10'b0010011_010: name = "SLTI";
10'b0010011_011: name = "SLTIU";
10'b0010011_100: name = "XORI";
10'b0010011_101: if (funct7[6:1] == 6'b000000) name = "SRLI";
else if (funct7[6:1] == 6'b010000) name = "SRAI";
else name = "ILLEGAL";
10'b0010011_110: name = "ORI";
10'b0010011_111: name = "ANDI";
10'b0010111_???: name = "AUIPC";
10'b0100011_000: name = "SB";
10'b0100011_001: name = "SH";
10'b0100011_010: name = "SW";
10'b0100011_011: name = "SD";
10'b0011011_000: name = "ADDIW";
10'b0011011_001: name = "SLLIW";
10'b0011011_101: if (funct7 == 7'b0000000) name = "SRLIW";
else if (funct7 == 7'b0100000) name = "SRAIW";
else name = "ILLEGAL";
10'b0111011_000: if (funct7 == 7'b0000000) name = "ADDW";
else if (funct7 == 7'b0100000) name = "SUBW";
else if (funct7 == 7'b0000001) name = "MULW";
else name = "ILLEGAL";
10'b0111011_001: if (funct7 == 7'b0000000) name = "SLLW";
else if (funct7 == 7'b0000001) name = "DIVW";
else name = "ILLEGAL";
10'b0111011_101: if (funct7 == 7'b0000000) name = "SRLW";
else if (funct7 == 7'b0100000) name = "SRAW";
else if (funct7 == 7'b0000001) name = "DIVUW";
else name = "ILLEGAL";
10'b0111011_110: if (funct7 == 7'b0000001) name = "REMW";
else name = "ILLEGAL";
10'b0111011_111: if (funct7 == 7'b0000001) name = "REMUW";
else name = "ILLEGAL";
10'b0110011_000: if (funct7 == 7'b0000000) name = "ADD";
else if (funct7 == 7'b0000001) name = "MUL";
else if (funct7 == 7'b0100000) name = "SUB";
else name = "ILLEGAL";
10'b0110011_001: if (funct7 == 7'b0000000) name = "SLL";
else if (funct7 == 7'b0000001) name = "MULH";
else name = "ILLEGAL";
10'b0110011_010: if (funct7 == 7'b0000000) name = "SLT";
else if (funct7 == 7'b0000001) name = "MULHSU";
else name = "ILLEGAL";
10'b0110011_011: if (funct7 == 7'b0000000) name = "SLTU";
else if (funct7 == 7'b0000001) name = "MULHU";
else name = "ILLEGAL";
10'b0110011_100: if (funct7 == 7'b0000000) name = "XOR";
else if (funct7 == 7'b0000001) name = "DIV";
else name = "ILLEGAL";
10'b0110011_101: if (funct7 == 7'b0000000) name = "SRL";
else if (funct7 == 7'b0000001) name = "DIVU";
else if (funct7 == 7'b0100000) name = "SRA";
else name = "ILLEGAL";
10'b0110011_110: if (funct7 == 7'b0000000) name = "OR";
else if (funct7 == 7'b0000001) name = "REM";
else name = "ILLEGAL";
10'b0110011_111: if (funct7 == 7'b0000000) name = "AND";
else if (funct7 == 7'b0000001) name = "REMU";
else name = "ILLEGAL";
10'b0110111_???: name = "LUI";
10'b1100011_000: name = "BEQ";
10'b1100011_001: name = "BNE";
10'b1100011_100: name = "BLT";
10'b1100011_101: name = "BGE";
10'b1100011_110: name = "BLTU";
10'b1100011_111: name = "BGEU";
10'b1100111_000: name = "JALR";
10'b1101111_???: name = "JAL";
10'b1110011_000: if (imm == 0) name = "ECALL";
else if (imm == 1) name = "EBREAK";
else if (imm == 2) name = "URET";
else if (imm == 258) name = "SRET";
else if (imm == 770) name = "MRET";
else name = "ILLEGAL";
10'b1110011_001: name = "CSRRW";
10'b1110011_010: name = "CSRRS";
10'b1110011_011: name = "CSRRC";
10'b1110011_101: name = "CSRRWI";
10'b1110011_110: name = "CSRRSI";
10'b1110011_111: name = "CSRRCI";
10'b0101111_010: if (funct7[6:2] == 5'b00010) name = "LR.W";
else if (funct7[6:2] == 5'b00011) name = "SC.W";
else if (funct7[6:2] == 5'b00001) name = "AMOSWAP.W";
else if (funct7[6:2] == 5'b00000) name = "AMOADD.W";
else if (funct7[6:2] == 5'b00100) name = "AMOAXOR.W";
else if (funct7[6:2] == 5'b01100) name = "AMOAND.W";
else if (funct7[6:2] == 5'b01000) name = "AMOOR.W";
else if (funct7[6:2] == 5'b10000) name = "AMOMIN.W";
else if (funct7[6:2] == 5'b10100) name = "AMOMAX.W";
else if (funct7[6:2] == 5'b11000) name = "AMOMINU.W";
else if (funct7[6:2] == 5'b11100) name = "AMOMAXU.W";
else name = "ILLEGAL";
10'b0101111_011: if (funct7[6:2] == 5'b00010) name = "LR.D";
else if (funct7[6:2] == 5'b00011) name = "SC.D";
else if (funct7[6:2] == 5'b00001) name = "AMOSWAP.D";
else if (funct7[6:2] == 5'b00000) name = "AMOADD.D";
else if (funct7[6:2] == 5'b00100) name = "AMOAXOR.D";
else if (funct7[6:2] == 5'b01100) name = "AMOAND.D";
else if (funct7[6:2] == 5'b01000) name = "AMOOR.D";
else if (funct7[6:2] == 5'b10000) name = "AMOMIN.D";
else if (funct7[6:2] == 5'b10100) name = "AMOMAX.D";
else if (funct7[6:2] == 5'b11000) name = "AMOMINU.D";
else if (funct7[6:2] == 5'b11100) name = "AMOMAXU.D";
else name = "ILLEGAL";
10'b0001111_???: name = "FENCE";
default: name = "ILLEGAL";
endcase
endmodule

View File

@ -116,7 +116,6 @@ module testbench();
end end
// read test vectors into memory // read test vectors into memory
memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"}; memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"};
$readmemh(memfilename, dut.imem.RAM);
$readmemh(memfilename, dut.uncore.dtim.RAM); $readmemh(memfilename, dut.uncore.dtim.RAM);
ProgramAddrMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.addr"}; ProgramAddrMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.addr"};
ProgramLabelMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.lab"}; ProgramLabelMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.lab"};
@ -191,7 +190,6 @@ module testbench();
end end
else begin else begin
memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"}; memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"};
$readmemh(memfilename, dut.imem.RAM);
$readmemh(memfilename, dut.uncore.dtim.RAM); $readmemh(memfilename, dut.uncore.dtim.RAM);
$display("Read memfile %s", memfilename); $display("Read memfile %s", memfilename);
ProgramAddrMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.addr"}; ProgramAddrMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.addr"};