refactor cache inst on I-Cache
This commit is contained in:
parent
4facc2dd10
commit
c4942661dc
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
@ -63,5 +63,9 @@
|
|||||||
"typeinfo": "cpp",
|
"typeinfo": "cpp",
|
||||||
"iomanip": "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
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ module MMU (
|
|||||||
I_WA,
|
I_WA,
|
||||||
I_WD1, I_WD2, I_WD3, I_WD4, I_WD5, I_WD6, I_WD7, I_WD8,
|
I_WD1, I_WD2, I_WD3, I_WD4, I_WD5, I_WD6, I_WD7, I_WD8,
|
||||||
I_REFILL,
|
I_REFILL,
|
||||||
I_CACHE, I_CACHE_REFILL
|
I_CACHE, I_CACHE_DISPATCH, I_CACHE_REFILL
|
||||||
} istate_t;
|
} istate_t;
|
||||||
|
|
||||||
typedef enum bit [3:0] {
|
typedef enum bit [3:0] {
|
||||||
@ -79,6 +79,16 @@ module MMU (
|
|||||||
DWA_WA
|
DWA_WA
|
||||||
} dwastate_t;
|
} 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 ========
|
// ======== iVar ========
|
||||||
// ======================
|
// ======================
|
||||||
@ -96,10 +106,6 @@ module MMU (
|
|||||||
|
|
||||||
word_t iD1, iD2, iD3, iD4, iD5, iD6, iD7;
|
word_t iD1, iD2, iD3, iD4, iD5, iD6, iD7;
|
||||||
|
|
||||||
logic diReq;
|
|
||||||
CacheOp_t cacheOp1;
|
|
||||||
word_t dVA1, diPA;
|
|
||||||
|
|
||||||
// ================================
|
// ================================
|
||||||
// ======== iState Machine ========
|
// ======== iState Machine ========
|
||||||
// ================================
|
// ================================
|
||||||
@ -122,7 +128,14 @@ module MMU (
|
|||||||
ic.clearIdx = 0;
|
ic.clearIdx = 0;
|
||||||
case (iState)
|
case (iState)
|
||||||
I_IDLE: begin
|
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;
|
iNextState = I_CACHE;
|
||||||
end else if (~iValid1) iEn = 1;
|
end else if (~iValid1) iEn = 1;
|
||||||
else begin
|
else begin
|
||||||
@ -151,7 +164,8 @@ module MMU (
|
|||||||
if (inst_axi.rvalid) begin
|
if (inst_axi.rvalid) begin
|
||||||
inst.data_ok = 1;
|
inst.data_ok = 1;
|
||||||
if (iCached2) iNextState = I_WD3;
|
if (iCached2) iNextState = I_WD3;
|
||||||
else if (diReq) iNextState = I_CACHE;
|
// make sure icReq is handled
|
||||||
|
else if (icReq) iNextState = I_CACHE;
|
||||||
else begin
|
else begin
|
||||||
iEn = 1;
|
iEn = 1;
|
||||||
iNextState = I_IDLE;
|
iNextState = I_IDLE;
|
||||||
@ -177,29 +191,43 @@ module MMU (
|
|||||||
if (inst_axi.rvalid) iNextState = I_REFILL;
|
if (inst_axi.rvalid) iNextState = I_REFILL;
|
||||||
end
|
end
|
||||||
I_REFILL: begin
|
I_REFILL: begin
|
||||||
if (diReq) iNextState = I_CACHE;
|
// make sure icReq is handled
|
||||||
|
if (icReq) iNextState = I_CACHE;
|
||||||
else begin
|
else begin
|
||||||
iEn = 1;
|
iEn = 1;
|
||||||
iNextState = I_IDLE;
|
iNextState = I_IDLE;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
I_CACHE: begin
|
I_CACHE: begin
|
||||||
/*
|
/* For "I-Cache Hit Invalid":
|
||||||
* I-Cache Cache指令实现备注:
|
* send TLB translation request here to reduce logic on critical path
|
||||||
* 在进入 I_CACHE 状态时需确保 iEn == 0
|
* For "I-Cache Index Invalid" or "I-Cache Index Store Tag":
|
||||||
* 跳出 I_CACHE 状态时 iEn = 0
|
* I-Cache's request is send here too to sync with Hit Invalid
|
||||||
* 注意处理 Exceptions
|
*
|
||||||
* TLB 转换请求在 iNextState == I_CACHE时发送
|
* Critical Signals:
|
||||||
* I-Cache 查询请求在 iNextState == I_CACHE时发送
|
* 1. ic.req = 1'b1
|
||||||
* 在 I_CACHE 状态下屏蔽 iAddressError 且只有在 Address 类型请求下允许 TLBRefill 和 TLBInvalid
|
* 2. iVA = dVA1 (use a dedicated var?)
|
||||||
* I_CACHE 状态下向 I_CACHE 发送 clear 信号
|
|
||||||
* drState 状态机同步
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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];
|
ic.clearIdx = cacheOp1[1];
|
||||||
iEn = 0;
|
iEn2 = 1; // use iPA1 as tag
|
||||||
iEn2 = 1;
|
|
||||||
iNextState = I_CACHE_REFILL;
|
iNextState = I_CACHE_REFILL;
|
||||||
end
|
end
|
||||||
I_CACHE_REFILL: begin
|
I_CACHE_REFILL: begin
|
||||||
@ -230,7 +258,9 @@ module MMU (
|
|||||||
// ========== iFunction ==========
|
// ========== 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 iValid1 = iReq1 & iHit1 & iMValid1 & (in_kernel | iUser1);
|
||||||
|
|
||||||
assign inst.addr_ok = iEn;
|
assign inst.addr_ok = iEn;
|
||||||
@ -245,7 +275,7 @@ module MMU (
|
|||||||
);
|
);
|
||||||
|
|
||||||
// I-Cache req on inst query or cache instruction
|
// 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.valid = iValid1 & iCached1;
|
||||||
assign ic.index = iVA[`IC_TAGL-1:`IC_INDEXL];
|
assign ic.index = iVA[`IC_TAGL-1:`IC_INDEXL];
|
||||||
assign ic.tag1 = iEn2 ? iPA1[31:`IC_TAGL] : iPA2[31:`IC_TAGL];
|
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.len = (iEn2 ? iCached1 : iCached2) ? 4'b0111 : 4'b0001;
|
||||||
assign inst_axi.size = 3'b010;
|
assign inst_axi.size = 3'b010;
|
||||||
|
|
||||||
assign iTLBRefill = (iState == I_IDLE & iReq1 | iState == I_CACHE & ~cacheOp1[1]) & ~iHit1;
|
assign iTLBRefill = (iState == I_IDLE & iReq1 | iState == I_CACHE_DISPATCH & ~cacheOp1[1]) & ~iHit1;
|
||||||
assign iTLBInvalid = (iState == I_IDLE & iReq1 | iState == I_CACHE & ~cacheOp1[1]) & ~iMValid1;
|
assign iTLBInvalid = (iState == I_IDLE & iReq1 | iState == I_CACHE_DISPATCH & ~cacheOp1[1]) & ~iMValid1;
|
||||||
assign iAddressError = (iState == I_IDLE) & iReq1 & ~in_kernel & ~iUser1;
|
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);
|
ffenr #(1) dvalid_ff (clk, rst, data.req, dEn, dReq1);
|
||||||
ffen #(2) dsize_ff (clk, data.size, dEn, dSize1);
|
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 #(32) dPA_ff (clk, dPA1, dEn2, dPA2);
|
||||||
ffen #(1) dCached_ff (clk, dCached1, dEn2, dCached2);
|
ffen #(1) dCached_ff (clk, dCached1, dEn2, dCached2);
|
||||||
ffen #(1) dwr_ff (clk, data.wr, dEn2, dwr1);
|
ffen #(1) dwr_ff (clk, data.wr, dEn2, dwr1);
|
||||||
ffen #(4) dwstrb_ff (clk, data.wstrb, dEn2, dWstrb1);
|
ffen #(4) dwstrb_ff (clk, data.wstrb, dEn2, dWstrb1);
|
||||||
ffen #(32) dwdata_ff (clk, data.wdata, dEn2, dWdata1);
|
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);
|
ffen #(1) dDirtValid_ff (clk, dc.dirt_valid, dEn2, dDirtValid);
|
||||||
ffenr #(1) dCCached_ff (clk, dCClear | rst, 1'b1, dCEn, dCCached);
|
ffenr #(1) dCCached_ff (clk, dCClear | rst, 1'b1, dCEn, dCCached);
|
||||||
@ -348,7 +376,7 @@ module MMU (
|
|||||||
dClrReq = 0;
|
dClrReq = 0;
|
||||||
case (drState)
|
case (drState)
|
||||||
DR_IDLE: begin
|
DR_IDLE: begin
|
||||||
if (diReq) drNextState = DR_ICACHE;
|
if (icReq) drNextState = DR_ICACHE;
|
||||||
else if (dReq1 & cacheOp1[2] & (dCached1 | dCCached | cacheOp1[1])) begin
|
else if (dReq1 & cacheOp1[2] & (dCached1 | dCCached | cacheOp1[1])) begin
|
||||||
if (cacheOp1[0]) begin
|
if (cacheOp1[0]) begin
|
||||||
// 不需要写回的情况
|
// 不需要写回的情况
|
||||||
@ -474,7 +502,6 @@ module MMU (
|
|||||||
// ================================
|
// ================================
|
||||||
|
|
||||||
assign dVA = data.addr;
|
assign dVA = data.addr;
|
||||||
assign diReq = dReq1 & ~cacheOp1[2] & |cacheOp1[1:0];
|
|
||||||
assign dcReq1 = dReq1 & (cacheOp1 == CNOP | cacheOp1[2]); // exclude I-Cache clear
|
assign dcReq1 = dReq1 & (cacheOp1 == CNOP | cacheOp1[2]); // exclude I-Cache clear
|
||||||
assign dValid1 = dReq1 & dHit1 & dMValid1 & (~data.wr | dDirty1) & (in_kernel | dUser1);
|
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.wdata = dEn2 ? data.wdata : dWdata1;
|
||||||
assign dc.wstrb = dEn2 ? data.wstrb : dWstrb1;
|
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 ==========
|
// ========== VA -> PA ==========
|
||||||
// ==============================
|
// ==============================
|
||||||
|
Loading…
Reference in New Issue
Block a user