refactor cache inst on I-Cache

This commit is contained in:
Paul Pan 2021-09-27 16:58:22 +08:00
parent 4facc2dd10
commit c4942661dc
2 changed files with 73 additions and 30 deletions

View File

@ -63,5 +63,9 @@
"typeinfo": "cpp",
"iomanip": "cpp"
},
"editor.defaultFormatter": "bmpenuelas.systemverilog-formatter-vscode"
"editor.defaultFormatter": "bmpenuelas.systemverilog-formatter-vscode",
"verilog.linting.linter": "verilator",
"verilog.linting.verilator.useWSL": true,
"verilog.linting.verilator.arguments": "-x-assign 0 -Wall --assert -Wno-UNOPT -Wno-UNOPTFLAT -Wno-BLKSEQ -DSIMULATION_PC -I./src/AXI/ -I./src/Cache/ -I./src/Core/ -I./src/CP0/ -I./src/Gadgets/ -I./src/include/ -I./src/IP/ -I./src/MMU/ -I./src/Core/Gadgets/ -I./src/IP/DCData_bram/ -I./src/IP/DCTag_bram/ -I./src/IP/div_signed/ -I./src/IP/div_unsigned/ -I./src/IP/ICData_bram/ -I./src/IP/ICTag_bram/ -I./src/IP/mul_signed/ -I./src/IP/mul_unsigned/ ./model/DCData_bram.v ./model/DCTag_bram.v ./model/div_signed.v ./model/div_unsigned.v ./model/ICData_bram.v ./model/ICTag_bram.v ./model/mul_signed.sv ./model/mul_unsigned.sv ./src/mycpu_top.sv ./src/AXI/AXIRead_i.sv ./src/AXI/AXI.sv ./src/AXI/AXIWrite_i.sv ./src/Cache/DCache_i.sv ./src/Cache/DCache.sv ./src/Cache/ICache_i.sv ./src/Cache/ICache.sv ./src/Core/ALU.sv ./src/Core/Controller.sv ./src/Core/Datapath.sv ./src/Core/Queue.sv ./src/Core/RF.sv ./src/CP0/CP0.sv ./src/Gadgets/extender.sv ./src/Gadgets/ffenrc.sv ./src/Gadgets/ffenr.sv ./src/Gadgets/ffen.sv ./src/Gadgets/mux2.sv ./src/Gadgets/mux3.sv ./src/Gadgets/mux4.sv ./src/Gadgets/mux5.sv ./src/Gadgets/mux6.sv ./src/Gadgets/myBuffer0.sv ./src/Gadgets/myBuffer.sv ./src/Gadgets/onehot_bin16.sv ./src/Gadgets/onehot_bin32.sv ./src/Gadgets/onehot_bin4.sv ./src/Gadgets/onehot_bin8.sv ./src/Gadgets/prio_mux4.sv ./src/Gadgets/prio_mux5.sv ./src/MMU/MMU.sv ./src/MMU/sram_i.sv ./src/MMU/SRAM_RO_AXI_i.sv ./src/MMU/sramro_i.sv ./src/MMU/SRAM_W_AXI_i.sv ./src/MMU/TLB_Lookup.sv ./src/MMU/TLB.sv -top mycpu_top",
"files.trimTrailingWhitespace": true
}

View File

