16d5ddbceSLemover/*************************************************************************************** 26d5ddbceSLemover* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3f320e0f0SYinan Xu* Copyright (c) 2020-2021 Peng Cheng Laboratory 46d5ddbceSLemover* 56d5ddbceSLemover* XiangShan is licensed under Mulan PSL v2. 66d5ddbceSLemover* You can use this software according to the terms and conditions of the Mulan PSL v2. 76d5ddbceSLemover* You may obtain a copy of Mulan PSL v2 at: 86d5ddbceSLemover* http://license.coscl.org.cn/MulanPSL2 96d5ddbceSLemover* 106d5ddbceSLemover* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 116d5ddbceSLemover* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 126d5ddbceSLemover* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 136d5ddbceSLemover* 146d5ddbceSLemover* See the Mulan PSL v2 for more details. 156d5ddbceSLemover***************************************************************************************/ 166d5ddbceSLemover 176d5ddbceSLemoverpackage xiangshan.cache.mmu 186d5ddbceSLemover 196d5ddbceSLemoverimport chipsalliance.rocketchip.config.Parameters 206d5ddbceSLemoverimport chisel3._ 216d5ddbceSLemoverimport chisel3.util._ 226d5ddbceSLemoverimport xiangshan._ 236d5ddbceSLemoverimport utils._ 246d5ddbceSLemoverimport xiangshan.backend.roq.RoqPtr 256d5ddbceSLemoverimport xiangshan.backend.fu.util.HasCSRConst 266d5ddbceSLemover 276d5ddbceSLemoverclass TLB(Width: Int, isDtlb: Boolean)(implicit p: Parameters) extends TlbModule with HasCSRConst{ 286d5ddbceSLemover val io = IO(new TlbIO(Width)) 296d5ddbceSLemover 306d5ddbceSLemover val req = io.requestor.map(_.req) 316d5ddbceSLemover val resp = io.requestor.map(_.resp) 326d5ddbceSLemover val ptw = io.ptw 336d5ddbceSLemover 346d5ddbceSLemover val sfence = io.sfence 356d5ddbceSLemover val csr = io.csr 366d5ddbceSLemover val satp = csr.satp 376d5ddbceSLemover val priv = csr.priv 386d5ddbceSLemover val ifecth = if (isDtlb) false.B else true.B 396d5ddbceSLemover val mode = if (isDtlb) priv.dmode else priv.imode 406d5ddbceSLemover // val vmEnable = satp.mode === 8.U // && (mode < ModeM) // FIXME: fix me when boot xv6/linux... 416d5ddbceSLemover val vmEnable = if(EnbaleTlbDebug) (satp.mode === 8.U) 426d5ddbceSLemover else (satp.mode === 8.U && (mode < ModeM)) 436d5ddbceSLemover 446d5ddbceSLemover val reqAddr = req.map(_.bits.vaddr.asTypeOf(vaBundle)) 456d5ddbceSLemover val cmd = req.map(_.bits.cmd) 466d5ddbceSLemover val valid = req.map(_.valid) 476d5ddbceSLemover 486d5ddbceSLemover def widthMapSeq[T <: Seq[Data]](f: Int => T) = (0 until Width).map(f) 496d5ddbceSLemover def widthMap[T <: Data](f: Int => T) = (0 until Width).map(f) 506d5ddbceSLemover 516d5ddbceSLemover // Normal page && Super page 526d5ddbceSLemover val nv = RegInit(VecInit(Seq.fill(TlbEntrySize)(false.B))) 536d5ddbceSLemover val nMeta = Module(new CAMTemplate(UInt(vpnLen.W), TlbEntrySize, Width + 1)).io 546d5ddbceSLemover val nData = Reg(Vec(TlbEntrySize, new TlbData(false))) 556d5ddbceSLemover val sv = RegInit(VecInit(Seq.fill(TlbSPEntrySize)(false.B))) 566d5ddbceSLemover val sMeta = Reg(Vec(TlbSPEntrySize, new TlbSPMeta)) 576d5ddbceSLemover val sData = Reg(Vec(TlbSPEntrySize, new TlbData(true))) 586d5ddbceSLemover val v = nv ++ sv 596d5ddbceSLemover val data = nData ++ sData 606d5ddbceSLemover val g = VecInit(data.map(_.perm.g)) 616d5ddbceSLemover val pf = VecInit(data.zip(v).map{ case(e, vi) => e.perm.pf & vi }) 626d5ddbceSLemover 636d5ddbceSLemover /** 646d5ddbceSLemover * PTW refill 656d5ddbceSLemover */ 666d5ddbceSLemover val refill = ptw.resp.fire() && !sfence.valid 676d5ddbceSLemover 686d5ddbceSLemover val normalReplacer = if (isDtlb) Some("random") else Some("plru") 696d5ddbceSLemover val superReplacer = if (isDtlb) Some("random") else Some("plru") 706d5ddbceSLemover val nReplace = ReplacementPolicy.fromString(normalReplacer, TlbEntrySize) 716d5ddbceSLemover val sReplace = ReplacementPolicy.fromString(superReplacer, TlbSPEntrySize) 726d5ddbceSLemover val nRefillIdx = replaceWrapper(nv, nReplace.way) 736d5ddbceSLemover val sRefillIdx = replaceWrapper(sv, sReplace.way) 746d5ddbceSLemover 756d5ddbceSLemover nMeta.w := DontCare 766d5ddbceSLemover nMeta.w.valid := false.B 776d5ddbceSLemover when (refill) { 786d5ddbceSLemover val resp = ptw.resp.bits 796d5ddbceSLemover when (resp.entry.level.getOrElse(0.U) === 2.U) { 806d5ddbceSLemover val refillIdx = nRefillIdx 816d5ddbceSLemover refillIdx.suggestName(s"NormalRefillIdx") 826d5ddbceSLemover 836d5ddbceSLemover nv(refillIdx) := true.B 846d5ddbceSLemover nMeta.w.bits.index := nRefillIdx 856d5ddbceSLemover nMeta.w.bits.data := resp.entry.tag 866d5ddbceSLemover nMeta.w.valid := true.B 876d5ddbceSLemover nData(refillIdx).apply( 886d5ddbceSLemover ppn = resp.entry.ppn, 896d5ddbceSLemover level = resp.entry.level.getOrElse(0.U), 906d5ddbceSLemover perm = VecInit(resp.entry.perm.getOrElse(0.U)).asUInt, 916d5ddbceSLemover pf = resp.pf 926d5ddbceSLemover ) 936d5ddbceSLemover nReplace.access(nRefillIdx) 946d5ddbceSLemover XSDebug(p"Refill normal: idx:${refillIdx} entry:${resp.entry} pf:${resp.pf}\n") 956d5ddbceSLemover }.otherwise { 966d5ddbceSLemover val refillIdx = sRefillIdx 976d5ddbceSLemover refillIdx.suggestName(s"SuperRefillIdx") 986d5ddbceSLemover 996d5ddbceSLemover val dup = Cat(sv.zip(sMeta).map{ case (v, m) => 1006d5ddbceSLemover v && m.hit(resp.entry.tag) 1016d5ddbceSLemover }).orR // NOTE: may have long latency, RegNext it 1026d5ddbceSLemover 1036d5ddbceSLemover when (!dup) { 1046d5ddbceSLemover sv(refillIdx) := true.B 1056d5ddbceSLemover sMeta(refillIdx).apply( 1066d5ddbceSLemover vpn = resp.entry.tag, 1076d5ddbceSLemover level = resp.entry.level.getOrElse(0.U) 1086d5ddbceSLemover ) 1096d5ddbceSLemover sData(refillIdx).apply( 1106d5ddbceSLemover ppn = resp.entry.ppn, 1116d5ddbceSLemover level = resp.entry.level.getOrElse(0.U), 1126d5ddbceSLemover perm = VecInit(resp.entry.perm.getOrElse(0.U)).asUInt, 1136d5ddbceSLemover pf = resp.pf 1146d5ddbceSLemover ) 1156d5ddbceSLemover sReplace.access(sRefillIdx) 1166d5ddbceSLemover XSDebug(p"Refill superpage: idx:${refillIdx} entry:${resp.entry} pf:${resp.pf}\n") 1176d5ddbceSLemover } 1186d5ddbceSLemover } 1196d5ddbceSLemover } 1206d5ddbceSLemover 1216d5ddbceSLemover /** 1226d5ddbceSLemover * L1 TLB read 1236d5ddbceSLemover */ 1246d5ddbceSLemover val sfenceVpn = sfence.bits.addr.asTypeOf(vaBundle).vpn 1256d5ddbceSLemover for (i <- 0 until Width) { 1266d5ddbceSLemover nMeta.r.req(i) := io.requestor(i).req.bits.vaddr.asTypeOf(vaBundle).vpn 1276d5ddbceSLemover } 1286d5ddbceSLemover nMeta.r.req(Width) := sfenceVpn 1296d5ddbceSLemover 1306d5ddbceSLemover val nRefillMask = Mux(refill, UIntToOH(nRefillIdx)(TlbEntrySize-1, 0), 0.U).asBools 1316d5ddbceSLemover val sRefillMask = Mux(refill, UIntToOH(sRefillIdx)(TlbSPEntrySize-1, 0), 0.U).asBools 1326d5ddbceSLemover def TLBNormalRead(i: Int) = { 1336d5ddbceSLemover val entryHitVec = ( 1346d5ddbceSLemover if (isDtlb) 1356d5ddbceSLemover VecInit(nMeta.r.resp(i).zip(nRefillMask).map{ case (e, m) => ~m && e } ++ 1366d5ddbceSLemover sMeta.zip(sRefillMask).map{ case (e,m) => ~m && e.hit(reqAddr(i).vpn) }) 1376d5ddbceSLemover else 1386d5ddbceSLemover VecInit(nMeta.r.resp(i) ++ sMeta.map(_.hit(reqAddr(i).vpn/*, satp.asid*/))) 1396d5ddbceSLemover ) 1406d5ddbceSLemover 1416d5ddbceSLemover val reqAddrReg = if (isDtlb) RegNext(reqAddr(i)) else reqAddr(i) 1426d5ddbceSLemover val cmdReg = if (isDtlb) RegNext(cmd(i)) else cmd(i) 1436d5ddbceSLemover val validReg = if (isDtlb) RegNext(valid(i)) else valid(i) 1446d5ddbceSLemover val entryHitVecReg = if (isDtlb) RegNext(entryHitVec) else entryHitVec 1456d5ddbceSLemover entryHitVecReg.suggestName(s"entryHitVecReg_${i}") 1466d5ddbceSLemover 147*149086eaSLemover /***************** next cycle when two cycle is need********************/ 148*149086eaSLemover 1496d5ddbceSLemover val hitVec = VecInit((v zip entryHitVecReg).map{ case (a,b) => a&b }) 1506d5ddbceSLemover val pfHitVec = VecInit((pf zip entryHitVecReg).map{ case (a,b) => a&b }) 1516d5ddbceSLemover val pfArray = ParallelOR(pfHitVec).asBool && validReg && vmEnable 1526d5ddbceSLemover val hit = ParallelOR(hitVec).asBool && validReg && vmEnable && ~pfArray 1536d5ddbceSLemover val miss = !hit && validReg && vmEnable && ~pfArray 1546d5ddbceSLemover val hitppn = ParallelMux(hitVec zip data.map(_.genPPN(reqAddrReg.vpn))) 1556d5ddbceSLemover val hitPerm = ParallelMux(hitVec zip data.map(_.perm)) 1566d5ddbceSLemover 1576d5ddbceSLemover hitVec.suggestName(s"hitVec_${i}") 1586d5ddbceSLemover pfHitVec.suggestName(s"pfHitVec_${i}") 1596d5ddbceSLemover hit.suggestName(s"hit_${i}") 1606d5ddbceSLemover miss.suggestName(s"miss_${i}") 1616d5ddbceSLemover hitppn.suggestName(s"hitppn_${i}") 1626d5ddbceSLemover hitPerm.suggestName(s"hitPerm_${i}") 1636d5ddbceSLemover 1646d5ddbceSLemover XSDebug(valid(i), p"(${i.U}) entryHit:${Hexadecimal(entryHitVec.asUInt)}\n") 1656d5ddbceSLemover XSDebug(validReg, p"(${i.U}) entryHitReg:${Hexadecimal(entryHitVecReg.asUInt)} hitVec:${Hexadecimal(hitVec.asUInt)} pfHitVec:${Hexadecimal(pfHitVec.asUInt)} pfArray:${Hexadecimal(pfArray.asUInt)} hit:${hit} miss:${miss} hitppn:${Hexadecimal(hitppn)} hitPerm:${hitPerm}\n") 1666d5ddbceSLemover 1676d5ddbceSLemover // resp // TODO: A/D has not being concerned 1686d5ddbceSLemover val paddr = Cat(hitppn, reqAddrReg.off) 1696d5ddbceSLemover val vaddr = SignExt(req(i).bits.vaddr, PAddrBits) 1706d5ddbceSLemover 1716d5ddbceSLemover req(i).ready := resp(i).ready 1726d5ddbceSLemover resp(i).valid := validReg 1736d5ddbceSLemover resp(i).bits.paddr := Mux(vmEnable, paddr, if (isDtlb) RegNext(vaddr) else vaddr) 1746d5ddbceSLemover resp(i).bits.miss := miss 1756d5ddbceSLemover resp(i).bits.ptwBack := io.ptw.resp.fire() 1766d5ddbceSLemover 1776d5ddbceSLemover val perm = hitPerm // NOTE: given the excp, the out module choose one to use? 1786d5ddbceSLemover val update = false.B && hit && (!hitPerm.a || !hitPerm.d && TlbCmd.isWrite(cmdReg)) // update A/D through exception 1796d5ddbceSLemover val modeCheck = !(mode === ModeU && !perm.u || mode === ModeS && perm.u && (!priv.sum || ifecth)) 1806d5ddbceSLemover val ldPf = (pfArray && TlbCmd.isRead(cmdReg) && true.B /*!isAMO*/) || hit && !(modeCheck && (perm.r || priv.mxr && perm.x)) && (TlbCmd.isRead(cmdReg) && true.B/*!isAMO*/) // TODO: handle isAMO 1816d5ddbceSLemover val stPf = (pfArray && TlbCmd.isWrite(cmdReg) || false.B /*isAMO*/ ) || hit && !(modeCheck && perm.w) && (TlbCmd.isWrite(cmdReg) || false.B/*TODO isAMO. */) 1826d5ddbceSLemover val instrPf = (pfArray && TlbCmd.isExec(cmdReg)) || hit && !(modeCheck && perm.x) && TlbCmd.isExec(cmdReg) 1836d5ddbceSLemover resp(i).bits.excp.pf.ld := ldPf || update 1846d5ddbceSLemover resp(i).bits.excp.pf.st := stPf || update 1856d5ddbceSLemover resp(i).bits.excp.pf.instr := instrPf || update 1866d5ddbceSLemover 1876d5ddbceSLemover // if vmenable, use pre-calcuated pma check result 1886d5ddbceSLemover resp(i).bits.mmio := Mux(TlbCmd.isExec(cmdReg), !perm.pi, !perm.pd) 1896d5ddbceSLemover resp(i).bits.excp.af.ld := Mux(TlbCmd.isAtom(cmdReg), !perm.pa, !perm.pr) && TlbCmd.isRead(cmdReg) 1906d5ddbceSLemover resp(i).bits.excp.af.st := Mux(TlbCmd.isAtom(cmdReg), !perm.pa, !perm.pw) && TlbCmd.isWrite(cmdReg) 1916d5ddbceSLemover resp(i).bits.excp.af.instr := Mux(TlbCmd.isAtom(cmdReg), false.B, !perm.pe) 1926d5ddbceSLemover 1936d5ddbceSLemover // if !vmenable, check pma 1946d5ddbceSLemover val (pmaMode, accessWidth) = AddressSpace.memmapAddrMatch(resp(i).bits.paddr) 1956d5ddbceSLemover when(!vmEnable){ 1966d5ddbceSLemover resp(i).bits.mmio := Mux(TlbCmd.isExec(cmdReg), !PMAMode.icache(pmaMode), !PMAMode.dcache(pmaMode)) 1976d5ddbceSLemover resp(i).bits.excp.af.ld := Mux(TlbCmd.isAtom(cmdReg), !PMAMode.atomic(pmaMode), !PMAMode.read(pmaMode)) && TlbCmd.isRead(cmdReg) 1986d5ddbceSLemover resp(i).bits.excp.af.st := Mux(TlbCmd.isAtom(cmdReg), !PMAMode.atomic(pmaMode), !PMAMode.write(pmaMode)) && TlbCmd.isWrite(cmdReg) 1996d5ddbceSLemover resp(i).bits.excp.af.instr := Mux(TlbCmd.isAtom(cmdReg), false.B, !PMAMode.execute(pmaMode)) 2006d5ddbceSLemover } 2016d5ddbceSLemover 2026d5ddbceSLemover // TODO: MMIO check 2036d5ddbceSLemover 2046d5ddbceSLemover (hit, miss, hitVec, validReg) 2056d5ddbceSLemover } 2066d5ddbceSLemover 2076d5ddbceSLemover val readResult = (0 until Width).map(TLBNormalRead(_)) 2086d5ddbceSLemover val hitVec = readResult.map(res => res._1) 2096d5ddbceSLemover val missVec = readResult.map(res => res._2) 2106d5ddbceSLemover val hitVecVec = readResult.map(res => res._3) 2116d5ddbceSLemover val validRegVec = readResult.map(res => res._4) 2126d5ddbceSLemover 213*149086eaSLemover // replacement 214*149086eaSLemover def get_access_index(one_hot: UInt): Valid[UInt] = { 215*149086eaSLemover val res = Wire(Valid(UInt(log2Up(one_hot.getWidth).W))) 216*149086eaSLemover res.valid := Cat(one_hot).orR 217*149086eaSLemover res.bits := OHToUInt(one_hot) 218*149086eaSLemover res 219*149086eaSLemover } 220*149086eaSLemover def get_access(one_hot: Seq[Bool], stop: Int, start: Int): Valid[UInt] = { 221*149086eaSLemover val tmp = VecInit(one_hot).asUInt 222*149086eaSLemover get_access_index(tmp(stop, start)) 223*149086eaSLemover } 224*149086eaSLemover val nAccess = hitVecVec.map(a => get_access(a, TlbEntrySize - 1, 0)) 225*149086eaSLemover val sAccess = hitVecVec.map(a => get_access(a, TlbEntrySize + TlbSPEntrySize - 1, TlbEntrySize)) 226*149086eaSLemover if (Width == 1) { 227*149086eaSLemover when (nAccess(0).valid) { nReplace.access(nAccess(0).bits) } 228*149086eaSLemover when (sAccess(0).valid) { sReplace.access(sAccess(0).bits) } 229*149086eaSLemover } else { 230*149086eaSLemover nReplace.access(nAccess) 231*149086eaSLemover sReplace.access(sAccess) 232*149086eaSLemover } 233*149086eaSLemover 2346d5ddbceSLemover for (i <- 0 until Width) { 2356d5ddbceSLemover io.ptw.req(i).valid := validRegVec(i) && missVec(i) && !RegNext(refill) 2366d5ddbceSLemover io.ptw.req(i).bits.vpn := RegNext(reqAddr(i).vpn) 2376d5ddbceSLemover } 2386d5ddbceSLemover io.ptw.resp.ready := true.B 2396d5ddbceSLemover 2406d5ddbceSLemover // val tooManyPf = PopCount(pf) > 5.U 2416d5ddbceSLemover // when (tooManyPf) { // when too much pf, just clear 2426d5ddbceSLemover // XSDebug(p"Too many pf just flush all the pf v:${Hexadecimal(VecInit(v).asUInt)} pf:${Hexadecimal(pf.asUInt)}\n") 2436d5ddbceSLemover // v.zipWithIndex.map{ case (a, i) => a := a & !pf(i) } 2446d5ddbceSLemover // } 2456d5ddbceSLemover 2466d5ddbceSLemover // sfence (flush) 2476d5ddbceSLemover val sfenceHit = nMeta.r.resp(Width) ++ sMeta.map(_.hit(sfenceVpn)) 2486d5ddbceSLemover when (sfence.valid) { 2496d5ddbceSLemover when (sfence.bits.rs1) { // virtual address *.rs1 <- (rs1===0.U) 2506d5ddbceSLemover when (sfence.bits.rs2) { // asid, but i do not want to support asid, *.rs2 <- (rs2===0.U) 2516d5ddbceSLemover // all addr and all asid 2526d5ddbceSLemover v.map(_ := false.B) 2536d5ddbceSLemover }.otherwise { 2546d5ddbceSLemover // all addr but specific asid 2556d5ddbceSLemover v.zipWithIndex.map{ case (a,i) => a := a & g(i) } 2566d5ddbceSLemover } 2576d5ddbceSLemover }.otherwise { 2586d5ddbceSLemover when (sfence.bits.rs2) { 2596d5ddbceSLemover // specific addr but all asid 2606d5ddbceSLemover v.zipWithIndex.map{ case (a,i) => a := a & !sfenceHit(i) } 2616d5ddbceSLemover }.otherwise { 2626d5ddbceSLemover // specific addr and specific asid 2636d5ddbceSLemover v.zipWithIndex.map{ case (a,i) => a := a & !sfenceHit(i) && !g(i) } 2646d5ddbceSLemover } 2656d5ddbceSLemover } 2666d5ddbceSLemover } 2676d5ddbceSLemover 2686d5ddbceSLemover if (isDtlb) { 2696d5ddbceSLemover for (i <- 0 until Width) { 2706d5ddbceSLemover XSPerfAccumulate("first_access" + Integer.toString(i, 10), validRegVec(i) && vmEnable && RegNext(req(i).bits.debug.isFirstIssue)) 2716d5ddbceSLemover XSPerfAccumulate("access" + Integer.toString(i, 10), validRegVec(i) && vmEnable) 2726d5ddbceSLemover } 2736d5ddbceSLemover for (i <- 0 until Width) { 2746d5ddbceSLemover XSPerfAccumulate("first_miss" + Integer.toString(i, 10), validRegVec(i) && vmEnable && missVec(i) && RegNext(req(i).bits.debug.isFirstIssue)) 2756d5ddbceSLemover XSPerfAccumulate("miss" + Integer.toString(i, 10), validRegVec(i) && vmEnable && missVec(i)) 2766d5ddbceSLemover } 2776d5ddbceSLemover } else { 2786d5ddbceSLemover // NOTE: ITLB is blocked, so every resp will be valid only when hit 2796d5ddbceSLemover // every req will be ready only when hit 2806d5ddbceSLemover XSPerfAccumulate("access", io.requestor(0).req.fire() && vmEnable) 2816d5ddbceSLemover XSPerfAccumulate("miss", ptw.req(0).fire()) 2826d5ddbceSLemover } 2836d5ddbceSLemover //val reqCycleCnt = Reg(UInt(16.W)) 2846d5ddbceSLemover //reqCycleCnt := reqCycleCnt + BoolStopWatch(ptw.req(0).fire(), ptw.resp.fire || sfence.valid) 2856d5ddbceSLemover //XSPerfAccumulate("ptw_req_count", ptw.req.fire()) 2866d5ddbceSLemover //XSPerfAccumulate("ptw_req_cycle", Mux(ptw.resp.fire(), reqCycleCnt, 0.U)) 2876d5ddbceSLemover XSPerfAccumulate("ptw_resp_count", ptw.resp.fire()) 2886d5ddbceSLemover XSPerfAccumulate("ptw_resp_pf_count", ptw.resp.fire() && ptw.resp.bits.pf) 2896d5ddbceSLemover for (i <- 0 until TlbEntrySize) { 2906d5ddbceSLemover val indexHitVec = hitVecVec.zip(validRegVec).map{ case (h, v) => h(i) && v } 2916d5ddbceSLemover XSPerfAccumulate(s"NormalAccessIndex${i}", Mux(vmEnable, PopCount(indexHitVec), 0.U)) 2926d5ddbceSLemover } 2936d5ddbceSLemover for (i <- 0 until TlbSPEntrySize) { 2946d5ddbceSLemover val indexHitVec = hitVecVec.zip(validRegVec).map{ case (h, v) => h(i + TlbEntrySize) && v } 2956d5ddbceSLemover XSPerfAccumulate(s"SuperAccessIndex${i}", Mux(vmEnable, PopCount(indexHitVec), 0.U)) 2966d5ddbceSLemover } 2976d5ddbceSLemover for (i <- 0 until TlbEntrySize) { 2986d5ddbceSLemover XSPerfAccumulate(s"NormalRefillIndex${i}", refill && ptw.resp.bits.entry.level.getOrElse(0.U) === 2.U && i.U === nRefillIdx) 2996d5ddbceSLemover } 3006d5ddbceSLemover for (i <- 0 until TlbSPEntrySize) { 3016d5ddbceSLemover XSPerfAccumulate(s"SuperRefillIndex${i}", refill && ptw.resp.bits.entry.level.getOrElse(0.U) =/= 2.U && i.U === sRefillIdx) 3026d5ddbceSLemover } 3036d5ddbceSLemover 3046d5ddbceSLemover // Log 3056d5ddbceSLemover for(i <- 0 until Width) { 3066d5ddbceSLemover XSDebug(req(i).valid, p"req(${i.U}): (${req(i).valid} ${req(i).ready}) ${req(i).bits}\n") 3076d5ddbceSLemover XSDebug(resp(i).valid, p"resp(${i.U}): (${resp(i).valid} ${resp(i).ready}) ${resp(i).bits}\n") 3086d5ddbceSLemover } 3096d5ddbceSLemover 3106d5ddbceSLemover XSDebug(sfence.valid, p"Sfence: ${sfence}\n") 3116d5ddbceSLemover XSDebug(ParallelOR(valid)|| ptw.resp.valid, p"CSR: ${csr}\n") 3126d5ddbceSLemover XSDebug(ParallelOR(valid) || ptw.resp.valid, p"vmEnable:${vmEnable} hit:${Binary(VecInit(hitVec).asUInt)} miss:${Binary(VecInit(missVec).asUInt)} v:${Hexadecimal(VecInit(v).asUInt)} pf:${Hexadecimal(pf.asUInt)}\n") 3136d5ddbceSLemover for (i <- ptw.req.indices) { 3146d5ddbceSLemover XSDebug(ptw.req(i).fire(), p"PTW req:${ptw.req(i).bits}\n") 3156d5ddbceSLemover } 3166d5ddbceSLemover XSDebug(ptw.resp.valid, p"PTW resp:${ptw.resp.bits} (v:${ptw.resp.valid}r:${ptw.resp.ready}) \n") 3176d5ddbceSLemover 3186d5ddbceSLemover// // NOTE: just for simple tlb debug, comment it after tlb's debug 3196d5ddbceSLemover // assert(!io.ptw.resp.valid || io.ptw.resp.bits.entry.tag === io.ptw.resp.bits.entry.ppn, "Simple tlb debug requires vpn === ppn") 3206d5ddbceSLemover} 3216d5ddbceSLemover 3226d5ddbceSLemoverobject TLB { 3236d5ddbceSLemover def apply 3246d5ddbceSLemover ( 3256d5ddbceSLemover in: Seq[BlockTlbRequestIO], 3266d5ddbceSLemover sfence: SfenceBundle, 3276d5ddbceSLemover csr: TlbCsrBundle, 3286d5ddbceSLemover width: Int, 3296d5ddbceSLemover isDtlb: Boolean, 3306d5ddbceSLemover shouldBlock: Boolean 3316d5ddbceSLemover )(implicit p: Parameters) = { 3326d5ddbceSLemover require(in.length == width) 3336d5ddbceSLemover 3346d5ddbceSLemover val tlb = Module(new TLB(width, isDtlb)) 3356d5ddbceSLemover 3366d5ddbceSLemover tlb.io.sfence <> sfence 3376d5ddbceSLemover tlb.io.csr <> csr 3386d5ddbceSLemover 3396d5ddbceSLemover if (!shouldBlock) { // dtlb 3406d5ddbceSLemover for (i <- 0 until width) { 3416d5ddbceSLemover tlb.io.requestor(i) <> in(i) 3426d5ddbceSLemover // tlb.io.requestor(i).req.valid := in(i).req.valid 3436d5ddbceSLemover // tlb.io.requestor(i).req.bits := in(i).req.bits 3446d5ddbceSLemover // in(i).req.ready := tlb.io.requestor(i).req.ready 3456d5ddbceSLemover 3466d5ddbceSLemover // in(i).resp.valid := tlb.io.requestor(i).resp.valid 3476d5ddbceSLemover // in(i).resp.bits := tlb.io.requestor(i).resp.bits 3486d5ddbceSLemover // tlb.io.requestor(i).resp.ready := in(i).resp.ready 3496d5ddbceSLemover } 3506d5ddbceSLemover } else { // itlb 3516d5ddbceSLemover require(width == 1) 3526d5ddbceSLemover tlb.io.requestor(0).req.valid := in(0).req.valid 3536d5ddbceSLemover tlb.io.requestor(0).req.bits := in(0).req.bits 3546d5ddbceSLemover in(0).req.ready := !tlb.io.requestor(0).resp.bits.miss && in(0).resp.ready && tlb.io.requestor(0).req.ready 3556d5ddbceSLemover 3566d5ddbceSLemover in(0).resp.valid := tlb.io.requestor(0).resp.valid && !tlb.io.requestor(0).resp.bits.miss 3576d5ddbceSLemover in(0).resp.bits := tlb.io.requestor(0).resp.bits 3586d5ddbceSLemover tlb.io.requestor(0).resp.ready := in(0).resp.ready 3596d5ddbceSLemover } 3606d5ddbceSLemover 3616d5ddbceSLemover tlb.io.ptw 3626d5ddbceSLemover } 3636d5ddbceSLemover} 364