feat: implement privileged mode support
This commit is contained in:
542
docs/superpowers/plans/2026-06-29-privileged-test-fixes.md
Normal file
542
docs/superpowers/plans/2026-06-29-privileged-test-fixes.md
Normal file
@@ -0,0 +1,542 @@
|
||||
# Privileged Test Fixes Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Make `rv64mi-p-instret_overflow`, `rv64mi-p-mcsr`, `rv64si-p-dirty`, and `rv64si-p-icache-alias` behave according to the privileged tests instead of failing or timing out.
|
||||
|
||||
**Architecture:** Fix the small M-mode CSR gaps first, then make address translation privilege-aware for data accesses, then add an instruction-side translation path. Keep the implementation minimal for these tests: Sv39 only, no ASIDs, no speculative PTW sharing, and no broader cache redesign.
|
||||
|
||||
**Tech Stack:** Scala 2.13, Chisel 7.7, ScalaTest, generated SystemVerilog, Verilator RISC-V testbench.
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
- Modify `src/main/scala/common/Privileged.scala`: add missing machine CSR constants and mstatus bit constants used by translation logic.
|
||||
- Modify `src/main/scala/csr/CSRPermission.scala`: classify read-only ID CSRs and writable machine counters correctly.
|
||||
- Modify `src/main/scala/csr/CSRFile.scala`: implement `mvendorid/marchid/mimpid`, `minstret`, `mcountinhibit.IR`, and instret/minstret write semantics.
|
||||
- Modify `src/main/scala/common/Bundles.scala`: carry privilege and mstatus-derived access controls into translation requests.
|
||||
- Modify `src/main/scala/memory/MMU.scala`: enforce Sv39 permissions for S/U/MPRV, A/D, SUM, and superpage alignment.
|
||||
- Modify `src/main/scala/memory/LSU.scala`: decide effective privilege for loads/stores using `mstatus.MPRV/MPP`, and run translation only when effective privilege is S/U with non-Bare `satp`.
|
||||
- Modify `src/main/scala/OoOBackend.scala`: pass `currentPriv` and `mstatus` into LSU.
|
||||
- Modify `src/main/scala/frontend/Frontend.scala`: add `satp/currentPriv` inputs and an instruction PTW path.
|
||||
- Modify `src/main/scala/Core.scala`: wire frontend `satp/currentPriv` from backend/privilege state.
|
||||
- Test `src/test/scala/csr/CSRPermissionSpec.scala`: cover missing CSR permissions.
|
||||
- Test `src/test/scala/csr/CSRFileSpec.scala`: cover generated CSR read/write behavior.
|
||||
- Test `src/test/scala/memory/Sv39Spec.scala`: cover the generated MMU/LSU/Frontend ports and key permission expressions.
|
||||
- Verify with `sim/scripts/run_privileged_tests.sh`.
|
||||
|
||||
## Task 1: Fix Machine CSR Address Map
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/main/scala/common/Privileged.scala`
|
||||
- Modify: `src/main/scala/csr/CSRPermission.scala`
|
||||
- Test: `src/test/scala/csr/CSRPermissionSpec.scala`
|
||||
|
||||
- [ ] **Step 1: Add constants for missing machine CSRs**
|
||||
|
||||
In `src/main/scala/common/Privileged.scala`, add these constants near the existing machine CSR constants:
|
||||
|
||||
```scala
|
||||
val CSR_MVENDORID = "hf11".U(12.W)
|
||||
val CSR_MARCHID = "hf12".U(12.W)
|
||||
val CSR_MIMPID = "hf13".U(12.W)
|
||||
val CSR_MHARTID = "hf14".U(12.W)
|
||||
val CSR_MCOUNTINHIBIT = "h320".U(12.W)
|
||||
val CSR_MINSTRET = "hb02".U(12.W)
|
||||
```
|
||||
|
||||
Keep `CSR_CYCLE`, `CSR_TIME`, and `CSR_INSTRET` as user-visible read-only counter aliases at `0xc00` through `0xc02`.
|
||||
|
||||
- [ ] **Step 2: Update CSR permission sets**
|
||||
|
||||
In `CSRPermission.scala`, include the missing machine CSRs in `machineCsrs`, and treat ID CSRs as read-only:
|
||||
|
||||
```scala
|
||||
private val machineCsrs = Set(
|
||||
0x300, 0x301, 0x302, 0x303, 0x304, 0x305, 0x306, 0x320,
|
||||
0x340, 0x341, 0x342, 0x343, 0x344,
|
||||
0x3a0, 0x3b0, 0x744, 0x7a0, 0x7a1, 0x7a2, 0x7a5,
|
||||
0xb02, 0xf11, 0xf12, 0xf13, 0xf14)
|
||||
private val counterCsrs = Set(0xc00, 0xc01, 0xc02)
|
||||
private val readOnlyCsrs = Set(0xf11, 0xf12, 0xf13, 0xf14) ++ counterCsrs
|
||||
```
|
||||
|
||||
Update `isMachine` to include `CSR_MCOUNTINHIBIT`, `CSR_MINSTRET`, `CSR_MVENDORID`, `CSR_MARCHID`, and `CSR_MIMPID`.
|
||||
|
||||
- [ ] **Step 3: Add permission regression tests**
|
||||
|
||||
Append these cases to `CSRPermissionSpec.scala`:
|
||||
|
||||
```scala
|
||||
it should "allow machine-mode reads of implementation ID CSRs and reject writes" in {
|
||||
val ids = Seq(Privileged.CSR_MVENDORID, Privileged.CSR_MARCHID, Privileged.CSR_MIMPID, Privileged.CSR_MHARTID)
|
||||
ids.foreach { csr =>
|
||||
CSRPermission.readAllowedLit(csr.litValue, Privileged.PRV_M.litValue) should be(true)
|
||||
CSRPermission.writeAllowedLit(csr.litValue, Privileged.PRV_M.litValue) should be(false)
|
||||
CSRPermission.readAllowedLit(csr.litValue, Privileged.PRV_S.litValue) should be(false)
|
||||
}
|
||||
}
|
||||
|
||||
it should "allow machine-mode writes to minstret and mcountinhibit" in {
|
||||
CSRPermission.readAllowedLit(Privileged.CSR_MINSTRET.litValue, Privileged.PRV_M.litValue) should be(true)
|
||||
CSRPermission.writeAllowedLit(Privileged.CSR_MINSTRET.litValue, Privileged.PRV_M.litValue) should be(true)
|
||||
CSRPermission.readAllowedLit(Privileged.CSR_MCOUNTINHIBIT.litValue, Privileged.PRV_M.litValue) should be(true)
|
||||
CSRPermission.writeAllowedLit(Privileged.CSR_MCOUNTINHIBIT.litValue, Privileged.PRV_M.litValue) should be(true)
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Run the targeted test**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
sbt "testOnly CSRPermissionSpec"
|
||||
```
|
||||
|
||||
Expected before implementation: failures for missing constants or denied CSRs. Expected after implementation: `CSRPermissionSpec` passes.
|
||||
|
||||
## Task 2: Implement `mcsr` and `instret_overflow` CSR Semantics
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/main/scala/csr/CSRFile.scala`
|
||||
- Test: `src/test/scala/csr/CSRFileSpec.scala`
|
||||
|
||||
- [ ] **Step 1: Add CSR state**
|
||||
|
||||
In `CSRFile.scala`, add:
|
||||
|
||||
```scala
|
||||
val mcountinhibit = RegInit(0.U(p.xlen.W))
|
||||
val suppressInstretIncrement = WireDefault(false.B)
|
||||
```
|
||||
|
||||
The existing `instret` register should serve both `minstret` and `instret`.
|
||||
|
||||
- [ ] **Step 2: Increment `instret` unless inhibited or just written**
|
||||
|
||||
Replace the unconditional counter update region with:
|
||||
|
||||
```scala
|
||||
cycle := cycle + 1.U
|
||||
when(!mcountinhibit(2) && !suppressInstretIncrement) {
|
||||
instret := instret + 1.U
|
||||
}
|
||||
```
|
||||
|
||||
This matches the test expectation that a write to `minstret` suppresses the increment observed by the immediately following read.
|
||||
|
||||
- [ ] **Step 3: Add CSR reads**
|
||||
|
||||
Add to both the read switch and `writeOld` switch:
|
||||
|
||||
```scala
|
||||
is(Privileged.CSR_MCOUNTINHIBIT) { r := mcountinhibit }
|
||||
is(Privileged.CSR_MINSTRET) { r := instret }
|
||||
is(Privileged.CSR_MVENDORID) { r := 0.U }
|
||||
is(Privileged.CSR_MARCHID) { r := 0.U }
|
||||
is(Privileged.CSR_MIMPID) { r := 0.U }
|
||||
```
|
||||
|
||||
For the `writeOld` switch, use `writeOld := ...` instead of `r := ...`.
|
||||
|
||||
- [ ] **Step 4: Add CSR writes**
|
||||
|
||||
Inside the CSR write switch:
|
||||
|
||||
```scala
|
||||
is(Privileged.CSR_MCOUNTINHIBIT) { mcountinhibit := next & 4.U }
|
||||
is(Privileged.CSR_MINSTRET) {
|
||||
instret := next
|
||||
suppressInstretIncrement := true.B
|
||||
}
|
||||
```
|
||||
|
||||
Do not make `mvendorid/marchid/mimpid/mhartid` writable.
|
||||
|
||||
- [ ] **Step 5: Add generated-Verilog smoke tests**
|
||||
|
||||
Append to `CSRFileSpec.scala`:
|
||||
|
||||
```scala
|
||||
it should "contain machine counter and ID CSR decode paths" in {
|
||||
val verilog = ChiselStage.emitSystemVerilog(new CSRFile())
|
||||
verilog should include("mcountinhibit")
|
||||
verilog should include("12'hB02")
|
||||
verilog should include("12'hF11")
|
||||
verilog should include("12'hF12")
|
||||
verilog should include("12'hF13")
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 6: Run targeted tests and two privileged binaries**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
sbt "testOnly CSRPermissionSpec CSRFileSpec"
|
||||
make -C sim/verilator compile
|
||||
timeout 5s sim/verilator/obj_dir/VCore ../../riscv-tests/isa/rv64mi-p-mcsr
|
||||
timeout 5s sim/verilator/obj_dir/VCore ../../riscv-tests/isa/rv64mi-p-instret_overflow
|
||||
```
|
||||
|
||||
Expected: both Verilator commands exit `0`.
|
||||
|
||||
## Task 3: Make Data Translation Privilege-Aware
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/main/scala/common/Privileged.scala`
|
||||
- Modify: `src/main/scala/common/Bundles.scala`
|
||||
- Modify: `src/main/scala/memory/MMU.scala`
|
||||
- Modify: `src/main/scala/memory/LSU.scala`
|
||||
- Modify: `src/main/scala/OoOBackend.scala`
|
||||
- Test: `src/test/scala/memory/Sv39Spec.scala`
|
||||
|
||||
- [ ] **Step 1: Add mstatus bit constants**
|
||||
|
||||
In `Privileged.scala`, add:
|
||||
|
||||
```scala
|
||||
val MSTATUS_MPRV_BIT = 17
|
||||
val MSTATUS_SUM_BIT = 18
|
||||
val MSTATUS_MXR_BIT = 19
|
||||
val MSTATUS_MPP_HI = 12
|
||||
val MSTATUS_MPP_LO = 11
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Extend TLB request metadata**
|
||||
|
||||
In `Bundles.scala`, extend `TlbReq`:
|
||||
|
||||
```scala
|
||||
class TlbReq(p: CoreParams = CoreParams()) extends Bundle {
|
||||
val valid = Bool()
|
||||
val vaddr = UInt(p.xlen.W)
|
||||
val isStore = Bool()
|
||||
val isFetch = Bool()
|
||||
val priv = UInt(2.W)
|
||||
val sum = Bool()
|
||||
val mxr = Bool()
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Enforce Sv39 permissions in the page walker**
|
||||
|
||||
In `MMU.scala`, register `priv/sum/mxr` alongside request state:
|
||||
|
||||
```scala
|
||||
val privReg = Reg(UInt(2.W))
|
||||
val sumReg = Reg(Bool())
|
||||
val mxrReg = Reg(Bool())
|
||||
```
|
||||
|
||||
Set them in `sIdle` when accepting a request:
|
||||
|
||||
```scala
|
||||
privReg := io.req.priv
|
||||
sumReg := io.req.sum
|
||||
mxrReg := io.req.mxr
|
||||
```
|
||||
|
||||
Replace the existing `permFault` with:
|
||||
|
||||
```scala
|
||||
val userPage = pteU
|
||||
val supervisorAccessToUser = privReg === Privileged.PRV_S && userPage && !sumReg && !isFetchReg
|
||||
val supervisorFetchUser = privReg === Privileged.PRV_S && userPage && isFetchReg
|
||||
val userAccessSupervisor = privReg === Privileged.PRV_U && !userPage
|
||||
val readAllowed = pteR || (mxrReg && pteX)
|
||||
val accessPermFault = Mux(isFetchReg, !pteX, Mux(isStoreReg, !pteW || !pteD, !readAllowed))
|
||||
val adFault = !pteA || (isStoreReg && !pteD)
|
||||
val permFault = accessPermFault || adFault || supervisorAccessToUser || supervisorFetchUser || userAccessSupervisor
|
||||
```
|
||||
|
||||
Add superpage PPN alignment checks in the leaf case:
|
||||
|
||||
```scala
|
||||
val misalignedSuperpage =
|
||||
(level === 2.U && ptePpn(17, 0) =/= 0.U) ||
|
||||
(level === 1.U && ptePpn(8, 0) =/= 0.U)
|
||||
when(permFault || misalignedSuperpage) {
|
||||
walkFault := true.B
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Make LSU choose effective privilege**
|
||||
|
||||
Add LSU IO inputs:
|
||||
|
||||
```scala
|
||||
val currentPriv = Input(UInt(2.W))
|
||||
val mstatus = Input(UInt(p.xlen.W))
|
||||
```
|
||||
|
||||
In `LSU.scala`, replace `bare` with effective-mode logic:
|
||||
|
||||
```scala
|
||||
val mprv = io.mstatus(Privileged.MSTATUS_MPRV_BIT)
|
||||
val mpp = io.mstatus(Privileged.MSTATUS_MPP_HI, Privileged.MSTATUS_MPP_LO)
|
||||
val effectivePriv = Mux(io.currentPriv === Privileged.PRV_M && mprv, mpp, io.currentPriv)
|
||||
val translate = io.satp(63, 60) =/= 0.U && effectivePriv =/= Privileged.PRV_M
|
||||
val bare = !translate
|
||||
```
|
||||
|
||||
Populate DTLB/MMU request metadata:
|
||||
|
||||
```scala
|
||||
dtlb.io.req.priv := effectivePriv
|
||||
dtlb.io.req.sum := io.mstatus(Privileged.MSTATUS_SUM_BIT)
|
||||
dtlb.io.req.mxr := io.mstatus(Privileged.MSTATUS_MXR_BIT)
|
||||
mmu.io.req.priv := effectivePriv
|
||||
mmu.io.req.sum := io.mstatus(Privileged.MSTATUS_SUM_BIT)
|
||||
mmu.io.req.mxr := io.mstatus(Privileged.MSTATUS_MXR_BIT)
|
||||
```
|
||||
|
||||
- [ ] **Step 5: Wire backend to LSU**
|
||||
|
||||
In `OoOBackend.scala`, add:
|
||||
|
||||
```scala
|
||||
lsu.io.currentPriv := io.currentPriv
|
||||
lsu.io.mstatus := csr.io.mstatus
|
||||
```
|
||||
|
||||
- [ ] **Step 6: Update tests**
|
||||
|
||||
Append to `Sv39Spec.scala`:
|
||||
|
||||
```scala
|
||||
it should "generate LSU effective privilege translation controls" in {
|
||||
val verilog = ChiselStage.emitSystemVerilog(new LSU())
|
||||
verilog should include("io_currentPriv")
|
||||
verilog should include("io_mstatus")
|
||||
verilog should include("io_mstatus[17]")
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 7: Run tests and dirty binary**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
sbt "testOnly Sv39Spec"
|
||||
make -C sim/verilator compile
|
||||
timeout 5s sim/verilator/obj_dir/VCore ../../riscv-tests/isa/rv64si-p-dirty
|
||||
```
|
||||
|
||||
Expected: `rv64si-p-dirty` exits `0`. If it still fails, inspect whether the first `TESTNUM=2` store raises store page fault and whether the M-mode handler reads `page_table_1` physically.
|
||||
|
||||
## Task 4: Add Instruction-Side Sv39 Translation
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/main/scala/frontend/ITLB.scala`
|
||||
- Modify: `src/main/scala/frontend/Frontend.scala`
|
||||
- Modify: `src/main/scala/OoOBackend.scala`
|
||||
- Modify: `src/main/scala/Core.scala`
|
||||
- Test: `src/test/scala/memory/Sv39Spec.scala`
|
||||
|
||||
- [ ] **Step 1: Extend Frontend IO**
|
||||
|
||||
Add to `Frontend` IO:
|
||||
|
||||
```scala
|
||||
val satp = Input(UInt(p.xlen.W))
|
||||
val currentPriv = Input(UInt(2.W))
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Add an instruction MMU instance**
|
||||
|
||||
In `Frontend.scala`, instantiate MMU:
|
||||
|
||||
```scala
|
||||
val immu = Module(new MMU(p))
|
||||
val fetchTranslate = io.satp(63, 60) =/= 0.U && io.currentPriv =/= Privileged.PRV_M
|
||||
```
|
||||
|
||||
Set ITLB request valid only when translation is active:
|
||||
|
||||
```scala
|
||||
itlb.io.req.valid := fetchTranslate
|
||||
itlb.io.req.vaddr := pc
|
||||
itlb.io.req.isStore := false.B
|
||||
itlb.io.req.isFetch := true.B
|
||||
itlb.io.req.priv := io.currentPriv
|
||||
itlb.io.req.sum := false.B
|
||||
itlb.io.req.mxr := false.B
|
||||
```
|
||||
|
||||
Drive `immu` for ITLB misses:
|
||||
|
||||
```scala
|
||||
immu.io.satp := io.satp
|
||||
immu.io.req.valid := fetchTranslate && itlb.io.resp.miss
|
||||
immu.io.req.vaddr := pc
|
||||
immu.io.req.isStore := false.B
|
||||
immu.io.req.isFetch := true.B
|
||||
immu.io.req.priv := io.currentPriv
|
||||
immu.io.req.sum := false.B
|
||||
immu.io.req.mxr := false.B
|
||||
itlb.io.refill := immu.io.refill
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Add instruction PTW memory port**
|
||||
|
||||
Add frontend IO:
|
||||
|
||||
```scala
|
||||
val ptwMemReqValid = Output(Bool())
|
||||
val ptwMemReqAddr = Output(UInt(p.xlen.W))
|
||||
val ptwMemRespValid = Input(Bool())
|
||||
val ptwMemRespData = Input(UInt(p.xlen.W))
|
||||
```
|
||||
|
||||
Wire:
|
||||
|
||||
```scala
|
||||
io.ptwMemReqValid := immu.io.ptwMemReq.valid
|
||||
io.ptwMemReqAddr := immu.io.ptwMemReq.addr
|
||||
immu.io.ptwMemResp.valid := io.ptwMemRespValid
|
||||
immu.io.ptwMemResp.data := io.ptwMemRespData
|
||||
```
|
||||
|
||||
In `Core.scala`, arbitrate instruction-side PTW reads onto the existing data memory read path. Add a one-bit outstanding register so the frontend only consumes the memory response that belongs to its PTW request:
|
||||
|
||||
```scala
|
||||
val frontendPtwOutstanding = RegInit(false.B)
|
||||
val frontendPtwFire = frontend.io.ptwMemReqValid
|
||||
when(frontendPtwFire) {
|
||||
frontendPtwOutstanding := true.B
|
||||
}.elsewhen(io.dmem_resp_valid && frontendPtwOutstanding) {
|
||||
frontendPtwOutstanding := false.B
|
||||
}
|
||||
|
||||
io.dmem_req_valid := frontend.io.ptwMemReqValid || backend.io.dmemReqValid
|
||||
io.dmem_req_bits_addr := Mux(frontend.io.ptwMemReqValid, frontend.io.ptwMemReqAddr, backend.io.dmemReq.addr)
|
||||
io.dmem_req_bits_data := Mux(frontend.io.ptwMemReqValid, 0.U, backend.io.dmemReq.data)
|
||||
io.dmem_req_bits_isStore := Mux(frontend.io.ptwMemReqValid, false.B, backend.io.dmemReq.isStore)
|
||||
io.dmem_req_bits_size := Mux(frontend.io.ptwMemReqValid, 3.U, backend.io.dmemReq.size)
|
||||
frontend.io.ptwMemRespValid := io.dmem_resp_valid && frontendPtwOutstanding
|
||||
frontend.io.ptwMemRespData := io.dmem_resp_bits
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Gate fetch while instruction translation is pending**
|
||||
|
||||
Use translated physical address only when translation is ready:
|
||||
|
||||
```scala
|
||||
val fetchTranslationReady = !fetchTranslate || itlb.io.resp.hit
|
||||
val fetchTranslationFault = fetchTranslate && (itlb.io.resp.pageFault || immu.io.resp.pageFault)
|
||||
val fetchPaddr = Mux(fetchTranslate, itlb.io.resp.paddr, pc)
|
||||
icache.io.reqValid := fetchTranslationReady && !fetchTranslationFault && !instMisaligned && !faultPending
|
||||
icache.io.reqAddr := fetchPaddr
|
||||
```
|
||||
|
||||
Update `fetchFault` to include `fetchTranslationFault`.
|
||||
|
||||
- [ ] **Step 5: Expose backend CSR `satp`**
|
||||
|
||||
In `OoOBackend.scala`, add an output:
|
||||
|
||||
```scala
|
||||
val satpOut = Output(UInt(p.xlen.W))
|
||||
```
|
||||
|
||||
Drive it from the CSR file:
|
||||
|
||||
```scala
|
||||
io.satpOut := csr.io.satp
|
||||
```
|
||||
|
||||
Keep the existing LSU connection:
|
||||
|
||||
```scala
|
||||
lsu.io.satp := csr.io.satp
|
||||
```
|
||||
|
||||
- [ ] **Step 6: Wire frontend privilege inputs**
|
||||
|
||||
In `Core.scala`:
|
||||
|
||||
```scala
|
||||
frontend.io.satp := backend.io.satpOut
|
||||
frontend.io.currentPriv := privCtrl.io.priv
|
||||
```
|
||||
|
||||
- [ ] **Step 7: Add generated-Verilog frontend test**
|
||||
|
||||
Append to `Sv39Spec.scala`:
|
||||
|
||||
```scala
|
||||
it should "generate frontend instruction-side translation ports" in {
|
||||
val verilog = ChiselStage.emitSystemVerilog(new Frontend())
|
||||
verilog should include("io_satp")
|
||||
verilog should include("io_currentPriv")
|
||||
verilog should include("ptwMemReq")
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 8: Run icache-alias**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
sbt "testOnly Sv39Spec"
|
||||
make -C sim/verilator compile
|
||||
timeout 5s sim/verilator/obj_dir/VCore ../../riscv-tests/isa/rv64si-p-icache-alias
|
||||
```
|
||||
|
||||
Expected: no `Bad imem fetch pc=0x0`, no out-of-bounds fetch stream, exit `0`.
|
||||
|
||||
## Task 5: Full Privileged Regression
|
||||
|
||||
**Files:**
|
||||
- No source edits.
|
||||
- Verify: `sim/results/privileged_test_results.txt`
|
||||
|
||||
- [ ] **Step 1: Rebuild generated RTL/testbench**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
sbt "runMain CoreOoO"
|
||||
make -C sim/verilator compile
|
||||
```
|
||||
|
||||
Expected: both commands exit `0`.
|
||||
|
||||
- [ ] **Step 2: Run privileged suite**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd sim/scripts
|
||||
TIMEOUT_SECONDS=10 ./run_privileged_tests.sh
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
```text
|
||||
rv64mi-p-instret_overflow: exit=0 PASS
|
||||
rv64mi-p-mcsr: exit=0 PASS
|
||||
rv64si-p-dirty: exit=0 PASS
|
||||
rv64si-p-icache-alias: exit=0 PASS
|
||||
```
|
||||
|
||||
`rv64ui-p-ma_data` is not in this privileged script and remains acceptable as a known aligned-access limitation in the base UI suite.
|
||||
|
||||
- [ ] **Step 3: Run base ISA suite**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd sim/scripts
|
||||
./run_tests.sh
|
||||
```
|
||||
|
||||
Expected: existing PASS count is preserved, with only `rv64ui-p-ma_data` failing if the processor intentionally does not support misaligned data access.
|
||||
|
||||
## Self-Review
|
||||
|
||||
- Spec coverage: `rv64mi-p-instret_overflow` is covered by Task 1 and Task 2; `rv64mi-p-mcsr` is covered by Task 1 and Task 2; `rv64si-p-dirty` is covered by Task 3; `rv64si-p-icache-alias` is covered by Task 4.
|
||||
- Placeholder scan: no deferred design items are left in the plan; every task has concrete files, code snippets, commands, and expected outcomes.
|
||||
- Type consistency: new `TlbReq` fields are populated in LSU and Frontend; MMU consumes the same field names; Core/OoOBackend wiring is explicitly called out where ownership of `satp` crosses module boundaries.
|
||||
@@ -8,18 +8,31 @@ module CSRFile(
|
||||
input [63:0] io_cmd_rs1,
|
||||
input [4:0] io_cmd_zimm,
|
||||
input [11:0] io_readAddr,
|
||||
input [1:0] io_currentPriv,
|
||||
output [63:0] io_rdata,
|
||||
output io_readIllegal,
|
||||
input io_trap,
|
||||
input [63:0] io_trapPc,
|
||||
io_trapCause,
|
||||
io_trapTval,
|
||||
input [1:0] io_trapTargetPriv,
|
||||
output [63:0] io_trapVector,
|
||||
input io_xret,
|
||||
io_xretIsMret,
|
||||
output [63:0] io_satp,
|
||||
io_mtvec,
|
||||
io_mepc
|
||||
io_mepc,
|
||||
io_sepc,
|
||||
io_medeleg,
|
||||
io_mstatus
|
||||
);
|
||||
|
||||
reg [63:0] cycle;
|
||||
reg [63:0] instret;
|
||||
reg [63:0] mcountinhibit;
|
||||
reg suppressInstretAfterWrite;
|
||||
reg [63:0] mstatus;
|
||||
reg [63:0] mtvecReg;
|
||||
reg [63:0] mscratch;
|
||||
reg [63:0] mepcReg;
|
||||
reg [63:0] mcause;
|
||||
reg [63:0] mtval;
|
||||
@@ -27,18 +40,171 @@ module CSRFile(
|
||||
reg [63:0] mideleg;
|
||||
reg [63:0] mie;
|
||||
reg [63:0] mip;
|
||||
reg [63:0] sstatus;
|
||||
reg [63:0] mcounteren;
|
||||
reg [63:0] pmpcfg0;
|
||||
reg [63:0] pmpaddr0;
|
||||
reg [63:0] tdata1;
|
||||
reg [63:0] tdata2;
|
||||
reg [63:0] tcontrol;
|
||||
reg [63:0] mnstatus;
|
||||
reg [63:0] scounteren;
|
||||
reg [63:0] stvec;
|
||||
reg [63:0] sepc;
|
||||
reg [63:0] scause;
|
||||
reg [63:0] stval;
|
||||
reg [63:0] sscratch;
|
||||
reg [63:0] satpReg;
|
||||
wire _readAllowed_T_75 = io_readAddr == 12'h300;
|
||||
wire _readAllowed_T_76 = io_readAddr == 12'h301;
|
||||
wire _readAllowed_T_78 = io_readAddr == 12'h302;
|
||||
wire _readAllowed_T_80 = io_readAddr == 12'h303;
|
||||
wire _readAllowed_T_82 = io_readAddr == 12'h304;
|
||||
wire _readAllowed_T_84 = io_readAddr == 12'h305;
|
||||
wire _readAllowed_T_86 = io_readAddr == 12'h306;
|
||||
wire _readAllowed_T_88 = io_readAddr == 12'h340;
|
||||
wire _readAllowed_T_90 = io_readAddr == 12'h341;
|
||||
wire _readAllowed_T_92 = io_readAddr == 12'h342;
|
||||
wire _readAllowed_T_94 = io_readAddr == 12'h343;
|
||||
wire _readAllowed_T_96 = io_readAddr == 12'h344;
|
||||
wire _readAllowed_T_98 = io_readAddr == 12'h3A0;
|
||||
wire _readAllowed_T_100 = io_readAddr == 12'h3B0;
|
||||
wire _readAllowed_T_102 = io_readAddr == 12'h7A0;
|
||||
wire _readAllowed_T_104 = io_readAddr == 12'h7A1;
|
||||
wire _readAllowed_T_106 = io_readAddr == 12'h7A2;
|
||||
wire _readAllowed_T_108 = io_readAddr == 12'h7A5;
|
||||
wire _readAllowed_T_110 = io_readAddr == 12'h744;
|
||||
wire _readAllowed_T_112 = io_readAddr == 12'h320;
|
||||
wire _readAllowed_T_114 = io_readAddr == 12'hB02;
|
||||
wire _readAllowed_T_116 = io_readAddr == 12'hF11;
|
||||
wire _readAllowed_T_118 = io_readAddr == 12'hF12;
|
||||
wire _readAllowed_T_120 = io_readAddr == 12'hF13;
|
||||
wire _readAllowed_T_122 = io_readAddr == 12'hF14;
|
||||
wire _readAllowed_T_125 = io_readAddr == 12'h100;
|
||||
wire _readAllowed_T_126 = io_readAddr == 12'h104;
|
||||
wire _readAllowed_T_128 = io_readAddr == 12'h105;
|
||||
wire _readAllowed_T_130 = io_readAddr == 12'h140;
|
||||
wire _readAllowed_T_132 = io_readAddr == 12'h106;
|
||||
wire _readAllowed_T_134 = io_readAddr == 12'h141;
|
||||
wire _readAllowed_T_136 = io_readAddr == 12'h142;
|
||||
wire _readAllowed_T_138 = io_readAddr == 12'h143;
|
||||
wire _readAllowed_T_140 = io_readAddr == 12'h144;
|
||||
wire _readAllowed_T_142 = io_readAddr == 12'h180;
|
||||
wire _readAllowed_T_69 = io_readAddr == 12'hC00;
|
||||
wire _readAllowed_T_70 = io_readAddr == 12'hC01;
|
||||
wire _readAllowed_T_72 = io_readAddr == 12'hC02;
|
||||
wire readAllowed =
|
||||
(_readAllowed_T_75 | _readAllowed_T_76 | _readAllowed_T_78 | _readAllowed_T_80
|
||||
| _readAllowed_T_82 | _readAllowed_T_84 | _readAllowed_T_86 | _readAllowed_T_88
|
||||
| _readAllowed_T_90 | _readAllowed_T_92 | _readAllowed_T_94 | _readAllowed_T_96
|
||||
| _readAllowed_T_98 | _readAllowed_T_100 | _readAllowed_T_102 | _readAllowed_T_104
|
||||
| _readAllowed_T_106 | _readAllowed_T_108 | _readAllowed_T_110 | _readAllowed_T_112
|
||||
| _readAllowed_T_114 | _readAllowed_T_116 | _readAllowed_T_118 | _readAllowed_T_120
|
||||
| _readAllowed_T_122 | _readAllowed_T_125 | _readAllowed_T_126 | _readAllowed_T_128
|
||||
| _readAllowed_T_130 | _readAllowed_T_132 | _readAllowed_T_134 | _readAllowed_T_136
|
||||
| _readAllowed_T_138 | _readAllowed_T_140 | _readAllowed_T_142 | _readAllowed_T_69
|
||||
| _readAllowed_T_70 | _readAllowed_T_72)
|
||||
& (_readAllowed_T_75 | _readAllowed_T_76 | _readAllowed_T_78 | _readAllowed_T_80
|
||||
| _readAllowed_T_82 | _readAllowed_T_84 | _readAllowed_T_86 | _readAllowed_T_88
|
||||
| _readAllowed_T_90 | _readAllowed_T_92 | _readAllowed_T_94 | _readAllowed_T_96
|
||||
| _readAllowed_T_98 | _readAllowed_T_100 | _readAllowed_T_102 | _readAllowed_T_104
|
||||
| _readAllowed_T_106 | _readAllowed_T_108 | _readAllowed_T_110 | _readAllowed_T_112
|
||||
| _readAllowed_T_114 | _readAllowed_T_116 | _readAllowed_T_118 | _readAllowed_T_120
|
||||
| _readAllowed_T_122
|
||||
? (&io_currentPriv)
|
||||
: ~(_readAllowed_T_125 | _readAllowed_T_126 | _readAllowed_T_128
|
||||
| _readAllowed_T_130 | _readAllowed_T_132 | _readAllowed_T_134
|
||||
| _readAllowed_T_136 | _readAllowed_T_138 | _readAllowed_T_140
|
||||
| _readAllowed_T_142) | (|io_currentPriv));
|
||||
wire _writeAllowed_T_75 = io_cmd_addr == 12'h300;
|
||||
wire _writeAllowed_T_76 = io_cmd_addr == 12'h301;
|
||||
wire _writeAllowed_T_78 = io_cmd_addr == 12'h302;
|
||||
wire _writeAllowed_T_80 = io_cmd_addr == 12'h303;
|
||||
wire _writeAllowed_T_82 = io_cmd_addr == 12'h304;
|
||||
wire _writeAllowed_T_84 = io_cmd_addr == 12'h305;
|
||||
wire _writeAllowed_T_86 = io_cmd_addr == 12'h306;
|
||||
wire _writeAllowed_T_88 = io_cmd_addr == 12'h340;
|
||||
wire _writeAllowed_T_90 = io_cmd_addr == 12'h341;
|
||||
wire _writeAllowed_T_92 = io_cmd_addr == 12'h342;
|
||||
wire _writeAllowed_T_94 = io_cmd_addr == 12'h343;
|
||||
wire _writeAllowed_T_96 = io_cmd_addr == 12'h344;
|
||||
wire _writeAllowed_T_98 = io_cmd_addr == 12'h3A0;
|
||||
wire _writeAllowed_T_100 = io_cmd_addr == 12'h3B0;
|
||||
wire _writeAllowed_T_102 = io_cmd_addr == 12'h7A0;
|
||||
wire _writeAllowed_T_104 = io_cmd_addr == 12'h7A1;
|
||||
wire _writeAllowed_T_106 = io_cmd_addr == 12'h7A2;
|
||||
wire _writeAllowed_T_108 = io_cmd_addr == 12'h7A5;
|
||||
wire _writeAllowed_T_110 = io_cmd_addr == 12'h744;
|
||||
wire _writeAllowed_T_112 = io_cmd_addr == 12'h320;
|
||||
wire _writeAllowed_T_114 = io_cmd_addr == 12'hB02;
|
||||
wire _writeAllowed_T_148 = io_cmd_addr == 12'hF11;
|
||||
wire _writeAllowed_T_149 = io_cmd_addr == 12'hF12;
|
||||
wire _writeAllowed_T_151 = io_cmd_addr == 12'hF13;
|
||||
wire _writeAllowed_T_153 = io_cmd_addr == 12'hF14;
|
||||
wire _writeAllowed_T_125 = io_cmd_addr == 12'h100;
|
||||
wire _writeAllowed_T_126 = io_cmd_addr == 12'h104;
|
||||
wire _writeAllowed_T_128 = io_cmd_addr == 12'h105;
|
||||
wire _writeAllowed_T_130 = io_cmd_addr == 12'h140;
|
||||
wire _writeAllowed_T_132 = io_cmd_addr == 12'h106;
|
||||
wire _writeAllowed_T_134 = io_cmd_addr == 12'h141;
|
||||
wire _writeAllowed_T_136 = io_cmd_addr == 12'h142;
|
||||
wire _writeAllowed_T_138 = io_cmd_addr == 12'h143;
|
||||
wire _writeAllowed_T_140 = io_cmd_addr == 12'h144;
|
||||
wire _writeAllowed_T_142 = io_cmd_addr == 12'h180;
|
||||
wire _writeAllowed_T_155 = io_cmd_addr == 12'hC00;
|
||||
wire _writeAllowed_T_156 = io_cmd_addr == 12'hC01;
|
||||
wire _writeAllowed_T_158 = io_cmd_addr == 12'hC02;
|
||||
wire [63:0] mstatusView = mstatus & 64'hFFFFFFF0FFFFFFFF | 64'hA00000000;
|
||||
wire [63:0] sstatusView = {30'h0, mstatusView[33:1] & 33'h10006F0B1, 1'h0};
|
||||
wire _GEN =
|
||||
io_cmd_valid & (|io_cmd_cmd)
|
||||
& (_writeAllowed_T_75 | _writeAllowed_T_76 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | _writeAllowed_T_86 | _writeAllowed_T_88
|
||||
| _writeAllowed_T_90 | _writeAllowed_T_92 | _writeAllowed_T_94 | _writeAllowed_T_96
|
||||
| _writeAllowed_T_98 | _writeAllowed_T_100 | _writeAllowed_T_102
|
||||
| _writeAllowed_T_104 | _writeAllowed_T_106 | _writeAllowed_T_108
|
||||
| _writeAllowed_T_110 | _writeAllowed_T_112 | _writeAllowed_T_114
|
||||
| _writeAllowed_T_148 | _writeAllowed_T_149 | _writeAllowed_T_151
|
||||
| _writeAllowed_T_153 | _writeAllowed_T_125 | _writeAllowed_T_126
|
||||
| _writeAllowed_T_128 | _writeAllowed_T_130 | _writeAllowed_T_132
|
||||
| _writeAllowed_T_134 | _writeAllowed_T_136 | _writeAllowed_T_138
|
||||
| _writeAllowed_T_140 | _writeAllowed_T_142 | _writeAllowed_T_155
|
||||
| _writeAllowed_T_156 | _writeAllowed_T_158)
|
||||
& (_writeAllowed_T_75 | _writeAllowed_T_76 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | _writeAllowed_T_86 | _writeAllowed_T_88
|
||||
| _writeAllowed_T_90 | _writeAllowed_T_92 | _writeAllowed_T_94 | _writeAllowed_T_96
|
||||
| _writeAllowed_T_98 | _writeAllowed_T_100 | _writeAllowed_T_102
|
||||
| _writeAllowed_T_104 | _writeAllowed_T_106 | _writeAllowed_T_108
|
||||
| _writeAllowed_T_110 | _writeAllowed_T_112 | _writeAllowed_T_114
|
||||
| _writeAllowed_T_148 | _writeAllowed_T_149 | _writeAllowed_T_151
|
||||
| _writeAllowed_T_153
|
||||
? (&io_currentPriv)
|
||||
: ~(_writeAllowed_T_125 | _writeAllowed_T_126 | _writeAllowed_T_128
|
||||
| _writeAllowed_T_130 | _writeAllowed_T_132 | _writeAllowed_T_134
|
||||
| _writeAllowed_T_136 | _writeAllowed_T_138 | _writeAllowed_T_140
|
||||
| _writeAllowed_T_142) | (|io_currentPriv))
|
||||
& ~(_writeAllowed_T_148 | _writeAllowed_T_149 | _writeAllowed_T_151
|
||||
| _writeAllowed_T_153 | _writeAllowed_T_155 | _writeAllowed_T_156
|
||||
| _writeAllowed_T_158);
|
||||
wire _GEN_0 =
|
||||
_writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80 | _writeAllowed_T_82
|
||||
| _writeAllowed_T_84 | _writeAllowed_T_86 | _writeAllowed_T_112 | _writeAllowed_T_88
|
||||
| _writeAllowed_T_90 | _writeAllowed_T_92 | _writeAllowed_T_94 | _writeAllowed_T_96
|
||||
| _writeAllowed_T_98 | _writeAllowed_T_100 | _writeAllowed_T_104 | _writeAllowed_T_106
|
||||
| _writeAllowed_T_108 | _writeAllowed_T_110 | _writeAllowed_T_125
|
||||
| _writeAllowed_T_126 | _writeAllowed_T_128 | _writeAllowed_T_132
|
||||
| _writeAllowed_T_130 | _writeAllowed_T_134 | _writeAllowed_T_136
|
||||
| _writeAllowed_T_138 | _writeAllowed_T_140 | _writeAllowed_T_142;
|
||||
wire suppressInstretIncrement = _GEN & ~_GEN_0 & _writeAllowed_T_114;
|
||||
wire trapToS = io_trapTargetPriv == 2'h1;
|
||||
always @(posedge clock) begin
|
||||
if (reset) begin
|
||||
cycle <= 64'h0;
|
||||
instret <= 64'h0;
|
||||
mcountinhibit <= 64'h0;
|
||||
suppressInstretAfterWrite <= 1'h0;
|
||||
mstatus <= 64'h0;
|
||||
mtvecReg <= 64'h0;
|
||||
mscratch <= 64'h0;
|
||||
mepcReg <= 64'h0;
|
||||
mcause <= 64'h0;
|
||||
mtval <= 64'h0;
|
||||
@@ -46,7 +212,14 @@ module CSRFile(
|
||||
mideleg <= 64'h0;
|
||||
mie <= 64'h0;
|
||||
mip <= 64'h0;
|
||||
sstatus <= 64'h0;
|
||||
mcounteren <= 64'h0;
|
||||
pmpcfg0 <= 64'h0;
|
||||
pmpaddr0 <= 64'h0;
|
||||
tdata1 <= 64'h0;
|
||||
tdata2 <= 64'h0;
|
||||
tcontrol <= 64'h0;
|
||||
mnstatus <= 64'h0;
|
||||
scounteren <= 64'h0;
|
||||
stvec <= 64'h0;
|
||||
sepc <= 64'h0;
|
||||
scause <= 64'h0;
|
||||
@@ -55,206 +228,466 @@ module CSRFile(
|
||||
satpReg <= 64'h0;
|
||||
end
|
||||
else begin
|
||||
automatic logic _GEN;
|
||||
automatic logic _GEN_0;
|
||||
automatic logic _GEN_1;
|
||||
automatic logic _GEN_2;
|
||||
automatic logic _GEN_3;
|
||||
automatic logic _GEN_4;
|
||||
automatic logic _GEN_5;
|
||||
automatic logic _GEN_6 = io_cmd_addr == 12'h343;
|
||||
automatic logic _GEN_7 = io_cmd_addr == 12'h344;
|
||||
automatic logic _GEN_8 = io_cmd_addr == 12'h100;
|
||||
automatic logic _GEN_9 = io_cmd_addr == 12'h105;
|
||||
automatic logic _GEN_10 = io_cmd_addr == 12'h140;
|
||||
automatic logic _GEN_11 = io_cmd_addr == 12'h141;
|
||||
automatic logic _GEN_12 = io_cmd_addr == 12'h142;
|
||||
automatic logic _GEN_13 = io_cmd_addr == 12'h143;
|
||||
automatic logic _GEN_14 = io_cmd_addr == 12'h180;
|
||||
automatic logic [63:0] _GEN_15;
|
||||
automatic logic [63:0] writeOld;
|
||||
automatic logic [63:0] writeOld =
|
||||
_writeAllowed_T_75
|
||||
? mstatusView
|
||||
: _writeAllowed_T_76
|
||||
? 64'h8000000000141101
|
||||
: _writeAllowed_T_78
|
||||
? medeleg
|
||||
: _writeAllowed_T_80
|
||||
? mideleg
|
||||
: _writeAllowed_T_82
|
||||
? mie
|
||||
: _writeAllowed_T_84
|
||||
? mtvecReg
|
||||
: _writeAllowed_T_86
|
||||
? mcounteren
|
||||
: _writeAllowed_T_112
|
||||
? mcountinhibit
|
||||
: _writeAllowed_T_88
|
||||
? mscratch
|
||||
: _writeAllowed_T_90
|
||||
? mepcReg
|
||||
: _writeAllowed_T_92
|
||||
? mcause
|
||||
: _writeAllowed_T_94
|
||||
? mtval
|
||||
: _writeAllowed_T_96
|
||||
? mip
|
||||
: _writeAllowed_T_98
|
||||
? pmpcfg0
|
||||
: _writeAllowed_T_100
|
||||
? pmpaddr0
|
||||
: _writeAllowed_T_102
|
||||
? 64'h1
|
||||
: _writeAllowed_T_104
|
||||
? tdata1
|
||||
: _writeAllowed_T_106
|
||||
? tdata2
|
||||
: _writeAllowed_T_108
|
||||
? tcontrol
|
||||
: _writeAllowed_T_110
|
||||
? mnstatus
|
||||
: _writeAllowed_T_125
|
||||
? sstatusView
|
||||
: _writeAllowed_T_126
|
||||
? mie
|
||||
& mideleg
|
||||
: _writeAllowed_T_128
|
||||
? stvec
|
||||
: _writeAllowed_T_132
|
||||
? scounteren
|
||||
: _writeAllowed_T_130
|
||||
? sscratch
|
||||
: _writeAllowed_T_134
|
||||
? sepc
|
||||
: _writeAllowed_T_136
|
||||
? scause
|
||||
: _writeAllowed_T_138
|
||||
? stval
|
||||
: _writeAllowed_T_140
|
||||
? mip
|
||||
& mideleg
|
||||
: _writeAllowed_T_142
|
||||
? satpReg
|
||||
: _writeAllowed_T_148
|
||||
| _writeAllowed_T_149
|
||||
| _writeAllowed_T_151
|
||||
| _writeAllowed_T_153
|
||||
? 64'h0
|
||||
: _writeAllowed_T_114
|
||||
? instret
|
||||
: _writeAllowed_T_155
|
||||
| _writeAllowed_T_156
|
||||
? cycle
|
||||
: _writeAllowed_T_158
|
||||
? instret
|
||||
: 64'h0;
|
||||
automatic logic [63:0] operand;
|
||||
automatic logic [63:0] _next_T_1;
|
||||
automatic logic [63:0] _next_T_3;
|
||||
automatic logic [3:0][63:0] _GEN_16;
|
||||
automatic logic [3:0][63:0] _GEN_1;
|
||||
automatic logic [63:0] next;
|
||||
automatic logic _GEN_17;
|
||||
_GEN = io_cmd_addr == 12'h300;
|
||||
_GEN_0 = io_cmd_addr == 12'h302;
|
||||
_GEN_1 = io_cmd_addr == 12'h303;
|
||||
_GEN_2 = io_cmd_addr == 12'h304;
|
||||
_GEN_3 = io_cmd_addr == 12'h305;
|
||||
_GEN_4 = io_cmd_addr == 12'h341;
|
||||
_GEN_5 = io_cmd_addr == 12'h342;
|
||||
_GEN_15 =
|
||||
io_cmd_addr == 12'h301
|
||||
? 64'h800000000014112D
|
||||
: _GEN_0
|
||||
? medeleg
|
||||
: _GEN_1
|
||||
? mideleg
|
||||
: _GEN_2
|
||||
? mie
|
||||
: _GEN_3
|
||||
? mtvecReg
|
||||
: _GEN_4
|
||||
? mepcReg
|
||||
: _GEN_5
|
||||
? mcause
|
||||
: _GEN_6
|
||||
? mtval
|
||||
: _GEN_7
|
||||
? mip
|
||||
: _GEN_8
|
||||
? sstatus
|
||||
: _GEN_9
|
||||
? stvec
|
||||
: _GEN_10
|
||||
? sscratch
|
||||
: _GEN_11
|
||||
? sepc
|
||||
: _GEN_12
|
||||
? scause
|
||||
: _GEN_13
|
||||
? stval
|
||||
: _GEN_14
|
||||
? satpReg
|
||||
: io_cmd_addr == 12'hF14
|
||||
| io_cmd_addr != 12'hC00
|
||||
? 64'h0
|
||||
: cycle;
|
||||
writeOld = _GEN ? mstatus : _GEN_15;
|
||||
operand = io_cmd_cmd[2] ? {59'h0, io_cmd_zimm} : io_cmd_rs1;
|
||||
_next_T_1 = writeOld | operand;
|
||||
_next_T_3 = writeOld & ~operand;
|
||||
_GEN_16 = {{_next_T_3}, {_next_T_1}, {operand}, {writeOld}};
|
||||
next = _GEN_16[io_cmd_cmd[1:0]];
|
||||
_GEN_17 = io_cmd_valid & (|io_cmd_cmd);
|
||||
_GEN_1 = {{_next_T_3}, {_next_T_1}, {operand}, {writeOld}};
|
||||
next = _GEN_1[io_cmd_cmd[1:0]];
|
||||
cycle <= cycle + 64'h1;
|
||||
if (_GEN_17 & _GEN)
|
||||
mstatus <= next;
|
||||
if (~_GEN_17 | _GEN | _GEN_0 | _GEN_1 | _GEN_2 | ~_GEN_3) begin
|
||||
if (~_GEN | _GEN_0 | ~_writeAllowed_T_114) begin
|
||||
if (mcountinhibit[2] | suppressInstretIncrement | suppressInstretAfterWrite) begin
|
||||
end
|
||||
else
|
||||
instret <= instret + 64'h1;
|
||||
end
|
||||
else
|
||||
instret <= next;
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | _writeAllowed_T_86
|
||||
| ~_writeAllowed_T_112) begin
|
||||
end
|
||||
else
|
||||
mcountinhibit <= {61'h0, next[2], 2'h0};
|
||||
suppressInstretAfterWrite <=
|
||||
~suppressInstretAfterWrite
|
||||
& (suppressInstretIncrement | suppressInstretAfterWrite);
|
||||
if (io_trap) begin
|
||||
automatic logic [63:0] _GEN_2 =
|
||||
mstatus[1] ? mstatus | 64'h20 : mstatus & 64'hFFFFFFFFFFFFFFDF;
|
||||
mstatus <=
|
||||
trapToS
|
||||
? (io_currentPriv == 2'h1
|
||||
? _GEN_2 & 64'hFFFFFFFFFFFFFFFD | 64'h100
|
||||
: _GEN_2 & 64'hFFFFFFFFFFFFFEFD)
|
||||
: (mstatus[3] ? mstatus | 64'h80 : mstatus & 64'hFFFFFFFFFFFFFF7F)
|
||||
& 64'hFFFFFFFFFFFFE7F7 | {51'h0, io_currentPriv, 11'h0};
|
||||
end
|
||||
else if (io_xret)
|
||||
mstatus <=
|
||||
io_xretIsMret
|
||||
? ((mstatus[7] ? mstatus | 64'h8 : mstatus & 64'hFFFFFFFFFFFFFFF7) | 64'h80)
|
||||
& 64'hFFFFFFFFFFFFE7FF
|
||||
: ((mstatus[5] ? mstatus | 64'h2 : mstatus & 64'hFFFFFFFFFFFFFFFD) | 64'h20)
|
||||
& 64'hFFFFFFFFFFFFFEFF;
|
||||
else if (_GEN) begin
|
||||
if (_writeAllowed_T_75) begin
|
||||
automatic logic [3:0][63:0] _GEN_3;
|
||||
_GEN_3 = {{_next_T_3}, {_next_T_1}, {operand}, {mstatusView}};
|
||||
mstatus <= _GEN_3[io_cmd_cmd[1:0]];
|
||||
end
|
||||
else if (_writeAllowed_T_78 | _writeAllowed_T_80 | _writeAllowed_T_82
|
||||
| _writeAllowed_T_84 | _writeAllowed_T_86 | _writeAllowed_T_112
|
||||
| _writeAllowed_T_88 | _writeAllowed_T_90 | _writeAllowed_T_92
|
||||
| _writeAllowed_T_94 | _writeAllowed_T_96 | _writeAllowed_T_98
|
||||
| _writeAllowed_T_100 | _writeAllowed_T_104 | _writeAllowed_T_106
|
||||
| _writeAllowed_T_108 | _writeAllowed_T_110 | ~_writeAllowed_T_125) begin
|
||||
end
|
||||
else
|
||||
mstatus <=
|
||||
mstatus & 64'hFFFFFFFDFFF21E9D | {30'h0, next[33:1] & 33'h10006F0B1, 1'h0};
|
||||
end
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | ~_writeAllowed_T_84) begin
|
||||
end
|
||||
else
|
||||
mtvecReg <= next;
|
||||
if (io_trap) begin
|
||||
mepcReg <= io_trapPc;
|
||||
mcause <= io_trapCause;
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | _writeAllowed_T_86
|
||||
| _writeAllowed_T_112 | ~_writeAllowed_T_88) begin
|
||||
end
|
||||
else begin
|
||||
if (~_GEN_17 | _GEN | _GEN_0 | _GEN_1 | _GEN_2 | _GEN_3 | ~_GEN_4) begin
|
||||
else
|
||||
mscratch <= next;
|
||||
if (~io_trap | trapToS) begin
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | _writeAllowed_T_86
|
||||
| _writeAllowed_T_112 | _writeAllowed_T_88 | ~_writeAllowed_T_90) begin
|
||||
end
|
||||
else
|
||||
mepcReg <= next;
|
||||
if (~_GEN_17 | _GEN | _GEN_0 | _GEN_1 | _GEN_2 | _GEN_3 | _GEN_4 | ~_GEN_5) begin
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | _writeAllowed_T_86
|
||||
| _writeAllowed_T_112 | _writeAllowed_T_88 | _writeAllowed_T_90
|
||||
| ~_writeAllowed_T_92) begin
|
||||
end
|
||||
else
|
||||
mcause <= next;
|
||||
end
|
||||
if (~_GEN_17 | _GEN | _GEN_0 | _GEN_1 | _GEN_2 | _GEN_3 | _GEN_4 | _GEN_5
|
||||
| ~_GEN_6) begin
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | _writeAllowed_T_86
|
||||
| _writeAllowed_T_112 | _writeAllowed_T_88 | _writeAllowed_T_90
|
||||
| _writeAllowed_T_92 | ~_writeAllowed_T_94) begin
|
||||
end
|
||||
else
|
||||
mtval <= next;
|
||||
if (~_GEN_17 | _GEN | ~_GEN_0) begin
|
||||
end
|
||||
else begin
|
||||
automatic logic [3:0][63:0] _GEN_18;
|
||||
_GEN_18 = {{_next_T_3}, {_next_T_1}, {operand}, {_GEN_15}};
|
||||
medeleg <= _GEN_18[io_cmd_cmd[1:0]];
|
||||
mepcReg <= io_trapPc;
|
||||
mcause <= io_trapCause;
|
||||
mtval <= io_trapTval;
|
||||
end
|
||||
if (~_GEN_17 | _GEN | _GEN_0 | ~_GEN_1) begin
|
||||
if (~_GEN | _writeAllowed_T_75 | ~_writeAllowed_T_78) begin
|
||||
end
|
||||
else
|
||||
mideleg <= next;
|
||||
if (~_GEN_17 | _GEN | _GEN_0 | _GEN_1 | ~_GEN_2) begin
|
||||
else begin
|
||||
automatic logic [3:0][63:0] _GEN_4;
|
||||
_GEN_4 =
|
||||
{{_next_T_3},
|
||||
{_next_T_1},
|
||||
{operand},
|
||||
{_writeAllowed_T_76 ? 64'h8000000000141101 : medeleg}};
|
||||
medeleg <= _GEN_4[io_cmd_cmd[1:0]];
|
||||
end
|
||||
else
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | ~_writeAllowed_T_80) begin
|
||||
end
|
||||
else begin
|
||||
automatic logic [3:0][63:0] _GEN_5;
|
||||
_GEN_5 =
|
||||
{{_next_T_3},
|
||||
{_next_T_1},
|
||||
{operand},
|
||||
{_writeAllowed_T_75
|
||||
? mstatusView
|
||||
: _writeAllowed_T_76
|
||||
? 64'h8000000000141101
|
||||
: _writeAllowed_T_78 ? medeleg : mideleg}};
|
||||
mideleg <= _GEN_5[io_cmd_cmd[1:0]];
|
||||
end
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80) begin
|
||||
end
|
||||
else if (_writeAllowed_T_82)
|
||||
mie <= next;
|
||||
if (~_GEN_17 | _GEN | _GEN_0 | _GEN_1 | _GEN_2 | _GEN_3 | _GEN_4 | _GEN_5 | _GEN_6
|
||||
| ~_GEN_7) begin
|
||||
else if (_writeAllowed_T_84 | _writeAllowed_T_86 | _writeAllowed_T_112
|
||||
| _writeAllowed_T_88 | _writeAllowed_T_90 | _writeAllowed_T_92
|
||||
| _writeAllowed_T_94 | _writeAllowed_T_96 | _writeAllowed_T_98
|
||||
| _writeAllowed_T_100 | _writeAllowed_T_104 | _writeAllowed_T_106
|
||||
| _writeAllowed_T_108 | _writeAllowed_T_110 | _writeAllowed_T_125
|
||||
| ~_writeAllowed_T_126) begin
|
||||
end
|
||||
else
|
||||
mie <= mie & ~mideleg | next & mideleg;
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | _writeAllowed_T_86
|
||||
| _writeAllowed_T_112 | _writeAllowed_T_88 | _writeAllowed_T_90
|
||||
| _writeAllowed_T_92 | _writeAllowed_T_94) begin
|
||||
end
|
||||
else if (_writeAllowed_T_96)
|
||||
mip <= next;
|
||||
if (~_GEN_17 | _GEN | _GEN_0 | _GEN_1 | _GEN_2 | _GEN_3 | _GEN_4 | _GEN_5 | _GEN_6
|
||||
| _GEN_7 | ~_GEN_8) begin
|
||||
else if (_writeAllowed_T_98 | _writeAllowed_T_100 | _writeAllowed_T_104
|
||||
| _writeAllowed_T_106 | _writeAllowed_T_108 | _writeAllowed_T_110
|
||||
| _writeAllowed_T_125 | _writeAllowed_T_126 | _writeAllowed_T_128
|
||||
| _writeAllowed_T_132 | _writeAllowed_T_130 | _writeAllowed_T_134
|
||||
| _writeAllowed_T_136 | _writeAllowed_T_138 | ~_writeAllowed_T_140) begin
|
||||
end
|
||||
else
|
||||
sstatus <= next;
|
||||
if (~_GEN_17 | _GEN | _GEN_0 | _GEN_1 | _GEN_2 | _GEN_3 | _GEN_4 | _GEN_5 | _GEN_6
|
||||
| _GEN_7 | _GEN_8 | ~_GEN_9) begin
|
||||
mip <= mip & ~mideleg | next & mideleg;
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | ~_writeAllowed_T_86) begin
|
||||
end
|
||||
else
|
||||
mcounteren <= next;
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | _writeAllowed_T_86
|
||||
| _writeAllowed_T_112 | _writeAllowed_T_88 | _writeAllowed_T_90
|
||||
| _writeAllowed_T_92 | _writeAllowed_T_94 | _writeAllowed_T_96
|
||||
| ~_writeAllowed_T_98) begin
|
||||
end
|
||||
else
|
||||
pmpcfg0 <= next;
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | _writeAllowed_T_86
|
||||
| _writeAllowed_T_112 | _writeAllowed_T_88 | _writeAllowed_T_90
|
||||
| _writeAllowed_T_92 | _writeAllowed_T_94 | _writeAllowed_T_96
|
||||
| _writeAllowed_T_98 | ~_writeAllowed_T_100) begin
|
||||
end
|
||||
else
|
||||
pmpaddr0 <= next;
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | _writeAllowed_T_86
|
||||
| _writeAllowed_T_112 | _writeAllowed_T_88 | _writeAllowed_T_90
|
||||
| _writeAllowed_T_92 | _writeAllowed_T_94 | _writeAllowed_T_96
|
||||
| _writeAllowed_T_98 | _writeAllowed_T_100 | ~_writeAllowed_T_104) begin
|
||||
end
|
||||
else
|
||||
tdata1 <= next;
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | _writeAllowed_T_86
|
||||
| _writeAllowed_T_112 | _writeAllowed_T_88 | _writeAllowed_T_90
|
||||
| _writeAllowed_T_92 | _writeAllowed_T_94 | _writeAllowed_T_96
|
||||
| _writeAllowed_T_98 | _writeAllowed_T_100 | _writeAllowed_T_104
|
||||
| ~_writeAllowed_T_106) begin
|
||||
end
|
||||
else
|
||||
tdata2 <= next;
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | _writeAllowed_T_86
|
||||
| _writeAllowed_T_112 | _writeAllowed_T_88 | _writeAllowed_T_90
|
||||
| _writeAllowed_T_92 | _writeAllowed_T_94 | _writeAllowed_T_96
|
||||
| _writeAllowed_T_98 | _writeAllowed_T_100 | _writeAllowed_T_104
|
||||
| _writeAllowed_T_106 | ~_writeAllowed_T_108) begin
|
||||
end
|
||||
else
|
||||
tcontrol <= next;
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | _writeAllowed_T_86
|
||||
| _writeAllowed_T_112 | _writeAllowed_T_88 | _writeAllowed_T_90
|
||||
| _writeAllowed_T_92 | _writeAllowed_T_94 | _writeAllowed_T_96
|
||||
| _writeAllowed_T_98 | _writeAllowed_T_100 | _writeAllowed_T_104
|
||||
| _writeAllowed_T_106 | _writeAllowed_T_108 | ~_writeAllowed_T_110) begin
|
||||
end
|
||||
else
|
||||
mnstatus <= next;
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | _writeAllowed_T_86
|
||||
| _writeAllowed_T_112 | _writeAllowed_T_88 | _writeAllowed_T_90
|
||||
| _writeAllowed_T_92 | _writeAllowed_T_94 | _writeAllowed_T_96
|
||||
| _writeAllowed_T_98 | _writeAllowed_T_100 | _writeAllowed_T_104
|
||||
| _writeAllowed_T_106 | _writeAllowed_T_108 | _writeAllowed_T_110
|
||||
| _writeAllowed_T_125 | _writeAllowed_T_126 | _writeAllowed_T_128
|
||||
| ~_writeAllowed_T_132) begin
|
||||
end
|
||||
else
|
||||
scounteren <= next;
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | _writeAllowed_T_86
|
||||
| _writeAllowed_T_112 | _writeAllowed_T_88 | _writeAllowed_T_90
|
||||
| _writeAllowed_T_92 | _writeAllowed_T_94 | _writeAllowed_T_96
|
||||
| _writeAllowed_T_98 | _writeAllowed_T_100 | _writeAllowed_T_104
|
||||
| _writeAllowed_T_106 | _writeAllowed_T_108 | _writeAllowed_T_110
|
||||
| _writeAllowed_T_125 | _writeAllowed_T_126 | ~_writeAllowed_T_128) begin
|
||||
end
|
||||
else
|
||||
stvec <= next;
|
||||
if (~_GEN_17 | _GEN | _GEN_0 | _GEN_1 | _GEN_2 | _GEN_3 | _GEN_4 | _GEN_5 | _GEN_6
|
||||
| _GEN_7 | _GEN_8 | _GEN_9 | _GEN_10 | ~_GEN_11) begin
|
||||
if (io_trap & trapToS) begin
|
||||
sepc <= io_trapPc;
|
||||
scause <= io_trapCause;
|
||||
stval <= io_trapTval;
|
||||
end
|
||||
else begin
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | _writeAllowed_T_86
|
||||
| _writeAllowed_T_112 | _writeAllowed_T_88 | _writeAllowed_T_90
|
||||
| _writeAllowed_T_92 | _writeAllowed_T_94 | _writeAllowed_T_96
|
||||
| _writeAllowed_T_98 | _writeAllowed_T_100 | _writeAllowed_T_104
|
||||
| _writeAllowed_T_106 | _writeAllowed_T_108 | _writeAllowed_T_110
|
||||
| _writeAllowed_T_125 | _writeAllowed_T_126 | _writeAllowed_T_128
|
||||
| _writeAllowed_T_132 | _writeAllowed_T_130 | ~_writeAllowed_T_134) begin
|
||||
end
|
||||
else
|
||||
sepc <= next;
|
||||
if (~_GEN_17 | _GEN | _GEN_0 | _GEN_1 | _GEN_2 | _GEN_3 | _GEN_4 | _GEN_5 | _GEN_6
|
||||
| _GEN_7 | _GEN_8 | _GEN_9 | _GEN_10 | _GEN_11 | ~_GEN_12) begin
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | _writeAllowed_T_86
|
||||
| _writeAllowed_T_112 | _writeAllowed_T_88 | _writeAllowed_T_90
|
||||
| _writeAllowed_T_92 | _writeAllowed_T_94 | _writeAllowed_T_96
|
||||
| _writeAllowed_T_98 | _writeAllowed_T_100 | _writeAllowed_T_104
|
||||
| _writeAllowed_T_106 | _writeAllowed_T_108 | _writeAllowed_T_110
|
||||
| _writeAllowed_T_125 | _writeAllowed_T_126 | _writeAllowed_T_128
|
||||
| _writeAllowed_T_132 | _writeAllowed_T_130 | _writeAllowed_T_134
|
||||
| ~_writeAllowed_T_136) begin
|
||||
end
|
||||
else
|
||||
scause <= next;
|
||||
if (~_GEN_17 | _GEN | _GEN_0 | _GEN_1 | _GEN_2 | _GEN_3 | _GEN_4 | _GEN_5 | _GEN_6
|
||||
| _GEN_7 | _GEN_8 | _GEN_9 | _GEN_10 | _GEN_11 | _GEN_12 | ~_GEN_13) begin
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | _writeAllowed_T_86
|
||||
| _writeAllowed_T_112 | _writeAllowed_T_88 | _writeAllowed_T_90
|
||||
| _writeAllowed_T_92 | _writeAllowed_T_94 | _writeAllowed_T_96
|
||||
| _writeAllowed_T_98 | _writeAllowed_T_100 | _writeAllowed_T_104
|
||||
| _writeAllowed_T_106 | _writeAllowed_T_108 | _writeAllowed_T_110
|
||||
| _writeAllowed_T_125 | _writeAllowed_T_126 | _writeAllowed_T_128
|
||||
| _writeAllowed_T_132 | _writeAllowed_T_130 | _writeAllowed_T_134
|
||||
| _writeAllowed_T_136 | ~_writeAllowed_T_138) begin
|
||||
end
|
||||
else
|
||||
stval <= next;
|
||||
if (~_GEN_17 | _GEN | _GEN_0 | _GEN_1 | _GEN_2 | _GEN_3 | _GEN_4 | _GEN_5 | _GEN_6
|
||||
| _GEN_7 | _GEN_8 | _GEN_9 | ~_GEN_10) begin
|
||||
end
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | _writeAllowed_T_86
|
||||
| _writeAllowed_T_112 | _writeAllowed_T_88 | _writeAllowed_T_90
|
||||
| _writeAllowed_T_92 | _writeAllowed_T_94 | _writeAllowed_T_96
|
||||
| _writeAllowed_T_98 | _writeAllowed_T_100 | _writeAllowed_T_104
|
||||
| _writeAllowed_T_106 | _writeAllowed_T_108 | _writeAllowed_T_110
|
||||
| _writeAllowed_T_125 | _writeAllowed_T_126 | _writeAllowed_T_128
|
||||
| _writeAllowed_T_132 | ~_writeAllowed_T_130) begin
|
||||
end
|
||||
else
|
||||
sscratch <= next;
|
||||
if (~_GEN_17 | _GEN | _GEN_0 | _GEN_1 | _GEN_2 | _GEN_3 | _GEN_4 | _GEN_5 | _GEN_6
|
||||
| _GEN_7 | _GEN_8 | _GEN_9 | _GEN_10 | _GEN_11 | _GEN_12 | _GEN_13
|
||||
| ~_GEN_14) begin
|
||||
if (~_GEN | _writeAllowed_T_75 | _writeAllowed_T_78 | _writeAllowed_T_80
|
||||
| _writeAllowed_T_82 | _writeAllowed_T_84 | _writeAllowed_T_86
|
||||
| _writeAllowed_T_112 | _writeAllowed_T_88 | _writeAllowed_T_90
|
||||
| _writeAllowed_T_92 | _writeAllowed_T_94 | _writeAllowed_T_96
|
||||
| _writeAllowed_T_98 | _writeAllowed_T_100 | _writeAllowed_T_104
|
||||
| _writeAllowed_T_106 | _writeAllowed_T_108 | _writeAllowed_T_110
|
||||
| _writeAllowed_T_125 | _writeAllowed_T_126 | _writeAllowed_T_128
|
||||
| _writeAllowed_T_132 | _writeAllowed_T_130 | _writeAllowed_T_134
|
||||
| _writeAllowed_T_136 | _writeAllowed_T_138 | _writeAllowed_T_140
|
||||
| ~_writeAllowed_T_142) begin
|
||||
end
|
||||
else
|
||||
satpReg <= next;
|
||||
end
|
||||
end // always @(posedge)
|
||||
assign io_rdata =
|
||||
io_readAddr == 12'h300
|
||||
? mstatus
|
||||
: io_readAddr == 12'h301
|
||||
? 64'h800000000014112D
|
||||
: io_readAddr == 12'h302
|
||||
readAllowed
|
||||
? (_readAllowed_T_75
|
||||
? mstatusView
|
||||
: _readAllowed_T_76
|
||||
? 64'h8000000000141101
|
||||
: _readAllowed_T_78
|
||||
? medeleg
|
||||
: io_readAddr == 12'h303
|
||||
: _readAllowed_T_80
|
||||
? mideleg
|
||||
: io_readAddr == 12'h304
|
||||
: _readAllowed_T_82
|
||||
? mie
|
||||
: io_readAddr == 12'h305
|
||||
: _readAllowed_T_84
|
||||
? mtvecReg
|
||||
: io_readAddr == 12'h341
|
||||
: _readAllowed_T_86
|
||||
? mcounteren
|
||||
: _readAllowed_T_112
|
||||
? mcountinhibit
|
||||
: _readAllowed_T_88
|
||||
? mscratch
|
||||
: _readAllowed_T_90
|
||||
? mepcReg
|
||||
: io_readAddr == 12'h342
|
||||
: _readAllowed_T_92
|
||||
? mcause
|
||||
: io_readAddr == 12'h343
|
||||
: _readAllowed_T_94
|
||||
? mtval
|
||||
: io_readAddr == 12'h344
|
||||
: _readAllowed_T_96
|
||||
? mip
|
||||
: io_readAddr == 12'h100
|
||||
? sstatus
|
||||
: io_readAddr == 12'h105
|
||||
: _readAllowed_T_98
|
||||
? pmpcfg0
|
||||
: _readAllowed_T_100
|
||||
? pmpaddr0
|
||||
: _readAllowed_T_102
|
||||
? 64'h1
|
||||
: _readAllowed_T_104
|
||||
? tdata1
|
||||
: _readAllowed_T_106
|
||||
? tdata2
|
||||
: _readAllowed_T_108
|
||||
? tcontrol
|
||||
: _readAllowed_T_110
|
||||
? mnstatus
|
||||
: _readAllowed_T_125
|
||||
? sstatusView
|
||||
: _readAllowed_T_126
|
||||
? mie
|
||||
& mideleg
|
||||
: _readAllowed_T_128
|
||||
? stvec
|
||||
: io_readAddr == 12'h140
|
||||
: _readAllowed_T_132
|
||||
? scounteren
|
||||
: _readAllowed_T_130
|
||||
? sscratch
|
||||
: io_readAddr == 12'h141
|
||||
: _readAllowed_T_134
|
||||
? sepc
|
||||
: io_readAddr == 12'h142
|
||||
: _readAllowed_T_136
|
||||
? scause
|
||||
: io_readAddr == 12'h143
|
||||
: _readAllowed_T_138
|
||||
? stval
|
||||
: io_readAddr == 12'h180
|
||||
: _readAllowed_T_140
|
||||
? mip
|
||||
& mideleg
|
||||
: _readAllowed_T_142
|
||||
? satpReg
|
||||
: io_readAddr == 12'hF14
|
||||
| io_readAddr != 12'hC00
|
||||
: _readAllowed_T_116
|
||||
| _readAllowed_T_118
|
||||
| _readAllowed_T_120
|
||||
| _readAllowed_T_122
|
||||
? 64'h0
|
||||
: cycle;
|
||||
: _readAllowed_T_114
|
||||
? instret
|
||||
: _readAllowed_T_69
|
||||
| _readAllowed_T_70
|
||||
? cycle
|
||||
: _readAllowed_T_72
|
||||
? instret
|
||||
: 64'h0)
|
||||
: 64'h0;
|
||||
assign io_readIllegal = ~readAllowed;
|
||||
assign io_trapVector = trapToS ? stvec : mtvecReg;
|
||||
assign io_satp = satpReg;
|
||||
assign io_mtvec = mtvecReg;
|
||||
assign io_mepc = mepcReg;
|
||||
assign io_sepc = sepc;
|
||||
assign io_medeleg = medeleg;
|
||||
assign io_mstatus = mstatus;
|
||||
endmodule
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
module CommitStage(
|
||||
input io_robValid_0,
|
||||
io_robValid_1,
|
||||
input [63:0] io_robEntry_0_pc,
|
||||
input [4:0] io_robEntry_0_archDest,
|
||||
input io_robEntry_0_writesDest,
|
||||
input [3:0] io_robEntry_0_opClass,
|
||||
@@ -14,6 +15,10 @@ module CommitStage(
|
||||
input [63:0] io_robEntry_0_redirectPc,
|
||||
input io_robEntry_0_csrValid,
|
||||
io_robEntry_0_fenceI,
|
||||
io_robEntry_0_sfenceVma,
|
||||
io_robEntry_0_xret,
|
||||
io_robEntry_0_xretIsMret,
|
||||
input [63:0] io_robEntry_1_pc,
|
||||
input [4:0] io_robEntry_1_archDest,
|
||||
input io_robEntry_1_writesDest,
|
||||
input [5:0] io_robEntry_1_dest,
|
||||
@@ -25,6 +30,9 @@ module CommitStage(
|
||||
input [63:0] io_robEntry_1_redirectPc,
|
||||
input io_robEntry_1_csrValid,
|
||||
io_robEntry_1_fenceI,
|
||||
io_robEntry_1_sfenceVma,
|
||||
io_robEntry_1_xret,
|
||||
io_robEntry_1_xretIsMret,
|
||||
output io_commitReady_0,
|
||||
io_commitReady_1,
|
||||
io_freeOldPhys_0,
|
||||
@@ -42,38 +50,53 @@ module CommitStage(
|
||||
output io_exception,
|
||||
output [63:0] io_exceptionCause,
|
||||
io_badAddr,
|
||||
output io_fenceI
|
||||
io_trapPc,
|
||||
output io_fenceI,
|
||||
io_sfenceVma,
|
||||
io_xret,
|
||||
io_xretIsMret,
|
||||
io_setPriv
|
||||
);
|
||||
|
||||
wire firstTrap =
|
||||
io_robValid_0 & (io_robEntry_0_exception | io_robEntry_0_branchMispredict);
|
||||
io_robValid_0
|
||||
& (io_robEntry_0_exception | io_robEntry_0_branchMispredict | io_robEntry_0_xret
|
||||
| io_robEntry_0_sfenceVma | io_robEntry_0_fenceI);
|
||||
wire secondTrap =
|
||||
io_robValid_1 & (io_robEntry_1_exception | io_robEntry_1_branchMispredict);
|
||||
io_robValid_1
|
||||
& (io_robEntry_1_exception | io_robEntry_1_branchMispredict | io_robEntry_1_xret
|
||||
| io_robEntry_1_sfenceVma | io_robEntry_1_fenceI);
|
||||
wire io_commitReady_1_0 =
|
||||
io_robValid_1 & ~firstTrap & ~secondTrap
|
||||
& ~(io_robValid_0 & io_robValid_1 & io_robEntry_0_csrValid & io_robEntry_1_csrValid)
|
||||
& ~(io_robValid_0 & io_robEntry_0_opClass == 4'h4);
|
||||
wire _io_commitMapValid_0_T = io_robValid_0 & io_robEntry_0_writesDest;
|
||||
wire _io_commitMapValid_1_T = io_commitReady_1_0 & io_robEntry_1_writesDest;
|
||||
wire commitWritesDest =
|
||||
io_robValid_0 & ~io_robEntry_0_exception & io_robEntry_0_writesDest;
|
||||
wire commitWritesDest_1 =
|
||||
io_commitReady_1_0 & ~io_robEntry_1_exception & io_robEntry_1_writesDest;
|
||||
wire secondTrapSelected = ~io_robValid_0 & secondTrap;
|
||||
wire selectedTrap = firstTrap | secondTrapSelected;
|
||||
wire io_exception_0 =
|
||||
firstTrap ? io_robEntry_0_exception : secondTrapSelected & io_robEntry_1_exception;
|
||||
wire io_xret_0 =
|
||||
io_robValid_0 & io_robEntry_0_xret | io_commitReady_1_0 & io_robEntry_1_xret;
|
||||
assign io_commitReady_0 = io_robValid_0;
|
||||
assign io_commitReady_1 = io_commitReady_1_0;
|
||||
assign io_freeOldPhys_0 =
|
||||
_io_commitMapValid_0_T & io_robEntry_0_oldDest != io_robEntry_0_dest;
|
||||
commitWritesDest & io_robEntry_0_oldDest != io_robEntry_0_dest;
|
||||
assign io_freeOldPhys_1 =
|
||||
_io_commitMapValid_1_T & io_robEntry_1_oldDest != io_robEntry_1_dest;
|
||||
commitWritesDest_1 & io_robEntry_1_oldDest != io_robEntry_1_dest;
|
||||
assign io_oldPhys_0 = io_robEntry_0_oldDest;
|
||||
assign io_oldPhys_1 = io_robEntry_1_oldDest;
|
||||
assign io_commitMapValid_0 = _io_commitMapValid_0_T & (|io_robEntry_0_archDest);
|
||||
assign io_commitMapValid_1 = _io_commitMapValid_1_T & (|io_robEntry_1_archDest);
|
||||
assign io_commitMapValid_0 = commitWritesDest & (|io_robEntry_0_archDest);
|
||||
assign io_commitMapValid_1 = commitWritesDest_1 & (|io_robEntry_1_archDest);
|
||||
assign io_commitArch_0 = io_robEntry_0_archDest;
|
||||
assign io_commitArch_1 = io_robEntry_1_archDest;
|
||||
assign io_commitPhys_0 = io_robEntry_0_dest;
|
||||
assign io_commitPhys_1 = io_robEntry_1_dest;
|
||||
assign io_flush = firstTrap | secondTrapSelected;
|
||||
assign io_flush = selectedTrap;
|
||||
assign io_redirectPc = firstTrap ? io_robEntry_0_redirectPc : io_robEntry_1_redirectPc;
|
||||
assign io_exception =
|
||||
firstTrap ? io_robEntry_0_exception : secondTrapSelected & io_robEntry_1_exception;
|
||||
assign io_exception = io_exception_0;
|
||||
assign io_exceptionCause =
|
||||
firstTrap
|
||||
? io_robEntry_0_exceptionCause
|
||||
@@ -82,7 +105,16 @@ module CommitStage(
|
||||
firstTrap
|
||||
? io_robEntry_0_badAddr
|
||||
: secondTrapSelected ? io_robEntry_1_badAddr : 64'h0;
|
||||
assign io_trapPc =
|
||||
firstTrap ? io_robEntry_0_pc : secondTrapSelected ? io_robEntry_1_pc : 64'h0;
|
||||
assign io_fenceI =
|
||||
io_robValid_0 & io_robEntry_0_fenceI | io_commitReady_1_0 & io_robEntry_1_fenceI;
|
||||
assign io_sfenceVma =
|
||||
io_robValid_0 & io_robEntry_0_sfenceVma | io_commitReady_1_0
|
||||
& io_robEntry_1_sfenceVma;
|
||||
assign io_xret = io_xret_0;
|
||||
assign io_xretIsMret =
|
||||
firstTrap ? io_robEntry_0_xretIsMret : ~secondTrapSelected | io_robEntry_1_xretIsMret;
|
||||
assign io_setPriv = selectedTrap & (io_exception_0 | io_xret_0);
|
||||
endmodule
|
||||
|
||||
|
||||
@@ -16,10 +16,20 @@ module Core(
|
||||
input [63:0] io_dmem_resp_bits
|
||||
);
|
||||
|
||||
wire [1:0] _privCtrl_io_priv;
|
||||
wire _backend_io_decodeReady;
|
||||
wire _backend_io_flush;
|
||||
wire [63:0] _backend_io_redirectPc;
|
||||
wire _backend_io_invalidateICache;
|
||||
wire _backend_io_sfenceVma;
|
||||
wire _backend_io_setPriv;
|
||||
wire [1:0] _backend_io_targetPriv;
|
||||
wire _backend_io_dmemReqValid;
|
||||
wire [63:0] _backend_io_dmemReq_addr;
|
||||
wire [63:0] _backend_io_dmemReq_data;
|
||||
wire _backend_io_dmemReq_isStore;
|
||||
wire [2:0] _backend_io_dmemReq_size;
|
||||
wire [63:0] _backend_io_satpOut;
|
||||
wire _id_io_outValid_0;
|
||||
wire _id_io_outValid_1;
|
||||
wire [63:0] _id_io_out_0_pc;
|
||||
@@ -48,10 +58,20 @@ module Core(
|
||||
wire _id_io_out_0_isWord;
|
||||
wire _id_io_out_0_isSystem;
|
||||
wire _id_io_out_0_isFenceI;
|
||||
wire _id_io_out_0_isEcall;
|
||||
wire _id_io_out_0_isEbreak;
|
||||
wire _id_io_out_0_isMret;
|
||||
wire _id_io_out_0_isSret;
|
||||
wire _id_io_out_0_isSfenceVma;
|
||||
wire _id_io_out_0_isXret;
|
||||
wire _id_io_out_0_isWfi;
|
||||
wire _id_io_out_0_isAmo;
|
||||
wire [4:0] _id_io_out_0_amoOp;
|
||||
wire _id_io_out_0_writesRd;
|
||||
wire _id_io_out_0_illegal;
|
||||
wire _id_io_out_0_fetchException;
|
||||
wire [63:0] _id_io_out_0_fetchExceptionCause;
|
||||
wire [63:0] _id_io_out_0_fetchExceptionTval;
|
||||
wire [63:0] _id_io_out_1_pc;
|
||||
wire [31:0] _id_io_out_1_inst;
|
||||
wire [4:0] _id_io_out_1_rs1;
|
||||
@@ -78,29 +98,70 @@ module Core(
|
||||
wire _id_io_out_1_isWord;
|
||||
wire _id_io_out_1_isSystem;
|
||||
wire _id_io_out_1_isFenceI;
|
||||
wire _id_io_out_1_isEcall;
|
||||
wire _id_io_out_1_isEbreak;
|
||||
wire _id_io_out_1_isMret;
|
||||
wire _id_io_out_1_isSret;
|
||||
wire _id_io_out_1_isSfenceVma;
|
||||
wire _id_io_out_1_isXret;
|
||||
wire _id_io_out_1_isWfi;
|
||||
wire _id_io_out_1_isAmo;
|
||||
wire [4:0] _id_io_out_1_amoOp;
|
||||
wire _id_io_out_1_writesRd;
|
||||
wire _id_io_out_1_illegal;
|
||||
wire _id_io_out_1_fetchException;
|
||||
wire [63:0] _id_io_out_1_fetchExceptionCause;
|
||||
wire [63:0] _id_io_out_1_fetchExceptionTval;
|
||||
wire _frontend_io_ptwMemReqValid;
|
||||
wire [63:0] _frontend_io_ptwMemReqAddr;
|
||||
wire _frontend_io_outValid;
|
||||
wire [63:0] _frontend_io_out_pc;
|
||||
wire [31:0] _frontend_io_out_inst_0;
|
||||
wire [31:0] _frontend_io_out_inst_1;
|
||||
wire _frontend_io_out_laneValid_0;
|
||||
wire _frontend_io_out_laneValid_1;
|
||||
wire _frontend_io_out_exception;
|
||||
wire [63:0] _frontend_io_out_exceptionCause;
|
||||
wire [63:0] _frontend_io_out_exceptionTval;
|
||||
reg fetchValid;
|
||||
reg [63:0] fetchReg_pc;
|
||||
reg [31:0] fetchReg_inst_0;
|
||||
reg [31:0] fetchReg_inst_1;
|
||||
reg fetchReg_laneValid_0;
|
||||
reg fetchReg_laneValid_1;
|
||||
reg fetchReg_exception;
|
||||
reg [63:0] fetchReg_exceptionCause;
|
||||
reg [63:0] fetchReg_exceptionTval;
|
||||
wire fetchReady = ~fetchValid | _backend_io_decodeReady;
|
||||
reg frontendPtwOutstanding;
|
||||
reg backendReadOutstanding;
|
||||
wire frontendPtwCanIssue =
|
||||
_frontend_io_ptwMemReqValid & ~frontendPtwOutstanding & ~backendReadOutstanding
|
||||
& ~_backend_io_dmemReqValid;
|
||||
wire _io_dmem_req_bits_isStore_T =
|
||||
_backend_io_dmemReqValid & ~frontendPtwOutstanding;
|
||||
wire frontendPtwRespValid =
|
||||
io_dmem_resp_valid & (frontendPtwOutstanding | frontendPtwCanIssue);
|
||||
wire backendRespValid =
|
||||
io_dmem_resp_valid & ~frontendPtwOutstanding & ~frontendPtwCanIssue;
|
||||
always @(posedge clock) begin
|
||||
if (reset)
|
||||
if (reset) begin
|
||||
fetchValid <= 1'h0;
|
||||
else
|
||||
frontendPtwOutstanding <= 1'h0;
|
||||
backendReadOutstanding <= 1'h0;
|
||||
end
|
||||
else begin
|
||||
automatic logic backendReadIssue =
|
||||
_io_dmem_req_bits_isStore_T & ~_backend_io_dmemReq_isStore
|
||||
& ~backendReadOutstanding;
|
||||
fetchValid <=
|
||||
~_backend_io_flush & (fetchReady ? _frontend_io_outValid : fetchValid);
|
||||
frontendPtwOutstanding <=
|
||||
~frontendPtwRespValid & (frontendPtwCanIssue | frontendPtwOutstanding);
|
||||
backendReadOutstanding <=
|
||||
~(backendRespValid & (backendReadOutstanding | backendReadIssue))
|
||||
& (backendReadIssue & ~backendRespValid | backendReadOutstanding);
|
||||
end
|
||||
if (_backend_io_flush | ~fetchReady) begin
|
||||
end
|
||||
else begin
|
||||
@@ -109,6 +170,9 @@ module Core(
|
||||
fetchReg_inst_1 <= _frontend_io_out_inst_1;
|
||||
fetchReg_laneValid_0 <= _frontend_io_out_laneValid_0;
|
||||
fetchReg_laneValid_1 <= _frontend_io_out_laneValid_1;
|
||||
fetchReg_exception <= _frontend_io_out_exception;
|
||||
fetchReg_exceptionCause <= _frontend_io_out_exceptionCause;
|
||||
fetchReg_exceptionTval <= _frontend_io_out_exceptionTval;
|
||||
end
|
||||
end // always @(posedge)
|
||||
Frontend frontend (
|
||||
@@ -117,18 +181,28 @@ module Core(
|
||||
.io_redirectValid (_backend_io_flush),
|
||||
.io_redirectPc (_backend_io_redirectPc),
|
||||
.io_invalidateICache (_backend_io_invalidateICache),
|
||||
.io_sfenceVma (_backend_io_sfenceVma),
|
||||
.io_satp (_backend_io_satpOut),
|
||||
.io_currentPriv (_privCtrl_io_priv),
|
||||
.io_imemReqValid (io_imem_req_valid),
|
||||
.io_imemReqAddr (io_imem_req_bits),
|
||||
.io_imemRespValid (io_imem_resp_valid),
|
||||
.io_imemRespBits_0 (io_imem_resp_bits_0),
|
||||
.io_imemRespBits_1 (io_imem_resp_bits_1),
|
||||
.io_ptwMemReqValid (_frontend_io_ptwMemReqValid),
|
||||
.io_ptwMemReqAddr (_frontend_io_ptwMemReqAddr),
|
||||
.io_ptwMemRespValid (frontendPtwRespValid),
|
||||
.io_ptwMemRespData (io_dmem_resp_bits),
|
||||
.io_outReady (fetchReady),
|
||||
.io_outValid (_frontend_io_outValid),
|
||||
.io_out_pc (_frontend_io_out_pc),
|
||||
.io_out_inst_0 (_frontend_io_out_inst_0),
|
||||
.io_out_inst_1 (_frontend_io_out_inst_1),
|
||||
.io_out_laneValid_0 (_frontend_io_out_laneValid_0),
|
||||
.io_out_laneValid_1 (_frontend_io_out_laneValid_1)
|
||||
.io_out_laneValid_1 (_frontend_io_out_laneValid_1),
|
||||
.io_out_exception (_frontend_io_out_exception),
|
||||
.io_out_exceptionCause (_frontend_io_out_exceptionCause),
|
||||
.io_out_exceptionTval (_frontend_io_out_exceptionTval)
|
||||
);
|
||||
IDStage id (
|
||||
.io_inValid (fetchValid),
|
||||
@@ -137,6 +211,9 @@ module Core(
|
||||
.io_in_inst_1 (fetchReg_inst_1),
|
||||
.io_in_laneValid_0 (fetchReg_laneValid_0),
|
||||
.io_in_laneValid_1 (fetchReg_laneValid_1),
|
||||
.io_in_exception (fetchReg_exception),
|
||||
.io_in_exceptionCause (fetchReg_exceptionCause),
|
||||
.io_in_exceptionTval (fetchReg_exceptionTval),
|
||||
.io_outValid_0 (_id_io_outValid_0),
|
||||
.io_outValid_1 (_id_io_outValid_1),
|
||||
.io_out_0_pc (_id_io_out_0_pc),
|
||||
@@ -165,10 +242,20 @@ module Core(
|
||||
.io_out_0_isWord (_id_io_out_0_isWord),
|
||||
.io_out_0_isSystem (_id_io_out_0_isSystem),
|
||||
.io_out_0_isFenceI (_id_io_out_0_isFenceI),
|
||||
.io_out_0_isEcall (_id_io_out_0_isEcall),
|
||||
.io_out_0_isEbreak (_id_io_out_0_isEbreak),
|
||||
.io_out_0_isMret (_id_io_out_0_isMret),
|
||||
.io_out_0_isSret (_id_io_out_0_isSret),
|
||||
.io_out_0_isSfenceVma (_id_io_out_0_isSfenceVma),
|
||||
.io_out_0_isXret (_id_io_out_0_isXret),
|
||||
.io_out_0_isWfi (_id_io_out_0_isWfi),
|
||||
.io_out_0_isAmo (_id_io_out_0_isAmo),
|
||||
.io_out_0_amoOp (_id_io_out_0_amoOp),
|
||||
.io_out_0_writesRd (_id_io_out_0_writesRd),
|
||||
.io_out_0_illegal (_id_io_out_0_illegal),
|
||||
.io_out_0_fetchException (_id_io_out_0_fetchException),
|
||||
.io_out_0_fetchExceptionCause (_id_io_out_0_fetchExceptionCause),
|
||||
.io_out_0_fetchExceptionTval (_id_io_out_0_fetchExceptionTval),
|
||||
.io_out_1_pc (_id_io_out_1_pc),
|
||||
.io_out_1_inst (_id_io_out_1_inst),
|
||||
.io_out_1_rs1 (_id_io_out_1_rs1),
|
||||
@@ -195,10 +282,20 @@ module Core(
|
||||
.io_out_1_isWord (_id_io_out_1_isWord),
|
||||
.io_out_1_isSystem (_id_io_out_1_isSystem),
|
||||
.io_out_1_isFenceI (_id_io_out_1_isFenceI),
|
||||
.io_out_1_isEcall (_id_io_out_1_isEcall),
|
||||
.io_out_1_isEbreak (_id_io_out_1_isEbreak),
|
||||
.io_out_1_isMret (_id_io_out_1_isMret),
|
||||
.io_out_1_isSret (_id_io_out_1_isSret),
|
||||
.io_out_1_isSfenceVma (_id_io_out_1_isSfenceVma),
|
||||
.io_out_1_isXret (_id_io_out_1_isXret),
|
||||
.io_out_1_isWfi (_id_io_out_1_isWfi),
|
||||
.io_out_1_isAmo (_id_io_out_1_isAmo),
|
||||
.io_out_1_amoOp (_id_io_out_1_amoOp),
|
||||
.io_out_1_writesRd (_id_io_out_1_writesRd),
|
||||
.io_out_1_illegal (_id_io_out_1_illegal)
|
||||
.io_out_1_illegal (_id_io_out_1_illegal),
|
||||
.io_out_1_fetchException (_id_io_out_1_fetchException),
|
||||
.io_out_1_fetchExceptionCause (_id_io_out_1_fetchExceptionCause),
|
||||
.io_out_1_fetchExceptionTval (_id_io_out_1_fetchExceptionTval)
|
||||
);
|
||||
OoOBackend backend (
|
||||
.clock (clock),
|
||||
@@ -231,10 +328,20 @@ module Core(
|
||||
.io_decode_0_isWord (_id_io_out_0_isWord),
|
||||
.io_decode_0_isSystem (_id_io_out_0_isSystem),
|
||||
.io_decode_0_isFenceI (_id_io_out_0_isFenceI),
|
||||
.io_decode_0_isEcall (_id_io_out_0_isEcall),
|
||||
.io_decode_0_isEbreak (_id_io_out_0_isEbreak),
|
||||
.io_decode_0_isMret (_id_io_out_0_isMret),
|
||||
.io_decode_0_isSret (_id_io_out_0_isSret),
|
||||
.io_decode_0_isSfenceVma (_id_io_out_0_isSfenceVma),
|
||||
.io_decode_0_isXret (_id_io_out_0_isXret),
|
||||
.io_decode_0_isWfi (_id_io_out_0_isWfi),
|
||||
.io_decode_0_isAmo (_id_io_out_0_isAmo),
|
||||
.io_decode_0_amoOp (_id_io_out_0_amoOp),
|
||||
.io_decode_0_writesRd (_id_io_out_0_writesRd),
|
||||
.io_decode_0_illegal (_id_io_out_0_illegal),
|
||||
.io_decode_0_fetchException (_id_io_out_0_fetchException),
|
||||
.io_decode_0_fetchExceptionCause (_id_io_out_0_fetchExceptionCause),
|
||||
.io_decode_0_fetchExceptionTval (_id_io_out_0_fetchExceptionTval),
|
||||
.io_decode_1_pc (_id_io_out_1_pc),
|
||||
.io_decode_1_inst (_id_io_out_1_inst),
|
||||
.io_decode_1_rs1 (_id_io_out_1_rs1),
|
||||
@@ -261,21 +368,50 @@ module Core(
|
||||
.io_decode_1_isWord (_id_io_out_1_isWord),
|
||||
.io_decode_1_isSystem (_id_io_out_1_isSystem),
|
||||
.io_decode_1_isFenceI (_id_io_out_1_isFenceI),
|
||||
.io_decode_1_isEcall (_id_io_out_1_isEcall),
|
||||
.io_decode_1_isEbreak (_id_io_out_1_isEbreak),
|
||||
.io_decode_1_isMret (_id_io_out_1_isMret),
|
||||
.io_decode_1_isSret (_id_io_out_1_isSret),
|
||||
.io_decode_1_isSfenceVma (_id_io_out_1_isSfenceVma),
|
||||
.io_decode_1_isXret (_id_io_out_1_isXret),
|
||||
.io_decode_1_isWfi (_id_io_out_1_isWfi),
|
||||
.io_decode_1_isAmo (_id_io_out_1_isAmo),
|
||||
.io_decode_1_amoOp (_id_io_out_1_amoOp),
|
||||
.io_decode_1_writesRd (_id_io_out_1_writesRd),
|
||||
.io_decode_1_illegal (_id_io_out_1_illegal),
|
||||
.io_decode_1_fetchException (_id_io_out_1_fetchException),
|
||||
.io_decode_1_fetchExceptionCause (_id_io_out_1_fetchExceptionCause),
|
||||
.io_decode_1_fetchExceptionTval (_id_io_out_1_fetchExceptionTval),
|
||||
.io_decodeReady (_backend_io_decodeReady),
|
||||
.io_flush (_backend_io_flush),
|
||||
.io_redirectPc (_backend_io_redirectPc),
|
||||
.io_invalidateICache (_backend_io_invalidateICache),
|
||||
.io_dmemReqValid (io_dmem_req_valid),
|
||||
.io_dmemReq_addr (io_dmem_req_bits_addr),
|
||||
.io_dmemReq_data (io_dmem_req_bits_data),
|
||||
.io_dmemReq_isStore (io_dmem_req_bits_isStore),
|
||||
.io_dmemReq_size (io_dmem_req_bits_size),
|
||||
.io_dmemRespValid (io_dmem_resp_valid),
|
||||
.io_dmemRespData (io_dmem_resp_bits)
|
||||
.io_sfenceVma (_backend_io_sfenceVma),
|
||||
.io_setPriv (_backend_io_setPriv),
|
||||
.io_targetPriv (_backend_io_targetPriv),
|
||||
.io_dmemReqValid (_backend_io_dmemReqValid),
|
||||
.io_dmemReq_addr (_backend_io_dmemReq_addr),
|
||||
.io_dmemReq_data (_backend_io_dmemReq_data),
|
||||
.io_dmemReq_isStore (_backend_io_dmemReq_isStore),
|
||||
.io_dmemReq_size (_backend_io_dmemReq_size),
|
||||
.io_dmemRespValid (backendRespValid),
|
||||
.io_dmemRespData (io_dmem_resp_bits),
|
||||
.io_satpOut (_backend_io_satpOut),
|
||||
.io_currentPriv (_privCtrl_io_priv)
|
||||
);
|
||||
PrivilegeControl privCtrl (
|
||||
.clock (clock),
|
||||
.reset (reset),
|
||||
.io_nextPriv (_backend_io_targetPriv),
|
||||
.io_setPriv (_backend_io_setPriv),
|
||||
.io_priv (_privCtrl_io_priv)
|
||||
);
|
||||
assign io_dmem_req_valid = _io_dmem_req_bits_isStore_T | frontendPtwCanIssue;
|
||||
assign io_dmem_req_bits_addr =
|
||||
frontendPtwCanIssue ? _frontend_io_ptwMemReqAddr : _backend_io_dmemReq_addr;
|
||||
assign io_dmem_req_bits_data = frontendPtwCanIssue ? 64'h0 : _backend_io_dmemReq_data;
|
||||
assign io_dmem_req_bits_isStore =
|
||||
_io_dmem_req_bits_isStore_T & _backend_io_dmemReq_isStore;
|
||||
assign io_dmem_req_bits_size = frontendPtwCanIssue ? 3'h3 : _backend_io_dmemReq_size;
|
||||
endmodule
|
||||
|
||||
|
||||
73981
generated-ooo/DCache.sv
73981
generated-ooo/DCache.sv
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -28,6 +28,13 @@ module Decoder(
|
||||
io_out_isWord,
|
||||
io_out_isSystem,
|
||||
io_out_isFenceI,
|
||||
io_out_isEcall,
|
||||
io_out_isEbreak,
|
||||
io_out_isMret,
|
||||
io_out_isSret,
|
||||
io_out_isSfenceVma,
|
||||
io_out_isXret,
|
||||
io_out_isWfi,
|
||||
io_out_isAmo,
|
||||
output [4:0] io_out_amoOp,
|
||||
output io_out_writesRd,
|
||||
@@ -36,7 +43,16 @@ module Decoder(
|
||||
|
||||
wire [7:0][4:0] _GEN = '{5'hE, 5'hD, 5'hC, 5'hB, 5'h12, 5'h11, 5'h10, 5'hA};
|
||||
wire [7:0][1:0] _GEN_0 = '{2'h3, 2'h2, 2'h1, 2'h0, 2'h3, 2'h2, 2'h1, 2'h0};
|
||||
wire _isSfenceVma_T = io_inst[14:12] == 3'h0;
|
||||
wire _d_isFenceI_T = io_inst[14:12] == 3'h1;
|
||||
wire isSystemOpcode = io_inst[6:0] == 7'h73;
|
||||
wire isFenceOpcode = io_inst[6:0] == 7'hF;
|
||||
wire isEcall = io_inst == 32'h73;
|
||||
wire isEbreak = io_inst == 32'h100073;
|
||||
wire isMret = io_inst == 32'h30200073;
|
||||
wire isSret = io_inst == 32'h10200073;
|
||||
wire isWfi = io_inst == 32'h10500073;
|
||||
wire isSfenceVma = isSystemOpcode & _isSfenceVma_T & io_inst[31:25] == 7'h9;
|
||||
wire d_isLui = io_inst[6:0] == 7'h37;
|
||||
wire _GEN_1 = io_inst[6:0] == 7'h17;
|
||||
wire _GEN_2 = io_inst[6:0] == 7'h6F;
|
||||
@@ -70,15 +86,15 @@ module Decoder(
|
||||
{5'h3},
|
||||
{5'h2},
|
||||
{{4'h0, io_inst[30]}}};
|
||||
wire _GEN_14 = io_inst[6:0] == 7'hF;
|
||||
wire _GEN_15 = _GEN_8 | _GEN_12;
|
||||
wire _GEN_16 = io_inst[6:0] == 7'h73;
|
||||
wire _GEN_17 = io_inst[6:0] == 7'h2F;
|
||||
wire _GEN_18 = _GEN_14 | _GEN_16;
|
||||
wire _GEN_19 = _GEN_7 | _GEN_8 | _GEN_12 | _GEN_18;
|
||||
wire _GEN_20 = _GEN_2 | _GEN_4 | _GEN_5;
|
||||
wire _GEN_21 =
|
||||
d_isLui | _GEN_1 | _GEN_2 | _GEN_4 | _GEN_5 | _GEN_6 | _GEN_19;
|
||||
wire _GEN_14 = _GEN_8 | _GEN_12;
|
||||
wire _GEN_15 =
|
||||
d_isLui | _GEN_1 | _GEN_2 | _GEN_4 | _GEN_5 | _GEN_6 | _GEN_7 | _GEN_14;
|
||||
wire _GEN_16 = io_inst[6:0] == 7'h2F;
|
||||
wire _GEN_17 = isFenceOpcode | isSystemOpcode;
|
||||
wire _GEN_18 = _GEN_7 | _GEN_8 | _GEN_12 | _GEN_17;
|
||||
wire _GEN_19 = _GEN_2 | _GEN_4 | _GEN_5;
|
||||
wire _GEN_20 =
|
||||
d_isLui | _GEN_1 | _GEN_2 | _GEN_4 | _GEN_5 | _GEN_6 | _GEN_18;
|
||||
assign io_out_pc = io_pc;
|
||||
assign io_out_inst = io_inst;
|
||||
assign io_out_rs1 = io_inst[19:15];
|
||||
@@ -95,11 +111,11 @@ module Decoder(
|
||||
assign io_out_opClass =
|
||||
_GEN_3
|
||||
? 4'h1
|
||||
: _GEN_20
|
||||
: _GEN_19
|
||||
? 4'h2
|
||||
: _GEN_6
|
||||
? 4'h3
|
||||
: _GEN_7 ? 4'h4 : _GEN_15 ? 4'h1 : _GEN_18 ? 4'h5 : _GEN_17 ? 4'h3 : 4'h0;
|
||||
: _GEN_7 ? 4'h4 : _GEN_14 ? 4'h1 : _GEN_17 ? 4'h5 : _GEN_16 ? 4'h3 : 4'h0;
|
||||
assign io_out_aluFn =
|
||||
d_isLui
|
||||
? 5'hF
|
||||
@@ -113,9 +129,9 @@ module Decoder(
|
||||
: _GEN_13[io_inst[14:12]])
|
||||
: 5'h0;
|
||||
assign io_out_memWidth =
|
||||
_GEN_21 | ~_GEN_17 ? {1'h0, _GEN_0[io_inst[14:12]]} : {2'h1, io_inst[14:12] != 3'h2};
|
||||
_GEN_20 | ~_GEN_16 ? {1'h0, _GEN_0[io_inst[14:12]]} : {2'h1, io_inst[14:12] != 3'h2};
|
||||
assign io_out_memSigned = ~(io_inst[14]);
|
||||
assign io_out_isLoad = ~(d_isLui | _GEN_1 | _GEN_20) & (_GEN_6 | ~_GEN_19 & _GEN_17);
|
||||
assign io_out_isLoad = ~(d_isLui | _GEN_1 | _GEN_19) & (_GEN_6 | ~_GEN_18 & _GEN_16);
|
||||
assign io_out_isStore =
|
||||
~(d_isLui | _GEN_1 | _GEN_2 | _GEN_4 | _GEN_5 | _GEN_6) & _GEN_7;
|
||||
assign io_out_isBranch = ~(d_isLui | _GEN_1 | _GEN_2 | _GEN_4) & _GEN_5;
|
||||
@@ -127,11 +143,16 @@ module Decoder(
|
||||
assign io_out_isWord = ~_GEN_10 & (_GEN_8 ? _d_isWord_T : _GEN_12 & _d_isWord_T_1);
|
||||
assign io_out_isSystem =
|
||||
~(d_isLui | _GEN_1 | _GEN_2 | _GEN_4 | _GEN_5 | _GEN_6 | _GEN_7 | _GEN_8 | _GEN_12
|
||||
| _GEN_14) & _GEN_16;
|
||||
assign io_out_isFenceI =
|
||||
~(d_isLui | _GEN_1 | _GEN_2 | _GEN_4 | _GEN_5 | _GEN_6 | _GEN_7 | _GEN_15) & _GEN_14
|
||||
& _d_isFenceI_T;
|
||||
assign io_out_isAmo = ~_GEN_21 & _GEN_17;
|
||||
| isFenceOpcode) & isSystemOpcode;
|
||||
assign io_out_isFenceI = ~_GEN_15 & isFenceOpcode & _d_isFenceI_T;
|
||||
assign io_out_isEcall = isEcall;
|
||||
assign io_out_isEbreak = isEbreak;
|
||||
assign io_out_isMret = isMret;
|
||||
assign io_out_isSret = isSret;
|
||||
assign io_out_isSfenceVma = isSfenceVma;
|
||||
assign io_out_isXret = isMret | isSret;
|
||||
assign io_out_isWfi = isWfi;
|
||||
assign io_out_isAmo = ~_GEN_20 & _GEN_16;
|
||||
assign io_out_amoOp = io_inst[31:27];
|
||||
assign io_out_writesRd =
|
||||
d_isLui
|
||||
@@ -150,15 +171,20 @@ module Decoder(
|
||||
? (|(io_inst[11:7]))
|
||||
: _GEN_12
|
||||
? (|(io_inst[11:7]))
|
||||
: ~_GEN_14
|
||||
& (_GEN_16
|
||||
: ~isFenceOpcode
|
||||
& (isSystemOpcode
|
||||
? (|(io_inst[11:7])) & (|(io_inst[14:12]))
|
||||
: _GEN_17 & (|(io_inst[11:7])))));
|
||||
: _GEN_16 & (|(io_inst[11:7])))));
|
||||
assign io_out_illegal =
|
||||
io_inst[6:0] != 7'h37 & io_inst[6:0] != 7'h17 & io_inst[6:0] != 7'h6F
|
||||
& io_inst[6:0] != 7'h67 & io_inst[6:0] != 7'h63 & io_inst[6:0] != 7'h3
|
||||
& io_inst[6:0] != 7'h23 & io_inst[6:0] != 7'h13 & io_inst[6:0] != 7'h1B
|
||||
& io_inst[6:0] != 7'h33 & io_inst[6:0] != 7'h3B & io_inst[6:0] != 7'hF
|
||||
& io_inst[6:0] != 7'h73 & io_inst[6:0] != 7'h2F;
|
||||
isSystemOpcode & io_inst == 32'h200073 | io_inst[6:0] != 7'h37 & io_inst[6:0] != 7'h17
|
||||
& io_inst[6:0] != 7'h6F & io_inst[6:0] != 7'h67 & io_inst[6:0] != 7'h63
|
||||
& io_inst[6:0] != 7'h3 & io_inst[6:0] != 7'h23 & io_inst[6:0] != 7'h13
|
||||
& io_inst[6:0] != 7'h1B & io_inst[6:0] != 7'h33 & io_inst[6:0] != 7'h3B
|
||||
& io_inst[6:0] != 7'hF & io_inst[6:0] != 7'h73 & io_inst[6:0] != 7'h2F | ~_GEN_15
|
||||
& (isFenceOpcode
|
||||
? (|(io_inst[14:12])) & io_inst[14:12] != 3'h1
|
||||
: isSystemOpcode & _isSfenceVma_T
|
||||
& ~((isEcall | isEbreak | isMret | isSret | isSfenceVma | isWfi)
|
||||
& io_inst != 32'h200073));
|
||||
endmodule
|
||||
|
||||
|
||||
@@ -5,41 +5,135 @@ module Frontend(
|
||||
io_redirectValid,
|
||||
input [63:0] io_redirectPc,
|
||||
input io_invalidateICache,
|
||||
io_sfenceVma,
|
||||
input [63:0] io_satp,
|
||||
input [1:0] io_currentPriv,
|
||||
output io_imemReqValid,
|
||||
output [63:0] io_imemReqAddr,
|
||||
input io_imemRespValid,
|
||||
input [31:0] io_imemRespBits_0,
|
||||
io_imemRespBits_1,
|
||||
output io_ptwMemReqValid,
|
||||
output [63:0] io_ptwMemReqAddr,
|
||||
input io_ptwMemRespValid,
|
||||
input [63:0] io_ptwMemRespData,
|
||||
input io_outReady,
|
||||
output io_outValid,
|
||||
output [63:0] io_out_pc,
|
||||
output [31:0] io_out_inst_0,
|
||||
io_out_inst_1,
|
||||
output io_out_laneValid_0,
|
||||
io_out_laneValid_1
|
||||
io_out_laneValid_1,
|
||||
io_out_exception,
|
||||
output [63:0] io_out_exceptionCause,
|
||||
io_out_exceptionTval
|
||||
);
|
||||
|
||||
wire _icache_io_respValid;
|
||||
wire [63:0] _icache_io_resp_pc;
|
||||
wire [31:0] _icache_io_resp_inst_0;
|
||||
wire [31:0] _icache_io_resp_inst_1;
|
||||
wire _icache_io_resp_laneValid_0;
|
||||
wire _icache_io_resp_laneValid_1;
|
||||
wire _icache_io_resp_exception;
|
||||
wire [63:0] _icache_io_resp_exceptionCause;
|
||||
wire [63:0] _icache_io_resp_exceptionTval;
|
||||
wire _immu_io_resp_pageFault;
|
||||
wire _immu_io_refill_valid;
|
||||
wire [26:0] _immu_io_refill_vpn;
|
||||
wire [43:0] _immu_io_refill_ppn;
|
||||
wire [1:0] _immu_io_refill_level;
|
||||
wire [7:0] _immu_io_refill_flags;
|
||||
wire _itlb_io_resp_hit;
|
||||
wire _itlb_io_resp_miss;
|
||||
wire [63:0] _itlb_io_resp_paddr;
|
||||
wire _itlb_io_resp_pageFault;
|
||||
reg [63:0] pc;
|
||||
reg faultPending;
|
||||
reg [63:0] faultPc;
|
||||
reg [63:0] faultCause;
|
||||
wire fetchTranslate = (|(io_satp[63:60])) & io_currentPriv != 2'h3;
|
||||
wire itlbMiss = fetchTranslate & _itlb_io_resp_miss;
|
||||
wire instPageFault =
|
||||
fetchTranslate & (_itlb_io_resp_pageFault | _immu_io_resp_pageFault);
|
||||
wire fetchFault = (|(pc[1:0])) | instPageFault;
|
||||
wire translationReady = ~fetchTranslate | _itlb_io_resp_hit | instPageFault;
|
||||
wire [63:0] translatedFetchAddr = fetchTranslate ? _itlb_io_resp_paddr : pc;
|
||||
always @(posedge clock) begin
|
||||
if (reset)
|
||||
automatic logic _GEN;
|
||||
_GEN = fetchFault & ~faultPending;
|
||||
if (reset) begin
|
||||
pc <= 64'h80000000;
|
||||
else if (io_redirectValid)
|
||||
faultPending <= 1'h0;
|
||||
end
|
||||
else begin
|
||||
automatic logic _GEN_0;
|
||||
_GEN_0 = faultPending & io_outReady;
|
||||
if (io_redirectValid)
|
||||
pc <= io_redirectPc;
|
||||
else if (~_GEN) begin
|
||||
if (_GEN_0)
|
||||
pc <= pc + 64'h4;
|
||||
else if (_icache_io_respValid & io_outReady)
|
||||
pc <=
|
||||
_icache_io_resp_pc
|
||||
+ {60'h0,
|
||||
{1'h0, _icache_io_resp_laneValid_0} + {1'h0, _icache_io_resp_laneValid_1},
|
||||
2'h0};
|
||||
end
|
||||
faultPending <= ~io_redirectValid & (_GEN | ~_GEN_0 & faultPending);
|
||||
end
|
||||
if (io_redirectValid | ~_GEN) begin
|
||||
end
|
||||
else begin
|
||||
faultPc <= pc;
|
||||
faultCause <= {56'h0, (|(pc[1:0])) ? 8'h0 : 8'hC};
|
||||
end
|
||||
end // always @(posedge)
|
||||
ITLB itlb (
|
||||
.clock (clock),
|
||||
.reset (reset),
|
||||
.io_req_valid (fetchTranslate & ~faultPending),
|
||||
.io_req_vaddr (pc),
|
||||
.io_req_priv (io_currentPriv),
|
||||
.io_resp_hit (_itlb_io_resp_hit),
|
||||
.io_resp_miss (_itlb_io_resp_miss),
|
||||
.io_resp_paddr (_itlb_io_resp_paddr),
|
||||
.io_resp_pageFault (_itlb_io_resp_pageFault),
|
||||
.io_refill_valid (_immu_io_refill_valid),
|
||||
.io_refill_vpn (_immu_io_refill_vpn),
|
||||
.io_refill_ppn (_immu_io_refill_ppn),
|
||||
.io_refill_level (_immu_io_refill_level),
|
||||
.io_refill_flags (_immu_io_refill_flags),
|
||||
.io_flush (io_redirectValid | io_invalidateICache | io_sfenceVma)
|
||||
);
|
||||
MMU immu (
|
||||
.clock (clock),
|
||||
.reset (reset),
|
||||
.io_satp (io_satp),
|
||||
.io_req_valid (itlbMiss),
|
||||
.io_req_vaddr (pc),
|
||||
.io_req_isStore (1'h0),
|
||||
.io_req_isFetch (1'h1),
|
||||
.io_req_priv (io_currentPriv),
|
||||
.io_req_sum (1'h0),
|
||||
.io_req_mxr (1'h0),
|
||||
.io_resp_pageFault (_immu_io_resp_pageFault),
|
||||
.io_ptwMemReq_valid (io_ptwMemReqValid),
|
||||
.io_ptwMemReq_addr (io_ptwMemReqAddr),
|
||||
.io_ptwMemResp_valid (io_ptwMemRespValid),
|
||||
.io_ptwMemResp_data (io_ptwMemRespData),
|
||||
.io_refill_valid (_immu_io_refill_valid),
|
||||
.io_refill_vpn (_immu_io_refill_vpn),
|
||||
.io_refill_ppn (_immu_io_refill_ppn),
|
||||
.io_refill_level (_immu_io_refill_level),
|
||||
.io_refill_flags (_immu_io_refill_flags)
|
||||
);
|
||||
ICache icache (
|
||||
.clock (clock),
|
||||
.reset (reset),
|
||||
.io_reqAddr (pc),
|
||||
.io_reqValid (~fetchFault & ~faultPending & translationReady),
|
||||
.io_reqAddr (translatedFetchAddr),
|
||||
.io_reqPc (pc),
|
||||
.io_flush (io_redirectValid),
|
||||
.io_invalidate (io_invalidateICache),
|
||||
@@ -51,14 +145,23 @@ module Frontend(
|
||||
.io_memRespBits_1 (io_imemRespBits_1),
|
||||
.io_respValid (_icache_io_respValid),
|
||||
.io_resp_pc (_icache_io_resp_pc),
|
||||
.io_resp_inst_0 (io_out_inst_0),
|
||||
.io_resp_inst_1 (io_out_inst_1),
|
||||
.io_resp_inst_0 (_icache_io_resp_inst_0),
|
||||
.io_resp_inst_1 (_icache_io_resp_inst_1),
|
||||
.io_resp_laneValid_0 (_icache_io_resp_laneValid_0),
|
||||
.io_resp_laneValid_1 (_icache_io_resp_laneValid_1)
|
||||
.io_resp_laneValid_1 (_icache_io_resp_laneValid_1),
|
||||
.io_resp_exception (_icache_io_resp_exception),
|
||||
.io_resp_exceptionCause (_icache_io_resp_exceptionCause),
|
||||
.io_resp_exceptionTval (_icache_io_resp_exceptionTval)
|
||||
);
|
||||
assign io_outValid = _icache_io_respValid;
|
||||
assign io_out_pc = _icache_io_resp_pc;
|
||||
assign io_out_laneValid_0 = _icache_io_resp_laneValid_0;
|
||||
assign io_out_laneValid_1 = _icache_io_resp_laneValid_1;
|
||||
assign io_outValid = faultPending | _icache_io_respValid;
|
||||
assign io_out_pc = faultPending ? faultPc : _icache_io_resp_pc;
|
||||
assign io_out_inst_0 = faultPending ? 32'h0 : _icache_io_resp_inst_0;
|
||||
assign io_out_inst_1 = faultPending ? 32'h0 : _icache_io_resp_inst_1;
|
||||
assign io_out_laneValid_0 = faultPending | _icache_io_resp_laneValid_0;
|
||||
assign io_out_laneValid_1 = ~faultPending & _icache_io_resp_laneValid_1;
|
||||
assign io_out_exception = faultPending | _icache_io_resp_exception;
|
||||
assign io_out_exceptionCause =
|
||||
faultPending ? faultCause : _icache_io_resp_exceptionCause;
|
||||
assign io_out_exceptionTval = faultPending ? faultPc : _icache_io_resp_exceptionTval;
|
||||
endmodule
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
module ICache(
|
||||
input clock,
|
||||
reset,
|
||||
io_reqValid,
|
||||
input [63:0] io_reqAddr,
|
||||
io_reqPc,
|
||||
input io_flush,
|
||||
@@ -17,7 +18,10 @@ module ICache(
|
||||
output [31:0] io_resp_inst_0,
|
||||
io_resp_inst_1,
|
||||
output io_resp_laneValid_0,
|
||||
io_resp_laneValid_1
|
||||
io_resp_laneValid_1,
|
||||
io_resp_exception,
|
||||
output [63:0] io_resp_exceptionCause,
|
||||
io_resp_exceptionTval
|
||||
);
|
||||
|
||||
wire [31:0] dataWrite_3_1;
|
||||
@@ -9295,8 +9299,9 @@ module ICache(
|
||||
reg [31:0] respReg_inst_1;
|
||||
reg respReg_laneValid_0;
|
||||
reg respReg_laneValid_1;
|
||||
reg respReg_exception;
|
||||
wire _readFire_T = state == 2'h0;
|
||||
wire readFire = _readFire_T & ~io_flush;
|
||||
wire readFire = _readFire_T & io_reqValid & ~io_flush;
|
||||
wire tagHitVec_0 =
|
||||
(|{lookupValidRow_0_1, lookupValidRow_0_0})
|
||||
& _tags_ext_R0_data[50:0] == lookupAddr[63:13];
|
||||
@@ -38132,7 +38137,7 @@ module ICache(
|
||||
{{_GEN_18 ? _GEN_2082 : state},
|
||||
{io_respReady ? 2'h0 : state},
|
||||
{(|_hitWay_T) ? _GEN_2082 : 2'h3},
|
||||
{2'h1}};
|
||||
{io_reqValid ? 2'h1 : state}};
|
||||
state <= _GEN_2083[state];
|
||||
end
|
||||
missReqSent <=
|
||||
@@ -38143,7 +38148,7 @@ module ICache(
|
||||
? (|_hitWay_T) & missReqSent
|
||||
: ~_io_resp_T & (&state) & ~missReqSent | missReqSent);
|
||||
end
|
||||
if (_GEN_16 | ~_readFire_T) begin
|
||||
if (_GEN_16 | ~(_readFire_T & io_reqValid)) begin
|
||||
end
|
||||
else begin
|
||||
automatic logic [1023:0] _GEN_2084 =
|
||||
@@ -47420,8 +47425,12 @@ module ICache(
|
||||
missValidRow_3_1 <= lookupValidRow_3_1;
|
||||
end
|
||||
if (~_GEN_17) begin
|
||||
automatic logic _GEN_2093;
|
||||
automatic logic _GEN_2094;
|
||||
_GEN_2093 = ~(|_hitWay_T) | io_respReady;
|
||||
_GEN_2094 = _io_resp_T | ~_GEN_18 | io_respReady;
|
||||
if (_io_miss_T) begin
|
||||
if (~(|_hitWay_T) | io_respReady) begin
|
||||
if (_GEN_2093) begin
|
||||
end
|
||||
else begin
|
||||
respReg_pc <= lookupPc;
|
||||
@@ -47430,7 +47439,7 @@ module ICache(
|
||||
respReg_laneValid_1 <= lookupLane1Valid;
|
||||
end
|
||||
end
|
||||
else if (_io_resp_T | ~_GEN_18 | io_respReady) begin
|
||||
else if (_GEN_2094) begin
|
||||
end
|
||||
else begin
|
||||
respReg_pc <= missPc;
|
||||
@@ -47442,6 +47451,8 @@ module ICache(
|
||||
_io_miss_T
|
||||
? (|_hitWay_T) & ~io_respReady | respReg_laneValid_0
|
||||
: ~_io_resp_T & _GEN_18 & ~io_respReady | respReg_laneValid_0;
|
||||
respReg_exception <=
|
||||
_io_miss_T ? _GEN_2093 & respReg_exception : _GEN_2094 & respReg_exception;
|
||||
end
|
||||
end // always @(posedge)
|
||||
tags_1024x204 tags_ext (
|
||||
@@ -47487,5 +47498,8 @@ module ICache(
|
||||
assign io_resp_laneValid_0 = ~_io_resp_T | respReg_laneValid_0;
|
||||
assign io_resp_laneValid_1 =
|
||||
_io_resp_T ? respReg_laneValid_1 : _io_resp_T_2 ? ~missInst : lookupLane1Valid;
|
||||
assign io_resp_exception = _io_resp_T & respReg_exception;
|
||||
assign io_resp_exceptionCause = 64'h0;
|
||||
assign io_resp_exceptionTval = 64'h0;
|
||||
endmodule
|
||||
|
||||
|
||||
@@ -6,6 +6,9 @@ module IDStage(
|
||||
io_in_inst_1,
|
||||
input io_in_laneValid_0,
|
||||
io_in_laneValid_1,
|
||||
io_in_exception,
|
||||
input [63:0] io_in_exceptionCause,
|
||||
io_in_exceptionTval,
|
||||
output io_outValid_0,
|
||||
io_outValid_1,
|
||||
output [63:0] io_out_0_pc,
|
||||
@@ -34,11 +37,21 @@ module IDStage(
|
||||
io_out_0_isWord,
|
||||
io_out_0_isSystem,
|
||||
io_out_0_isFenceI,
|
||||
io_out_0_isEcall,
|
||||
io_out_0_isEbreak,
|
||||
io_out_0_isMret,
|
||||
io_out_0_isSret,
|
||||
io_out_0_isSfenceVma,
|
||||
io_out_0_isXret,
|
||||
io_out_0_isWfi,
|
||||
io_out_0_isAmo,
|
||||
output [4:0] io_out_0_amoOp,
|
||||
output io_out_0_writesRd,
|
||||
io_out_0_illegal,
|
||||
output [63:0] io_out_1_pc,
|
||||
io_out_0_fetchException,
|
||||
output [63:0] io_out_0_fetchExceptionCause,
|
||||
io_out_0_fetchExceptionTval,
|
||||
io_out_1_pc,
|
||||
output [31:0] io_out_1_inst,
|
||||
output [4:0] io_out_1_rs1,
|
||||
io_out_1_rs2,
|
||||
@@ -64,10 +77,20 @@ module IDStage(
|
||||
io_out_1_isWord,
|
||||
io_out_1_isSystem,
|
||||
io_out_1_isFenceI,
|
||||
io_out_1_isEcall,
|
||||
io_out_1_isEbreak,
|
||||
io_out_1_isMret,
|
||||
io_out_1_isSret,
|
||||
io_out_1_isSfenceVma,
|
||||
io_out_1_isXret,
|
||||
io_out_1_isWfi,
|
||||
io_out_1_isAmo,
|
||||
output [4:0] io_out_1_amoOp,
|
||||
output io_out_1_writesRd,
|
||||
io_out_1_illegal
|
||||
io_out_1_illegal,
|
||||
io_out_1_fetchException,
|
||||
output [63:0] io_out_1_fetchExceptionCause,
|
||||
io_out_1_fetchExceptionTval
|
||||
);
|
||||
|
||||
Decoder decoders_0 (
|
||||
@@ -99,6 +122,13 @@ module IDStage(
|
||||
.io_out_isWord (io_out_0_isWord),
|
||||
.io_out_isSystem (io_out_0_isSystem),
|
||||
.io_out_isFenceI (io_out_0_isFenceI),
|
||||
.io_out_isEcall (io_out_0_isEcall),
|
||||
.io_out_isEbreak (io_out_0_isEbreak),
|
||||
.io_out_isMret (io_out_0_isMret),
|
||||
.io_out_isSret (io_out_0_isSret),
|
||||
.io_out_isSfenceVma (io_out_0_isSfenceVma),
|
||||
.io_out_isXret (io_out_0_isXret),
|
||||
.io_out_isWfi (io_out_0_isWfi),
|
||||
.io_out_isAmo (io_out_0_isAmo),
|
||||
.io_out_amoOp (io_out_0_amoOp),
|
||||
.io_out_writesRd (io_out_0_writesRd),
|
||||
@@ -133,6 +163,13 @@ module IDStage(
|
||||
.io_out_isWord (io_out_1_isWord),
|
||||
.io_out_isSystem (io_out_1_isSystem),
|
||||
.io_out_isFenceI (io_out_1_isFenceI),
|
||||
.io_out_isEcall (io_out_1_isEcall),
|
||||
.io_out_isEbreak (io_out_1_isEbreak),
|
||||
.io_out_isMret (io_out_1_isMret),
|
||||
.io_out_isSret (io_out_1_isSret),
|
||||
.io_out_isSfenceVma (io_out_1_isSfenceVma),
|
||||
.io_out_isXret (io_out_1_isXret),
|
||||
.io_out_isWfi (io_out_1_isWfi),
|
||||
.io_out_isAmo (io_out_1_isAmo),
|
||||
.io_out_amoOp (io_out_1_amoOp),
|
||||
.io_out_writesRd (io_out_1_writesRd),
|
||||
@@ -140,5 +177,11 @@ module IDStage(
|
||||
);
|
||||
assign io_outValid_0 = io_inValid & io_in_laneValid_0;
|
||||
assign io_outValid_1 = io_inValid & io_in_laneValid_1;
|
||||
assign io_out_0_fetchException = io_in_exception;
|
||||
assign io_out_0_fetchExceptionCause = io_in_exceptionCause;
|
||||
assign io_out_0_fetchExceptionTval = io_in_exceptionTval;
|
||||
assign io_out_1_fetchException = io_in_exception;
|
||||
assign io_out_1_fetchExceptionCause = io_in_exceptionCause;
|
||||
assign io_out_1_fetchExceptionTval = io_in_exceptionTval;
|
||||
endmodule
|
||||
|
||||
|
||||
1319
generated-ooo/ITLB.sv
Normal file
1319
generated-ooo/ITLB.sv
Normal file
File diff suppressed because it is too large
Load Diff
@@ -28,10 +28,20 @@ module IssueQueue(
|
||||
io_enq_0_decoded_isWord,
|
||||
io_enq_0_decoded_isSystem,
|
||||
io_enq_0_decoded_isFenceI,
|
||||
io_enq_0_decoded_isEcall,
|
||||
io_enq_0_decoded_isEbreak,
|
||||
io_enq_0_decoded_isMret,
|
||||
io_enq_0_decoded_isSret,
|
||||
io_enq_0_decoded_isSfenceVma,
|
||||
io_enq_0_decoded_isXret,
|
||||
io_enq_0_decoded_isWfi,
|
||||
io_enq_0_decoded_isAmo,
|
||||
input [4:0] io_enq_0_decoded_amoOp,
|
||||
input io_enq_0_decoded_writesRd,
|
||||
io_enq_0_decoded_illegal,
|
||||
io_enq_0_decoded_fetchException,
|
||||
input [63:0] io_enq_0_decoded_fetchExceptionCause,
|
||||
io_enq_0_decoded_fetchExceptionTval,
|
||||
input [5:0] io_enq_0_prs1,
|
||||
io_enq_0_prs2,
|
||||
input io_enq_0_src1Ready,
|
||||
@@ -62,10 +72,20 @@ module IssueQueue(
|
||||
io_enq_1_decoded_isWord,
|
||||
io_enq_1_decoded_isSystem,
|
||||
io_enq_1_decoded_isFenceI,
|
||||
io_enq_1_decoded_isEcall,
|
||||
io_enq_1_decoded_isEbreak,
|
||||
io_enq_1_decoded_isMret,
|
||||
io_enq_1_decoded_isSret,
|
||||
io_enq_1_decoded_isSfenceVma,
|
||||
io_enq_1_decoded_isXret,
|
||||
io_enq_1_decoded_isWfi,
|
||||
io_enq_1_decoded_isAmo,
|
||||
input [4:0] io_enq_1_decoded_amoOp,
|
||||
input io_enq_1_decoded_writesRd,
|
||||
io_enq_1_decoded_illegal,
|
||||
io_enq_1_decoded_fetchException,
|
||||
input [63:0] io_enq_1_decoded_fetchExceptionCause,
|
||||
io_enq_1_decoded_fetchExceptionTval,
|
||||
input [5:0] io_enq_1_prs1,
|
||||
io_enq_1_prs2,
|
||||
input io_enq_1_src1Ready,
|
||||
@@ -103,10 +123,20 @@ module IssueQueue(
|
||||
io_issue_0_decoded_isWord,
|
||||
io_issue_0_decoded_isSystem,
|
||||
io_issue_0_decoded_isFenceI,
|
||||
io_issue_0_decoded_isEcall,
|
||||
io_issue_0_decoded_isEbreak,
|
||||
io_issue_0_decoded_isMret,
|
||||
io_issue_0_decoded_isSret,
|
||||
io_issue_0_decoded_isSfenceVma,
|
||||
io_issue_0_decoded_isXret,
|
||||
io_issue_0_decoded_isWfi,
|
||||
io_issue_0_decoded_isAmo,
|
||||
output [4:0] io_issue_0_decoded_amoOp,
|
||||
output io_issue_0_decoded_writesRd,
|
||||
io_issue_0_decoded_illegal,
|
||||
io_issue_0_decoded_fetchException,
|
||||
output [63:0] io_issue_0_decoded_fetchExceptionCause,
|
||||
io_issue_0_decoded_fetchExceptionTval,
|
||||
output [5:0] io_issue_0_prs1,
|
||||
io_issue_0_prs2,
|
||||
io_issue_0_prd,
|
||||
@@ -134,17 +164,29 @@ module IssueQueue(
|
||||
io_issue_1_decoded_isWord,
|
||||
io_issue_1_decoded_isSystem,
|
||||
io_issue_1_decoded_isFenceI,
|
||||
io_issue_1_decoded_isEcall,
|
||||
io_issue_1_decoded_isEbreak,
|
||||
io_issue_1_decoded_isMret,
|
||||
io_issue_1_decoded_isSret,
|
||||
io_issue_1_decoded_isSfenceVma,
|
||||
io_issue_1_decoded_isXret,
|
||||
io_issue_1_decoded_isWfi,
|
||||
io_issue_1_decoded_isAmo,
|
||||
output [4:0] io_issue_1_decoded_amoOp,
|
||||
output io_issue_1_decoded_writesRd,
|
||||
io_issue_1_decoded_illegal,
|
||||
io_issue_1_decoded_fetchException,
|
||||
output [63:0] io_issue_1_decoded_fetchExceptionCause,
|
||||
io_issue_1_decoded_fetchExceptionTval,
|
||||
output [5:0] io_issue_1_prs1,
|
||||
io_issue_1_prs2,
|
||||
io_issue_1_prd,
|
||||
io_issue_1_robIdx,
|
||||
input io_issueReady_0,
|
||||
io_issueReady_1,
|
||||
io_flush
|
||||
io_robHeadValid,
|
||||
input [5:0] io_robHeadIdx,
|
||||
input io_flush
|
||||
);
|
||||
|
||||
ReservationStation intRs (
|
||||
@@ -176,10 +218,20 @@ module IssueQueue(
|
||||
.io_enq_0_decoded_isWord (io_enq_0_decoded_isWord),
|
||||
.io_enq_0_decoded_isSystem (io_enq_0_decoded_isSystem),
|
||||
.io_enq_0_decoded_isFenceI (io_enq_0_decoded_isFenceI),
|
||||
.io_enq_0_decoded_isEcall (io_enq_0_decoded_isEcall),
|
||||
.io_enq_0_decoded_isEbreak (io_enq_0_decoded_isEbreak),
|
||||
.io_enq_0_decoded_isMret (io_enq_0_decoded_isMret),
|
||||
.io_enq_0_decoded_isSret (io_enq_0_decoded_isSret),
|
||||
.io_enq_0_decoded_isSfenceVma (io_enq_0_decoded_isSfenceVma),
|
||||
.io_enq_0_decoded_isXret (io_enq_0_decoded_isXret),
|
||||
.io_enq_0_decoded_isWfi (io_enq_0_decoded_isWfi),
|
||||
.io_enq_0_decoded_isAmo (io_enq_0_decoded_isAmo),
|
||||
.io_enq_0_decoded_amoOp (io_enq_0_decoded_amoOp),
|
||||
.io_enq_0_decoded_writesRd (io_enq_0_decoded_writesRd),
|
||||
.io_enq_0_decoded_illegal (io_enq_0_decoded_illegal),
|
||||
.io_enq_0_decoded_fetchException (io_enq_0_decoded_fetchException),
|
||||
.io_enq_0_decoded_fetchExceptionCause (io_enq_0_decoded_fetchExceptionCause),
|
||||
.io_enq_0_decoded_fetchExceptionTval (io_enq_0_decoded_fetchExceptionTval),
|
||||
.io_enq_0_prs1 (io_enq_0_prs1),
|
||||
.io_enq_0_prs2 (io_enq_0_prs2),
|
||||
.io_enq_0_src1Ready (io_enq_0_src1Ready),
|
||||
@@ -210,10 +262,20 @@ module IssueQueue(
|
||||
.io_enq_1_decoded_isWord (io_enq_1_decoded_isWord),
|
||||
.io_enq_1_decoded_isSystem (io_enq_1_decoded_isSystem),
|
||||
.io_enq_1_decoded_isFenceI (io_enq_1_decoded_isFenceI),
|
||||
.io_enq_1_decoded_isEcall (io_enq_1_decoded_isEcall),
|
||||
.io_enq_1_decoded_isEbreak (io_enq_1_decoded_isEbreak),
|
||||
.io_enq_1_decoded_isMret (io_enq_1_decoded_isMret),
|
||||
.io_enq_1_decoded_isSret (io_enq_1_decoded_isSret),
|
||||
.io_enq_1_decoded_isSfenceVma (io_enq_1_decoded_isSfenceVma),
|
||||
.io_enq_1_decoded_isXret (io_enq_1_decoded_isXret),
|
||||
.io_enq_1_decoded_isWfi (io_enq_1_decoded_isWfi),
|
||||
.io_enq_1_decoded_isAmo (io_enq_1_decoded_isAmo),
|
||||
.io_enq_1_decoded_amoOp (io_enq_1_decoded_amoOp),
|
||||
.io_enq_1_decoded_writesRd (io_enq_1_decoded_writesRd),
|
||||
.io_enq_1_decoded_illegal (io_enq_1_decoded_illegal),
|
||||
.io_enq_1_decoded_fetchException (io_enq_1_decoded_fetchException),
|
||||
.io_enq_1_decoded_fetchExceptionCause (io_enq_1_decoded_fetchExceptionCause),
|
||||
.io_enq_1_decoded_fetchExceptionTval (io_enq_1_decoded_fetchExceptionTval),
|
||||
.io_enq_1_prs1 (io_enq_1_prs1),
|
||||
.io_enq_1_prs2 (io_enq_1_prs2),
|
||||
.io_enq_1_src1Ready (io_enq_1_src1Ready),
|
||||
@@ -251,10 +313,20 @@ module IssueQueue(
|
||||
.io_issue_0_decoded_isWord (io_issue_0_decoded_isWord),
|
||||
.io_issue_0_decoded_isSystem (io_issue_0_decoded_isSystem),
|
||||
.io_issue_0_decoded_isFenceI (io_issue_0_decoded_isFenceI),
|
||||
.io_issue_0_decoded_isEcall (io_issue_0_decoded_isEcall),
|
||||
.io_issue_0_decoded_isEbreak (io_issue_0_decoded_isEbreak),
|
||||
.io_issue_0_decoded_isMret (io_issue_0_decoded_isMret),
|
||||
.io_issue_0_decoded_isSret (io_issue_0_decoded_isSret),
|
||||
.io_issue_0_decoded_isSfenceVma (io_issue_0_decoded_isSfenceVma),
|
||||
.io_issue_0_decoded_isXret (io_issue_0_decoded_isXret),
|
||||
.io_issue_0_decoded_isWfi (io_issue_0_decoded_isWfi),
|
||||
.io_issue_0_decoded_isAmo (io_issue_0_decoded_isAmo),
|
||||
.io_issue_0_decoded_amoOp (io_issue_0_decoded_amoOp),
|
||||
.io_issue_0_decoded_writesRd (io_issue_0_decoded_writesRd),
|
||||
.io_issue_0_decoded_illegal (io_issue_0_decoded_illegal),
|
||||
.io_issue_0_decoded_fetchException (io_issue_0_decoded_fetchException),
|
||||
.io_issue_0_decoded_fetchExceptionCause (io_issue_0_decoded_fetchExceptionCause),
|
||||
.io_issue_0_decoded_fetchExceptionTval (io_issue_0_decoded_fetchExceptionTval),
|
||||
.io_issue_0_prs1 (io_issue_0_prs1),
|
||||
.io_issue_0_prs2 (io_issue_0_prs2),
|
||||
.io_issue_0_prd (io_issue_0_prd),
|
||||
@@ -282,16 +354,28 @@ module IssueQueue(
|
||||
.io_issue_1_decoded_isWord (io_issue_1_decoded_isWord),
|
||||
.io_issue_1_decoded_isSystem (io_issue_1_decoded_isSystem),
|
||||
.io_issue_1_decoded_isFenceI (io_issue_1_decoded_isFenceI),
|
||||
.io_issue_1_decoded_isEcall (io_issue_1_decoded_isEcall),
|
||||
.io_issue_1_decoded_isEbreak (io_issue_1_decoded_isEbreak),
|
||||
.io_issue_1_decoded_isMret (io_issue_1_decoded_isMret),
|
||||
.io_issue_1_decoded_isSret (io_issue_1_decoded_isSret),
|
||||
.io_issue_1_decoded_isSfenceVma (io_issue_1_decoded_isSfenceVma),
|
||||
.io_issue_1_decoded_isXret (io_issue_1_decoded_isXret),
|
||||
.io_issue_1_decoded_isWfi (io_issue_1_decoded_isWfi),
|
||||
.io_issue_1_decoded_isAmo (io_issue_1_decoded_isAmo),
|
||||
.io_issue_1_decoded_amoOp (io_issue_1_decoded_amoOp),
|
||||
.io_issue_1_decoded_writesRd (io_issue_1_decoded_writesRd),
|
||||
.io_issue_1_decoded_illegal (io_issue_1_decoded_illegal),
|
||||
.io_issue_1_decoded_fetchException (io_issue_1_decoded_fetchException),
|
||||
.io_issue_1_decoded_fetchExceptionCause (io_issue_1_decoded_fetchExceptionCause),
|
||||
.io_issue_1_decoded_fetchExceptionTval (io_issue_1_decoded_fetchExceptionTval),
|
||||
.io_issue_1_prs1 (io_issue_1_prs1),
|
||||
.io_issue_1_prs2 (io_issue_1_prs2),
|
||||
.io_issue_1_prd (io_issue_1_prd),
|
||||
.io_issue_1_robIdx (io_issue_1_robIdx),
|
||||
.io_issueReady_0 (io_issueReady_0),
|
||||
.io_issueReady_1 (io_issueReady_1),
|
||||
.io_robHeadValid (io_robHeadValid),
|
||||
.io_robHeadIdx (io_robHeadIdx),
|
||||
.io_flush (io_flush)
|
||||
);
|
||||
endmodule
|
||||
|
||||
@@ -28,10 +28,20 @@ module IssueStage(
|
||||
io_in_0_decoded_isWord,
|
||||
io_in_0_decoded_isSystem,
|
||||
io_in_0_decoded_isFenceI,
|
||||
io_in_0_decoded_isEcall,
|
||||
io_in_0_decoded_isEbreak,
|
||||
io_in_0_decoded_isMret,
|
||||
io_in_0_decoded_isSret,
|
||||
io_in_0_decoded_isSfenceVma,
|
||||
io_in_0_decoded_isXret,
|
||||
io_in_0_decoded_isWfi,
|
||||
io_in_0_decoded_isAmo,
|
||||
input [4:0] io_in_0_decoded_amoOp,
|
||||
input io_in_0_decoded_writesRd,
|
||||
io_in_0_decoded_illegal,
|
||||
io_in_0_decoded_fetchException,
|
||||
input [63:0] io_in_0_decoded_fetchExceptionCause,
|
||||
io_in_0_decoded_fetchExceptionTval,
|
||||
input [5:0] io_in_0_prs1,
|
||||
io_in_0_prs2,
|
||||
input io_in_0_src1Ready,
|
||||
@@ -62,10 +72,20 @@ module IssueStage(
|
||||
io_in_1_decoded_isWord,
|
||||
io_in_1_decoded_isSystem,
|
||||
io_in_1_decoded_isFenceI,
|
||||
io_in_1_decoded_isEcall,
|
||||
io_in_1_decoded_isEbreak,
|
||||
io_in_1_decoded_isMret,
|
||||
io_in_1_decoded_isSret,
|
||||
io_in_1_decoded_isSfenceVma,
|
||||
io_in_1_decoded_isXret,
|
||||
io_in_1_decoded_isWfi,
|
||||
io_in_1_decoded_isAmo,
|
||||
input [4:0] io_in_1_decoded_amoOp,
|
||||
input io_in_1_decoded_writesRd,
|
||||
io_in_1_decoded_illegal,
|
||||
io_in_1_decoded_fetchException,
|
||||
input [63:0] io_in_1_decoded_fetchExceptionCause,
|
||||
io_in_1_decoded_fetchExceptionTval,
|
||||
input [5:0] io_in_1_prs1,
|
||||
io_in_1_prs2,
|
||||
input io_in_1_src1Ready,
|
||||
@@ -103,10 +123,20 @@ module IssueStage(
|
||||
io_out_0_decoded_isWord,
|
||||
io_out_0_decoded_isSystem,
|
||||
io_out_0_decoded_isFenceI,
|
||||
io_out_0_decoded_isEcall,
|
||||
io_out_0_decoded_isEbreak,
|
||||
io_out_0_decoded_isMret,
|
||||
io_out_0_decoded_isSret,
|
||||
io_out_0_decoded_isSfenceVma,
|
||||
io_out_0_decoded_isXret,
|
||||
io_out_0_decoded_isWfi,
|
||||
io_out_0_decoded_isAmo,
|
||||
output [4:0] io_out_0_decoded_amoOp,
|
||||
output io_out_0_decoded_writesRd,
|
||||
io_out_0_decoded_illegal,
|
||||
io_out_0_decoded_fetchException,
|
||||
output [63:0] io_out_0_decoded_fetchExceptionCause,
|
||||
io_out_0_decoded_fetchExceptionTval,
|
||||
output [5:0] io_out_0_prs1,
|
||||
io_out_0_prs2,
|
||||
io_out_0_prd,
|
||||
@@ -134,17 +164,29 @@ module IssueStage(
|
||||
io_out_1_decoded_isWord,
|
||||
io_out_1_decoded_isSystem,
|
||||
io_out_1_decoded_isFenceI,
|
||||
io_out_1_decoded_isEcall,
|
||||
io_out_1_decoded_isEbreak,
|
||||
io_out_1_decoded_isMret,
|
||||
io_out_1_decoded_isSret,
|
||||
io_out_1_decoded_isSfenceVma,
|
||||
io_out_1_decoded_isXret,
|
||||
io_out_1_decoded_isWfi,
|
||||
io_out_1_decoded_isAmo,
|
||||
output [4:0] io_out_1_decoded_amoOp,
|
||||
output io_out_1_decoded_writesRd,
|
||||
io_out_1_decoded_illegal,
|
||||
io_out_1_decoded_fetchException,
|
||||
output [63:0] io_out_1_decoded_fetchExceptionCause,
|
||||
io_out_1_decoded_fetchExceptionTval,
|
||||
output [5:0] io_out_1_prs1,
|
||||
io_out_1_prs2,
|
||||
io_out_1_prd,
|
||||
io_out_1_robIdx,
|
||||
input io_outReady_0,
|
||||
io_outReady_1,
|
||||
io_flush
|
||||
io_robHeadValid,
|
||||
input [5:0] io_robHeadIdx,
|
||||
input io_flush
|
||||
);
|
||||
|
||||
IssueQueue queue (
|
||||
@@ -176,10 +218,20 @@ module IssueStage(
|
||||
.io_enq_0_decoded_isWord (io_in_0_decoded_isWord),
|
||||
.io_enq_0_decoded_isSystem (io_in_0_decoded_isSystem),
|
||||
.io_enq_0_decoded_isFenceI (io_in_0_decoded_isFenceI),
|
||||
.io_enq_0_decoded_isEcall (io_in_0_decoded_isEcall),
|
||||
.io_enq_0_decoded_isEbreak (io_in_0_decoded_isEbreak),
|
||||
.io_enq_0_decoded_isMret (io_in_0_decoded_isMret),
|
||||
.io_enq_0_decoded_isSret (io_in_0_decoded_isSret),
|
||||
.io_enq_0_decoded_isSfenceVma (io_in_0_decoded_isSfenceVma),
|
||||
.io_enq_0_decoded_isXret (io_in_0_decoded_isXret),
|
||||
.io_enq_0_decoded_isWfi (io_in_0_decoded_isWfi),
|
||||
.io_enq_0_decoded_isAmo (io_in_0_decoded_isAmo),
|
||||
.io_enq_0_decoded_amoOp (io_in_0_decoded_amoOp),
|
||||
.io_enq_0_decoded_writesRd (io_in_0_decoded_writesRd),
|
||||
.io_enq_0_decoded_illegal (io_in_0_decoded_illegal),
|
||||
.io_enq_0_decoded_fetchException (io_in_0_decoded_fetchException),
|
||||
.io_enq_0_decoded_fetchExceptionCause (io_in_0_decoded_fetchExceptionCause),
|
||||
.io_enq_0_decoded_fetchExceptionTval (io_in_0_decoded_fetchExceptionTval),
|
||||
.io_enq_0_prs1 (io_in_0_prs1),
|
||||
.io_enq_0_prs2 (io_in_0_prs2),
|
||||
.io_enq_0_src1Ready (io_in_0_src1Ready),
|
||||
@@ -210,10 +262,20 @@ module IssueStage(
|
||||
.io_enq_1_decoded_isWord (io_in_1_decoded_isWord),
|
||||
.io_enq_1_decoded_isSystem (io_in_1_decoded_isSystem),
|
||||
.io_enq_1_decoded_isFenceI (io_in_1_decoded_isFenceI),
|
||||
.io_enq_1_decoded_isEcall (io_in_1_decoded_isEcall),
|
||||
.io_enq_1_decoded_isEbreak (io_in_1_decoded_isEbreak),
|
||||
.io_enq_1_decoded_isMret (io_in_1_decoded_isMret),
|
||||
.io_enq_1_decoded_isSret (io_in_1_decoded_isSret),
|
||||
.io_enq_1_decoded_isSfenceVma (io_in_1_decoded_isSfenceVma),
|
||||
.io_enq_1_decoded_isXret (io_in_1_decoded_isXret),
|
||||
.io_enq_1_decoded_isWfi (io_in_1_decoded_isWfi),
|
||||
.io_enq_1_decoded_isAmo (io_in_1_decoded_isAmo),
|
||||
.io_enq_1_decoded_amoOp (io_in_1_decoded_amoOp),
|
||||
.io_enq_1_decoded_writesRd (io_in_1_decoded_writesRd),
|
||||
.io_enq_1_decoded_illegal (io_in_1_decoded_illegal),
|
||||
.io_enq_1_decoded_fetchException (io_in_1_decoded_fetchException),
|
||||
.io_enq_1_decoded_fetchExceptionCause (io_in_1_decoded_fetchExceptionCause),
|
||||
.io_enq_1_decoded_fetchExceptionTval (io_in_1_decoded_fetchExceptionTval),
|
||||
.io_enq_1_prs1 (io_in_1_prs1),
|
||||
.io_enq_1_prs2 (io_in_1_prs2),
|
||||
.io_enq_1_src1Ready (io_in_1_src1Ready),
|
||||
@@ -251,10 +313,20 @@ module IssueStage(
|
||||
.io_issue_0_decoded_isWord (io_out_0_decoded_isWord),
|
||||
.io_issue_0_decoded_isSystem (io_out_0_decoded_isSystem),
|
||||
.io_issue_0_decoded_isFenceI (io_out_0_decoded_isFenceI),
|
||||
.io_issue_0_decoded_isEcall (io_out_0_decoded_isEcall),
|
||||
.io_issue_0_decoded_isEbreak (io_out_0_decoded_isEbreak),
|
||||
.io_issue_0_decoded_isMret (io_out_0_decoded_isMret),
|
||||
.io_issue_0_decoded_isSret (io_out_0_decoded_isSret),
|
||||
.io_issue_0_decoded_isSfenceVma (io_out_0_decoded_isSfenceVma),
|
||||
.io_issue_0_decoded_isXret (io_out_0_decoded_isXret),
|
||||
.io_issue_0_decoded_isWfi (io_out_0_decoded_isWfi),
|
||||
.io_issue_0_decoded_isAmo (io_out_0_decoded_isAmo),
|
||||
.io_issue_0_decoded_amoOp (io_out_0_decoded_amoOp),
|
||||
.io_issue_0_decoded_writesRd (io_out_0_decoded_writesRd),
|
||||
.io_issue_0_decoded_illegal (io_out_0_decoded_illegal),
|
||||
.io_issue_0_decoded_fetchException (io_out_0_decoded_fetchException),
|
||||
.io_issue_0_decoded_fetchExceptionCause (io_out_0_decoded_fetchExceptionCause),
|
||||
.io_issue_0_decoded_fetchExceptionTval (io_out_0_decoded_fetchExceptionTval),
|
||||
.io_issue_0_prs1 (io_out_0_prs1),
|
||||
.io_issue_0_prs2 (io_out_0_prs2),
|
||||
.io_issue_0_prd (io_out_0_prd),
|
||||
@@ -282,16 +354,28 @@ module IssueStage(
|
||||
.io_issue_1_decoded_isWord (io_out_1_decoded_isWord),
|
||||
.io_issue_1_decoded_isSystem (io_out_1_decoded_isSystem),
|
||||
.io_issue_1_decoded_isFenceI (io_out_1_decoded_isFenceI),
|
||||
.io_issue_1_decoded_isEcall (io_out_1_decoded_isEcall),
|
||||
.io_issue_1_decoded_isEbreak (io_out_1_decoded_isEbreak),
|
||||
.io_issue_1_decoded_isMret (io_out_1_decoded_isMret),
|
||||
.io_issue_1_decoded_isSret (io_out_1_decoded_isSret),
|
||||
.io_issue_1_decoded_isSfenceVma (io_out_1_decoded_isSfenceVma),
|
||||
.io_issue_1_decoded_isXret (io_out_1_decoded_isXret),
|
||||
.io_issue_1_decoded_isWfi (io_out_1_decoded_isWfi),
|
||||
.io_issue_1_decoded_isAmo (io_out_1_decoded_isAmo),
|
||||
.io_issue_1_decoded_amoOp (io_out_1_decoded_amoOp),
|
||||
.io_issue_1_decoded_writesRd (io_out_1_decoded_writesRd),
|
||||
.io_issue_1_decoded_illegal (io_out_1_decoded_illegal),
|
||||
.io_issue_1_decoded_fetchException (io_out_1_decoded_fetchException),
|
||||
.io_issue_1_decoded_fetchExceptionCause (io_out_1_decoded_fetchExceptionCause),
|
||||
.io_issue_1_decoded_fetchExceptionTval (io_out_1_decoded_fetchExceptionTval),
|
||||
.io_issue_1_prs1 (io_out_1_prs1),
|
||||
.io_issue_1_prs2 (io_out_1_prs2),
|
||||
.io_issue_1_prd (io_out_1_prd),
|
||||
.io_issue_1_robIdx (io_out_1_robIdx),
|
||||
.io_issueReady_0 (io_outReady_0),
|
||||
.io_issueReady_1 (io_outReady_1),
|
||||
.io_robHeadValid (io_robHeadValid),
|
||||
.io_robHeadIdx (io_robHeadIdx),
|
||||
.io_flush (io_flush)
|
||||
);
|
||||
endmodule
|
||||
|
||||
@@ -10,6 +10,10 @@ module LSU(
|
||||
io_req_isAmo,
|
||||
input [4:0] io_req_amoOp,
|
||||
input [2:0] io_req_size,
|
||||
input io_checkOnly,
|
||||
io_sfenceVma,
|
||||
input [1:0] io_currentPriv,
|
||||
input [63:0] io_mstatus,
|
||||
output io_reqReady,
|
||||
input [63:0] io_satp,
|
||||
output io_dmemReqValid,
|
||||
@@ -21,7 +25,10 @@ module LSU(
|
||||
input [63:0] io_dmemRespData,
|
||||
output io_respValid,
|
||||
output [63:0] io_respData,
|
||||
output io_pageFault
|
||||
output io_pageFault,
|
||||
io_misaligned,
|
||||
output [63:0] io_faultCause,
|
||||
io_faultAddr
|
||||
);
|
||||
|
||||
wire _dcache_io_reqReady;
|
||||
@@ -37,26 +44,96 @@ module LSU(
|
||||
wire _mmu_io_refill_valid;
|
||||
wire [26:0] _mmu_io_refill_vpn;
|
||||
wire [43:0] _mmu_io_refill_ppn;
|
||||
wire [1:0] _mmu_io_refill_level;
|
||||
wire [7:0] _mmu_io_refill_flags;
|
||||
wire _dtlb_io_resp_hit;
|
||||
wire _dtlb_io_resp_miss;
|
||||
wire [63:0] _dtlb_io_resp_paddr;
|
||||
wire _dtlb_io_resp_pageFault;
|
||||
wire [1:0] effectivePriv =
|
||||
(&io_currentPriv) & io_mstatus[17] ? io_mstatus[12:11] : io_currentPriv;
|
||||
reg pendingValid;
|
||||
reg [63:0] pendingReq_addr;
|
||||
reg [63:0] pendingReq_data;
|
||||
reg pendingReq_isStore;
|
||||
reg pendingReq_isSigned;
|
||||
reg pendingReq_isAmo;
|
||||
reg [4:0] pendingReq_amoOp;
|
||||
reg [2:0] pendingReq_size;
|
||||
reg pendingCheckOnly;
|
||||
reg [1:0] pendingPriv;
|
||||
reg [63:0] pendingMstatus;
|
||||
reg [63:0] pendingSatp;
|
||||
wire io_reqReady_0 = _dcache_io_reqReady & ~pendingValid;
|
||||
wire acceptCurrent = io_reqValid & io_reqReady_0;
|
||||
wire activeValid = pendingValid | acceptCurrent;
|
||||
wire [2:0] activeReq_size = pendingValid ? pendingReq_size : io_req_size;
|
||||
wire activeReq_isStore = pendingValid ? pendingReq_isStore : io_req_isStore;
|
||||
wire [63:0] io_faultAddr_0 = pendingValid ? pendingReq_addr : io_req_addr;
|
||||
wire activeCheckOnly = pendingValid ? pendingCheckOnly : io_checkOnly;
|
||||
wire [1:0] activePriv = pendingValid ? pendingPriv : effectivePriv;
|
||||
wire [1:0] activeMstatus = pendingValid ? pendingMstatus[19:18] : io_mstatus[19:18];
|
||||
wire [63:0] activeSatp = pendingValid ? pendingSatp : io_satp;
|
||||
wire translate = (|(activeSatp[63:60])) & activePriv != 2'h3;
|
||||
wire dtlb_io_req_valid = activeValid & translate;
|
||||
reg ptwOutstanding;
|
||||
wire ptwReqFire = _mmu_io_ptwMemReq_valid & ~ptwOutstanding;
|
||||
wire ptwRespFire = io_dmemRespValid & (ptwOutstanding | ptwReqFire);
|
||||
wire translationReady = ~translate | _dtlb_io_resp_hit;
|
||||
wire translationFault = _dtlb_io_resp_pageFault | _mmu_io_resp_pageFault;
|
||||
wire misaligned =
|
||||
activeValid
|
||||
& (|((activeReq_size == 3'h3
|
||||
? 3'h0
|
||||
: activeReq_size == 3'h2
|
||||
? 3'h4
|
||||
: activeReq_size == 3'h1 ? 3'h2 : {2'h0, activeReq_size == 3'h0}) - 3'h1
|
||||
& io_faultAddr_0[2:0]));
|
||||
wire newFault = activeValid & (translationFault | misaligned);
|
||||
wire checkOnlyDispatch =
|
||||
activeValid & activeCheckOnly & translationReady & ~translationFault & ~misaligned;
|
||||
wire dcacheDispatch =
|
||||
activeValid & ~activeCheckOnly & translationReady & ~translationFault & ~misaligned
|
||||
& _dcache_io_reqReady;
|
||||
wire storeComplete = dcacheDispatch & activeReq_isStore | checkOnlyDispatch;
|
||||
always @(posedge clock) begin
|
||||
if (reset)
|
||||
automatic logic latchPending;
|
||||
automatic logic clearPending;
|
||||
latchPending = acceptCurrent & ~dcacheDispatch & ~newFault;
|
||||
clearPending = pendingValid & (dcacheDispatch | checkOnlyDispatch | newFault);
|
||||
if (reset) begin
|
||||
pendingValid <= 1'h0;
|
||||
ptwOutstanding <= 1'h0;
|
||||
else
|
||||
ptwOutstanding <=
|
||||
_mmu_io_ptwMemReq_valid | ~(io_dmemRespValid & ptwOutstanding) & ptwOutstanding;
|
||||
end
|
||||
else begin
|
||||
pendingValid <= ~clearPending & (latchPending | pendingValid);
|
||||
ptwOutstanding <= ~ptwRespFire & (ptwReqFire | ptwOutstanding);
|
||||
end
|
||||
if (clearPending | ~latchPending) begin
|
||||
end
|
||||
else begin
|
||||
pendingReq_addr <= io_req_addr;
|
||||
pendingReq_data <= io_req_data;
|
||||
pendingReq_isStore <= io_req_isStore;
|
||||
pendingReq_isSigned <= io_req_isSigned;
|
||||
pendingReq_isAmo <= io_req_isAmo;
|
||||
pendingReq_amoOp <= io_req_amoOp;
|
||||
pendingReq_size <= io_req_size;
|
||||
pendingCheckOnly <= io_checkOnly;
|
||||
pendingPriv <= effectivePriv;
|
||||
pendingMstatus <= io_mstatus;
|
||||
pendingSatp <= io_satp;
|
||||
end
|
||||
end // always @(posedge)
|
||||
DTLB dtlb (
|
||||
.clock (clock),
|
||||
.reset (reset),
|
||||
.io_req_valid (io_reqValid & (|(io_satp[63:60]))),
|
||||
.io_req_vaddr (io_req_addr),
|
||||
.io_req_isStore (io_req_isStore),
|
||||
.io_req_valid (dtlb_io_req_valid),
|
||||
.io_req_vaddr (io_faultAddr_0),
|
||||
.io_req_isStore (activeReq_isStore),
|
||||
.io_req_priv (activePriv),
|
||||
.io_req_sum (activeMstatus[0]),
|
||||
.io_req_mxr (activeMstatus[1]),
|
||||
.io_resp_hit (_dtlb_io_resp_hit),
|
||||
.io_resp_miss (_dtlb_io_resp_miss),
|
||||
.io_resp_paddr (_dtlb_io_resp_paddr),
|
||||
@@ -64,56 +141,68 @@ module LSU(
|
||||
.io_refill_valid (_mmu_io_refill_valid),
|
||||
.io_refill_vpn (_mmu_io_refill_vpn),
|
||||
.io_refill_ppn (_mmu_io_refill_ppn),
|
||||
.io_refill_flags (_mmu_io_refill_flags)
|
||||
.io_refill_level (_mmu_io_refill_level),
|
||||
.io_refill_flags (_mmu_io_refill_flags),
|
||||
.io_flush (io_sfenceVma)
|
||||
);
|
||||
MMU mmu (
|
||||
.clock (clock),
|
||||
.reset (reset),
|
||||
.io_satp (io_satp),
|
||||
.io_req_valid (io_reqValid & (|(io_satp[63:60])) & _dtlb_io_resp_miss),
|
||||
.io_req_vaddr (io_req_addr),
|
||||
.io_req_isStore (io_req_isStore),
|
||||
.io_satp (activeSatp),
|
||||
.io_req_valid (dtlb_io_req_valid & _dtlb_io_resp_miss),
|
||||
.io_req_vaddr (io_faultAddr_0),
|
||||
.io_req_isStore (activeReq_isStore),
|
||||
.io_req_isFetch (1'h0),
|
||||
.io_req_priv (activePriv),
|
||||
.io_req_sum (activeMstatus[0]),
|
||||
.io_req_mxr (activeMstatus[1]),
|
||||
.io_resp_pageFault (_mmu_io_resp_pageFault),
|
||||
.io_ptwMemReq_valid (_mmu_io_ptwMemReq_valid),
|
||||
.io_ptwMemReq_addr (_mmu_io_ptwMemReq_addr),
|
||||
.io_ptwMemResp_valid (io_dmemRespValid & ptwOutstanding),
|
||||
.io_ptwMemResp_valid (ptwRespFire),
|
||||
.io_ptwMemResp_data (io_dmemRespData),
|
||||
.io_refill_valid (_mmu_io_refill_valid),
|
||||
.io_refill_vpn (_mmu_io_refill_vpn),
|
||||
.io_refill_ppn (_mmu_io_refill_ppn),
|
||||
.io_refill_level (_mmu_io_refill_level),
|
||||
.io_refill_flags (_mmu_io_refill_flags)
|
||||
);
|
||||
DCache dcache (
|
||||
.clock (clock),
|
||||
.reset (reset),
|
||||
.io_reqValid
|
||||
(io_reqValid & (~(|(io_satp[63:60])) | _dtlb_io_resp_hit) & ~translationFault),
|
||||
.io_req_addr ((|(io_satp[63:60])) ? _dtlb_io_resp_paddr : io_req_addr),
|
||||
.io_req_data (io_req_data),
|
||||
.io_req_isStore (io_req_isStore),
|
||||
.io_req_isSigned (io_req_isSigned),
|
||||
.io_req_isAmo (io_req_isAmo),
|
||||
.io_req_amoOp (io_req_amoOp),
|
||||
.io_req_size (io_req_size),
|
||||
.io_reqValid (dcacheDispatch),
|
||||
.io_req_addr (translate ? _dtlb_io_resp_paddr : io_faultAddr_0),
|
||||
.io_req_data (pendingValid ? pendingReq_data : io_req_data),
|
||||
.io_req_isStore (activeReq_isStore),
|
||||
.io_req_isSigned (pendingValid ? pendingReq_isSigned : io_req_isSigned),
|
||||
.io_req_isAmo (pendingValid ? pendingReq_isAmo : io_req_isAmo),
|
||||
.io_req_amoOp (pendingValid ? pendingReq_amoOp : io_req_amoOp),
|
||||
.io_req_size (activeReq_size),
|
||||
.io_reqReady (_dcache_io_reqReady),
|
||||
.io_memReqValid (_dcache_io_memReqValid),
|
||||
.io_memReq_addr (_dcache_io_memReq_addr),
|
||||
.io_memReq_data (_dcache_io_memReq_data),
|
||||
.io_memReq_isStore (_dcache_io_memReq_isStore),
|
||||
.io_memReq_size (_dcache_io_memReq_size),
|
||||
.io_memRespValid (io_dmemRespValid & ~ptwOutstanding),
|
||||
.io_memRespValid (io_dmemRespValid & ~ptwOutstanding & ~ptwReqFire),
|
||||
.io_memRespData (io_dmemRespData),
|
||||
.io_respValid (_dcache_io_respValid),
|
||||
.io_respData (io_respData)
|
||||
);
|
||||
assign io_reqReady = _dcache_io_reqReady & ~ptwOutstanding;
|
||||
assign io_dmemReqValid = _mmu_io_ptwMemReq_valid | _dcache_io_memReqValid;
|
||||
assign io_dmemReq_addr =
|
||||
_mmu_io_ptwMemReq_valid ? _mmu_io_ptwMemReq_addr : _dcache_io_memReq_addr;
|
||||
assign io_dmemReq_data = _mmu_io_ptwMemReq_valid ? 64'h0 : _dcache_io_memReq_data;
|
||||
assign io_dmemReq_isStore = ~_mmu_io_ptwMemReq_valid & _dcache_io_memReq_isStore;
|
||||
assign io_dmemReq_size = _mmu_io_ptwMemReq_valid ? 3'h3 : _dcache_io_memReq_size;
|
||||
assign io_respValid = _dcache_io_respValid | translationFault;
|
||||
assign io_reqReady = io_reqReady_0;
|
||||
assign io_dmemReqValid = ptwReqFire | _dcache_io_memReqValid;
|
||||
assign io_dmemReq_addr = ptwReqFire ? _mmu_io_ptwMemReq_addr : _dcache_io_memReq_addr;
|
||||
assign io_dmemReq_data = ptwReqFire ? 64'h0 : _dcache_io_memReq_data;
|
||||
assign io_dmemReq_isStore = ~ptwReqFire & _dcache_io_memReq_isStore;
|
||||
assign io_dmemReq_size = ptwReqFire ? 3'h3 : _dcache_io_memReq_size;
|
||||
assign io_respValid = _dcache_io_respValid | newFault | storeComplete;
|
||||
assign io_pageFault = translationFault;
|
||||
assign io_misaligned = misaligned;
|
||||
assign io_faultCause =
|
||||
{56'h0,
|
||||
misaligned
|
||||
? {6'h1, activeReq_isStore, 1'h0}
|
||||
: {4'h0, translationFault, 1'h1, activeReq_isStore, 1'h1}};
|
||||
assign io_faultAddr = io_faultAddr_0;
|
||||
endmodule
|
||||
|
||||
|
||||
@@ -6,6 +6,10 @@ module MMU(
|
||||
input io_req_valid,
|
||||
input [63:0] io_req_vaddr,
|
||||
input io_req_isStore,
|
||||
io_req_isFetch,
|
||||
input [1:0] io_req_priv,
|
||||
input io_req_sum,
|
||||
io_req_mxr,
|
||||
output io_resp_pageFault,
|
||||
io_ptwMemReq_valid,
|
||||
output [63:0] io_ptwMemReq_addr,
|
||||
@@ -14,6 +18,7 @@ module MMU(
|
||||
output io_refill_valid,
|
||||
output [26:0] io_refill_vpn,
|
||||
output [43:0] io_refill_ppn,
|
||||
output [1:0] io_refill_level,
|
||||
output [7:0] io_refill_flags
|
||||
);
|
||||
|
||||
@@ -25,6 +30,10 @@ module MMU(
|
||||
.io_reqValid (io_req_valid & (|(io_satp[63:60]))),
|
||||
.io_reqVpn (io_req_vaddr[38:12]),
|
||||
.io_isStore (io_req_isStore),
|
||||
.io_isFetch (io_req_isFetch),
|
||||
.io_priv (io_req_priv),
|
||||
.io_sum (io_req_sum),
|
||||
.io_mxr (io_req_mxr),
|
||||
.io_satp (io_satp),
|
||||
.io_memReq_valid (io_ptwMemReq_valid),
|
||||
.io_memReq_addr (io_ptwMemReq_addr),
|
||||
@@ -34,6 +43,7 @@ module MMU(
|
||||
.io_refill_valid (io_refill_valid),
|
||||
.io_refill_vpn (io_refill_vpn),
|
||||
.io_refill_ppn (io_refill_ppn),
|
||||
.io_refill_level (io_refill_level),
|
||||
.io_refill_flags (io_refill_flags),
|
||||
.io_pageFault (_walker_io_pageFault)
|
||||
);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,10 @@ module PageTableWalker(
|
||||
io_reqValid,
|
||||
input [26:0] io_reqVpn,
|
||||
input io_isStore,
|
||||
io_isFetch,
|
||||
input [1:0] io_priv,
|
||||
input io_sum,
|
||||
io_mxr,
|
||||
input [63:0] io_satp,
|
||||
output io_memReq_valid,
|
||||
output [63:0] io_memReq_addr,
|
||||
@@ -14,6 +18,7 @@ module PageTableWalker(
|
||||
io_refill_valid,
|
||||
output [26:0] io_refill_vpn,
|
||||
output [43:0] io_refill_ppn,
|
||||
output [1:0] io_refill_level,
|
||||
output [7:0] io_refill_flags,
|
||||
output io_pageFault
|
||||
);
|
||||
@@ -21,20 +26,28 @@ module PageTableWalker(
|
||||
reg [2:0] state;
|
||||
reg [26:0] vpnReg;
|
||||
reg isStoreReg;
|
||||
reg walkFault;
|
||||
reg [43:0] nextPpn;
|
||||
reg isFetchReg;
|
||||
reg [1:0] privReg;
|
||||
reg sumReg;
|
||||
reg mxrReg;
|
||||
wire _io_memReq_addr_T = state == 3'h1;
|
||||
wire _io_memReq_addr_T_1 = state == 3'h2;
|
||||
reg walkFault;
|
||||
reg [43:0] nextPpn;
|
||||
reg [7:0] leafFlagsReg;
|
||||
reg [1:0] leafLevelReg;
|
||||
reg [43:0] curPpn;
|
||||
wire _io_memReq_valid_T_3 = state == 3'h3;
|
||||
wire io_respValid_0 = state == 3'h4;
|
||||
always @(posedge clock) begin
|
||||
automatic logic [1:0] level;
|
||||
automatic logic pteIsLeaf;
|
||||
automatic logic invalidPte;
|
||||
automatic logic _GEN;
|
||||
automatic logic _GEN_0;
|
||||
automatic logic _GEN_1;
|
||||
automatic logic _GEN_2;
|
||||
level = _io_memReq_addr_T ? 2'h2 : {1'h0, _io_memReq_addr_T_1};
|
||||
pteIsLeaf = io_memResp_data[1] | io_memResp_data[3];
|
||||
invalidPte = ~(io_memResp_data[0]) | ~(io_memResp_data[1]) & io_memResp_data[2];
|
||||
_GEN = state == 3'h0;
|
||||
@@ -60,25 +73,36 @@ module PageTableWalker(
|
||||
& (_GEN_1
|
||||
? invalidPte
|
||||
| (pteIsLeaf
|
||||
? (isStoreReg
|
||||
? ~(io_memResp_data[2]) | ~(io_memResp_data[7])
|
||||
: ~(io_memResp_data[1])) | ~(io_memResp_data[6]) | walkFault
|
||||
? privReg == 2'h1 & io_memResp_data[4] & (isFetchReg | ~sumReg)
|
||||
| privReg == 2'h0 & ~(io_memResp_data[4])
|
||||
| ~(isFetchReg
|
||||
? io_memResp_data[3]
|
||||
: isStoreReg
|
||||
? io_memResp_data[2] & io_memResp_data[7]
|
||||
: io_memResp_data[1] | mxrReg & io_memResp_data[3])
|
||||
| ~(io_memResp_data[6]) | level == 2'h2
|
||||
& (|(io_memResp_data[27:10])) | level == 2'h1
|
||||
& (|(io_memResp_data[18:10])) | walkFault
|
||||
: ~_GEN_0 | walkFault)
|
||||
: walkFault);
|
||||
end
|
||||
if (_GEN & io_reqValid) begin
|
||||
vpnReg <= io_reqVpn;
|
||||
isStoreReg <= io_isStore;
|
||||
isFetchReg <= io_isFetch;
|
||||
privReg <= io_priv;
|
||||
sumReg <= io_sum;
|
||||
mxrReg <= io_mxr;
|
||||
end
|
||||
if (_GEN | ~_GEN_1 | invalidPte | ~pteIsLeaf) begin
|
||||
end
|
||||
else begin
|
||||
automatic logic [1:0] level =
|
||||
_io_memReq_addr_T ? 2'h2 : {1'h0, _io_memReq_addr_T_1};
|
||||
nextPpn <=
|
||||
{io_memResp_data[53:28],
|
||||
level[1] ? vpnReg[17:9] : io_memResp_data[27:19],
|
||||
level == 2'h0 ? io_memResp_data[18:10] : vpnReg[8:0]};
|
||||
leafFlagsReg <= io_memResp_data[7:0];
|
||||
leafLevelReg <= level;
|
||||
end
|
||||
if (_GEN | ~_GEN_1 | _GEN_2) begin
|
||||
end
|
||||
@@ -96,7 +120,8 @@ module PageTableWalker(
|
||||
assign io_refill_valid = io_respValid_0 & ~walkFault;
|
||||
assign io_refill_vpn = vpnReg;
|
||||
assign io_refill_ppn = nextPpn;
|
||||
assign io_refill_flags = io_memResp_data[7:0];
|
||||
assign io_refill_level = leafLevelReg;
|
||||
assign io_refill_flags = leafFlagsReg;
|
||||
assign io_pageFault = walkFault;
|
||||
endmodule
|
||||
|
||||
|
||||
19
generated-ooo/PrivilegeControl.sv
Normal file
19
generated-ooo/PrivilegeControl.sv
Normal file
@@ -0,0 +1,19 @@
|
||||
// Generated by CIRCT firtool-1.139.0
|
||||
module PrivilegeControl(
|
||||
input clock,
|
||||
reset,
|
||||
input [1:0] io_nextPriv,
|
||||
input io_setPriv,
|
||||
output [1:0] io_priv
|
||||
);
|
||||
|
||||
reg [1:0] privReg;
|
||||
always @(posedge clock) begin
|
||||
if (reset)
|
||||
privReg <= 2'h3;
|
||||
else if (io_setPriv)
|
||||
privReg <= io_nextPriv;
|
||||
end // always @(posedge)
|
||||
assign io_priv = privReg;
|
||||
endmodule
|
||||
|
||||
7911
generated-ooo/ROB.sv
7911
generated-ooo/ROB.sv
File diff suppressed because it is too large
Load Diff
@@ -30,11 +30,21 @@ module RenameStage(
|
||||
io_in_0_isWord,
|
||||
io_in_0_isSystem,
|
||||
io_in_0_isFenceI,
|
||||
io_in_0_isEcall,
|
||||
io_in_0_isEbreak,
|
||||
io_in_0_isMret,
|
||||
io_in_0_isSret,
|
||||
io_in_0_isSfenceVma,
|
||||
io_in_0_isXret,
|
||||
io_in_0_isWfi,
|
||||
io_in_0_isAmo,
|
||||
input [4:0] io_in_0_amoOp,
|
||||
input io_in_0_writesRd,
|
||||
io_in_0_illegal,
|
||||
input [63:0] io_in_1_pc,
|
||||
io_in_0_fetchException,
|
||||
input [63:0] io_in_0_fetchExceptionCause,
|
||||
io_in_0_fetchExceptionTval,
|
||||
io_in_1_pc,
|
||||
input [31:0] io_in_1_inst,
|
||||
input [4:0] io_in_1_rs1,
|
||||
io_in_1_rs2,
|
||||
@@ -60,10 +70,20 @@ module RenameStage(
|
||||
io_in_1_isWord,
|
||||
io_in_1_isSystem,
|
||||
io_in_1_isFenceI,
|
||||
io_in_1_isEcall,
|
||||
io_in_1_isEbreak,
|
||||
io_in_1_isMret,
|
||||
io_in_1_isSret,
|
||||
io_in_1_isSfenceVma,
|
||||
io_in_1_isXret,
|
||||
io_in_1_isWfi,
|
||||
io_in_1_isAmo,
|
||||
input [4:0] io_in_1_amoOp,
|
||||
input io_in_1_writesRd,
|
||||
io_in_1_illegal,
|
||||
io_in_1_fetchException,
|
||||
input [63:0] io_in_1_fetchExceptionCause,
|
||||
io_in_1_fetchExceptionTval,
|
||||
output io_outValid_0,
|
||||
io_outValid_1,
|
||||
output [63:0] io_out_0_decoded_pc,
|
||||
@@ -90,10 +110,20 @@ module RenameStage(
|
||||
io_out_0_decoded_isWord,
|
||||
io_out_0_decoded_isSystem,
|
||||
io_out_0_decoded_isFenceI,
|
||||
io_out_0_decoded_isEcall,
|
||||
io_out_0_decoded_isEbreak,
|
||||
io_out_0_decoded_isMret,
|
||||
io_out_0_decoded_isSret,
|
||||
io_out_0_decoded_isSfenceVma,
|
||||
io_out_0_decoded_isXret,
|
||||
io_out_0_decoded_isWfi,
|
||||
io_out_0_decoded_isAmo,
|
||||
output [4:0] io_out_0_decoded_amoOp,
|
||||
output io_out_0_decoded_writesRd,
|
||||
io_out_0_decoded_illegal,
|
||||
io_out_0_decoded_fetchException,
|
||||
output [63:0] io_out_0_decoded_fetchExceptionCause,
|
||||
io_out_0_decoded_fetchExceptionTval,
|
||||
output [5:0] io_out_0_prs1,
|
||||
io_out_0_prs2,
|
||||
output io_out_0_src1Ready,
|
||||
@@ -124,10 +154,20 @@ module RenameStage(
|
||||
io_out_1_decoded_isWord,
|
||||
io_out_1_decoded_isSystem,
|
||||
io_out_1_decoded_isFenceI,
|
||||
io_out_1_decoded_isEcall,
|
||||
io_out_1_decoded_isEbreak,
|
||||
io_out_1_decoded_isMret,
|
||||
io_out_1_decoded_isSret,
|
||||
io_out_1_decoded_isSfenceVma,
|
||||
io_out_1_decoded_isXret,
|
||||
io_out_1_decoded_isWfi,
|
||||
io_out_1_decoded_isAmo,
|
||||
output [4:0] io_out_1_decoded_amoOp,
|
||||
output io_out_1_decoded_writesRd,
|
||||
io_out_1_decoded_illegal,
|
||||
io_out_1_decoded_fetchException,
|
||||
output [63:0] io_out_1_decoded_fetchExceptionCause,
|
||||
io_out_1_decoded_fetchExceptionTval,
|
||||
output [5:0] io_out_1_prs1,
|
||||
io_out_1_prs2,
|
||||
output io_out_1_src1Ready,
|
||||
@@ -163,11 +203,21 @@ module RenameStage(
|
||||
io_completeCsrRs1_1,
|
||||
input [4:0] io_completeCsrZimm_0,
|
||||
io_completeCsrZimm_1,
|
||||
input io_commitReady_0,
|
||||
input io_completeFenceI_0,
|
||||
io_completeFenceI_1,
|
||||
io_completeSfenceVma_0,
|
||||
io_completeSfenceVma_1,
|
||||
io_completeXret_0,
|
||||
io_completeXret_1,
|
||||
io_completeXretIsMret_0,
|
||||
io_completeXretIsMret_1,
|
||||
io_commitReady_0,
|
||||
io_commitReady_1,
|
||||
output io_commitValid_0,
|
||||
io_commitValid_1,
|
||||
io_commitEntry_0_valid,
|
||||
output [5:0] io_commitEntry_0_robIdx,
|
||||
output [63:0] io_commitEntry_0_pc,
|
||||
output [4:0] io_commitEntry_0_archDest,
|
||||
output io_commitEntry_0_writesDest,
|
||||
output [3:0] io_commitEntry_0_opClass,
|
||||
@@ -184,7 +234,11 @@ module RenameStage(
|
||||
output [63:0] io_commitEntry_0_csrRs1,
|
||||
output [4:0] io_commitEntry_0_csrZimm,
|
||||
output io_commitEntry_0_fenceI,
|
||||
io_commitEntry_0_sfenceVma,
|
||||
io_commitEntry_0_xret,
|
||||
io_commitEntry_0_xretIsMret,
|
||||
output [5:0] io_commitEntry_1_robIdx,
|
||||
output [63:0] io_commitEntry_1_pc,
|
||||
output [4:0] io_commitEntry_1_archDest,
|
||||
output io_commitEntry_1_writesDest,
|
||||
output [3:0] io_commitEntry_1_opClass,
|
||||
@@ -201,6 +255,9 @@ module RenameStage(
|
||||
output [63:0] io_commitEntry_1_csrRs1,
|
||||
output [4:0] io_commitEntry_1_csrZimm,
|
||||
output io_commitEntry_1_fenceI,
|
||||
io_commitEntry_1_sfenceVma,
|
||||
io_commitEntry_1_xret,
|
||||
io_commitEntry_1_xretIsMret,
|
||||
input io_commitMapValid_0,
|
||||
io_commitMapValid_1,
|
||||
input [4:0] io_commitArch_0,
|
||||
@@ -893,18 +950,26 @@ module RenameStage(
|
||||
.reset (reset),
|
||||
.io_allocateValid_0 (e_valid),
|
||||
.io_allocateValid_1 (e_1_valid),
|
||||
.io_allocateEntry_0_pc (io_in_0_pc),
|
||||
.io_allocateEntry_0_archDest (io_in_0_rd),
|
||||
.io_allocateEntry_0_writesDest (io_in_0_writesRd),
|
||||
.io_allocateEntry_0_opClass (io_in_0_opClass),
|
||||
.io_allocateEntry_0_dest (e_dest),
|
||||
.io_allocateEntry_0_oldDest (_table_io_oldPrd_0),
|
||||
.io_allocateEntry_0_fenceI (io_in_0_isFenceI),
|
||||
.io_allocateEntry_0_sfenceVma (io_in_0_isSfenceVma),
|
||||
.io_allocateEntry_0_xret (io_in_0_isXret),
|
||||
.io_allocateEntry_0_xretIsMret (io_in_0_isMret),
|
||||
.io_allocateEntry_1_pc (io_in_1_pc),
|
||||
.io_allocateEntry_1_archDest (io_in_1_rd),
|
||||
.io_allocateEntry_1_writesDest (io_in_1_writesRd),
|
||||
.io_allocateEntry_1_opClass (io_in_1_opClass),
|
||||
.io_allocateEntry_1_dest (e_1_dest),
|
||||
.io_allocateEntry_1_oldDest (_table_io_oldPrd_1),
|
||||
.io_allocateEntry_1_fenceI (io_in_1_isFenceI),
|
||||
.io_allocateEntry_1_sfenceVma (io_in_1_isSfenceVma),
|
||||
.io_allocateEntry_1_xret (io_in_1_isXret),
|
||||
.io_allocateEntry_1_xretIsMret (io_in_1_isMret),
|
||||
.io_allocateIdx_0 (io_out_0_robIdx),
|
||||
.io_allocateIdx_1 (io_out_1_robIdx),
|
||||
.io_canAllocate (_rob_io_canAllocate),
|
||||
@@ -932,9 +997,19 @@ module RenameStage(
|
||||
.io_completeCsrRs1_1 (io_completeCsrRs1_1),
|
||||
.io_completeCsrZimm_0 (io_completeCsrZimm_0),
|
||||
.io_completeCsrZimm_1 (io_completeCsrZimm_1),
|
||||
.io_completeFenceI_0 (io_completeFenceI_0),
|
||||
.io_completeFenceI_1 (io_completeFenceI_1),
|
||||
.io_completeSfenceVma_0 (io_completeSfenceVma_0),
|
||||
.io_completeSfenceVma_1 (io_completeSfenceVma_1),
|
||||
.io_completeXret_0 (io_completeXret_0),
|
||||
.io_completeXret_1 (io_completeXret_1),
|
||||
.io_completeXretIsMret_0 (io_completeXretIsMret_0),
|
||||
.io_completeXretIsMret_1 (io_completeXretIsMret_1),
|
||||
.io_commitValid_0 (io_commitValid_0),
|
||||
.io_commitValid_1 (io_commitValid_1),
|
||||
.io_commit_0_valid (io_commitEntry_0_valid),
|
||||
.io_commit_0_robIdx (io_commitEntry_0_robIdx),
|
||||
.io_commit_0_pc (io_commitEntry_0_pc),
|
||||
.io_commit_0_archDest (io_commitEntry_0_archDest),
|
||||
.io_commit_0_writesDest (io_commitEntry_0_writesDest),
|
||||
.io_commit_0_opClass (io_commitEntry_0_opClass),
|
||||
@@ -951,7 +1026,11 @@ module RenameStage(
|
||||
.io_commit_0_csrRs1 (io_commitEntry_0_csrRs1),
|
||||
.io_commit_0_csrZimm (io_commitEntry_0_csrZimm),
|
||||
.io_commit_0_fenceI (io_commitEntry_0_fenceI),
|
||||
.io_commit_0_sfenceVma (io_commitEntry_0_sfenceVma),
|
||||
.io_commit_0_xret (io_commitEntry_0_xret),
|
||||
.io_commit_0_xretIsMret (io_commitEntry_0_xretIsMret),
|
||||
.io_commit_1_robIdx (io_commitEntry_1_robIdx),
|
||||
.io_commit_1_pc (io_commitEntry_1_pc),
|
||||
.io_commit_1_archDest (io_commitEntry_1_archDest),
|
||||
.io_commit_1_writesDest (io_commitEntry_1_writesDest),
|
||||
.io_commit_1_opClass (io_commitEntry_1_opClass),
|
||||
@@ -968,6 +1047,9 @@ module RenameStage(
|
||||
.io_commit_1_csrRs1 (io_commitEntry_1_csrRs1),
|
||||
.io_commit_1_csrZimm (io_commitEntry_1_csrZimm),
|
||||
.io_commit_1_fenceI (io_commitEntry_1_fenceI),
|
||||
.io_commit_1_sfenceVma (io_commitEntry_1_sfenceVma),
|
||||
.io_commit_1_xret (io_commitEntry_1_xret),
|
||||
.io_commit_1_xretIsMret (io_commitEntry_1_xretIsMret),
|
||||
.io_commitReady_0 (io_commitReady_0),
|
||||
.io_commitReady_1 (io_commitReady_1),
|
||||
.io_flush (io_flush)
|
||||
@@ -998,10 +1080,20 @@ module RenameStage(
|
||||
assign io_out_0_decoded_isWord = io_in_0_isWord;
|
||||
assign io_out_0_decoded_isSystem = io_in_0_isSystem;
|
||||
assign io_out_0_decoded_isFenceI = io_in_0_isFenceI;
|
||||
assign io_out_0_decoded_isEcall = io_in_0_isEcall;
|
||||
assign io_out_0_decoded_isEbreak = io_in_0_isEbreak;
|
||||
assign io_out_0_decoded_isMret = io_in_0_isMret;
|
||||
assign io_out_0_decoded_isSret = io_in_0_isSret;
|
||||
assign io_out_0_decoded_isSfenceVma = io_in_0_isSfenceVma;
|
||||
assign io_out_0_decoded_isXret = io_in_0_isXret;
|
||||
assign io_out_0_decoded_isWfi = io_in_0_isWfi;
|
||||
assign io_out_0_decoded_isAmo = io_in_0_isAmo;
|
||||
assign io_out_0_decoded_amoOp = io_in_0_amoOp;
|
||||
assign io_out_0_decoded_writesRd = io_in_0_writesRd;
|
||||
assign io_out_0_decoded_illegal = io_in_0_illegal;
|
||||
assign io_out_0_decoded_fetchException = io_in_0_fetchException;
|
||||
assign io_out_0_decoded_fetchExceptionCause = io_in_0_fetchExceptionCause;
|
||||
assign io_out_0_decoded_fetchExceptionTval = io_in_0_fetchExceptionTval;
|
||||
assign io_out_0_prs1 = _table_io_prs1_0;
|
||||
assign io_out_0_prs2 = _table_io_prs2_0;
|
||||
assign io_out_0_src1Ready =
|
||||
@@ -1039,10 +1131,20 @@ module RenameStage(
|
||||
assign io_out_1_decoded_isWord = io_in_1_isWord;
|
||||
assign io_out_1_decoded_isSystem = io_in_1_isSystem;
|
||||
assign io_out_1_decoded_isFenceI = io_in_1_isFenceI;
|
||||
assign io_out_1_decoded_isEcall = io_in_1_isEcall;
|
||||
assign io_out_1_decoded_isEbreak = io_in_1_isEbreak;
|
||||
assign io_out_1_decoded_isMret = io_in_1_isMret;
|
||||
assign io_out_1_decoded_isSret = io_in_1_isSret;
|
||||
assign io_out_1_decoded_isSfenceVma = io_in_1_isSfenceVma;
|
||||
assign io_out_1_decoded_isXret = io_in_1_isXret;
|
||||
assign io_out_1_decoded_isWfi = io_in_1_isWfi;
|
||||
assign io_out_1_decoded_isAmo = io_in_1_isAmo;
|
||||
assign io_out_1_decoded_amoOp = io_in_1_amoOp;
|
||||
assign io_out_1_decoded_writesRd = io_in_1_writesRd;
|
||||
assign io_out_1_decoded_illegal = io_in_1_illegal;
|
||||
assign io_out_1_decoded_fetchException = io_in_1_fetchException;
|
||||
assign io_out_1_decoded_fetchExceptionCause = io_in_1_fetchExceptionCause;
|
||||
assign io_out_1_decoded_fetchExceptionTval = io_in_1_fetchExceptionTval;
|
||||
assign io_out_1_prs1 = _table_io_prs1_1;
|
||||
assign io_out_1_prs2 = _table_io_prs2_1;
|
||||
assign io_out_1_src1Ready =
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,6 @@
|
||||
ITLB.sv
|
||||
PageTableWalker.sv
|
||||
MMU.sv
|
||||
tags_1024x204.sv
|
||||
data_1024x256.sv
|
||||
ICache.sv
|
||||
@@ -20,12 +23,12 @@ CommitStage.sv
|
||||
LoadQueue.sv
|
||||
StoreQueue.sv
|
||||
DTLB.sv
|
||||
PageTableWalker.sv
|
||||
MMU.sv
|
||||
verification/assert/DCache_Verification_Assert.sv
|
||||
tags_64x416.sv
|
||||
data_64x4096.sv
|
||||
DCache.sv
|
||||
LSU.sv
|
||||
CSRFile.sv
|
||||
OoOBackend.sv
|
||||
PrivilegeControl.sv
|
||||
Core.sv
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
// Generated by CIRCT firtool-1.139.0
|
||||
|
||||
// Users can define 'STOP_COND' to add an extra gate to stop conditions.
|
||||
`ifndef STOP_COND_
|
||||
`ifdef STOP_COND
|
||||
`define STOP_COND_ (`STOP_COND)
|
||||
`else // STOP_COND
|
||||
`define STOP_COND_ 1
|
||||
`endif // STOP_COND
|
||||
`endif // not def STOP_COND_
|
||||
|
||||
// Users can define 'ASSERT_VERBOSE_COND' to add an extra gate to assert error printing.
|
||||
`ifndef ASSERT_VERBOSE_COND_
|
||||
`ifdef ASSERT_VERBOSE_COND
|
||||
`define ASSERT_VERBOSE_COND_ (`ASSERT_VERBOSE_COND)
|
||||
`else // ASSERT_VERBOSE_COND
|
||||
`define ASSERT_VERBOSE_COND_ 1
|
||||
`endif // ASSERT_VERBOSE_COND
|
||||
`endif // not def ASSERT_VERBOSE_COND_
|
||||
module DCache_Verification_Assert();
|
||||
`ifndef SYNTHESIS
|
||||
always @(posedge DCache.clock) begin
|
||||
if (~DCache.reset & DCache.io_reqValid
|
||||
& (|((DCache._storeEndSet_T_6
|
||||
? 3'h0
|
||||
: DCache._storeEndSet_T_4
|
||||
? 3'h4
|
||||
: DCache._storeEndSet_T_2 ? 3'h2 : {2'h0, DCache._storeEndSet_T})
|
||||
- 3'h1 & DCache.io_req_addr[2:0]))) begin
|
||||
if (`ASSERT_VERBOSE_COND_)
|
||||
$error("Assertion failed: DCache received misaligned request; LSU must trap before DCache\n");
|
||||
if (`STOP_COND_)
|
||||
$fatal;
|
||||
end
|
||||
end // always @(posedge)
|
||||
`endif // not def SYNTHESIS
|
||||
endmodule
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
`ifndef layers_Core_Verification_Assert
|
||||
`define layers_Core_Verification_Assert
|
||||
`include "layers-Core-Verification.sv"
|
||||
`include "layers-OoOBackend-Verification-Assert.sv"
|
||||
`endif // not def layers_Core_Verification_Assert
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// Generated by CIRCT firtool-1.139.0
|
||||
`ifndef layers_DCache_Verification_Assert
|
||||
`define layers_DCache_Verification_Assert
|
||||
`include "layers-DCache-Verification.sv"
|
||||
bind DCache DCache_Verification_Assert verification_assert ();
|
||||
`endif // not def layers_DCache_Verification_Assert
|
||||
@@ -0,0 +1,6 @@
|
||||
// Generated by CIRCT firtool-1.139.0
|
||||
`ifndef layers_LSU_Verification_Assert
|
||||
`define layers_LSU_Verification_Assert
|
||||
`include "layers-LSU-Verification.sv"
|
||||
`include "layers-DCache-Verification-Assert.sv"
|
||||
`endif // not def layers_LSU_Verification_Assert
|
||||
@@ -0,0 +1,6 @@
|
||||
// Generated by CIRCT firtool-1.139.0
|
||||
`ifndef layers_OoOBackend_Verification_Assert
|
||||
`define layers_OoOBackend_Verification_Assert
|
||||
`include "layers-OoOBackend-Verification.sv"
|
||||
`include "layers-LSU-Verification-Assert.sv"
|
||||
`endif // not def layers_OoOBackend_Verification_Assert
|
||||
@@ -1,4 +1,5 @@
|
||||
// Generated by CIRCT firtool-1.139.0
|
||||
`ifndef layers_Core_Verification
|
||||
`define layers_Core_Verification
|
||||
`include "layers-OoOBackend-Verification.sv"
|
||||
`endif // not def layers_Core_Verification
|
||||
|
||||
4
generated-ooo/verification/layers-DCache-Verification.sv
Normal file
4
generated-ooo/verification/layers-DCache-Verification.sv
Normal file
@@ -0,0 +1,4 @@
|
||||
// Generated by CIRCT firtool-1.139.0
|
||||
`ifndef layers_DCache_Verification
|
||||
`define layers_DCache_Verification
|
||||
`endif // not def layers_DCache_Verification
|
||||
5
generated-ooo/verification/layers-LSU-Verification.sv
Normal file
5
generated-ooo/verification/layers-LSU-Verification.sv
Normal file
@@ -0,0 +1,5 @@
|
||||
// Generated by CIRCT firtool-1.139.0
|
||||
`ifndef layers_LSU_Verification
|
||||
`define layers_LSU_Verification
|
||||
`include "layers-DCache-Verification.sv"
|
||||
`endif // not def layers_LSU_Verification
|
||||
@@ -1,6 +1,5 @@
|
||||
// Generated by CIRCT firtool-1.139.0
|
||||
`ifndef layers_OoOBackend_Verification
|
||||
`define layers_OoOBackend_Verification
|
||||
`include "layers-RenameStage-Verification.sv"
|
||||
bind OoOBackend OoOBackend_Verification verification ();
|
||||
`include "layers-LSU-Verification.sv"
|
||||
`endif // not def layers_OoOBackend_Verification
|
||||
|
||||
93
sim/results/privileged_test_results.txt
Normal file
93
sim/results/privileged_test_results.txt
Normal file
@@ -0,0 +1,93 @@
|
||||
Running privileged RISC-V tests...
|
||||
=================================
|
||||
rv64mi-p-breakpoint: exit=0 PASS
|
||||
rv64mi-p-csr: exit=0 PASS
|
||||
rv64mi-p-illegal: exit=0 PASS
|
||||
rv64mi-p-instret_overflow: exit=1 FAIL
|
||||
[5] FLUSH exception=0 mtvec=0x0 mepc=0x0 mcause=0x0 frontend_pc=0x80000008
|
||||
[65] CSR commit slot0=1 slot1=0 addr=0x305 cmd=1 next=0x0 mtvec=0x0
|
||||
[66] CSR commit slot0=1 slot1=0 addr=0x744 cmd=5 next=0x800000e8 mtvec=0x800000e8
|
||||
[71] CSR commit slot0=1 slot1=0 addr=0x305 cmd=1 next=0x0 mtvec=0x800000e8
|
||||
[72] CSR commit slot0=1 slot1=0 addr=0x180 cmd=5 next=0x800000f8 mtvec=0x800000f8
|
||||
[77] CSR commit slot0=1 slot1=0 addr=0x305 cmd=1 next=0x0 mtvec=0x800000f8
|
||||
[83] CSR commit slot0=1 slot1=0 addr=0x3b0 cmd=1 next=0x0 mtvec=0x8000011c
|
||||
[86] CSR commit slot0=1 slot1=0 addr=0x3a0 cmd=1 next=0x0 mtvec=0x8000011c
|
||||
[87] CSR commit slot0=1 slot1=0 addr=0x304 cmd=5 next=0x1f mtvec=0x8000011c
|
||||
[92] CSR commit slot0=1 slot1=0 addr=0x305 cmd=1 next=0x0 mtvec=0x8000011c
|
||||
[93] CSR commit slot0=1 slot1=0 addr=0x302 cmd=5 next=0x80000134 mtvec=0x80000134
|
||||
[95] CSR commit slot0=1 slot1=0 addr=0x303 cmd=5 next=0x0 mtvec=0x80000134
|
||||
[101] CSR commit slot0=1 slot1=0 addr=0x305 cmd=1 next=0x0 mtvec=0x80000134
|
||||
[105] FLUSH exception=0 mtvec=0x80000004 mepc=0x0 mcause=0x0 frontend_pc=0x80000158
|
||||
[114] FLUSH exception=0 mtvec=0x80000004 mepc=0x0 mcause=0x0 frontend_pc=0x80000170
|
||||
[120] CSR commit slot0=1 slot1=0 addr=0x300 cmd=5 next=0x0 mtvec=0x80000004
|
||||
[126] CSR commit slot0=1 slot1=0 addr=0x300 cmd=2 next=0x0 mtvec=0x80000004
|
||||
[130] CSR commit slot0=1 slot1=0 addr=0x341 cmd=1 next=0x0 mtvec=0x80000004
|
||||
[133] FLUSH exception=0 mtvec=0x80000004 mepc=0x800001a0 mcause=0x0 frontend_pc=0x800001a8
|
||||
[141] CSR commit slot0=1 slot1=0 addr=0x305 cmd=1 next=0x0 mtvec=0x80000004
|
||||
[142] FLUSH exception=1 mtvec=0x800001b0 mepc=0x800001a0 mcause=0x0 frontend_pc=0x800001b8
|
||||
[147] CSR commit slot0=1 slot1=0 addr=0x305 cmd=1 next=0x0 mtvec=0x800001b0
|
||||
[150] FLUSH exception=1 mtvec=0x80000004 mepc=0x800001ac mcause=0x2 frontend_pc=0x800001c0
|
||||
[171] FLUSH exception=0 mtvec=0x80000004 mepc=0x800001b8 mcause=0x2 frontend_pc=0x80000038
|
||||
[177] FLUSH exception=0 mtvec=0x80000004 mepc=0x800001b8 mcause=0x2 frontend_pc=0x80000200
|
||||
[193] FLUSH exception=1 mtvec=0x80000004 mepc=0x800001b8 mcause=0x2 frontend_pc=0x800001f0
|
||||
[205] FLUSH exception=0 mtvec=0x80000004 mepc=0x800001e4 mcause=0xb frontend_pc=0x80000028
|
||||
[213] STORE addr=0x80001000 data=0x5 size=2
|
||||
Loaded segment: paddr=0x80000000 size=576
|
||||
Loaded segment: paddr=0x80001000 size=72
|
||||
ELF loaded: entry=0x80000000
|
||||
[213] TEST FAILED: error code 2
|
||||
rv64mi-p-ld-misaligned: exit=0 PASS
|
||||
rv64mi-p-lh-misaligned: exit=0 PASS
|
||||
rv64mi-p-lw-misaligned: exit=0 PASS
|
||||
rv64mi-p-ma_addr: exit=0 PASS
|
||||
rv64mi-p-ma_fetch: exit=0 PASS
|
||||
rv64mi-p-mcsr: exit=1 FAIL
|
||||
[5] FLUSH exception=0 mtvec=0x0 mepc=0x0 mcause=0x0 frontend_pc=0x80000008
|
||||
[63] CSR commit slot0=1 slot1=0 addr=0x305 cmd=1 next=0x0 mtvec=0x0
|
||||
[65] CSR commit slot0=1 slot1=0 addr=0x744 cmd=5 next=0x0 mtvec=0x800000e4
|
||||
[69] CSR commit slot0=1 slot1=0 addr=0x305 cmd=1 next=0x0 mtvec=0x800000e4
|
||||
[71] CSR commit slot0=1 slot1=0 addr=0x180 cmd=5 next=0x0 mtvec=0x800000f4
|
||||
[75] CSR commit slot0=1 slot1=0 addr=0x305 cmd=1 next=0x0 mtvec=0x800000f4
|
||||
[81] CSR commit slot0=1 slot1=0 addr=0x3b0 cmd=1 next=0x0 mtvec=0x80000118
|
||||
[84] CSR commit slot0=1 slot1=0 addr=0x3a0 cmd=1 next=0x0 mtvec=0x80000118
|
||||
[86] CSR commit slot0=1 slot1=0 addr=0x304 cmd=5 next=0x0 mtvec=0x80000118
|
||||
[90] CSR commit slot0=1 slot1=0 addr=0x305 cmd=1 next=0x0 mtvec=0x80000118
|
||||
[92] CSR commit slot0=1 slot1=0 addr=0x302 cmd=5 next=0x0 mtvec=0x80000130
|
||||
[93] CSR commit slot0=1 slot1=0 addr=0x303 cmd=5 next=0x0 mtvec=0x80000130
|
||||
[99] CSR commit slot0=1 slot1=0 addr=0x305 cmd=1 next=0x0 mtvec=0x80000130
|
||||
[104] FLUSH exception=0 mtvec=0x80000004 mepc=0x0 mcause=0x0 frontend_pc=0x80000150
|
||||
[111] FLUSH exception=0 mtvec=0x80000004 mepc=0x0 mcause=0x0 frontend_pc=0x80000170
|
||||
[117] CSR commit slot0=1 slot1=0 addr=0x300 cmd=5 next=0x0 mtvec=0x80000004
|
||||
[121] CSR commit slot0=1 slot1=0 addr=0x300 cmd=2 next=0x0 mtvec=0x80000004
|
||||
[126] CSR commit slot0=1 slot1=0 addr=0x341 cmd=1 next=0x0 mtvec=0x80000004
|
||||
[129] FLUSH exception=0 mtvec=0x80000004 mepc=0x8000019c mcause=0x0 frontend_pc=0x800001a0
|
||||
[149] FLUSH exception=1 mtvec=0x80000004 mepc=0x8000019c mcause=0x0 frontend_pc=0x800001c8
|
||||
[167] FLUSH exception=0 mtvec=0x80000004 mepc=0x800001c0 mcause=0x2 frontend_pc=0x80000030
|
||||
[175] FLUSH exception=0 mtvec=0x80000004 mepc=0x800001c0 mcause=0x2 frontend_pc=0x80000038
|
||||
[185] STORE addr=0x80001000 data=0x53b size=2
|
||||
Loaded segment: paddr=0x80000000 size=572
|
||||
Loaded segment: paddr=0x80001000 size=72
|
||||
ELF loaded: entry=0x80000000
|
||||
[185] TEST FAILED: error code 669
|
||||
rv64mi-p-pmpaddr: exit=0 PASS
|
||||
rv64mi-p-sbreak: exit=0 PASS
|
||||
rv64mi-p-scall: exit=0 PASS
|
||||
rv64mi-p-sd-misaligned: exit=0 PASS
|
||||
rv64mi-p-sh-misaligned: exit=0 PASS
|
||||
rv64mi-p-sw-misaligned: exit=0 PASS
|
||||
rv64mi-p-zicntr: exit=0 PASS
|
||||
rv64si-p-csr: exit=0 PASS
|
||||
rv64si-p-dirty: exit=124 TIMEOUT
|
||||
rv64si-p-icache-alias: exit=124 TIMEOUT
|
||||
rv64si-p-ma_fetch: exit=0 PASS
|
||||
rv64si-p-sbreak: exit=0 PASS
|
||||
rv64si-p-scall: exit=0 PASS
|
||||
rv64si-p-wfi: exit=0 PASS
|
||||
rv64ui-p-fence_i: exit=0 PASS
|
||||
|
||||
=================================
|
||||
Summary:
|
||||
PASS: 21
|
||||
FAIL: 2
|
||||
TIMEOUT: 2
|
||||
TOTAL: 25
|
||||
95
sim/results/test_results.txt
Normal file
95
sim/results/test_results.txt
Normal file
@@ -0,0 +1,95 @@
|
||||
Running RISC-V tests...
|
||||
====================
|
||||
rv64ui-p-add: PASS
|
||||
rv64ui-p-addi: PASS
|
||||
rv64ui-p-addiw: PASS
|
||||
rv64ui-p-addw: PASS
|
||||
rv64ui-p-and: PASS
|
||||
rv64ui-p-andi: PASS
|
||||
rv64ui-p-auipc: PASS
|
||||
rv64ui-p-beq: PASS
|
||||
rv64ui-p-bge: PASS
|
||||
rv64ui-p-bgeu: PASS
|
||||
rv64ui-p-blt: PASS
|
||||
rv64ui-p-bltu: PASS
|
||||
rv64ui-p-bne: PASS
|
||||
rv64ui-p-fence_i: PASS
|
||||
rv64ui-p-jal: PASS
|
||||
rv64ui-p-jalr: PASS
|
||||
rv64ui-p-lb: PASS
|
||||
rv64ui-p-lbu: PASS
|
||||
rv64ui-p-ld: PASS
|
||||
rv64ui-p-ld_st: PASS
|
||||
rv64ui-p-lh: PASS
|
||||
rv64ui-p-lhu: PASS
|
||||
rv64ui-p-lui: PASS
|
||||
rv64ui-p-lw: PASS
|
||||
rv64ui-p-lwu: PASS
|
||||
rv64ui-p-ma_data: FAIL
|
||||
rv64ui-p-or: PASS
|
||||
rv64ui-p-ori: PASS
|
||||
rv64ui-p-sb: PASS
|
||||
rv64ui-p-sd: PASS
|
||||
rv64ui-p-sh: PASS
|
||||
rv64ui-p-simple: PASS
|
||||
rv64ui-p-sll: PASS
|
||||
rv64ui-p-slli: PASS
|
||||
rv64ui-p-slliw: PASS
|
||||
rv64ui-p-sllw: PASS
|
||||
rv64ui-p-slt: PASS
|
||||
rv64ui-p-slti: PASS
|
||||
rv64ui-p-sltiu: PASS
|
||||
rv64ui-p-sltu: PASS
|
||||
rv64ui-p-sra: PASS
|
||||
rv64ui-p-srai: PASS
|
||||
rv64ui-p-sraiw: PASS
|
||||
rv64ui-p-sraw: PASS
|
||||
rv64ui-p-srl: PASS
|
||||
rv64ui-p-srli: PASS
|
||||
rv64ui-p-srliw: PASS
|
||||
rv64ui-p-srlw: PASS
|
||||
rv64ui-p-st_ld: PASS
|
||||
rv64ui-p-sub: PASS
|
||||
rv64ui-p-subw: PASS
|
||||
rv64ui-p-sw: PASS
|
||||
rv64ui-p-xor: PASS
|
||||
rv64ui-p-xori: PASS
|
||||
rv64um-p-div: PASS
|
||||
rv64um-p-divu: PASS
|
||||
rv64um-p-divuw: PASS
|
||||
rv64um-p-divw: PASS
|
||||
rv64um-p-mul: PASS
|
||||
rv64um-p-mulh: PASS
|
||||
rv64um-p-mulhsu: PASS
|
||||
rv64um-p-mulhu: PASS
|
||||
rv64um-p-mulw: PASS
|
||||
rv64um-p-rem: PASS
|
||||
rv64um-p-remu: PASS
|
||||
rv64um-p-remuw: PASS
|
||||
rv64um-p-remw: PASS
|
||||
rv64ua-p-amoadd_d: PASS
|
||||
rv64ua-p-amoadd_w: PASS
|
||||
rv64ua-p-amoand_d: PASS
|
||||
rv64ua-p-amoand_w: PASS
|
||||
rv64ua-p-amomax_d: PASS
|
||||
rv64ua-p-amomaxu_d: PASS
|
||||
rv64ua-p-amomaxu_w: PASS
|
||||
rv64ua-p-amomax_w: PASS
|
||||
rv64ua-p-amomin_d: PASS
|
||||
rv64ua-p-amominu_d: PASS
|
||||
rv64ua-p-amominu_w: PASS
|
||||
rv64ua-p-amomin_w: PASS
|
||||
rv64ua-p-amoor_d: PASS
|
||||
rv64ua-p-amoor_w: PASS
|
||||
rv64ua-p-amoswap_d: PASS
|
||||
rv64ua-p-amoswap_w: PASS
|
||||
rv64ua-p-amoxor_d: PASS
|
||||
rv64ua-p-amoxor_w: PASS
|
||||
rv64ua-p-lrsc: PASS
|
||||
|
||||
====================
|
||||
Summary:
|
||||
PASS: 85
|
||||
FAIL: 1
|
||||
TIMEOUT: 0
|
||||
TOTAL: 86
|
||||
28
sim/scripts/run_opensbi.sh
Executable file
28
sim/scripts/run_opensbi.sh
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
set -u
|
||||
|
||||
TESTBENCH="../verilator/obj_dir/VCore"
|
||||
OPENSBI_BIN="${OPENSBI_BIN:-../../opensbi/build/platform/generic/firmware/fw_payload.elf}"
|
||||
TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-10}"
|
||||
|
||||
if [ ! -x "$TESTBENCH" ]; then
|
||||
echo "Error: Testbench not found. Run 'make -C sim/verilator compile' first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$OPENSBI_BIN" ]; then
|
||||
echo "Error: OpenSBI payload not found: $OPENSBI_BIN"
|
||||
echo "Set OPENSBI_BIN to a firmware ELF path."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
echo "Running OpenSBI payload: $OPENSBI_BIN"
|
||||
timeout "${TIMEOUT_SECONDS}s" "$TESTBENCH" "$OPENSBI_BIN"
|
||||
exitcode=$?
|
||||
|
||||
if [ "$exitcode" -eq 124 ]; then
|
||||
echo "OpenSBI run timed out"
|
||||
exit 124
|
||||
fi
|
||||
|
||||
exit "$exitcode"
|
||||
75
sim/scripts/run_privileged_tests.sh
Executable file
75
sim/scripts/run_privileged_tests.sh
Executable file
@@ -0,0 +1,75 @@
|
||||
#!/bin/bash
|
||||
set -u
|
||||
|
||||
TESTBENCH="../verilator/obj_dir/VCore"
|
||||
TESTS_DIR="../../riscv-tests/isa"
|
||||
RESULTS_DIR="../results"
|
||||
RESULTS_FILE="$RESULTS_DIR/privileged_test_results.txt"
|
||||
TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-5}"
|
||||
|
||||
mkdir -p "$RESULTS_DIR"
|
||||
|
||||
if [ ! -x "$TESTBENCH" ]; then
|
||||
echo "Error: Testbench not found. Run 'make -C sim/verilator compile' first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Running privileged RISC-V tests..." > "$RESULTS_FILE"
|
||||
echo "=================================" >> "$RESULTS_FILE"
|
||||
|
||||
PASS=0
|
||||
FAIL=0
|
||||
TIMEOUT=0
|
||||
|
||||
shopt -s nullglob
|
||||
tests=(
|
||||
"$TESTS_DIR"/rv64mi-p-*
|
||||
"$TESTS_DIR"/rv64si-p-*
|
||||
"$TESTS_DIR"/rv64ui-p-fence_i
|
||||
)
|
||||
|
||||
for test in "${tests[@]}"; do
|
||||
[[ "$test" == *.dump ]] && continue
|
||||
[ ! -f "$test" ] && continue
|
||||
|
||||
testname=$(basename "$test")
|
||||
printf "Running %s... " "$testname"
|
||||
|
||||
output=$(timeout "${TIMEOUT_SECONDS}s" "$TESTBENCH" "$test" 2>&1)
|
||||
exitcode=$?
|
||||
|
||||
if [ "$exitcode" -eq 0 ]; then
|
||||
echo "PASS"
|
||||
echo "$testname: exit=0 PASS" >> "$RESULTS_FILE"
|
||||
PASS=$((PASS + 1))
|
||||
elif [ "$exitcode" -eq 124 ]; then
|
||||
echo "TIMEOUT"
|
||||
echo "$testname: exit=124 TIMEOUT" >> "$RESULTS_FILE"
|
||||
TIMEOUT=$((TIMEOUT + 1))
|
||||
else
|
||||
echo "FAIL (exit code $exitcode)"
|
||||
echo "$testname: exit=$exitcode FAIL" >> "$RESULTS_FILE"
|
||||
printf '%s\n' "$output" >> "$RESULTS_FILE"
|
||||
FAIL=$((FAIL + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
TOTAL=$((PASS + FAIL + TIMEOUT))
|
||||
{
|
||||
echo ""
|
||||
echo "================================="
|
||||
echo "Summary:"
|
||||
echo " PASS: $PASS"
|
||||
echo " FAIL: $FAIL"
|
||||
echo " TIMEOUT: $TIMEOUT"
|
||||
echo " TOTAL: $TOTAL"
|
||||
} >> "$RESULTS_FILE"
|
||||
|
||||
echo ""
|
||||
echo "Summary:"
|
||||
echo " PASS: $PASS"
|
||||
echo " FAIL: $FAIL"
|
||||
echo " TIMEOUT: $TIMEOUT"
|
||||
echo " TOTAL: $TOTAL"
|
||||
echo ""
|
||||
echo "Results saved to $RESULTS_FILE"
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
TESTBENCH="../verilator/obj_dir/VCore"
|
||||
TESTS_DIR="../../riscv-tests/isa"
|
||||
RESULTS_FILE="test_results.txt"
|
||||
RESULTS_FILE="../results/test_results.txt"
|
||||
|
||||
if [ ! -x "$TESTBENCH" ]; then
|
||||
echo "Error: Testbench not found. Run 'make compile' first."
|
||||
|
||||
4
sim/tests/EcallDelegationTest.scala
Normal file
4
sim/tests/EcallDelegationTest.scala
Normal file
@@ -0,0 +1,4 @@
|
||||
// Verilator scenario checklist:
|
||||
// 1. Set medeleg bit 8 and execute ecall from U-mode.
|
||||
// 2. Expect delegation to S-mode handler when S support is enabled.
|
||||
// 3. Clear delegation and verify ecall from U-mode traps to M-mode.
|
||||
4
sim/tests/InterruptEnableTest.scala
Normal file
4
sim/tests/InterruptEnableTest.scala
Normal file
@@ -0,0 +1,4 @@
|
||||
// Verilator scenario checklist:
|
||||
// 1. Toggle MSI, MTI, and MEI pending sources.
|
||||
// 2. Verify enable bits gate interrupt injection.
|
||||
// 3. Verify MEI > MTI > MSI priority and S-mode delegation bits.
|
||||
5
sim/tests/PrivilegeTransitionTest.scala
Normal file
5
sim/tests/PrivilegeTransitionTest.scala
Normal file
@@ -0,0 +1,5 @@
|
||||
// Verilator scenario checklist:
|
||||
// 1. Start in M-mode after reset.
|
||||
// 2. Configure mstatus.MPP=S and mepc to an S-mode entry point.
|
||||
// 3. Execute mret and verify the redirected PC equals mepc.
|
||||
// 4. Execute an S-mode ecall path and verify trap state is recoverable.
|
||||
4
sim/tests/SfenceTest.scala
Normal file
4
sim/tests/SfenceTest.scala
Normal file
@@ -0,0 +1,4 @@
|
||||
// Verilator scenario checklist:
|
||||
// 1. sfence.vma in U-mode raises illegal instruction.
|
||||
// 2. sfence.vma in S/M-mode flushes DTLB state.
|
||||
// 3. fence.i invalidates ICache and flushes younger instructions.
|
||||
4
sim/tests/XretFlushTest.scala
Normal file
4
sim/tests/XretFlushTest.scala
Normal file
@@ -0,0 +1,4 @@
|
||||
// Verilator scenario checklist:
|
||||
// 1. Execute mret and sret with younger instructions in flight.
|
||||
// 2. Verify commit emits flush and redirect.
|
||||
// 3. Verify younger side effects are squashed.
|
||||
3
sim/tests/exception/MisalignedTest.scala
Normal file
3
sim/tests/exception/MisalignedTest.scala
Normal file
@@ -0,0 +1,3 @@
|
||||
// Verilator scenario checklist:
|
||||
// 1. Instruction fetch with pc[1:0] != 0 raises instruction address misaligned.
|
||||
// 2. Load/store addresses not aligned to access size raise load/store address misaligned.
|
||||
4
sim/tests/exception/PageFaultTest.scala
Normal file
4
sim/tests/exception/PageFaultTest.scala
Normal file
@@ -0,0 +1,4 @@
|
||||
// Verilator scenario checklist:
|
||||
// 1. Unmapped instruction fetch raises instruction page fault.
|
||||
// 2. Unmapped load/store raises load/store page fault.
|
||||
// 3. U/S permission violations raise page fault instead of access fault.
|
||||
@@ -20,7 +20,7 @@ endif
|
||||
SBT = env SBT_OPTS="-Dsbt.boot.directory=/tmp/sbt-boot -Dsbt.ivy.home=/tmp/sbt-ivy" COURSIER_CACHE=/tmp/coursier-cache sbt
|
||||
|
||||
CHISEL_DIR = ../..
|
||||
OOO ?= 0
|
||||
OOO ?= 1
|
||||
ifeq ($(OOO),1)
|
||||
RUN_MAIN = CoreOoO
|
||||
GENERATED_DIR = $(CHISEL_DIR)/generated-ooo
|
||||
|
||||
@@ -206,7 +206,8 @@ int main(int argc, char** argv) {
|
||||
core->rootp->Core__DOT__frontend__DOT__icache__DOT__missAddr,
|
||||
(unsigned)core->rootp->Core__DOT__fetchValid,
|
||||
(unsigned)core->rootp->Core__DOT__fetchReady,
|
||||
(unsigned)core->rootp->Core__DOT___frontend_io_outValid,
|
||||
(unsigned)(core->rootp->Core__DOT__frontend__DOT__faultPending |
|
||||
core->rootp->Core__DOT__frontend__DOT___icache_io_respValid),
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT___issue_io_inReady_0,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__rename__DOT__rob__DOT__count,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__freeMask,
|
||||
@@ -255,18 +256,16 @@ int main(int argc, char** argv) {
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__issue0OH,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__issue1OH);
|
||||
fprintf(stderr,
|
||||
"complete: valid=%u/%u idx0=%u exc=%u/%u mis=%u/%u cause=0x%lx/0x%lx redirect=0x%lx/0x%lx\n",
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeValid_0,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeValid_1,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeIdx_0,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeException_0,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeException_1,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeMispredict_0,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeMispredict_1,
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeCause_0,
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeCause_1,
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeRedirectPc_0,
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeRedirectPc_1);
|
||||
"complete: valid=%u/%u idx0=%u exc=%u/%u cause=0x%lx/0x%lx redirect=0x%lx/0x%lx\n",
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__completeValid_0,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__completeValid_1,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__completeIdx_0,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__completeException_0,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__completeException_1,
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT__completeCause_0,
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT__completeCause_1,
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT__completeRedirectPc_0,
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT__completeRedirectPc_1);
|
||||
exit_code = 2;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,14 +23,22 @@ class Core(p: CoreParams = CoreParams()) extends Module {
|
||||
val frontend = Module(new Frontend(p))
|
||||
val id = Module(new IDStage(p))
|
||||
val backend = Module(new OoOBackend(p))
|
||||
val privCtrl = Module(new PrivilegeControl(p))
|
||||
|
||||
privCtrl.io.setPriv := backend.io.setPriv
|
||||
privCtrl.io.nextPriv := backend.io.targetPriv
|
||||
|
||||
frontend.io.redirectValid := backend.io.flush
|
||||
frontend.io.redirectPc := backend.io.redirectPc
|
||||
frontend.io.invalidateICache := backend.io.invalidateICache
|
||||
frontend.io.sfenceVma := backend.io.sfenceVma
|
||||
frontend.io.satp := backend.io.satpOut
|
||||
frontend.io.currentPriv := privCtrl.io.priv
|
||||
frontend.io.imemRespValid := io.imem_resp_valid
|
||||
frontend.io.imemRespBits(0) := io.imem_resp_bits_0
|
||||
frontend.io.imemRespBits(1) := io.imem_resp_bits_1
|
||||
frontend.io.branchUpdate := 0.U.asTypeOf(new BranchUpdate(p))
|
||||
dontTouch(frontend.io.outValid)
|
||||
|
||||
val fetchValid = RegInit(false.B)
|
||||
val fetchReg = Reg(new FetchPacket(p))
|
||||
@@ -48,17 +56,41 @@ class Core(p: CoreParams = CoreParams()) extends Module {
|
||||
|
||||
backend.io.decodeValid := id.io.outValid
|
||||
backend.io.decode := id.io.out
|
||||
backend.io.dmemRespValid := io.dmem_resp_valid
|
||||
val frontendPtwOutstanding = RegInit(false.B)
|
||||
val backendReadOutstanding = RegInit(false.B)
|
||||
val frontendPtwCanIssue = frontend.io.ptwMemReqValid && !frontendPtwOutstanding &&
|
||||
!backendReadOutstanding && !backend.io.dmemReqValid
|
||||
val backendCanIssue = !frontendPtwOutstanding
|
||||
val backendReadIssue = backend.io.dmemReqValid && backendCanIssue && !backend.io.dmemReq.isStore && !backendReadOutstanding
|
||||
val frontendPtwRespValid = io.dmem_resp_valid && (frontendPtwOutstanding || frontendPtwCanIssue)
|
||||
val backendRespValid = io.dmem_resp_valid && !frontendPtwOutstanding && !frontendPtwCanIssue
|
||||
|
||||
when(frontendPtwRespValid) {
|
||||
frontendPtwOutstanding := false.B
|
||||
}.elsewhen(frontendPtwCanIssue) {
|
||||
frontendPtwOutstanding := true.B
|
||||
}
|
||||
|
||||
when(backendRespValid && (backendReadOutstanding || backendReadIssue)) {
|
||||
backendReadOutstanding := false.B
|
||||
}.elsewhen(backendReadIssue && !backendRespValid) {
|
||||
backendReadOutstanding := true.B
|
||||
}
|
||||
|
||||
backend.io.dmemRespValid := backendRespValid
|
||||
backend.io.dmemRespData := io.dmem_resp_bits
|
||||
backend.io.satp := 0.U
|
||||
backend.io.currentPriv := privCtrl.io.priv
|
||||
frontend.io.ptwMemRespValid := frontendPtwRespValid
|
||||
frontend.io.ptwMemRespData := io.dmem_resp_bits
|
||||
|
||||
io.imem_req_valid := frontend.io.imemReqValid
|
||||
io.imem_req_bits := frontend.io.imemReqAddr
|
||||
io.dmem_req_valid := backend.io.dmemReqValid
|
||||
io.dmem_req_bits_addr := backend.io.dmemReq.addr
|
||||
io.dmem_req_bits_data := backend.io.dmemReq.data
|
||||
io.dmem_req_bits_isStore := backend.io.dmemReq.isStore
|
||||
io.dmem_req_bits_size := backend.io.dmemReq.size
|
||||
io.dmem_req_valid := (backend.io.dmemReqValid && backendCanIssue) || frontendPtwCanIssue
|
||||
io.dmem_req_bits_addr := Mux(frontendPtwCanIssue, frontend.io.ptwMemReqAddr, backend.io.dmemReq.addr)
|
||||
io.dmem_req_bits_data := Mux(frontendPtwCanIssue, 0.U, backend.io.dmemReq.data)
|
||||
io.dmem_req_bits_isStore := backend.io.dmemReqValid && backendCanIssue && backend.io.dmemReq.isStore
|
||||
io.dmem_req_bits_size := Mux(frontendPtwCanIssue, 3.U, backend.io.dmemReq.size)
|
||||
} else {
|
||||
|
||||
val sFetch :: sExec :: sLoadWait :: Nil = Enum(3)
|
||||
@@ -77,6 +109,10 @@ class Core(p: CoreParams = CoreParams()) extends Module {
|
||||
val alu = Module(new ALU(p))
|
||||
val branch = Module(new BranchUnit(p))
|
||||
val csr = Module(new CSRFile(p))
|
||||
val privCtrl = Module(new PrivilegeControl(p))
|
||||
|
||||
privCtrl.io.setPriv := false.B
|
||||
privCtrl.io.nextPriv := Privileged.PRV_M
|
||||
|
||||
def regRead(addr: UInt): UInt = Mux(addr === 0.U, 0.U, regs(addr))
|
||||
def lowLoad(data: UInt, size: UInt, signed: Bool): UInt = {
|
||||
@@ -110,13 +146,35 @@ class Core(p: CoreParams = CoreParams()) extends Module {
|
||||
csr.io.cmd.rs1 := src1
|
||||
csr.io.cmd.zimm := dec.rs1
|
||||
csr.io.readAddr := instReg(31, 20)
|
||||
csr.io.currentPriv := privCtrl.io.priv
|
||||
val isEcall = instReg === "h00000073".U
|
||||
val isEbreak = instReg === "h00100073".U
|
||||
val isMret = instReg === "h30200073".U
|
||||
val takeTrap = state === sExec && (isEcall || isEbreak)
|
||||
val illegalPriv = (dec.isMret && privCtrl.io.priv =/= Privileged.PRV_M) ||
|
||||
(dec.isSret && privCtrl.io.priv === Privileged.PRV_U) ||
|
||||
(dec.isSfenceVma && privCtrl.io.priv === Privileged.PRV_U)
|
||||
val csrAccess = dec.isSystem && dec.funct3 =/= 0.U
|
||||
val csrWrites = csrAccess && !(dec.funct3(1) && dec.rs1 === 0.U)
|
||||
val takeIllegal = state === sExec && (dec.illegal || illegalPriv ||
|
||||
(csrAccess && csr.io.readIllegal) || (csrWrites && csr.io.writeIllegal))
|
||||
val takeTrap = state === sExec && (isEcall || isEbreak) || takeIllegal
|
||||
val takeMret = state === sExec && isMret
|
||||
val takeSret = state === sExec && dec.isSret
|
||||
val trapTargetPriv = PrivilegeTransitions.trapTargetPriv(
|
||||
privCtrl.io.priv, csr.io.trapCause, false.B, csr.io.medeleg, csr.io.mideleg)
|
||||
privCtrl.io.setPriv := takeTrap || takeMret || takeSret
|
||||
privCtrl.io.nextPriv := Mux(takeMret || takeSret,
|
||||
PrivilegeTransitions.xretNextPriv(takeMret, csr.io.mstatus),
|
||||
trapTargetPriv)
|
||||
csr.io.trap := takeTrap
|
||||
csr.io.trapPc := pcReg
|
||||
csr.io.trapCause := Mux(isEbreak, 3.U, 11.U)
|
||||
csr.io.trapCause := Mux(takeIllegal, Privileged.CAUSE_ILLEGAL_INSTRUCTION,
|
||||
Mux(isEbreak, Privileged.CAUSE_BREAKPOINT, Privileged.CAUSE_ECALL_FROM_M))
|
||||
csr.io.trapTval := 0.U
|
||||
csr.io.trapTargetPriv := trapTargetPriv
|
||||
csr.io.trapIsInterrupt := false.B
|
||||
csr.io.xret := takeMret || takeSret
|
||||
csr.io.xretIsMret := takeMret
|
||||
|
||||
val loadAddr = src1 + dec.immI
|
||||
val storeAddr = src1 + dec.immS
|
||||
@@ -166,10 +224,10 @@ class Core(p: CoreParams = CoreParams()) extends Module {
|
||||
}
|
||||
}.elsewhen(state === sExec) {
|
||||
when(takeTrap) {
|
||||
pc := csr.io.mtvec
|
||||
pc := csr.io.trapVector
|
||||
state := sFetch
|
||||
}.elsewhen(isMret) {
|
||||
pc := csr.io.mepc
|
||||
}.elsewhen(isMret || dec.isSret) {
|
||||
pc := PrivilegeTransitions.xretTargetPc(isMret, csr.io.mepc, csr.io.sepc)
|
||||
state := sFetch
|
||||
}.elsewhen(dec.isLoad && !amoStoreLike) {
|
||||
when(io.dmem_resp_valid) {
|
||||
|
||||
@@ -16,12 +16,17 @@ class OoOBackend(p: CoreParams = CoreParams()) extends Module {
|
||||
val flush = Output(Bool())
|
||||
val redirectPc = Output(UInt(p.xlen.W))
|
||||
val invalidateICache = Output(Bool())
|
||||
val sfenceVma = Output(Bool())
|
||||
val setPriv = Output(Bool())
|
||||
val targetPriv = Output(UInt(2.W))
|
||||
|
||||
val dmemReqValid = Output(Bool())
|
||||
val dmemReq = Output(new MemRequest(p))
|
||||
val dmemRespValid = Input(Bool())
|
||||
val dmemRespData = Input(UInt(p.xlen.W))
|
||||
val satp = Input(UInt(p.xlen.W))
|
||||
val satpOut = Output(UInt(p.xlen.W))
|
||||
val currentPriv = Input(UInt(2.W))
|
||||
})
|
||||
|
||||
val rename = Module(new RenameStage(p))
|
||||
@@ -47,9 +52,18 @@ class OoOBackend(p: CoreParams = CoreParams()) extends Module {
|
||||
val completeCsrCmd = Wire(Vec(p.issueWidth, UInt(3.W)))
|
||||
val completeCsrRs1 = Wire(Vec(p.issueWidth, UInt(p.xlen.W)))
|
||||
val completeCsrZimm = Wire(Vec(p.issueWidth, UInt(5.W)))
|
||||
val completeFenceI = Wire(Vec(p.issueWidth, Bool()))
|
||||
val completeSfenceVma = Wire(Vec(p.issueWidth, Bool()))
|
||||
val completeXret = Wire(Vec(p.issueWidth, Bool()))
|
||||
val completeXretIsMret = Wire(Vec(p.issueWidth, Bool()))
|
||||
val wakeup = Wire(Vec(p.issueWidth, new Wakeup(p)))
|
||||
val wakeupReg = RegInit(VecInit(Seq.fill(p.issueWidth)(0.U.asTypeOf(new Wakeup(p)))))
|
||||
val csrRData = Wire(Vec(p.issueWidth, UInt(p.xlen.W)))
|
||||
dontTouch(completeValid)
|
||||
dontTouch(completeIdx)
|
||||
dontTouch(completeException)
|
||||
dontTouch(completeCause)
|
||||
dontTouch(completeRedirectPc)
|
||||
|
||||
rename.io.inValid := VecInit((0 until p.issueWidth).map(i => io.decodeValid(i) && issue.io.inReady(i)))
|
||||
rename.io.in := io.decode
|
||||
@@ -67,6 +81,10 @@ class OoOBackend(p: CoreParams = CoreParams()) extends Module {
|
||||
rename.io.completeCsrCmd := completeCsrCmd
|
||||
rename.io.completeCsrRs1 := completeCsrRs1
|
||||
rename.io.completeCsrZimm := completeCsrZimm
|
||||
rename.io.completeFenceI := completeFenceI
|
||||
rename.io.completeSfenceVma := completeSfenceVma
|
||||
rename.io.completeXret := completeXret
|
||||
rename.io.completeXretIsMret := completeXretIsMret
|
||||
rename.io.commitReady := commit.io.commitReady
|
||||
rename.io.commitMapValid := commit.io.commitMapValid
|
||||
rename.io.commitArch := commit.io.commitArch
|
||||
@@ -78,6 +96,8 @@ class OoOBackend(p: CoreParams = CoreParams()) extends Module {
|
||||
issue.io.inValid := rename.io.outValid
|
||||
issue.io.in := rename.io.out
|
||||
issue.io.wakeup := wakeupReg
|
||||
issue.io.robHeadValid := rename.io.commitEntry(0).valid
|
||||
issue.io.robHeadIdx := rename.io.commitEntry(0).robIdx
|
||||
val loadPending = RegInit(false.B)
|
||||
val loadPendingRob = Reg(UInt(robBits.W))
|
||||
val loadPendingPhys = Reg(UInt(physBits.W))
|
||||
@@ -89,7 +109,14 @@ class OoOBackend(p: CoreParams = CoreParams()) extends Module {
|
||||
val forwardPendingData = Reg(UInt(p.xlen.W))
|
||||
val loadRespValid = (lsu.io.respValid && loadPending) || forwardPending
|
||||
val loadRespData = Mux(forwardPending, forwardPendingData, lsu.io.respData)
|
||||
val loadRespPageFault = !forwardPending && lsu.io.pageFault
|
||||
val loadRespFault = !forwardPending && (lsu.io.pageFault || lsu.io.accessFault || lsu.io.misaligned)
|
||||
val storeCheckPending = RegInit(false.B)
|
||||
val storeCheckPendingRob = Reg(UInt(robBits.W))
|
||||
dontTouch(storeCheckPending)
|
||||
val storeCheckRespNow = Wire(Bool())
|
||||
val storeCheckRespPending = storeCheckPending && lsu.io.respValid
|
||||
val storeCheckResp = storeCheckRespNow || storeCheckRespPending
|
||||
val storeCheckFault = storeCheckResp && (lsu.io.pageFault || lsu.io.accessFault || lsu.io.misaligned)
|
||||
val memIssue = Wire(Vec(p.issueWidth, Bool()))
|
||||
for (i <- 0 until p.issueWidth) {
|
||||
memIssue(i) := issue.io.outValid(i) && (issue.io.out(i).decoded.isLoad || issue.io.out(i).decoded.isStore)
|
||||
@@ -103,22 +130,47 @@ class OoOBackend(p: CoreParams = CoreParams()) extends Module {
|
||||
val memSlot0 = memIssue(0)
|
||||
val memSlot1 = !memSlot0 && memIssue(1)
|
||||
val memSlot = Mux(memSlot0, 0.U, 1.U)
|
||||
val canIssueMem = !loadPending && !forwardPending
|
||||
val canIssueMem = !loadPending && !forwardPending && !storeCheckPending
|
||||
val issue_io_outReady_0 = Wire(Bool())
|
||||
val issue_io_outReady_1 = Wire(Bool())
|
||||
dontTouch(issue_io_outReady_0)
|
||||
dontTouch(issue_io_outReady_1)
|
||||
val isMem0 = issue.io.out(0).decoded.isLoad || issue.io.out(0).decoded.isStore
|
||||
val isMem1 = issue.io.out(1).decoded.isLoad || issue.io.out(1).decoded.isStore
|
||||
val serializing0 = issue.io.out(0).decoded.isSystem || issue.io.out(0).decoded.isFenceI ||
|
||||
issue.io.out(0).decoded.isSfenceVma || issue.io.out(0).decoded.isWfi
|
||||
val serializing1 = issue.io.out(1).decoded.isSystem || issue.io.out(1).decoded.isFenceI ||
|
||||
issue.io.out(1).decoded.isSfenceVma || issue.io.out(1).decoded.isWfi
|
||||
val serializingReady0 = !serializing0 ||
|
||||
(rename.io.commitEntry(0).valid && rename.io.commitEntry(0).robIdx === issue.io.out(0).robIdx)
|
||||
val serializingReady1 = !serializing1 ||
|
||||
(rename.io.commitEntry(0).valid && rename.io.commitEntry(0).robIdx === issue.io.out(1).robIdx)
|
||||
dontTouch(serializingReady0)
|
||||
dontTouch(serializingReady1)
|
||||
val loadBlocked0 = issue.io.out(0).decoded.isLoad && sq.io.forwardBlock
|
||||
val loadBlocked1 = issue.io.out(1).decoded.isLoad && sq.io.forwardBlock
|
||||
val amoBlocked0 = issue.io.out(0).decoded.isAmo && (sq.io.olderStoreValid || sq.io.drainValid)
|
||||
val amoBlocked1 = issue.io.out(1).decoded.isAmo && (sq.io.olderStoreValid || sq.io.drainValid)
|
||||
val robHeadValid = rename.io.commitEntry(0).valid
|
||||
val issue0AtHead = robHeadValid && rename.io.commitEntry(0).robIdx === issue.io.out(0).robIdx
|
||||
val issue1AtHead = robHeadValid && rename.io.commitEntry(0).robIdx === issue.io.out(1).robIdx
|
||||
val olderSerializingAtHead0 = robHeadValid && !issue0AtHead &&
|
||||
(rename.io.commitEntry(0).csrValid || rename.io.commitEntry(0).fenceI ||
|
||||
rename.io.commitEntry(0).sfenceVma || rename.io.commitEntry(0).xret)
|
||||
val olderSerializingAtHead1 = robHeadValid && !issue1AtHead &&
|
||||
(rename.io.commitEntry(0).csrValid || rename.io.commitEntry(0).fenceI ||
|
||||
rename.io.commitEntry(0).sfenceVma || rename.io.commitEntry(0).xret)
|
||||
val memReady0 = (!isMem0 || (lsu.io.reqReady && canIssueMem && !amoBlocked0 && !loadBlocked0)) &&
|
||||
!loadPending && !forwardPending
|
||||
val memReady1 = !isMem1 || (lsu.io.reqReady && canIssueMem && !memSlot0 && !amoBlocked1 && !loadBlocked1)
|
||||
issue_io_outReady_0 := memReady0
|
||||
issue_io_outReady_1 := memReady1 && !stallSecondCsrRead
|
||||
!loadPending && !forwardPending && serializingReady0 && !olderSerializingAtHead0
|
||||
val memReady1 = (!isMem1 || (lsu.io.reqReady && canIssueMem && !memSlot0 && !amoBlocked1 && !loadBlocked1)) &&
|
||||
serializingReady1 && !olderSerializingAtHead1
|
||||
val baseIssueReady0 = memReady0 && !storeCheckPending
|
||||
val baseIssueReady1 = memReady1 && !storeCheckPending
|
||||
val slot0WouldIssueSerializing = issue.io.outValid(0) && baseIssueReady0 && serializing0
|
||||
val slot1WouldIssueSerializing = issue.io.outValid(1) && baseIssueReady1 && serializing1
|
||||
issue_io_outReady_0 := baseIssueReady0 && !slot1WouldIssueSerializing
|
||||
issue_io_outReady_1 := baseIssueReady1 && !slot0WouldIssueSerializing &&
|
||||
!(stallSecondCsrRead && issue_io_outReady_0)
|
||||
issue.io.outReady := VecInit(Seq(issue_io_outReady_0, issue_io_outReady_1))
|
||||
val issueFire = Wire(Vec(p.issueWidth, Bool()))
|
||||
for (i <- 0 until p.issueWidth) {
|
||||
@@ -132,12 +184,19 @@ class OoOBackend(p: CoreParams = CoreParams()) extends Module {
|
||||
val memSrc1 = Mux(memSlot0, prf.io.rdata(0), prf.io.rdata(2))
|
||||
val memSrc2 = Mux(memSlot0, prf.io.rdata(1), prf.io.rdata(3))
|
||||
val memAddr = memSrc1 + Mux(memDecoded.isAmo, 0.U, Mux(memDecoded.isStore, memDecoded.immS, memDecoded.immI))
|
||||
def accessBytes(size: UInt): UInt = MuxLookup(size, 8.U(4.W))(Seq(
|
||||
0.U -> 1.U(4.W),
|
||||
1.U -> 2.U(4.W),
|
||||
2.U -> 4.U(4.W),
|
||||
3.U -> 8.U(4.W)
|
||||
))
|
||||
|
||||
val loadEnq = (memSlot0 || memSlot1) && memDecoded.isLoad && issue.io.outReady(memSlot)
|
||||
val storeEnq = (memSlot0 || memSlot1) && memDecoded.isStore && issue.io.outReady(memSlot)
|
||||
val sqForwardValid = sq.io.forwardValid && !memDecoded.isAmo
|
||||
val forwardLoad = loadEnq && sqForwardValid
|
||||
val lsuLoadReq = loadEnq && !sqForwardValid
|
||||
val lsuStoreCheckReq = storeEnq
|
||||
val forwardByte = sq.io.forwardData(7, 0)
|
||||
val forwardHalf = sq.io.forwardData(15, 0)
|
||||
val forwardWord = sq.io.forwardData(31, 0)
|
||||
@@ -183,10 +242,15 @@ class OoOBackend(p: CoreParams = CoreParams()) extends Module {
|
||||
rename.io.commitEntry(1).opClass === Consts.OP_STORE
|
||||
sq.io.commitValid := commitStore0 || commitStore1
|
||||
sq.io.commitRobIdx := Mux(commitStore0, rename.io.commitEntry(0).robIdx, rename.io.commitEntry(1).robIdx)
|
||||
sq.io.drainReady := !lsuLoadReq && lsu.io.reqReady
|
||||
val storeDrainFire = sq.io.drainValid && !lsuLoadReq && !lsuStoreCheckReq && lsu.io.reqReady
|
||||
sq.io.drainReady := storeDrainFire
|
||||
sq.io.flush := commit.io.flush
|
||||
|
||||
lsu.io.reqValid := lsuLoadReq || sq.io.drainValid
|
||||
lsu.io.reqValid := lsuLoadReq || lsuStoreCheckReq || storeDrainFire
|
||||
lsu.io.checkOnly := lsuStoreCheckReq
|
||||
lsu.io.sfenceVma := commit.io.sfenceVma
|
||||
lsu.io.currentPriv := io.currentPriv
|
||||
lsu.io.mstatus := csr.io.mstatus
|
||||
val loadReq = WireDefault(0.U.asTypeOf(new MemRequest(p)))
|
||||
loadReq.addr := memAddr
|
||||
loadReq.data := memSrc2
|
||||
@@ -195,20 +259,42 @@ class OoOBackend(p: CoreParams = CoreParams()) extends Module {
|
||||
loadReq.isAmo := memDecoded.isAmo
|
||||
loadReq.amoOp := memDecoded.amoOp
|
||||
loadReq.size := memDecoded.memWidth
|
||||
lsu.io.req := Mux(lsuLoadReq, loadReq, sq.io.drain)
|
||||
val storeCheckReq = WireDefault(0.U.asTypeOf(new MemRequest(p)))
|
||||
storeCheckReq.addr := memAddr
|
||||
storeCheckReq.data := memSrc2
|
||||
storeCheckReq.isStore := true.B
|
||||
storeCheckReq.isSigned := false.B
|
||||
storeCheckReq.isAmo := false.B
|
||||
storeCheckReq.amoOp := 0.U
|
||||
storeCheckReq.size := memDecoded.memWidth
|
||||
lsu.io.req := Mux(lsuLoadReq, loadReq, Mux(lsuStoreCheckReq, storeCheckReq, sq.io.drain))
|
||||
storeCheckRespNow := lsuStoreCheckReq && lsu.io.respValid
|
||||
lsu.io.dmemRespValid := io.dmemRespValid
|
||||
lsu.io.dmemRespData := io.dmemRespData
|
||||
lsu.io.satp := csr.io.satp
|
||||
io.satpOut := csr.io.satp
|
||||
io.dmemReqValid := lsu.io.dmemReqValid
|
||||
io.dmemReq := lsu.io.dmemReq
|
||||
|
||||
val csrReadFire = VecInit((0 until p.issueWidth).map(i => csrReadReq(i) && issue.io.outReady(i)))
|
||||
csr.io.readAddr := Mux(csrReadFire(0), issue.io.out(0).decoded.inst(31, 20), issue.io.out(1).decoded.inst(31, 20))
|
||||
csr.io.currentPriv := io.currentPriv
|
||||
csrRData(0) := csr.io.rdata
|
||||
csrRData(1) := csr.io.rdata
|
||||
csr.io.trap := commit.io.flush && commit.io.exception
|
||||
csr.io.trapPc := commit.io.badAddr
|
||||
csr.io.trapPc := commit.io.trapPc
|
||||
csr.io.trapCause := commit.io.exceptionCause
|
||||
csr.io.trapTval := commit.io.badAddr
|
||||
val trapTargetPriv = PrivilegeTransitions.trapTargetPriv(
|
||||
io.currentPriv,
|
||||
commit.io.exceptionCause,
|
||||
false.B,
|
||||
csr.io.medeleg,
|
||||
csr.io.mideleg)
|
||||
csr.io.trapTargetPriv := trapTargetPriv
|
||||
csr.io.trapIsInterrupt := false.B
|
||||
csr.io.xret := commit.io.flush && commit.io.xret
|
||||
csr.io.xretIsMret := commit.io.xretIsMret
|
||||
val commitCsr0 = commit.io.commitReady(0) && rename.io.commitValid(0) && rename.io.commitEntry(0).csrValid
|
||||
val commitCsr1 = commit.io.commitReady(1) && rename.io.commitValid(1) && rename.io.commitEntry(1).csrValid
|
||||
val commitCsrEntry = Mux(commitCsr0, rename.io.commitEntry(0), rename.io.commitEntry(1))
|
||||
@@ -221,6 +307,7 @@ class OoOBackend(p: CoreParams = CoreParams()) extends Module {
|
||||
when(commit.io.flush) {
|
||||
loadPending := false.B
|
||||
forwardPending := false.B
|
||||
storeCheckPending := false.B
|
||||
}.elsewhen(forwardLoad) {
|
||||
forwardPending := true.B
|
||||
forwardPendingRob := issue.io.out(memSlot).robIdx
|
||||
@@ -237,6 +324,14 @@ class OoOBackend(p: CoreParams = CoreParams()) extends Module {
|
||||
}.elsewhen(loadRespValid) {
|
||||
loadPending := false.B
|
||||
}
|
||||
when(!commit.io.flush) {
|
||||
when(storeCheckRespPending) {
|
||||
storeCheckPending := false.B
|
||||
}.elsewhen(lsuStoreCheckReq && !storeCheckRespNow) {
|
||||
storeCheckPending := true.B
|
||||
storeCheckPendingRob := issue.io.out(memSlot).robIdx
|
||||
}
|
||||
}
|
||||
|
||||
for (i <- 0 until p.issueWidth) {
|
||||
prf.io.raddr(2 * i) := issue.io.out(i).prs1
|
||||
@@ -245,8 +340,12 @@ class OoOBackend(p: CoreParams = CoreParams()) extends Module {
|
||||
|
||||
for (i <- 0 until p.issueWidth) {
|
||||
val decoded = issue.io.out(i).decoded
|
||||
val src1 = prf.io.rdata(2 * i)
|
||||
val rs2Val = prf.io.rdata(2 * i + 1)
|
||||
val src1Raw = prf.io.rdata(2 * i)
|
||||
val rs2Raw = prf.io.rdata(2 * i + 1)
|
||||
val src1 = MuxCase(src1Raw, (0 until p.issueWidth).map(w =>
|
||||
(wakeupReg(w).valid && wakeupReg(w).phys =/= 0.U && wakeupReg(w).phys === issue.io.out(i).prs1) -> wakeupReg(w).data))
|
||||
val rs2Val = MuxCase(rs2Raw, (0 until p.issueWidth).map(w =>
|
||||
(wakeupReg(w).valid && wakeupReg(w).phys =/= 0.U && wakeupReg(w).phys === issue.io.out(i).prs2) -> wakeupReg(w).data))
|
||||
val src2 = Mux(decoded.isOpImm || decoded.isLoad || decoded.isJalr, decoded.immI, rs2Val)
|
||||
|
||||
exec(i).io.inValid := issueFire(i)
|
||||
@@ -254,8 +353,40 @@ class OoOBackend(p: CoreParams = CoreParams()) extends Module {
|
||||
exec(i).io.src1 := src1
|
||||
exec(i).io.src2 := src2
|
||||
|
||||
val isLoadRespSlot = i.U === 0.U && loadRespValid
|
||||
val useExecWb = exec(i).io.outValid && decoded.writesRd && !decoded.isLoad
|
||||
val branchTarget = decoded.pc + decoded.immB
|
||||
val jalTarget = decoded.pc + decoded.immJ
|
||||
val jalrTarget = (src1 + decoded.immI) & (~1.U(p.xlen.W))
|
||||
val controlTarget = Mux(decoded.isJal, jalTarget,
|
||||
Mux(decoded.isJalr, jalrTarget, branchTarget))
|
||||
val controlTargetMisaligned = issueFire(i) &&
|
||||
(decoded.isJal || decoded.isJalr || (decoded.isBranch && exec(i).io.branchTaken)) &&
|
||||
controlTarget(1, 0) =/= 0.U
|
||||
dontTouch(controlTargetMisaligned)
|
||||
val branchRedirect = Mux(decoded.isJal, jalTarget,
|
||||
Mux(decoded.isJalr, jalrTarget,
|
||||
Mux(decoded.isBranch && exec(i).io.branchTaken, branchTarget, decoded.pc + 4.U)))
|
||||
val isEcall = decoded.isEcall
|
||||
val isEbreak = decoded.isEbreak
|
||||
val isMret = decoded.isMret
|
||||
val illegalPriv = (decoded.isMret && io.currentPriv =/= Privileged.PRV_M) ||
|
||||
(decoded.isSret && io.currentPriv === Privileged.PRV_U) ||
|
||||
(decoded.isSfenceVma && io.currentPriv === Privileged.PRV_U)
|
||||
val csrReadIllegal = csrReadFire(i) && csr.io.readIllegal
|
||||
val csrWrites = decoded.isSystem && decoded.funct3 =/= 0.U &&
|
||||
!(decoded.funct3(1) && decoded.rs1 === 0.U)
|
||||
val csrWriteIllegal = csrWrites && !CSRPermission.writeAllowed(decoded.inst(31, 20), io.currentPriv)
|
||||
val illegalInst = !decoded.fetchException && (decoded.illegal || illegalPriv || csrReadIllegal || csrWriteIllegal)
|
||||
val dataAddr = src1 + Mux(decoded.isStore, decoded.immS, decoded.immI)
|
||||
val dataMisaligned = (dataAddr(2, 0) & (accessBytes(decoded.memWidth) - 1.U)) =/= 0.U
|
||||
val storeMisaligned = issueFire(i) && decoded.isStore && dataMisaligned
|
||||
|
||||
val loadFaultNow = lsuLoadReq && lsu.io.respValid && (lsu.io.misaligned || lsu.io.pageFault || lsu.io.accessFault)
|
||||
val issueRaisesException = issueFire(i) &&
|
||||
(decoded.fetchException || illegalInst || isEcall || isEbreak || lq.io.violation || storeMisaligned ||
|
||||
controlTargetMisaligned)
|
||||
val loadRespHasFault = loadRespFault || loadFaultNow
|
||||
val isLoadRespSlot = i.U === 0.U && loadRespValid && !loadRespHasFault
|
||||
val useExecWb = exec(i).io.outValid && decoded.writesRd && !decoded.isLoad && !issueRaisesException
|
||||
wb(i).io.valid := useExecWb || isLoadRespSlot
|
||||
wb(i).io.physDest := Mux(isLoadRespSlot, Mux(forwardPending, forwardPendingPhys, loadPendingPhys), issue.io.out(i).prd)
|
||||
wb(i).io.data := Mux(isLoadRespSlot, loadRespData, Mux(decoded.isLui, decoded.immU,
|
||||
@@ -271,36 +402,47 @@ class OoOBackend(p: CoreParams = CoreParams()) extends Module {
|
||||
wakeup(i).phys := wb(i).io.waddr
|
||||
wakeup(i).data := wb(i).io.wdata
|
||||
|
||||
val branchTarget = decoded.pc + decoded.immB
|
||||
val jalTarget = decoded.pc + decoded.immJ
|
||||
val jalrTarget = (src1 + decoded.immI) & (~1.U(p.xlen.W))
|
||||
val branchRedirect = Mux(decoded.isJal, jalTarget,
|
||||
Mux(decoded.isJalr, jalrTarget,
|
||||
Mux(decoded.isBranch && exec(i).io.branchTaken, branchTarget, decoded.pc + 4.U)))
|
||||
val isEcall = decoded.inst === "h00000073".U
|
||||
val isEbreak = decoded.inst === "h00100073".U
|
||||
val isMret = decoded.inst === "h30200073".U
|
||||
|
||||
val completeLoadResp = i.U === 0.U && loadRespValid
|
||||
completeValid(i) := (issueFire(i) && !decoded.isLoad) || completeLoadResp
|
||||
completeIdx(i) := Mux(completeLoadResp, Mux(forwardPending, forwardPendingRob, loadPendingRob), issue.io.out(i).robIdx)
|
||||
completeException(i) := (issueFire(i) && (decoded.illegal || isEcall || isEbreak || lq.io.violation)) ||
|
||||
(completeLoadResp && loadRespPageFault)
|
||||
completeCause(i) := Mux(completeLoadResp && loadRespPageFault, 13.U,
|
||||
Mux(issueFire(i) && isEbreak, 3.U,
|
||||
Mux(issueFire(i) && isEcall, 11.U,
|
||||
Mux(issueFire(i) && decoded.illegal, 2.U, 0.U))))
|
||||
completeBadAddr(i) := decoded.pc
|
||||
val completeLoadResp = i.U === 0.U && (loadRespValid || loadFaultNow)
|
||||
val completeStoreResp = (i.U === 0.U && storeCheckRespPending) ||
|
||||
(storeCheckRespNow && issueFire(i) && decoded.isStore)
|
||||
completeValid(i) := (issueFire(i) && !decoded.isLoad && !decoded.isStore) || completeLoadResp || completeStoreResp
|
||||
val storeCompleteIdx = Mux(storeCheckRespPending, storeCheckPendingRob, issue.io.out(i).robIdx)
|
||||
completeIdx(i) := Mux(completeStoreResp, storeCompleteIdx,
|
||||
Mux(completeLoadResp, Mux(loadFaultNow, issue.io.out(memSlot).robIdx, Mux(forwardPending, forwardPendingRob, loadPendingRob)),
|
||||
issue.io.out(i).robIdx))
|
||||
val issueException = issueRaisesException
|
||||
val thisStoreCheckFault = completeStoreResp && storeCheckFault
|
||||
completeException(i) := issueException || (completeLoadResp && (loadRespFault || loadFaultNow)) || thisStoreCheckFault
|
||||
completeCause(i) := Mux(thisStoreCheckFault || (completeLoadResp && (loadRespFault || loadFaultNow)), lsu.io.faultCause,
|
||||
Mux(issueFire(i) && decoded.fetchException, decoded.fetchExceptionCause,
|
||||
Mux(issueFire(i) && isEbreak, Privileged.CAUSE_BREAKPOINT,
|
||||
Mux(issueFire(i) && isEcall, ExceptionSource.ecallCause(io.currentPriv),
|
||||
Mux(storeMisaligned, Privileged.CAUSE_STORE_ADDR_MISALIGNED,
|
||||
Mux(controlTargetMisaligned, Privileged.CAUSE_INSTR_ADDR_MISALIGNED,
|
||||
Mux(issueFire(i) && illegalInst, Privileged.CAUSE_ILLEGAL_INSTRUCTION, 0.U)))))))
|
||||
completeBadAddr(i) := Mux(thisStoreCheckFault || (completeLoadResp && (loadRespFault || loadFaultNow)), lsu.io.faultAddr,
|
||||
Mux(storeMisaligned, dataAddr,
|
||||
Mux(issueFire(i) && decoded.fetchException, decoded.fetchExceptionTval,
|
||||
Mux(controlTargetMisaligned, controlTarget,
|
||||
Mux(issueFire(i) && illegalInst, decoded.inst.pad(p.xlen), 0.U)))))
|
||||
completeMispredict(i) := issueFire(i) &&
|
||||
(decoded.isJal || decoded.isJalr || isMret || decoded.isFenceI ||
|
||||
(decoded.isJal || decoded.isJalr || decoded.isXret || decoded.isFenceI || decoded.isSfenceVma || decoded.isWfi ||
|
||||
(decoded.isBranch && exec(i).io.branchTaken))
|
||||
completeRedirectPc(i) := Mux(isEcall || isEbreak, csr.io.mtvec, Mux(isMret, csr.io.mepc, branchRedirect))
|
||||
completeRedirectPc(i) := Mux(isEcall || isEbreak,
|
||||
csr.io.trapVector,
|
||||
Mux(decoded.isXret,
|
||||
PrivilegeTransitions.xretTargetPc(decoded.isMret, csr.io.mepc, csr.io.sepc),
|
||||
Mux(decoded.isWfi, decoded.pc + 4.U, branchRedirect)))
|
||||
completeCsrValid(i) := issueFire(i) && decoded.isSystem && decoded.funct3 =/= 0.U &&
|
||||
!(decoded.funct3(1) && decoded.rs1 === 0.U)
|
||||
!(decoded.funct3(1) && decoded.rs1 === 0.U) && !illegalInst
|
||||
completeCsrAddr(i) := decoded.inst(31, 20)
|
||||
completeCsrCmd(i) := decoded.funct3
|
||||
completeCsrRs1(i) := src1
|
||||
completeCsrZimm(i) := decoded.rs1
|
||||
completeFenceI(i) := issueFire(i) && decoded.isFenceI
|
||||
completeSfenceVma(i) := issueFire(i) && decoded.isSfenceVma
|
||||
completeXret(i) := issueFire(i) && decoded.isXret
|
||||
completeXretIsMret(i) := issueFire(i) && decoded.isMret
|
||||
}
|
||||
wakeupReg := wakeup
|
||||
|
||||
@@ -310,8 +452,16 @@ class OoOBackend(p: CoreParams = CoreParams()) extends Module {
|
||||
io.commitValid := VecInit((0 until p.issueWidth).map(i => rename.io.commitValid(i) && commit.io.commitReady(i)))
|
||||
io.commitEntry := rename.io.commitEntry
|
||||
io.flush := commit.io.flush
|
||||
io.redirectPc := Mux(commit.io.exception, csr.io.mtvec, commit.io.redirectPc)
|
||||
val xretRedirectPc = PrivilegeTransitions.xretTargetPc(commit.io.xretIsMret, csr.io.mepc, csr.io.sepc)
|
||||
dontTouch(xretRedirectPc)
|
||||
io.redirectPc := Mux(commit.io.exception, csr.io.trapVector,
|
||||
Mux(commit.io.xret, xretRedirectPc, commit.io.redirectPc))
|
||||
io.invalidateICache := commit.io.fenceI
|
||||
io.sfenceVma := commit.io.sfenceVma
|
||||
io.setPriv := commit.io.setPriv
|
||||
io.targetPriv := Mux(commit.io.exception,
|
||||
trapTargetPriv,
|
||||
Mux(commit.io.xret, PrivilegeTransitions.xretNextPriv(commit.io.xretIsMret, csr.io.mstatus), io.currentPriv))
|
||||
}
|
||||
|
||||
object OoOBackend extends App {
|
||||
|
||||
@@ -18,11 +18,18 @@ class CommitStage(p: CoreParams = CoreParams()) extends Module {
|
||||
val exception = Output(Bool())
|
||||
val exceptionCause = Output(UInt(p.xlen.W))
|
||||
val badAddr = Output(UInt(p.xlen.W))
|
||||
val trapPc = Output(UInt(p.xlen.W))
|
||||
val fenceI = Output(Bool())
|
||||
val sfenceVma = Output(Bool())
|
||||
val xret = Output(Bool())
|
||||
val xretIsMret = Output(Bool())
|
||||
val setPriv = Output(Bool())
|
||||
})
|
||||
|
||||
val firstTrap = io.robValid(0) && (io.robEntry(0).exception || io.robEntry(0).branchMispredict)
|
||||
val secondTrap = io.robValid(1) && (io.robEntry(1).exception || io.robEntry(1).branchMispredict)
|
||||
val firstTrap = io.robValid(0) && (io.robEntry(0).exception || io.robEntry(0).branchMispredict ||
|
||||
io.robEntry(0).xret || io.robEntry(0).sfenceVma || io.robEntry(0).fenceI)
|
||||
val secondTrap = io.robValid(1) && (io.robEntry(1).exception || io.robEntry(1).branchMispredict ||
|
||||
io.robEntry(1).xret || io.robEntry(1).sfenceVma || io.robEntry(1).fenceI)
|
||||
val twoCsrWrites = io.robValid(0) && io.robValid(1) &&
|
||||
io.robEntry(0).csrValid && io.robEntry(1).csrValid
|
||||
val firstStore = io.robValid(0) && io.robEntry(0).opClass === Consts.OP_STORE
|
||||
@@ -31,10 +38,11 @@ class CommitStage(p: CoreParams = CoreParams()) extends Module {
|
||||
|
||||
for (i <- 0 until p.issueWidth) {
|
||||
val doCommit = io.commitReady(i)
|
||||
io.freeOldPhys(i) := doCommit && io.robEntry(i).writesDest &&
|
||||
val commitWritesDest = doCommit && !io.robEntry(i).exception && io.robEntry(i).writesDest
|
||||
io.freeOldPhys(i) := commitWritesDest &&
|
||||
io.robEntry(i).oldDest =/= io.robEntry(i).dest
|
||||
io.oldPhys(i) := io.robEntry(i).oldDest
|
||||
io.commitMapValid(i) := doCommit && io.robEntry(i).writesDest &&
|
||||
io.commitMapValid(i) := commitWritesDest &&
|
||||
io.robEntry(i).archDest =/= 0.U
|
||||
io.commitArch(i) := io.robEntry(i).archDest
|
||||
io.commitPhys(i) := io.robEntry(i).dest
|
||||
@@ -50,6 +58,15 @@ class CommitStage(p: CoreParams = CoreParams()) extends Module {
|
||||
Mux(secondTrapSelected, io.robEntry(1).exceptionCause, 0.U))
|
||||
io.badAddr := Mux(firstTrap, io.robEntry(0).badAddr,
|
||||
Mux(secondTrapSelected, io.robEntry(1).badAddr, 0.U))
|
||||
io.trapPc := Mux(firstTrap, io.robEntry(0).pc,
|
||||
Mux(secondTrapSelected, io.robEntry(1).pc, 0.U))
|
||||
io.fenceI := io.commitReady(0) && io.robEntry(0).fenceI ||
|
||||
io.commitReady(1) && io.robEntry(1).fenceI
|
||||
io.sfenceVma := io.commitReady(0) && io.robEntry(0).sfenceVma ||
|
||||
io.commitReady(1) && io.robEntry(1).sfenceVma
|
||||
io.xret := io.commitReady(0) && io.robEntry(0).xret ||
|
||||
io.commitReady(1) && io.robEntry(1).xret
|
||||
io.xretIsMret := Mux(firstTrap, io.robEntry(0).xretIsMret,
|
||||
Mux(secondTrapSelected, io.robEntry(1).xretIsMret, true.B))
|
||||
io.setPriv := selectedTrap && (io.exception || io.xret)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,9 @@ class FetchPacket(p: CoreParams = CoreParams()) extends Bundle {
|
||||
val laneValid = Vec(p.fetchWidth, Bool())
|
||||
val predictedTaken = Bool()
|
||||
val predictedTarget = UInt(p.xlen.W)
|
||||
val exception = Bool()
|
||||
val exceptionCause = UInt(p.xlen.W)
|
||||
val exceptionTval = UInt(p.xlen.W)
|
||||
}
|
||||
|
||||
class BranchUpdate(p: CoreParams = CoreParams()) extends Bundle {
|
||||
@@ -48,10 +51,21 @@ class DecodedInst(p: CoreParams = CoreParams()) extends Bundle {
|
||||
val isWord = Bool()
|
||||
val isSystem = Bool()
|
||||
val isFenceI = Bool()
|
||||
val isEcall = Bool()
|
||||
val isEbreak = Bool()
|
||||
val isMret = Bool()
|
||||
val isSret = Bool()
|
||||
val isUret = Bool()
|
||||
val isSfenceVma = Bool()
|
||||
val isXret = Bool()
|
||||
val isWfi = Bool()
|
||||
val isAmo = Bool()
|
||||
val amoOp = UInt(5.W)
|
||||
val writesRd = Bool()
|
||||
val illegal = Bool()
|
||||
val fetchException = Bool()
|
||||
val fetchExceptionCause = UInt(p.xlen.W)
|
||||
val fetchExceptionTval = UInt(p.xlen.W)
|
||||
}
|
||||
|
||||
class RenamePacket(p: CoreParams = CoreParams()) extends Bundle {
|
||||
@@ -90,11 +104,23 @@ class CsrCommand(p: CoreParams = CoreParams()) extends Bundle {
|
||||
val zimm = UInt(5.W)
|
||||
}
|
||||
|
||||
class TrapInfo(p: CoreParams = CoreParams()) extends Bundle {
|
||||
val valid = Bool()
|
||||
val isInterrupt = Bool()
|
||||
val cause = UInt(p.xlen.W)
|
||||
val tval = UInt(p.xlen.W)
|
||||
val epc = UInt(p.xlen.W)
|
||||
val originPriv = UInt(2.W)
|
||||
}
|
||||
|
||||
class TlbReq(p: CoreParams = CoreParams()) extends Bundle {
|
||||
val valid = Bool()
|
||||
val vaddr = UInt(p.xlen.W)
|
||||
val isStore = Bool()
|
||||
val isFetch = Bool()
|
||||
val priv = UInt(2.W)
|
||||
val sum = Bool()
|
||||
val mxr = Bool()
|
||||
}
|
||||
|
||||
class TlbResp(p: CoreParams = CoreParams()) extends Bundle {
|
||||
|
||||
77
src/main/scala/common/Privileged.scala
Normal file
77
src/main/scala/common/Privileged.scala
Normal file
@@ -0,0 +1,77 @@
|
||||
import chisel3._
|
||||
|
||||
object Privileged {
|
||||
val MISA_RV64_IMASU = "h8000000000141101".U(64.W)
|
||||
|
||||
val PRV_U = 0.U(2.W)
|
||||
val PRV_S = 1.U(2.W)
|
||||
val PRV_M = 3.U(2.W)
|
||||
|
||||
val MSTATUS_MPRV_BIT = 17
|
||||
val MSTATUS_SUM_BIT = 18
|
||||
val MSTATUS_MXR_BIT = 19
|
||||
val MSTATUS_MPP_HI = 12
|
||||
val MSTATUS_MPP_LO = 11
|
||||
|
||||
val CAUSE_INSTR_ADDR_MISALIGNED = 0.U(8.W)
|
||||
val CAUSE_INSTR_ACCESS_FAULT = 1.U(8.W)
|
||||
val CAUSE_ILLEGAL_INSTRUCTION = 2.U(8.W)
|
||||
val CAUSE_BREAKPOINT = 3.U(8.W)
|
||||
val CAUSE_LOAD_ADDR_MISALIGNED = 4.U(8.W)
|
||||
val CAUSE_LOAD_ACCESS_FAULT = 5.U(8.W)
|
||||
val CAUSE_STORE_ADDR_MISALIGNED = 6.U(8.W)
|
||||
val CAUSE_STORE_ACCESS_FAULT = 7.U(8.W)
|
||||
val CAUSE_ECALL_FROM_U = 8.U(8.W)
|
||||
val CAUSE_ECALL_FROM_S = 9.U(8.W)
|
||||
val CAUSE_ECALL_FROM_M = 11.U(8.W)
|
||||
val CAUSE_INSTR_PAGE_FAULT = 12.U(8.W)
|
||||
val CAUSE_LOAD_PAGE_FAULT = 13.U(8.W)
|
||||
val CAUSE_STORE_PAGE_FAULT = 15.U(8.W)
|
||||
|
||||
val CAUSE_SUPERVISOR_SOFTWARE_INTERRUPT = 1.U(8.W)
|
||||
val CAUSE_MACHINE_SOFTWARE_INTERRUPT = 3.U(8.W)
|
||||
val CAUSE_SUPERVISOR_TIMER_INTERRUPT = 5.U(8.W)
|
||||
val CAUSE_MACHINE_TIMER_INTERRUPT = 7.U(8.W)
|
||||
val CAUSE_SUPERVISOR_EXTERNAL_INTERRUPT = 9.U(8.W)
|
||||
val CAUSE_MACHINE_EXTERNAL_INTERRUPT = 11.U(8.W)
|
||||
|
||||
val CSR_SSTATUS = "h100".U(12.W)
|
||||
val CSR_SIE = "h104".U(12.W)
|
||||
val CSR_STVEC = "h105".U(12.W)
|
||||
val CSR_SCOUNTEREN = "h106".U(12.W)
|
||||
val CSR_SSCRATCH = "h140".U(12.W)
|
||||
val CSR_SEPC = "h141".U(12.W)
|
||||
val CSR_SCAUSE = "h142".U(12.W)
|
||||
val CSR_STVAL = "h143".U(12.W)
|
||||
val CSR_SIP = "h144".U(12.W)
|
||||
val CSR_SATP = "h180".U(12.W)
|
||||
|
||||
val CSR_MSTATUS = "h300".U(12.W)
|
||||
val CSR_MISA = "h301".U(12.W)
|
||||
val CSR_MEDELEG = "h302".U(12.W)
|
||||
val CSR_MIDELEG = "h303".U(12.W)
|
||||
val CSR_MIE = "h304".U(12.W)
|
||||
val CSR_MTVEC = "h305".U(12.W)
|
||||
val CSR_MCOUNTEREN = "h306".U(12.W)
|
||||
val CSR_MCOUNTINHIBIT = "h320".U(12.W)
|
||||
val CSR_MSCRATCH = "h340".U(12.W)
|
||||
val CSR_MEPC = "h341".U(12.W)
|
||||
val CSR_MCAUSE = "h342".U(12.W)
|
||||
val CSR_MTVAL = "h343".U(12.W)
|
||||
val CSR_MIP = "h344".U(12.W)
|
||||
val CSR_PMPCFG0 = "h3a0".U(12.W)
|
||||
val CSR_PMPADDR0 = "h3b0".U(12.W)
|
||||
val CSR_TSELECT = "h7a0".U(12.W)
|
||||
val CSR_TDATA1 = "h7a1".U(12.W)
|
||||
val CSR_TDATA2 = "h7a2".U(12.W)
|
||||
val CSR_TCONTROL = "h7a5".U(12.W)
|
||||
val CSR_MNSTATUS = "h744".U(12.W)
|
||||
val CSR_MINSTRET = "hb02".U(12.W)
|
||||
val CSR_MVENDORID = "hf11".U(12.W)
|
||||
val CSR_MARCHID = "hf12".U(12.W)
|
||||
val CSR_MIMPID = "hf13".U(12.W)
|
||||
val CSR_MHARTID = "hf14".U(12.W)
|
||||
val CSR_CYCLE = "hc00".U(12.W)
|
||||
val CSR_TIME = "hc01".U(12.W)
|
||||
val CSR_INSTRET = "hc02".U(12.W)
|
||||
}
|
||||
@@ -5,20 +5,42 @@ class CSRFile(p: CoreParams = CoreParams()) extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val cmd = Input(new CsrCommand(p))
|
||||
val readAddr = Input(UInt(12.W))
|
||||
val currentPriv = Input(UInt(2.W))
|
||||
val rdata = Output(UInt(p.xlen.W))
|
||||
val readIllegal = Output(Bool())
|
||||
val writeIllegal = Output(Bool())
|
||||
val illegal = Output(Bool())
|
||||
val trap = Input(Bool())
|
||||
val trapPc = Input(UInt(p.xlen.W))
|
||||
val trapCause = Input(UInt(p.xlen.W))
|
||||
val trapTval = Input(UInt(p.xlen.W))
|
||||
val trapTargetPriv = Input(UInt(2.W))
|
||||
val trapIsInterrupt = Input(Bool())
|
||||
val trapVector = Output(UInt(p.xlen.W))
|
||||
val xret = Input(Bool())
|
||||
val xretIsMret = Input(Bool())
|
||||
val satp = Output(UInt(p.xlen.W))
|
||||
val mtvec = Output(UInt(p.xlen.W))
|
||||
val mepc = Output(UInt(p.xlen.W))
|
||||
val stvec = Output(UInt(p.xlen.W))
|
||||
val sepc = Output(UInt(p.xlen.W))
|
||||
val medeleg = Output(UInt(p.xlen.W))
|
||||
val mideleg = Output(UInt(p.xlen.W))
|
||||
val mie = Output(UInt(p.xlen.W))
|
||||
val mip = Output(UInt(p.xlen.W))
|
||||
val mstatus = Output(UInt(p.xlen.W))
|
||||
})
|
||||
|
||||
val cycle = RegInit(0.U(p.xlen.W))
|
||||
val instret = RegInit(0.U(p.xlen.W))
|
||||
val mcountinhibit = RegInit(0.U(p.xlen.W))
|
||||
val suppressInstretIncrement = WireDefault(false.B)
|
||||
val suppressInstretAfterWrite = RegInit(false.B)
|
||||
dontTouch(suppressInstretIncrement)
|
||||
val mstatus = RegInit(0.U(p.xlen.W))
|
||||
val misa = RegInit("h800000000014112d".U(p.xlen.W))
|
||||
val misa = RegInit(Privileged.MISA_RV64_IMASU)
|
||||
val mtvecReg = RegInit(0.U(p.xlen.W))
|
||||
val mscratch = RegInit(0.U(p.xlen.W))
|
||||
val mepcReg = RegInit(0.U(p.xlen.W))
|
||||
val mcause = RegInit(0.U(p.xlen.W))
|
||||
val mtval = RegInit(0.U(p.xlen.W))
|
||||
@@ -26,7 +48,14 @@ class CSRFile(p: CoreParams = CoreParams()) extends Module {
|
||||
val mideleg = RegInit(0.U(p.xlen.W))
|
||||
val mie = RegInit(0.U(p.xlen.W))
|
||||
val mip = RegInit(0.U(p.xlen.W))
|
||||
val sstatus = RegInit(0.U(p.xlen.W))
|
||||
val mcounteren = RegInit(0.U(p.xlen.W))
|
||||
val pmpcfg0 = RegInit(0.U(p.xlen.W))
|
||||
val pmpaddr0 = RegInit(0.U(p.xlen.W))
|
||||
val tdata1 = RegInit(0.U(p.xlen.W))
|
||||
val tdata2 = RegInit(0.U(p.xlen.W))
|
||||
val tcontrol = RegInit(0.U(p.xlen.W))
|
||||
val mnstatus = RegInit(0.U(p.xlen.W))
|
||||
val scounteren = RegInit(0.U(p.xlen.W))
|
||||
val stvec = RegInit(0.U(p.xlen.W))
|
||||
val sepc = RegInit(0.U(p.xlen.W))
|
||||
val scause = RegInit(0.U(p.xlen.W))
|
||||
@@ -35,59 +64,116 @@ class CSRFile(p: CoreParams = CoreParams()) extends Module {
|
||||
val satpReg = RegInit(0.U(p.xlen.W))
|
||||
|
||||
cycle := cycle + 1.U
|
||||
when(!mcountinhibit(2) && !suppressInstretIncrement && !suppressInstretAfterWrite) {
|
||||
instret := instret + 1.U
|
||||
}
|
||||
io.satp := satpReg
|
||||
io.mtvec := mtvecReg
|
||||
io.mepc := mepcReg
|
||||
io.stvec := stvec
|
||||
io.sepc := sepc
|
||||
io.medeleg := medeleg
|
||||
io.mideleg := mideleg
|
||||
io.mie := mie
|
||||
io.mip := mip
|
||||
io.mstatus := mstatus
|
||||
|
||||
val readAllowed = CSRPermission.readAllowed(io.readAddr, io.currentPriv)
|
||||
val writeAllowed = CSRPermission.writeAllowed(io.cmd.addr, io.currentPriv)
|
||||
val readIllegal = !readAllowed
|
||||
val writeIllegal = io.cmd.valid && io.cmd.cmd =/= 0.U && !writeAllowed
|
||||
val xlenStatusMask = "h0000000f00000000".U(p.xlen.W)
|
||||
val rv64XlenStatus = "h0000000a00000000".U(p.xlen.W)
|
||||
val mstatusView = (mstatus & ~xlenStatusMask) | rv64XlenStatus
|
||||
val sstatusMask = "h00000002000de162".U(p.xlen.W)
|
||||
val sstatusView = mstatusView & sstatusMask
|
||||
|
||||
val r = WireDefault(0.U(p.xlen.W))
|
||||
switch(io.readAddr) {
|
||||
is("h300".U) { r := mstatus }
|
||||
is("h301".U) { r := misa }
|
||||
is("h302".U) { r := medeleg }
|
||||
is("h303".U) { r := mideleg }
|
||||
is("h304".U) { r := mie }
|
||||
is("h305".U) { r := mtvecReg }
|
||||
is("h341".U) { r := mepcReg }
|
||||
is("h342".U) { r := mcause }
|
||||
is("h343".U) { r := mtval }
|
||||
is("h344".U) { r := mip }
|
||||
is("h100".U) { r := sstatus }
|
||||
is("h105".U) { r := stvec }
|
||||
is("h140".U) { r := sscratch }
|
||||
is("h141".U) { r := sepc }
|
||||
is("h142".U) { r := scause }
|
||||
is("h143".U) { r := stval }
|
||||
is("h180".U) { r := satpReg }
|
||||
is("hf14".U) { r := 0.U }
|
||||
is("hc00".U) { r := cycle }
|
||||
is("hc01".U) { r := 0.U }
|
||||
is("hc02".U) { r := instret }
|
||||
is(Privileged.CSR_MSTATUS) { r := mstatusView }
|
||||
is(Privileged.CSR_MISA) { r := misa }
|
||||
is(Privileged.CSR_MEDELEG) { r := medeleg }
|
||||
is(Privileged.CSR_MIDELEG) { r := mideleg }
|
||||
is(Privileged.CSR_MIE) { r := mie }
|
||||
is(Privileged.CSR_MTVEC) { r := mtvecReg }
|
||||
is(Privileged.CSR_MCOUNTEREN) { r := mcounteren }
|
||||
is(Privileged.CSR_MCOUNTINHIBIT) { r := mcountinhibit }
|
||||
is(Privileged.CSR_MSCRATCH) { r := mscratch }
|
||||
is(Privileged.CSR_MEPC) { r := mepcReg }
|
||||
is(Privileged.CSR_MCAUSE) { r := mcause }
|
||||
is(Privileged.CSR_MTVAL) { r := mtval }
|
||||
is(Privileged.CSR_MIP) { r := mip }
|
||||
is(Privileged.CSR_PMPCFG0) { r := pmpcfg0 }
|
||||
is(Privileged.CSR_PMPADDR0) { r := pmpaddr0 }
|
||||
is(Privileged.CSR_TSELECT) { r := 1.U }
|
||||
is(Privileged.CSR_TDATA1) { r := tdata1 }
|
||||
is(Privileged.CSR_TDATA2) { r := tdata2 }
|
||||
is(Privileged.CSR_TCONTROL) { r := tcontrol }
|
||||
is(Privileged.CSR_MNSTATUS) { r := mnstatus }
|
||||
is(Privileged.CSR_SSTATUS) { r := sstatusView }
|
||||
is(Privileged.CSR_SIE) { r := mie & mideleg }
|
||||
is(Privileged.CSR_STVEC) { r := stvec }
|
||||
is(Privileged.CSR_SCOUNTEREN) { r := scounteren }
|
||||
is(Privileged.CSR_SSCRATCH) { r := sscratch }
|
||||
is(Privileged.CSR_SEPC) { r := sepc }
|
||||
is(Privileged.CSR_SCAUSE) { r := scause }
|
||||
is(Privileged.CSR_STVAL) { r := stval }
|
||||
is(Privileged.CSR_SIP) { r := mip & mideleg }
|
||||
is(Privileged.CSR_SATP) { r := satpReg }
|
||||
is(Privileged.CSR_MVENDORID) { r := 0.U }
|
||||
is(Privileged.CSR_MARCHID) { r := 0.U }
|
||||
is(Privileged.CSR_MIMPID) { r := 0.U }
|
||||
is(Privileged.CSR_MHARTID) { r := 0.U }
|
||||
is(Privileged.CSR_MINSTRET) { r := instret }
|
||||
is(Privileged.CSR_CYCLE) { r := cycle }
|
||||
is(Privileged.CSR_TIME) { r := cycle }
|
||||
is(Privileged.CSR_INSTRET) { r := instret }
|
||||
}
|
||||
io.rdata := r
|
||||
io.rdata := Mux(readAllowed, r, 0.U)
|
||||
io.readIllegal := readIllegal
|
||||
io.writeIllegal := writeIllegal
|
||||
io.illegal := readIllegal || writeIllegal
|
||||
|
||||
val writeOld = WireDefault(0.U(p.xlen.W))
|
||||
switch(io.cmd.addr) {
|
||||
is("h300".U) { writeOld := mstatus }
|
||||
is("h301".U) { writeOld := misa }
|
||||
is("h302".U) { writeOld := medeleg }
|
||||
is("h303".U) { writeOld := mideleg }
|
||||
is("h304".U) { writeOld := mie }
|
||||
is("h305".U) { writeOld := mtvecReg }
|
||||
is("h341".U) { writeOld := mepcReg }
|
||||
is("h342".U) { writeOld := mcause }
|
||||
is("h343".U) { writeOld := mtval }
|
||||
is("h344".U) { writeOld := mip }
|
||||
is("h100".U) { writeOld := sstatus }
|
||||
is("h105".U) { writeOld := stvec }
|
||||
is("h140".U) { writeOld := sscratch }
|
||||
is("h141".U) { writeOld := sepc }
|
||||
is("h142".U) { writeOld := scause }
|
||||
is("h143".U) { writeOld := stval }
|
||||
is("h180".U) { writeOld := satpReg }
|
||||
is("hf14".U) { writeOld := 0.U }
|
||||
is("hc00".U) { writeOld := cycle }
|
||||
is("hc01".U) { writeOld := 0.U }
|
||||
is("hc02".U) { writeOld := instret }
|
||||
is(Privileged.CSR_MSTATUS) { writeOld := mstatusView }
|
||||
is(Privileged.CSR_MISA) { writeOld := misa }
|
||||
is(Privileged.CSR_MEDELEG) { writeOld := medeleg }
|
||||
is(Privileged.CSR_MIDELEG) { writeOld := mideleg }
|
||||
is(Privileged.CSR_MIE) { writeOld := mie }
|
||||
is(Privileged.CSR_MTVEC) { writeOld := mtvecReg }
|
||||
is(Privileged.CSR_MCOUNTEREN) { writeOld := mcounteren }
|
||||
is(Privileged.CSR_MCOUNTINHIBIT) { writeOld := mcountinhibit }
|
||||
is(Privileged.CSR_MSCRATCH) { writeOld := mscratch }
|
||||
is(Privileged.CSR_MEPC) { writeOld := mepcReg }
|
||||
is(Privileged.CSR_MCAUSE) { writeOld := mcause }
|
||||
is(Privileged.CSR_MTVAL) { writeOld := mtval }
|
||||
is(Privileged.CSR_MIP) { writeOld := mip }
|
||||
is(Privileged.CSR_PMPCFG0) { writeOld := pmpcfg0 }
|
||||
is(Privileged.CSR_PMPADDR0) { writeOld := pmpaddr0 }
|
||||
is(Privileged.CSR_TSELECT) { writeOld := 1.U }
|
||||
is(Privileged.CSR_TDATA1) { writeOld := tdata1 }
|
||||
is(Privileged.CSR_TDATA2) { writeOld := tdata2 }
|
||||
is(Privileged.CSR_TCONTROL) { writeOld := tcontrol }
|
||||
is(Privileged.CSR_MNSTATUS) { writeOld := mnstatus }
|
||||
is(Privileged.CSR_SSTATUS) { writeOld := sstatusView }
|
||||
is(Privileged.CSR_SIE) { writeOld := mie & mideleg }
|
||||
is(Privileged.CSR_STVEC) { writeOld := stvec }
|
||||
is(Privileged.CSR_SCOUNTEREN) { writeOld := scounteren }
|
||||
is(Privileged.CSR_SSCRATCH) { writeOld := sscratch }
|
||||
is(Privileged.CSR_SEPC) { writeOld := sepc }
|
||||
is(Privileged.CSR_SCAUSE) { writeOld := scause }
|
||||
is(Privileged.CSR_STVAL) { writeOld := stval }
|
||||
is(Privileged.CSR_SIP) { writeOld := mip & mideleg }
|
||||
is(Privileged.CSR_SATP) { writeOld := satpReg }
|
||||
is(Privileged.CSR_MVENDORID) { writeOld := 0.U }
|
||||
is(Privileged.CSR_MARCHID) { writeOld := 0.U }
|
||||
is(Privileged.CSR_MIMPID) { writeOld := 0.U }
|
||||
is(Privileged.CSR_MHARTID) { writeOld := 0.U }
|
||||
is(Privileged.CSR_MINSTRET) { writeOld := instret }
|
||||
is(Privileged.CSR_CYCLE) { writeOld := cycle }
|
||||
is(Privileged.CSR_TIME) { writeOld := cycle }
|
||||
is(Privileged.CSR_INSTRET) { writeOld := instret }
|
||||
}
|
||||
|
||||
val operand = Mux(io.cmd.cmd(2), io.cmd.zimm, io.cmd.rs1)
|
||||
@@ -97,29 +183,82 @@ class CSRFile(p: CoreParams = CoreParams()) extends Module {
|
||||
3.U -> (writeOld & ~operand)
|
||||
))
|
||||
|
||||
when(io.cmd.valid && io.cmd.cmd =/= 0.U) {
|
||||
when(io.cmd.valid && io.cmd.cmd =/= 0.U && writeAllowed) {
|
||||
switch(io.cmd.addr) {
|
||||
is("h300".U) { mstatus := next }
|
||||
is("h302".U) { medeleg := next }
|
||||
is("h303".U) { mideleg := next }
|
||||
is("h304".U) { mie := next }
|
||||
is("h305".U) { mtvecReg := next }
|
||||
is("h341".U) { mepcReg := next }
|
||||
is("h342".U) { mcause := next }
|
||||
is("h343".U) { mtval := next }
|
||||
is("h344".U) { mip := next }
|
||||
is("h100".U) { sstatus := next }
|
||||
is("h105".U) { stvec := next }
|
||||
is("h140".U) { sscratch := next }
|
||||
is("h141".U) { sepc := next }
|
||||
is("h142".U) { scause := next }
|
||||
is("h143".U) { stval := next }
|
||||
is("h180".U) { satpReg := next }
|
||||
is(Privileged.CSR_MSTATUS) { mstatus := next }
|
||||
is(Privileged.CSR_MEDELEG) { medeleg := next }
|
||||
is(Privileged.CSR_MIDELEG) { mideleg := next }
|
||||
is(Privileged.CSR_MIE) { mie := next }
|
||||
is(Privileged.CSR_MTVEC) { mtvecReg := next }
|
||||
is(Privileged.CSR_MCOUNTEREN) { mcounteren := next }
|
||||
is(Privileged.CSR_MCOUNTINHIBIT) { mcountinhibit := next & 4.U }
|
||||
is(Privileged.CSR_MSCRATCH) { mscratch := next }
|
||||
is(Privileged.CSR_MEPC) { mepcReg := next }
|
||||
is(Privileged.CSR_MCAUSE) { mcause := next }
|
||||
is(Privileged.CSR_MTVAL) { mtval := next }
|
||||
is(Privileged.CSR_MIP) { mip := next }
|
||||
is(Privileged.CSR_PMPCFG0) { pmpcfg0 := next }
|
||||
is(Privileged.CSR_PMPADDR0) { pmpaddr0 := next }
|
||||
is(Privileged.CSR_TDATA1) { tdata1 := next }
|
||||
is(Privileged.CSR_TDATA2) { tdata2 := next }
|
||||
is(Privileged.CSR_TCONTROL) { tcontrol := next }
|
||||
is(Privileged.CSR_MNSTATUS) { mnstatus := next }
|
||||
is(Privileged.CSR_SSTATUS) { mstatus := (mstatus & ~sstatusMask) | (next & sstatusMask) }
|
||||
is(Privileged.CSR_SIE) { mie := (mie & ~mideleg) | (next & mideleg) }
|
||||
is(Privileged.CSR_STVEC) { stvec := next }
|
||||
is(Privileged.CSR_SCOUNTEREN) { scounteren := next }
|
||||
is(Privileged.CSR_SSCRATCH) { sscratch := next }
|
||||
is(Privileged.CSR_SEPC) { sepc := next }
|
||||
is(Privileged.CSR_SCAUSE) { scause := next }
|
||||
is(Privileged.CSR_STVAL) { stval := next }
|
||||
is(Privileged.CSR_SIP) { mip := (mip & ~mideleg) | (next & mideleg) }
|
||||
is(Privileged.CSR_SATP) { satpReg := next }
|
||||
is(Privileged.CSR_MINSTRET) {
|
||||
instret := next
|
||||
suppressInstretIncrement := true.B
|
||||
suppressInstretAfterWrite := true.B
|
||||
}
|
||||
}
|
||||
}
|
||||
when(suppressInstretAfterWrite) {
|
||||
suppressInstretAfterWrite := false.B
|
||||
}
|
||||
|
||||
val trapToS = io.trapTargetPriv === Privileged.PRV_S
|
||||
io.trapVector := Mux(trapToS, stvec, mtvecReg)
|
||||
val bitMie = 1.U(p.xlen.W) << 3
|
||||
val bitMpie = 1.U(p.xlen.W) << 7
|
||||
val mppMask = 3.U(p.xlen.W) << 11
|
||||
val bitSie = 1.U(p.xlen.W) << 1
|
||||
val bitSpie = 1.U(p.xlen.W) << 5
|
||||
val bitSpp = 1.U(p.xlen.W) << 8
|
||||
|
||||
when(io.trap) {
|
||||
when(trapToS) {
|
||||
sepc := io.trapPc
|
||||
scause := io.trapCause
|
||||
stval := io.trapTval
|
||||
val withSpie = Mux((mstatus & bitSie) =/= 0.U, mstatus | bitSpie, mstatus & ~bitSpie)
|
||||
val withSieCleared = withSpie & ~bitSie
|
||||
val withSpp = Mux(io.currentPriv === Privileged.PRV_S, withSieCleared | bitSpp, withSieCleared & ~bitSpp)
|
||||
mstatus := withSpp
|
||||
}.otherwise {
|
||||
mepcReg := io.trapPc
|
||||
mcause := io.trapCause
|
||||
mtval := io.trapTval
|
||||
val withMpie = Mux((mstatus & bitMie) =/= 0.U, mstatus | bitMpie, mstatus & ~bitMpie)
|
||||
val withMieCleared = withMpie & ~bitMie
|
||||
mstatus := (withMieCleared & ~mppMask) | (io.currentPriv.pad(p.xlen) << 11)
|
||||
}
|
||||
}.elsewhen(io.xret) {
|
||||
when(io.xretIsMret) {
|
||||
val withMie = Mux((mstatus & bitMpie) =/= 0.U, mstatus | bitMie, mstatus & ~bitMie)
|
||||
val withMpie = withMie | bitMpie
|
||||
mstatus := withMpie & ~mppMask
|
||||
}.otherwise {
|
||||
val withSie = Mux((mstatus & bitSpie) =/= 0.U, mstatus | bitSie, mstatus & ~bitSie)
|
||||
val withSpie = withSie | bitSpie
|
||||
mstatus := withSpie & ~bitSpp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
63
src/main/scala/csr/CSRPermission.scala
Normal file
63
src/main/scala/csr/CSRPermission.scala
Normal file
@@ -0,0 +1,63 @@
|
||||
import chisel3._
|
||||
|
||||
object CSRPermission {
|
||||
private val machineCsrs = Set(
|
||||
0x300, 0x301, 0x302, 0x303, 0x304, 0x305, 0x306, 0x340, 0x341, 0x342, 0x343, 0x344,
|
||||
0x320, 0x3a0, 0x3b0, 0x744, 0x7a0, 0x7a1, 0x7a2, 0x7a5, 0xb02,
|
||||
0xf11, 0xf12, 0xf13, 0xf14)
|
||||
private val supervisorCsrs = Set(0x100, 0x104, 0x105, 0x106, 0x140, 0x141, 0x142, 0x143, 0x144, 0x180)
|
||||
private val counterCsrs = Set(0xc00, 0xc01, 0xc02)
|
||||
private val readOnlyCsrs = Set(0xf11, 0xf12, 0xf13, 0xf14) ++ counterCsrs
|
||||
|
||||
def implementedLit(addr: BigInt): Boolean =
|
||||
machineCsrs(addr.toInt) || supervisorCsrs(addr.toInt) || counterCsrs(addr.toInt)
|
||||
|
||||
def readAllowedLit(addr: BigInt, priv: BigInt): Boolean =
|
||||
implementedLit(addr) && {
|
||||
if (machineCsrs(addr.toInt)) priv == 3
|
||||
else if (supervisorCsrs(addr.toInt)) priv != 0
|
||||
else true
|
||||
}
|
||||
|
||||
def writeAllowedLit(addr: BigInt, priv: BigInt): Boolean =
|
||||
readAllowedLit(addr, priv) && !readOnlyCsrs(addr.toInt)
|
||||
|
||||
private def isMachine(addr: UInt): Bool =
|
||||
addr === Privileged.CSR_MSTATUS || addr === Privileged.CSR_MISA ||
|
||||
addr === Privileged.CSR_MEDELEG || addr === Privileged.CSR_MIDELEG ||
|
||||
addr === Privileged.CSR_MIE || addr === Privileged.CSR_MTVEC ||
|
||||
addr === Privileged.CSR_MCOUNTEREN || addr === Privileged.CSR_MSCRATCH || addr === Privileged.CSR_MEPC ||
|
||||
addr === Privileged.CSR_MCAUSE || addr === Privileged.CSR_MTVAL ||
|
||||
addr === Privileged.CSR_MIP || addr === Privileged.CSR_PMPCFG0 ||
|
||||
addr === Privileged.CSR_PMPADDR0 || addr === Privileged.CSR_TSELECT ||
|
||||
addr === Privileged.CSR_TDATA1 || addr === Privileged.CSR_TDATA2 ||
|
||||
addr === Privileged.CSR_TCONTROL || addr === Privileged.CSR_MNSTATUS ||
|
||||
addr === Privileged.CSR_MCOUNTINHIBIT || addr === Privileged.CSR_MINSTRET ||
|
||||
addr === Privileged.CSR_MVENDORID || addr === Privileged.CSR_MARCHID ||
|
||||
addr === Privileged.CSR_MIMPID || addr === Privileged.CSR_MHARTID
|
||||
|
||||
private def isSupervisor(addr: UInt): Bool =
|
||||
addr === Privileged.CSR_SSTATUS || addr === Privileged.CSR_SIE ||
|
||||
addr === Privileged.CSR_STVEC || addr === Privileged.CSR_SSCRATCH ||
|
||||
addr === Privileged.CSR_SCOUNTEREN || addr === Privileged.CSR_SEPC || addr === Privileged.CSR_SCAUSE ||
|
||||
addr === Privileged.CSR_STVAL || addr === Privileged.CSR_SIP ||
|
||||
addr === Privileged.CSR_SATP
|
||||
|
||||
private def isCounter(addr: UInt): Bool =
|
||||
addr === Privileged.CSR_CYCLE || addr === Privileged.CSR_TIME ||
|
||||
addr === Privileged.CSR_INSTRET
|
||||
|
||||
private def isReadOnly(addr: UInt): Bool =
|
||||
addr === Privileged.CSR_MVENDORID || addr === Privileged.CSR_MARCHID ||
|
||||
addr === Privileged.CSR_MIMPID || addr === Privileged.CSR_MHARTID ||
|
||||
isCounter(addr)
|
||||
|
||||
def implemented(addr: UInt): Bool = isMachine(addr) || isSupervisor(addr) || isCounter(addr)
|
||||
|
||||
def readAllowed(addr: UInt, priv: UInt): Bool =
|
||||
implemented(addr) && Mux(isMachine(addr), priv === Privileged.PRV_M,
|
||||
Mux(isSupervisor(addr), priv =/= Privileged.PRV_U, true.B))
|
||||
|
||||
def writeAllowed(addr: UInt, priv: UInt): Bool =
|
||||
readAllowed(addr, priv) && !isReadOnly(addr)
|
||||
}
|
||||
@@ -2,20 +2,14 @@ import chisel3._
|
||||
|
||||
class PrivilegeControl(p: CoreParams = CoreParams()) extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val trap = Input(Bool())
|
||||
val mret = Input(Bool())
|
||||
val sret = Input(Bool())
|
||||
val privilege = Output(UInt(2.W))
|
||||
val nextPriv = Input(UInt(2.W))
|
||||
val setPriv = Input(Bool())
|
||||
val priv = Output(UInt(2.W))
|
||||
})
|
||||
|
||||
val mode = RegInit(3.U(2.W))
|
||||
when(io.trap) {
|
||||
mode := 3.U
|
||||
}.elsewhen(io.mret) {
|
||||
mode := 0.U
|
||||
}.elsewhen(io.sret) {
|
||||
mode := 0.U
|
||||
val privReg = RegInit(Privileged.PRV_M)
|
||||
when(io.setPriv) {
|
||||
privReg := io.nextPriv
|
||||
}
|
||||
io.privilege := mode
|
||||
io.priv := privReg
|
||||
}
|
||||
|
||||
|
||||
47
src/main/scala/csr/PrivilegeTransitions.scala
Normal file
47
src/main/scala/csr/PrivilegeTransitions.scala
Normal file
@@ -0,0 +1,47 @@
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
object PrivilegeTransitions {
|
||||
private def delegated(cause: UInt, delegation: UInt): Bool = delegation(cause(5, 0))
|
||||
|
||||
def trapTargetPriv(
|
||||
currentPriv: UInt,
|
||||
cause: UInt,
|
||||
isInterrupt: Bool,
|
||||
medeleg: UInt,
|
||||
mideleg: UInt): UInt = {
|
||||
val delegation = Mux(isInterrupt, mideleg, medeleg)
|
||||
val toSupervisor = currentPriv =/= Privileged.PRV_M && delegated(cause, delegation)
|
||||
Mux(toSupervisor, Privileged.PRV_S, Privileged.PRV_M)
|
||||
}
|
||||
|
||||
def mretNextPriv(mstatus: UInt): UInt = mstatus(12, 11)
|
||||
|
||||
def sretNextPriv(mstatus: UInt): UInt = Mux(mstatus(8), Privileged.PRV_S, Privileged.PRV_U)
|
||||
|
||||
def xretTargetPc(isMret: Bool, mepc: UInt, sepc: UInt): UInt =
|
||||
Mux(isMret, mepc, sepc)
|
||||
|
||||
def xretNextPriv(isMret: Bool, mstatus: UInt): UInt =
|
||||
Mux(isMret, mretNextPriv(mstatus), sretNextPriv(mstatus))
|
||||
|
||||
def trapTargetPrivLit(
|
||||
currentPriv: BigInt,
|
||||
cause: BigInt,
|
||||
isInterrupt: Boolean,
|
||||
medeleg: BigInt,
|
||||
mideleg: BigInt): BigInt = {
|
||||
val delegation = if (isInterrupt) mideleg else medeleg
|
||||
val delegated = ((delegation >> cause.toInt) & 1) == 1
|
||||
if (currentPriv != Privileged.PRV_M.litValue && delegated) Privileged.PRV_S.litValue
|
||||
else Privileged.PRV_M.litValue
|
||||
}
|
||||
|
||||
def mretNextPrivLit(mstatus: BigInt): BigInt = (mstatus >> 11) & 3
|
||||
|
||||
def sretNextPrivLit(mstatus: BigInt): BigInt =
|
||||
if (((mstatus >> 8) & 1) == 1) Privileged.PRV_S.litValue else Privileged.PRV_U.litValue
|
||||
|
||||
def xretTargetPcLit(isMret: Boolean, mepc: BigInt, sepc: BigInt): BigInt =
|
||||
if (isMret) mepc else sepc
|
||||
}
|
||||
@@ -47,6 +47,24 @@ class Decoder(p: CoreParams = CoreParams()) extends Module {
|
||||
))
|
||||
d.memSigned := !funct3(2)
|
||||
d.illegal := false.B
|
||||
val isSystemOpcode = opcode === "b1110011".U
|
||||
val isFenceOpcode = opcode === "b0001111".U
|
||||
val isEcall = io.inst === "h00000073".U
|
||||
val isEbreak = io.inst === "h00100073".U
|
||||
val isMret = io.inst === "h30200073".U
|
||||
val isSret = io.inst === "h10200073".U
|
||||
val isUret = io.inst === "h00200073".U
|
||||
val isWfi = io.inst === "h10500073".U
|
||||
val isSfenceVma = isSystemOpcode && funct3 === 0.U && funct7 === "b0001001".U
|
||||
val isKnownPrivInst = isEcall || isEbreak || isMret || isSret || isSfenceVma || isWfi
|
||||
d.isEcall := isEcall
|
||||
d.isEbreak := isEbreak
|
||||
d.isMret := isMret
|
||||
d.isSret := isSret
|
||||
d.isUret := isUret
|
||||
d.isSfenceVma := isSfenceVma
|
||||
d.isXret := isMret || isSret
|
||||
d.isWfi := isWfi
|
||||
|
||||
switch(opcode) {
|
||||
is("b0110111".U) {
|
||||
@@ -128,11 +146,15 @@ class Decoder(p: CoreParams = CoreParams()) extends Module {
|
||||
is("b0001111".U) {
|
||||
d.opClass := Consts.OP_SYSTEM
|
||||
d.isFenceI := funct3 === "b001".U
|
||||
d.illegal := funct3 =/= 0.U && funct3 =/= "b001".U
|
||||
}
|
||||
is("b1110011".U) {
|
||||
d.isSystem := true.B
|
||||
d.writesRd := rd =/= 0.U && funct3 =/= 0.U
|
||||
d.opClass := Consts.OP_SYSTEM
|
||||
when(funct3 === 0.U) {
|
||||
d.illegal := !(isKnownPrivInst && !isUret)
|
||||
}
|
||||
}
|
||||
is("b0101111".U) {
|
||||
d.isLoad := true.B
|
||||
@@ -151,5 +173,9 @@ class Decoder(p: CoreParams = CoreParams()) extends Module {
|
||||
d.illegal := true.B
|
||||
}
|
||||
|
||||
when(isSystemOpcode && isUret) {
|
||||
d.illegal := true.B
|
||||
}
|
||||
|
||||
io.out := d
|
||||
}
|
||||
|
||||
@@ -14,6 +14,9 @@ class IDStage(p: CoreParams = CoreParams()) extends Module {
|
||||
decoders(i).io.inst := io.in.inst(i)
|
||||
io.out(i) := decoders(i).io.out
|
||||
io.out(i).valid := io.inValid && io.in.laneValid(i)
|
||||
io.out(i).fetchException := io.in.exception
|
||||
io.out(i).fetchExceptionCause := io.in.exceptionCause
|
||||
io.out(i).fetchExceptionTval := io.in.exceptionTval
|
||||
io.outValid(i) := io.inValid && io.in.laneValid(i)
|
||||
}
|
||||
}
|
||||
|
||||
35
src/main/scala/execute/ExceptionSource.scala
Normal file
35
src/main/scala/execute/ExceptionSource.scala
Normal file
@@ -0,0 +1,35 @@
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
object ExceptionSource {
|
||||
private val priorityTable = Map(
|
||||
12 -> 0,
|
||||
1 -> 1,
|
||||
2 -> 2,
|
||||
0 -> 3,
|
||||
3 -> 4,
|
||||
8 -> 5,
|
||||
9 -> 5,
|
||||
11 -> 5,
|
||||
13 -> 6,
|
||||
5 -> 7,
|
||||
4 -> 8,
|
||||
15 -> 9,
|
||||
7 -> 10,
|
||||
6 -> 11
|
||||
)
|
||||
|
||||
def priorityOf(cause: UInt): Int =
|
||||
priorityTable.getOrElse(cause.litValue.toInt, 100)
|
||||
|
||||
def ecallCause(priv: UInt): UInt = MuxLookup(priv, Privileged.CAUSE_ECALL_FROM_M)(Seq(
|
||||
Privileged.PRV_U -> Privileged.CAUSE_ECALL_FROM_U,
|
||||
Privileged.PRV_S -> Privileged.CAUSE_ECALL_FROM_S,
|
||||
Privileged.PRV_M -> Privileged.CAUSE_ECALL_FROM_M
|
||||
))
|
||||
|
||||
def ecallCauseLit(priv: BigInt): BigInt =
|
||||
if (priv == BigInt(0)) Privileged.CAUSE_ECALL_FROM_U.litValue
|
||||
else if (priv == BigInt(1)) Privileged.CAUSE_ECALL_FROM_S.litValue
|
||||
else Privileged.CAUSE_ECALL_FROM_M.litValue
|
||||
}
|
||||
@@ -6,35 +6,78 @@ class Frontend(p: CoreParams = CoreParams()) extends Module {
|
||||
val redirectValid = Input(Bool())
|
||||
val redirectPc = Input(UInt(p.xlen.W))
|
||||
val invalidateICache = Input(Bool())
|
||||
val sfenceVma = Input(Bool())
|
||||
val satp = Input(UInt(p.xlen.W))
|
||||
val currentPriv = Input(UInt(2.W))
|
||||
val imemReqValid = Output(Bool())
|
||||
val imemReqAddr = Output(UInt(p.xlen.W))
|
||||
val imemRespValid = Input(Bool())
|
||||
val imemRespBits = Input(Vec(p.fetchWidth, UInt(32.W)))
|
||||
val ptwMemReqValid = Output(Bool())
|
||||
val ptwMemReqAddr = Output(UInt(p.xlen.W))
|
||||
val ptwMemRespValid = Input(Bool())
|
||||
val ptwMemRespData = Input(UInt(p.xlen.W))
|
||||
val outReady = Input(Bool())
|
||||
val outValid = Output(Bool())
|
||||
val out = Output(new FetchPacket(p))
|
||||
val instMisaligned = Output(Bool())
|
||||
val instPageFault = Output(Bool())
|
||||
val faultPc = Output(UInt(p.xlen.W))
|
||||
val branchUpdate = Input(new BranchUpdate(p))
|
||||
})
|
||||
|
||||
val pc = RegInit(Consts.ResetVector)
|
||||
val predictor = Module(new BranchPredictor(p))
|
||||
val itlb = Module(new ITLB(p))
|
||||
val immu = Module(new MMU(p))
|
||||
val icache = Module(new ICache(p))
|
||||
val faultPending = RegInit(false.B)
|
||||
val faultPc = Reg(UInt(p.xlen.W))
|
||||
val faultCause = Reg(UInt(p.xlen.W))
|
||||
|
||||
predictor.io.pc := pc
|
||||
predictor.io.update := io.branchUpdate
|
||||
itlb.io.req.valid := true.B
|
||||
|
||||
val fetchTranslate = io.satp(63, 60) =/= 0.U && io.currentPriv =/= Privileged.PRV_M
|
||||
dontTouch(fetchTranslate)
|
||||
val itlbReqValid = fetchTranslate && !faultPending
|
||||
itlb.io.req.valid := itlbReqValid
|
||||
itlb.io.req.vaddr := pc
|
||||
itlb.io.req.isStore := false.B
|
||||
itlb.io.req.isFetch := true.B
|
||||
itlb.io.refill.valid := false.B
|
||||
itlb.io.refill.vpn := 0.U
|
||||
itlb.io.refill.ppn := 0.U
|
||||
itlb.io.refill.level := 0.U
|
||||
itlb.io.refill.flags := 0.U
|
||||
itlb.io.req.priv := io.currentPriv
|
||||
itlb.io.req.sum := false.B
|
||||
itlb.io.req.mxr := false.B
|
||||
itlb.io.flush := io.redirectValid || io.invalidateICache || io.sfenceVma
|
||||
|
||||
icache.io.reqValid := true.B
|
||||
icache.io.reqAddr := Mux(itlb.io.resp.hit, itlb.io.resp.paddr, pc)
|
||||
val itlbMiss = fetchTranslate && itlb.io.resp.miss
|
||||
dontTouch(itlbMiss)
|
||||
immu.io.satp := io.satp
|
||||
immu.io.req.valid := itlbMiss
|
||||
immu.io.req.vaddr := pc
|
||||
immu.io.req.isStore := false.B
|
||||
immu.io.req.isFetch := true.B
|
||||
immu.io.req.priv := io.currentPriv
|
||||
immu.io.req.sum := false.B
|
||||
immu.io.req.mxr := false.B
|
||||
immu.io.ptwMemResp.valid := io.ptwMemRespValid
|
||||
immu.io.ptwMemResp.data := io.ptwMemRespData
|
||||
itlb.io.refill := immu.io.refill
|
||||
|
||||
io.ptwMemReqValid := immu.io.ptwMemReq.valid
|
||||
io.ptwMemReqAddr := immu.io.ptwMemReq.addr
|
||||
|
||||
val instMisaligned = pc(1, 0) =/= 0.U
|
||||
val instPageFault = fetchTranslate && (itlb.io.resp.pageFault || immu.io.resp.pageFault)
|
||||
val fetchFault = instMisaligned || instPageFault
|
||||
val translationFault = instPageFault
|
||||
val translationReady = !fetchTranslate || itlb.io.resp.hit || translationFault
|
||||
dontTouch(translationReady)
|
||||
val translatedFetchAddr = Mux(fetchTranslate, itlb.io.resp.paddr, pc)
|
||||
dontTouch(translatedFetchAddr)
|
||||
|
||||
icache.io.reqValid := !fetchFault && !faultPending && translationReady
|
||||
icache.io.reqAddr := translatedFetchAddr
|
||||
icache.io.reqPc := pc
|
||||
icache.io.flush := io.redirectValid
|
||||
icache.io.invalidate := io.invalidateICache
|
||||
@@ -44,15 +87,33 @@ class Frontend(p: CoreParams = CoreParams()) extends Module {
|
||||
|
||||
io.imemReqValid := icache.io.memReqValid
|
||||
io.imemReqAddr := icache.io.memReqAddr
|
||||
io.outValid := icache.io.respValid
|
||||
io.out := icache.io.resp
|
||||
val faultPacket = WireDefault(0.U.asTypeOf(new FetchPacket(p)))
|
||||
faultPacket.pc := faultPc
|
||||
faultPacket.laneValid(0) := true.B
|
||||
faultPacket.exception := true.B
|
||||
faultPacket.exceptionCause := faultCause
|
||||
faultPacket.exceptionTval := faultPc
|
||||
|
||||
io.outValid := faultPending || icache.io.respValid
|
||||
io.out := Mux(faultPending, faultPacket, icache.io.resp)
|
||||
io.out.predictedTaken := predictor.io.taken
|
||||
io.out.predictedTarget := predictor.io.target
|
||||
io.instMisaligned := instMisaligned
|
||||
io.instPageFault := instPageFault
|
||||
io.faultPc := pc
|
||||
|
||||
val sequentialNextPc = icache.io.resp.pc + (PopCount(icache.io.resp.laneValid) << 2)
|
||||
|
||||
when(io.redirectValid) {
|
||||
faultPending := false.B
|
||||
pc := io.redirectPc
|
||||
}.elsewhen(fetchFault && !faultPending) {
|
||||
faultPending := true.B
|
||||
faultPc := pc
|
||||
faultCause := Mux(instMisaligned, Privileged.CAUSE_INSTR_ADDR_MISALIGNED, Privileged.CAUSE_INSTR_PAGE_FAULT)
|
||||
}.elsewhen(faultPending && io.outReady) {
|
||||
faultPending := false.B
|
||||
pc := pc + 4.U
|
||||
}.elsewhen(icache.io.respValid && io.outReady) {
|
||||
pc := Mux(predictor.io.taken, predictor.io.target, sequentialNextPc)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ class ITLB(p: CoreParams = CoreParams()) extends Module {
|
||||
val req = Input(new TlbReq(p))
|
||||
val resp = Output(new TlbResp(p))
|
||||
val refill = Input(new TlbRefill(p))
|
||||
val flush = Input(Bool())
|
||||
val missVpn = Output(UInt(vpnBits.W))
|
||||
})
|
||||
|
||||
@@ -22,20 +23,34 @@ class ITLB(p: CoreParams = CoreParams()) extends Module {
|
||||
|
||||
val reqVpn = io.req.vaddr(38, 12)
|
||||
val pageOff = io.req.vaddr(11, 0)
|
||||
val hitVec = VecInit((0 until p.itlbEntries).map(i => valid(i) && vpn(i) === reqVpn))
|
||||
val hitVec = VecInit((0 until p.itlbEntries).map { i =>
|
||||
val samePage = Mux(level(i) === 2.U, vpn(i)(26, 18) === reqVpn(26, 18),
|
||||
Mux(level(i) === 1.U, vpn(i)(26, 9) === reqVpn(26, 9), vpn(i) === reqVpn))
|
||||
valid(i) && samePage
|
||||
})
|
||||
val hit = io.req.valid && hitVec.asUInt.orR
|
||||
val hitIdx = OHToUInt(hitVec)
|
||||
val hitLevel = level(hitIdx)
|
||||
val paddrPpn0 = Mux(hitLevel === 0.U, ppn(hitIdx)(8, 0), reqVpn(8, 0))
|
||||
val paddrPpn1 = Mux(hitLevel <= 1.U, ppn(hitIdx)(17, 9), reqVpn(17, 9))
|
||||
val paddrPpn2 = ppn(hitIdx)(43, 18)
|
||||
val x = flags(hitIdx)(3)
|
||||
val pageFault = hit && !x
|
||||
val u = flags(hitIdx)(4)
|
||||
val a = flags(hitIdx)(6)
|
||||
val sModeToUserFault = io.req.priv === Privileged.PRV_S && u
|
||||
val uModeToSupervisorFault = io.req.priv === Privileged.PRV_U && !u
|
||||
val pageFault = hit && (sModeToUserFault || uModeToSupervisorFault || !x || !a)
|
||||
|
||||
io.resp.hit := hit && !pageFault
|
||||
io.resp.miss := io.req.valid && !hit
|
||||
io.resp.paddr := Cat(ppn(hitIdx), pageOff)
|
||||
io.resp.paddr := Cat(paddrPpn2, paddrPpn1, paddrPpn0, pageOff)
|
||||
io.resp.pageFault := pageFault
|
||||
io.resp.accessFault := false.B
|
||||
io.missVpn := reqVpn
|
||||
|
||||
when(io.refill.valid) {
|
||||
when(io.flush) {
|
||||
valid := VecInit(Seq.fill(p.itlbEntries)(false.B))
|
||||
}.elsewhen(io.refill.valid) {
|
||||
valid(repl) := true.B
|
||||
vpn(repl) := io.refill.vpn
|
||||
ppn(repl) := io.refill.ppn
|
||||
|
||||
34
src/main/scala/interrupt/Clint.scala
Normal file
34
src/main/scala/interrupt/Clint.scala
Normal file
@@ -0,0 +1,34 @@
|
||||
import chisel3._
|
||||
|
||||
class Clint(p: CoreParams = CoreParams()) extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val addr = Input(UInt(p.xlen.W))
|
||||
val wen = Input(Bool())
|
||||
val wdata = Input(UInt(p.xlen.W))
|
||||
val ren = Input(Bool())
|
||||
val rdata = Output(UInt(p.xlen.W))
|
||||
val mipMSIP = Output(Bool())
|
||||
val mipMTIP = Output(Bool())
|
||||
})
|
||||
|
||||
val msip = RegInit(false.B)
|
||||
val mtime = RegInit(0.U(p.xlen.W))
|
||||
val mtimecmp = RegInit(~0.U(p.xlen.W))
|
||||
mtime := mtime + 1.U
|
||||
|
||||
when(io.wen) {
|
||||
when(io.addr === "h0".U) {
|
||||
msip := io.wdata(0)
|
||||
}.elsewhen(io.addr === "h4000".U) {
|
||||
mtimecmp := io.wdata
|
||||
}.elsewhen(io.addr === "hbff8".U) {
|
||||
mtime := io.wdata
|
||||
}
|
||||
}
|
||||
|
||||
io.rdata := Mux(io.addr === "h0".U, msip,
|
||||
Mux(io.addr === "h4000".U, mtimecmp,
|
||||
Mux(io.addr === "hbff8".U, mtime, 0.U)))
|
||||
io.mipMSIP := msip
|
||||
io.mipMTIP := mtime >= mtimecmp
|
||||
}
|
||||
45
src/main/scala/interrupt/InterruptController.scala
Normal file
45
src/main/scala/interrupt/InterruptController.scala
Normal file
@@ -0,0 +1,45 @@
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
class InterruptController(p: CoreParams = CoreParams()) extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val currentPriv = Input(UInt(2.W))
|
||||
val mstatus = Input(UInt(p.xlen.W))
|
||||
val mie = Input(UInt(p.xlen.W))
|
||||
val mip = Input(UInt(p.xlen.W))
|
||||
val mideleg = Input(UInt(p.xlen.W))
|
||||
val interruptValid = Output(Bool())
|
||||
val interruptCause = Output(UInt(p.xlen.W))
|
||||
val targetPriv = Output(UInt(2.W))
|
||||
})
|
||||
|
||||
val pendingEnabled = io.mie & io.mip
|
||||
val mei = pendingEnabled(11)
|
||||
val mti = pendingEnabled(7)
|
||||
val msi = pendingEnabled(3)
|
||||
val sei = pendingEnabled(9) && io.mideleg(9)
|
||||
val sti = pendingEnabled(5) && io.mideleg(5)
|
||||
val ssi = pendingEnabled(1) && io.mideleg(1)
|
||||
val machineCause = Mux(mei, Privileged.CAUSE_MACHINE_EXTERNAL_INTERRUPT,
|
||||
Mux(mti, Privileged.CAUSE_MACHINE_TIMER_INTERRUPT, Privileged.CAUSE_MACHINE_SOFTWARE_INTERRUPT))
|
||||
val supervisorCause = Mux(sei, Privileged.CAUSE_SUPERVISOR_EXTERNAL_INTERRUPT,
|
||||
Mux(sti, Privileged.CAUSE_SUPERVISOR_TIMER_INTERRUPT, Privileged.CAUSE_SUPERVISOR_SOFTWARE_INTERRUPT))
|
||||
|
||||
val machinePending = mei || mti || msi
|
||||
val supervisorPending = sei || sti || ssi
|
||||
val takeSupervisor = io.currentPriv =/= Privileged.PRV_M && supervisorPending
|
||||
io.interruptValid := machinePending || takeSupervisor
|
||||
io.interruptCause := Mux(takeSupervisor, supervisorCause, machineCause)
|
||||
io.targetPriv := Mux(takeSupervisor, Privileged.PRV_S, Privileged.PRV_M)
|
||||
}
|
||||
|
||||
object InterruptController {
|
||||
def highestMachineCauseLit(msip: Boolean, mtip: Boolean, meip: Boolean): BigInt =
|
||||
if (meip) Privileged.CAUSE_MACHINE_EXTERNAL_INTERRUPT.litValue
|
||||
else if (mtip) Privileged.CAUSE_MACHINE_TIMER_INTERRUPT.litValue
|
||||
else if (msip) Privileged.CAUSE_MACHINE_SOFTWARE_INTERRUPT.litValue
|
||||
else BigInt(0)
|
||||
|
||||
def delegatesToSupervisorLit(cause: BigInt, mideleg: BigInt): Boolean =
|
||||
((mideleg >> cause.toInt) & 1) == 1
|
||||
}
|
||||
11
src/main/scala/interrupt/Plic.scala
Normal file
11
src/main/scala/interrupt/Plic.scala
Normal file
@@ -0,0 +1,11 @@
|
||||
import chisel3._
|
||||
|
||||
class Plic(p: CoreParams = CoreParams()) extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val externalPending = Input(Bool())
|
||||
val enable = Input(Bool())
|
||||
val mipMEIP = Output(Bool())
|
||||
})
|
||||
|
||||
io.mipMEIP := io.externalPending && io.enable
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
class IssueQueue(p: CoreParams = CoreParams()) extends Module {
|
||||
val io = IO(new Bundle {
|
||||
@@ -9,6 +10,8 @@ class IssueQueue(p: CoreParams = CoreParams()) extends Module {
|
||||
val issueValid = Output(Vec(p.issueWidth, Bool()))
|
||||
val issue = Output(Vec(p.issueWidth, new RenamePacket(p)))
|
||||
val issueReady = Input(Vec(p.issueWidth, Bool()))
|
||||
val robHeadValid = Input(Bool())
|
||||
val robHeadIdx = Input(UInt(log2Ceil(p.robEntries).W))
|
||||
val flush = Input(Bool())
|
||||
})
|
||||
|
||||
@@ -17,6 +20,8 @@ class IssueQueue(p: CoreParams = CoreParams()) extends Module {
|
||||
intRs.io.enq := io.enq
|
||||
intRs.io.wakeup := io.wakeup
|
||||
intRs.io.issueReady := io.issueReady
|
||||
intRs.io.robHeadValid := io.robHeadValid
|
||||
intRs.io.robHeadIdx := io.robHeadIdx
|
||||
intRs.io.flush := io.flush
|
||||
|
||||
io.enqReady := intRs.io.enqReady
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
class IssueStage(p: CoreParams = CoreParams()) extends Module {
|
||||
val io = IO(new Bundle {
|
||||
@@ -9,6 +10,8 @@ class IssueStage(p: CoreParams = CoreParams()) extends Module {
|
||||
val outValid = Output(Vec(p.issueWidth, Bool()))
|
||||
val out = Output(Vec(p.issueWidth, new RenamePacket(p)))
|
||||
val outReady = Input(Vec(p.issueWidth, Bool()))
|
||||
val robHeadValid = Input(Bool())
|
||||
val robHeadIdx = Input(UInt(log2Ceil(p.robEntries).W))
|
||||
val flush = Input(Bool())
|
||||
})
|
||||
|
||||
@@ -17,6 +20,8 @@ class IssueStage(p: CoreParams = CoreParams()) extends Module {
|
||||
queue.io.enq := io.in
|
||||
queue.io.wakeup := io.wakeup
|
||||
queue.io.issueReady := io.outReady
|
||||
queue.io.robHeadValid := io.robHeadValid
|
||||
queue.io.robHeadIdx := io.robHeadIdx
|
||||
queue.io.flush := io.flush
|
||||
|
||||
io.inReady := queue.io.enqReady
|
||||
|
||||
@@ -10,6 +10,8 @@ class ReservationStation(p: CoreParams = CoreParams(), entries: Int = 16) extend
|
||||
val issueValid = Output(Vec(p.issueWidth, Bool()))
|
||||
val issue = Output(Vec(p.issueWidth, new RenamePacket(p)))
|
||||
val issueReady = Input(Vec(p.issueWidth, Bool()))
|
||||
val robHeadValid = Input(Bool())
|
||||
val robHeadIdx = Input(UInt(log2Ceil(p.robEntries).W))
|
||||
val flush = Input(Bool())
|
||||
})
|
||||
|
||||
@@ -37,7 +39,10 @@ class ReservationStation(p: CoreParams = CoreParams(), entries: Int = 16) extend
|
||||
valid(j) && slots(j).decoded.isStore && isOlder(slots(j).robIdx, slots(i).robIdx)
|
||||
)).asUInt.orR
|
||||
val waitsForOlderStore = (slots(i).decoded.isLoad || slots(i).decoded.isAmo) && olderStorePending
|
||||
readyVec(i) := valid(i) && src1ReadyNow && src2ReadyNow && !waitsForOlderStore
|
||||
val serializing = slots(i).decoded.isSystem || slots(i).decoded.isFenceI ||
|
||||
slots(i).decoded.isSfenceVma || slots(i).decoded.isWfi
|
||||
val serializingAtHead = !serializing || (io.robHeadValid && slots(i).robIdx === io.robHeadIdx)
|
||||
readyVec(i) := valid(i) && src1ReadyNow && src2ReadyNow && !waitsForOlderStore && serializingAtHead
|
||||
}
|
||||
|
||||
val issue0OH = PriorityEncoderOH(readyVec.asUInt)
|
||||
|
||||
@@ -87,7 +87,7 @@ class DCache(p: CoreParams = CoreParams()) extends Module {
|
||||
val data = SyncReadMem(sets, Vec(p.dCacheWays, Vec(lineWords, UInt(p.xlen.W))))
|
||||
val repl = RegInit(VecInit(Seq.fill(sets)(0.U(log2Ceil(p.dCacheWays).W))))
|
||||
|
||||
val sIdle :: sLookup :: sMiss :: sAmoRead :: sAmoWrite :: sMisalignReadLo :: sMisalignReadHi :: sMisalignResp :: Nil = Enum(8)
|
||||
val sIdle :: sLookup :: sMiss :: sAmoRead :: sAmoWrite :: Nil = Enum(5)
|
||||
val state = RegInit(sIdle)
|
||||
val reqReg = Reg(new MemRequest(p))
|
||||
val reqSet = Reg(UInt(setBits.W))
|
||||
@@ -101,12 +101,13 @@ class DCache(p: CoreParams = CoreParams()) extends Module {
|
||||
val scStore = RegInit(false.B)
|
||||
val reservationValid = RegInit(false.B)
|
||||
val reservationAddr = Reg(UInt(p.xlen.W))
|
||||
val misalignLo = Reg(UInt(p.xlen.W))
|
||||
val misalignHi = Reg(UInt(p.xlen.W))
|
||||
|
||||
def reservationGranule(addr: UInt): UInt = addr(p.xlen - 1, 2)
|
||||
|
||||
val set = setIndex(io.req.addr)
|
||||
val reqBytes = accessBytes(io.req.size)
|
||||
val reqMisaligned = (io.req.addr(2, 0) & (reqBytes - 1.U)) =/= 0.U
|
||||
assert(!(io.reqValid && reqMisaligned), "DCache received misaligned request; LSU must trap before DCache")
|
||||
val storeEndSet = setIndex(io.req.addr + accessBytes(io.req.size) - 1.U)
|
||||
val word = wordIndex(io.req.addr)
|
||||
val readFire = state === sIdle && io.reqValid && !io.req.isStore && !io.req.isAmo
|
||||
@@ -130,24 +131,6 @@ class DCache(p: CoreParams = CoreParams()) extends Module {
|
||||
memReq.amoOp := reqReg.amoOp
|
||||
memReq.size := 3.U
|
||||
|
||||
val misalignLoReq = WireDefault(0.U.asTypeOf(new MemRequest(p)))
|
||||
misalignLoReq.addr := alignedWordAddr(reqReg.addr)
|
||||
misalignLoReq.data := 0.U
|
||||
misalignLoReq.isStore := false.B
|
||||
misalignLoReq.isSigned := reqReg.isSigned
|
||||
misalignLoReq.isAmo := false.B
|
||||
misalignLoReq.amoOp := reqReg.amoOp
|
||||
misalignLoReq.size := 3.U
|
||||
|
||||
val misalignHiReq = WireDefault(0.U.asTypeOf(new MemRequest(p)))
|
||||
misalignHiReq.addr := alignedWordAddr(reqReg.addr) + 8.U
|
||||
misalignHiReq.data := 0.U
|
||||
misalignHiReq.isStore := false.B
|
||||
misalignHiReq.isSigned := reqReg.isSigned
|
||||
misalignHiReq.isAmo := false.B
|
||||
misalignHiReq.amoOp := reqReg.amoOp
|
||||
misalignHiReq.size := 3.U
|
||||
|
||||
val amoReadReq = WireDefault(0.U.asTypeOf(new MemRequest(p)))
|
||||
amoReadReq.addr := lineAddr(reqReg.addr) + (reqWord << byteBits)
|
||||
amoReadReq.data := 0.U
|
||||
@@ -167,21 +150,16 @@ class DCache(p: CoreParams = CoreParams()) extends Module {
|
||||
amoWriteReq.size := reqReg.size
|
||||
|
||||
io.reqReady := state === sIdle
|
||||
io.memReqValid := state === sMiss || storeBypass || state === sMisalignReadLo ||
|
||||
state === sMisalignReadHi || state === sAmoRead ||
|
||||
io.memReqValid := state === sMiss || storeBypass || state === sAmoRead ||
|
||||
state === sAmoWrite && scStore
|
||||
io.memReq := Mux(storeBypass, io.req,
|
||||
Mux(state === sMisalignReadLo, misalignLoReq,
|
||||
Mux(state === sMisalignReadHi, misalignHiReq,
|
||||
Mux(state === sAmoRead, amoReadReq,
|
||||
Mux(state === sAmoWrite, amoWriteReq, memReq)))))
|
||||
Mux(state === sAmoWrite, amoWriteReq, memReq)))
|
||||
io.respValid := state === sLookup && hit && !reqReg.isStore ||
|
||||
state === sMiss && io.memRespValid && !reqReg.isStore ||
|
||||
state === sAmoWrite || state === sMisalignResp
|
||||
val misalignMerged = (Cat(misalignHi, misalignLo) >> (reqReg.addr(byteBits - 1, 0) << 3))(p.xlen - 1, 0)
|
||||
state === sAmoWrite
|
||||
io.respData := Mux(state === sAmoWrite, amoOldData,
|
||||
Mux(state === sMisalignResp, loadSelect(misalignMerged, 0.U, reqReg.size, reqReg.isSigned),
|
||||
Mux(state === sMiss, loadSelect(io.memRespData, reqReg.addr, reqReg.size, reqReg.isSigned), hitResp)))
|
||||
Mux(state === sMiss, loadSelect(io.memRespData, reqReg.addr, reqReg.size, reqReg.isSigned), hitResp))
|
||||
io.miss := state === sLookup && !hit || state === sMiss
|
||||
|
||||
when(storeBypass) {
|
||||
@@ -211,11 +189,6 @@ class DCache(p: CoreParams = CoreParams()) extends Module {
|
||||
reqSet := set
|
||||
reqWord := word
|
||||
state := sAmoRead
|
||||
}.elsewhen(io.reqValid && !io.req.isStore && crossesWord(io.req.addr, io.req.size)) {
|
||||
reqReg := io.req
|
||||
reqSet := set
|
||||
reqWord := word
|
||||
state := sMisalignReadLo
|
||||
}.elsewhen(io.reqValid && !io.req.isStore) {
|
||||
reqReg := io.req
|
||||
reqSet := set
|
||||
@@ -272,17 +245,5 @@ class DCache(p: CoreParams = CoreParams()) extends Module {
|
||||
}.elsewhen(state === sAmoWrite) {
|
||||
scStore := false.B
|
||||
state := sIdle
|
||||
}.elsewhen(state === sMisalignReadLo) {
|
||||
when(io.memRespValid) {
|
||||
misalignLo := io.memRespData
|
||||
state := sMisalignReadHi
|
||||
}
|
||||
}.elsewhen(state === sMisalignReadHi) {
|
||||
when(io.memRespValid) {
|
||||
misalignHi := io.memRespData
|
||||
state := sMisalignResp
|
||||
}
|
||||
}.elsewhen(state === sMisalignResp) {
|
||||
state := sIdle
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ class DTLB(p: CoreParams = CoreParams()) extends Module {
|
||||
val req = Input(new TlbReq(p))
|
||||
val resp = Output(new TlbResp(p))
|
||||
val refill = Input(new TlbRefill(p))
|
||||
val flush = Input(Bool())
|
||||
val missVpn = Output(UInt(vpnBits.W))
|
||||
})
|
||||
|
||||
@@ -22,21 +23,39 @@ class DTLB(p: CoreParams = CoreParams()) extends Module {
|
||||
|
||||
val reqVpn = io.req.vaddr(38, 12)
|
||||
val pageOff = io.req.vaddr(11, 0)
|
||||
val hitVec = VecInit((0 until p.dtlbEntries).map(i => valid(i) && vpn(i) === reqVpn))
|
||||
val hitVec = VecInit((0 until p.dtlbEntries).map { i =>
|
||||
val samePage = Mux(level(i) === 2.U, vpn(i)(26, 18) === reqVpn(26, 18),
|
||||
Mux(level(i) === 1.U, vpn(i)(26, 9) === reqVpn(26, 9), vpn(i) === reqVpn))
|
||||
valid(i) && samePage
|
||||
})
|
||||
val hit = io.req.valid && hitVec.asUInt.orR
|
||||
val hitIdx = OHToUInt(hitVec)
|
||||
val hitLevel = level(hitIdx)
|
||||
val paddrPpn0 = Mux(hitLevel === 0.U, ppn(hitIdx)(8, 0), reqVpn(8, 0))
|
||||
val paddrPpn1 = Mux(hitLevel <= 1.U, ppn(hitIdx)(17, 9), reqVpn(17, 9))
|
||||
val paddrPpn2 = ppn(hitIdx)(43, 18)
|
||||
val r = flags(hitIdx)(1)
|
||||
val w = flags(hitIdx)(2)
|
||||
val pageFault = hit && Mux(io.req.isStore, !w, !r)
|
||||
val x = flags(hitIdx)(3)
|
||||
val u = flags(hitIdx)(4)
|
||||
val a = flags(hitIdx)(6)
|
||||
val d = flags(hitIdx)(7)
|
||||
val sModeToUserFault = io.req.priv === Privileged.PRV_S && u && !io.req.sum
|
||||
val uModeToSupervisorFault = io.req.priv === Privileged.PRV_U && !u
|
||||
val readAllowed = r || (io.req.mxr && x)
|
||||
val accessAllowed = Mux(io.req.isStore, w && d, readAllowed)
|
||||
val pageFault = hit && (sModeToUserFault || uModeToSupervisorFault || !accessAllowed || !a)
|
||||
|
||||
io.resp.hit := hit && !pageFault
|
||||
io.resp.miss := io.req.valid && !hit
|
||||
io.resp.paddr := Cat(ppn(hitIdx), pageOff)
|
||||
io.resp.paddr := Cat(paddrPpn2, paddrPpn1, paddrPpn0, pageOff)
|
||||
io.resp.pageFault := pageFault
|
||||
io.resp.accessFault := false.B
|
||||
io.missVpn := reqVpn
|
||||
|
||||
when(io.refill.valid) {
|
||||
when(io.flush) {
|
||||
valid := VecInit(Seq.fill(p.dtlbEntries)(false.B))
|
||||
}.elsewhen(io.refill.valid) {
|
||||
valid(repl) := true.B
|
||||
vpn(repl) := io.refill.vpn
|
||||
ppn(repl) := io.refill.ppn
|
||||
|
||||
@@ -5,6 +5,10 @@ class LSU(p: CoreParams = CoreParams()) extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val reqValid = Input(Bool())
|
||||
val req = Input(new MemRequest(p))
|
||||
val checkOnly = Input(Bool())
|
||||
val sfenceVma = Input(Bool())
|
||||
val currentPriv = Input(UInt(2.W))
|
||||
val mstatus = Input(UInt(p.xlen.W))
|
||||
val reqReady = Output(Bool())
|
||||
val satp = Input(UInt(p.xlen.W))
|
||||
val dmemReqValid = Output(Bool())
|
||||
@@ -14,44 +18,114 @@ class LSU(p: CoreParams = CoreParams()) extends Module {
|
||||
val respValid = Output(Bool())
|
||||
val respData = Output(UInt(p.xlen.W))
|
||||
val pageFault = Output(Bool())
|
||||
val accessFault = Output(Bool())
|
||||
val misaligned = Output(Bool())
|
||||
val faultCause = Output(UInt(p.xlen.W))
|
||||
val faultAddr = Output(UInt(p.xlen.W))
|
||||
})
|
||||
|
||||
val dtlb = Module(new DTLB(p))
|
||||
val mmu = Module(new MMU(p))
|
||||
val dcache = Module(new DCache(p))
|
||||
val bare = io.satp(63, 60) === 0.U
|
||||
val mprv = io.mstatus(Privileged.MSTATUS_MPRV_BIT)
|
||||
val mpp = io.mstatus(Privileged.MSTATUS_MPP_HI, Privileged.MSTATUS_MPP_LO)
|
||||
val effectivePriv = Mux(io.currentPriv === Privileged.PRV_M && mprv, mpp, io.currentPriv)
|
||||
val pendingValid = RegInit(false.B)
|
||||
val pendingReq = Reg(new MemRequest(p))
|
||||
val pendingCheckOnly = Reg(Bool())
|
||||
val pendingPriv = Reg(UInt(2.W))
|
||||
val pendingMstatus = Reg(UInt(p.xlen.W))
|
||||
val pendingSatp = Reg(UInt(p.xlen.W))
|
||||
|
||||
dtlb.io.req.valid := io.reqValid && !bare
|
||||
dtlb.io.req.vaddr := io.req.addr
|
||||
dtlb.io.req.isStore := io.req.isStore
|
||||
io.reqReady := dcache.io.reqReady && !pendingValid
|
||||
|
||||
val acceptCurrent = io.reqValid && io.reqReady
|
||||
val activeValid = pendingValid || acceptCurrent
|
||||
val activeReq = WireDefault(io.req)
|
||||
val activeCheckOnly = WireDefault(io.checkOnly)
|
||||
val activePriv = WireDefault(effectivePriv)
|
||||
val activeMstatus = WireDefault(io.mstatus)
|
||||
val activeSatp = WireDefault(io.satp)
|
||||
when(pendingValid) {
|
||||
activeReq := pendingReq
|
||||
activeCheckOnly := pendingCheckOnly
|
||||
activePriv := pendingPriv
|
||||
activeMstatus := pendingMstatus
|
||||
activeSatp := pendingSatp
|
||||
}
|
||||
val translate = activeSatp(63, 60) =/= 0.U && activePriv =/= Privileged.PRV_M
|
||||
|
||||
dtlb.io.req.valid := activeValid && translate
|
||||
dtlb.io.req.vaddr := activeReq.addr
|
||||
dtlb.io.req.isStore := activeReq.isStore
|
||||
dtlb.io.req.isFetch := false.B
|
||||
dtlb.io.req.priv := activePriv
|
||||
dtlb.io.req.sum := activeMstatus(Privileged.MSTATUS_SUM_BIT)
|
||||
dtlb.io.req.mxr := activeMstatus(Privileged.MSTATUS_MXR_BIT)
|
||||
dtlb.io.flush := io.sfenceVma
|
||||
|
||||
mmu.io.satp := io.satp
|
||||
mmu.io.req.valid := io.reqValid && !bare && dtlb.io.resp.miss
|
||||
mmu.io.req.vaddr := io.req.addr
|
||||
mmu.io.req.isStore := io.req.isStore
|
||||
mmu.io.satp := activeSatp
|
||||
mmu.io.req.valid := activeValid && translate && dtlb.io.resp.miss
|
||||
mmu.io.req.vaddr := activeReq.addr
|
||||
mmu.io.req.isStore := activeReq.isStore
|
||||
mmu.io.req.isFetch := false.B
|
||||
mmu.io.req.priv := activePriv
|
||||
mmu.io.req.sum := activeMstatus(Privileged.MSTATUS_SUM_BIT)
|
||||
mmu.io.req.mxr := activeMstatus(Privileged.MSTATUS_MXR_BIT)
|
||||
dtlb.io.refill := mmu.io.refill
|
||||
|
||||
val ptwOutstanding = RegInit(false.B)
|
||||
when(mmu.io.ptwMemReq.valid) {
|
||||
ptwOutstanding := true.B
|
||||
}.elsewhen(io.dmemRespValid && ptwOutstanding) {
|
||||
val ptwReqFire = mmu.io.ptwMemReq.valid && !ptwOutstanding
|
||||
val ptwRespFire = io.dmemRespValid && (ptwOutstanding || ptwReqFire)
|
||||
dontTouch(ptwReqFire)
|
||||
when(ptwRespFire) {
|
||||
ptwOutstanding := false.B
|
||||
}.elsewhen(ptwReqFire) {
|
||||
ptwOutstanding := true.B
|
||||
}
|
||||
|
||||
mmu.io.ptwMemResp.valid := io.dmemRespValid && ptwOutstanding
|
||||
mmu.io.ptwMemResp.valid := ptwRespFire
|
||||
mmu.io.ptwMemResp.data := io.dmemRespData
|
||||
|
||||
val translatedAddr = Mux(bare, io.req.addr, dtlb.io.resp.paddr)
|
||||
val translationReady = bare || dtlb.io.resp.hit
|
||||
val translatedAddr = Mux(translate, dtlb.io.resp.paddr, activeReq.addr)
|
||||
val translationReady = !translate || dtlb.io.resp.hit
|
||||
val translationFault = dtlb.io.resp.pageFault || mmu.io.resp.pageFault
|
||||
io.reqReady := dcache.io.reqReady && !ptwOutstanding
|
||||
val accessFault = dtlb.io.resp.accessFault || mmu.io.resp.accessFault
|
||||
val accessBytes = MuxLookup(activeReq.size, 8.U(4.W))(Seq(
|
||||
0.U -> 1.U(4.W),
|
||||
1.U -> 2.U(4.W),
|
||||
2.U -> 4.U(4.W),
|
||||
3.U -> 8.U(4.W)
|
||||
))
|
||||
val misaligned = activeValid && (activeReq.addr(2, 0) & (accessBytes - 1.U)) =/= 0.U
|
||||
val newFault = activeValid && (translationFault || accessFault || misaligned)
|
||||
val computedFaultCause = Mux(misaligned,
|
||||
Mux(activeReq.isStore, Privileged.CAUSE_STORE_ADDR_MISALIGNED, Privileged.CAUSE_LOAD_ADDR_MISALIGNED),
|
||||
Mux(translationFault,
|
||||
Mux(activeReq.isStore, Privileged.CAUSE_STORE_PAGE_FAULT, Privileged.CAUSE_LOAD_PAGE_FAULT),
|
||||
Mux(activeReq.isStore, Privileged.CAUSE_STORE_ACCESS_FAULT, Privileged.CAUSE_LOAD_ACCESS_FAULT)))
|
||||
val checkOnlyDispatch = activeValid && activeCheckOnly && translationReady && !translationFault && !accessFault && !misaligned
|
||||
val dcacheDispatch = activeValid && !activeCheckOnly && translationReady && !translationFault && !accessFault && !misaligned && dcache.io.reqReady
|
||||
val storeComplete = dcacheDispatch && activeReq.isStore || checkOnlyDispatch
|
||||
dontTouch(storeComplete)
|
||||
val latchPending = acceptCurrent && !dcacheDispatch && !newFault
|
||||
val clearPending = pendingValid && (dcacheDispatch || checkOnlyDispatch || newFault)
|
||||
|
||||
dcache.io.reqValid := io.reqValid && translationReady && !translationFault
|
||||
dcache.io.req := io.req
|
||||
when(clearPending) {
|
||||
pendingValid := false.B
|
||||
}.elsewhen(latchPending) {
|
||||
pendingValid := true.B
|
||||
pendingReq := io.req
|
||||
pendingCheckOnly := io.checkOnly
|
||||
pendingPriv := effectivePriv
|
||||
pendingMstatus := io.mstatus
|
||||
pendingSatp := io.satp
|
||||
}
|
||||
|
||||
dcache.io.reqValid := dcacheDispatch
|
||||
dcache.io.req := activeReq
|
||||
dcache.io.req.addr := translatedAddr
|
||||
dcache.io.memRespValid := io.dmemRespValid && !ptwOutstanding
|
||||
dcache.io.memRespValid := io.dmemRespValid && !ptwOutstanding && !ptwReqFire
|
||||
dcache.io.memRespData := io.dmemRespData
|
||||
|
||||
val ptwReqAsMem = WireDefault(0.U.asTypeOf(new MemRequest(p)))
|
||||
@@ -63,9 +137,13 @@ class LSU(p: CoreParams = CoreParams()) extends Module {
|
||||
ptwReqAsMem.amoOp := 0.U
|
||||
ptwReqAsMem.size := 3.U
|
||||
|
||||
io.dmemReqValid := mmu.io.ptwMemReq.valid || dcache.io.memReqValid
|
||||
io.dmemReq := Mux(mmu.io.ptwMemReq.valid, ptwReqAsMem, dcache.io.memReq)
|
||||
io.respValid := dcache.io.respValid || translationFault
|
||||
io.dmemReqValid := ptwReqFire || dcache.io.memReqValid
|
||||
io.dmemReq := Mux(ptwReqFire, ptwReqAsMem, dcache.io.memReq)
|
||||
io.respValid := dcache.io.respValid || newFault || storeComplete
|
||||
io.respData := dcache.io.respData
|
||||
io.pageFault := translationFault
|
||||
io.accessFault := accessFault
|
||||
io.misaligned := misaligned
|
||||
io.faultCause := computedFaultCause
|
||||
io.faultAddr := activeReq.addr
|
||||
}
|
||||
|
||||
@@ -7,6 +7,9 @@ class PageTableWalker(p: CoreParams = CoreParams()) extends Module {
|
||||
val reqVpn = Input(UInt(27.W))
|
||||
val isStore = Input(Bool())
|
||||
val isFetch = Input(Bool())
|
||||
val priv = Input(UInt(2.W))
|
||||
val sum = Input(Bool())
|
||||
val mxr = Input(Bool())
|
||||
val satp = Input(UInt(p.xlen.W))
|
||||
val memReq = Output(new PtwMemReq(p))
|
||||
val memResp = Input(new PtwMemResp(p))
|
||||
@@ -20,6 +23,9 @@ class PageTableWalker(p: CoreParams = CoreParams()) extends Module {
|
||||
val vpnReg = Reg(UInt(27.W))
|
||||
val isStoreReg = Reg(Bool())
|
||||
val isFetchReg = Reg(Bool())
|
||||
val privReg = Reg(UInt(2.W))
|
||||
val sumReg = Reg(Bool())
|
||||
val mxrReg = Reg(Bool())
|
||||
val rootPpn = io.satp(43, 0)
|
||||
val pte = io.memResp.data
|
||||
val pteV = pte(0)
|
||||
@@ -32,17 +38,29 @@ class PageTableWalker(p: CoreParams = CoreParams()) extends Module {
|
||||
val pteD = pte(7)
|
||||
val pteFlags = pte(7, 0)
|
||||
val ptePpn = pte(53, 10)
|
||||
val level = Wire(UInt(2.W))
|
||||
level := Mux(state === sL2, 2.U, Mux(state === sL1, 1.U, 0.U))
|
||||
val pteIsLeaf = pteR || pteX
|
||||
val invalidPte = !pteV || (!pteR && pteW)
|
||||
val permFault = Mux(isFetchReg, !pteX, Mux(isStoreReg, !pteW || !pteD, !pteR)) || !pteA
|
||||
val userPage = pteU
|
||||
val sModeToUserFault = privReg === Privileged.PRV_S && userPage && (isFetchReg || !sumReg)
|
||||
val uModeToSupervisorFault = privReg === Privileged.PRV_U && !userPage
|
||||
val privilegeFault = sModeToUserFault || uModeToSupervisorFault
|
||||
val readAllowed = pteR || (mxrReg && pteX)
|
||||
val accessAllowed = Mux(isFetchReg, pteX, Mux(isStoreReg, pteW && pteD, readAllowed))
|
||||
val accessFault = !accessAllowed || !pteA
|
||||
val superpageMisaligned =
|
||||
(level === 2.U && ptePpn(17, 0) =/= 0.U) ||
|
||||
(level === 1.U && ptePpn(8, 0) =/= 0.U)
|
||||
val permFault = privilegeFault || accessFault || superpageMisaligned
|
||||
val walkFault = RegInit(false.B)
|
||||
val nextPpn = Reg(UInt(44.W))
|
||||
val leafFlagsReg = Reg(UInt(8.W))
|
||||
val leafLevelReg = Reg(UInt(2.W))
|
||||
|
||||
def vpnPart(vpn: UInt, level: Int): UInt =
|
||||
vpn(9 * level + 8, 9 * level)
|
||||
|
||||
val level = Wire(UInt(2.W))
|
||||
level := Mux(state === sL2, 2.U, Mux(state === sL1, 1.U, 0.U))
|
||||
val curPpn = Reg(UInt(44.W))
|
||||
val pteAddr = Cat(curPpn, vpnPart(vpnReg, 0), 0.U(3.W))
|
||||
val pteAddrL1 = Cat(curPpn, vpnPart(vpnReg, 1), 0.U(3.W))
|
||||
@@ -54,8 +72,8 @@ class PageTableWalker(p: CoreParams = CoreParams()) extends Module {
|
||||
io.pageFault := walkFault
|
||||
io.refill.valid := state === sDone && !walkFault
|
||||
io.refill.vpn := vpnReg
|
||||
io.refill.level := level
|
||||
io.refill.flags := pteFlags
|
||||
io.refill.level := leafLevelReg
|
||||
io.refill.flags := leafFlagsReg
|
||||
io.refill.ppn := nextPpn
|
||||
|
||||
when(state === sIdle) {
|
||||
@@ -64,6 +82,9 @@ class PageTableWalker(p: CoreParams = CoreParams()) extends Module {
|
||||
vpnReg := io.reqVpn
|
||||
isStoreReg := io.isStore
|
||||
isFetchReg := io.isFetch
|
||||
privReg := io.priv
|
||||
sumReg := io.sum
|
||||
mxrReg := io.mxr
|
||||
state := sL2
|
||||
}
|
||||
}.elsewhen((state === sL2 || state === sL1 || state === sL0) && io.memResp.valid) {
|
||||
@@ -78,6 +99,8 @@ class PageTableWalker(p: CoreParams = CoreParams()) extends Module {
|
||||
val ppn1 = Mux(level <= 1.U, ptePpn(17, 9), vpnReg(17, 9))
|
||||
val ppn2 = ptePpn(43, 18)
|
||||
nextPpn := Cat(ppn2, ppn1, ppn0)
|
||||
leafFlagsReg := pteFlags
|
||||
leafLevelReg := level
|
||||
state := sDone
|
||||
}.otherwise {
|
||||
curPpn := ptePpn
|
||||
@@ -111,6 +134,9 @@ class MMU(p: CoreParams = CoreParams()) extends Module {
|
||||
walker.io.reqVpn := io.req.vaddr(38, 12)
|
||||
walker.io.isStore := io.req.isStore
|
||||
walker.io.isFetch := io.req.isFetch
|
||||
walker.io.priv := io.req.priv
|
||||
walker.io.sum := io.req.sum
|
||||
walker.io.mxr := io.req.mxr
|
||||
walker.io.satp := io.satp
|
||||
walker.io.memResp := io.ptwMemResp
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ class MemStage(p: CoreParams = CoreParams()) extends Module {
|
||||
val reqValid = Input(Bool())
|
||||
val req = Input(new MemRequest(p))
|
||||
val satp = Input(UInt(p.xlen.W))
|
||||
val currentPriv = Input(UInt(2.W))
|
||||
val mstatus = Input(UInt(p.xlen.W))
|
||||
val dmemReqValid = Output(Bool())
|
||||
val dmemReq = Output(new MemRequest(p))
|
||||
val dmemRespValid = Input(Bool())
|
||||
@@ -17,6 +19,10 @@ class MemStage(p: CoreParams = CoreParams()) extends Module {
|
||||
val lsu = Module(new LSU(p))
|
||||
lsu.io.reqValid := io.reqValid
|
||||
lsu.io.req := io.req
|
||||
lsu.io.checkOnly := false.B
|
||||
lsu.io.sfenceVma := false.B
|
||||
lsu.io.currentPriv := io.currentPriv
|
||||
lsu.io.mstatus := io.mstatus
|
||||
lsu.io.satp := io.satp
|
||||
lsu.io.dmemRespValid := io.dmemRespValid
|
||||
lsu.io.dmemRespData := io.dmemRespData
|
||||
|
||||
@@ -30,6 +30,7 @@ class StoreQueue(p: CoreParams = CoreParams()) extends Module {
|
||||
val commitRobIdx = Input(UInt(robBits.W))
|
||||
val drainValid = Output(Bool())
|
||||
val drain = Output(new MemRequest(p))
|
||||
val drainRobIdx = Output(UInt(robBits.W))
|
||||
val drainReady = Input(Bool())
|
||||
val flush = Input(Bool())
|
||||
})
|
||||
@@ -140,6 +141,7 @@ class StoreQueue(p: CoreParams = CoreParams()) extends Module {
|
||||
io.drain.isAmo := false.B
|
||||
io.drain.amoOp := 0.U
|
||||
io.drain.size := entries(drainIdx).size
|
||||
io.drainRobIdx := entries(drainIdx).robIdx
|
||||
|
||||
when(io.flush) {
|
||||
entries.foreach(_ := 0.U.asTypeOf(new StoreQueueEntry(p)))
|
||||
|
||||
@@ -22,6 +22,9 @@ class RobEntry(p: CoreParams = CoreParams()) extends Bundle {
|
||||
val csrRs1 = UInt(p.xlen.W)
|
||||
val csrZimm = UInt(5.W)
|
||||
val fenceI = Bool()
|
||||
val sfenceVma = Bool()
|
||||
val xret = Bool()
|
||||
val xretIsMret = Bool()
|
||||
}
|
||||
|
||||
class ROB(p: CoreParams = CoreParams()) extends Module {
|
||||
@@ -43,6 +46,10 @@ class ROB(p: CoreParams = CoreParams()) extends Module {
|
||||
val completeCsrCmd = Input(Vec(p.issueWidth, UInt(3.W)))
|
||||
val completeCsrRs1 = Input(Vec(p.issueWidth, UInt(p.xlen.W)))
|
||||
val completeCsrZimm = Input(Vec(p.issueWidth, UInt(5.W)))
|
||||
val completeFenceI = Input(Vec(p.issueWidth, Bool()))
|
||||
val completeSfenceVma = Input(Vec(p.issueWidth, Bool()))
|
||||
val completeXret = Input(Vec(p.issueWidth, Bool()))
|
||||
val completeXretIsMret = Input(Vec(p.issueWidth, Bool()))
|
||||
val commitValid = Output(Vec(p.issueWidth, Bool()))
|
||||
val commit = Output(Vec(p.issueWidth, new RobEntry(p)))
|
||||
val commitReady = Input(Vec(p.issueWidth, Bool()))
|
||||
@@ -63,6 +70,10 @@ class ROB(p: CoreParams = CoreParams()) extends Module {
|
||||
val csrCmd = RegInit(VecInit(Seq.fill(p.robEntries)(0.U(3.W))))
|
||||
val csrRs1 = RegInit(VecInit(Seq.fill(p.robEntries)(0.U(p.xlen.W))))
|
||||
val csrZimm = RegInit(VecInit(Seq.fill(p.robEntries)(0.U(5.W))))
|
||||
val fenceI = RegInit(VecInit(Seq.fill(p.robEntries)(false.B)))
|
||||
val sfenceVma = RegInit(VecInit(Seq.fill(p.robEntries)(false.B)))
|
||||
val xret = RegInit(VecInit(Seq.fill(p.robEntries)(false.B)))
|
||||
val xretIsMret = RegInit(VecInit(Seq.fill(p.robEntries)(false.B)))
|
||||
val head = RegInit(0.U(idxBits.W))
|
||||
val tail = RegInit(0.U(idxBits.W))
|
||||
val count = RegInit(0.U(log2Ceil(p.robEntries + 1).W))
|
||||
@@ -87,6 +98,10 @@ class ROB(p: CoreParams = CoreParams()) extends Module {
|
||||
headEntry0.csrCmd := csrCmd(head0)
|
||||
headEntry0.csrRs1 := csrRs1(head0)
|
||||
headEntry0.csrZimm := csrZimm(head0)
|
||||
headEntry0.fenceI := fenceI(head0)
|
||||
headEntry0.sfenceVma := sfenceVma(head0)
|
||||
headEntry0.xret := xret(head0)
|
||||
headEntry0.xretIsMret := xretIsMret(head0)
|
||||
headEntry1 := entries(head1)
|
||||
headEntry1.valid := valid(head1)
|
||||
headEntry1.completed := completed(head1)
|
||||
@@ -100,6 +115,10 @@ class ROB(p: CoreParams = CoreParams()) extends Module {
|
||||
headEntry1.csrCmd := csrCmd(head1)
|
||||
headEntry1.csrRs1 := csrRs1(head1)
|
||||
headEntry1.csrZimm := csrZimm(head1)
|
||||
headEntry1.fenceI := fenceI(head1)
|
||||
headEntry1.sfenceVma := sfenceVma(head1)
|
||||
headEntry1.xret := xret(head1)
|
||||
headEntry1.xretIsMret := xretIsMret(head1)
|
||||
|
||||
io.empty := count === 0.U
|
||||
io.canAllocate := (p.robEntries.U - count) >= p.issueWidth.U
|
||||
@@ -117,6 +136,10 @@ class ROB(p: CoreParams = CoreParams()) extends Module {
|
||||
exception := VecInit(Seq.fill(p.robEntries)(false.B))
|
||||
branchMispredict := VecInit(Seq.fill(p.robEntries)(false.B))
|
||||
csrValid := VecInit(Seq.fill(p.robEntries)(false.B))
|
||||
fenceI := VecInit(Seq.fill(p.robEntries)(false.B))
|
||||
sfenceVma := VecInit(Seq.fill(p.robEntries)(false.B))
|
||||
xret := VecInit(Seq.fill(p.robEntries)(false.B))
|
||||
xretIsMret := VecInit(Seq.fill(p.robEntries)(false.B))
|
||||
head := 0.U
|
||||
tail := 0.U
|
||||
count := 0.U
|
||||
@@ -136,6 +159,10 @@ class ROB(p: CoreParams = CoreParams()) extends Module {
|
||||
csrCmd(tail0) := 0.U
|
||||
csrRs1(tail0) := 0.U
|
||||
csrZimm(tail0) := 0.U
|
||||
fenceI(tail0) := io.allocateEntry(0).fenceI
|
||||
sfenceVma(tail0) := io.allocateEntry(0).sfenceVma
|
||||
xret(tail0) := io.allocateEntry(0).xret
|
||||
xretIsMret(tail0) := io.allocateEntry(0).xretIsMret
|
||||
}
|
||||
when(io.allocateValid(1) && io.canAllocate) {
|
||||
entries(tail1) := io.allocateEntry(1)
|
||||
@@ -152,6 +179,10 @@ class ROB(p: CoreParams = CoreParams()) extends Module {
|
||||
csrCmd(tail1) := 0.U
|
||||
csrRs1(tail1) := 0.U
|
||||
csrZimm(tail1) := 0.U
|
||||
fenceI(tail1) := io.allocateEntry(1).fenceI
|
||||
sfenceVma(tail1) := io.allocateEntry(1).sfenceVma
|
||||
xret(tail1) := io.allocateEntry(1).xret
|
||||
xretIsMret(tail1) := io.allocateEntry(1).xretIsMret
|
||||
}
|
||||
for (i <- 0 until p.issueWidth) {
|
||||
when(io.completeValid(i)) {
|
||||
@@ -166,6 +197,10 @@ class ROB(p: CoreParams = CoreParams()) extends Module {
|
||||
csrCmd(io.completeIdx(i)) := io.completeCsrCmd(i)
|
||||
csrRs1(io.completeIdx(i)) := io.completeCsrRs1(i)
|
||||
csrZimm(io.completeIdx(i)) := io.completeCsrZimm(i)
|
||||
fenceI(io.completeIdx(i)) := io.completeFenceI(i)
|
||||
sfenceVma(io.completeIdx(i)) := io.completeSfenceVma(i)
|
||||
xret(io.completeIdx(i)) := io.completeXret(i)
|
||||
xretIsMret(io.completeIdx(i)) := io.completeXretIsMret(i)
|
||||
}
|
||||
}
|
||||
val commit0 = io.commitValid(0) && io.commitReady(0)
|
||||
|
||||
@@ -27,6 +27,10 @@ class RenameStage(p: CoreParams = CoreParams()) extends Module {
|
||||
val completeCsrCmd = Input(Vec(p.issueWidth, UInt(3.W)))
|
||||
val completeCsrRs1 = Input(Vec(p.issueWidth, UInt(p.xlen.W)))
|
||||
val completeCsrZimm = Input(Vec(p.issueWidth, UInt(5.W)))
|
||||
val completeFenceI = Input(Vec(p.issueWidth, Bool()))
|
||||
val completeSfenceVma = Input(Vec(p.issueWidth, Bool()))
|
||||
val completeXret = Input(Vec(p.issueWidth, Bool()))
|
||||
val completeXretIsMret = Input(Vec(p.issueWidth, Bool()))
|
||||
|
||||
val commitReady = Input(Vec(p.issueWidth, Bool()))
|
||||
val commitValid = Output(Vec(p.issueWidth, Bool()))
|
||||
@@ -96,6 +100,9 @@ class RenameStage(p: CoreParams = CoreParams()) extends Module {
|
||||
e.dest := Mux(io.in(i).writesRd, freeList.io.allocPhys(i), table.io.oldPrd(i))
|
||||
e.oldDest := table.io.oldPrd(i)
|
||||
e.fenceI := io.in(i).isFenceI
|
||||
e.sfenceVma := io.in(i).isSfenceVma
|
||||
e.xret := io.in(i).isXret
|
||||
e.xretIsMret := io.in(i).isMret
|
||||
rob.io.allocateEntry(i) := e
|
||||
}
|
||||
rob.io.completeValid := io.completeValid
|
||||
@@ -110,6 +117,10 @@ class RenameStage(p: CoreParams = CoreParams()) extends Module {
|
||||
rob.io.completeCsrCmd := io.completeCsrCmd
|
||||
rob.io.completeCsrRs1 := io.completeCsrRs1
|
||||
rob.io.completeCsrZimm := io.completeCsrZimm
|
||||
rob.io.completeFenceI := io.completeFenceI
|
||||
rob.io.completeSfenceVma := io.completeSfenceVma
|
||||
rob.io.completeXret := io.completeXret
|
||||
rob.io.completeXretIsMret := io.completeXretIsMret
|
||||
rob.io.commitReady := io.commitReady
|
||||
rob.io.flush := io.flush
|
||||
io.commitValid := rob.io.commitValid
|
||||
|
||||
50
src/test/scala/commit/CommitPrivilegeSpec.scala
Normal file
50
src/test/scala/commit/CommitPrivilegeSpec.scala
Normal file
@@ -0,0 +1,50 @@
|
||||
import chisel3._
|
||||
import _root_.circt.stage.ChiselStage
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class CommitPrivilegeSpec extends AnyFlatSpec with Matchers {
|
||||
"Commit" should "emit redirect, trap, and xRET ports" in {
|
||||
class Harness extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val redirectPc = Output(UInt(64.W))
|
||||
val xret = Output(Bool())
|
||||
})
|
||||
val dut = Module(new CommitStage())
|
||||
dut.io.robValid := VecInit(Seq.fill(2)(false.B))
|
||||
dut.io.robEntry := VecInit(Seq.fill(2)(0.U.asTypeOf(new RobEntry())))
|
||||
io.redirectPc := dut.io.redirectPc
|
||||
io.xret := dut.io.xret
|
||||
}
|
||||
|
||||
val verilog = ChiselStage.emitSystemVerilog(new Harness)
|
||||
verilog should include("io_redirectPc")
|
||||
verilog should include("io_xret")
|
||||
}
|
||||
|
||||
it should "not commit destination mappings for excepting instructions" in {
|
||||
class Harness extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val commitReady = Output(Bool())
|
||||
val commitMapValid = Output(Bool())
|
||||
})
|
||||
val dut = Module(new CommitStage())
|
||||
val entry = WireDefault(0.U.asTypeOf(new RobEntry()))
|
||||
entry.valid := true.B
|
||||
entry.completed := true.B
|
||||
entry.exception := true.B
|
||||
entry.writesDest := true.B
|
||||
entry.archDest := 10.U
|
||||
entry.dest := 33.U
|
||||
|
||||
dut.io.robValid := VecInit(Seq(true.B, false.B))
|
||||
dut.io.robEntry := VecInit(Seq(entry, 0.U.asTypeOf(new RobEntry())))
|
||||
io.commitReady := dut.io.commitReady(0)
|
||||
io.commitMapValid := dut.io.commitMapValid(0)
|
||||
}
|
||||
|
||||
val verilog = ChiselStage.emitSystemVerilog(new Harness)
|
||||
verilog should include("assign io_commitReady = 1'h1;")
|
||||
verilog should include("assign io_commitMapValid = 1'h0;")
|
||||
}
|
||||
}
|
||||
24
src/test/scala/commit/RobCommitMetaSpec.scala
Normal file
24
src/test/scala/commit/RobCommitMetaSpec.scala
Normal file
@@ -0,0 +1,24 @@
|
||||
import chisel3._
|
||||
import _root_.circt.stage.ChiselStage
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class RobCommitMetaSpec extends AnyFlatSpec with Matchers {
|
||||
"ROB and CommitStage" should "emit privilege metadata IO" in {
|
||||
class Harness extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val flush = Output(Bool())
|
||||
val sfence = Output(Bool())
|
||||
})
|
||||
val dut = Module(new CommitStage())
|
||||
dut.io.robValid := VecInit(Seq.fill(2)(false.B))
|
||||
dut.io.robEntry := VecInit(Seq.fill(2)(0.U.asTypeOf(new RobEntry())))
|
||||
io.flush := dut.io.flush
|
||||
io.sfence := dut.io.sfenceVma
|
||||
}
|
||||
|
||||
val verilog = ChiselStage.emitSystemVerilog(new Harness)
|
||||
verilog should include("io_flush")
|
||||
verilog should include("io_sfence")
|
||||
}
|
||||
}
|
||||
28
src/test/scala/common/BundlesSpec.scala
Normal file
28
src/test/scala/common/BundlesSpec.scala
Normal file
@@ -0,0 +1,28 @@
|
||||
import chisel3._
|
||||
import _root_.circt.stage.ChiselStage
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class BundlesSpec extends AnyFlatSpec with Matchers {
|
||||
"TrapInfo" should "emit the expected trap fields" in {
|
||||
class Harness extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val cause = Output(UInt(64.W))
|
||||
val originPriv = Output(UInt(2.W))
|
||||
})
|
||||
val trap = Wire(new TrapInfo())
|
||||
trap.valid := true.B
|
||||
trap.isInterrupt := false.B
|
||||
trap.cause := Privileged.CAUSE_ILLEGAL_INSTRUCTION
|
||||
trap.tval := 0.U
|
||||
trap.epc := 0.U
|
||||
trap.originPriv := Privileged.PRV_M
|
||||
io.cause := trap.cause
|
||||
io.originPriv := trap.originPriv
|
||||
}
|
||||
|
||||
val verilog = ChiselStage.emitSystemVerilog(new Harness)
|
||||
verilog should include("io_cause")
|
||||
verilog should include("io_originPriv")
|
||||
}
|
||||
}
|
||||
27
src/test/scala/common/PrivilegedSpec.scala
Normal file
27
src/test/scala/common/PrivilegedSpec.scala
Normal file
@@ -0,0 +1,27 @@
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class PrivilegedSpec extends AnyFlatSpec with Matchers {
|
||||
"privilege encodings" should "match RV64 spec" in {
|
||||
Privileged.PRV_U.litValue should be(0)
|
||||
Privileged.PRV_S.litValue should be(1)
|
||||
Privileged.PRV_M.litValue should be(3)
|
||||
}
|
||||
|
||||
"ecall causes" should "match U/S/M encodings" in {
|
||||
Privileged.CAUSE_ECALL_FROM_U.litValue should be(8)
|
||||
Privileged.CAUSE_ECALL_FROM_S.litValue should be(9)
|
||||
Privileged.CAUSE_ECALL_FROM_M.litValue should be(11)
|
||||
}
|
||||
|
||||
"misa" should "only advertise implemented base extensions" in {
|
||||
val misa = Privileged.MISA_RV64_IMASU.litValue
|
||||
val fBit = BigInt(1) << ('F' - 'A')
|
||||
val dBit = BigInt(1) << ('D' - 'A')
|
||||
val cBit = BigInt(1) << ('C' - 'A')
|
||||
|
||||
(misa & fBit) should be(0)
|
||||
(misa & dBit) should be(0)
|
||||
(misa & cBit) should be(0)
|
||||
}
|
||||
}
|
||||
86
src/test/scala/csr/CSRFileSpec.scala
Normal file
86
src/test/scala/csr/CSRFileSpec.scala
Normal file
@@ -0,0 +1,86 @@
|
||||
import chisel3._
|
||||
import _root_.circt.stage.ChiselStage
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class CSRFileSpec extends AnyFlatSpec with Matchers {
|
||||
private def driveDefaults(dut: CSRFile): Unit = {
|
||||
dut.io.cmd.valid := false.B
|
||||
dut.io.cmd.addr := 0.U
|
||||
dut.io.cmd.cmd := 0.U
|
||||
dut.io.cmd.rs1 := 0.U
|
||||
dut.io.cmd.zimm := 0.U
|
||||
dut.io.currentPriv := Privileged.PRV_M
|
||||
dut.io.trap := false.B
|
||||
dut.io.trapPc := 0.U
|
||||
dut.io.trapCause := 0.U
|
||||
dut.io.trapTval := 0.U
|
||||
dut.io.trapTargetPriv := Privileged.PRV_M
|
||||
dut.io.trapIsInterrupt := false.B
|
||||
dut.io.xret := false.B
|
||||
dut.io.xretIsMret := true.B
|
||||
}
|
||||
|
||||
"CSRFile" should "expose permission and trap-aware ports" in {
|
||||
class Harness extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val rdata = Output(UInt(64.W))
|
||||
val illegal = Output(Bool())
|
||||
})
|
||||
val dut = Module(new CSRFile())
|
||||
driveDefaults(dut)
|
||||
dut.io.readAddr := Privileged.CSR_MSTATUS
|
||||
dut.io.currentPriv := Privileged.PRV_U
|
||||
io.rdata := dut.io.rdata
|
||||
io.illegal := dut.io.illegal
|
||||
}
|
||||
|
||||
val verilog = ChiselStage.emitSystemVerilog(new Harness)
|
||||
verilog should include("io_rdata")
|
||||
verilog should include("io_illegal")
|
||||
}
|
||||
|
||||
it should "read RV64 xlen fields as SXL=2 and UXL=2" in {
|
||||
class Harness extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val rdata = Output(UInt(64.W))
|
||||
})
|
||||
val dut = Module(new CSRFile())
|
||||
driveDefaults(dut)
|
||||
dut.io.readAddr := Privileged.CSR_MSTATUS
|
||||
io.rdata := dut.io.rdata
|
||||
}
|
||||
|
||||
val verilog = ChiselStage.emitSystemVerilog(new Harness)
|
||||
verilog should include("64'hA00000000")
|
||||
}
|
||||
|
||||
it should "emit machine counter and ID CSR decode semantics" in {
|
||||
class Harness extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val readAddr = Input(UInt(12.W))
|
||||
val writeAddr = Input(UInt(12.W))
|
||||
val writeData = Input(UInt(64.W))
|
||||
val rdata = Output(UInt(64.W))
|
||||
})
|
||||
val dut = Module(new CSRFile())
|
||||
driveDefaults(dut)
|
||||
dut.io.cmd.valid := true.B
|
||||
dut.io.cmd.addr := io.writeAddr
|
||||
dut.io.cmd.cmd := 1.U
|
||||
dut.io.cmd.rs1 := io.writeData
|
||||
dut.io.readAddr := io.readAddr
|
||||
io.rdata := dut.io.rdata
|
||||
}
|
||||
|
||||
val verilog = ChiselStage.emitSystemVerilog(new Harness)
|
||||
verilog should include("mcountinhibit")
|
||||
verilog should include("suppressInstretIncrement")
|
||||
verilog should include("12'h320")
|
||||
verilog should include("12'hB02")
|
||||
verilog should include("12'hF11")
|
||||
verilog should include("12'hF12")
|
||||
verilog should include("12'hF13")
|
||||
verilog should include("12'hF14")
|
||||
}
|
||||
}
|
||||
71
src/test/scala/csr/CSRPermissionSpec.scala
Normal file
71
src/test/scala/csr/CSRPermissionSpec.scala
Normal file
@@ -0,0 +1,71 @@
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class CSRPermissionSpec extends AnyFlatSpec with Matchers {
|
||||
"readAllowed" should "allow U-read of user counters and deny M-only CSRs" in {
|
||||
CSRPermission.readAllowedLit(Privileged.CSR_CYCLE.litValue, Privileged.PRV_U.litValue) should be(true)
|
||||
CSRPermission.readAllowedLit(Privileged.CSR_MSTATUS.litValue, Privileged.PRV_U.litValue) should be(false)
|
||||
}
|
||||
|
||||
"writeAllowed" should "block read-only and privilege-incompatible CSRs" in {
|
||||
CSRPermission.writeAllowedLit(Privileged.CSR_MTVEC.litValue, Privileged.PRV_S.litValue) should be(false)
|
||||
CSRPermission.writeAllowedLit(Privileged.CSR_SATP.litValue, Privileged.PRV_U.litValue) should be(false)
|
||||
CSRPermission.writeAllowedLit(Privileged.CSR_SATP.litValue, Privileged.PRV_S.litValue) should be(true)
|
||||
}
|
||||
|
||||
it should "allow machine-mode WARL writes to misa" in {
|
||||
CSRPermission.writeAllowedLit(Privileged.CSR_MISA.litValue, Privileged.PRV_M.litValue) should be(true)
|
||||
}
|
||||
|
||||
"CSR permissions" should "reject writes to read-only counters" in {
|
||||
CSRPermission.writeAllowedLit(Privileged.CSR_CYCLE.litValue, Privileged.PRV_M.litValue) should be(false)
|
||||
CSRPermission.readAllowedLit(Privileged.CSR_CYCLE.litValue, Privileged.PRV_M.litValue) should be(true)
|
||||
}
|
||||
|
||||
it should "reject machine CSRs below M mode" in {
|
||||
CSRPermission.readAllowedLit(Privileged.CSR_MSTATUS.litValue, Privileged.PRV_S.litValue) should be(false)
|
||||
CSRPermission.writeAllowedLit(Privileged.CSR_MSTATUS.litValue, Privileged.PRV_S.litValue) should be(false)
|
||||
}
|
||||
|
||||
it should "allow machine-mode access to debug trigger and PMP CSRs used by privileged tests" in {
|
||||
val machineWritable = Seq(
|
||||
Privileged.CSR_TSELECT,
|
||||
Privileged.CSR_TDATA1,
|
||||
Privileged.CSR_TDATA2,
|
||||
Privileged.CSR_TCONTROL,
|
||||
Privileged.CSR_PMPADDR0,
|
||||
Privileged.CSR_PMPCFG0,
|
||||
Privileged.CSR_MNSTATUS)
|
||||
|
||||
machineWritable.foreach { csr =>
|
||||
CSRPermission.readAllowedLit(csr.litValue, Privileged.PRV_M.litValue) should be(true)
|
||||
CSRPermission.writeAllowedLit(csr.litValue, Privileged.PRV_M.litValue) should be(true)
|
||||
CSRPermission.readAllowedLit(csr.litValue, Privileged.PRV_S.litValue) should be(false)
|
||||
}
|
||||
}
|
||||
|
||||
it should "allow machine-mode reads of machine ID CSRs only and reject writes" in {
|
||||
val machineIds = Seq(
|
||||
Privileged.CSR_MVENDORID,
|
||||
Privileged.CSR_MARCHID,
|
||||
Privileged.CSR_MIMPID,
|
||||
Privileged.CSR_MHARTID)
|
||||
|
||||
machineIds.foreach { csr =>
|
||||
CSRPermission.readAllowedLit(csr.litValue, Privileged.PRV_M.litValue) should be(true)
|
||||
CSRPermission.writeAllowedLit(csr.litValue, Privileged.PRV_M.litValue) should be(false)
|
||||
CSRPermission.readAllowedLit(csr.litValue, Privileged.PRV_S.litValue) should be(false)
|
||||
}
|
||||
}
|
||||
|
||||
it should "allow machine-mode reads and writes to minstret and mcountinhibit" in {
|
||||
val machineCounters = Seq(
|
||||
Privileged.CSR_MINSTRET,
|
||||
Privileged.CSR_MCOUNTINHIBIT)
|
||||
|
||||
machineCounters.foreach { csr =>
|
||||
CSRPermission.readAllowedLit(csr.litValue, Privileged.PRV_M.litValue) should be(true)
|
||||
CSRPermission.writeAllowedLit(csr.litValue, Privileged.PRV_M.litValue) should be(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/test/scala/csr/PrivilegeControlSpec.scala
Normal file
19
src/test/scala/csr/PrivilegeControlSpec.scala
Normal file
@@ -0,0 +1,19 @@
|
||||
import chisel3._
|
||||
import _root_.circt.stage.ChiselStage
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class PrivilegeControlSpec extends AnyFlatSpec with Matchers {
|
||||
"PrivilegeControl" should "expose current privilege and set interface" in {
|
||||
class Harness extends Module {
|
||||
val io = IO(new Bundle { val priv = Output(UInt(2.W)) })
|
||||
val dut = Module(new PrivilegeControl())
|
||||
dut.io.nextPriv := Privileged.PRV_M
|
||||
dut.io.setPriv := false.B
|
||||
io.priv := dut.io.priv
|
||||
}
|
||||
|
||||
val verilog = ChiselStage.emitSystemVerilog(new Harness)
|
||||
verilog should include("io_priv")
|
||||
}
|
||||
}
|
||||
46
src/test/scala/csr/PrivilegeTransitionSpec.scala
Normal file
46
src/test/scala/csr/PrivilegeTransitionSpec.scala
Normal file
@@ -0,0 +1,46 @@
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import _root_.circt.stage.ChiselStage
|
||||
|
||||
class PrivilegeTransitionSpec extends AnyFlatSpec with Matchers {
|
||||
"trap target privilege" should "honor exception delegation only below M-mode" in {
|
||||
val uEcallBit = BigInt(1) << Privileged.CAUSE_ECALL_FROM_U.litValue.toInt
|
||||
PrivilegeTransitions.trapTargetPrivLit(
|
||||
currentPriv = Privileged.PRV_U.litValue,
|
||||
cause = Privileged.CAUSE_ECALL_FROM_U.litValue,
|
||||
isInterrupt = false,
|
||||
medeleg = uEcallBit,
|
||||
mideleg = 0) should be(Privileged.PRV_S.litValue)
|
||||
PrivilegeTransitions.trapTargetPrivLit(
|
||||
currentPriv = Privileged.PRV_M.litValue,
|
||||
cause = Privileged.CAUSE_ECALL_FROM_M.litValue,
|
||||
isInterrupt = false,
|
||||
medeleg = BigInt(1) << Privileged.CAUSE_ECALL_FROM_M.litValue.toInt,
|
||||
mideleg = 0) should be(Privileged.PRV_M.litValue)
|
||||
}
|
||||
|
||||
"xRET target privilege" should "recover MPP and SPP fields" in {
|
||||
val mstatusMppS = BigInt(1) << 11
|
||||
val sstatusSpp = BigInt(1) << 8
|
||||
PrivilegeTransitions.mretNextPrivLit(mstatusMppS) should be(Privileged.PRV_S.litValue)
|
||||
PrivilegeTransitions.sretNextPrivLit(sstatusSpp) should be(Privileged.PRV_S.litValue)
|
||||
PrivilegeTransitions.sretNextPrivLit(0) should be(Privileged.PRV_U.litValue)
|
||||
}
|
||||
|
||||
"xRET target pc selection" should "use mepc for mret and sepc for sret" in {
|
||||
PrivilegeTransitions.xretTargetPcLit(isMret = true, mepc = 0x1000, sepc = 0x2000) should be(0x1000)
|
||||
PrivilegeTransitions.xretTargetPcLit(isMret = false, mepc = 0x1000, sepc = 0x2000) should be(0x2000)
|
||||
}
|
||||
|
||||
it should "select xRET redirect pc from commit-time CSR state" in {
|
||||
val verilog = ChiselStage.emitSystemVerilog(new OoOBackend())
|
||||
verilog should include("xretRedirectPc")
|
||||
verilog should include("io_redirectPc")
|
||||
}
|
||||
|
||||
it should "serialize CSR and privileged side-effect instructions at the ROB head" in {
|
||||
val verilog = ChiselStage.emitSystemVerilog(new OoOBackend())
|
||||
verilog should include("serializingReady0")
|
||||
verilog should include("serializingReady1")
|
||||
}
|
||||
}
|
||||
30
src/test/scala/decode/DecoderPrivFlagSpec.scala
Normal file
30
src/test/scala/decode/DecoderPrivFlagSpec.scala
Normal file
@@ -0,0 +1,30 @@
|
||||
import chisel3._
|
||||
import _root_.circt.stage.ChiselStage
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class DecoderPrivFlagSpec extends AnyFlatSpec with Matchers {
|
||||
"Decoder" should "emit privileged instruction flags" in {
|
||||
class Harness extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val ecall = Output(Bool())
|
||||
val sfence = Output(Bool())
|
||||
val fenceI = Output(Bool())
|
||||
val wfi = Output(Bool())
|
||||
})
|
||||
val dut = Module(new Decoder())
|
||||
dut.io.pc := 0.U
|
||||
dut.io.inst := "h10500073".U
|
||||
io.ecall := dut.io.out.isEcall
|
||||
io.sfence := dut.io.out.isSfenceVma
|
||||
io.fenceI := dut.io.out.isFenceI
|
||||
io.wfi := dut.io.out.isWfi
|
||||
}
|
||||
|
||||
val verilog = ChiselStage.emitSystemVerilog(new Harness)
|
||||
verilog should include("io_ecall")
|
||||
verilog should include("io_sfence")
|
||||
verilog should include("io_fenceI")
|
||||
verilog should include("io_wfi")
|
||||
}
|
||||
}
|
||||
10
src/test/scala/exception/EcallCauseSpec.scala
Normal file
10
src/test/scala/exception/EcallCauseSpec.scala
Normal file
@@ -0,0 +1,10 @@
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class EcallCauseSpec extends AnyFlatSpec with Matchers {
|
||||
"ECALL cause" should "depend on current privilege" in {
|
||||
ExceptionSource.ecallCauseLit(Privileged.PRV_U.litValue) should be(Privileged.CAUSE_ECALL_FROM_U.litValue)
|
||||
ExceptionSource.ecallCauseLit(Privileged.PRV_S.litValue) should be(Privileged.CAUSE_ECALL_FROM_S.litValue)
|
||||
ExceptionSource.ecallCauseLit(Privileged.PRV_M.litValue) should be(Privileged.CAUSE_ECALL_FROM_M.litValue)
|
||||
}
|
||||
}
|
||||
11
src/test/scala/exception/ExceptionPrioritySpec.scala
Normal file
11
src/test/scala/exception/ExceptionPrioritySpec.scala
Normal file
@@ -0,0 +1,11 @@
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class ExceptionPrioritySpec extends AnyFlatSpec with Matchers {
|
||||
"priority ranking" should "prefer instruction faults before illegal and ecall" in {
|
||||
ExceptionSource.priorityOf(Privileged.CAUSE_INSTR_PAGE_FAULT) should be(0)
|
||||
ExceptionSource.priorityOf(Privileged.CAUSE_INSTR_ACCESS_FAULT) should be(1)
|
||||
ExceptionSource.priorityOf(Privileged.CAUSE_ILLEGAL_INSTRUCTION) should be(2)
|
||||
ExceptionSource.priorityOf(Privileged.CAUSE_ECALL_FROM_U) should be(5)
|
||||
}
|
||||
}
|
||||
44
src/test/scala/exception/IllegalInstructionSpec.scala
Normal file
44
src/test/scala/exception/IllegalInstructionSpec.scala
Normal file
@@ -0,0 +1,44 @@
|
||||
import chisel3._
|
||||
import _root_.circt.stage.ChiselStage
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class IllegalInstructionSpec extends AnyFlatSpec with Matchers {
|
||||
"Decoder" should "emit illegal and privileged instruction fields" in {
|
||||
class Harness extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val illegal = Output(Bool())
|
||||
val isMret = Output(Bool())
|
||||
val isEcall = Output(Bool())
|
||||
})
|
||||
val dut = Module(new Decoder())
|
||||
dut.io.pc := 0.U
|
||||
dut.io.inst := "h30200073".U
|
||||
io.illegal := dut.io.out.illegal
|
||||
io.isMret := dut.io.out.isMret
|
||||
io.isEcall := dut.io.out.isEcall
|
||||
}
|
||||
|
||||
val verilog = ChiselStage.emitSystemVerilog(new Harness)
|
||||
verilog should include("io_isMret")
|
||||
verilog should include("io_isEcall")
|
||||
}
|
||||
|
||||
"OoOBackend" should "gate writeback when an issued instruction raises an exception" in {
|
||||
val verilog = ChiselStage.emitSystemVerilog(new OoOBackend())
|
||||
verilog should include("issueRaisesException")
|
||||
verilog should include("loadRespHasFault")
|
||||
}
|
||||
|
||||
it should "report illegal instruction bits in trap tval instead of the pc" in {
|
||||
val verilog = ChiselStage.emitSystemVerilog(new OoOBackend())
|
||||
verilog should include("decoded_inst")
|
||||
verilog should not include(": _issue_io_out_0_decoded_pc")
|
||||
verilog should not include(": _issue_io_out_1_decoded_pc")
|
||||
}
|
||||
|
||||
it should "raise instruction-address-misaligned on control-transfer targets" in {
|
||||
val verilog = ChiselStage.emitSystemVerilog(new OoOBackend())
|
||||
verilog should include("controlTargetMisaligned")
|
||||
}
|
||||
}
|
||||
26
src/test/scala/interrupt/ClintSpec.scala
Normal file
26
src/test/scala/interrupt/ClintSpec.scala
Normal file
@@ -0,0 +1,26 @@
|
||||
import chisel3._
|
||||
import _root_.circt.stage.ChiselStage
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class ClintSpec extends AnyFlatSpec with Matchers {
|
||||
"Clint" should "emit timer and software interrupt outputs" in {
|
||||
class Harness extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val msip = Output(Bool())
|
||||
val mtip = Output(Bool())
|
||||
})
|
||||
val dut = Module(new Clint())
|
||||
dut.io.addr := 0.U
|
||||
dut.io.wen := false.B
|
||||
dut.io.wdata := 0.U
|
||||
dut.io.ren := false.B
|
||||
io.msip := dut.io.mipMSIP
|
||||
io.mtip := dut.io.mipMTIP
|
||||
}
|
||||
|
||||
val verilog = ChiselStage.emitSystemVerilog(new Harness)
|
||||
verilog should include("io_msip")
|
||||
verilog should include("io_mtip")
|
||||
}
|
||||
}
|
||||
14
src/test/scala/interrupt/InterruptControllerSpec.scala
Normal file
14
src/test/scala/interrupt/InterruptControllerSpec.scala
Normal file
@@ -0,0 +1,14 @@
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class InterruptControllerSpec extends AnyFlatSpec with Matchers {
|
||||
"InterruptController" should "prefer MEI over MTI over MSI and honor delegation" in {
|
||||
InterruptController.highestMachineCauseLit(msip = true, mtip = true, meip = true) should be(
|
||||
Privileged.CAUSE_MACHINE_EXTERNAL_INTERRUPT.litValue)
|
||||
InterruptController.highestMachineCauseLit(msip = true, mtip = true, meip = false) should be(
|
||||
Privileged.CAUSE_MACHINE_TIMER_INTERRUPT.litValue)
|
||||
InterruptController.delegatesToSupervisorLit(
|
||||
cause = Privileged.CAUSE_SUPERVISOR_TIMER_INTERRUPT.litValue,
|
||||
mideleg = BigInt(1) << Privileged.CAUSE_SUPERVISOR_TIMER_INTERRUPT.litValue.toInt) should be(true)
|
||||
}
|
||||
}
|
||||
19
src/test/scala/interrupt/PlicSpec.scala
Normal file
19
src/test/scala/interrupt/PlicSpec.scala
Normal file
@@ -0,0 +1,19 @@
|
||||
import chisel3._
|
||||
import _root_.circt.stage.ChiselStage
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class PlicSpec extends AnyFlatSpec with Matchers {
|
||||
"Plic" should "emit external interrupt output" in {
|
||||
class Harness extends Module {
|
||||
val io = IO(new Bundle { val meip = Output(Bool()) })
|
||||
val dut = Module(new Plic())
|
||||
dut.io.externalPending := true.B
|
||||
dut.io.enable := true.B
|
||||
io.meip := dut.io.mipMEIP
|
||||
}
|
||||
|
||||
val verilog = ChiselStage.emitSystemVerilog(new Harness)
|
||||
verilog should include("io_meip")
|
||||
}
|
||||
}
|
||||
94
src/test/scala/memory/Sv39Spec.scala
Normal file
94
src/test/scala/memory/Sv39Spec.scala
Normal file
@@ -0,0 +1,94 @@
|
||||
import chisel3._
|
||||
import _root_.circt.stage.ChiselStage
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class Sv39Spec extends AnyFlatSpec with Matchers {
|
||||
private def occurrences(haystack: String, needle: String): Int =
|
||||
haystack.sliding(needle.length).count(_ == needle)
|
||||
|
||||
"MMU" should "emit Sv39 response and refill fields" in {
|
||||
class Harness extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val pageFault = Output(Bool())
|
||||
val paddr = Output(UInt(64.W))
|
||||
})
|
||||
val dut = Module(new MMU())
|
||||
dut.io.satp := 0.U
|
||||
dut.io.req.valid := false.B
|
||||
dut.io.req.vaddr := 0.U
|
||||
dut.io.req.isStore := false.B
|
||||
dut.io.req.isFetch := false.B
|
||||
dut.io.req.priv := Privileged.PRV_M
|
||||
dut.io.req.sum := false.B
|
||||
dut.io.req.mxr := false.B
|
||||
dut.io.ptwMemResp.valid := false.B
|
||||
dut.io.ptwMemResp.data := 0.U
|
||||
io.pageFault := dut.io.resp.pageFault
|
||||
io.paddr := dut.io.resp.paddr
|
||||
}
|
||||
|
||||
val verilog = ChiselStage.emitSystemVerilog(new Harness)
|
||||
verilog should include("io_pageFault")
|
||||
verilog should include("io_paddr")
|
||||
}
|
||||
|
||||
it should "emit registered refill metadata" in {
|
||||
val verilog = ChiselStage.emitSystemVerilog(new MMU())
|
||||
verilog should include("leafFlagsReg")
|
||||
verilog should include("leafLevelReg")
|
||||
}
|
||||
|
||||
"DTLB" should "emit data permission controls for cached hits" in {
|
||||
val verilog = ChiselStage.emitSystemVerilog(new DTLB())
|
||||
occurrences(verilog, "io_req_priv") should be > 1
|
||||
occurrences(verilog, "io_req_sum") should be > 1
|
||||
occurrences(verilog, "io_req_mxr") should be > 1
|
||||
}
|
||||
|
||||
"LSU" should "emit effective privilege controls for data translation" in {
|
||||
val verilog = ChiselStage.emitSystemVerilog(new LSU())
|
||||
verilog should include("io_currentPriv")
|
||||
verilog should include("io_mstatus")
|
||||
verilog should include("io_mstatus[17]")
|
||||
}
|
||||
|
||||
"Frontend" should "emit instruction-side Sv39 translation controls" in {
|
||||
val verilog = ChiselStage.emitSystemVerilog(new Frontend())
|
||||
verilog should include("io_satp")
|
||||
verilog should include("io_currentPriv")
|
||||
verilog should include("io_ptwMemReqValid")
|
||||
verilog should include("io_ptwMemReqAddr")
|
||||
verilog should include("io_ptwMemRespValid")
|
||||
verilog should include("io_ptwMemRespData")
|
||||
verilog should include("fetchTranslate")
|
||||
verilog should include("immu")
|
||||
verilog should include("itlbMiss")
|
||||
verilog should include("translationReady")
|
||||
verilog should include("translatedFetchAddr")
|
||||
}
|
||||
|
||||
it should "emit pending request replay state for DTLB misses" in {
|
||||
val verilog = ChiselStage.emitSystemVerilog(new LSU())
|
||||
verilog should include("pendingValid")
|
||||
verilog should include("pendingReq_addr")
|
||||
verilog should include("pendingPriv")
|
||||
verilog should include("pendingMstatus")
|
||||
verilog should include("ptwReqFire")
|
||||
verilog should include("storeComplete")
|
||||
verilog should not include("faultValid")
|
||||
}
|
||||
|
||||
"OoOBackend" should "complete stores from LSU drain responses" in {
|
||||
val verilog = ChiselStage.emitSystemVerilog(new OoOBackend())
|
||||
verilog should include("storeCheckPending")
|
||||
verilog should include("storeCheckPendingRob")
|
||||
verilog should include("storeCheckResp")
|
||||
}
|
||||
|
||||
"MemStage" should "expose LSU privilege controls" in {
|
||||
val verilog = ChiselStage.emitSystemVerilog(new MemStage())
|
||||
verilog should include("io_currentPriv")
|
||||
verilog should include("io_mstatus")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user