diff --git a/src/Cache/ICache.sv b/src/Cache/ICache.sv index 5080203..fc15e62 100644 --- a/src/Cache/ICache.sv +++ b/src/Cache/ICache.sv @@ -50,6 +50,7 @@ module ICache ( wire [`IC_TAG_LENGTH-1:0] tagOut1[4]; wire [`IC_DATA_LENGTH-1:0] dataOut1[4]; + wire [3:0] tagV1; wire hit1; // Cache hit or not wire [3:0] hitWay1; // Cache Line hit or not @@ -66,6 +67,7 @@ module ICache ( wire hit2; wire [3:0] hitWay2; + wire [3:0] tagV2; typedef enum logic [1:0] { Idle, @@ -81,6 +83,7 @@ module ICache ( wire [5:0] addr3; wire [`IC_TAG_LENGTH-2:0] tag3; wire [1:0] victim3; + wire [3:0] tagV3; wire [3:0] wen3; @@ -103,10 +106,11 @@ module ICache ( end end - mux2 #(6) ctrl0_mux ( + mux3 #(6) ctrl0_mux ( sram.addr[9:4], + PC1[9:4], wAddr4, - ctrl0, + {ctrl0, ~sram.addr_ok}, // TODO: 这里可能有问题,需要详细测试 cacheAddress0 ); @@ -135,7 +139,7 @@ module ICache ( // =========== Lookup =========== // ============================== - // TODO: 确保cacheMiss时tagOut1和dataOut1不变 + // 确保cacheMiss时tagOut1和dataOut1不变 -> L106 mux3解决? assign tagOut1[0] = TagRAM0.rdata; assign tagOut1[1] = TagRAM1.rdata; assign tagOut1[2] = TagRAM2.rdata; @@ -146,14 +150,19 @@ module ICache ( assign dataOut1[2] = DataRAM2.rdata; assign dataOut1[3] = DataRAM3.rdata; + assign tagV1[0] = tagOut1[0][0]; + assign tagV1[1] = tagOut1[1][0]; + assign tagV1[2] = tagOut1[2][0]; + assign tagV1[3] = tagOut1[3][0]; // Hit Check assign tag1 = PC1[31:10]; + assign addr1 = PC1[9:4]; - assign hitWay1[0] = tagOut1[0][0] & tagOut1[0][`IC_TAG_LENGTH-1:1] == tag1; - assign hitWay1[1] = tagOut1[1][0] & tagOut1[1][`IC_TAG_LENGTH-1:1] == tag1; - assign hitWay1[2] = tagOut1[2][0] & tagOut1[2][`IC_TAG_LENGTH-1:1] == tag1; - assign hitWay1[3] = tagOut1[3][0] & tagOut1[3][`IC_TAG_LENGTH-1:1] == tag1; + assign hitWay1[0] = tagV1[0] & tagOut1[0][`IC_TAG_LENGTH-1:1] == tag1; + assign hitWay1[1] = tagV1[1] & tagOut1[1][`IC_TAG_LENGTH-1:1] == tag1; + assign hitWay1[2] = tagV1[2] & tagOut1[2][`IC_TAG_LENGTH-1:1] == tag1; + assign hitWay1[3] = tagV1[3] & tagOut1[3][`IC_TAG_LENGTH-1:1] == tag1; assign hit1 = hitWay1[0] | hitWay1[1] | hitWay1[2] | hitWay1[3]; assign cacheLine1 = (hitWay1[0] ? dataOut1[0] : `IC_DATA_LENGTH'b0) | @@ -221,12 +230,12 @@ module ICache ( // ==== Pipeline Register 2 ===== // ============================== - ffenr #(37) pipelineReg2 ( + ffenr #(41) pipelineReg2 ( .clk(clk), .rst(rst | AXIBlocker == Done), .en (AXIBlocker == Idle), // TODO: 这里需要重新设计一下: AXI是否流水 - .d ({PC1, hitWay1, cacheMiss}), - .q ({PC2, hitWay2, req2}) // TODO: Req2的逻辑可能有误 + .d ({PC1, hitWay1, cacheMiss, tagV1}), + .q ({PC2, hitWay2, req2, tagV2}) ); // ============================== @@ -268,19 +277,23 @@ module ICache ( // ==== Pipeline Register 3 ===== // ============================== - ffenr #(`IC_DATA_LENGTH + 1 + 6 + 22) pipelineReg3 ( + ffenr #(`IC_DATA_LENGTH + 1 + 6 + 22 + 4) pipelineReg3 ( .clk(clk), .rst(rst), .en (1'b1), - .d ({ICacheLine, ICacheLineOK, PC2[9:4], PC2[31:10]}), - .q ({ICacheLine3, ICacheLineOK3, addr3, tag3}) + .d ({ICacheLine, ICacheLineOK, PC2[9:4], PC2[31:10], tagV2}), + .q ({ICacheLine3, ICacheLineOK3, addr3, tag3, tagV3}) ); // ============================== // ========== Replace =========== // ============================== - assign victim3 = LRU[addr3][0] == 0 ? 2'b00 : + assign victim3 = tagV3[0] == 0 ? 2'b00 : + tagV3[1] == 0 ? 2'b01 : + tagV3[2] == 0 ? 2'b10 : + tagV3[3] == 0 ? 2'b11 : + LRU[addr3][0] == 0 ? 2'b00 : LRU[addr3][1] == 0 ? 2'b01 : LRU[addr3][2] == 0 ? 2'b10 : LRU[addr3][3] == 0 ? 2'b11 : @@ -290,6 +303,13 @@ module ICache ( assign wen3[2] = (victim3 == 2) & ICacheLineOK3; assign wen3[3] = (victim3 == 3) & ICacheLineOK3; + always_ff @(posedge clk) begin + if (wen3 != 0) begin + $display("Victim Found: wen3=0x%b, addr3=0x%8h, tagV3=0x%b, LRU=0x%b", wen3, addr3, tagV3, + LRU[addr3]); + end + end + // ============================== // ==== Pipeline Register 4 ===== // ============================== diff --git a/src/testbench/icache/.gitignore b/src/testbench/icache/.gitignore index 40e786d..a44109d 100644 --- a/src/testbench/icache/.gitignore +++ b/src/testbench/icache/.gitignore @@ -1,3 +1 @@ -obj_dir -logs coe \ No newline at end of file diff --git a/src/testbench/icache/make.sh b/src/testbench/icache/make.sh deleted file mode 100755 index e7964c7..0000000 --- a/src/testbench/icache/make.sh +++ /dev/null @@ -1,13 +0,0 @@ -verilator -I/home/paul/loongson/MIPS/src/AXI/ \ - -I/home/paul/loongson/MIPS/src/Cache/ \ - -I/home/paul/loongson/MIPS/src/Core/ \ - -I/home/paul/loongson/MIPS/src/CP0/ \ - -I/home/paul/loongson/MIPS/src/include/ \ - -I/home/paul/loongson/MIPS/src/testbench/happy/ \ - +1800-2017ext+sv \ - --cc --trace --exe --build \ - sim_main.cpp testbench.sv - -./obj_dir/Vtestbench +trace - -gtkwave ./logs/vlt_dump.vcd diff --git a/src/testbench/icache/sim_main.cpp b/src/testbench/icache/sim_main.cpp deleted file mode 100644 index 57602a4..0000000 --- a/src/testbench/icache/sim_main.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include -#include "Vtestbench.h" -#include "verilated.h" - -int main(int argc, char **argv, char **env) -{ - // Create logs/ directory in case we have traces to put under it - Verilated::mkdir("logs"); - - // Construct a VerilatedContext to hold simulation time, etc. - // Multiple modules (made later below with Vtop) may share the same - // context to share time, or modules may have different contexts if - // they should be independent from each other. - - // Using unique_ptr is similar to - // "VerilatedContext* contextp = new VerilatedContext" then deleting at end. - const std::unique_ptr contextp{new VerilatedContext}; - - // Set debug level, 0 is off, 9 is highest presently used - // May be overridden by commandArgs argument parsing - contextp->debug(0); - - // Randomization reset policy - // May be overridden by commandArgs argument parsing - contextp->randReset(2); - - // Verilator must compute traced signals - contextp->traceEverOn(true); - - // Pass arguments so Verilated code can see them, e.g. $value$plusargs - // This needs to be called before you create any model - contextp->commandArgs(argc, argv); - - // Construct the Verilated model, from Vtop.h generated from Verilating "top.v". - // Using unique_ptr is similar to "Vtop* top = new Vtop" then deleting at end. - // "TOP" will be the hierarchical name of the module. - const std::unique_ptr top{new Vtestbench{contextp.get(), "TESTBENCH"}}; - - // Set Vtop's input signals - top->clk = 0; - top->rst = 0; - - // Simulate until $finish - while (!contextp->gotFinish()) - { - // Historical note, before Verilator 4.200 Verilated::gotFinish() - // was used above in place of contextp->gotFinish(). - // Most of the contextp-> calls can use Verilated:: calls instead; - // the Verilated:: versions simply assume there's a single context - // being used (per thread). It's faster and clearer to use the - // newer contextp-> versions. - - contextp->timeInc(1); // 1 timeprecision period passes... - // Historical note, before Verilator 4.200 a sc_time_stamp() - // function was required instead of using timeInc. Once timeInc() - // is called (with non-zero), the Verilated libraries assume the - // new API, and sc_time_stamp() will no longer work. - - // Toggle a fast (time/2 period) clock - top->clk = !top->clk; - - // Evaluate model - // (If you have multiple models being simulated in the same - // timestep then instead of eval(), call eval_step() on each, then - // eval_end_step() on each. See the manual.) - top->eval(); - - // Read outputs - VL_PRINTF("[%" VL_PRI64 "d] clk=%x rst=%x -> " - "req=%x " - "addr=%" VL_PRI64 "x " - "addr_ok=%x data_ok=%x " - "rdata0=%" VL_PRI64 "x " - "rdata1=%" VL_PRI64 "x " - "\n", - contextp->time(), top->clk, top->rst, - top->req, - top->addr, - top->addr_ok, top->data_ok, - top->rdata0, - top->rdata1); - } - - // Final model cleanup - top->final(); - - // Return good completion status - // Don't use exit() or destructor won't get called - return 0; -} diff --git a/src/testbench/icache/test.txt b/src/testbench/icache/test.sv similarity index 90% rename from src/testbench/icache/test.txt rename to src/testbench/icache/test.sv index 54fb69d..74ac348 100644 --- a/src/testbench/icache/test.txt +++ b/src/testbench/icache/test.sv @@ -114,7 +114,7 @@ module test (); assign rready = fake_axi.AXIReadAddr.rready; integer counter = 0; - reg [31:0] addr; + reg [11:0] addr; enum logic [1:0] { IDLE, REQ, @@ -135,8 +135,8 @@ module test (); nextStatus = REQ; end else begin fake_sram.req = 1'b1; - //fake_sram.addr = addr; - fake_sram.addr = addrt[addrx]; + fake_sram.addr = {18'b0, addr, 2'b0}; + //fake_sram.addr = addrt[addrx]; nextStatus = REQ; end end else nextStatus = IDLE; @@ -148,8 +148,12 @@ module test (); end if (fake_sram.data_ok) begin nextStatus = IDLE; - //addr = addr + 8; - addrx = addrx + 1; + if(fake_sram.rdata0 != (addr&'hFFE) && fake_sram.rdata1 != (addr&'hFFE) + 1)begin + $display("ERROR OCCURED! addr=0x%8h, rdata0=0x%8h, rdata1=0x%8h", + ((addr-1)<<2), fake_sram.rdata0, fake_sram.rdata1); + end + addr = addr + 1; + //addrx = addrx + 1; end else nextStatus = REQ; end else nextStatus = IDLE; end @@ -190,7 +194,7 @@ module test (); $dumpvars(); status = IDLE; - addr = 20; + addr = 0; addrx = 0; addrt[0] = 48; diff --git a/src/testbench/icache/testbench.sv b/src/testbench/icache/testbench.sv deleted file mode 100644 index a1b8ff1..0000000 --- a/src/testbench/icache/testbench.sv +++ /dev/null @@ -1,45 +0,0 @@ -`include "ICache.svh" -`include "sram.svh" - -module testbench ( - input clk, - input rst, - output req, - output word_t addr, - output addr_ok, - output data_ok, - output word_t rdata0, - output word_t rdata1 -); - - sramro_i fake_sram (); - ICache ic ( - .clk (clk), - .rst (rst), - .sram(fake_sram.slave) - ); - - assign req = fake_sram.req; - assign addr = fake_sram.addr; - assign addr_ok = fake_sram.addr_ok; - assign data_ok = fake_sram.data_ok; - assign rdata0 = fake_sram.rdata0; - assign rdata1 = fake_sram.rdata1; - - initial begin - $dumpfile("logs/vlt_dump.vcd"); - $dumpvars(); - fake_sram.req = 1; - fake_sram.addr = 32'b0100000; - end - - integer counter = 0; - always_ff @(posedge clk) begin - if (fake_sram.data_ok) fake_sram.addr = fake_sram.addr + 1; - if (clk == 1'b1) begin - counter = counter + 1; - if (counter >= 16) $finish; - end - end - -endmodule