diff --git a/chisel/playground/src/Core.scala b/chisel/playground/src/Core.scala index c8af575..5c28a4b 100644 --- a/chisel/playground/src/Core.scala +++ b/chisel/playground/src/Core.scala @@ -109,16 +109,17 @@ class Core(implicit val cpuConfig: CpuConfig) extends Module { csr.ext_int := io.ext_int - memoryUnit.dataMemory.in.rdata := io.data.rdata - memoryUnit.dataMemory.in.acc_err := io.data.access_fault - memoryUnit.dataMemory.in.ready := io.data.dcache_ready - io.data.en := memoryUnit.dataMemory.out.en - io.data.rlen := memoryUnit.dataMemory.out.rlen - io.data.wen := memoryUnit.dataMemory.out.wen - io.data.wdata := memoryUnit.dataMemory.out.wdata - io.data.addr := memoryUnit.dataMemory.out.addr - io.data.wstrb := memoryUnit.dataMemory.out.wstrb - io.data.exe_addr := executeUnit.dataMemory.addr + memoryUnit.dataMemory.in.rdata := io.data.rdata + memoryUnit.dataMemory.in.access_fault := io.data.access_fault + memoryUnit.dataMemory.in.page_fault := io.data.page_fault + memoryUnit.dataMemory.in.ready := io.data.dcache_ready + io.data.en := memoryUnit.dataMemory.out.en + io.data.rlen := memoryUnit.dataMemory.out.rlen + io.data.wen := memoryUnit.dataMemory.out.wen + io.data.wdata := memoryUnit.dataMemory.out.wdata + io.data.addr := memoryUnit.dataMemory.out.addr + io.data.wstrb := memoryUnit.dataMemory.out.wstrb + io.data.exe_addr := executeUnit.dataMemory.addr writeBackStage.memoryUnit <> memoryUnit.writeBackStage writeBackStage.ctrl.allow_to_go := ctrl.writeBackUnit.allow_to_go diff --git a/chisel/playground/src/cache/DCache.scala b/chisel/playground/src/cache/DCache.scala index 21f6c1b..1ea590f 100644 --- a/chisel/playground/src/cache/DCache.scala +++ b/chisel/playground/src/cache/DCache.scala @@ -261,9 +261,11 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo io.axi.b.ready := true.B val access_fault = RegInit(false.B) + val page_fault = RegInit(false.B) val addr_err = io.cpu.addr(XLEN - 1, VADDR_WID).orR io.cpu.access_fault := access_fault + io.cpu.page_fault := page_fault // write buffer when(writeFifo_axi_busy) { @@ -294,7 +296,8 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo switch(state) { is(s_idle) { - access_fault := false.B // 在idle时清除acc_err + access_fault := false.B // 在idle时清除access_fault + page_fault := false.B // 在idle时清除page_fault when(io.cpu.en) { when(addr_err) { access_fault := true.B @@ -496,6 +499,17 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo } is(s_tlb_refill) { io.cpu.tlb.ptw.vpn.ready := ptw_state === s_handshake + when(io.cpu.tlb.access_fault) { + access_fault := true.B + state := s_wait + }.elsewhen(io.cpu.tlb.page_fault) { + page_fault := true.B + state := s_wait + }.otherwise { + when(io.cpu.tlb.hit) { + state := s_idle + } + } } } @@ -503,7 +517,7 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo // 实现页表访问,回填tlb val satp = io.cpu.tlb.csr.satp.asTypeOf(satpBundle) val mstatus = io.cpu.tlb.csr.mstatus.asTypeOf(new Mstatus) - val mode = io.cpu.tlb.csr.mode + val mode = Mux(io.cpu.tlb.access_type === AccessType.fetch, io.cpu.tlb.csr.imode, io.cpu.tlb.csr.dmode) val sum = mstatus.sum val mxr = mstatus.mxr val vpn = io.cpu.tlb.ptw.vpn.bits.asTypeOf(vpnBundle) diff --git a/chisel/playground/src/cache/ICache.scala b/chisel/playground/src/cache/ICache.scala index dfb4821..05e092b 100644 --- a/chisel/playground/src/cache/ICache.scala +++ b/chisel/playground/src/cache/ICache.scala @@ -211,7 +211,7 @@ class ICache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo switch(state) { is(s_idle) { - access_fault := false.B // 在idle时清除acc_err + access_fault := false.B // 在idle时清除access_fault page_fault := false.B // 在idle时清除page_fault when(io.cpu.req) { when(addr_err) { diff --git a/chisel/playground/src/cache/mmu/Tlb.scala b/chisel/playground/src/cache/mmu/Tlb.scala index 9dd3087..f7efcf8 100644 --- a/chisel/playground/src/cache/mmu/Tlb.scala +++ b/chisel/playground/src/cache/mmu/Tlb.scala @@ -57,19 +57,20 @@ class Tlb extends Module with HasTlbConst with HasCSRConst { val satp = io.csr.satp.asTypeOf(satpBundle) val mstatus = io.csr.mstatus.asTypeOf(new Mstatus) - val mode = io.csr.mode + val imode = io.csr.imode + val dmode = io.csr.dmode // 当SUM=0时,S模式内存访问U模式可访问的页面(U=1)将出现故障。 // 当SUM=1时,这些访问是允许的。当基于页面的虚拟内存不生效时,SUM无效。 // 请注意,虽然SUM通常在不在S模式下执行时被忽略,但当MPRV=1和MPP=S时,SUM有效。 - val sum_valid = (mode === ModeS) || mstatus.mprv && mstatus.mpp === ModeS - val sum = mstatus.sum + val sum = mstatus.sum // 当MXR=0时,只有标记为可读的页面(R=1)的加载才会成功。 // 当MXR=1时,标记为可读或可执行的页面(R=1或X=1)的加载才会成功。 // 当基于页面的虚拟内存无效时,MXR无效。 val mxr = mstatus.mxr // 只有当satp.mode为8且当前模式低于M模式时,才启用虚拟内存 - val vm_enabled = (satp.mode === 8.U) && (mode < ModeM) + val ivm_enabled = (satp.mode === 8.U) && (imode < ModeM) + val dvm_enabled = (satp.mode === 8.U) && (dmode < ModeM) val itlb = RegInit(0.U.asTypeOf(tlbBundle)) val dtlb = RegInit(0.U.asTypeOf(tlbBundle)) @@ -120,7 +121,7 @@ class Tlb extends Module with HasTlbConst with HasCSRConst { val ar_sel_lock = RegInit(false.B) val ar_sel_val = RegInit(false.B) // 我们默认优先发送数据tlb的请求 - val ar_sel = Mux(ar_sel_lock, ar_sel_val, !req_ptw(0) && req_ptw(1)) + val ar_sel = Mux(ar_sel_lock, ar_sel_val, req_ptw(0) && !req_ptw(1)) when(io.dcache.ptw.vpn.valid) { when(io.dcache.ptw.vpn.ready) { @@ -140,13 +141,13 @@ class Tlb extends Module with HasTlbConst with HasCSRConst { // 将ptw模块集成到dcache中,ptw通过dcache的axi进行内存访问 io.dcache.ptw.vpn.valid := false.B - io.dcache.ptw.access_type := Mux(ar_sel === 0.U, AccessType.fetch, io.dcache.access_type) - io.dcache.ptw.vpn.bits := Mux(ar_sel === 0.U, ivpn, dvpn) + io.dcache.ptw.access_type := Mux(ar_sel, AccessType.fetch, io.dcache.access_type) + io.dcache.ptw.vpn.bits := Mux(ar_sel, ivpn, dvpn) io.dcache.ptw.pte.ready := true.B // 恒为true io.dcache.csr <> io.csr def imodeCheck(): Unit = { - switch(mode) { + switch(imode) { is(ModeS) { when(itlb.flag.u && sum === 0.U) { ipage_fault := true.B @@ -167,7 +168,7 @@ class Tlb extends Module with HasTlbConst with HasCSRConst { } def dmodeCheck(): Unit = { - switch(mode) { + switch(dmode) { is(ModeS) { when(dtlb.flag.u && sum === 0.U) { dpage_fault := true.B @@ -196,7 +197,7 @@ class Tlb extends Module with HasTlbConst with HasCSRConst { // 在icache实现访问tlb的pma和pmp权限检查 ipage_fault := false.B iaccess_fault := false.B - when(!vm_enabled) { + when(!ivm_enabled) { io.icache.hit := true.B }.elsewhen(itlbl1_hit) { // 在这里进行取指需要的所有的权限检查 @@ -222,7 +223,7 @@ class Tlb extends Module with HasTlbConst with HasCSRConst { itlb := tlbl2(PriorityEncoder(il2_hit_vec)) }.otherwise { req_ptw(0) := true.B - when(ar_sel === 0.U && io.dcache.ptw.vpn.ready) { + when(ar_sel && io.dcache.ptw.vpn.ready) { io.dcache.ptw.vpn.valid := true.B immu_state := search_pte } @@ -269,7 +270,7 @@ class Tlb extends Module with HasTlbConst with HasCSRConst { // 在dcache实现访问tlb的pma和pmp权限检查 dpage_fault := false.B daccess_fault := false.B - when(!vm_enabled) { + when(!dvm_enabled) { io.dcache.hit := true.B }.elsewhen(dtlbl1_hit) { // 在这里进行取指需要的所有的权限检查 @@ -316,8 +317,8 @@ class Tlb extends Module with HasTlbConst with HasCSRConst { dmmu_state := search_l1 dtlb := tlbl2(PriorityEncoder(il2_hit_vec)) }.otherwise { - req_ptw(0) := true.B - when(ar_sel === 0.U && io.dcache.ptw.vpn.ready) { + req_ptw(1) := true.B + when(!ar_sel && io.dcache.ptw.vpn.ready) { io.dcache.ptw.vpn.valid := true.B dmmu_state := search_pte } @@ -408,11 +409,11 @@ class Tlb extends Module with HasTlbConst with HasCSRConst { } io.icache.uncached := AddressSpace.isMMIO(io.icache.addr) - io.icache.ptag := Mux(vm_enabled, itlb.ppn, io.icache.addr(PADDR_WID - 1, pageOffsetLen)) + io.icache.ptag := Mux(ivm_enabled, itlb.ppn, io.icache.addr(PADDR_WID - 1, pageOffsetLen)) io.icache.paddr := Cat(io.icache.ptag, io.icache.addr(pageOffsetLen - 1, 0)) io.dcache.uncached := AddressSpace.isMMIO(io.dcache.addr) - io.dcache.ptag := Mux(vm_enabled, dtlb.ppn, io.dcache.addr(PADDR_WID - 1, pageOffsetLen)) + io.dcache.ptag := Mux(dvm_enabled, dtlb.ppn, io.dcache.addr(PADDR_WID - 1, pageOffsetLen)) io.dcache.paddr := Cat(io.dcache.ptag, io.dcache.addr(pageOffsetLen - 1, 0)) } diff --git a/chisel/playground/src/defines/Bundles.scala b/chisel/playground/src/defines/Bundles.scala index aa33266..97b5792 100644 --- a/chisel/playground/src/defines/Bundles.scala +++ b/chisel/playground/src/defines/Bundles.scala @@ -147,6 +147,7 @@ class Cache_DCache extends Bundle { val rdata = Input(UInt(XLEN.W)) val access_fault = Input(Bool()) + val page_fault = Input(Bool()) val dcache_ready = Input(Bool()) val tlb = new Tlb_DCache() diff --git a/chisel/playground/src/pipeline/execute/fu/Csr.scala b/chisel/playground/src/pipeline/execute/fu/Csr.scala index aea621f..215f704 100644 --- a/chisel/playground/src/pipeline/execute/fu/Csr.scala +++ b/chisel/playground/src/pipeline/execute/fu/Csr.scala @@ -50,7 +50,8 @@ class CsrDecodeUnit extends Bundle { class CsrTlb extends Bundle { val satp = Output(UInt(XLEN.W)) val mstatus = Output(UInt(XLEN.W)) - val mode = Output(Priv()) + val imode = Output(Priv()) + val dmode = Output(Priv()) } class Csr(implicit val cpuConfig: CpuConfig) extends Module with HasCSRConst { @@ -245,11 +246,13 @@ class Csr(implicit val cpuConfig: CpuConfig) extends Module with HasCSRConst { val mip_has_interrupt = WireInit(mip.asTypeOf(new Interrupt())) mip_has_interrupt.e.s := mip.asTypeOf(new Interrupt).e.s | seip + val mstatusBundle = mstatus.asTypeOf(new Mstatus()) + val ideleg = (mideleg & mip_has_interrupt.asUInt) def priviledgedEnableDetect(x: Bool): Bool = Mux( x, - ((mode === ModeS) && mstatus.asTypeOf(new Mstatus()).ie.s) || (mode < ModeS), - ((mode === ModeM) && mstatus.asTypeOf(new Mstatus()).ie.m) || (mode < ModeM) + ((mode === ModeS) && mstatusBundle.ie.s) || (mode < ModeS), + ((mode === ModeM) && mstatusBundle.ie.m) || (mode < ModeM) ) val interrupt_enable = Wire(Vec(INT_WID, Bool())) @@ -414,7 +417,8 @@ class Csr(implicit val cpuConfig: CpuConfig) extends Module with HasCSRConst { ret_target := sepc(VADDR_WID - 1, 0) } - io.tlb.mode := mode + io.tlb.imode := mode + io.tlb.dmode := Mux(mstatusBundle.mprv, mstatusBundle.mpp, mode) io.tlb.satp := satp io.tlb.mstatus := mstatus io.decodeUnit.mode := mode diff --git a/chisel/playground/src/pipeline/memory/Lsu.scala b/chisel/playground/src/pipeline/memory/Lsu.scala index 6c9e89b..5082b1a 100644 --- a/chisel/playground/src/pipeline/memory/Lsu.scala +++ b/chisel/playground/src/pipeline/memory/Lsu.scala @@ -9,9 +9,10 @@ import chisel3.util.experimental.BoringUtils class Lsu_DataMemory extends Bundle { val in = Input(new Bundle { - val acc_err = Bool() - val ready = Bool() - val rdata = UInt(XLEN.W) + val access_fault = Bool() + val page_fault = Bool() + val ready = Bool() + val rdata = UInt(XLEN.W) }) val out = Output(new Bundle { val en = Bool() @@ -183,7 +184,9 @@ class Lsu(implicit val cpuConfig: CpuConfig) extends Module { lsExe.out.loadAddrMisaligned || lsExe.out.storeAddrMisaligned || lsExe.out.loadAccessFault || - lsExe.out.storeAccessFault + lsExe.out.storeAccessFault || + lsExe.out.loadPageFault || + lsExe.out.storePageFault ) { state := s_idle io.memoryUnit.out.ready := true.B @@ -201,6 +204,8 @@ class Lsu(implicit val cpuConfig: CpuConfig) extends Module { io.memoryUnit.out.ex.exception(storeAddrMisaligned) := lsExe.out.storeAddrMisaligned io.memoryUnit.out.ex.exception(loadAccessFault) := lsExe.out.loadAccessFault io.memoryUnit.out.ex.exception(storeAccessFault) := lsExe.out.storeAccessFault + io.memoryUnit.out.ex.exception(loadPageFault) := lsExe.out.loadPageFault + io.memoryUnit.out.ex.exception(storePageFault) := lsExe.out.storePageFault io.memoryUnit.out.ex.tval := io.dataMemory.out.addr io.memoryUnit.out.rdata := MuxCase( diff --git a/chisel/playground/src/pipeline/memory/lsu/LsExecute.scala b/chisel/playground/src/pipeline/memory/lsu/LsExecute.scala index 5018ec5..095b0f0 100644 --- a/chisel/playground/src/pipeline/memory/lsu/LsExecute.scala +++ b/chisel/playground/src/pipeline/memory/lsu/LsExecute.scala @@ -20,6 +20,8 @@ class LsExecute extends Module { val storeAddrMisaligned = Bool() val loadAccessFault = Bool() val storeAccessFault = Bool() + val loadPageFault = Bool() + val storePageFault = Bool() val rdata = UInt(XLEN.W) val ready = Bool() }) @@ -83,8 +85,9 @@ class LsExecute extends Module { val reqWdata = if (XLEN == 32) genWdata32(io.in.wdata, size) else genWdata(io.in.wdata, size) val reqWmask = if (XLEN == 32) genWmask32(addr, size) else genWmask(addr, size) - val rdata = io.dataMemory.in.rdata - val acc_err = io.dataMemory.in.acc_err + val rdata = io.dataMemory.in.rdata + val access_fault = io.dataMemory.in.access_fault + val page_fault = io.dataMemory.in.page_fault val rdataSel64 = LookupTree( addr(2, 0), @@ -141,7 +144,9 @@ class LsExecute extends Module { io.out.ready := io.dataMemory.in.ready && io.dataMemory.out.en io.out.rdata := Mux(partialLoad, rdataPartialLoad, rdataSel) io.out.loadAddrMisaligned := valid && !isStore && !is_amo && !addrAligned - io.out.loadAccessFault := valid && !isStore && !is_amo && (acc_err || has_acc_err) + io.out.loadAccessFault := valid && !isStore && !is_amo && (access_fault || has_acc_err) + io.out.loadPageFault := valid && !isStore && !is_amo && page_fault io.out.storeAddrMisaligned := valid && (isStore || is_amo) && !addrAligned - io.out.storeAccessFault := valid && (isStore || is_amo) && (acc_err || has_acc_err) + io.out.storeAccessFault := valid && (isStore || is_amo) && (access_fault || has_acc_err) + io.out.storePageFault := valid && (isStore || is_amo) && page_fault }