From 2143cbe63072e7c7afb8bc7acb0ff6b90ad21b7a Mon Sep 17 00:00:00 2001 From: Paul Pan Date: Fri, 3 Sep 2021 21:23:32 +0800 Subject: [PATCH] try add I-Cache's CACHE inst --- src/Cache/ICache.sv | 12 +-- src/MMU/MMU.sv | 201 +++++++++++++++++++++----------------------- 2 files changed, 102 insertions(+), 111 deletions(-) diff --git a/src/Cache/ICache.sv b/src/Cache/ICache.sv index 566609d..5b1e5a9 100644 --- a/src/Cache/ICache.sv +++ b/src/Cache/ICache.sv @@ -68,7 +68,7 @@ module ICache ( end end LOOKUP: begin - if (~port.valid | hit) begin + if (~port.valid | hit | port.clear) begin if (~port.req) begin nextState = IDLE; end @@ -164,7 +164,7 @@ module ICache ( port.req, baddr ); - assign bwe = (state == REPLACE) & port.rvalid; + assign bwe = (state == REPLACE) & port.rvalid | port.clear; // 地址 assign TagRAM0.addr = baddr; @@ -189,10 +189,10 @@ module ICache ( 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.rdata; - assign DataRAM1.wdata = port.rdata; - assign DataRAM2.wdata = port.rdata; - assign DataRAM3.wdata = port.rdata; + 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; ICTag_bram tag_ram0 ( .addra(TagRAM0.addr), diff --git a/src/MMU/MMU.sv b/src/MMU/MMU.sv index 0f70239..ff367d8 100644 --- a/src/MMU/MMU.sv +++ b/src/MMU/MMU.sv @@ -55,33 +55,22 @@ module MMU ( typedef enum bit [3:0] { I_IDLE, I_WA, - I_WD1, - I_WD2, - I_WD3, - I_WD4, - I_WD5, - I_WD6, - I_WD7, - I_WD8, - I_REFILL + I_WD1, I_WD2, I_WD3, I_WD4, I_WD5, I_WD6, I_WD7, I_WD8, + I_REFILL, + I_CACHE } istate_t; typedef enum bit [2:0] { DR_IDLE, DR_WA, - DR_WD1, - DR_WD2, - DR_WD3, - DR_WD4, - DR_REFILL + DR_WD1, DR_WD2, DR_WD3, DR_WD4, + DR_REFILL, + DR_CACHE } drstate_t; typedef enum bit [2:0] { DW_IDLE, - DW_WD1, - DW_WD2, - DW_WD3, - DW_WD4, + DW_WD1, DW_WD2, DW_WD3, DW_WD4, DW_WB, DW_WAITR } dwstate_t; @@ -121,14 +110,17 @@ module MMU ( end always_comb begin - iEn = 0; - iEn2 = 0; - iNextState = iState; + iEn = 0; + iEn2 = 0; + iNextState = iState; inst.data_ok = 0; inst_axi.req = 0; + ic.clear = 0; case (iState) I_IDLE: begin - if (~iValid1) iEn = 1; + if (diReq & ~iValid1) begin + iNextState = I_CACHE; + end else if (~iValid1) iEn = 1; else begin iEn2 = 1; if (iCached1 & ic.hit) begin @@ -155,6 +147,7 @@ module MMU ( if (inst_axi.rvalid) begin inst.data_ok = 1; if (iCached2) iNextState = I_WD3; + else if (diReq) iNextState = I_CACHE; else begin iEn = 1; iNextState = I_IDLE; @@ -180,7 +173,27 @@ module MMU ( if (inst_axi.rvalid) iNextState = I_REFILL; end I_REFILL: begin - iEn = 1; + if (diReq) iNextState = I_CACHE; + else begin + iEn = 1; + iNextState = I_IDLE; + end + end + I_CACHE: begin + /* + * I-Cache Cache指令实现备注: + * 在进入 I_CACHE 状态时需确保 iEn == 0 + * 跳出 I_CACHE 状态时 iEn = 1 + * 注意处理 Exceptions + * TLB 转换请求在 iNextState == I_CACHE时发送 + * I-Cache 查询请求在 iNextState == I_CACHE时发送 + * 在 I_CACHE 状态下屏蔽 iAddressError 且只有在 Address 类型请求下允许 TLBRefill 和 TLBInvalid + * I_CACHE 状态下向 I_CACHE 发送 clear 信号 + * drState 状态机同步 + */ + + if (~iTLBRefill & ~iTLBInvalid & iCached1 & (ic.hit | cacheOp1[1])) ic.clear = 1; + iEn = 1; iNextState = I_IDLE; end endcase @@ -190,74 +203,23 @@ module MMU ( // ======== iFlip-Flop ======== // ============================ - ffenr #(1) ivalid_ff ( - clk, - rst, - inst.req, - iEn, - iReq1 - ); - ffen #(32) iPA_ff ( - clk, - iPA1, - iEn2, - iPA2 - ); - ffen #(1) iCached_ff ( - clk, - iCached1, - iEn2, - iCached2 - ); + ffenr #(1) ivalid_ff (clk, rst, inst.req, iEn, iReq1); + ffen #(32) iPA_ff (clk, iPA1, iEn2, iPA2); + ffen #(1) iCached_ff (clk, iCached1, iEn2, iCached2); - ffen #(32) id1_ff ( - clk, - inst_axi.rdata, - iState == I_WA | iState == I_WD1, - iD1 - ); - ffen #(32) id2_ff ( - clk, - inst_axi.rdata, - iState == I_WD2, - iD2 - ); - ffen #(32) id3_ff ( - clk, - inst_axi.rdata, - iState == I_WD3, - iD3 - ); - ffen #(32) id4_ff ( - clk, - inst_axi.rdata, - iState == I_WD4, - iD4 - ); - ffen #(32) id5_ff ( - clk, - inst_axi.rdata, - iState == I_WD5, - iD5 - ); - ffen #(32) id6_ff ( - clk, - inst_axi.rdata, - iState == I_WD6, - iD6 - ); - ffen #(32) id7_ff ( - clk, - inst_axi.rdata, - iState == I_WD7, - iD7 - ); + ffen #(32) id1_ff (clk, inst_axi.rdata, iState == I_WA | iState == I_WD1, iD1); + ffen #(32) id2_ff (clk, inst_axi.rdata, iState == I_WD2, iD2); + ffen #(32) id3_ff (clk, inst_axi.rdata, iState == I_WD3, iD3); + ffen #(32) id4_ff (clk, inst_axi.rdata, iState == I_WD4, iD4); + ffen #(32) id5_ff (clk, inst_axi.rdata, iState == I_WD5, iD5); + ffen #(32) id6_ff (clk, inst_axi.rdata, iState == I_WD6, iD6); + ffen #(32) id7_ff (clk, inst_axi.rdata, iState == I_WD7, iD7); // =============================== // ========== iFunction ========== // =============================== - assign iVA = inst.addr; + assign iVA = iNextState == I_CACHE ? data.addr : inst.addr; assign iValid1 = iReq1 & iHit1 & iMValid1 & (in_kernel | iUser1); assign inst.addr_ok = iEn; @@ -271,11 +233,13 @@ module MMU ( {inst.rdata1, inst.rdata0} ); - assign ic.req = iEn; + // I-Cache req on inst query or cache instruction + assign ic.req = iEn | 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}, @@ -290,8 +254,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 & ~iHit1; - assign iTLBInvalid = (iState == I_IDLE) & iReq1 & ~iMValid1; + 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 iAddressError = (iState == I_IDLE) & iReq1 & ~in_kernel & ~iUser1; // ====================== @@ -301,7 +265,7 @@ module MMU ( word_t dVA; logic dEn; - logic dReq1; + logic dReq1, dcReq1, diReq; logic dHit1; logic dCached1, dCached2; logic dDirty1; @@ -328,15 +292,15 @@ module MMU ( // ======== dFlip-Flop ======== // ============================ - ffenr #(1) dvalid_ff (clk, rst, data.req, dEn, dReq1); - ffen #(2) dsize_ff (clk, data.size, dEn, dSize1); - 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); - ffen #(4) dwstrb_ff (clk, data.wstrb, dEn2, dWstrb1); - ffen #(32) dwdata_ff (clk, data.wdata, dEn2, dWdata1); - ffen #(3) cache_op_ff (clk, cacheOp[2:0], dEn, cacheOp1[2:0]); - ffen #(3) cache_op2_ff (clk, cacheOp1[2:0], dEn2, cacheOp2[2:0]); + ffenr #(1) dvalid_ff (clk, rst, data.req, dEn, dReq1); + ffen #(2) dsize_ff (clk, data.size, dEn, dSize1); + 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); + ffen #(4) dwstrb_ff (clk, data.wstrb, dEn2, dWstrb1); + ffen #(32) dwdata_ff (clk, data.wdata, dEn2, dWdata1); + ffen #(3) cache_op_ff (clk, cacheOp[2:0], dEn, cacheOp1[2:0]); + ffen #(3) cache_op2_ff (clk, cacheOp1[2:0], dEn2, cacheOp2[2:0]); // ================================= // ======== drState Machine ======== @@ -359,6 +323,7 @@ module MMU ( case (drState) DR_IDLE: begin if (~dValid1) dEn = 1; + else if (~dcReq1) drNextState = DR_CACHE; else begin dEn2 = 1; if (data.wr) data.data_ok = 1; @@ -412,6 +377,17 @@ module MMU ( drNextState = DR_IDLE; end end + DR_CACHE: begin + /* + * 该状态是 I-CACHE 的清除指令 + * 当 iState == I_CACHE 代表下一个周期恢复正常工作 + */ + if (iState == I_CACHE) begin + data.data_ok = 1; + dEn = 1; + drNextState = DR_IDLE; + end + end endcase end @@ -419,13 +395,27 @@ module MMU ( // ========== dFunction ========== // ================================ - assign dVA = data.addr; - assign dValid1 = dReq1 & dHit1 & dMValid1 & (~data.wr | dDirty1) & (in_kernel | dUser1); + /* + * D-Cache Cache 指令实现备注 + * Cache 指令当成写指令处理 + * TLB 转换请求和 D-Cache 请求与普通访存一致 + * dc.req 在 I-Cache Cache 指令发生时为0 + * 清除请求时 drState 进入 DR_REFILL 状态,后由 DW_STATE 确定返回 + * dwState 和 dwaState 需判断是否是 CACHE 指令且是否允许写回 + * 屏蔽 dAddressError 和 TLBModified 且只有在 Address 类型请求下允许 TLBRefill 和 TLBInvalid + * dc.clear 在查询完成后一阶段或者写回完成阶段发送 + */ - assign dTLBRefill = (drState == DR_IDLE) & dReq1 & ~cacheOp1[1] & ~dHit1; - assign dTLBInvalid = (drState == DR_IDLE) & dReq1 & ~cacheOp1[1] & ~dMValid1; - assign dTLBModified = (drState == DR_IDLE) & dReq1 & ~cacheOp1[1] & data.wr & ~dDirty1; - assign dAddressError = (drState == DR_IDLE) & dReq1 & ~cacheOp1[1] & ~in_kernel & ~dUser1; + 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 dValid1 = dReq1 & dHit1 & dMValid1 & (~data.wr | dDirty1) & (in_kernel | dUser1); + + assign dTLBRefill = drState == DR_IDLE & dcReq1 & (cacheOp1 == CNOP | ~cacheOp1[1]) & ~dHit1; + assign dTLBInvalid = drState == DR_IDLE & dcReq1 & (cacheOp1 == CNOP | ~cacheOp1[1]) & ~dMValid1; + assign dTLBModified = drState == DR_IDLE & dcReq1 & data.wr & ~dDirty1; + assign dAddressError = drState == DR_IDLE & dcReq1 & ~in_kernel & ~dUser1; // ============================= // ======== drFlip-Flop ======== @@ -465,7 +455,8 @@ module MMU ( data.rdata ); - assign dc.req = dEn; + // do not request when handling CACHE instruction on I-Cache + assign dc.req = dEn & (cacheOp[2] | ~|cacheOp[1:0]); 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];