Merge branch 'fix/cache' into soc_top
This commit is contained in:
commit
00170784d0
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
@ -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
|
||||
}
|
||||
|
54
README.md
54
README.md
@ -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`指令需要清空流水线
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 ==========
|
||||
// ==============================
|
||||
|
Loading…
Reference in New Issue
Block a user