xref: /XiangShan/src/main/scala/xiangshan/cache/mmu/TLB.scala (revision a0301c0d86a76a8bbed79fab2db5e6571a62b88a)
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._
21*a0301c0dSLemoverimport chisel3.internal.naming.chiselName
226d5ddbceSLemoverimport chisel3.util._
23*a0301c0dSLemoverimport freechips.rocketchip.util.SRAMAnnotation
246d5ddbceSLemoverimport xiangshan._
256d5ddbceSLemoverimport utils._
266d5ddbceSLemoverimport xiangshan.backend.roq.RoqPtr
276d5ddbceSLemoverimport xiangshan.backend.fu.util.HasCSRConst
286d5ddbceSLemover
29*a0301c0dSLemover
30*a0301c0dSLemover@chiselName
31*a0301c0dSLemoverclass TLB(Width: Int, q: TLBParameters)(implicit p: Parameters) extends TlbModule with HasCSRConst {
32*a0301c0dSLemover  val io = IO(new TlbIO(Width, q))
33*a0301c0dSLemover
34*a0301c0dSLemover  require(q.superAssociative == "fa")
35*a0301c0dSLemover  if (q.sameCycle) {
36*a0301c0dSLemover    require(q.normalAssociative == "fa")
37*a0301c0dSLemover  }
386d5ddbceSLemover
396d5ddbceSLemover  val req = io.requestor.map(_.req)
406d5ddbceSLemover  val resp = io.requestor.map(_.resp)
416d5ddbceSLemover  val ptw = io.ptw
426d5ddbceSLemover
436d5ddbceSLemover  val sfence = io.sfence
446d5ddbceSLemover  val csr = io.csr
456d5ddbceSLemover  val satp = csr.satp
466d5ddbceSLemover  val priv = csr.priv
47*a0301c0dSLemover  val ifecth = if (q.fetchi) true.B else false.B
48*a0301c0dSLemover  val mode = if (q.useDmode) priv.dmode else priv.imode
496d5ddbceSLemover  // val vmEnable = satp.mode === 8.U // && (mode < ModeM) // FIXME: fix me when boot xv6/linux...
506d5ddbceSLemover  val vmEnable = if (EnbaleTlbDebug) (satp.mode === 8.U)
516d5ddbceSLemover  else (satp.mode === 8.U && (mode < ModeM))
526d5ddbceSLemover
53*a0301c0dSLemover  val reqAddr = req.map(_.bits.vaddr.asTypeOf((new VaBundle).cloneType))
54*a0301c0dSLemover  val vpn = reqAddr.map(_.vpn)
556d5ddbceSLemover  val cmd = req.map(_.bits.cmd)
566d5ddbceSLemover  val valid = req.map(_.valid)
576d5ddbceSLemover
586d5ddbceSLemover  def widthMapSeq[T <: Seq[Data]](f: Int => T) = (0 until Width).map(f)
59*a0301c0dSLemover
606d5ddbceSLemover  def widthMap[T <: Data](f: Int => T) = (0 until Width).map(f)
616d5ddbceSLemover
626d5ddbceSLemover  // Normal page && Super page
63*a0301c0dSLemover  val normalPage = TlbStorage(
64*a0301c0dSLemover    name = "normal",
65*a0301c0dSLemover    associative = q.normalAssociative,
66*a0301c0dSLemover    sameCycle = q.sameCycle,
67*a0301c0dSLemover    ports = Width,
68*a0301c0dSLemover    nSets = q.normalNSets,
69*a0301c0dSLemover    nWays = q.normalNWays,
70*a0301c0dSLemover    sramSinglePort = sramSinglePort,
71*a0301c0dSLemover    normalPage = true,
72*a0301c0dSLemover    superPage = false
736d5ddbceSLemover  )
74*a0301c0dSLemover  val superPage = TlbStorage(
75*a0301c0dSLemover    name = "super",
76*a0301c0dSLemover    associative = q.superAssociative,
77*a0301c0dSLemover    sameCycle = q.sameCycle,
78*a0301c0dSLemover    ports = Width,
79*a0301c0dSLemover    nSets = q.superNSets,
80*a0301c0dSLemover    nWays = q.superNWays,
81*a0301c0dSLemover    sramSinglePort = sramSinglePort,
82*a0301c0dSLemover    normalPage = q.normalAsVictim,
83*a0301c0dSLemover    superPage = true,
846d5ddbceSLemover  )
856d5ddbceSLemover
86*a0301c0dSLemover
876d5ddbceSLemover  for (i <- 0 until Width) {
88*a0301c0dSLemover    normalPage.r_req_apply(
89*a0301c0dSLemover      valid = io.requestor(i).req.valid,
90*a0301c0dSLemover      vpn = vpn(i),
91*a0301c0dSLemover      i = i
926d5ddbceSLemover    )
93*a0301c0dSLemover    superPage.r_req_apply(
94*a0301c0dSLemover      valid = io.requestor(i).req.valid,
95*a0301c0dSLemover      vpn = vpn(i),
96*a0301c0dSLemover      i = i
97*a0301c0dSLemover    )
98*a0301c0dSLemover  }
996d5ddbceSLemover
1006d5ddbceSLemover
101*a0301c0dSLemover  normalPage.victim.in <> superPage.victim.out
102*a0301c0dSLemover  normalPage.victim.out <> superPage.victim.in
103*a0301c0dSLemover  normalPage.sfence <> io.sfence
104*a0301c0dSLemover  superPage.sfence <> io.sfence
105149086eaSLemover
106*a0301c0dSLemover  def TLBNormalRead(i: Int) = {
107*a0301c0dSLemover    val (normal_hit, normal_ppn, normal_perm, normal_hitVec) = normalPage.r_resp_apply(i)
108*a0301c0dSLemover    val (super_hit, super_ppn, super_perm, super_hitVec) = superPage.r_resp_apply(i)
109*a0301c0dSLemover    assert(!(normal_hit && super_hit && vmEnable && RegNext(req(i).valid, init = false.B)))
1106d5ddbceSLemover
111*a0301c0dSLemover    val hit = normal_hit || super_hit
112*a0301c0dSLemover    val ppn = Mux(normal_hit, normal_ppn, super_ppn)
113*a0301c0dSLemover    val perm = Mux(normal_hit, normal_perm, super_perm)
114*a0301c0dSLemover
115*a0301c0dSLemover    val pf = perm.pf && hit
116*a0301c0dSLemover    val cmdReg = if (!q.sameCycle) RegNext(cmd(i)) else cmd(i)
117*a0301c0dSLemover    val validReg = if (!q.sameCycle) RegNext(valid(i)) else valid(i)
118*a0301c0dSLemover    val offReg = if (!q.sameCycle) RegNext(reqAddr(i).off) else reqAddr(i).off
119*a0301c0dSLemover
120*a0301c0dSLemover    /** *************** next cycle when two cycle is false******************* */
121*a0301c0dSLemover    val miss = !hit && vmEnable
1226d5ddbceSLemover    hit.suggestName(s"hit_${i}")
1236d5ddbceSLemover    miss.suggestName(s"miss_${i}")
1246d5ddbceSLemover
125*a0301c0dSLemover    XSDebug(validReg, p"(${i.U}) hit:${hit} miss:${miss} ppn:${Hexadecimal(ppn)} perm:${perm}\n")
1266d5ddbceSLemover
127*a0301c0dSLemover    val paddr = Cat(ppn, offReg)
1286d5ddbceSLemover    val vaddr = SignExt(req(i).bits.vaddr, PAddrBits)
1296d5ddbceSLemover
1306d5ddbceSLemover    req(i).ready := resp(i).ready
1316d5ddbceSLemover    resp(i).valid := validReg
132*a0301c0dSLemover    resp(i).bits.paddr := Mux(vmEnable, paddr, if (!q.sameCycle) RegNext(vaddr) else vaddr)
1336d5ddbceSLemover    resp(i).bits.miss := miss
1346d5ddbceSLemover    resp(i).bits.ptwBack := io.ptw.resp.fire()
1356d5ddbceSLemover
136*a0301c0dSLemover    val update = hit && (!perm.a || !perm.d && TlbCmd.isWrite(cmdReg)) // update A/D through exception
1376d5ddbceSLemover    val modeCheck = !(mode === ModeU && !perm.u || mode === ModeS && perm.u && (!priv.sum || ifecth))
138*a0301c0dSLemover    val ldPf = !(modeCheck && (perm.r || priv.mxr && perm.x)) && (TlbCmd.isRead(cmdReg) && true.B /* TODO !isAMO*/)
139*a0301c0dSLemover    val stPf = !(modeCheck && perm.w) && (TlbCmd.isWrite(cmdReg) || false.B /*TODO isAMO. */)
140*a0301c0dSLemover    val instrPf = !(modeCheck && perm.x) && TlbCmd.isExec(cmdReg)
141*a0301c0dSLemover    resp(i).bits.excp.pf.ld := (ldPf || update || pf) && vmEnable && hit
142*a0301c0dSLemover    resp(i).bits.excp.pf.st := (stPf || update || pf) && vmEnable && hit
143*a0301c0dSLemover    resp(i).bits.excp.pf.instr := (instrPf || update || pf) && vmEnable && hit
1446d5ddbceSLemover
1456d5ddbceSLemover    // if vmenable, use pre-calcuated pma check result
146*a0301c0dSLemover    resp(i).bits.mmio := Mux(TlbCmd.isExec(cmdReg), !perm.pi, !perm.pd) && vmEnable && hit
147*a0301c0dSLemover    resp(i).bits.excp.af.ld := Mux(TlbCmd.isAtom(cmdReg), !perm.pa, !perm.pr) && TlbCmd.isRead(cmdReg) && vmEnable && hit
148*a0301c0dSLemover    resp(i).bits.excp.af.st := Mux(TlbCmd.isAtom(cmdReg), !perm.pa, !perm.pw) && TlbCmd.isWrite(cmdReg) && vmEnable && hit
149*a0301c0dSLemover    resp(i).bits.excp.af.instr := Mux(TlbCmd.isAtom(cmdReg), false.B, !perm.pe) && vmEnable && hit
1506d5ddbceSLemover
1516d5ddbceSLemover    // if !vmenable, check pma
1526d5ddbceSLemover    val (pmaMode, accessWidth) = AddressSpace.memmapAddrMatch(resp(i).bits.paddr)
1536d5ddbceSLemover    when(!vmEnable) {
1546d5ddbceSLemover      resp(i).bits.mmio := Mux(TlbCmd.isExec(cmdReg), !PMAMode.icache(pmaMode), !PMAMode.dcache(pmaMode))
1556d5ddbceSLemover      resp(i).bits.excp.af.ld := Mux(TlbCmd.isAtom(cmdReg), !PMAMode.atomic(pmaMode), !PMAMode.read(pmaMode)) && TlbCmd.isRead(cmdReg)
1566d5ddbceSLemover      resp(i).bits.excp.af.st := Mux(TlbCmd.isAtom(cmdReg), !PMAMode.atomic(pmaMode), !PMAMode.write(pmaMode)) && TlbCmd.isWrite(cmdReg)
1576d5ddbceSLemover      resp(i).bits.excp.af.instr := Mux(TlbCmd.isAtom(cmdReg), false.B, !PMAMode.execute(pmaMode))
1586d5ddbceSLemover    }
1596d5ddbceSLemover
160*a0301c0dSLemover    (hit, miss, normal_hitVec, super_hitVec, validReg)
1616d5ddbceSLemover  }
1626d5ddbceSLemover
1636d5ddbceSLemover  val readResult = (0 until Width).map(TLBNormalRead(_))
164*a0301c0dSLemover  val hitVec = readResult.map(_._1)
165*a0301c0dSLemover  val missVec = readResult.map(_._2)
166*a0301c0dSLemover  val normalhitVecVec = readResult.map(_._3)
167*a0301c0dSLemover  val superhitVecVec = readResult.map(_._4)
168*a0301c0dSLemover  val validRegVec = readResult.map(_._5)
1696d5ddbceSLemover
170149086eaSLemover  // replacement
171*a0301c0dSLemover  def get_access(one_hot: UInt, valid: Bool): Valid[UInt] = {
172149086eaSLemover    val res = Wire(Valid(UInt(log2Up(one_hot.getWidth).W)))
173*a0301c0dSLemover    res.valid := Cat(one_hot).orR && valid
174149086eaSLemover    res.bits := OHToUInt(one_hot)
175149086eaSLemover    res
176149086eaSLemover  }
177*a0301c0dSLemover
178*a0301c0dSLemover  val normal_refill_idx = if (q.outReplace) {
179*a0301c0dSLemover    io.replace.normalPage.access.sets := vpn.map(get_idx(_, q.normalNSets))
180*a0301c0dSLemover    io.replace.normalPage.access.touch_ways := normalhitVecVec.zipWithIndex.map{ case (hv, i) => get_access(hv,
181*a0301c0dSLemover      validRegVec(i))}
182*a0301c0dSLemover    io.replace.normalPage.chosen_set := get_idx(io.ptw.resp.bits.entry.tag, q.normalNSets)
183*a0301c0dSLemover    io.replace.normalPage.refillIdx
184*a0301c0dSLemover  } else if (q.normalAssociative == "fa") {
185*a0301c0dSLemover    val re = ReplacementPolicy.fromString(q.normalReplacer, q.normalNWays)
186*a0301c0dSLemover    re.access(normalhitVecVec.zipWithIndex.map{ case (hv, i) => get_access(hv, validRegVec(i))})
187*a0301c0dSLemover    re.way
188*a0301c0dSLemover  } else { // set-acco && plru
189*a0301c0dSLemover    val re = ReplacementPolicy.fromString(q.normalReplacer, q.normalNSets, q.normalNWays)
190*a0301c0dSLemover    re.access(vpn.map(get_idx(_, q.normalNSets)), normalhitVecVec.zipWithIndex.map{ case (hv, i) => get_access(hv,
191*a0301c0dSLemover      validRegVec(i))})
192*a0301c0dSLemover    re.way(get_idx(io.ptw.resp.bits.entry.tag, q.normalNSets))
193149086eaSLemover  }
194*a0301c0dSLemover
195*a0301c0dSLemover  val super_refill_idx = if (q.outReplace) {
196*a0301c0dSLemover    io.replace.superPage.access.sets := vpn.map(get_idx(_, q.normalNSets))
197*a0301c0dSLemover    io.replace.superPage.access.touch_ways := superhitVecVec.zipWithIndex.map{ case (hv, i) => get_access(hv,
198*a0301c0dSLemover      validRegVec(i))}
199*a0301c0dSLemover    io.replace.superPage.chosen_set := DontCare
200*a0301c0dSLemover    io.replace.superPage.refillIdx
201149086eaSLemover  } else {
202*a0301c0dSLemover    val re = ReplacementPolicy.fromString(q.superReplacer, q.superNWays)
203*a0301c0dSLemover    re.access(superhitVecVec.zipWithIndex.map{ case (hv, i) => get_access(hv, validRegVec(i))})
204*a0301c0dSLemover    re.way
205149086eaSLemover  }
206149086eaSLemover
207*a0301c0dSLemover  val refill = ptw.resp.fire() && !sfence.valid
208*a0301c0dSLemover  normalPage.w_apply(
209*a0301c0dSLemover    valid = { if (q.normalAsVictim) false.B
210*a0301c0dSLemover    else refill && ptw.resp.bits.entry.level.get === 2.U },
211*a0301c0dSLemover    wayIdx = normal_refill_idx,
212*a0301c0dSLemover    data = ptw.resp.bits
213*a0301c0dSLemover  )
214*a0301c0dSLemover  superPage.w_apply(
215*a0301c0dSLemover    valid = { if (q.normalAsVictim) refill
216*a0301c0dSLemover    else refill && ptw.resp.bits.entry.level.get =/= 2.U },
217*a0301c0dSLemover    wayIdx = super_refill_idx,
218*a0301c0dSLemover    data = ptw.resp.bits
219*a0301c0dSLemover  )
220*a0301c0dSLemover
2216d5ddbceSLemover  for (i <- 0 until Width) {
2226d5ddbceSLemover    io.ptw.req(i).valid := validRegVec(i) && missVec(i) && !RegNext(refill)
2236d5ddbceSLemover    io.ptw.req(i).bits.vpn := RegNext(reqAddr(i).vpn)
2246d5ddbceSLemover  }
2256d5ddbceSLemover  io.ptw.resp.ready := true.B
2266d5ddbceSLemover
227*a0301c0dSLemover  if (!q.shouldBlock) {
2286d5ddbceSLemover    for (i <- 0 until Width) {
2296d5ddbceSLemover      XSPerfAccumulate("first_access" + Integer.toString(i, 10), validRegVec(i) && vmEnable && RegNext(req(i).bits.debug.isFirstIssue))
2306d5ddbceSLemover      XSPerfAccumulate("access" + Integer.toString(i, 10), validRegVec(i) && vmEnable)
2316d5ddbceSLemover    }
2326d5ddbceSLemover    for (i <- 0 until Width) {
2336d5ddbceSLemover      XSPerfAccumulate("first_miss" + Integer.toString(i, 10), validRegVec(i) && vmEnable && missVec(i) && RegNext(req(i).bits.debug.isFirstIssue))
2346d5ddbceSLemover      XSPerfAccumulate("miss" + Integer.toString(i, 10), validRegVec(i) && vmEnable && missVec(i))
2356d5ddbceSLemover    }
2366d5ddbceSLemover  } else {
2376d5ddbceSLemover    // NOTE: ITLB is blocked, so every resp will be valid only when hit
2386d5ddbceSLemover    // every req will be ready only when hit
239*a0301c0dSLemover    for (i <- 0 until Width) {
240*a0301c0dSLemover      XSPerfAccumulate(s"access${i}", io.requestor(i).req.fire() && vmEnable)
241*a0301c0dSLemover      XSPerfAccumulate(s"miss${i}", ptw.req(i).fire())
242*a0301c0dSLemover    }
243*a0301c0dSLemover
2446d5ddbceSLemover  }
2456d5ddbceSLemover  //val reqCycleCnt = Reg(UInt(16.W))
2466d5ddbceSLemover  //reqCycleCnt := reqCycleCnt + BoolStopWatch(ptw.req(0).fire(), ptw.resp.fire || sfence.valid)
2476d5ddbceSLemover  //XSPerfAccumulate("ptw_req_count", ptw.req.fire())
2486d5ddbceSLemover  //XSPerfAccumulate("ptw_req_cycle", Mux(ptw.resp.fire(), reqCycleCnt, 0.U))
2496d5ddbceSLemover  XSPerfAccumulate("ptw_resp_count", ptw.resp.fire())
2506d5ddbceSLemover  XSPerfAccumulate("ptw_resp_pf_count", ptw.resp.fire() && ptw.resp.bits.pf)
2516d5ddbceSLemover
2526d5ddbceSLemover  // Log
2536d5ddbceSLemover  for(i <- 0 until Width) {
2546d5ddbceSLemover    XSDebug(req(i).valid, p"req(${i.U}): (${req(i).valid} ${req(i).ready}) ${req(i).bits}\n")
2556d5ddbceSLemover    XSDebug(resp(i).valid, p"resp(${i.U}): (${resp(i).valid} ${resp(i).ready}) ${resp(i).bits}\n")
2566d5ddbceSLemover  }
2576d5ddbceSLemover
2586d5ddbceSLemover  XSDebug(sfence.valid, p"Sfence: ${sfence}\n")
2596d5ddbceSLemover  XSDebug(ParallelOR(valid)|| ptw.resp.valid, p"CSR: ${csr}\n")
260*a0301c0dSLemover  XSDebug(ParallelOR(valid) || ptw.resp.valid, p"vmEnable:${vmEnable} hit:${Binary(VecInit(hitVec).asUInt)} miss:${Binary(VecInit(missVec).asUInt)}\n")
2616d5ddbceSLemover  for (i <- ptw.req.indices) {
2626d5ddbceSLemover    XSDebug(ptw.req(i).fire(), p"PTW req:${ptw.req(i).bits}\n")
2636d5ddbceSLemover  }
2646d5ddbceSLemover  XSDebug(ptw.resp.valid, p"PTW resp:${ptw.resp.bits} (v:${ptw.resp.valid}r:${ptw.resp.ready}) \n")
2656d5ddbceSLemover
266*a0301c0dSLemover  println(s"${q.name}: normal page: ${q.normalNWays} ${q.normalAssociative} ${q.normalReplacer.get} super page: ${q.superNWays} ${q.superAssociative} ${q.superReplacer.get}")
267*a0301c0dSLemover
2686d5ddbceSLemover//   // NOTE: just for simple tlb debug, comment it after tlb's debug
2696d5ddbceSLemover  // assert(!io.ptw.resp.valid || io.ptw.resp.bits.entry.tag === io.ptw.resp.bits.entry.ppn, "Simple tlb debug requires vpn === ppn")
2706d5ddbceSLemover}
2716d5ddbceSLemover
272*a0301c0dSLemoverclass TlbReplace(Width: Int, q: TLBParameters)(implicit p: Parameters) extends TlbModule {
273*a0301c0dSLemover  val io = IO(new TlbReplaceIO(Width, q))
274*a0301c0dSLemover
275*a0301c0dSLemover  if (q.normalAssociative == "fa") {
276*a0301c0dSLemover    val re = ReplacementPolicy.fromString(q.normalReplacer, q.normalNWays)
277*a0301c0dSLemover    re.access(io.normalPage.access.touch_ways)
278*a0301c0dSLemover    io.normalPage.refillIdx := re.way
279*a0301c0dSLemover  } else { // set-acco && plru
280*a0301c0dSLemover    val re = ReplacementPolicy.fromString(q.normalReplacer, q.normalNSets, q.normalNWays)
281*a0301c0dSLemover    re.access(io.normalPage.access.sets, io.normalPage.access.touch_ways)
282*a0301c0dSLemover    io.normalPage.refillIdx := { if (q.normalNWays == 1) 0.U else re.way(io.normalPage.chosen_set) }
283*a0301c0dSLemover  }
284*a0301c0dSLemover
285*a0301c0dSLemover  if (q.superAssociative == "fa") {
286*a0301c0dSLemover    val re = ReplacementPolicy.fromString(q.superReplacer, q.superNWays)
287*a0301c0dSLemover    re.access(io.superPage.access.touch_ways)
288*a0301c0dSLemover    io.superPage.refillIdx := re.way
289*a0301c0dSLemover  } else { // set-acco && plru
290*a0301c0dSLemover    val re = ReplacementPolicy.fromString(q.superReplacer, q.superNSets, q.superNWays)
291*a0301c0dSLemover    re.access(io.superPage.access.sets, io.superPage.access.touch_ways)
292*a0301c0dSLemover    io.superPage.refillIdx := { if (q.superNWays == 1) 0.U else re.way(io.superPage.chosen_set) }
293*a0301c0dSLemover  }
294*a0301c0dSLemover}
295*a0301c0dSLemover
2966d5ddbceSLemoverobject TLB {
2976d5ddbceSLemover  def apply
2986d5ddbceSLemover  (
2996d5ddbceSLemover    in: Seq[BlockTlbRequestIO],
3006d5ddbceSLemover    sfence: SfenceBundle,
3016d5ddbceSLemover    csr: TlbCsrBundle,
3026d5ddbceSLemover    width: Int,
303*a0301c0dSLemover    shouldBlock: Boolean,
304*a0301c0dSLemover    q: TLBParameters
3056d5ddbceSLemover  )(implicit p: Parameters) = {
3066d5ddbceSLemover    require(in.length == width)
3076d5ddbceSLemover
308*a0301c0dSLemover    val tlb = Module(new TLB(width, q))
3096d5ddbceSLemover
3106d5ddbceSLemover    tlb.io.sfence <> sfence
3116d5ddbceSLemover    tlb.io.csr <> csr
312*a0301c0dSLemover    tlb.suggestName(s"tlb_${q.name}")
3136d5ddbceSLemover
3146d5ddbceSLemover    if (!shouldBlock) { // dtlb
3156d5ddbceSLemover      for (i <- 0 until width) {
3166d5ddbceSLemover        tlb.io.requestor(i) <> in(i)
3176d5ddbceSLemover        // tlb.io.requestor(i).req.valid := in(i).req.valid
3186d5ddbceSLemover        // tlb.io.requestor(i).req.bits := in(i).req.bits
3196d5ddbceSLemover        // in(i).req.ready := tlb.io.requestor(i).req.ready
3206d5ddbceSLemover
3216d5ddbceSLemover        // in(i).resp.valid := tlb.io.requestor(i).resp.valid
3226d5ddbceSLemover        // in(i).resp.bits := tlb.io.requestor(i).resp.bits
3236d5ddbceSLemover        // tlb.io.requestor(i).resp.ready := in(i).resp.ready
3246d5ddbceSLemover      }
3256d5ddbceSLemover    } else { // itlb
326d57bda64SJinYue      //require(width == 1)
327d57bda64SJinYue      (0 until width).map{ i =>
328d57bda64SJinYue        tlb.io.requestor(i).req.valid := in(i).req.valid
329d57bda64SJinYue        tlb.io.requestor(i).req.bits := in(i).req.bits
330d57bda64SJinYue        in(i).req.ready := !tlb.io.requestor(i).resp.bits.miss && in(i).resp.ready && tlb.io.requestor(i).req.ready
3316d5ddbceSLemover
332d57bda64SJinYue        in(i).resp.valid := tlb.io.requestor(i).resp.valid && !tlb.io.requestor(i).resp.bits.miss
333d57bda64SJinYue        in(i).resp.bits := tlb.io.requestor(i).resp.bits
334d57bda64SJinYue        tlb.io.requestor(i).resp.ready := in(i).resp.ready
335d57bda64SJinYue      }
3366d5ddbceSLemover    }
3376d5ddbceSLemover
3386d5ddbceSLemover    tlb.io.ptw
3396d5ddbceSLemover  }
3406d5ddbceSLemover}
341