Merge pull request #453 from davidharrishmc/dev

Fixed regression error of watchdog timeout when PCM is optimized out of the IFU
This commit is contained in:
Rose Thompson 2023-11-05 15:53:57 -08:00 committed by GitHub
commit 380694293f
29 changed files with 136 additions and 113 deletions

View File

@ -20,7 +20,7 @@
--override cpu/Zicboz=T --override cpu/Zicboz=T
--override cpu/Svpbmt=T --override cpu/Svpbmt=T
# 64 KiB continuous huge pages supported # 64 KiB continuous huge pages supported
--override cpu/Svnapot_page_mask=1<<16 --override cpu/Svnapot_page_mask=65536
# clarify # clarify

View File

@ -8,15 +8,9 @@ basepath=$(dirname $0)/..
#for config in rv32e rv64gc rv32gc rv32imc rv32i rv64i rv64fpquad; do #for config in rv32e rv64gc rv32gc rv32imc rv32i rv64i rv64fpquad; do
for config in rv64gc; do for config in rv64gc; do
echo "$config simulating..." echo "$config simulating..."
if !($verilator --timescale "1ns/1ns" --timing --cc "$@" --top-module testbench "-I$basepath/config/shared" "-I$basepath/config/$config" $basepath/src/wally/cvw.sv $basepath/testbench/common/*.sv $basepath/testbench/testbench.sv $basepath/src/*/*.sv $basepath/src/*/*/*.sv --relative-includes ); then if !($verilator --timescale "1ns/1ns" --timing --exe --cc "$@" --top-module testbench "-I$basepath/config/shared" "-I$basepath/config/$config" $basepath/src/cvw.sv $basepath/testbench/testbench.sv $basepath/testbench/common/*.sv $basepath/src/*/*.sv $basepath/src/*/*/*.sv --relative-includes ); then
echo "Exiting after $config lint due to errors or warnings" echo "Exiting after $config lint due to errors or warnings"
exit 1 exit 1
fi fi
done done
echo "All lints run with no errors or warnings" echo "Verilation complete"
# --lint-only just runs lint rather than trying to compile and simulate
# -I points to the include directory where files such as `include config.vh are found
# For more exhaustive (and sometimes spurious) warnings, add --Wall to the Verilator command
# Unfortunately, this produces a bunch of UNUSED and UNDRIVEN signal warnings in blocks that are configured to not exist.

View File

@ -126,7 +126,7 @@ module cacheway import cvw::*; #(parameter cvw_t P,
// Tag Array // Tag Array
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
ram1p1rwe #(.P(P), .DEPTH(NUMLINES), .WIDTH(TAGLEN)) CacheTagMem(.clk, .ce(CacheEn), ram1p1rwe #(.USE_SRAM(P.USE_SRAM), .DEPTH(NUMLINES), .WIDTH(TAGLEN)) CacheTagMem(.clk, .ce(CacheEn),
.addr(CacheSet), .dout(ReadTag), .addr(CacheSet), .dout(ReadTag),
.din(PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]), .we(SetValidEN)); .din(PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]), .we(SetValidEN));
@ -148,12 +148,12 @@ module cacheway import cvw::*; #(parameter cvw_t P,
for(words = 0; words < NUMSRAM; words++) begin: word for(words = 0; words < NUMSRAM; words++) begin: word
if (!READ_ONLY_CACHE) begin:wordram if (!READ_ONLY_CACHE) begin:wordram
ram1p1rwbe #(.P(P), .DEPTH(NUMLINES), .WIDTH(SRAMLEN)) CacheDataMem(.clk, .ce(CacheEn), .addr(CacheSet), ram1p1rwbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(NUMLINES), .WIDTH(SRAMLEN)) CacheDataMem(.clk, .ce(CacheEn), .addr(CacheSet),
.dout(ReadDataLine[SRAMLEN*(words+1)-1:SRAMLEN*words]), .dout(ReadDataLine[SRAMLEN*(words+1)-1:SRAMLEN*words]),
.din(LineWriteData[SRAMLEN*(words+1)-1:SRAMLEN*words]), .din(LineWriteData[SRAMLEN*(words+1)-1:SRAMLEN*words]),
.we(SelectedWriteWordEn), .bwe(FinalByteMask[SRAMLENINBYTES*(words+1)-1:SRAMLENINBYTES*words])); .we(SelectedWriteWordEn), .bwe(FinalByteMask[SRAMLENINBYTES*(words+1)-1:SRAMLENINBYTES*words]));
end else begin:wordram // no byte-enable needed for i$. end else begin:wordram // no byte-enable needed for i$.
ram1p1rwe #(.P(P), .DEPTH(NUMLINES), .WIDTH(SRAMLEN)) CacheDataMem(.clk, .ce(CacheEn), .addr(CacheSet), ram1p1rwe #(.USE_SRAM(P.USE_SRAM), .DEPTH(NUMLINES), .WIDTH(SRAMLEN)) CacheDataMem(.clk, .ce(CacheEn), .addr(CacheSet),
.dout(ReadDataLine[SRAMLEN*(words+1)-1:SRAMLEN*words]), .dout(ReadDataLine[SRAMLEN*(words+1)-1:SRAMLEN*words]),
.din(LineWriteData[SRAMLEN*(words+1)-1:SRAMLEN*words]), .din(LineWriteData[SRAMLEN*(words+1)-1:SRAMLEN*words]),
.we(SelectedWriteWordEn)); .we(SelectedWriteWordEn));

View File

@ -65,7 +65,8 @@ module fdivsqrtcycles import cvw::*; #(parameter cvw_t P) (
endcase endcase
always_comb begin always_comb begin
if (SqrtE) fbits = Nf + 2 + 2; // Nf + two fractional bits for round/guard + 2 for right shift by up to 2 if (SqrtE) fbits = Nf + 2 + 1; // Nf + two fractional bits for round/guard + 2 for right shift by up to 2 *** unclear why it works with just +1; is it related to DIVCOPIES logic below?
// if (SqrtE) fbits = Nf + 2 + 2; // Nf + two fractional bits for round/guard + 2 for right shift by up to 2
else fbits = Nf + 2 + P.LOGR; // Nf + two fractional bits for round/guard + integer bits - try this when placing results in msbs else fbits = Nf + 2 + P.LOGR; // Nf + two fractional bits for round/guard + integer bits - try this when placing results in msbs
if (P.IDIV_ON_FPU) CyclesE = IntDivE ? ((nE + 1)/P.DIVCOPIES) : (fbits + (P.LOGR*P.DIVCOPIES)-1)/(P.LOGR*P.DIVCOPIES); if (P.IDIV_ON_FPU) CyclesE = IntDivE ? ((nE + 1)/P.DIVCOPIES) : (fbits + (P.LOGR*P.DIVCOPIES)-1)/(P.LOGR*P.DIVCOPIES);
else CyclesE = (fbits + (P.LOGR*P.DIVCOPIES)-1)/(P.LOGR*P.DIVCOPIES); else CyclesE = (fbits + (P.LOGR*P.DIVCOPIES)-1)/(P.LOGR*P.DIVCOPIES);

