diff --git a/pipelined/config/buildroot/wally-config.vh b/pipelined/config/buildroot/wally-config.vh index b0d85e517..3cbd3f7dc 100644 --- a/pipelined/config/buildroot/wally-config.vh +++ b/pipelined/config/buildroot/wally-config.vh @@ -50,9 +50,9 @@ `define UARCH_PIPELINED 1 `define UARCH_SUPERSCALR 0 `define UARCH_SINGLECYCLE 0 -`define MEM_DTIM 1 +`define MEM_DTIM 0 `define MEM_DCACHE 1 -`define MEM_IROM 1 +`define MEM_IROM 0 `define MEM_ICACHE 1 `define MEM_VIRTMEM 1 `define VECTORED_INTERRUPTS_SUPPORTED 1 diff --git a/pipelined/config/busybear/wally-config.vh b/pipelined/config/busybear/wally-config.vh index d9c61a852..bd8671ceb 100644 --- a/pipelined/config/busybear/wally-config.vh +++ b/pipelined/config/busybear/wally-config.vh @@ -48,9 +48,9 @@ `define UARCH_PIPELINED 1 `define UARCH_SUPERSCALR 0 `define UARCH_SINGLECYCLE 0 -`define MEM_DTIM 1 +`define MEM_DTIM 0 `define MEM_DCACHE 1 -`define MEM_IROM 1 +`define MEM_IROM 0 `define MEM_ICACHE 1 `define MEM_VIRTMEM 1 `define VECTORED_INTERRUPTS_SUPPORTED 1 diff --git a/pipelined/config/fpga/wally-config.vh b/pipelined/config/fpga/wally-config.vh index b3c87cc78..df40d7a33 100644 --- a/pipelined/config/fpga/wally-config.vh +++ b/pipelined/config/fpga/wally-config.vh @@ -50,9 +50,9 @@ `define UARCH_PIPELINED 1 `define UARCH_SUPERSCALR 0 `define UARCH_SINGLECYCLE 0 -`define MEM_DTIM 1 +`define MEM_DTIM 0 `define MEM_DCACHE 1 -`define MEM_IROM 1 +`define MEM_IROM 0 `define MEM_ICACHE 1 `define MEM_VIRTMEM 1 `define VECTORED_INTERRUPTS_SUPPORTED 1 diff --git a/pipelined/config/rv32gc/wally-config.vh b/pipelined/config/rv32gc/wally-config.vh index cb96c5a4b..3f96917e8 100644 --- a/pipelined/config/rv32gc/wally-config.vh +++ b/pipelined/config/rv32gc/wally-config.vh @@ -51,7 +51,7 @@ `define UARCH_SINGLECYCLE 0 `define MEM_DTIM 0 `define MEM_DCACHE 1 -`define MEM_IROM 1 +`define MEM_IROM 0 `define MEM_ICACHE 1 `define MEM_VIRTMEM 1 `define VECTORED_INTERRUPTS_SUPPORTED 1 diff --git a/pipelined/config/rv32ic/wally-config.vh b/pipelined/config/rv32ic/wally-config.vh index c06c82b50..e59fc094b 100644 --- a/pipelined/config/rv32ic/wally-config.vh +++ b/pipelined/config/rv32ic/wally-config.vh @@ -52,7 +52,7 @@ `define MEM_DTIM 0 `define MEM_DCACHE 0 `define MEM_IROM 0 -`define MEM_ICACHE 1 +`define MEM_ICACHE 0 `define MEM_VIRTMEM 0 `define VECTORED_INTERRUPTS_SUPPORTED 1 diff --git a/pipelined/config/rv64BP/wally-config.vh b/pipelined/config/rv64BP/wally-config.vh index 0a3ebc9c1..79acf4854 100644 --- a/pipelined/config/rv64BP/wally-config.vh +++ b/pipelined/config/rv64BP/wally-config.vh @@ -51,9 +51,9 @@ `define UARCH_PIPELINED 1 `define UARCH_SUPERSCALR 0 `define UARCH_SINGLECYCLE 0 -`define MEM_DTIM 1 +`define MEM_DTIM 0 `define MEM_DCACHE 1 -`define MEM_IROM 1 +`define MEM_IROM 0 `define MEM_ICACHE 1 `define MEM_VIRTMEM 1 `define VECTORED_INTERRUPTS_SUPPORTED 1 diff --git a/pipelined/config/rv64gc/wally-config.vh b/pipelined/config/rv64gc/wally-config.vh index 874b6602a..4483c20e2 100644 --- a/pipelined/config/rv64gc/wally-config.vh +++ b/pipelined/config/rv64gc/wally-config.vh @@ -52,7 +52,7 @@ `define UARCH_SINGLECYCLE 0 `define MEM_DTIM 0 `define MEM_DCACHE 1 -`define MEM_IROM 1 +`define MEM_IROM 0 `define MEM_ICACHE 1 `define MEM_VIRTMEM 1 `define VECTORED_INTERRUPTS_SUPPORTED 1 diff --git a/pipelined/config/rv64ic/wally-config.vh b/pipelined/config/rv64ic/wally-config.vh index 4957a0e8c..49abbce91 100644 --- a/pipelined/config/rv64ic/wally-config.vh +++ b/pipelined/config/rv64ic/wally-config.vh @@ -50,9 +50,9 @@ `define UARCH_PIPELINED 1 `define UARCH_SUPERSCALR 0 `define UARCH_SINGLECYCLE 0 -`define MEM_DTIM 1 +`define MEM_DTIM 0 `define MEM_DCACHE 1 -`define MEM_IROM 1 +`define MEM_IROM 0 `define MEM_ICACHE 1 `define MEM_VIRTMEM 1 `define VECTORED_INTERRUPTS_SUPPORTED 1 diff --git a/pipelined/regression/wally-harvard.do b/pipelined/regression/wally-harvard.do new file mode 100644 index 000000000..e6050d2c7 --- /dev/null +++ b/pipelined/regression/wally-harvard.do @@ -0,0 +1,56 @@ +# wally-pipelined.do +# +# Modification by Oklahoma State University & Harvey Mudd College +# Use with Testbench +# James Stine, 2008; David Harris 2021 +# Go Cowboys!!!!!! +# +# Takes 1:10 to run RV64IC tests using gui + +# run with vsim -do "do wally-pipelined.do rv64ic riscvarchtest-64m" + +# Use this wally-pipelined.do file to run this example. +# Either bring up ModelSim and type the following at the "ModelSim>" prompt: +# do wally-pipelined.do +# or, to run from a shell, type the following at the shell prompt: +# vsim -do wally-pipelined.do -c +# (omit the "-c" to see the GUI while running from the shell) + +onbreak {resume} + +# create library +if [file exists work] { + vdel -all +} +vlib work + +# compile source files +# suppress spurious warnngs about +# "Extra checking for conflicts with always_comb done at vopt time" +# because vsim will run vopt + +# default to config/rv64ic, but allow this to be overridden at the command line. For example: +# do wally-pipelined.do ../config/rv32ic +#switch $argc { +# 0 {vlog +incdir+../config/rv64ic +incdir+../config/shared ../testbench/testbench.sv ../testbench/common/*.sv ../src/*/*.sv -suppress 2583} +# 1 {vlog +incdir+$1 +incdir+../config/shared ../testbench/testbench.sv ../testbench/common/*.sv ../src/*/*.sv -suppress 2583} +#} +# start and run simulation +# remove +acc flag for faster sim during regressions if there is no need to access internal signals +vlog +incdir+../config/$1 +incdir+../config/shared ../testbench/testbench-harvard.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583 +vopt +acc work.testbench -G TEST=$2 -o workopt +vsim workopt + +view wave +-- display input and output signals as hexidecimal values +#do ./wave-dos/peripheral-waves.do +add log -recursive /* +do wave.do + +-- Run the Simulation +#run 3600 +run -all +#quit +#noview ../testbench/testbench-imperas.sv +noview ../testbench/testbench.sv +view wave diff --git a/pipelined/src/generic/flop/simpleram.sv b/pipelined/src/generic/flop/simpleram.sv new file mode 100644 index 000000000..b348dc4ec --- /dev/null +++ b/pipelined/src/generic/flop/simpleram.sv @@ -0,0 +1,80 @@ +/////////////////////////////////////////// +// simpleram.sv +// +// Written: David_Harris@hmc.edu 9 January 2021 +// Modified: +// +// Purpose: On-chip SIMPLERAM, external to hart +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University +// +// MIT LICENSE +// 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 simpleram #(parameter BASE=0, RANGE = 65535) ( + input logic HCLK, HRESETn, + input logic HSELRam, + input logic [31:0] HADDR, + input logic HWRITE, + input logic HREADY, + input logic [1:0] HTRANS, + input logic [`XLEN-1:0] HWDATA, + output logic [`XLEN-1:0] HREADRam, + output logic HRESPRam, HREADYRam +); + + localparam MemStartAddr = BASE>>(1+`XLEN/32); + localparam MemEndAddr = (RANGE+BASE)>>1+(`XLEN/32); + + logic [`XLEN-1:0] RAM[BASE>>(1+`XLEN/32):(RANGE+BASE)>>1+(`XLEN/32)]; + logic [31:0] HWADDR, A; + logic [`XLEN-1:0] HREADRam0; + + logic prevHREADYRam, risingHREADYRam; + logic initTrans; + logic memwrite; + logic [3:0] busycount; + + + /* verilator lint_off WIDTH */ + if (`XLEN == 64) begin:ramrw + always_ff @(posedge HCLK) begin + if (HWRITE & |HTRANS) RAM[HADDR[31:3]] <= #1 HWDATA; + end + end else begin + always_ff @(posedge HCLK) begin:ramrw + if (HWRITE & |HTRANS) RAM[HADDR[31:2]] <= #1 HWDATA; + end + end + + // read + if(`XLEN == 64) begin: ramr + assign HREADRam0 = RAM[HADDR[31:3]]; + end else begin + assign HREADRam0 = RAM[HADDR[31:2]]; + end + + /* verilator lint_on WIDTH */ + + assign HREADRam = HREADRam0; +endmodule + diff --git a/pipelined/src/ifu/ifu.sv b/pipelined/src/ifu/ifu.sv index 631e72980..e68eef96c 100644 --- a/pipelined/src/ifu/ifu.sv +++ b/pipelined/src/ifu/ifu.sv @@ -285,18 +285,23 @@ module ifu ( if (`MEM_IROM == 1) begin : irom - ram #( + logic [`XLEN-1:0] FinalInstrRawF_FIXME; + + simpleram #( .BASE(`RAM_BASE), .RANGE(`RAM_RANGE)) ram ( .HCLK(clk), .HRESETn(~reset), .HSELRam(1'b1), .HADDR(PCPF[31:0]), .HWRITE(1'b0), .HREADY(1'b1), - .HTRANS(2'b10), .HWDATA(0), .HREADRam(FinalInstrRawF), + .HTRANS(2'b10), .HWDATA(0), .HREADRam(FinalInstrRawF_FIXME), .HRESPRam(), .HREADYRam()); + assign FinalInstrRawF = FinalInstrRawF_FIXME[31:0]; assign BusStall = 0; assign IFUBusRead = 0; assign ICacheBusAck = 0; assign SelUncachedAdr = 0; + assign IFUBusAdr = 0; + end else begin : bus genvar index; diff --git a/pipelined/src/lsu/lsu.sv b/pipelined/src/lsu/lsu.sv index bda9342d0..e6391fd1b 100644 --- a/pipelined/src/lsu/lsu.sv +++ b/pipelined/src/lsu/lsu.sv @@ -359,7 +359,7 @@ module lsu if (`MEM_DTIM == 1) begin : dtim - ram #( + simpleram #( .BASE(`RAM_BASE), .RANGE(`RAM_RANGE)) ram ( .HCLK(clk), .HRESETn(~reset), .HSELRam(1'b1), .HADDR(LSUPAdrM[31:0]), diff --git a/pipelined/testbench/testbench-harvard.sv b/pipelined/testbench/testbench-harvard.sv new file mode 100644 index 000000000..66e554e8b --- /dev/null +++ b/pipelined/testbench/testbench-harvard.sv @@ -0,0 +1,476 @@ +/////////////////////////////////////////// +// testbench.sv +// +// Written: David_Harris@hmc.edu 9 January 2021 +// Modified: +// +// Purpose: Wally Testbench and helper modules +// Applies test programs from the riscv-arch-test and Imperas suites +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University +// +// MIT LICENSE +// 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" +`include "tests.vh" + +module testbench; + parameter TESTSPERIPH = 0; // set to 0 for regression + parameter TESTSPRIV = 0; // set to 0 for regression + parameter DEBUG=0; + parameter TEST="none"; + + logic clk; + logic reset_ext, reset; + + parameter SIGNATURESIZE = 5000000; + + int test, i, errors, totalerrors; + logic [31:0] sig32[0:SIGNATURESIZE]; + logic [`XLEN-1:0] signature[0:SIGNATURESIZE]; + logic [`XLEN-1:0] testadr; + string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName; + logic [31:0] InstrW; + logic [`XLEN-1:0] meminit; + + +string tests[]; +logic [3:0] dummy; + + 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; + + logic DCacheFlushDone, DCacheFlushStart; + + 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); + + // check assertions for a legal configuration + riscvassertions riscvassertions(); + + // pick tests based on modes supported + initial begin + $display("TEST is %s", TEST); + //tests = '{}; + if (`XLEN == 64) begin // RV64 + case (TEST) + "arch64i": tests = arch64i; + "arch64priv": tests = arch64priv; + "arch64c": if (`C_SUPPORTED) + if (`ZICSR_SUPPORTED) tests = {arch64c, arch64cpriv}; + else tests = {arch64c}; + "arch64m": if (`M_SUPPORTED) tests = arch64m; + "arch64d": if (`D_SUPPORTED) tests = arch64d; + "imperas64i": tests = imperas64i; + "imperas64p": tests = imperas64p; +// "imperas64mmu": if (`MEM_VIRTMEM) tests = imperas64mmu; + "imperas64f": if (`F_SUPPORTED) tests = imperas64f; + "imperas64d": if (`D_SUPPORTED) tests = imperas64d; + "imperas64m": if (`M_SUPPORTED) tests = imperas64m; + "imperas64a": if (`A_SUPPORTED) tests = imperas64a; + "imperas64c": if (`C_SUPPORTED) tests = imperas64c; + else tests = imperas64iNOc; + "testsBP64": tests = testsBP64; + "wally64i": tests = wally64i; // *** redo + "wally64priv": tests = wally64priv;// *** redo + "imperas64periph": tests = imperas64periph; + endcase + end else begin // RV32 + case (TEST) + "arch32i": tests = arch32i; + "arch32priv": tests = arch32priv; + "arch32c": if (`C_SUPPORTED) + if (`ZICSR_SUPPORTED) tests = {arch32c, arch32cpriv}; + else tests = {arch32c}; + "arch32m": if (`M_SUPPORTED) tests = arch32m; + "arch32f": if (`F_SUPPORTED) tests = arch32f; + "imperas32i": tests = imperas32i; + "imperas32p": tests = imperas32p; +// "imperas32mmu": if (`MEM_VIRTMEM) tests = imperas32mmu; + "imperas32f": if (`F_SUPPORTED) tests = imperas32f; + "imperas32m": if (`M_SUPPORTED) tests = imperas32m; + "imperas32a": if (`A_SUPPORTED) tests = imperas32a; + "imperas32c": if (`C_SUPPORTED) tests = imperas32c; + else tests = imperas32iNOc; + "wally32i": tests = wally32i; // *** redo + "wally32priv": tests = wally32priv; // *** redo + "imperas32periph": tests = imperas32periph; + endcase + end + if (tests.size() == 0) begin + $display("TEST %s not supported in this configuration", TEST); + $stop; + end + end + + string signame, memfilename, pathname; + + logic [31:0] GPIOPinsIn, GPIOPinsOut, GPIOPinsEn; + logic UARTSin, UARTSout; + + logic SDCCLK; + logic SDCCmdIn; + logic SDCCmdOut; + logic SDCCmdOE; + logic [3:0] SDCDatIn; + + logic HREADY; + logic HSELEXT; + + + // instantiate device to be tested + assign GPIOPinsIn = 0; + assign UARTSin = 1; + assign HREADYEXT = 1; + assign HRESPEXT = 0; + assign HRDATAEXT = 0; + + wallypipelinedsoc dut(.clk, .reset_ext, .reset, .HRDATAEXT,.HREADYEXT, .HRESPEXT,.HSELEXT, + .HCLK, .HRESETn, .HADDR, .HWDATA, .HWRITE, .HSIZE, .HBURST, .HPROT, + .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOPinsIn, .GPIOPinsOut, .GPIOPinsEn, + .UARTSin, .UARTSout, .SDCCmdIn, .SDCCmdOut, .SDCCmdOE, .SDCDatIn, .SDCCLK); + + // Track names of instructions + instrTrackerTB it(clk, reset, dut.hart.ieu.dp.FlushE, + dut.hart.ifu.FinalInstrRawF, + dut.hart.ifu.InstrD, dut.hart.ifu.InstrE, + dut.hart.ifu.InstrM, InstrW, + InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); + + // initialize tests + localparam integer MemStartAddr = `RAM_BASE>>(1+`XLEN/32); + localparam integer MemEndAddr = (`RAM_RANGE+`RAM_BASE)>>1+(`XLEN/32); + + initial + begin + test = 1; + totalerrors = 0; + testadr = 0; + // fill memory with defined values to reduce Xs in simulation + // 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 + // 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 + // the design. + if (`XLEN == 32) meminit = 32'hFEDC0123; + else meminit = 64'hFEDCBA9876543210; + // *** broken because DTIM also drives RAM + if (`TESTSBP) begin + for (i=MemStartAddr; i= 128 | `MEM_DCACHE == 0) else $error("DCACHE_LINELENINBITS must be at least 128 when caches are enabled"); + assert (`DCACHE_LINELENINBITS < `DCACHE_WAYSIZEINBYTES*8) else $error("DCACHE_LINELENINBITS must be smaller than way size"); + assert (`ICACHE_WAYSIZEINBYTES <= 4096 | `MEM_ICACHE == 0 | `MEM_VIRTMEM == 0) else $error("ICACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)"); + assert (`ICACHE_LINELENINBITS >= 32 | `MEM_ICACHE == 0) else $error("ICACHE_LINELENINBITS must be at least 32 when caches are enabled"); + assert (`ICACHE_LINELENINBITS < `ICACHE_WAYSIZEINBYTES*8) else $error("ICACHE_LINELENINBITS must be smaller than way size"); + assert (2**$clog2(`DCACHE_LINELENINBITS) == `DCACHE_LINELENINBITS | `MEM_DCACHE==0) else $error("DCACHE_LINELENINBITS must be a power of 2"); + assert (2**$clog2(`DCACHE_WAYSIZEINBYTES) == `DCACHE_WAYSIZEINBYTES | `MEM_DCACHE==0) else $error("DCACHE_WAYSIZEINBYTES must be a power of 2"); + assert (2**$clog2(`ICACHE_LINELENINBITS) == `ICACHE_LINELENINBITS | `MEM_ICACHE==0) else $error("ICACHE_LINELENINBITS must be a power of 2"); + assert (2**$clog2(`ICACHE_WAYSIZEINBYTES) == `ICACHE_WAYSIZEINBYTES | `MEM_ICACHE==0) else $error("ICACHE_WAYSIZEINBYTES must be a power of 2"); + assert (2**$clog2(`ITLB_ENTRIES) == `ITLB_ENTRIES | `MEM_VIRTMEM==0) else $error("ITLB_ENTRIES must be a power of 2"); + assert (2**$clog2(`DTLB_ENTRIES) == `DTLB_ENTRIES | `MEM_VIRTMEM==0) else $error("DTLB_ENTRIES must be a power of 2"); + assert (`RAM_RANGE >= 56'h07FFFFFF) else $warning("Some regression tests will fail if RAM_RANGE is less than 56'h07FFFFFF"); + assert (`ZICSR_SUPPORTED == 1 | (`PMP_ENTRIES == 0 & `MEM_VIRTMEM == 0)) else $error("PMP_ENTRIES and MEM_VIRTMEM must be zero if ZICSR not supported."); + assert (`ZICSR_SUPPORTED == 1 | (`S_SUPPORTED == 0 & `U_SUPPORTED == 0)) else $error("S and U modes not supported if ZISR not supported"); + assert (`U_SUPPORTED | (`S_SUPPORTED == 0)) else $error ("S mode only supported if U also is supported"); + end +endmodule + + +/* verilator lint_on STMTDLY */ +/* verilator lint_on WIDTH */ + +module DCacheFlushFSM + (input logic clk, + input logic reset, + input logic start, + output logic done); + + genvar adr; + + logic [`XLEN-1:0] ShadowRAM[`RAM_BASE>>(1+`XLEN/32):(`RAM_RANGE+`RAM_BASE)>>1+(`XLEN/32)]; + + if(`MEM_DCACHE) begin + localparam integer numlines = testbench.dut.hart.lsu.dcache.dcache.NUMLINES; + localparam integer numways = testbench.dut.hart.lsu.dcache.dcache.NUMWAYS; + localparam integer linebytelen = testbench.dut.hart.lsu.dcache.dcache.LINEBYTELEN; + localparam integer numwords = testbench.dut.hart.lsu.dcache.dcache.LINELEN/`XLEN; + localparam integer lognumlines = $clog2(numlines); + localparam integer loglinebytelen = $clog2(linebytelen); + localparam integer lognumways = $clog2(numways); + localparam integer tagstart = lognumlines + loglinebytelen; + + + + genvar index, way, cacheWord; + logic [`XLEN-1:0] CacheData [numways-1:0] [numlines-1:0] [numwords-1:0]; + logic [`XLEN-1:0] CacheTag [numways-1:0] [numlines-1:0] [numwords-1:0]; + logic CacheValid [numways-1:0] [numlines-1:0] [numwords-1:0]; + logic CacheDirty [numways-1:0] [numlines-1:0] [numwords-1:0]; + logic [`PA_BITS-1:0] CacheAdr [numways-1:0] [numlines-1:0] [numwords-1:0]; + for(index = 0; index < numlines; index++) begin + for(way = 0; way < numways; way++) begin + for(cacheWord = 0; cacheWord < numwords; cacheWord++) begin + copyShadow #(.tagstart(tagstart), + .loglinebytelen(loglinebytelen)) + copyShadow(.clk, + .start, + .tag(testbench.dut.hart.lsu.dcache.dcache.MemWay[way].CacheTagMem.StoredData[index]), + .valid(testbench.dut.hart.lsu.dcache.dcache.MemWay[way].ValidBits[index]), + .dirty(testbench.dut.hart.lsu.dcache.dcache.MemWay[way].DirtyBits[index]), + .data(testbench.dut.hart.lsu.dcache.dcache.MemWay[way].word[cacheWord].CacheDataMem.StoredData[index]), + .index(index), + .cacheWord(cacheWord), + .CacheData(CacheData[way][index][cacheWord]), + .CacheAdr(CacheAdr[way][index][cacheWord]), + .CacheTag(CacheTag[way][index][cacheWord]), + .CacheValid(CacheValid[way][index][cacheWord]), + .CacheDirty(CacheDirty[way][index][cacheWord])); + end + end + end + + integer i, j, k; + + always @(posedge clk) begin + if (start) begin #1 + #1 + for(i = 0; i < numlines; i++) begin + for(j = 0; j < numways; j++) begin + for(k = 0; k < numwords; k++) begin + if (CacheValid[j][i][k] & CacheDirty[j][i][k]) begin + ShadowRAM[CacheAdr[j][i][k] >> $clog2(`XLEN/8)] = CacheData[j][i][k]; + end + end + end + end + end + end + + + end + flop #(1) doneReg(.clk, .d(start), .q(done)); +endmodule + +module copyShadow + #(parameter tagstart, loglinebytelen) + (input logic clk, + input logic start, + input logic [`PA_BITS-1:tagstart] tag, + input logic valid, dirty, + input logic [`XLEN-1:0] data, + input logic [32-1:0] index, + input logic [32-1:0] cacheWord, + output logic [`XLEN-1:0] CacheData, + output logic [`PA_BITS-1:0] CacheAdr, + output logic [`XLEN-1:0] CacheTag, + output logic CacheValid, + output logic CacheDirty); + + + always_ff @(posedge clk) begin + if(start) begin + CacheTag = tag; + CacheValid = valid; + CacheDirty = dirty; + CacheData = data; + CacheAdr = (tag << tagstart) + (index << loglinebytelen) + (cacheWord << $clog2(`XLEN/8)); + end + end + +endmodule +