@ -56,7 +56,7 @@ module MMU (
I_WA,
I_WD1, I_WD2, I_WD3, I_WD4, I_WD5, I_WD6, I_WD7, I_WD8,
I_REFILL,
I_CACHE, I_CACHE_REFILL
I_CACHE, I_CACHE_DISPATCH, I_CACHE_REFILL
} istate_t;
typedef enum bit [3:0] {
@ -79,6 +79,16 @@ module MMU (
DWA_WA
} dwastate_t;
// ==========================
// ======== CacheVar ========
// ==========================
logic icReq; // whether there is a i-cache request
logic icvReq; // whether the i-cache req is valid (I_CACHE_DISPATCH)
CacheOp_t cacheOp1; // cacheOp piped for a cycle
word_t dVA1;
// ======================
// ======== iVar ========
// ======================
@ -96,10 +106,6 @@ module MMU (
word_t iD1, iD2, iD3, iD4, iD5, iD6, iD7;
logic diReq;
CacheOp_t cacheOp1;
word_t dVA1, diPA;
// ================================
// ======== iState Machine ========
// ================================
@ -122,7 +128,14 @@ module MMU (
ic.clearIdx = 0;
case (iState)
I_IDLE: begin
if (diReq & ~iValid1) begin
if (icReq & ~iReq1) begin
/*
* Try to strip TLB-related logic from the critical path
* When there is a cache request, if the instruction queue
* has been filled, directly handle the request to avoid
* deadlock , or else the request will be handled when
* current request is finished at I-REFILL or I-WD2
*/
iNextState = I_CACHE;
end else if (~iValid1) iEn = 1;
else begin
@ -151,7 +164,8 @@ module MMU (
if (inst_axi.rvalid) begin
inst.data_ok = 1;
if (iCached2) iNextState = I_WD3;
else if (diReq) iNextState = I_CACHE;
// make sure icReq is handled
else if (icReq) iNextState = I_CACHE;
else begin
iEn = 1;
iNextState = I_IDLE;
@ -177,29 +191,43 @@ module MMU (
if (inst_axi.rvalid) iNextState = I_REFILL;
end
I_REFILL: begin
if (diReq) iNextState = I_CACHE;
// make sure icReq is handled
if (icReq) 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 = 0
* Exceptions
* TLB iNextState == I_CACHE时发送
* I-Cache iNextState == I_CACHE时发送
* I_CACHE iAddressError Address TLBRefill TLBInvalid
* I_CACHE I_CACHE clear
* drState
/* For "I-Cache Hit Invalid":
* send TLB translation request here to reduce logic on critical path
* For "I-Cache Index Invalid" or "I-Cache Index Store Tag":
* I-Cache's request is send here too to sync with Hit Invalid
*
* Critical Signals:
* 1. ic.req = 1'b1
* 2. iVA = dVA1 (use a dedicated var?)
*/
if (~iTLBRefill & ~iTLBInvalid & (iCached1 & ic.hit | cacheOp1[1])) ic.clear = 1;
iNextState = I_CACHE_DISPATCH;
end
I_CACHE_DISPATCH: begin
/*
* State:
* 1. I-Cache state == LOOKUP
* 2. TLB iCached1 iHit1 iValid1 ... is valid
*
* Critical Signals:
* 1. ic.req = 1'b0
* 2. ic.tag1 -> iEn2 -> iPA1
* 3. ic.clear & ic.clearIdx
*/
if (icvReq) ic.clear = 1;
ic.clearIdx = cacheOp1[1];
iEn = 0;
iEn2 = 1;
iEn2 = 1; // use iPA1 as tag
iNextState = I_CACHE_REFILL;
end
I_CACHE_REFILL: begin
@ -230,7 +258,9 @@ module MMU (
// ========== iFunction ==========
// ===============================
assign iVA = (iNextState == I_CACHE | iState == I_CACHE) ? dVA1 : inst.addr;
// On I_CACHE: sending cache request
// On I_CACHE_DISPATCH: using the same addr to clear
assign iVA = (iState == I_CACHE | iState == I_CACHE_DISPATCH) ? dVA1 : inst.addr;
assign iValid1 = iReq1 & iHit1 & iMValid1 & (in_kernel | iUser1);
assign inst.addr_ok = iEn;
@ -245,7 +275,7 @@ module MMU (
);
// I-Cache req on inst query or cache instruction
assign ic.req = iEn & iState != I_CACHE | iNextState == I_CACHE;
assign ic.req = iEn | iState == 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];
@ -264,8 +294,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 & ~cacheOp1[1]) & ~iHit1;
assign iTLBInvalid = (iState == I_IDLE & iReq1 | iState == I_CACHE & ~cacheOp1[1]) & ~iMValid1;
assign iTLBRefill = (iState == I_IDLE & iReq1 | iState == I_CACHE_DISPATCH & ~cacheOp1[1]) & ~iHit1;
assign iTLBInvalid = (iState == I_IDLE & iReq1 | iState == I_CACHE_DISPATCH & ~cacheOp1[1]) & ~iMValid1;
assign iAddressError = (iState == I_IDLE) & iReq1 & ~in_kernel & ~iUser1;
// ======================
@ -307,13 +337,11 @@ 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);
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 #(1) dDirtValid_ff (clk, dc.dirt_valid, dEn2, dDirtValid);
ffenr #(1) dCCached_ff (clk, dCClear | rst, 1'b1, dCEn, dCCached);
@ -348,7 +376,7 @@ module MMU (
dClrReq = 0;
case (drState)
DR_IDLE: begin
if (diReq) drNextState = DR_ICACHE;
if (icReq) drNextState = DR_ICACHE;
else if (dReq1 & cacheOp1[2] & (dCached1 | dCCached | cacheOp1[1])) begin
if (cacheOp1[0]) begin
// 不需要写回的情况
@ -474,7 +502,6 @@ module MMU (
// ================================
assign dVA = data.addr;
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);
@ -722,6 +749,18 @@ module MMU (
assign dc.wdata = dEn2 ? data.wdata : dWdata1;
assign dc.wstrb = dEn2 ? data.wstrb : dWstrb1;
// ===============================
// ========== CacheInst ==========
// ===============================
ffen #(3) cache_op_ff (clk, cacheOp[2:0], dEn, cacheOp1[2:0]);
ffen #(32) dVA1_ff (clk, data.addr, dEn, dVA1);
assign icReq = dReq1 & ~cacheOp1[2] & |cacheOp1[1:0];
assign icvReq = ~iTLBRefill & ~iTLBInvalid & (iCached1 & ic.hit | cacheOp1[1]);
// ==============================
// ========== VA -> PA ==========
// ==============================