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._ 21a0301c0dSLemoverimport chisel3.internal.naming.chiselName 226d5ddbceSLemoverimport chisel3.util._ 23a0301c0dSLemoverimport freechips.rocketchip.util.SRAMAnnotation 246d5ddbceSLemoverimport xiangshan._ 256d5ddbceSLemoverimport utils._ 26b6982e83SLemoverimport xiangshan.backend.fu.{PMPChecker, PMPReqBundle} 279aca92b9SYinan Xuimport xiangshan.backend.rob.RobPtr 286d5ddbceSLemoverimport xiangshan.backend.fu.util.HasCSRConst 296d5ddbceSLemover 30a0301c0dSLemover 31a0301c0dSLemover@chiselName 321ca0e4f3SYinan Xuclass TLB(Width: Int, q: TLBParameters)(implicit p: Parameters) extends TlbModule with HasCSRConst with HasPerfEvents { 33a0301c0dSLemover val io = IO(new TlbIO(Width, q)) 34a0301c0dSLemover 35a0301c0dSLemover require(q.superAssociative == "fa") 36fb90f54dSLemover if (q.sameCycle || q.missSameCycle) { 37a0301c0dSLemover require(q.normalAssociative == "fa") 38a0301c0dSLemover } 396d5ddbceSLemover 406d5ddbceSLemover val req = io.requestor.map(_.req) 416d5ddbceSLemover val resp = io.requestor.map(_.resp) 426d5ddbceSLemover val ptw = io.ptw 43b6982e83SLemover val pmp = io.pmp 446d5ddbceSLemover 456d5ddbceSLemover val sfence = io.sfence 466d5ddbceSLemover val csr = io.csr 476d5ddbceSLemover val satp = csr.satp 486d5ddbceSLemover val priv = csr.priv 49a0301c0dSLemover val ifecth = if (q.fetchi) true.B else false.B 50a0301c0dSLemover val mode = if (q.useDmode) priv.dmode else priv.imode 516d5ddbceSLemover // val vmEnable = satp.mode === 8.U // && (mode < ModeM) // FIXME: fix me when boot xv6/linux... 526d5ddbceSLemover val vmEnable = if (EnbaleTlbDebug) (satp.mode === 8.U) 536d5ddbceSLemover else (satp.mode === 8.U && (mode < ModeM)) 546d5ddbceSLemover 552c2c1588SLemover val reqAddr = req.map(_.bits.vaddr.asTypeOf(new VaBundle)) 56a0301c0dSLemover val vpn = reqAddr.map(_.vpn) 576d5ddbceSLemover val cmd = req.map(_.bits.cmd) 586d5ddbceSLemover val valid = req.map(_.valid) 596d5ddbceSLemover 606d5ddbceSLemover def widthMapSeq[T <: Seq[Data]](f: Int => T) = (0 until Width).map(f) 61a0301c0dSLemover 626d5ddbceSLemover def widthMap[T <: Data](f: Int => T) = (0 until Width).map(f) 636d5ddbceSLemover 646d5ddbceSLemover // Normal page && Super page 65a0301c0dSLemover val normalPage = TlbStorage( 66a0301c0dSLemover name = "normal", 67a0301c0dSLemover associative = q.normalAssociative, 68a0301c0dSLemover sameCycle = q.sameCycle, 69a0301c0dSLemover ports = Width, 70a0301c0dSLemover nSets = q.normalNSets, 71a0301c0dSLemover nWays = q.normalNWays, 72a0301c0dSLemover sramSinglePort = sramSinglePort, 735cf62c1aSLemover saveLevel = q.saveLevel, 74a0301c0dSLemover normalPage = true, 75a0301c0dSLemover superPage = false 766d5ddbceSLemover ) 77a0301c0dSLemover val superPage = TlbStorage( 78a0301c0dSLemover name = "super", 79a0301c0dSLemover associative = q.superAssociative, 80a0301c0dSLemover sameCycle = q.sameCycle, 81a0301c0dSLemover ports = Width, 82a0301c0dSLemover nSets = q.superNSets, 83a0301c0dSLemover nWays = q.superNWays, 84a0301c0dSLemover sramSinglePort = sramSinglePort, 855cf62c1aSLemover saveLevel = q.saveLevel, 86a0301c0dSLemover normalPage = q.normalAsVictim, 87a0301c0dSLemover superPage = true, 886d5ddbceSLemover ) 896d5ddbceSLemover 90a0301c0dSLemover 916d5ddbceSLemover for (i <- 0 until Width) { 92a0301c0dSLemover normalPage.r_req_apply( 93a0301c0dSLemover valid = io.requestor(i).req.valid, 94a0301c0dSLemover vpn = vpn(i), 9545f497a4Shappy-lx asid = csr.satp.asid, 96a0301c0dSLemover i = i 976d5ddbceSLemover ) 98a0301c0dSLemover superPage.r_req_apply( 99a0301c0dSLemover valid = io.requestor(i).req.valid, 100a0301c0dSLemover vpn = vpn(i), 10145f497a4Shappy-lx asid = csr.satp.asid, 102a0301c0dSLemover i = i 103a0301c0dSLemover ) 104a0301c0dSLemover } 1056d5ddbceSLemover 106a0301c0dSLemover normalPage.victim.in <> superPage.victim.out 107a0301c0dSLemover normalPage.victim.out <> superPage.victim.in 108a0301c0dSLemover normalPage.sfence <> io.sfence 109a0301c0dSLemover superPage.sfence <> io.sfence 11045f497a4Shappy-lx normalPage.csr <> io.csr 11145f497a4Shappy-lx superPage.csr <> io.csr 112149086eaSLemover 113a0301c0dSLemover def TLBNormalRead(i: Int) = { 114fb90f54dSLemover val (n_hit_sameCycle, normal_hit, normal_ppn, normal_perm) = normalPage.r_resp_apply(i) 115fb90f54dSLemover val (s_hit_sameCycle, super_hit, super_ppn, super_perm) = superPage.r_resp_apply(i) 11670083794SLemover // assert(!(normal_hit && super_hit && vmEnable && RegNext(req(i).valid, init = false.B))) 1176d5ddbceSLemover 118a0301c0dSLemover val hit = normal_hit || super_hit 119fb90f54dSLemover val hit_sameCycle = n_hit_sameCycle || s_hit_sameCycle 120cccfc98dSLemover val ppn = Mux(super_hit, super_ppn, normal_ppn) 121cccfc98dSLemover val perm = Mux(super_hit, super_perm, normal_perm) 122a0301c0dSLemover 123e9092fe2SLemover val pf = perm.pf 124e9092fe2SLemover val af = perm.af 125a0301c0dSLemover val cmdReg = if (!q.sameCycle) RegNext(cmd(i)) else cmd(i) 126a0301c0dSLemover val validReg = if (!q.sameCycle) RegNext(valid(i)) else valid(i) 127a0301c0dSLemover val offReg = if (!q.sameCycle) RegNext(reqAddr(i).off) else reqAddr(i).off 128b6982e83SLemover val sizeReg = if (!q.sameCycle) RegNext(req(i).bits.size) else req(i).bits.size 129a0301c0dSLemover 130a0301c0dSLemover /** *************** next cycle when two cycle is false******************* */ 131a0301c0dSLemover val miss = !hit && vmEnable 132cccfc98dSLemover val fast_miss = !super_hit && vmEnable 133fb90f54dSLemover val miss_sameCycle = !hit_sameCycle && vmEnable 1346d5ddbceSLemover hit.suggestName(s"hit_${i}") 1356d5ddbceSLemover miss.suggestName(s"miss_${i}") 1366d5ddbceSLemover 137a0301c0dSLemover XSDebug(validReg, p"(${i.U}) hit:${hit} miss:${miss} ppn:${Hexadecimal(ppn)} perm:${perm}\n") 1386d5ddbceSLemover 139a0301c0dSLemover val paddr = Cat(ppn, offReg) 1406d5ddbceSLemover val vaddr = SignExt(req(i).bits.vaddr, PAddrBits) 14170083794SLemover val refill_reg = RegNext(io.ptw.resp.valid) 1426d5ddbceSLemover req(i).ready := resp(i).ready 1436d5ddbceSLemover resp(i).valid := validReg 144a0301c0dSLemover resp(i).bits.paddr := Mux(vmEnable, paddr, if (!q.sameCycle) RegNext(vaddr) else vaddr) 14570083794SLemover resp(i).bits.miss := { if (q.missSameCycle) miss_sameCycle else (miss || refill_reg) } 14670083794SLemover resp(i).bits.fast_miss := fast_miss || refill_reg 1476d5ddbceSLemover resp(i).bits.ptwBack := io.ptw.resp.fire() 1486d5ddbceSLemover 1495b7ef044SLemover // for timing optimization, pmp check is divided into dynamic and static 1505b7ef044SLemover // dynamic: superpage (or full-connected reg entries) -> check pmp when translation done 1515b7ef044SLemover // static: 4K pages (or sram entries) -> check pmp with pre-checked results 1525b7ef044SLemover val pmp_paddr = Mux(vmEnable, Cat(super_ppn, offReg), if (!q.sameCycle) RegNext(vaddr) else vaddr) 153b6982e83SLemover pmp(i).valid := resp(i).valid 1545b7ef044SLemover pmp(i).bits.addr := pmp_paddr 155b6982e83SLemover pmp(i).bits.size := sizeReg 156b6982e83SLemover pmp(i).bits.cmd := cmdReg 157b6982e83SLemover 158e9092fe2SLemover val ldUpdate = !perm.a && TlbCmd.isRead(cmdReg) && !TlbCmd.isAmo(cmdReg) // update A/D through exception 159e9092fe2SLemover val stUpdate = (!perm.a || !perm.d) && (TlbCmd.isWrite(cmdReg) || TlbCmd.isAmo(cmdReg)) // update A/D through exception 160e9092fe2SLemover val instrUpdate = !perm.a && TlbCmd.isExec(cmdReg) // update A/D through exception 1616d5ddbceSLemover val modeCheck = !(mode === ModeU && !perm.u || mode === ModeS && perm.u && (!priv.sum || ifecth)) 162a79fef67Swakafa val ldPermFail = !(modeCheck && (perm.r || priv.mxr && perm.x)) 163a79fef67Swakafa val stPermFail = !(modeCheck && perm.w) 164a79fef67Swakafa val instrPermFail = !(modeCheck && perm.x) 165a79fef67Swakafa val ldPf = (ldPermFail || pf) && (TlbCmd.isRead(cmdReg) && !TlbCmd.isAmo(cmdReg)) 166a79fef67Swakafa val stPf = (stPermFail || pf) && (TlbCmd.isWrite(cmdReg) || TlbCmd.isAmo(cmdReg)) 167a79fef67Swakafa val instrPf = (instrPermFail || pf) && TlbCmd.isExec(cmdReg) 1682c2c1588SLemover val fault_valid = vmEnable 169ca2f90a6SLemover resp(i).bits.excp.pf.ld := (ldPf || ldUpdate) && fault_valid && !af 170ca2f90a6SLemover resp(i).bits.excp.pf.st := (stPf || stUpdate) && fault_valid && !af 171ca2f90a6SLemover resp(i).bits.excp.pf.instr := (instrPf || instrUpdate) && fault_valid && !af 172b6982e83SLemover // NOTE: pf need && with !af, page fault has higher priority than access fault 173b6982e83SLemover // but ptw may also have access fault, then af happens, the translation is wrong. 174b6982e83SLemover // In this case, pf has lower priority than af 1756d5ddbceSLemover 1765b7ef044SLemover val spm = normal_perm.pm // static physical memory protection or attribute 1775b7ef044SLemover val spm_v = !super_hit && vmEnable && q.partialStaticPMP.B // static pm valid; do not use normal_hit, it's too long. 1785b7ef044SLemover // for tlb without sram, tlb will miss, pm should be ignored outsize 1795b7ef044SLemover resp(i).bits.excp.af.ld := (af || (spm_v && !spm.r)) && TlbCmd.isRead(cmdReg) && fault_valid 1805b7ef044SLemover resp(i).bits.excp.af.st := (af || (spm_v && !spm.w)) && TlbCmd.isWrite(cmdReg) && fault_valid 1815b7ef044SLemover resp(i).bits.excp.af.instr := (af || (spm_v && !spm.x)) && TlbCmd.isExec(cmdReg) && fault_valid 1825b7ef044SLemover resp(i).bits.static_pm.valid := spm_v && fault_valid // ls/st unit should use this mmio, not the result from pmp 1835b7ef044SLemover resp(i).bits.static_pm.bits := !spm.c 1846d5ddbceSLemover 1853889e11eSLemover (hit, miss, validReg) 1866d5ddbceSLemover } 1876d5ddbceSLemover 1886d5ddbceSLemover val readResult = (0 until Width).map(TLBNormalRead(_)) 189a0301c0dSLemover val hitVec = readResult.map(_._1) 190a0301c0dSLemover val missVec = readResult.map(_._2) 1913889e11eSLemover val validRegVec = readResult.map(_._3) 1926d5ddbceSLemover 193149086eaSLemover // replacement 194a0301c0dSLemover def get_access(one_hot: UInt, valid: Bool): Valid[UInt] = { 195149086eaSLemover val res = Wire(Valid(UInt(log2Up(one_hot.getWidth).W))) 196a0301c0dSLemover res.valid := Cat(one_hot).orR && valid 197149086eaSLemover res.bits := OHToUInt(one_hot) 198149086eaSLemover res 199149086eaSLemover } 200a0301c0dSLemover 201a0301c0dSLemover val normal_refill_idx = if (q.outReplace) { 2023889e11eSLemover io.replace.normalPage.access <> normalPage.access 2033889e11eSLemover io.replace.normalPage.chosen_set := get_set_idx(io.ptw.resp.bits.entry.tag, q.normalNSets) 204a0301c0dSLemover io.replace.normalPage.refillIdx 205a0301c0dSLemover } else if (q.normalAssociative == "fa") { 206a0301c0dSLemover val re = ReplacementPolicy.fromString(q.normalReplacer, q.normalNWays) 2073889e11eSLemover re.access(normalPage.access.map(_.touch_ways)) // normalhitVecVec.zipWithIndex.map{ case (hv, i) => get_access(hv, validRegVec(i))}) 208a0301c0dSLemover re.way 209a0301c0dSLemover } else { // set-acco && plru 210a0301c0dSLemover val re = ReplacementPolicy.fromString(q.normalReplacer, q.normalNSets, q.normalNWays) 2113889e11eSLemover re.access(normalPage.access.map(_.sets), normalPage.access.map(_.touch_ways)) 2123889e11eSLemover re.way(get_set_idx(io.ptw.resp.bits.entry.tag, q.normalNSets)) 213149086eaSLemover } 214a0301c0dSLemover 215a0301c0dSLemover val super_refill_idx = if (q.outReplace) { 2163889e11eSLemover io.replace.superPage.access <> superPage.access 217a0301c0dSLemover io.replace.superPage.chosen_set := DontCare 218a0301c0dSLemover io.replace.superPage.refillIdx 219149086eaSLemover } else { 220a0301c0dSLemover val re = ReplacementPolicy.fromString(q.superReplacer, q.superNWays) 2213889e11eSLemover re.access(superPage.access.map(_.touch_ways)) 222a0301c0dSLemover re.way 223149086eaSLemover } 224149086eaSLemover 22545f497a4Shappy-lx val refill = ptw.resp.fire() && !sfence.valid && !satp.changed 226a0301c0dSLemover normalPage.w_apply( 227a0301c0dSLemover valid = { if (q.normalAsVictim) false.B 228a0301c0dSLemover else refill && ptw.resp.bits.entry.level.get === 2.U }, 229a0301c0dSLemover wayIdx = normal_refill_idx, 2305b7ef044SLemover data = ptw.resp.bits, 2315b7ef044SLemover data_replenish = io.ptw_replenish 232a0301c0dSLemover ) 233a0301c0dSLemover superPage.w_apply( 234a0301c0dSLemover valid = { if (q.normalAsVictim) refill 235a0301c0dSLemover else refill && ptw.resp.bits.entry.level.get =/= 2.U }, 236a0301c0dSLemover wayIdx = super_refill_idx, 2375b7ef044SLemover data = ptw.resp.bits, 2385b7ef044SLemover data_replenish = io.ptw_replenish 239a0301c0dSLemover ) 240a0301c0dSLemover 2412c2c1588SLemover // if sameCycle, just req.valid 2422c2c1588SLemover // if !sameCycle, add one more RegNext based on !sameCycle's RegNext 2432c2c1588SLemover // because sram is too slow and dtlb is too distant from dtlbRepeater 2446d5ddbceSLemover for (i <- 0 until Width) { 2452c2c1588SLemover io.ptw.req(i).valid := need_RegNextInit(!q.sameCycle, validRegVec(i) && missVec(i), false.B) && 2462c2c1588SLemover !RegNext(refill, init = false.B) && 2472c2c1588SLemover param_choose(!q.sameCycle, !RegNext(RegNext(refill, init = false.B), init = false.B), true.B) 2482c2c1588SLemover io.ptw.req(i).bits.vpn := need_RegNext(!q.sameCycle, need_RegNext(!q.sameCycle, reqAddr(i).vpn)) 2496d5ddbceSLemover } 2506d5ddbceSLemover io.ptw.resp.ready := true.B 2516d5ddbceSLemover 2522c2c1588SLemover def need_RegNext[T <: Data](need: Boolean, data: T): T = { 2532c2c1588SLemover if (need) RegNext(data) 2542c2c1588SLemover else data 2552c2c1588SLemover } 2562c2c1588SLemover def need_RegNextInit[T <: Data](need: Boolean, data: T, init_value: T): T = { 2572c2c1588SLemover if (need) RegNext(data, init = init_value) 2582c2c1588SLemover else data 2592c2c1588SLemover } 2602c2c1588SLemover 2612c2c1588SLemover def param_choose[T <: Data](need: Boolean, truedata: T, falsedata: T): T = { 2622c2c1588SLemover if (need) truedata 2632c2c1588SLemover else falsedata 2642c2c1588SLemover } 2652c2c1588SLemover 266a0301c0dSLemover if (!q.shouldBlock) { 2676d5ddbceSLemover for (i <- 0 until Width) { 2686d5ddbceSLemover XSPerfAccumulate("first_access" + Integer.toString(i, 10), validRegVec(i) && vmEnable && RegNext(req(i).bits.debug.isFirstIssue)) 2696d5ddbceSLemover XSPerfAccumulate("access" + Integer.toString(i, 10), validRegVec(i) && vmEnable) 2706d5ddbceSLemover } 2716d5ddbceSLemover for (i <- 0 until Width) { 2726d5ddbceSLemover XSPerfAccumulate("first_miss" + Integer.toString(i, 10), validRegVec(i) && vmEnable && missVec(i) && RegNext(req(i).bits.debug.isFirstIssue)) 2736d5ddbceSLemover XSPerfAccumulate("miss" + Integer.toString(i, 10), validRegVec(i) && vmEnable && missVec(i)) 2746d5ddbceSLemover } 2756d5ddbceSLemover } else { 2766d5ddbceSLemover // NOTE: ITLB is blocked, so every resp will be valid only when hit 2776d5ddbceSLemover // every req will be ready only when hit 278a0301c0dSLemover for (i <- 0 until Width) { 279a0301c0dSLemover XSPerfAccumulate(s"access${i}", io.requestor(i).req.fire() && vmEnable) 280a0301c0dSLemover XSPerfAccumulate(s"miss${i}", ptw.req(i).fire()) 281a0301c0dSLemover } 282a0301c0dSLemover 2836d5ddbceSLemover } 2846d5ddbceSLemover //val reqCycleCnt = Reg(UInt(16.W)) 2856d5ddbceSLemover //reqCycleCnt := reqCycleCnt + BoolStopWatch(ptw.req(0).fire(), ptw.resp.fire || sfence.valid) 2866d5ddbceSLemover //XSPerfAccumulate("ptw_req_count", ptw.req.fire()) 2876d5ddbceSLemover //XSPerfAccumulate("ptw_req_cycle", Mux(ptw.resp.fire(), reqCycleCnt, 0.U)) 2886d5ddbceSLemover XSPerfAccumulate("ptw_resp_count", ptw.resp.fire()) 2896d5ddbceSLemover XSPerfAccumulate("ptw_resp_pf_count", ptw.resp.fire() && ptw.resp.bits.pf) 2906d5ddbceSLemover 2916d5ddbceSLemover // Log 2926d5ddbceSLemover for(i <- 0 until Width) { 2936d5ddbceSLemover XSDebug(req(i).valid, p"req(${i.U}): (${req(i).valid} ${req(i).ready}) ${req(i).bits}\n") 2946d5ddbceSLemover XSDebug(resp(i).valid, p"resp(${i.U}): (${resp(i).valid} ${resp(i).ready}) ${resp(i).bits}\n") 2956d5ddbceSLemover } 2966d5ddbceSLemover 2976d5ddbceSLemover XSDebug(sfence.valid, p"Sfence: ${sfence}\n") 2986d5ddbceSLemover XSDebug(ParallelOR(valid)|| ptw.resp.valid, p"CSR: ${csr}\n") 299a0301c0dSLemover XSDebug(ParallelOR(valid) || ptw.resp.valid, p"vmEnable:${vmEnable} hit:${Binary(VecInit(hitVec).asUInt)} miss:${Binary(VecInit(missVec).asUInt)}\n") 3006d5ddbceSLemover for (i <- ptw.req.indices) { 301*92e3bfefSLemover XSDebug(ptw.req(i).fire(), p"L2TLB req:${ptw.req(i).bits}\n") 3026d5ddbceSLemover } 303*92e3bfefSLemover XSDebug(ptw.resp.valid, p"L2TLB resp:${ptw.resp.bits} (v:${ptw.resp.valid}r:${ptw.resp.ready}) \n") 3046d5ddbceSLemover 305a0301c0dSLemover println(s"${q.name}: normal page: ${q.normalNWays} ${q.normalAssociative} ${q.normalReplacer.get} super page: ${q.superNWays} ${q.superAssociative} ${q.superReplacer.get}") 306a0301c0dSLemover 3076d5ddbceSLemover// // NOTE: just for simple tlb debug, comment it after tlb's debug 3086d5ddbceSLemover // assert(!io.ptw.resp.valid || io.ptw.resp.bits.entry.tag === io.ptw.resp.bits.entry.ppn, "Simple tlb debug requires vpn === ppn") 3091ca0e4f3SYinan Xu 3101ca0e4f3SYinan Xu val perfEvents = if(!q.shouldBlock) { 3111ca0e4f3SYinan Xu Seq( 312cd365d4cSrvcoresjw ("access", PopCount((0 until Width).map(i => vmEnable && validRegVec(i))) ), 313cd365d4cSrvcoresjw ("miss ", PopCount((0 until Width).map(i => vmEnable && validRegVec(i) && missVec(i)))), 314cd365d4cSrvcoresjw ) 315cd365d4cSrvcoresjw } else { 3161ca0e4f3SYinan Xu Seq( 317cd365d4cSrvcoresjw ("access", PopCount((0 until Width).map(i => io.requestor(i).req.fire()))), 318cd365d4cSrvcoresjw ("miss ", PopCount((0 until Width).map(i => ptw.req(i).fire())) ), 319cd365d4cSrvcoresjw ) 320cd365d4cSrvcoresjw } 3211ca0e4f3SYinan Xu generatePerfEvent() 3226d5ddbceSLemover} 3236d5ddbceSLemover 324a0301c0dSLemoverclass TlbReplace(Width: Int, q: TLBParameters)(implicit p: Parameters) extends TlbModule { 325a0301c0dSLemover val io = IO(new TlbReplaceIO(Width, q)) 326a0301c0dSLemover 327a0301c0dSLemover if (q.normalAssociative == "fa") { 328a0301c0dSLemover val re = ReplacementPolicy.fromString(q.normalReplacer, q.normalNWays) 3293889e11eSLemover re.access(io.normalPage.access.map(_.touch_ways)) 330a0301c0dSLemover io.normalPage.refillIdx := re.way 331a0301c0dSLemover } else { // set-acco && plru 332a0301c0dSLemover val re = ReplacementPolicy.fromString(q.normalReplacer, q.normalNSets, q.normalNWays) 3333889e11eSLemover re.access(io.normalPage.access.map(_.sets), io.normalPage.access.map(_.touch_ways)) 334a0301c0dSLemover io.normalPage.refillIdx := { if (q.normalNWays == 1) 0.U else re.way(io.normalPage.chosen_set) } 335a0301c0dSLemover } 336a0301c0dSLemover 337a0301c0dSLemover if (q.superAssociative == "fa") { 338a0301c0dSLemover val re = ReplacementPolicy.fromString(q.superReplacer, q.superNWays) 3393889e11eSLemover re.access(io.superPage.access.map(_.touch_ways)) 340a0301c0dSLemover io.superPage.refillIdx := re.way 341a0301c0dSLemover } else { // set-acco && plru 342a0301c0dSLemover val re = ReplacementPolicy.fromString(q.superReplacer, q.superNSets, q.superNWays) 3433889e11eSLemover re.access(io.superPage.access.map(_.sets), io.superPage.access.map(_.touch_ways)) 344a0301c0dSLemover io.superPage.refillIdx := { if (q.superNWays == 1) 0.U else re.way(io.superPage.chosen_set) } 345a0301c0dSLemover } 346a0301c0dSLemover} 347a0301c0dSLemover 3486d5ddbceSLemoverobject TLB { 3496d5ddbceSLemover def apply 3506d5ddbceSLemover ( 3516d5ddbceSLemover in: Seq[BlockTlbRequestIO], 3526d5ddbceSLemover sfence: SfenceBundle, 3536d5ddbceSLemover csr: TlbCsrBundle, 3546d5ddbceSLemover width: Int, 355a0301c0dSLemover shouldBlock: Boolean, 356a0301c0dSLemover q: TLBParameters 3576d5ddbceSLemover )(implicit p: Parameters) = { 3586d5ddbceSLemover require(in.length == width) 3596d5ddbceSLemover 360a0301c0dSLemover val tlb = Module(new TLB(width, q)) 3616d5ddbceSLemover 3626d5ddbceSLemover tlb.io.sfence <> sfence 3636d5ddbceSLemover tlb.io.csr <> csr 364a0301c0dSLemover tlb.suggestName(s"tlb_${q.name}") 3656d5ddbceSLemover 3666d5ddbceSLemover if (!shouldBlock) { // dtlb 3676d5ddbceSLemover for (i <- 0 until width) { 3686d5ddbceSLemover tlb.io.requestor(i) <> in(i) 3696d5ddbceSLemover // tlb.io.requestor(i).req.valid := in(i).req.valid 3706d5ddbceSLemover // tlb.io.requestor(i).req.bits := in(i).req.bits 3716d5ddbceSLemover // in(i).req.ready := tlb.io.requestor(i).req.ready 3726d5ddbceSLemover 3736d5ddbceSLemover // in(i).resp.valid := tlb.io.requestor(i).resp.valid 3746d5ddbceSLemover // in(i).resp.bits := tlb.io.requestor(i).resp.bits 3756d5ddbceSLemover // tlb.io.requestor(i).resp.ready := in(i).resp.ready 3766d5ddbceSLemover } 3776d5ddbceSLemover } else { // itlb 378d57bda64SJinYue //require(width == 1) 379d57bda64SJinYue (0 until width).map{ i => 380d57bda64SJinYue tlb.io.requestor(i).req.valid := in(i).req.valid 381d57bda64SJinYue tlb.io.requestor(i).req.bits := in(i).req.bits 382d57bda64SJinYue in(i).req.ready := !tlb.io.requestor(i).resp.bits.miss && in(i).resp.ready && tlb.io.requestor(i).req.ready 3836d5ddbceSLemover 384fb90f54dSLemover require(q.missSameCycle || q.sameCycle) 385fb90f54dSLemover // NOTE: the resp.valid seems to be useless, it must be true when need 386fb90f54dSLemover // But don't know what happens when true but not need, so keep it correct value, not just true.B 387fb90f54dSLemover if (q.missSameCycle && !q.sameCycle) { 388fb90f54dSLemover in(i).resp.valid := tlb.io.requestor(i).resp.valid && !RegNext(tlb.io.requestor(i).resp.bits.miss) 389fb90f54dSLemover } else { 390d57bda64SJinYue in(i).resp.valid := tlb.io.requestor(i).resp.valid && !tlb.io.requestor(i).resp.bits.miss 391fb90f54dSLemover } 392d57bda64SJinYue in(i).resp.bits := tlb.io.requestor(i).resp.bits 393d57bda64SJinYue tlb.io.requestor(i).resp.ready := in(i).resp.ready 394d57bda64SJinYue } 3955b7ef044SLemover tlb.io.ptw_replenish <> DontCare // itlb only use reg, so no static pmp/pma 3966d5ddbceSLemover } 3976d5ddbceSLemover tlb.io.ptw 3986d5ddbceSLemover } 3996d5ddbceSLemover} 400