diff --git a/chisel/playground/src/CpuConfig.scala b/chisel/playground/src/CpuConfig.scala index 103a0d2..d9803d8 100644 --- a/chisel/playground/src/CpuConfig.scala +++ b/chisel/playground/src/CpuConfig.scala @@ -2,7 +2,7 @@ package cpu import chisel3.util._ import cpu.defines.Const._ -import cpu.defines.Sv39Const +import cpu.defines.HasTlbConst case class CpuConfig( val build: Boolean = false, // 是否为build模式 @@ -32,7 +32,7 @@ case class BranchPredictorConfig( case class CacheConfig( cacheType: String = "icache" // icache, dcache -) extends Sv39Const { +) extends HasTlbConst { // ========================================================== // | tag | index | offset | // | | | bank index | bank offset | diff --git a/chisel/playground/src/cache/CacheAXIInterface.scala b/chisel/playground/src/cache/CacheAXIInterface.scala index 1c6e444..143613f 100644 --- a/chisel/playground/src/cache/CacheAXIInterface.scala +++ b/chisel/playground/src/cache/CacheAXIInterface.scala @@ -42,30 +42,30 @@ class CacheAXIInterface extends Module { // mux ar { // we need to lock ar to avoid signals change during handshake - val ar_sel_lock = RegInit(false.B) - val ar_sel_val = RegInit(false.B) - val ar_sel = Mux(ar_sel_lock, ar_sel_val, !io.icache.ar.valid && io.dcache.ar.valid) + val ar_sel_lock = RegInit(false.B) + val ar_sel_val = RegInit(false.B) + val choose_dcache = Mux(ar_sel_lock, ar_sel_val, !io.icache.ar.valid && io.dcache.ar.valid) when(io.axi.ar.valid) { when(io.axi.ar.ready) { ar_sel_lock := false.B }.otherwise { ar_sel_lock := true.B - ar_sel_val := ar_sel + ar_sel_val := choose_dcache } } - io.axi.ar.bits.id := Cat(0.U(3.W), ar_sel) - io.axi.ar.bits.addr := Mux(ar_sel, io.dcache.ar.bits.addr, io.icache.ar.bits.addr) - io.axi.ar.bits.len := Mux(ar_sel, io.dcache.ar.bits.len, io.icache.ar.bits.len) - io.axi.ar.bits.size := Mux(ar_sel, io.dcache.ar.bits.size, io.icache.ar.bits.size) - io.axi.ar.valid := Mux(ar_sel, io.dcache.ar.valid, io.icache.ar.valid) + io.axi.ar.bits.id := Cat(0.U(3.W), choose_dcache) + io.axi.ar.bits.addr := Mux(choose_dcache, io.dcache.ar.bits.addr, io.icache.ar.bits.addr) + io.axi.ar.bits.len := Mux(choose_dcache, io.dcache.ar.bits.len, io.icache.ar.bits.len) + io.axi.ar.bits.size := Mux(choose_dcache, io.dcache.ar.bits.size, io.icache.ar.bits.size) + io.axi.ar.valid := Mux(choose_dcache, io.dcache.ar.valid, io.icache.ar.valid) io.axi.ar.bits.burst := 1.U io.axi.ar.bits.prot := 0.U io.axi.ar.bits.cache := 0.U io.axi.ar.bits.lock := 0.U - io.icache.ar.ready := !ar_sel && io.axi.ar.ready - io.dcache.ar.ready := ar_sel && io.axi.ar.ready + io.icache.ar.ready := !choose_dcache && io.axi.ar.ready + io.dcache.ar.ready := choose_dcache && io.axi.ar.ready // mux ar } // mux r based on rid { diff --git a/chisel/playground/src/cache/DCache.scala b/chisel/playground/src/cache/DCache.scala index 72d4858..afeaa14 100644 --- a/chisel/playground/src/cache/DCache.scala +++ b/chisel/playground/src/cache/DCache.scala @@ -51,7 +51,7 @@ class WriteBufferUnit extends Bundle { val size = UInt(AXI_SIZE_WID.W) } -class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Module with Sv39Const with HasCSRConst { +class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Module with HasTlbConst with HasCSRConst { val nway = cacheConfig.nway val nindex = cacheConfig.nindex val nbank = cacheConfig.nbank @@ -69,6 +69,17 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo // TODO:目前的实现只保证了AXI_DATA_WID为XLEN的情况下的正确性 require(AXI_DATA_WID == XLEN, "AXI_DATA_WID should be greater than XLEN") + def pAddr = new Bundle { + val tag = UInt(ppnLen.W) + val index = UInt(indexWidth.W) + val offset = UInt(offsetWidth.W) + } + + def bankAddr = new Bundle { + val index = UInt(bankIndexWidth.W) + val offset = UInt(bankOffsetWidth.W) + } + val io = IO(new Bundle { val cpu = Flipped(new Cache_DCache()) val axi = new DCache_AXIInterface() @@ -85,7 +96,7 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo // 临时寄存器 val ptw_working = ptw_state =/= ptw_handshake && ptw_state =/= ptw_set val ptw_scratch = RegInit(0.U.asTypeOf(new Bundle { - val paddr = cacheAddr + val paddr = pAddr val replace = Bool() val dcache_wait = Bool() })) @@ -99,17 +110,6 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo // | | | bank index | bank offset | // ========================================================== - def cacheAddr = new Bundle { - val tag = UInt(tagWidth.W) - val index = UInt(indexWidth.W) - val offset = UInt(offsetWidth.W) - } - - def bankAddr = new Bundle { - val index = UInt(bankIndexWidth.W) - val offset = UInt(bankOffsetWidth.W) - } - // exe级的index,用于访问第i行的数据 val exe_index = io.cpu.exe_addr(indexWidth + offsetWidth - 1, offsetWidth) // mem级的bank的index,用于访问第i个bank的数据 @@ -219,7 +219,7 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo io.cpu.rdata := Mux(state === s_wait, saved_rdata, data(bank_index)(select_way)) - io.cpu.tlb.addr := io.cpu.addr + io.cpu.tlb.vaddr := 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 @@ -357,7 +357,7 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo burst.wstrb(replace_way) := 1.U // 先写入第一块bank when(replace_dirty) { // cache行的脏位为真时需要写回,备份一下cache行,便于处理读写时序问题 - (0 until nbank).map(i => bank_replication(i) := data(i)(select_way)) + (0 until nbank).map(i => bank_replication(i) := data(i)(replace_way)) } }.otherwise { when(io.cpu.dcache_ready) { @@ -624,7 +624,7 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo (vpn_index === 2.U) -> vpn.vpn2 ) ) - val ptw_addr = paddrApply(ppn, vpnn).asTypeOf(cacheAddr) + val ptw_addr = paddrApply(ppn, vpnn).asTypeOf(pAddr) val uncached = AddressSpace.isMMIO(ptw_addr.asUInt) when(uncached) { arvalid := true.B @@ -679,12 +679,12 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo burst.wstrb(replace_way) := 1.U // 先写入第一块bank when(replace_dirty) { // cache行的脏位为真时需要写回,备份一下cache行,便于处理读写时序问题 - (0 until nbank).map(i => bank_replication(i) := data(i)(select_way)) + (0 until nbank).map(i => bank_replication(i) := data(i)(replace_way)) } } } } - is(ptw_uncached) { + is(ptw_uncached) { // 3 when(io.axi.ar.fire) { arvalid := false.B } @@ -711,7 +711,7 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo } } } - is(ptw_check) { + is(ptw_check) { // 4 // 检查权限 switch(access_type) { is(AccessType.load) { @@ -745,30 +745,33 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo } } } - is(ptw_set) { + is(ptw_set) { // 5 when( vpn_index > 0.U && ( - vpn_index === 1.U && pte.ppn(0) || - vpn_index === 2.U && pte.ppn(1, 0).orR + vpn_index === 1.U && pte.ppn.asTypeOf(ppnBundle).ppn0.orR || + vpn_index === 2.U && (pte.ppn.asTypeOf(ppnBundle).ppn1.orR || pte.ppn.asTypeOf(ppnBundle).ppn0.orR) ) ) { raisePageFault() }.elsewhen(!pte.flag.a || access_type === AccessType.store && !pte.flag.d) { raisePageFault() // 使用软件的方式设置脏位以及访问位 - }.otherwise { + }.otherwise { // 翻译成功 + val rmask = WireInit(~0.U(maskLen.W)) io.cpu.tlb.ptw.pte.valid := true.B - io.cpu.tlb.ptw.pte.bits.addr := ar.addr + io.cpu.tlb.ptw.pte.bits.rmask := rmask io.cpu.tlb.ptw.pte.bits.entry := pte val ppn_set = Wire(ppnBundle) when(vpn_index === 2.U) { ppn_set.ppn2 := pte.ppn.asTypeOf(ppnBundle).ppn2 ppn_set.ppn1 := vpn.vpn1 ppn_set.ppn0 := vpn.vpn0 + rmask := 0.U }.elsewhen(vpn_index === 1.U) { ppn_set.ppn2 := pte.ppn.asTypeOf(ppnBundle).ppn2 ppn_set.ppn1 := pte.ppn.asTypeOf(ppnBundle).ppn1 ppn_set.ppn0 := vpn.vpn0 + rmask := Cat(Fill(ppn1Len, true.B), 0.U(ppn0Len.W)) }.otherwise { ppn_set := pte.ppn.asTypeOf(ppnBundle) } diff --git a/chisel/playground/src/cache/ICache.scala b/chisel/playground/src/cache/ICache.scala index c96fafe..1f7b694 100644 --- a/chisel/playground/src/cache/ICache.scala +++ b/chisel/playground/src/cache/ICache.scala @@ -45,7 +45,7 @@ import cpu.defines.Const._ ===================================== */ -class ICache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Module { +class ICache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Module with HasTlbConst { val nway = cacheConfig.nway val nindex = cacheConfig.nindex val nbank = cacheConfig.nbank @@ -57,6 +57,18 @@ class ICache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo val indexWidth = cacheConfig.indexWidth val offsetWidth = cacheConfig.offsetWidth val bitsPerBank = cacheConfig.bitsPerBank + + def pAddr = new Bundle { + val tag = UInt(ppnLen.W) + val index = UInt(indexWidth.W) + val offset = UInt(offsetWidth.W) + } + + def bankAddr = new Bundle { + val index = UInt(bankIndexWidth.W) + val offset = UInt(bankOffsetWidth.W) + } + val io = IO(new Bundle { val cpu = Flipped(new Cache_ICache()) val axi = new ICache_AXIInterface() @@ -188,7 +200,7 @@ 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.vaddr := io.cpu.addr(0) io.cpu.tlb.complete_single_request := io.cpu.complete_single_request io.cpu.tlb.en := io.cpu.req && (state === s_idle || state === s_tlb_refill) diff --git a/chisel/playground/src/cache/mmu/Tlb.scala b/chisel/playground/src/cache/mmu/Tlb.scala index c843db3..308368f 100644 --- a/chisel/playground/src/cache/mmu/Tlb.scala +++ b/chisel/playground/src/cache/mmu/Tlb.scala @@ -15,20 +15,20 @@ object AccessType { def store = "b10".U } -class Tlb_Ptw extends Bundle with Sv39Const { +class Tlb_Ptw extends Bundle with HasTlbConst { val vpn = Decoupled(UInt(vpnLen.W)) val access_type = Output(AccessType()) val pte = Flipped(Decoupled(new Bundle { val access_fault = Bool() val page_fault = Bool() val entry = pteBundle - val addr = UInt(PADDR_WID.W) + val rmask = UInt(maskLen.W) })) } -class Tlb_ICache extends Bundle with Sv39Const { +class Tlb_ICache extends Bundle with HasTlbConst { val en = Input(Bool()) - val addr = Input(UInt(XLEN.W)) + val vaddr = Input(UInt(XLEN.W)) val complete_single_request = Input(Bool()) val uncached = Output(Bool()) @@ -76,27 +76,27 @@ class Tlb extends Module with HasTlbConst with HasCSRConst { val dtlb = RegInit(0.U.asTypeOf(tlbBundle)) val tlbl2 = RegInit(VecInit(Seq.fill(cpuConfig.tlbEntries)(0.U.asTypeOf(tlbBundle)))) - val ivpn = io.icache.addr(VADDR_WID - 1, pageOffsetLen) - val dvpn = io.dcache.addr(VADDR_WID - 1, pageOffsetLen) + val ivpn = io.icache.vaddr(VADDR_WID - 1, pageOffsetLen) + val dvpn = io.dcache.vaddr(VADDR_WID - 1, pageOffsetLen) // 当(VPN一致)且(ASID一致或PTE.G为1时)且(PTE.V为1)时,TLB命中 - val itlbl1_hit = itlb.vpn === ivpn && + val itlbl1_hit = vpnEq(itlb.rmask, ivpn, itlb.vpn) && (itlb.asid === satp.asid || itlb.flag.g) && itlb.flag.v - val dtlbl1_hit = dtlb.vpn === dvpn && + val dtlbl1_hit = vpnEq(dtlb.rmask, dvpn, dtlb.vpn) && (dtlb.asid === satp.asid || dtlb.flag.g) && dtlb.flag.v val il2_hit_vec = VecInit( tlbl2.map(tlb => - tlb.vpn === ivpn && + vpnEq(tlb.rmask, ivpn, tlb.vpn) && (tlb.asid === satp.asid || tlb.flag.g) && tlb.flag.v ) ) val dl2_hit_vec = VecInit( tlbl2.map(tlb => - tlb.vpn === dvpn && + vpnEq(tlb.rmask, dvpn, tlb.vpn) && (tlb.asid === satp.asid || tlb.flag.g) && tlb.flag.v ) @@ -243,7 +243,7 @@ class Tlb extends Module with HasTlbConst with HasCSRConst { 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 + replace_entry.rmask := io.dcache.ptw.pte.bits.rmask tlbl2(replace_index.value) := replace_entry itlb := replace_entry replace_index.inc() @@ -343,7 +343,7 @@ class Tlb extends Module with HasTlbConst with HasCSRConst { 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 + replace_entry.rmask := io.dcache.ptw.pte.bits.rmask tlbl2(replace_index.value) := replace_entry dtlb := replace_entry replace_index.inc() @@ -360,8 +360,8 @@ class Tlb extends Module with HasTlbConst with HasCSRConst { } } - val src1 = io.sfence_vma.src_info.src1_data - val src2 = io.sfence_vma.src_info.src2_data + val src1 = io.sfence_vma.src_info.src1_data(vpnLen - 1, 0) + val src2 = io.sfence_vma.src_info.src2_data(asidLen - 1, 0) when(io.sfence_vma.valid) { when(!src1.orR && !src2.orR) { // 将所有tlb的有效位置为0 @@ -385,39 +385,42 @@ class Tlb extends Module with HasTlbConst with HasCSRConst { } }.elsewhen(src1.orR && !src2.orR) { // 将vpn一致的tlb的有效位置为0 - when(itlb.vpn === src1) { + when(vpnEq(itlb.rmask, src1, itlb.vpn)) { itlb.flag.v := false.B } - when(dtlb.vpn === src1) { + when(vpnEq(dtlb.rmask, src1, dtlb.vpn)) { dtlb.flag.v := false.B } for (i <- 0 until cpuConfig.tlbEntries) { - when(tlbl2(i).vpn === src1) { + when(vpnEq(tlbl2(i).rmask, src1, tlbl2(i).vpn)) { tlbl2(i).flag.v := false.B } } }.elsewhen(src1.orR && src2.orR) { // 将asid一致的且vpn一致的tlb的有效位置为0,g为1的除外 - when(itlb.asid === src2 && itlb.vpn === src1 && !itlb.flag.g) { + when(itlb.asid === src2 && vpnEq(itlb.rmask, src1, itlb.vpn) && !itlb.flag.g) { itlb.flag.v := false.B } - when(dtlb.asid === src2 && dtlb.vpn === src1 && !dtlb.flag.g) { + when(dtlb.asid === src2 && vpnEq(dtlb.rmask, src1, dtlb.vpn) && !dtlb.flag.g) { dtlb.flag.v := false.B } for (i <- 0 until cpuConfig.tlbEntries) { - when(tlbl2(i).asid === src2 && tlbl2(i).vpn === src1 && !tlbl2(i).flag.g) { + when(tlbl2(i).asid === src2 && vpnEq(tlbl2(i).rmask, src1, tlbl2(i).vpn) && !tlbl2(i).flag.g) { tlbl2(i).flag.v := false.B } } } } - io.icache.uncached := AddressSpace.isMMIO(io.icache.addr) - 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)) + val imasktag = maskTag(itlb.rmask, itlb.ppn, ivpn) + val dmasktag = maskTag(dtlb.rmask, dtlb.ppn, dvpn) - io.dcache.uncached := AddressSpace.isMMIO(io.dcache.addr) - 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)) + io.icache.uncached := AddressSpace.isMMIO(io.icache.vaddr) + io.icache.ptag := Mux(ivm_enabled, imasktag, ivpn) + io.icache.paddr := Cat(io.icache.ptag, io.icache.vaddr(pageOffsetLen - 1, 0)) + + io.dcache.uncached := AddressSpace.isMMIO(io.dcache.vaddr) + io.dcache.ptag := Mux(dvm_enabled, dmasktag, dvpn) + io.dcache.paddr := Cat(io.dcache.ptag, io.dcache.vaddr(pageOffsetLen - 1, 0)) } diff --git a/chisel/playground/src/defines/TlbBundles.scala b/chisel/playground/src/defines/TlbBundles.scala index 1380729..396ab5f 100644 --- a/chisel/playground/src/defines/TlbBundles.scala +++ b/chisel/playground/src/defines/TlbBundles.scala @@ -6,7 +6,7 @@ import cpu.defines.Const._ import cpu.CacheConfig import cpu.CpuConfig -trait Sv39Const extends CoreParameter { +trait HasTlbConst extends CoreParameter { val PAddrBits = PADDR_WID // 32 val level = 3 val pageOffsetLen = 12 // 页面大小为4KB,对应的偏移量长度为12位 @@ -18,6 +18,7 @@ trait Sv39Const extends CoreParameter { val vpn1Len = 9 val vpn0Len = 9 val vpnLen = vpn2Len + vpn1Len + vpn0Len // 27 + val maskLen = ppn1Len + ppn0Len // 18 val satpLen = XLEN val satpModeLen = 4 @@ -31,21 +32,14 @@ trait Sv39Const extends CoreParameter { val cacheTagLen = PADDR_WID - pageOffsetLen // 32 - 12 = 20 require(ppnLen == cacheTagLen) - def vaBundle = new Bundle { - val vpn2 = UInt(vpn2Len.W) - val vpn1 = UInt(vpn1Len.W) - val vpn0 = UInt(vpn0Len.W) - val offset = UInt(pageOffsetLen.W) + def vpnEq(mask: UInt, vpn: UInt, tlbvpn: UInt) = { + val fullmask = Cat(Fill(vpn2Len, true.B), mask) + (vpn & fullmask) === (tlbvpn & fullmask) } - def vaBundle2 = new Bundle { - val vpn = UInt(vpnLen.W) - val offset = UInt(pageOffsetLen.W) - } - - def vaBundle3 = new Bundle { - val vpn = UInt(vpnLen.W) - val offset = UInt(pageOffsetLen.W) + def maskTag(mask: UInt, ppn: UInt, vpn: UInt) = { + val fullmask = Cat(Fill(ppn2Len, true.B), mask) + (ppn & fullmask) | (vpn & ~fullmask) } def vpnBundle = new Bundle { @@ -54,18 +48,6 @@ trait Sv39Const extends CoreParameter { val vpn0 = UInt(vpn0Len.W) } - def paBundle = new Bundle { - val ppn2 = UInt(ppn2Len.W) - val ppn1 = UInt(ppn1Len.W) - val ppn0 = UInt(ppn0Len.W) - val offset = UInt(pageOffsetLen.W) - } - - def paBundle2 = new Bundle { - val ppn = UInt(ppnLen.W) - val offset = UInt(pageOffsetLen.W) - } - def ppnBundle = new Bundle { val ppn2 = UInt(ppn2Len.W) val ppn1 = UInt(ppn1Len.W) @@ -110,23 +92,11 @@ trait Sv39Const extends CoreParameter { val v = Bool() } - def maskPaddr(ppn: UInt, vaddr: UInt, mask: UInt) = { - MaskData(vaddr, Cat(ppn, 0.U(pageOffsetLen.W)), Cat(Fill(ppn2Len, 1.U(1.W)), mask, 0.U(pageOffsetLen.W))) - } - - def MaskEQ(mask: UInt, pattern: UInt, vpn: UInt) = { - (Cat("h1ff".U(vpn2Len.W), mask) & pattern) === (Cat("h1ff".U(vpn2Len.W), mask) & vpn) - } - -} - -trait HasTlbConst extends Sv39Const { def tlbBundle = new Bundle { - val vpn = UInt(vpnLen.W) - val asid = UInt(asidLen.W) - val flag = flagBundle - val ppn = UInt(ppnLen.W) - val pteaddr = UInt(PAddrBits.W) + val vpn = UInt(vpnLen.W) + val asid = UInt(asidLen.W) + val flag = flagBundle + val ppn = UInt(ppnLen.W) + val rmask = UInt(maskLen.W) } - }