View File

@ -32,8 +32,7 @@
// WIDTH is number of bits in one "word" of the memory, DEPTH is number of such words // WIDTH is number of bits in one "word" of the memory, DEPTH is number of such words
module ram1p1rwbe import cvw::*; #(parameter cvw_t P, parameter DEPTH=64, WIDTH=44, module ram1p1rwbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=64, WIDTH=44, PRELOAD_ENABLED=0) (
parameter PRELOAD_ENABLED=0) (
input logic clk, input logic clk,
input logic ce, input logic ce,
input logic [$clog2(DEPTH)-1:0] addr, input logic [$clog2(DEPTH)-1:0] addr,
@ -48,7 +47,7 @@ module ram1p1rwbe import cvw::*; #(parameter cvw_t P, parameter DEPTH=64, WIDTH=
// *************************************************************************** // ***************************************************************************
// TRUE SRAM macro // TRUE SRAM macro
// *************************************************************************** // ***************************************************************************
if ((P.USE_SRAM == 1) & (WIDTH == 128) & (DEPTH == 64)) begin // Cache data subarray if ((USE_SRAM == 1) & (WIDTH == 128) & (DEPTH == 64)) begin // Cache data subarray
genvar index; genvar index;
// 64 x 128-bit SRAM // 64 x 128-bit SRAM
logic [WIDTH-1:0] BitWriteMask; logic [WIDTH-1:0] BitWriteMask;
@ -58,7 +57,7 @@ module ram1p1rwbe import cvw::*; #(parameter cvw_t P, parameter DEPTH=64, WIDTH=
.A(addr), .D(din), .A(addr), .D(din),
.BWEB(~BitWriteMask), .Q(dout)); .BWEB(~BitWriteMask), .Q(dout));
end else if ((P.USE_SRAM == 1) & (WIDTH == 44) & (DEPTH == 64)) begin // RV64 cache tag end else if ((USE_SRAM == 1) & (WIDTH == 44) & (DEPTH == 64)) begin // RV64 cache tag
genvar index; genvar index;
// 64 x 44-bit SRAM // 64 x 44-bit SRAM
logic [WIDTH-1:0] BitWriteMask; logic [WIDTH-1:0] BitWriteMask;
@ -68,7 +67,7 @@ module ram1p1rwbe import cvw::*; #(parameter cvw_t P, parameter DEPTH=64, WIDTH=
.A(addr), .D(din), .A(addr), .D(din),
.BWEB(~BitWriteMask), .Q(dout)); .BWEB(~BitWriteMask), .Q(dout));
end else if ((P.USE_SRAM == 1) & (WIDTH == 22) & (DEPTH == 64)) begin // RV32 cache tag end else if ((USE_SRAM == 1) & (WIDTH == 22) & (DEPTH == 64)) begin // RV32 cache tag
genvar index; genvar index;
// 64 x 22-bit SRAM // 64 x 22-bit SRAM
logic [WIDTH-1:0] BitWriteMask; logic [WIDTH-1:0] BitWriteMask;

View File

