From 2f3ff6e5dd3558e7a24e550a68c72e9fc136bba1 Mon Sep 17 00:00:00 2001 From: Liphen Date: Mon, 15 Jan 2024 13:36:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E9=99=A4vma=E6=8C=87?= =?UTF-8?q?=E4=BB=A4=E5=A4=96=E7=9A=84=E6=A1=86=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chisel/playground/src/Core.scala | 15 +- chisel/playground/src/cache/DCache.scala | 27 ++-- chisel/playground/src/cache/ICache.scala | 40 +++-- chisel/playground/src/cache/mmu/Tlb.scala | 147 +++++++++++++----- chisel/playground/src/defines/Bundles.scala | 9 +- .../src/pipeline/decode/DecodeUnit.scala | 6 +- .../src/pipeline/fetch/InstFifo.scala | 11 +- chisel/playground/test/src/TestMain.scala | 2 +- 8 files changed, 180 insertions(+), 77 deletions(-) diff --git a/chisel/playground/src/Core.scala b/chisel/playground/src/Core.scala index 992e760..cfa805b 100644 --- a/chisel/playground/src/Core.scala +++ b/chisel/playground/src/Core.scala @@ -66,12 +66,13 @@ class Core(implicit val cpuConfig: CpuConfig) extends Module { decodeUnit.instFifo.inst <> instFifo.read for (i <- 0 until cpuConfig.instFetchNum) { - instFifo.write(i).pht_index := bpu.instBuffer.pht_index(i) - bpu.instBuffer.pc(i) := instFifo.write(i).pc - instFifo.wen(i) := io.inst.inst_valid(i) - instFifo.write(i).pc := io.inst.addr(0) + (i * 4).U - instFifo.write(i).inst := io.inst.inst(i) - instFifo.write(i).acc_err := io.inst.acc_err + instFifo.write(i).pht_index := bpu.instBuffer.pht_index(i) + bpu.instBuffer.pc(i) := instFifo.write(i).pc + instFifo.wen(i) := io.inst.inst_valid(i) + instFifo.write(i).pc := io.inst.addr(0) + (i * 4).U + instFifo.write(i).inst := io.inst.inst(i) + instFifo.write(i).access_fault := io.inst.access_fault + instFifo.write(i).page_fault := io.inst.page_fault } decodeUnit.instFifo.info.empty := instFifo.empty @@ -108,7 +109,7 @@ 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.acc_err + 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 diff --git a/chisel/playground/src/cache/DCache.scala b/chisel/playground/src/cache/DCache.scala index 391e62c..21f6c1b 100644 --- a/chisel/playground/src/cache/DCache.scala +++ b/chisel/playground/src/cache/DCache.scala @@ -199,6 +199,7 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo io.cpu.tlb.addr := io.cpu.addr io.cpu.tlb.access_type := Mux(io.cpu.en && io.cpu.wen.orR, AccessType.store, AccessType.load) + io.cpu.tlb.en := io.cpu.en val bank_raddr = Mux(state === s_fence, dirty_index, Mux(use_next_addr, exe_index, replace_index)) val tag_raddr = Mux(state === s_fence, dirty_index, tag_rindex) @@ -259,12 +260,10 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo io.axi.b.ready := true.B - val acc_err = RegInit(false.B) - val addr_err = io.cpu.addr(XLEN - 1, VADDR_WID).orR - when(acc_err) { - acc_err := false.B - } - io.cpu.acc_err := acc_err + val access_fault = RegInit(false.B) + val addr_err = io.cpu.addr(XLEN - 1, VADDR_WID).orR + + io.cpu.access_fault := access_fault // write buffer when(writeFifo_axi_busy) { @@ -295,9 +294,10 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo switch(state) { is(s_idle) { + access_fault := false.B // 在idle时清除acc_err when(io.cpu.en) { when(addr_err) { - acc_err := true.B + access_fault := true.B }.elsewhen(!io.cpu.tlb.hit) { state := s_tlb_refill }.elsewhen(io.cpu.tlb.uncached) { @@ -363,10 +363,10 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo arvalid := false.B } when(io.axi.r.fire) { - rready := false.B - saved_rdata := io.axi.r.bits.data - acc_err := io.axi.r.bits.resp =/= RESP_OKEY.U - state := s_wait + rready := false.B + saved_rdata := io.axi.r.bits.data + access_fault := io.axi.r.bits.resp =/= RESP_OKEY.U + state := s_wait } } is(s_fence) { @@ -507,7 +507,7 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo val sum = mstatus.sum val mxr = mstatus.mxr val vpn = io.cpu.tlb.ptw.vpn.bits.asTypeOf(vpnBundle) - val access_type = io.cpu.tlb.access_type + val access_type = io.cpu.tlb.ptw.access_type val ppn = RegInit(0.U(ppnLen.W)) val vpn_index = RegInit(0.U(log2Up(level).W)) // 页表访问的层级 val pte = RegInit(0.U.asTypeOf(pteBundle)) // 页表项 @@ -516,6 +516,7 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo io.cpu.tlb.ptw.pte.bits := DontCare io.cpu.tlb.ptw.pte.bits.access_fault := false.B io.cpu.tlb.ptw.pte.bits.page_fault := false.B + io.cpu.tlb.complete_single_request := io.cpu.complete_single_request require(AXI_DATA_WID == XLEN) // 目前只考虑了AXI_DATA_WID == XLEN的情况 def raisePageFault(): Unit = { @@ -643,7 +644,7 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo io.cpu.tlb.ptw.pte.valid := true.B io.cpu.tlb.ptw.pte.bits.addr := ar.addr io.cpu.tlb.ptw.pte.bits.entry := pte - val ppn_set = WireInit(ppnBundle) + val ppn_set = Wire(ppnBundle) when(vpn_index === 2.U) { ppn_set.ppn2 := pte.ppn.asTypeOf(ppnBundle).ppn2 ppn_set.ppn1 := vpn.vpn1 diff --git a/chisel/playground/src/cache/ICache.scala b/chisel/playground/src/cache/ICache.scala index d1591a6..dfb4821 100644 --- a/chisel/playground/src/cache/ICache.scala +++ b/chisel/playground/src/cache/ICache.scala @@ -187,7 +187,10 @@ class ICache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo } io.cpu.icache_stall := Mux(state === s_idle, (!cache_hit_available && io.cpu.req), state =/= s_wait) - io.cpu.tlb.addr := io.cpu.addr(0) + + io.cpu.tlb.addr := io.cpu.addr(0) + io.cpu.tlb.complete_single_request := io.cpu.complete_single_request + io.cpu.tlb.en := io.cpu.req val ar = RegInit(0.U.asTypeOf(new AR())) val arvalid = RegInit(false.B) @@ -199,19 +202,22 @@ class ICache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo r <> io.axi.r.bits rready <> io.axi.r.ready - val acc_err = RegInit(false.B) - val addr_err = io.cpu.addr(use_next_addr)(XLEN - 1, VADDR_WID).orR + val access_fault = RegInit(false.B) + val page_fault = RegInit(false.B) + val addr_err = io.cpu.addr(use_next_addr)(XLEN - 1, VADDR_WID).orR - when(acc_err) { acc_err := false.B } - io.cpu.acc_err := acc_err //TODO:实现cached段中的访存错误 + io.cpu.access_fault := access_fault //TODO:实现cached段中的访存response错误 + io.cpu.page_fault := page_fault switch(state) { is(s_idle) { + access_fault := false.B // 在idle时清除acc_err + page_fault := false.B // 在idle时清除page_fault when(io.cpu.req) { when(addr_err) { - acc_err := true.B + access_fault := true.B state := s_wait - rdata_in_wait(0).inst := 0.U + rdata_in_wait(0).inst := Instructions.NOP rdata_in_wait(0).valid := true.B }.elsewhen(!io.cpu.tlb.hit) { state := s_tlb_refill @@ -252,11 +258,11 @@ class ICache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo } }.elsewhen(io.axi.r.fire) { // * uncached not support burst transport * // - state := s_wait rdata_in_wait(0).inst := Mux(ar.addr(2), io.axi.r.bits.data(63, 32), io.axi.r.bits.data(31, 0)) rdata_in_wait(0).valid := true.B rready := false.B - acc_err := io.axi.r.bits.resp =/= RESP_OKEY.U + access_fault := io.axi.r.bits.resp =/= RESP_OKEY.U + state := s_wait } } is(s_replace) { @@ -294,7 +300,21 @@ class ICache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo } } is(s_tlb_refill) { - // TODO: + when(io.cpu.tlb.access_fault) { + access_fault := true.B + state := s_wait + rdata_in_wait(0).inst := Instructions.NOP + rdata_in_wait(0).valid := true.B + }.elsewhen(io.cpu.tlb.page_fault) { + page_fault := true.B + state := s_wait + rdata_in_wait(0).inst := Instructions.NOP + rdata_in_wait(0).valid := true.B + }.otherwise { + when(io.cpu.tlb.hit) { + state := s_idle + } + } } } diff --git a/chisel/playground/src/cache/mmu/Tlb.scala b/chisel/playground/src/cache/mmu/Tlb.scala index cee1a7b..48059a2 100644 --- a/chisel/playground/src/cache/mmu/Tlb.scala +++ b/chisel/playground/src/cache/mmu/Tlb.scala @@ -27,6 +27,7 @@ class Tlb_Ptw extends Bundle with Sv39Const { } class Tlb_ICache extends Bundle with Sv39Const { + val en = Input(Bool()) val addr = Input(UInt(XLEN.W)) val complete_single_request = Input(Bool()) @@ -39,9 +40,11 @@ class Tlb_ICache extends Bundle with Sv39Const { } class Tlb_DCache extends Tlb_ICache { - val ptw = new Tlb_Ptw() val access_type = Input(AccessType()) - val csr = new CsrTlb() + + // ptw 相关参数 + val ptw = new Tlb_Ptw() + val csr = new CsrTlb() } class Tlb extends Module with HasTlbConst with HasCSRConst { @@ -49,10 +52,10 @@ class Tlb extends Module with HasTlbConst with HasCSRConst { val icache = new Tlb_ICache() val dcache = new Tlb_DCache() val csr = Flipped(new CsrTlb()) - val fence_vma = Input(new Bundle { - val src1 = UInt(XLEN.W) - val src2 = UInt(XLEN.W) - }) + // val fence_vma = Input(new Bundle { + // val src1 = UInt(XLEN.W) + // val src2 = UInt(XLEN.W) + // }) }) val satp = io.csr.satp.asTypeOf(satpBundle) @@ -103,6 +106,7 @@ class Tlb extends Module with HasTlbConst with HasCSRConst { val search_l1 :: search_l2 :: search_pte :: search_fault :: Nil = Enum(4) val immu_state = RegInit(search_l1) + val dmmu_state = RegInit(search_l1) // 使用随机的方法替换TLB条目 val replace_index = new Counter(cpuConfig.tlbEntries) @@ -144,41 +148,45 @@ class Tlb extends Module with HasTlbConst with HasCSRConst { io.dcache.ptw.pte.ready := true.B // 恒为true io.dcache.csr <> io.csr - // 指令虚实地址转换 + // --------------------------------------------------- + // ----------------- 指令虚实地址转换 ----------------- + // --------------------------------------------------- switch(immu_state) { is(search_l1) { - // TODO:在这里实现访问tlb的pma和pmp权限检查 - ipage_fault := false.B - iaccess_fault := false.B - when(!vm_enabled) { - io.icache.hit := true.B - }.elsewhen(itlbl1_hit) { - // 在这里进行取指需要的所有的权限检查 - // 0. X位检查,只有可执行的页面才能取指 - // 1. M模式,不可能到这里,因为vm_enabled为false - // 2. S模式,如果U位为1,需要检查SUM - // 3. U模式,必须保证U位为1 - io.icache.hit := false.B // 只有权限检查通过后可以置为true - when(!itlb.flag.x) { - ipage_fault := true.B - immu_state := search_fault - }.elsewhen(mode === ModeS) { - when(itlb.flag.u && sum === 0.U) { + when(io.icache.en) { + // 在icache实现访问tlb的pma和pmp权限检查 + ipage_fault := false.B + iaccess_fault := false.B + when(!vm_enabled) { + io.icache.hit := true.B + }.elsewhen(itlbl1_hit) { + // 在这里进行取指需要的所有的权限检查 + // 0. X位检查,只有可执行的页面才能取指 + // 1. M模式,不可能到这里,因为vm_enabled为false + // 2. S模式,如果U位为1,需要检查SUM + // 3. U模式,必须保证U位为1 + io.icache.hit := false.B // 只有权限检查通过后可以置为true + when(!itlb.flag.x) { ipage_fault := true.B immu_state := search_fault - }.otherwise { - io.icache.hit := true.B - } - }.elsewhen(mode === ModeU) { - when(!itlb.flag.u) { - ipage_fault := true.B - immu_state := search_fault - }.otherwise { - io.icache.hit := true.B + }.elsewhen(mode === ModeS) { + when(itlb.flag.u && sum === 0.U) { + ipage_fault := true.B + immu_state := search_fault + }.otherwise { + io.icache.hit := true.B + } + }.elsewhen(mode === ModeU) { + when(!itlb.flag.u) { + ipage_fault := true.B + immu_state := search_fault + }.otherwise { + io.icache.hit := true.B + } } + }.otherwise { + immu_state := search_l2 } - }.otherwise { - immu_state := search_l2 } } is(search_l2) { @@ -225,6 +233,75 @@ class Tlb extends Module with HasTlbConst with HasCSRConst { } } + // --------------------------------------------------- + // ----------------- 指令虚实地址转换 ----------------- + // --------------------------------------------------- + switch(dmmu_state) { + is(search_l1) { + when(io.dcache.en) { + // 在dcache实现访问tlb的pma和pmp权限检查 + dpage_fault := false.B + daccess_fault := false.B + when(!vm_enabled) { + io.dcache.hit := true.B + }.elsewhen(dtlbl1_hit) { + // 在这里进行取指需要的所有的权限检查 + // 0. X位检查,只有可执行的页面才能取指 + // 1. M模式,不可能到这里,因为vm_enabled为false + // 2. S模式,如果U位为1,需要检查SUM + // 3. U模式,必须保证U位为1 + io.dcache.hit := false.B // 只有权限检查通过后可以置为true + // TODO:增加权限检查 + + }.otherwise { + dmmu_state := search_l2 + } + } + } + is(search_l2) { + when(il2_hit_vec.asUInt.orR) { + 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) { + io.dcache.ptw.vpn.valid := true.B + dmmu_state := search_pte + } + } + } + is(search_pte) { + io.dcache.ptw.vpn.valid := true.B + when(io.dcache.ptw.pte.valid) { + when(io.dcache.ptw.pte.bits.access_fault) { + daccess_fault := true.B + dmmu_state := search_fault + }.elsewhen(io.dcache.ptw.pte.bits.page_fault) { + dpage_fault := true.B + dmmu_state := search_fault + }.otherwise { + // 在内存中找寻到了页表,将其写入TLB + val replace_entry = Wire(tlbBundle) + replace_entry.vpn := ivpn + replace_entry.asid := satp.asid + replace_entry.flag := io.dcache.ptw.pte.bits.entry.flag + replace_entry.ppn := io.dcache.ptw.pte.bits.entry.ppn + replace_entry.pteaddr := io.dcache.ptw.pte.bits.addr + tlbl2(replace_index.value) := replace_entry + dtlb := replace_entry + dmmu_state := search_l1 + } + } + } + is(search_fault) { + when(io.dcache.complete_single_request) { + dpage_fault := false.B + daccess_fault := false.B + dmmu_state := search_l1 + } + } + } + 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.paddr := Cat(io.icache.ptag, io.icache.addr(pageOffsetLen - 1, 0)) diff --git a/chisel/playground/src/defines/Bundles.scala b/chisel/playground/src/defines/Bundles.scala index aa41c12..6fb15a2 100644 --- a/chisel/playground/src/defines/Bundles.scala +++ b/chisel/playground/src/defines/Bundles.scala @@ -109,15 +109,16 @@ class WriteBackCtrl extends Bundle { class Cache_ICache(implicit val cpuConfig: CpuConfig) extends Bundle { // read inst request from cpu val req = Output(Bool()) - val complete_single_request = Output(Bool()) // !cpu_stall + val complete_single_request = Output(Bool()) val addr = Output(Vec(cpuConfig.instFetchNum, UInt(XLEN.W))) // virtual address and next virtual address val fence_i = Output(Bool()) - val dcache_stall = Output(Bool()) // dcache_stall + val dcache_stall = Output(Bool()) // read inst result val inst = Input(Vec(cpuConfig.instFetchNum, UInt(XLEN.W))) val inst_valid = Input(Vec(cpuConfig.instFetchNum, Bool())) - val acc_err = Input(Bool()) + val access_fault = Input(Bool()) + val page_fault = Input(Bool()) val icache_stall = Input(Bool()) // icache_stall // tlb @@ -137,7 +138,7 @@ class Cache_DCache extends Bundle { val wstrb = Output(UInt(AXI_STRB_WID.W)) val rdata = Input(UInt(XLEN.W)) - val acc_err = Input(Bool()) + val access_fault = Input(Bool()) val dcache_ready = Input(Bool()) val tlb = new Tlb_DCache() diff --git a/chisel/playground/src/pipeline/decode/DecodeUnit.scala b/chisel/playground/src/pipeline/decode/DecodeUnit.scala index 476dfa0..b79822b 100644 --- a/chisel/playground/src/pipeline/decode/DecodeUnit.scala +++ b/chisel/playground/src/pipeline/decode/DecodeUnit.scala @@ -122,7 +122,8 @@ class DecodeUnit(implicit val cpuConfig: CpuConfig) extends Module with HasExcep (0 until (INT_WID)).foreach(i => io.executeStage.inst0.ex.interrupt(i) := io.csr.interrupt(i)) io.executeStage.inst0.ex.exception.map(_ := false.B) io.executeStage.inst0.ex.exception(illegalInstr) := !info(0).inst_legal - io.executeStage.inst0.ex.exception(instrAccessFault) := io.instFifo.inst(0).acc_err + io.executeStage.inst0.ex.exception(instrAccessFault) := io.instFifo.inst(0).access_fault + io.executeStage.inst0.ex.exception(instrPageFault) := io.instFifo.inst(0).page_fault io.executeStage.inst0.ex.exception(instrAddrMisaligned) := pc(0)(log2Ceil(INST_WID / 8) - 1, 0).orR || io.fetchUnit.target(log2Ceil(INST_WID / 8) - 1, 0).orR && io.fetchUnit.branch io.executeStage.inst0.ex.exception(breakPoint) := info(0).inst(31, 20) === privEbreak && @@ -165,7 +166,8 @@ class DecodeUnit(implicit val cpuConfig: CpuConfig) extends Module with HasExcep (0 until (INT_WID)).foreach(i => io.executeStage.inst1.ex.interrupt(i) := io.csr.interrupt(i)) io.executeStage.inst1.ex.exception.map(_ := false.B) io.executeStage.inst1.ex.exception(illegalInstr) := !info(1).inst_legal - io.executeStage.inst1.ex.exception(instrAccessFault) := io.instFifo.inst(1).acc_err + io.executeStage.inst1.ex.exception(instrAccessFault) := io.instFifo.inst(1).access_fault + io.executeStage.inst1.ex.exception(instrPageFault) := io.instFifo.inst(1).page_fault io.executeStage.inst1.ex.exception(instrAddrMisaligned) := pc(1)(log2Ceil(INST_WID / 8) - 1, 0).orR || io.fetchUnit.target(log2Ceil(INST_WID / 8) - 1, 0).orR && io.fetchUnit.branch io.executeStage.inst1.ex.exception(breakPoint) := info(1).inst(31, 20) === privEbreak && diff --git a/chisel/playground/src/pipeline/fetch/InstFifo.scala b/chisel/playground/src/pipeline/fetch/InstFifo.scala index e8ffaf7..d69044d 100644 --- a/chisel/playground/src/pipeline/fetch/InstFifo.scala +++ b/chisel/playground/src/pipeline/fetch/InstFifo.scala @@ -6,11 +6,12 @@ import cpu.defines.Const._ import cpu.{BranchPredictorConfig, CpuConfig} class BufferUnit extends Bundle { - val bpuConfig = new BranchPredictorConfig() - val inst = UInt(XLEN.W) - val pht_index = UInt(bpuConfig.phtDepth.W) - val acc_err = Bool() - val pc = UInt(XLEN.W) + val bpuConfig = new BranchPredictorConfig() + val inst = UInt(XLEN.W) + val pht_index = UInt(bpuConfig.phtDepth.W) + val access_fault = Bool() + val page_fault = Bool() + val pc = UInt(XLEN.W) } class InstFifo(implicit val cpuConfig: CpuConfig) extends Module { diff --git a/chisel/playground/test/src/TestMain.scala b/chisel/playground/test/src/TestMain.scala index 88b43bf..7d2be15 100644 --- a/chisel/playground/test/src/TestMain.scala +++ b/chisel/playground/test/src/TestMain.scala @@ -8,7 +8,7 @@ import icache.mmu.Tlb object TestMain extends App { implicit val cpuConfig = new CpuConfig() implicit val dCacheConfig = CacheConfig(cacheType = "dcache") - def top = new Tlb + def top = new DCache(dCacheConfig) val useMFC = false // use MLIR-based firrtl compiler val generator = Seq(chisel3.stage.ChiselGeneratorAnnotation(() => top)) if (useMFC) {