From e08ded2242f3b16916333eb6185c9c3512e639de Mon Sep 17 00:00:00 2001 From: Paul Pan Date: Sat, 4 Sep 2021 16:31:25 +0800 Subject: [PATCH] Test Passed? maybe 1. fix timing loop 2. fix multi driven 3. fix CACHE I-Cache Index logic 4. fix testcase --- .../2021/soft/func/inst/n99_cache_icache.S | 82 ++++++++++++++----- resources/2021/soft/func/start.S | 39 ++++----- src/CP0/CP0.sv | 4 +- src/Cache/DCache.sv | 8 +- src/Cache/ICache.sv | 32 ++++---- src/Core/Datapath.sv | 2 + src/MMU/MMU.sv | 36 ++++---- src/include/ICache.svh | 2 +- 8 files changed, 128 insertions(+), 77 deletions(-) diff --git a/resources/2021/soft/func/inst/n99_cache_icache.S b/resources/2021/soft/func/inst/n99_cache_icache.S index 95f39dd..f1e86a9 100644 --- a/resources/2021/soft/func/inst/n99_cache_icache.S +++ b/resources/2021/soft/func/inst/n99_cache_icache.S @@ -8,22 +8,49 @@ LEAF(n99_cache_icache_test) li s2, 0x0 ###test inst +.n99_1_prepare: + addi a1, zero, 0 .n99_1: + addi a0, zero, 0 +.n99_1_replace: + nop # will be replaced with "addi a0, a0, 1" -> 20840001 + bne a0, a1, inst_error + nop + bne a1, zero, .n99_2_prepare # jump out 2nd + nop + addi a1, a1, 1 +.n99_1_work: la v0, .n99_1_replace li v1, 0x20840001 + li t0, 0x20000000 + subu v0, v0, t0 # v0 <- 9fcxxxxx sw v1, 0(v0) cache 21, 0(v0) # D-Cache Hit WriteBack Invalid cache 16, 0(v0) # I-Cache Hit Invalid - addi a0, zero, 0 - addi a1, zero, 1 -.n99_1_replace: - nop # line will be replaced with "addi a0, a0, 1" -> 20840001 - bne a0, a1, inst_error + # TODO: clear Datapath on CACHE + # using enough nop to stop prefetch + nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop + nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop + j .n99_1 nop + +.n99_2_prepare: + addi a1, zero, 0 .n99_2: + addi a0, zero, 0 +.n99_2_replace: + nop # will be replaced with "addi a0, a0, 1" -> 20840001 + bne a0, a1, inst_error + nop + bne a1, zero, .n99_3_prepare # jump out 2nd + nop + addi a1, a1, 1 +.n99_2_work: la v0, .n99_2_replace li v1, 0x20840001 + li t0, 0x20000000 + subu v0, v0, t0 sw v1, 0(v0) cache 21, 0(v0) # D-Cache Hit WriteBack Invalid addi t0, zero, 0 @@ -31,21 +58,35 @@ LEAF(n99_cache_icache_test) .n99_2_loop: beq t0, t1, .n99_2_check nop - add v0, t0, zero - cache 0, 0(v0) # I-Cache Index Invalid + cache 0, 0(t0) # I-Cache Index Invalid addi t0, t0, 1 j .n99_2_loop + nop .n99_2_check: - addi a0, zero, 0 - addi a1, zero, 1 -.n99_2_replace: - nop # line will be replaced with "addi a0, a0, 1" -> 20840001 - bne a0, a1, inst_error + # TODO: clear Datapath on CACHE + # using enough nop to stop prefetch + nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop + nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop + j .n99_2 nop + +.n99_3_prepare: + addi a1, zero, 0 .n99_3: + addi a0, zero, 0 +.n99_3_replace: + nop # will be replaced with "addi a0, a0, 1" -> 20840001 + bne a0, a1, inst_error + nop + bne a1, zero, .n99_success # jump out 2nd + nop + addi a1, a1, 1 +.n99_3_work: la v0, .n99_3_replace li v1, 0x20840001 + li t0, 0x20000000 + subu v0, v0, t0 sw v1, 0(v0) cache 21, 0(v0) # D-Cache Hit WriteBack Invalid addi t0, zero, 0 @@ -53,16 +94,19 @@ LEAF(n99_cache_icache_test) .n99_3_loop: beq t0, t1, .n99_3_check nop - add v0, t0, zero - cache 8, 0(v0) # I-Cache Index Store Tag + cache 0, 0(t0) # I-Cache Index Invalid addi t0, t0, 1 j .n99_3_loop + nop .n99_3_check: - addi a0, zero, 0 - addi a1, zero, 1 -.n99_3_replace: - nop # line will be replaced with "addi a0, a0, 1" -> 20840001 - bne a0, a1, inst_error + # TODO: clear Datapath on CACHE + # using enough nop to stop prefetch + nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop + nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop + j .n99_3 + nop + +.n99_success: nop ###detect exception diff --git a/resources/2021/soft/func/start.S b/resources/2021/soft/func/start.S index d78850c..cea091c 100644 --- a/resources/2021/soft/func/start.S +++ b/resources/2021/soft/func/start.S @@ -299,6 +299,26 @@ inst_test: nop ##### kseg0_kseg1: + jal n98_cache_dcache_test + nop + jal wait_1s + nop + + la t1, n99_kseg1_kseg0 + li t2, 0x20000000 + subu t9, t1, t2 + jr t9 + nop +n99_kseg1_kseg0: + jal n99_cache_icache_test + nop + jal wait_1s + nop + la t9, n99_kseg0_kseg1 + jr t9 + nop +n99_kseg0_kseg1: + jal n2_addu_test #addu nop jal wait_1s @@ -683,25 +703,6 @@ kseg0_kseg1: nop jal wait_1s nop - jal n98_cache_dcache_test - nop - jal wait_1s - nop - - la t1, n99_kseg1_kseg0 - li t2, 0x20000000 - subu t9, t1, t2 - jr t9 - nop -n99_kseg1_kseg0: - jal n99_cache_icache_test - nop - jal wait_1s - nop - la t9, n99_kseg0_kseg1 - jr t9 - nop -n99_kseg0_kseg1: ###check io access LI (a0, IO_SIMU_ADDR) diff --git a/src/CP0/CP0.sv b/src/CP0/CP0.sv index 304febf..7a03c2a 100644 --- a/src/CP0/CP0.sv +++ b/src/CP0/CP0.sv @@ -115,7 +115,7 @@ module CP0 ( rf_cp0.EntryLo0.V = 1'b0; rf_cp0.EntryLo0.G = 1'b0; rf_cp0.Index.P = 1'b0; - rf_cp0.Index.Index = 2'b0; + rf_cp0.Index.Index = 3'b0; rf_cp0.Random.Random = 3'b111; rf_cp0.EBase.EBase = 18'b0; @@ -166,7 +166,7 @@ module CP0 ( 9: rf_cp0.Count = wdata; 8: rf_cp0.BadVAddr = wdata; // 7: rf_cp0.HWREna = wdata; - 6: rf_cp0.Wired = wdata[2:0]; + 6: rf_cp0.Wired = {29'b0, wdata[2:0]}; // 5: rf_cp0.PageMask.Mask = wdata[24:13]; // 4: rf_cp0.Context = wdata; 3: begin diff --git a/src/Cache/DCache.sv b/src/Cache/DCache.sv index 5d1436f..96c4082 100644 --- a/src/Cache/DCache.sv +++ b/src/Cache/DCache.sv @@ -241,10 +241,10 @@ module DCache ( assign DataRAM2.wen = (bwe1 & wen[2]) | (bwe2 & wen2[2]); assign DataRAM3.wen = (bwe1 & wen[3]) | (bwe2 & wen2[3]); // 写数据 - assign TagRAM0.wdata = port.clear ? `DC_TAG_LENGTH'b0 : {port.tag1, port.wvalid, 1'b1}; - assign TagRAM1.wdata = port.clear ? `DC_TAG_LENGTH'b0 : {port.tag1, port.wvalid, 1'b1}; - assign TagRAM2.wdata = port.clear ? `DC_TAG_LENGTH'b0 : {port.tag1, port.wvalid, 1'b1}; - assign TagRAM3.wdata = port.clear ? `DC_TAG_LENGTH'b0 : {port.tag1, port.wvalid, 1'b1}; + assign TagRAM0.wdata = {port.tag1, port.wvalid, ~port.clear}; + assign TagRAM1.wdata = {port.tag1, port.wvalid, ~port.clear}; + assign TagRAM2.wdata = {port.tag1, port.wvalid, ~port.clear}; + assign TagRAM3.wdata = {port.tag1, port.wvalid, ~port.clear}; assign DataRAM0.wdata = state == LOOKUP ? wdata1[0] : wdata2[0]; assign DataRAM1.wdata = state == LOOKUP ? wdata1[1] : wdata2[1]; diff --git a/src/Cache/ICache.sv b/src/Cache/ICache.sv index 5b1e5a9..05deedf 100644 --- a/src/Cache/ICache.sv +++ b/src/Cache/ICache.sv @@ -176,23 +176,23 @@ module ICache ( assign DataRAM2.addr = baddr; assign DataRAM3.addr = baddr; // 写使能 - assign TagRAM0.wen = bwe & wen2[0]; - assign TagRAM1.wen = bwe & wen2[1]; - assign TagRAM2.wen = bwe & wen2[2]; - assign TagRAM3.wen = bwe & wen2[3]; - assign DataRAM0.wen = bwe & wen2[0]; - assign DataRAM1.wen = bwe & wen2[1]; - assign DataRAM2.wen = bwe & wen2[2]; - assign DataRAM3.wen = bwe & wen2[3]; + assign TagRAM0.wen = bwe & wen2[0] | port.clear & wen[0]; + assign TagRAM1.wen = bwe & wen2[1] | port.clear & wen[1]; + assign TagRAM2.wen = bwe & wen2[2] | port.clear & wen[2]; + assign TagRAM3.wen = bwe & wen2[3] | port.clear & wen[3]; + assign DataRAM0.wen = bwe & wen2[0] | port.clear & wen[0]; + assign DataRAM1.wen = bwe & wen2[1] | port.clear & wen[1]; + assign DataRAM2.wen = bwe & wen2[2] | port.clear & wen[2]; + assign DataRAM3.wen = bwe & wen2[3] | port.clear & wen[3]; // 写数据 - assign TagRAM0.wdata = {port.tag1, 1'b1}; - assign TagRAM1.wdata = {port.tag1, 1'b1}; - assign TagRAM2.wdata = {port.tag1, 1'b1}; - assign TagRAM3.wdata = {port.tag1, 1'b1}; - assign DataRAM0.wdata = port.clear ? `IC_TAG_LENGTH'b0 : port.rdata; - assign DataRAM1.wdata = port.clear ? `IC_TAG_LENGTH'b0 : port.rdata; - assign DataRAM2.wdata = port.clear ? `IC_TAG_LENGTH'b0 : port.rdata; - assign DataRAM3.wdata = port.clear ? `IC_TAG_LENGTH'b0 : port.rdata; + assign TagRAM0.wdata = {port.tag1, ~port.clear}; + assign TagRAM1.wdata = {port.tag1, ~port.clear}; + assign TagRAM2.wdata = {port.tag1, ~port.clear}; + assign TagRAM3.wdata = {port.tag1, ~port.clear}; + assign DataRAM0.wdata = port.rdata; + assign DataRAM1.wdata = port.rdata; + assign DataRAM2.wdata = port.rdata; + assign DataRAM3.wdata = port.rdata; ICTag_bram tag_ram0 ( .addra(TagRAM0.addr), diff --git a/src/Core/Datapath.sv b/src/Core/Datapath.sv index 7ce04d5..ad52678 100644 --- a/src/Core/Datapath.sv +++ b/src/Core/Datapath.sv @@ -1,6 +1,8 @@ `include "defines.svh" `include "sram.svh" `include "CP0.svh" +`include "ICache.svh" +`include "DCache.svh" module Datapath ( input clk, diff --git a/src/MMU/MMU.sv b/src/MMU/MMU.sv index ff367d8..f520f1a 100644 --- a/src/MMU/MMU.sv +++ b/src/MMU/MMU.sv @@ -97,6 +97,10 @@ module MMU ( word_t iD1, iD2, iD3, iD4, iD5, iD6, iD7; + logic diReq; + CacheOp_t cacheOp1, cacheOp2; + word_t dVA1; + // ================================ // ======== iState Machine ======== // ================================ @@ -183,7 +187,7 @@ module MMU ( /* * I-Cache Cache指令实现备注: * 在进入 I_CACHE 状态时需确保 iEn == 0 - * 跳出 I_CACHE 状态时 iEn = 1 + * 跳出 I_CACHE 状态时 iEn = 0 * 注意处理 Exceptions * TLB 转换请求在 iNextState == I_CACHE时发送 * I-Cache 查询请求在 iNextState == I_CACHE时发送 @@ -192,8 +196,9 @@ module MMU ( * drState 状态机同步 */ - if (~iTLBRefill & ~iTLBInvalid & iCached1 & (ic.hit | cacheOp1[1])) ic.clear = 1; - iEn = 1; + if (~iTLBRefill & ~iTLBInvalid & (iCached1 & ic.hit | cacheOp1[1])) ic.clear = 1; + iEn = 0; + iEn2 = 1; iNextState = I_IDLE; end endcase @@ -219,7 +224,7 @@ module MMU ( // ========== iFunction ========== // =============================== - assign iVA = iNextState == I_CACHE ? data.addr : inst.addr; + assign iVA = iNextState == I_CACHE ? dVA1 : inst.addr; assign iValid1 = iReq1 & iHit1 & iMValid1 & (in_kernel | iUser1); assign inst.addr_ok = iEn; @@ -234,12 +239,11 @@ module MMU ( ); // I-Cache req on inst query or cache instruction - assign ic.req = iEn | iNextState == I_CACHE; + assign ic.req = iEn & iState != I_CACHE | iNextState == I_CACHE; assign ic.valid = iValid1 & iCached1; assign ic.index = iVA[`IC_TAGL-1:`IC_INDEXL]; assign ic.tag1 = iEn2 ? iPA1[31:`IC_TAGL] : iPA2[31:`IC_TAGL]; assign ic.rvalid = inst_axi.rvalid & inst_axi.data_ok; - assign ic.clear = iState == I_CACHE & ~cacheOp1[2] & iCached1 & (ic.hit | cacheOp1[1]); mux4 #(256) ic_rdata_mux ( {inst_axi.rdata, iD7, iD6, iD5, iD4, iD3, iD2, iD1}, @@ -254,8 +258,8 @@ module MMU ( assign inst_axi.len = (iEn2 ? iCached1 : iCached2) ? 4'b0111 : 4'b0001; assign inst_axi.size = 3'b010; - assign iTLBRefill = (iState == I_IDLE & iReq1 | iState == I_CACHE & ~cacheOp[1]) & ~iHit1; - assign iTLBInvalid = (iState == I_IDLE & iReq1 | iState == I_CACHE & ~cacheOp[1]) & ~iMValid1; + assign iTLBRefill = (iState == I_IDLE & iReq1 | iState == I_CACHE & ~cacheOp1[1]) & ~iHit1; + assign iTLBInvalid = (iState == I_IDLE & iReq1 | iState == I_CACHE & ~cacheOp1[1]) & ~iMValid1; assign iAddressError = (iState == I_IDLE) & iReq1 & ~in_kernel & ~iUser1; // ====================== @@ -265,7 +269,7 @@ module MMU ( word_t dVA; logic dEn; - logic dReq1, dcReq1, diReq; + logic dReq1, dcReq1; logic dHit1; logic dCached1, dCached2; logic dDirty1; @@ -275,8 +279,6 @@ module MMU ( word_t dPA1, dPA2; logic [1:0] dSize1; - CacheOp_t cacheOp1, cacheOp2; - logic dEn2; logic dwr1; logic [3:0] dWstrb1; @@ -294,6 +296,7 @@ module MMU ( ffenr #(1) dvalid_ff (clk, rst, data.req, dEn, dReq1); ffen #(2) dsize_ff (clk, data.size, dEn, dSize1); + ffen #(32) dVA1_ff (clk, data.addr, dEn, dVA1); ffen #(32) dPA_ff (clk, dPA1, dEn2, dPA2); ffen #(1) dCached_ff (clk, dCached1, dEn2, dCached2); ffen #(1) dwr_ff (clk, data.wr, dEn2, dwr1); @@ -322,8 +325,8 @@ module MMU ( rdata_axi.req = 0; case (drState) DR_IDLE: begin - if (~dValid1) dEn = 1; - else if (~dcReq1) drNextState = DR_CACHE; + if (diReq) drNextState = DR_CACHE; + else if (~dValid1) dEn = 1; else begin dEn2 = 1; if (data.wr) data.data_ok = 1; @@ -407,9 +410,8 @@ module MMU ( */ assign dVA = data.addr; - assign diReq = dEn ? data.req & ~cacheOp[2] & |cacheOp[1:0] - : dReq1 & ~cacheOp1[2] & |cacheOp1[1:0]; - assign dcReq1 = dReq1 & (cacheOp1 == CNOP | cacheOp[2]); // exclude I-Cache clear + assign diReq = dReq1 & ~cacheOp1[2] & |cacheOp1[1:0]; + assign dcReq1 = dReq1 & (cacheOp1 == CNOP | cacheOp1[2]); // exclude I-Cache clear assign dValid1 = dReq1 & dHit1 & dMValid1 & (~data.wr | dDirty1) & (in_kernel | dUser1); assign dTLBRefill = drState == DR_IDLE & dcReq1 & (cacheOp1 == CNOP | ~cacheOp1[1]) & ~dHit1; @@ -457,6 +459,8 @@ module MMU ( // do not request when handling CACHE instruction on I-Cache assign dc.req = dEn & (cacheOp[2] | ~|cacheOp[1:0]); + // TODO: 在实现 CACHE 指令的 D-Cache Index 功能时应替换成下面注释的内容 + // assign dc.valid = dValid1 & (dCached1 & (~cacheOp1[2] | dc.hit) | cacheOp1[1]); assign dc.valid = dValid1 & dCached1 & (~cacheOp1[2] | cacheOp1[1] | dc.hit); assign dc.index = dVA[`DC_TAGL-1:`DC_INDEXL]; assign dc.tag1 = dEn2 ? dPA1[31:`DC_TAGL] : dPA2[31:`DC_TAGL]; diff --git a/src/include/ICache.svh b/src/include/ICache.svh index fd7ec03..63bf773 100644 --- a/src/include/ICache.svh +++ b/src/include/ICache.svh @@ -6,7 +6,7 @@ // IC for I-Cache `define IC_TAGL 11 `define IC_INDEXL 5 -`define IC_TAG_LENGTH (32-`IC_TAGL+1) // Tag + Valid +`define IC_TAG_LENGTH 22 // Tag + Valid `define IC_DATA_LENGTH 256 // 32Bytes typedef logic [`IC_DATA_LENGTH-1:0] ICData_t;