@ -30,8 +30,7 @@
// WIDTH is number of bits in one "word" of the memory, DEPTH is number of such words // WIDTH is number of bits in one "word" of the memory, DEPTH is number of such words
module ram1p1rwe import cvw::* ; #(parameter cvw_t P, module ram1p1rwe import cvw::* ; #(parameter USE_SRAM=0, DEPTH=64, WIDTH=44) (
parameter DEPTH=64, WIDTH=44) (
input logic clk, input logic clk,
input logic ce, input logic ce,
input logic [$clog2(DEPTH)-1:0] addr, input logic [$clog2(DEPTH)-1:0] addr,
@ -45,19 +44,19 @@ module ram1p1rwe import cvw::* ; #(parameter cvw_t P,
// *************************************************************************** // ***************************************************************************
// TRUE SRAM macro // TRUE SRAM macro
// *************************************************************************** // ***************************************************************************
if ((P.USE_SRAM == 1) & (WIDTH == 128) & (DEPTH == 64)) begin // Cache data subarray if ((USE_SRAM == 1) & (WIDTH == 128) & (DEPTH == 64)) begin // Cache data subarray
// 64 x 128-bit SRAM // 64 x 128-bit SRAM
ram1p1rwbe_64x128 sram1A (.CLK(clk), .CEB(~ce), .WEB(~we), ram1p1rwbe_64x128 sram1A (.CLK(clk), .CEB(~ce), .WEB(~we),
.A(addr), .D(din), .A(addr), .D(din),
.BWEB('0), .Q(dout)); .BWEB('0), .Q(dout));
end else if ((P.USE_SRAM == 1) & (WIDTH == 44) & (DEPTH == 64)) begin // RV64 cache tag end else if ((USE_SRAM == 1) & (WIDTH == 44) & (DEPTH == 64)) begin // RV64 cache tag
// 64 x 44-bit SRAM // 64 x 44-bit SRAM
ram1p1rwbe_64x44 sram1B (.CLK(clk), .CEB(~ce), .WEB(~we), ram1p1rwbe_64x44 sram1B (.CLK(clk), .CEB(~ce), .WEB(~we),
.A(addr), .D(din), .A(addr), .D(din),
.BWEB('0), .Q(dout)); .BWEB('0), .Q(dout));
end else if ((P.USE_SRAM == 1) & (WIDTH == 22) & (DEPTH == 64)) begin // RV32 cache tag end else if ((USE_SRAM == 1) & (WIDTH == 22) & (DEPTH == 64)) begin // RV32 cache tag
// 64 x 22-bit SRAM // 64 x 22-bit SRAM
ram1p1rwbe_64x22 sram1 (.CLK(clk), .CEB(~ce), .WEB(~we), ram1p1rwbe_64x22 sram1 (.CLK(clk), .CEB(~ce), .WEB(~we),
.A(addr), .D(din), .A(addr), .D(din),

View File

@ -31,8 +31,7 @@
// WIDTH is number of bits in one "word" of the memory, DEPTH is number of such words // WIDTH is number of bits in one "word" of the memory, DEPTH is number of such words
module ram2p1r1wbe import cvw::*; #(parameter cvw_t P, module ram2p1r1wbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=1024, WIDTH=68) (
parameter DEPTH=1024, WIDTH=68) (
input logic clk, input logic clk,
input logic ce1, ce2, input logic ce1, ce2,
input logic [$clog2(DEPTH)-1:0] ra1, input logic [$clog2(DEPTH)-1:0] ra1,
@ -51,7 +50,7 @@ module ram2p1r1wbe import cvw::*; #(parameter cvw_t P,
// TRUE Smem macro // TRUE Smem macro
// *************************************************************************** // ***************************************************************************
if ((P.USE_SRAM == 1) & (WIDTH == 68) & (DEPTH == 1024)) begin if ((USE_SRAM == 1) & (WIDTH == 68) & (DEPTH == 1024)) begin
ram2p1r1wbe_1024x68 memory1(.CLKA(clk), .CLKB(clk), ram2p1r1wbe_1024x68 memory1(.CLKA(clk), .CLKB(clk),
.CEBA(~ce1), .CEBB(~ce2), .CEBA(~ce1), .CEBB(~ce2),
@ -63,7 +62,7 @@ module ram2p1r1wbe import cvw::*; #(parameter cvw_t P,
.QA(rd1), .QA(rd1),
.QB()); .QB());
end else if ((P.USE_SRAM == 1) & (WIDTH == 36) & (DEPTH == 1024)) begin end else if ((USE_SRAM == 1) & (WIDTH == 36) & (DEPTH == 1024)) begin
ram2p1r1wbe_1024x36 memory1(.CLKA(clk), .CLKB(clk), ram2p1r1wbe_1024x36 memory1(.CLKA(clk), .CLKB(clk),
.CEBA(~ce1), .CEBB(~ce2), .CEBA(~ce1), .CEBB(~ce2),
@ -75,7 +74,7 @@ module ram2p1r1wbe import cvw::*; #(parameter cvw_t P,
.QA(rd1), .QA(rd1),
.QB()); .QB());
end else if ((P.USE_SRAM == 1) & (WIDTH == 2) & (DEPTH == 1024)) begin end else if ((USE_SRAM == 1) & (WIDTH == 2) & (DEPTH == 1024)) begin
logic [SRAMWIDTH-1:0] SRAMReadData; logic [SRAMWIDTH-1:0] SRAMReadData;
logic [SRAMWIDTH-1:0] SRAMWriteData; logic [SRAMWIDTH-1:0] SRAMWriteData;

View File

@ -25,9 +25,7 @@
// This model actually works correctly with vivado. // This model actually works correctly with vivado.
module rom1p1r #(parameter ADDR_WIDTH = 8, module rom1p1r #(parameter ADDR_WIDTH = 8, DATA_WIDTH = 32, PRELOAD_ENABLED = 0)
parameter DATA_WIDTH = 32,
parameter PRELOAD_ENABLED = 0)
(input logic clk, (input logic clk,
input logic ce, input logic ce,
input logic [ADDR_WIDTH-1:0] addr, input logic [ADDR_WIDTH-1:0] addr,

View File

@ -92,7 +92,7 @@ module btb import cvw::*; #(parameter cvw_t P,
// An optimization may be using a PC relative address. // An optimization may be using a PC relative address.
ram2p1r1wbe #(P, 2**Depth, P.XLEN+4) memory( ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**Depth), .WIDTH(P.XLEN+4)) memory(
.clk, .ce1(~StallF | reset), .ra1(PCNextFIndex), .rd1(TableBTBPredF), .clk, .ce1(~StallF | reset), .ra1(PCNextFIndex), .rd1(TableBTBPredF),
.ce2(~StallW & ~FlushW), .wa2(PCMIndex), .wd2({InstrClassM, IEUAdrM}), .we2(BTBWrongM), .bwe2('1)); .ce2(~StallW & ~FlushW), .wa2(PCMIndex), .wd2({InstrClassM, IEUAdrM}), .we2(BTBWrongM), .bwe2('1));

View File

@ -84,7 +84,7 @@ module gshare import cvw::*; #(parameter cvw_t P,
assign BPDirPredF = MatchX ? FwdNewDirPredF : TableBPDirPredF; assign BPDirPredF = MatchX ? FwdNewDirPredF : TableBPDirPredF;
ram2p1r1wbe #(P, 2**k, 2) PHT(.clk(clk), ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**k), .WIDTH(2)) PHT(.clk(clk),
.ce1(~StallF), .ce2(~StallW & ~FlushW), .ce1(~StallF), .ce2(~StallW & ~FlushW),
.ra1(IndexNextF), .ra1(IndexNextF),
.rd1(TableBPDirPredF), .rd1(TableBPDirPredF),

View File

@ -58,7 +58,7 @@ module gsharebasic import cvw::*; #(parameter cvw_t P,
assign IndexM = GHRM; assign IndexM = GHRM;
end end
ram2p1r1wbe #(P, 2**k, 2) PHT(.clk(clk), ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**k), .WIDTH(2)) PHT(.clk(clk),
.ce1(~StallF), .ce2(~StallW & ~FlushW), .ce1(~StallF), .ce2(~StallW & ~FlushW),
.ra1(IndexNextF), .ra1(IndexNextF),
.rd1(BPDirPredF), .rd1(BPDirPredF),

View File

@ -59,7 +59,7 @@ module localaheadbp import cvw::*; #(parameter cvw_t P,
//assign IndexNextF = LHR; //assign IndexNextF = LHR;
assign IndexM = LHRW; assign IndexM = LHRW;
ram2p1r1wbe #(P, 2**k, 2) PHT(.clk(clk), ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**k), .WIDTH(2)) PHT(.clk(clk),
.ce1(~StallD), .ce2(~StallW & ~FlushW), .ce1(~StallD), .ce2(~StallW & ~FlushW),
.ra1(LHRF), .ra1(LHRF),
.rd1(BPDirPredD), .rd1(BPDirPredD),
@ -92,7 +92,7 @@ module localaheadbp import cvw::*; #(parameter cvw_t P,
assign IndexLHRM = {PCW[m+1] ^ PCW[1], PCW[m:2]}; assign IndexLHRM = {PCW[m+1] ^ PCW[1], PCW[m:2]};
assign IndexLHRNextF = {PCNextF[m+1] ^ PCNextF[1], PCNextF[m:2]}; assign IndexLHRNextF = {PCNextF[m+1] ^ PCNextF[1], PCNextF[m:2]};
ram2p1r1wbe #(P, 2**m, k) BHT(.clk(clk), ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**m), .WIDTH(k)) BHT(.clk(clk),
.ce1(~StallF), .ce2(~StallW & ~FlushW), .ce1(~StallF), .ce2(~StallW & ~FlushW),
.ra1(IndexLHRNextF), .ra1(IndexLHRNextF),
.rd1(LHRF), .rd1(LHRF),

View File

@ -56,7 +56,7 @@ module localbpbasic import cvw::*; #(parameter cvw_t P,
assign IndexNextF = LHR; assign IndexNextF = LHR;
assign IndexM = LHRM; assign IndexM = LHRM;
ram2p1r1wbe #(P, 2**k, 2) PHT(.clk(clk), ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**k), .WIDTH(2)) PHT(.clk(clk),
.ce1(~StallF), .ce2(~StallW & ~FlushW), .ce1(~StallF), .ce2(~StallW & ~FlushW),
.ra1(IndexNextF), .ra1(IndexNextF),
.rd1(BPDirPredF), .rd1(BPDirPredF),

View File

@ -58,7 +58,7 @@ module localrepairbp import cvw::*; #(parameter cvw_t P,
logic SpeculativeFlushedF; logic SpeculativeFlushedF;
ram2p1r1wbe #(P, 2**k, 2) PHT(.clk(clk), ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**k), .WIDTH(2)) PHT(.clk(clk),
.ce1(~StallD), .ce2(~StallW & ~FlushW), .ce1(~StallD), .ce2(~StallW & ~FlushW),
.ra1(LHRF), .ra1(LHRF),
.rd1(BPDirPredD), .rd1(BPDirPredD),
@ -89,7 +89,7 @@ module localrepairbp import cvw::*; #(parameter cvw_t P,
assign IndexLHRM = {PCW[m+1] ^ PCW[1], PCW[m:2]}; assign IndexLHRM = {PCW[m+1] ^ PCW[1], PCW[m:2]};
assign IndexLHRNextF = {PCNextF[m+1] ^ PCNextF[1], PCNextF[m:2]}; assign IndexLHRNextF = {PCNextF[m+1] ^ PCNextF[1], PCNextF[m:2]};
ram2p1r1wbe #(P, 2**m, k) BHT(.clk(clk), ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**m), .WIDTH(k)) BHT(.clk(clk),
.ce1(~StallF), .ce2(~StallW & ~FlushW), .ce1(~StallF), .ce2(~StallW & ~FlushW),
.ra1(IndexLHRNextF), .ra1(IndexLHRNextF),
.rd1(LHRCommittedF), .rd1(LHRCommittedF),
@ -101,7 +101,7 @@ module localrepairbp import cvw::*; #(parameter cvw_t P,
assign IndexLHRD = {PCE[m+1] ^ PCE[1], PCE[m:2]}; assign IndexLHRD = {PCE[m+1] ^ PCE[1], PCE[m:2]};
assign LHRNextE = BranchD ? {BPDirPredD[1], LHRE[k-1:1]} : LHRE; assign LHRNextE = BranchD ? {BPDirPredD[1], LHRE[k-1:1]} : LHRE;
// *** replace with a small CAM // *** replace with a small CAM
ram2p1r1wbe #(P, 2**m, k) SHB(.clk(clk), ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**m), .WIDTH(k)) SHB(.clk(clk),
.ce1(~StallF), .ce2(~StallE & ~FlushE), .ce1(~StallF), .ce2(~StallE & ~FlushE),
.ra1(IndexLHRNextF), .ra1(IndexLHRNextF),
.rd1(LHRSpeculativeF), .rd1(LHRSpeculativeF),

View File

@ -53,7 +53,7 @@ module twoBitPredictor import cvw::*; #(parameter cvw_t P, parameter XLEN,
assign IndexM = {PCM[k+1] ^ PCM[1], PCM[k:2]}; assign IndexM = {PCM[k+1] ^ PCM[1], PCM[k:2]};
ram2p1r1wbe #(P, 2**k, 2) PHT(.clk(clk), ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**k), .WIDTH(2)) PHT(.clk(clk),
.ce1(~StallF), .ce2(~StallW & ~FlushW), .ce1(~StallF), .ce2(~StallW & ~FlushW),
.ra1(IndexNextF), .ra1(IndexNextF),
.rd1(BPDirPredF), .rd1(BPDirPredF),

View File

@ -114,10 +114,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
logic [31:0] IROMInstrF; // Instruction from the IROM logic [31:0] IROMInstrF; // Instruction from the IROM
logic [31:0] ICacheInstrF; // Instruction from the I$ logic [31:0] ICacheInstrF; // Instruction from the I$
logic [31:0] InstrRawF; // Instruction from the IROM, I$, or bus logic [31:0] InstrRawF; // Instruction from the IROM, I$, or bus
logic CompressedF; // The fetched instruction is compressed logic CompressedF, CompressedE; // The fetched instruction is compressed
logic CompressedD; // The decoded instruction is compressed
logic CompressedE; // The execution instruction is compressed
logic CompressedM; // The execution instruction is compressed
logic [31:0] PostSpillInstrRawF; // Fetch instruction after merge two halves of spill logic [31:0] PostSpillInstrRawF; // Fetch instruction after merge two halves of spill
logic [31:0] InstrRawD; // Non-decompressed instruction in the Decode stage logic [31:0] InstrRawD; // Non-decompressed instruction in the Decode stage
logic IllegalIEUInstrD; // IEU Instruction (regular or compressed) is not good logic IllegalIEUInstrD; // IEU Instruction (regular or compressed) is not good
@ -389,31 +386,40 @@ module ifu import cvw::*; #(parameter cvw_t P) (
assign BranchMisalignedFaultE = (IEUAdrE[1] & ~P.COMPRESSED_SUPPORTED) & PCSrcE; assign BranchMisalignedFaultE = (IEUAdrE[1] & ~P.COMPRESSED_SUPPORTED) & PCSrcE;
flopenr #(1) InstrMisalignedReg(clk, reset, ~StallM, BranchMisalignedFaultE, InstrMisalignedFaultM); flopenr #(1) InstrMisalignedReg(clk, reset, ~StallM, BranchMisalignedFaultE, InstrMisalignedFaultM);
// Instruction and PC pipeline registers // Instruction and PC pipeline registers flush to NOP, not zero
// Cannot use flopenrc for Instr(E/M) as it resets to NOP not 0.
mux2 #(32) FlushInstrEMux(InstrD, nop, FlushE, NextInstrD); mux2 #(32) FlushInstrEMux(InstrD, nop, FlushE, NextInstrD);
mux2 #(32) FlushInstrMMux(InstrE, nop, FlushM, NextInstrE);
flopenr #(32) InstrEReg(clk, reset, ~StallE, NextInstrD, InstrE); flopenr #(32) InstrEReg(clk, reset, ~StallE, NextInstrD, InstrE);
flopenr #(P.XLEN) PCEReg(clk, reset, ~StallE, PCD, PCE); flopenr #(P.XLEN) PCEReg(clk, reset, ~StallE, PCD, PCE);
// InstrM is only needed with CSRs or atomic operations // InstrM is only needed with CSRs or atomic operations
if (P.ZICSR_SUPPORTED | P.A_SUPPORTED) if (P.ZICSR_SUPPORTED | P.A_SUPPORTED) begin
mux2 #(32) FlushInstrMMux(InstrE, nop, FlushM, NextInstrE);
flopenr #(32) InstrMReg(clk, reset, ~StallM, NextInstrE, InstrM); flopenr #(32) InstrMReg(clk, reset, ~StallM, NextInstrE, InstrM);
else assign InstrM = 0; end else assign InstrM = 0;
// PCM is only needed with CSRs or branch prediction // PCM is only needed with CSRs or branch prediction
if (P.ZICSR_SUPPORTED | P.BPRED_SUPPORTED) if (P.ZICSR_SUPPORTED | P.BPRED_SUPPORTED)
flopenr #(P.XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM); flopenr #(P.XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM);
else assign PCM = 0; else assign PCM = 0;
flopenrc #(1) CompressedDReg(clk, reset, FlushD, ~StallD, CompressedF, CompressedD); // If compressed instructions are supported, increment PCLink by 2 or 4 for a jal. Otherwise, just by 4
flopenrc #(1) CompressedEReg(clk, reset, FlushE, ~StallE, CompressedD, CompressedE); if (P.COMPRESSED_SUPPORTED) begin
assign PCLinkE = PCE + (CompressedE ? 'd2 : 'd4); // 'd4 means 4 but stops Design Compiler complaining about signed to unsigned conversion logic CompressedD; // instruction is compressed
flopenrc #(1) CompressedDReg(clk, reset, FlushD, ~StallD, CompressedF, CompressedD);
flopenrc #(1) CompressedEReg(clk, reset, FlushE, ~StallE, CompressedD, CompressedE);
assign PCLinkE = PCE + (CompressedE ? 'd2 : 'd4); // 'd4 means 4 but stops Design Compiler complaining about signed to unsigned conversion
end else begin
assign CompressedE = 0;
assign PCLinkE = PCE + 'd4;
end
// pipeline original compressed instruction in case it is needed for MTVAL on an illegal instruction exception // pipeline original compressed instruction in case it is needed for MTVAL on an illegal instruction exception
if (P.ZICSR_SUPPORTED) begin if (P.ZICSR_SUPPORTED & P.COMPRESSED_SUPPORTED | 1) begin
logic CompressedM; // instruction is compressed
flopenrc #(16) InstrRawEReg(clk, reset, FlushE, ~StallE, InstrRawD[15:0], InstrRawE); flopenrc #(16) InstrRawEReg(clk, reset, FlushE, ~StallE, InstrRawD[15:0], InstrRawE);
flopenrc #(16) InstrRawMReg(clk, reset, FlushM, ~StallM, InstrRawE, InstrRawM); flopenrc #(16) InstrRawMReg(clk, reset, FlushM, ~StallM, InstrRawE, InstrRawM);
flopenrc #(1) CompressedMReg(clk, reset, FlushM, ~StallM, CompressedE, CompressedM); flopenrc #(1) CompressedMReg(clk, reset, FlushM, ~StallM, CompressedE, CompressedM);
mux2 #(32) InstrOrigMux(InstrM, {16'b0, InstrRawM}, CompressedM, InstrOrigM); mux2 #(32) InstrOrigMux(InstrM, {16'b0, InstrRawM}, CompressedM, InstrOrigM);
end else assign InstrOrigM = 0; end else
assign InstrOrigM = InstrM;
endmodule endmodule

View File

@ -49,6 +49,6 @@ module dtim import cvw::*; #(parameter cvw_t P) (
assign we = MemRWM[0] & ~FlushW; // have to ignore write if Trap. assign we = MemRWM[0] & ~FlushW; // have to ignore write if Trap.
ram1p1rwbe #(.P(P), .DEPTH(DEPTH), .WIDTH(P.LLEN)) ram1p1rwbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(DEPTH), .WIDTH(P.LLEN))
ram(.clk, .ce, .we, .bwe(ByteMaskM), .addr(DTIMAdr[ADDR_WDITH+OFFSET-1:OFFSET]), .dout(ReadDataWordM), .din(WriteDataM)); ram(.clk, .ce, .we, .bwe(ByteMaskM), .addr(DTIMAdr[ADDR_WDITH+OFFSET-1:OFFSET]), .dout(ReadDataWordM), .din(WriteDataM));
endmodule endmodule

View File

@ -71,7 +71,7 @@ module ram_ahb import cvw::*; #(parameter cvw_t P,
mux2 #(P.PA_BITS) adrmux(HADDR, HADDRD, memwriteD | ~HREADY, RamAddr); mux2 #(P.PA_BITS) adrmux(HADDR, HADDRD, memwriteD | ~HREADY, RamAddr);
// single-ported RAM // single-ported RAM
ram1p1rwbe #(.P(P), .DEPTH(RANGE/8), .WIDTH(P.XLEN), .PRELOAD_ENABLED(P.FPGA)) memory(.clk(HCLK), .ce(1'b1), ram1p1rwbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(RANGE/8), .WIDTH(P.XLEN), .PRELOAD_ENABLED(P.FPGA)) memory(.clk(HCLK), .ce(1'b1),
.addr(RamAddr[ADDR_WIDTH+OFFSET-1:OFFSET]), .we(memwriteD), .din(HWDATA), .bwe(HWSTRB), .dout(HREADRam)); .addr(RamAddr[ADDR_WIDTH+OFFSET-1:OFFSET]), .we(memwriteD), .din(HWDATA), .bwe(HWSTRB), .dout(HREADRam));
// use this to add arbitrary latency to ram. Helps test AHB controller correctness // use this to add arbitrary latency to ram. Helps test AHB controller correctness

View File

@ -32,17 +32,15 @@ eval file copy -force [glob ${hdl_src}/cvw.sv] {$outputDir/hdl/}
eval file copy -force [glob ${hdl_src}/*/*.sv] {$outputDir/hdl/} eval file copy -force [glob ${hdl_src}/*/*.sv] {$outputDir/hdl/}
eval file copy -force [glob ${hdl_src}/*/*/*.sv] {$outputDir/hdl/} eval file copy -force [glob ${hdl_src}/*/*/*.sv] {$outputDir/hdl/}
# Check if a wrapper is needed (when cvw_t parameters are used) # Check if a wrapper is needed and create it (to pass parameters when cvw_t parameters are used)
set wrapper 0 set wrapper 0
if {[eval exec grep "cvw_t" {$outputDir/hdl/$::env(DESIGN).sv}] ne ""} { if {[catch {eval exec grep "cvw_t" $outputDir/hdl/$::env(DESIGN).sv}] == 0} {
echo "Creating wrapper"
set wrapper 1 set wrapper 1
# make the wrapper # make the wrapper
exec python3 $::env(WALLY)/synthDC/scripts/wrapperGen.py $::env(DESIGN) $outputDir/hdl exec python3 $::env(WALLY)/synthDC/scripts/wrapperGen.py $::env(DESIGN) $outputDir/hdl
} }
# Only for FMA class project; comment out when done
# eval file copy -force [glob ${hdl_src}/fma/fma16.v] {hdl/}
# Enables name mapping # Enables name mapping
if { $saifpower == 1 } { if { $saifpower == 1 } {
saif_map -start saif_map -start

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////// ///////////////////////////////////////////
// shadowmem.sv // DCacheFlushFSM.sv
// //
// Written: David Harris David_Harris@hmc.edu and Ross Thompson ross1728@gmail.com // Written: David Harris David_Harris@hmc.edu and Ross Thompson ross1728@gmail.com
// Modified: 14 June 2023 // Modified: 14 June 2023

View File

@ -217,7 +217,7 @@ module loggers import cvw::*; #(parameter cvw_t P,
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.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

View File

@ -30,11 +30,13 @@ module watchdog #(parameter XLEN, WatchDogTimerThreshold)
); );
// check for hang up. // check for hang up.
logic [XLEN-1:0] PCW; logic [XLEN-1:0] PCM, PCW, OldPCW;
flopenr #(XLEN) PCWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.PCM, PCW);
logic [XLEN-1:0] OldPCW;
integer WatchDogTimerCount; integer WatchDogTimerCount;
logic WatchDogTimeOut; logic WatchDogTimeOut;
flopenr #(XLEN) PCMReg(clk, reset, ~dut.core.ifu.StallM, dut.core.ifu.PCE, PCM); // duplicate PCM register because it is not in ifu for all configurations
flopenr #(XLEN) PCWReg(clk, reset, ~dut.core.ieu.dp.StallW, PCM, PCW);
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;

View File

@ -644,11 +644,11 @@ module testbenchfp;
// Read the first test // Read the first test
initial begin initial begin
//string testname = {`PATH, Tests[TestNum]}; //string testname = {`PATH, Tests[TestNum]};
string p = `PATH; static string pp = `PATH;
string testname; string testname;
string tt0; string tt0;
tt0 = $psprintf("%s", Tests[TestNum]); tt0 = $psprintf("%s", Tests[TestNum]);
testname = {p, tt0}; testname = {pp, tt0};
$display("Here you are %s", testname); $display("Here you are %s", testname);
$display("\n\nRunning %s vectors ", Tests[TestNum]); $display("\n\nRunning %s vectors ", Tests[TestNum]);
$readmemh(testname, TestVectors); $readmemh(testname, TestVectors);

View File

@ -72,6 +72,7 @@ module testbench;
logic HMASTLOCK; logic HMASTLOCK;
logic HCLK, HRESETn; logic HCLK, HRESETn;
logic [P.XLEN-1:0] PCW; logic [P.XLEN-1:0] PCW;
logic [31:0] NextInstrE, InstrM;
string ProgramAddrMapFile, ProgramLabelMapFile; string ProgramAddrMapFile, ProgramLabelMapFile;
integer ProgramAddrLabelArray [string] = '{ "begin_signature" : 0, "tohost" : 0 }; integer ProgramAddrLabelArray [string] = '{ "begin_signature" : 0, "tohost" : 0 };
@ -81,7 +82,8 @@ module testbench;
logic [31:0] GPIOIN, GPIOOUT, GPIOEN; logic [31:0] GPIOIN, GPIOOUT, GPIOEN;
logic UARTSin, UARTSout; logic UARTSin, UARTSout;
logic SPIIn, SPIOut;
logic [3:0] SPICS;
logic SDCIntr; logic SDCIntr;
logic HREADY; logic HREADY;
@ -214,7 +216,7 @@ module testbench;
`endif `endif
flopenr #(P.XLEN) PCWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.PCM, PCW); flopenr #(P.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, InstrM, InstrW);
// check assertions for a legal configuration // check assertions for a legal configuration
riscvassertions #(P) riscvassertions(); riscvassertions #(P) riscvassertions();
@ -255,13 +257,13 @@ module testbench;
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC, wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
.UARTSin, .UARTSout, .SDCIntr); .UARTSin, .UARTSout, .SDCIntr, .SPICS, .SPIOut, .SPIIn);
// Track names of instructions // Track names of instructions
instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE, instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE,
dut.core.ifu.InstrRawF[31:0], dut.core.ifu.InstrRawF[31:0],
dut.core.ifu.InstrD, dut.core.ifu.InstrE, dut.core.ifu.InstrD, dut.core.ifu.InstrE,
dut.core.ifu.InstrM, InstrW, InstrM, InstrW,
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
// initialize tests // initialize tests
@ -298,6 +300,10 @@ module testbench;
.ProgramLabelMapFile(ProgramLabelMapFile)); .ProgramLabelMapFile(ProgramLabelMapFile));
end end
// Duplicate copy of pipeline registers that are optimized out of some configurations
mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE);
flopenr #(32) InstrMReg(clk, reset, ~dut.core.ifu.StallM, NextInstrE, InstrM);
// Termination condition // Termination condition
// terminate on a specific ECALL after li x3,1 for old Imperas tests, *** remove this when old imperas tests are removed // terminate on a specific ECALL after li x3,1 for old Imperas tests, *** remove this when old imperas tests are removed
// or sw gp,-56(t0) for new Imperas tests // or sw gp,-56(t0) for new Imperas tests
@ -311,7 +317,7 @@ module testbench;
(dut.core.ieu.dp.regf.we3 & (dut.core.ieu.dp.regf.we3 &
dut.core.ieu.dp.regf.a3 == 3 & dut.core.ieu.dp.regf.a3 == 3 &
dut.core.ieu.dp.regf.wd3 == 1)) | dut.core.ieu.dp.regf.wd3 == 1)) |
((dut.core.ifu.InstrM == 32'h6f | dut.core.ifu.InstrM == 32'hfc32a423 | dut.core.ifu.InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) | ((InstrM == 32'h6f | InstrM == 32'hfc32a423 | InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) |
((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" ); ((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" );
DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk), DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk),

View File

@ -229,10 +229,16 @@ module testbench;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
/////////////////////////////// Cache Issue /////////////////////////////////// /////////////////////////////// Cache Issue ///////////////////////////////////
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Duplicate copy of pipeline registers that are optimized out of some configurations
logic [31:0] NextInstrE, InstrM;
mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE);
flopenr #(32) InstrMReg(clk, reset, ~dut.core.ifu.StallM, NextInstrE, InstrM);
logic probe; logic probe;
if (NO_SPOOFING) if (NO_SPOOFING)
assign probe = testbench.dut.core.PCM == 64'hffffffff80200c8c assign probe = testbench.dut.core.PCM == 64'hffffffff80200c8c
& testbench.dut.core.InstrM != 32'h14021273 & InstrM != 32'h14021273
& testbench.dut.core.InstrValidM; & testbench.dut.core.InstrValidM;
@ -276,7 +282,9 @@ module testbench;
logic SDCCmdOE; logic SDCCmdOE;
logic [3:0] SDCDatIn; logic [3:0] SDCDatIn;
logic SDCIntr; logic SDCIntr;
logic SPIIn, SPIOut;
logic [3:0] SPICS;
// Hardwire UART, GPIO pins // Hardwire UART, GPIO pins
assign GPIOIN = 0; assign GPIOIN = 0;
@ -434,13 +442,10 @@ module testbench;
// Wally // Wally
wallypipelinedsoc #(P) dut(.clk, .reset, .reset_ext, wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
.HRDATAEXT, .HREADYEXT, .HREADY, .HSELEXT, .HRESPEXT, .HCLK, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
.HRESETn, .HADDR, .HWDATA, .HWRITE, .HWSTRB, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
.HTRANS, .HMASTLOCK, .UARTSin, .UARTSout, .SDCIntr, .SPICS, .SPIOut, .SPIIn);
.TIMECLK('0), .GPIOIN, .GPIOOUT, .GPIOEN,
.UARTSin, .UARTSout,
.SDCIntr);
// W-stage hardware not needed by Wally itself // W-stage hardware not needed by Wally itself
parameter nop = 'h13; parameter nop = 'h13;
@ -452,7 +457,7 @@ module testbench;
`define FLUSHW dut.core.FlushW `define FLUSHW dut.core.FlushW
`define STALLW dut.core.StallW `define STALLW dut.core.StallW
flopenrc #(P.XLEN) PCWReg(clk, reset, `FLUSHW, ~`STALLW, `PCM, PCW); flopenrc #(P.XLEN) PCWReg(clk, reset, `FLUSHW, ~`STALLW, `PCM, PCW);
flopenr #(32) InstrWReg(clk, reset, ~`STALLW, `FLUSHW ? nop : dut.core.ifu.InstrM, InstrW); flopenr #(32) InstrWReg(clk, reset, ~`STALLW, `FLUSHW ? nop : InstrM, InstrW);
flopenrc #(1) controlregW(clk, reset, `FLUSHW, ~`STALLW, dut.core.ieu.c.InstrValidM, InstrValidW); flopenrc #(1) controlregW(clk, reset, `FLUSHW, ~`STALLW, dut.core.ieu.c.InstrValidM, InstrValidW);
flopenrc #(P.XLEN) IEUAdrWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.IEUAdrM, IEUAdrW); flopenrc #(P.XLEN) IEUAdrWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.IEUAdrM, IEUAdrW);
flopenrc #(P.XLEN) WriteDataWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.lsu.WriteDataM, WriteDataW); flopenrc #(P.XLEN) WriteDataWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.lsu.WriteDataM, WriteDataW);
@ -969,7 +974,7 @@ module testbench;
instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE, instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE,
dut.core.ifu.InstrRawF[31:0], dut.core.ifu.InstrRawF[31:0],
dut.core.ifu.InstrD, dut.core.ifu.InstrE, dut.core.ifu.InstrD, dut.core.ifu.InstrE,
dut.core.ifu.InstrM, InstrW, InstrM, InstrW,
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
// ------------------ // ------------------

