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", "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
} }

View File

@ -5,11 +5,13 @@ Our awesome `MIPS` CPU written in `SystemVerilog` for Loongson Cup
``` ```
. .
├── model <-- IP行为模型
├── resources <-- 资源包 ├── resources <-- 资源包
├── src <-- CPU设计代码 ├── src <-- CPU设计代码
│ ├── AXI <-- AXI总线交互 │ ├── AXI <-- AXI总线交互
│ ├── Cache <-- Cache │ ├── Cache <-- Cache
│ ├── Core <-- CPU核心 │ ├── Core <-- CPU核心
│ ├── Gadgets <-- 小部件
│ ├── CP0 <-- CP0协处理器 │ ├── CP0 <-- CP0协处理器
│ ├── include <-- 头文件 │ ├── include <-- 头文件
│ ├── IP <-- 用到的IP │ ├── IP <-- 用到的IP
@ -26,53 +28,10 @@ Our awesome `MIPS` CPU written in `SystemVerilog` for Loongson Cup
- [ ] 浮点运算单元 - [ ] 浮点运算单元
- [ ] ~~做一个真的`FPU`~~ :x: - [ ] ~~做一个真的`FPU`~~ :x:
- [ ] 浮点运算指令报`Coprocessor Unusable`,同时`CP0`中新增`Cause.CE` :clock3: - [ ] 浮点运算指令报`Coprocessor Unusable`,同时`CP0`中新增`Cause.CE` :clock3:
- [ ] 新增指令 - [x] 新增指令
- [ ] `Cache`指令修正
| Status | Instruction | Type | Tier | Comment | - [x] 完善 Test Cases
| :----------------: | :-------------------------------: | :------: | :--: | :-------------------------------------- | - [ ] 重新阻止流水线结构 `TLB`转换)
| :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 | 修改编译指令 |
## `Cache`指令 ## `Cache`指令
@ -113,4 +72,3 @@ Hit Writeback Invalid : VA -> Lookup -> Hit? -> (Write Back) -> Write Zero
| 1 | 1 | 1 | | | 1 | 1 | 1 | |
| `I-Cache(0) or D-Cache(1)` | `Lookup(0) or Index(1)` | `WriteBack(0) or WriteOnly(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: .n98_done:
nop 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 ###detect exception
bne s2, zero, inst_error bne s2, zero, inst_error
nop nop

View File

@ -29,8 +29,8 @@ LEAF(n99_cache_icache_test)
cache 16, 0(v0) # I-Cache Hit Invalid cache 16, 0(v0) # I-Cache Hit Invalid
# TODO: clear Datapath on CACHE # TODO: clear Datapath on CACHE
# using enough nop to stop prefetch # 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 j .n99_1
nop nop
@ -65,8 +65,8 @@ LEAF(n99_cache_icache_test)
.n99_2_check: .n99_2_check:
# TODO: clear Datapath on CACHE # TODO: clear Datapath on CACHE
# using enough nop to stop prefetch # 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 j .n99_2
nop nop
@ -101,8 +101,8 @@ LEAF(n99_cache_icache_test)
.n99_3_check: .n99_3_check:
# TODO: clear Datapath on CACHE # TODO: clear Datapath on CACHE
# using enough nop to stop prefetch # 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 j .n99_3
nop nop
@ -129,8 +129,8 @@ LEAF(n99_cache_icache_test)
cache 0, 0(v0) # I-Cache Hit Invalid cache 0, 0(v0) # I-Cache Hit Invalid
# TODO: clear Datapath on CACHE # TODO: clear Datapath on CACHE
# using enough nop to stop prefetch # 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 j .n99_4
nop nop
@ -157,8 +157,8 @@ LEAF(n99_cache_icache_test)
cache 8, 0(v0) # I-Cache Index Store Tag cache 8, 0(v0) # I-Cache Index Store Tag
# TODO: clear Datapath on CACHE # TODO: clear Datapath on CACHE
# using enough nop to stop prefetch # 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 j .n99_5
nop nop
@ -261,8 +261,8 @@ LEAF(n99_cache_icache_test)
.n99_con_loop_end: .n99_con_loop_end:
# TODO: clear Datapath on CACHE # TODO: clear Datapath on CACHE
# using enough nop to stop prefetch # 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 j .n99_con
nop nop
@ -304,6 +304,128 @@ LEAF(n99_cache_icache_test)
148 00000000 nop 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 ###detect exception
bne s2, zero, inst_error bne s2, zero, inst_error
nop nop

View File

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

View File

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