Merge branch 'fix/cache' into soc_top

This commit is contained in:
Paul Pan 2021-10-14 22:20:31 +08:00
commit 00170784d0
No known key found for this signature in database
GPG Key ID: DA97C6DCB84DEC68
6 changed files with 315 additions and 108 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

@ -5,11 +5,13 @@ Our awesome `MIPS` CPU written in `SystemVerilog` for Loongson Cup
```
.
├── model <-- IP行为模型
├── resources <-- 资源包
├── src <-- CPU设计代码
│ ├── AXI <-- AXI总线交互
│ ├── Cache <-- Cache
│ ├── Core <-- CPU核心
│ ├── Gadgets <-- 小部件
│ ├── CP0 <-- CP0协处理器
│ ├── include <-- 头文件
│ ├── IP <-- 用到的IP
@ -26,53 +28,10 @@ Our awesome `MIPS` CPU written in `SystemVerilog` for Loongson Cup
- [ ] 浮点运算单元
- [ ] ~~做一个真的`FPU`~~ :x:
- [ ] 浮点运算指令报`Coprocessor Unusable`,同时`CP0`中新增`Cause.CE` :clock3:
- [ ] 新增指令
| Status | Instruction | Type | Tier | Comment |
| :----------------: | :-------------------------------: | :------: | :--: | :-------------------------------------- |
| :heavy_check_mark: | `I-Cache Index Invalid` | `SYS` | 2 | |
| :heavy_check_mark: | `I-Cache Hit Invalid` | `SYS` | 2 | |
| :heavy_check_mark: | `D-Cache Index Writeback Invalid` | `SYS` | 2 | :cry: |
| :heavy_check_mark: | `D-Cache Index Store Tag` | `SYS` | 2 | |
| :heavy_check_mark: | `D-Cache Hit Invalid` | `SYS` | 2 | |
| :heavy_check_mark: | `D-Cache Hit Writeback Invalid` | `SYS` | 2 | |
| :heavy_check_mark: | `PREF` | `SYS` | 1 | Treat as `NOP` |
| :heavy_check_mark: | `SYNC` | `SYS` | 1 | Treat as `NOP` (We're strongly ordered) |
| :clock3: | `WAIT` | `SYS` | 2 | |
| :heavy_check_mark: | `TEQ` | `SYS` | 2 | |
| :heavy_check_mark: | `TEQI` | `SYS` | 2 | |
| :heavy_check_mark: | `TGE` | `SYS` | 2 | |
| :heavy_check_mark: | `TGEI` | `SYS` | 2 | |
| :heavy_check_mark: | `TGEIU` | `SYS` | 2 | |
| :heavy_check_mark: | `TGEU` | `SYS` | 2 | |
| :heavy_check_mark: | `TLT` | `SYS` | 2 | |
| :heavy_check_mark: | `TLTI` | `SYS` | 2 | |
| :heavy_check_mark: | `TLTIU` | `SYS` | 2 | |
| :heavy_check_mark: | `TLTU` | `SYS` | 2 | |
| :heavy_check_mark: | `TNE` | `SYS` | 2 | |
| :heavy_check_mark: | `TNEI` | `SYS` | 2 | |
| :clock3: | `CLO` | `ARITH` | 2 | `RT == RD` |
| :clock3: | `CLZ` | `ARITH` | 2 | `RT == RD` |
| :heavy_check_mark: | `MADD` | `ARITH` | 2 | `M`阶段加一个流水级 |
| :heavy_check_mark: | `MADDU` | `ARITH` | 2 | `M`阶段加一个流水级 |
| :heavy_check_mark: | `MSUB` | `ARITH` | 2 | `M`阶段加一个流水级 |
| :heavy_check_mark: | `MSUBU` | `ARITH` | 2 | `M`阶段加一个流水级 |
| :heavy_check_mark: | `MOVN` | `ARITH` | 2 | |
| :heavy_check_mark: | `MOVZ` | `ARITH` | 2 | |
| :x: | `LL` | `MEM` | 3 | 修改内核去除相关指令 |
| :heavy_check_mark: | `LWL` | `MEM` | 1 | |
| :heavy_check_mark: | `LWR` | `MEM` | 1 | |
| :x: | `SC` | `MEM` | 3 | 修改内核去除相关指令 |
| :heavy_check_mark: | `SWL` | `MEM` | 1 | |
| :heavy_check_mark: | `SWR` | `MEM` | 1 | |
| :x: | `BEQL` | `BRANCH` | 3 | 修改编译指令 |
| :x: | `BGEZALL` | `BRANCH` | 3 | 修改编译指令 |
| :x: | `BGEZL` | `BRANCH` | 3 | 修改编译指令 |
| :x: | `BGTZL` | `BRANCH` | 3 | 修改编译指令 |
| :x: | `BLEZL` | `BRANCH` | 3 | 修改编译指令 |
| :x: | `BLTZALL` | `BRANCH` | 3 | 修改编译指令 |
| :x: | `BLTZL` | `BRANCH` | 3 | 修改编译指令 |
| :x: | `BNEL` | `BRANCH` | 3 | 修改编译指令 |
- [x] 新增指令
- [ ] `Cache`指令修正
- [x] 完善 Test Cases
- [ ] 重新阻止流水线结构 `TLB`转换)
## `Cache`指令
@ -113,4 +72,3 @@ Hit Writeback Invalid : VA -> Lookup -> Hit? -> (Write Back) -> Write Zero
| 1 | 1 | 1 | |
| `I-Cache(0) or D-Cache(1)` | `Lookup(0) or Index(1)` | `WriteBack(0) or WriteOnly(1)` | |
`Todo`: 涉及`I-Cache`的`CACHE`指令需要清空流水线

View File

@ -222,6 +222,87 @@ TEST_CACHE_DCACHE_HIT(0xa00d0028, 0x800d0028, 4, 0xF0F0F0F0, 0xABCDEFAB)
.n98_done:
nop
## CACHE 1 D-Cache Index Writeback Invalid
## Enforced test on writeback whole line
li t0, 0xa00d0000
li t1, 0xa00d0800
li t2, 0xa00d1000
li t3, 0xa00d1800
li v0, 0xa00d000c
.n98_en_rst:
beq t0, v0, .n98_en_w_bgn
nop
sw zero, 0(t0)
sw zero, 0(t1)
sw zero, 0(t2)
sw zero, 0(t3)
addi t0, t0, 4
addi t1, t1, 4
addi t2, t2, 4
addi t3, t3, 4
j .n98_en_rst
nop
.n98_en_w_bgn:
li t0, 0x800d0000
li t1, 0x800d0800
li t2, 0x800d1000
li t3, 0x800d1800
li v0, 0x800d000c
li a0, 0xa5a50000
.n98_en_w:
beq t0, v0, .n98_en_chk_bgn
nop
sw a0, 0(t0)
sw a0, 0(t1)
sw a0, 0(t2)
sw a0, 0(t3)
addi t0, t0, 4
addi t1, t1, 4
addi t2, t2, 4
addi t3, t3, 4
addi a0, a0, 1
j .n98_en_w
nop
.n98_en_chk_bgn:
li t0, 0xa00d0000
li t1, 0xa00d0800
li t2, 0xa00d1000
li t3, 0xa00d1800
li v0, 0xa00d000c
li a0, 0xa5a50000
cache 1, 0(zero)
.n98_en_chk:
beq t0, v0, .n98_en_end
nop
lw a1, 0(t0)
bne a0, a1, inst_error
nop
lw a1, 0(t1)
bne a0, a1, inst_error
nop
lw a1, 0(t2)
bne a0, a1, inst_error
nop
lw a1, 0(t3)
bne a0, a1, inst_error
nop
addi t0, t0, 4
addi t1, t1, 4
addi t2, t2, 4
addi t3, t3, 4
addi a0, a0, 1
j .n98_en_chk
nop
.n98_en_end:
nop
###detect exception
bne s2, zero, inst_error
nop

View File

@ -29,8 +29,8 @@ LEAF(n99_cache_icache_test)
cache 16, 0(v0) # I-Cache Hit Invalid
# 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
nop;nop;nop;nop;nop;nop;
nop;nop;nop;nop;nop;nop;
j .n99_1
nop
@ -65,8 +65,8 @@ LEAF(n99_cache_icache_test)
.n99_2_check:
# 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
nop;nop;nop;nop;nop;nop;
nop;nop;nop;nop;nop;nop;
j .n99_2
nop
@ -101,8 +101,8 @@ LEAF(n99_cache_icache_test)
.n99_3_check:
# 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
nop;nop;nop;nop;nop;nop;
nop;nop;nop;nop;nop;nop;
j .n99_3
nop
@ -129,8 +129,8 @@ LEAF(n99_cache_icache_test)
cache 0, 0(v0) # I-Cache Hit Invalid
# 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
nop;nop;nop;nop;nop;nop;
nop;nop;nop;nop;nop;nop;
j .n99_4
nop
@ -157,8 +157,8 @@ LEAF(n99_cache_icache_test)
cache 8, 0(v0) # I-Cache Index Store Tag
# 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
nop;nop;nop;nop;nop;nop;
nop;nop;nop;nop;nop;nop;
j .n99_5
nop
@ -261,8 +261,8 @@ LEAF(n99_cache_icache_test)
.n99_con_loop_end:
# 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
nop;nop;nop;nop;nop;nop;
nop;nop;nop;nop;nop;nop;
j .n99_con
nop
@ -304,6 +304,128 @@ LEAF(n99_cache_icache_test)
148 00000000 nop
*/
/*
Enhanced test:
1. fill 800d0000, 800D0800, 800D1000, 800D1800 with instructions
2. jump to 800d0000, 800D0800, 800D1000, 800D1800 and execute
3. return back to here and check registers
4. modify 800d0000, 800D0800, 800D1000, 800D1800
5. same as 2 3
20050000 addi $a1, $zero, 0
03e00008 jr $ra
20a5000[] addi $a1, $a1, [case]
*/
.n99_en_bgn:
move a0, ra
li t0, 0x800d0000
li t1, 0x800d0800
li t2, 0x800d1000
li t3, 0x800d1800
li a1, 0x20050000
li a2, 0x03e00008
li a3, 0x20a50000
.n98_en_step1:
sw a1, 0(t0)
sw a1, 0(t1)
sw a1, 0(t2)
sw a1, 0(t3)
sw a2, 4(t0)
sw a2, 4(t1)
sw a2, 4(t2)
sw a2, 4(t3)
sw a3, 8(t0)
addi a3, a3, 1
sw a3, 8(t1)
addi a3, a3, 1
sw a3, 8(t2)
addi a3, a3, 1
sw a3, 8(t3)
addi a3, a3, 1
cache 1, 0(zero)
cache 0, 0(zero)
.n98_en_step23:
li a1, 0
li a2, 0
jalr t0
nop
bne a1, a2, inst_error
nop
li a1, 0
li a2, 1
jalr t1
nop
bne a1, a2, inst_error
nop
li a1, 0
li a2, 2
jalr t2
nop
bne a1, a2, inst_error
nop
li a1, 0
li a2, 3
jalr t3
nop
bne a1, a2, inst_error
nop
.n98_en_step4:
sw a3, 8(t0)
addi a3, a3, 1
sw a3, 8(t1)
addi a3, a3, 1
sw a3, 8(t2)
addi a3, a3, 1
sw a3, 8(t3)
addi a3, a3, 1
cache 1, 0(zero)
cache 0, 0(zero)
.n98_en_step5:
li a1, 0
li a2, 4
jalr t0
nop
bne a1, a2, inst_error
nop
li a1, 0
li a2, 5
jalr t1
nop
bne a1, a2, inst_error
nop
li a1, 0
li a2, 6
jalr t2
nop
bne a1, a2, inst_error
nop
li a1, 0
li a2, 7
jalr t3
nop
bne a1, a2, inst_error
nop
.n98_en_rst:
move ra, a0
###detect exception
bne s2, zero, inst_error
nop

View File

@ -320,6 +320,27 @@ inst_test:
jr t9 #kseg0 -> kseg1
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
@ -704,25 +725,7 @@ 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:
jal n100_movz_movn_test
nop

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 ==========
// ==============================