View File

@ -212,10 +212,16 @@ module testbench;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
/////////////////////////////// Cache Issue /////////////////////////////////// /////////////////////////////// Cache Issue ///////////////////////////////////
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Duplicate copy of pipeline registers that are optimized out of some configurations
logic [31:0] NextInstrE, InstrM;
mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE);
flopenr #(32) InstrMReg(dut.core.clk, dut.core.reset, ~dut.core.ifu.StallM, NextInstrE, InstrM);
logic probe; logic probe;
if (NO_SPOOFING) if (NO_SPOOFING)
assign probe = testbench.dut.core.PCM == 64'hffffffff80200c8c assign probe = testbench.dut.core.PCM == 64'hffffffff80200c8c
& testbench.dut.core.InstrM != 32'h14021273 & InstrM != 32'h14021273
& testbench.dut.core.InstrValidM; & testbench.dut.core.InstrValidM;
@ -252,6 +258,8 @@ module testbench;
logic [31:0] GPIOIN; logic [31:0] GPIOIN;
logic [31:0] GPIOOUT, GPIOEN; logic [31:0] GPIOOUT, GPIOEN;
logic UARTSin, UARTSout; logic UARTSin, UARTSout;
logic SPIIn, SPIOut;
logic [3:0] SPICS;
// FPGA-specific Stuff // FPGA-specific Stuff
logic SDCIntr; logic SDCIntr;
@ -262,13 +270,10 @@ module testbench;
assign SDCIntr = 0; assign SDCIntr = 0;
// Wally // Wally
wallypipelinedsoc #(P) dut(.clk, .reset, .reset_ext, wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
.HRDATAEXT, .HREADYEXT, .HREADY, .HSELEXT, .HSELEXTSDC, .HRESPEXT, .HCLK, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
.HRESETn, .HADDR, .HWDATA, .HWRITE, .HWSTRB, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
.HTRANS, .HMASTLOCK, .UARTSin, .UARTSout, .SDCIntr, .SPICS, .SPIOut, .SPIIn);
.TIMECLK('0), .GPIOIN, .GPIOOUT, .GPIOEN,
.UARTSin, .UARTSout,
.SDCIntr);
// W-stage hardware not needed by Wally itself // W-stage hardware not needed by Wally itself
parameter nop = 'h13; parameter nop = 'h13;
@ -280,7 +285,7 @@ module testbench;
`define FLUSHW dut.core.FlushW `define FLUSHW dut.core.FlushW
`define STALLW dut.core.StallW `define STALLW dut.core.StallW
flopenrc #(P.XLEN) PCWReg(clk, reset, `FLUSHW, ~`STALLW, `PCM, PCW); flopenrc #(P.XLEN) PCWReg(clk, reset, `FLUSHW, ~`STALLW, `PCM, PCW);
flopenr #(32) InstrWReg(clk, reset, ~`STALLW, `FLUSHW ? nop : dut.core.ifu.InstrM, InstrW); flopenr #(32) InstrWReg(clk, reset, ~`STALLW, `FLUSHW ? nop : InstrM, InstrW);
flopenrc #(1) controlregW(clk, reset, `FLUSHW, ~`STALLW, dut.core.ieu.c.InstrValidM, InstrValidW); flopenrc #(1) controlregW(clk, reset, `FLUSHW, ~`STALLW, dut.core.ieu.c.InstrValidM, InstrValidW);
flopenrc #(P.XLEN) IEUAdrWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.IEUAdrM, IEUAdrW); flopenrc #(P.XLEN) IEUAdrWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.IEUAdrM, IEUAdrW);
flopenrc #(P.XLEN) WriteDataWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.lsu.WriteDataM, WriteDataW); flopenrc #(P.XLEN) WriteDataWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.lsu.WriteDataM, WriteDataW);
@ -794,7 +799,7 @@ module testbench;
instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE, instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE,
dut.core.ifu.InstrRawF[31:0], dut.core.ifu.InstrRawF[31:0],
dut.core.ifu.InstrD, dut.core.ifu.InstrE, dut.core.ifu.InstrD, dut.core.ifu.InstrE,
dut.core.ifu.InstrM, InstrW, InstrM, InstrW,
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
// ------------------ // ------------------

View File

@ -70,6 +70,8 @@ module testbench;
logic [3:0] SDCDatIn; logic [3:0] SDCDatIn;
tri1 [3:0] SDCDat; tri1 [3:0] SDCDat;
tri1 SDCCmd; tri1 SDCCmd;
logic SPIIn, SPIOut;
logic [3:0] SPICS;
logic HREADY; logic HREADY;
logic HSELEXT; logic HSELEXT;
@ -426,10 +428,10 @@ module testbench;
assign SDCDat = '0; assign SDCDat = '0;
end end
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT,.HREADYEXT, .HRESPEXT,.HSELEXT, wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
.UARTSin, .UARTSout, .SDCCmdIn, .SDCCmdOut, .SDCCmdOE, .SDCDatIn, .SDCCLK); .UARTSin, .UARTSout, .SDCIntr, .SPICS, .SPIOut, .SPIIn);
// generate clock to sequence tests // generate clock to sequence tests
always begin always begin
@ -440,20 +442,25 @@ module testbench;
// Support logic // Support logic
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Duplicate copy of pipeline registers that are optimized out of some configurations
logic [31:0] NextInstrE, InstrM;
mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE);
flopenr #(32) InstrMReg(clk, reset, ~dut.core.ifu.StallM, NextInstrE, InstrM);
// Track names of instructions // Track names of instructions
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName; string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
logic [31:0] InstrW; logic [31:0] InstrW;
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, InstrM, InstrW);
instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE, instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE,
dut.core.ifu.InstrRawF[31:0], dut.core.ifu.InstrRawF[31:0],
dut.core.ifu.InstrD, dut.core.ifu.InstrE, dut.core.ifu.InstrD, dut.core.ifu.InstrE,
dut.core.ifu.InstrM, InstrW, InstrM, InstrW,
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
// watch for problems such as lockup, reading unitialized memory, bad configs // watch for problems such as lockup, reading unitialized memory, bad configs
watchdog #(P.XLEN, 1000000) watchdog(.clk, .reset); // check if PCW is stuck watchdog #(P.XLEN, 1000000) watchdog(.clk, .reset); // check if PCW is stuck
ramxdetector #(P.XLEN, P.LLEN) ramxdetector(clk, dut.core.lsu.MemRWM[1], dut.core.lsu.LSULoadAccessFaultM, dut.core.lsu.ReadDataM, ramxdetector #(P.XLEN, P.LLEN) ramxdetector(clk, dut.core.lsu.MemRWM[1], dut.core.lsu.LSULoadAccessFaultM, dut.core.lsu.ReadDataM,
dut.core.ifu.PCM, dut.core.ifu.InstrM, dut.core.lsu.IEUAdrM, InstrMName); dut.core.ifu.PCM, InstrM, dut.core.lsu.IEUAdrM, InstrMName);
riscvassertions #(P) riscvassertions(); // check assertions for a legal configuration riscvassertions #(P) riscvassertions(); // check assertions for a legal configuration
loggers #(P, TEST, PrintHPMCounters, I_CACHE_ADDR_LOGGER, D_CACHE_ADDR_LOGGER, BPRED_LOGGER) loggers #(P, TEST, PrintHPMCounters, I_CACHE_ADDR_LOGGER, D_CACHE_ADDR_LOGGER, BPRED_LOGGER)
loggers (clk, reset, DCacheFlushStart, DCacheFlushDone, memfilename); loggers (clk, reset, DCacheFlushStart, DCacheFlushDone, memfilename);
@ -478,7 +485,7 @@ module testbench;
(dut.core.ieu.dp.regf.we3 & (dut.core.ieu.dp.regf.we3 &
dut.core.ieu.dp.regf.a3 == 3 & dut.core.ieu.dp.regf.a3 == 3 &
dut.core.ieu.dp.regf.wd3 == 1)) | dut.core.ieu.dp.regf.wd3 == 1)) |
((dut.core.ifu.InstrM == 32'h6f | dut.core.ifu.InstrM == 32'hfc32a423 | dut.core.ifu.InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) | ((InstrM == 32'h6f | InstrM == 32'hfc32a423 | InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) |
((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" ); ((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" );
DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk), .reset(reset), .start(DCacheFlushStart), .done(DCacheFlushDone)); DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk), .reset(reset), .start(DCacheFlushStart), .done(DCacheFlushDone));

View File

@ -410,20 +410,25 @@ module testbench;
// Support logic // Support logic
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Duplicate copy of pipeline registers that are optimized out of some configurations
logic [31:0] NextInstrE, InstrM;
mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE);
flopenr #(32) InstrMReg(clk, reset, ~dut.core.ifu.StallM, NextInstrE, InstrM);
// Track names of instructions // Track names of instructions
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName; string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
logic [31:0] InstrW; logic [31:0] InstrW;
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, InstrM, InstrW);
instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE, instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE,
dut.core.ifu.InstrRawF[31:0], dut.core.ifu.InstrRawF[31:0],
dut.core.ifu.InstrD, dut.core.ifu.InstrE, dut.core.ifu.InstrD, dut.core.ifu.InstrE,
dut.core.ifu.InstrM, InstrW, InstrM, InstrW,
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
// watch for problems such as lockup, reading unitialized memory, bad configs // watch for problems such as lockup, reading unitialized memory, bad configs
watchdog #(P.XLEN, 1000000) watchdog(.clk, .reset); // check if PCW is stuck watchdog #(P.XLEN, 1000000) watchdog(.clk, .reset); // check if PCW is stuck
ramxdetector #(P.XLEN, P.LLEN) ramxdetector(clk, dut.core.lsu.MemRWM[1], dut.core.lsu.LSULoadAccessFaultM, dut.core.lsu.ReadDataM, ramxdetector #(P.XLEN, P.LLEN) ramxdetector(clk, dut.core.lsu.MemRWM[1], dut.core.lsu.LSULoadAccessFaultM, dut.core.lsu.ReadDataM,
dut.core.ifu.PCM, dut.core.ifu.InstrM, dut.core.lsu.IEUAdrM, InstrMName); dut.core.ifu.PCM, InstrM, dut.core.lsu.IEUAdrM, InstrMName);
riscvassertions #(P) riscvassertions(); // check assertions for a legal configuration riscvassertions #(P) riscvassertions(); // check assertions for a legal configuration
loggers #(P, TEST, PrintHPMCounters, I_CACHE_ADDR_LOGGER, D_CACHE_ADDR_LOGGER, BPRED_LOGGER) loggers #(P, TEST, PrintHPMCounters, I_CACHE_ADDR_LOGGER, D_CACHE_ADDR_LOGGER, BPRED_LOGGER)
loggers (clk, reset, DCacheFlushStart, DCacheFlushDone, memfilename); loggers (clk, reset, DCacheFlushStart, DCacheFlushDone, memfilename);
@ -448,7 +453,7 @@ module testbench;
(dut.core.ieu.dp.regf.we3 & (dut.core.ieu.dp.regf.we3 &
dut.core.ieu.dp.regf.a3 == 3 & dut.core.ieu.dp.regf.a3 == 3 &
dut.core.ieu.dp.regf.wd3 == 1)) | dut.core.ieu.dp.regf.wd3 == 1)) |
((dut.core.ifu.InstrM == 32'h6f | dut.core.ifu.InstrM == 32'hfc32a423 | dut.core.ifu.InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) | ((InstrM == 32'h6f | InstrM == 32'hfc32a423 | InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) |
((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" ); ((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" );
DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk), .reset(reset), .start(DCacheFlushStart), .done(DCacheFlushDone)); DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk), .reset(reset), .start(DCacheFlushStart), .done(DCacheFlushDone));

View File

@ -1,11 +1,10 @@
/////////////////////////////////////////// ///////////////////////////////////////////
// testbench.sv // wallywrapper.sv
// //
// Written: David_Harris@hmc.edu 9 January 2021 // Written: David_Harris@hmc.edu 9 January 2021
// Modified: // Modified:
// //
// Purpose: Wally Testbench and helper modules // Purpose: Wrapper module to define parameters for Wally Verilator linting
// Applies test programs from the riscv-arch-test and Imperas suites
// //
// A component of the Wally configurable RISC-V project. // A component of the Wally configurable RISC-V project.
// //