xref: /XiangShan/src/main/scala/xiangshan/cache/mmu/TLBStorage.scala (revision 16534be3dcd1810cf96b4ea5033d4fc72fc0bfac)
1a0301c0dSLemover/***************************************************************************************
2a0301c0dSLemover  * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3a0301c0dSLemover  * Copyright (c) 2020-2021 Peng Cheng Laboratory
4a0301c0dSLemover  *
5a0301c0dSLemover  * XiangShan is licensed under Mulan PSL v2.
6a0301c0dSLemover  * You can use this software according to the terms and conditions of the Mulan PSL v2.
7a0301c0dSLemover  * You may obtain a copy of Mulan PSL v2 at:
8a0301c0dSLemover  *          http://license.coscl.org.cn/MulanPSL2
9a0301c0dSLemover  *
10a0301c0dSLemover  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11a0301c0dSLemover  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12a0301c0dSLemover  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13a0301c0dSLemover  *
14a0301c0dSLemover  * See the Mulan PSL v2 for more details.
15a0301c0dSLemover  ***************************************************************************************/
16a0301c0dSLemover
17a0301c0dSLemoverpackage xiangshan.cache.mmu
18a0301c0dSLemover
198891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters
20a0301c0dSLemoverimport chisel3._
211ca0e4f3SYinan Xuimport chisel3.util._
22a0301c0dSLemoverimport utils._
233c02ee8fSwakafaimport utility._
24f1fe8698SLemoverimport freechips.rocketchip.formal.PropertyClass
25e0374b1cSHaoyuan Fengimport xiangshan.backend.fu.util.HasCSRConst
26a0301c0dSLemover
27445d5c05SLemoverimport scala.math.min
28445d5c05SLemover
29f9ac118cSHaoyuan Feng// For Direct-map TLBs, we do not use it now
3003efd994Shappy-lxclass BankedAsyncDataModuleTemplateWithDup[T <: Data](
3103efd994Shappy-lx  gen: T,
3203efd994Shappy-lx  numEntries: Int,
3303efd994Shappy-lx  numRead: Int,
3403efd994Shappy-lx  numDup: Int,
3503efd994Shappy-lx  numBanks: Int
3603efd994Shappy-lx) extends Module {
3703efd994Shappy-lx  val io = IO(new Bundle {
3803efd994Shappy-lx    val raddr = Vec(numRead, Input(UInt(log2Ceil(numEntries).W)))
3903efd994Shappy-lx    val rdata = Vec(numRead, Vec(numDup, Output(gen)))
4003efd994Shappy-lx    val wen   = Input(Bool())
4103efd994Shappy-lx    val waddr = Input(UInt(log2Ceil(numEntries).W))
4203efd994Shappy-lx    val wdata = Input(gen)
4303efd994Shappy-lx  })
4403efd994Shappy-lx  require(numBanks > 1)
4503efd994Shappy-lx  require(numEntries > numBanks)
4603efd994Shappy-lx
4703efd994Shappy-lx  val numBankEntries = numEntries / numBanks
4803efd994Shappy-lx  def bankOffset(address: UInt): UInt = {
4903efd994Shappy-lx    address(log2Ceil(numBankEntries) - 1, 0)
5003efd994Shappy-lx  }
5103efd994Shappy-lx
5203efd994Shappy-lx  def bankIndex(address: UInt): UInt = {
5303efd994Shappy-lx    address(log2Ceil(numEntries) - 1, log2Ceil(numBankEntries))
5403efd994Shappy-lx  }
5503efd994Shappy-lx
5603efd994Shappy-lx  val dataBanks = Seq.tabulate(numBanks)(i => {
5703efd994Shappy-lx    val bankEntries = if (i < numBanks - 1) numBankEntries else (numEntries - (i * numBankEntries))
5803efd994Shappy-lx    Mem(bankEntries, gen)
5903efd994Shappy-lx  })
6003efd994Shappy-lx
6103efd994Shappy-lx  // async read, but regnext
6203efd994Shappy-lx  for (i <- 0 until numRead) {
6303efd994Shappy-lx    val data_read = Reg(Vec(numDup, Vec(numBanks, gen)))
6403efd994Shappy-lx    val bank_index = Reg(Vec(numDup, UInt(numBanks.W)))
6503efd994Shappy-lx    for (j <- 0 until numDup) {
6603efd994Shappy-lx      bank_index(j) := UIntToOH(bankIndex(io.raddr(i)))
6703efd994Shappy-lx      for (k <- 0 until numBanks) {
6803efd994Shappy-lx        data_read(j)(k) := Mux(io.wen && (io.waddr === io.raddr(i)),
6903efd994Shappy-lx          io.wdata, dataBanks(k)(bankOffset(io.raddr(i))))
7003efd994Shappy-lx      }
7103efd994Shappy-lx    }
7203efd994Shappy-lx    // next cycle
7303efd994Shappy-lx    for (j <- 0 until numDup) {
7403efd994Shappy-lx      io.rdata(i)(j) := Mux1H(bank_index(j), data_read(j))
7503efd994Shappy-lx    }
7603efd994Shappy-lx  }
7703efd994Shappy-lx
7803efd994Shappy-lx  // write
7903efd994Shappy-lx  for (i <- 0 until numBanks) {
8003efd994Shappy-lx    when (io.wen && (bankIndex(io.waddr) === i.U)) {
8103efd994Shappy-lx      dataBanks(i)(bankOffset(io.waddr)) := io.wdata
8203efd994Shappy-lx    }
8303efd994Shappy-lx  }
8403efd994Shappy-lx}
8503efd994Shappy-lx
86a0301c0dSLemoverclass TLBFA(
87cb8f2f2aSLemover  parentName: String,
88a0301c0dSLemover  ports: Int,
89f9ac118cSHaoyuan Feng  nDups: Int,
90a0301c0dSLemover  nSets: Int,
91a0301c0dSLemover  nWays: Int,
925cf62c1aSLemover  saveLevel: Boolean = false,
93a0301c0dSLemover  normalPage: Boolean,
94a0301c0dSLemover  superPage: Boolean
951ca0e4f3SYinan Xu)(implicit p: Parameters) extends TlbModule with HasPerfEvents {
96a0301c0dSLemover
97f9ac118cSHaoyuan Feng  val io = IO(new TlbStorageIO(nSets, nWays, ports, nDups))
98a0301c0dSLemover  io.r.req.map(_.ready := true.B)
99a0301c0dSLemover
100a0301c0dSLemover  val v = RegInit(VecInit(Seq.fill(nWays)(false.B)))
101b0fa7106SHaoyuan Feng  val entries = Reg(Vec(nWays, new TlbSectorEntry(normalPage, superPage)))
102a0301c0dSLemover  val g = entries.map(_.perm.g)
103a0301c0dSLemover
104a0301c0dSLemover  for (i <- 0 until ports) {
105a0301c0dSLemover    val req = io.r.req(i)
106a0301c0dSLemover    val resp = io.r.resp(i)
1073889e11eSLemover    val access = io.access(i)
108a0301c0dSLemover
109a0301c0dSLemover    val vpn = req.bits.vpn
110b436d3b6Speixiaokun    val vpn_reg = RegEnable(vpn, req.fire)
111d0de7e4aSpeixiaokun    val hasS2xlate = req.bits.s2xlate =/= noS2xlate
112d0de7e4aSpeixiaokun    val OnlyS2 = req.bits.s2xlate === onlyStage2
11386b5ba4aSpeixiaokun    val OnlyS1 = req.bits.s2xlate === onlyStage1
114f1fe8698SLemover    val refill_mask = Mux(io.w.valid, UIntToOH(io.w.bits.wayIdx), 0.U(nWays.W))
115d0de7e4aSpeixiaokun    val hitVec = VecInit((entries.zipWithIndex).zip(v zip refill_mask.asBools).map{
116d0de7e4aSpeixiaokun      case (e, m) => {
117d0de7e4aSpeixiaokun        val s2xlate_hit = e._1.s2xlate === req.bits.s2xlate
11897929664SXiaokun-Pei        val hit = e._1.hit(vpn, Mux(hasS2xlate, io.csr.vsatp.asid, io.csr.satp.asid), vmid = io.csr.hgatp.vmid, hasS2xlate = hasS2xlate, onlyS2 = OnlyS2, onlyS1 = OnlyS1)
11982978df9Speixiaokun        s2xlate_hit && hit && m._1 && !m._2
120d0de7e4aSpeixiaokun      }
121d0de7e4aSpeixiaokun    })
122a0301c0dSLemover
123a0301c0dSLemover    hitVec.suggestName("hitVec")
124a0301c0dSLemover
125f9ac118cSHaoyuan Feng    val hitVecReg = RegEnable(hitVec, req.fire)
12663632028SHaoyuan Feng    // Sector tlb may trigger multi-hit, see def "wbhit"
12763632028SHaoyuan Feng    XSPerfAccumulate(s"port${i}_multi_hit", !(!resp.valid || (PopCount(hitVecReg) === 0.U || PopCount(hitVecReg) === 1.U)))
128a0301c0dSLemover
1295adc4829SYanqin Li    resp.valid := GatedValidRegNext(req.valid)
130a0301c0dSLemover    resp.bits.hit := Cat(hitVecReg).orR
131*16534be3Scz4e    val reqVpn   = RegEnable(vpn, 0.U, req.fire)
132*16534be3Scz4e    val pbmt     = entries.map(_.pbmt)
133*16534be3Scz4e    val gpbmt    = entries.map(_.g_pbmt)
134*16534be3Scz4e    val perm     = entries.map(_.perm)
135*16534be3Scz4e    val gPerm    = entries.map(_.g_perm)
136*16534be3Scz4e    val s2xLate  = entries.map(_.s2xlate)
1375cf62c1aSLemover    if (nWays == 1) {
138f9ac118cSHaoyuan Feng      for (d <- 0 until nDups) {
139*16534be3Scz4e        resp.bits.ppn(d) := entries(0).genPPN(saveLevel, resp.valid)(reqVpn)
140*16534be3Scz4e        resp.bits.pbmt(d) := pbmt(0)
141*16534be3Scz4e        resp.bits.g_pbmt(d) := gpbmt(0)
142*16534be3Scz4e        resp.bits.perm(d) := perm(0)
143*16534be3Scz4e        resp.bits.g_perm(d) := gPerm(0)
14498b3f67fSweiding liu        resp.bits.s2xlate(d) := s2xLate(0)
145f9ac118cSHaoyuan Feng      }
1465cf62c1aSLemover    } else {
147f9ac118cSHaoyuan Feng      for (d <- 0 until nDups) {
148*16534be3Scz4e        resp.bits.ppn(d) := Mux1H(hitVecReg zip entries.map(_.genPPN(saveLevel, resp.valid)(reqVpn)))
149*16534be3Scz4e        resp.bits.pbmt(d) := Mux1H(hitVecReg zip pbmt)
150*16534be3Scz4e        resp.bits.g_pbmt(d) := Mux1H(hitVecReg zip gpbmt)
151*16534be3Scz4e        resp.bits.perm(d) := Mux1H(hitVecReg zip perm)
152*16534be3Scz4e        resp.bits.g_perm(d) := Mux1H(hitVecReg zip gPerm)
15398b3f67fSweiding liu        resp.bits.s2xlate(d) := Mux1H(hitVecReg zip s2xLate)
154f9ac118cSHaoyuan Feng      }
1555cf62c1aSLemover    }
1563889e11eSLemover
15763632028SHaoyuan Feng    access.sets := get_set_idx(vpn_reg(vpn_reg.getWidth - 1, sectortlbwidth), nSets) // no use
1583889e11eSLemover    access.touch_ways.valid := resp.valid && Cat(hitVecReg).orR
1593889e11eSLemover    access.touch_ways.bits := OHToUInt(hitVecReg)
160a0301c0dSLemover
161a0301c0dSLemover    resp.bits.hit.suggestName("hit")
162a0301c0dSLemover    resp.bits.ppn.suggestName("ppn")
163002c10a4SYanqin Li    resp.bits.pbmt.suggestName("pbmt")
164002c10a4SYanqin Li    resp.bits.g_pbmt.suggestName("g_pbmt")
165a0301c0dSLemover    resp.bits.perm.suggestName("perm")
166d0de7e4aSpeixiaokun    resp.bits.g_perm.suggestName("g_perm")
167a0301c0dSLemover  }
168a0301c0dSLemover
169a0301c0dSLemover  when (io.w.valid) {
170a0301c0dSLemover    v(io.w.bits.wayIdx) := true.B
171496c751cSpeixiaokun    entries(io.w.bits.wayIdx).apply(io.w.bits.data)
172a0301c0dSLemover  }
17363632028SHaoyuan Feng  // write assert, should not duplicate with the existing entries
174d6b32cb0SHaoyuan Feng  val w_hit_vec = VecInit(entries.zip(v).map{case (e, vi) => e.wbhit(io.w.bits.data, Mux(io.w.bits.data.s2xlate =/= noS2xlate, io.csr.vsatp.asid, io.csr.satp.asid), io.csr.hgatp.vmid, s2xlate = io.w.bits.data.s2xlate) && vi })
1759930e66fSLemover  XSError(io.w.valid && Cat(w_hit_vec).orR, s"${parentName} refill, duplicate with existing entries")
176a0301c0dSLemover
1775adc4829SYanqin Li  val refill_vpn_reg = RegEnable(io.w.bits.data.s1.entry.tag, io.w.valid)
1785adc4829SYanqin Li  val refill_wayIdx_reg = RegEnable(io.w.bits.wayIdx, io.w.valid)
1795adc4829SYanqin Li  when (GatedValidRegNext(io.w.valid)) {
1803889e11eSLemover    io.access.map { access =>
1813889e11eSLemover      access.sets := get_set_idx(refill_vpn_reg, nSets)
1823889e11eSLemover      access.touch_ways.valid := true.B
1833889e11eSLemover      access.touch_ways.bits := refill_wayIdx_reg
1843889e11eSLemover    }
1853889e11eSLemover  }
1863889e11eSLemover
187a0301c0dSLemover  val sfence = io.sfence
188d0de7e4aSpeixiaokun  val sfence_valid = sfence.valid && !sfence.bits.hg && !sfence.bits.hv
189d0de7e4aSpeixiaokun  val sfence_vpn = sfence.bits.addr(VAddrBits - 1, offLen)
19097929664SXiaokun-Pei  val sfenceHit = entries.map(_.hit(sfence_vpn, sfence.bits.id, vmid = io.csr.hgatp.vmid, hasS2xlate = io.csr.priv.virt))
19197929664SXiaokun-Pei  val sfenceHit_noasid = entries.map(_.hit(sfence_vpn, sfence.bits.id, ignoreAsid = true, vmid = io.csr.hgatp.vmid, hasS2xlate = io.csr.priv.virt))
19263632028SHaoyuan Feng  // Sfence will flush all sectors of an entry when hit
193d0de7e4aSpeixiaokun  when (sfence_valid) {
194a0301c0dSLemover    when (sfence.bits.rs1) { // virtual address *.rs1 <- (rs1===0.U)
195a0301c0dSLemover      when (sfence.bits.rs2) { // asid, but i do not want to support asid, *.rs2 <- (rs2===0.U)
196a0301c0dSLemover        // all addr and all asid
19782978df9Speixiaokun        v.zipWithIndex.map{ case(a, i) => a := a && !((io.csr.priv.virt === false.B && entries(i).s2xlate === noS2xlate) ||
19897929664SXiaokun-Pei          (io.csr.priv.virt && entries(i).s2xlate =/= noS2xlate && entries(i).vmid === io.csr.hgatp.vmid))}
199a0301c0dSLemover      }.otherwise {
200a0301c0dSLemover        // all addr but specific asid
20182978df9Speixiaokun        v.zipWithIndex.map{ case (a, i) => a := a && !(!g(i) && ((!io.csr.priv.virt && entries(i).s2xlate === noS2xlate && entries(i).asid === sfence.bits.id) ||
20297929664SXiaokun-Pei          (io.csr.priv.virt && entries(i).s2xlate =/= noS2xlate && entries(i).asid === sfence.bits.id && entries(i).vmid === io.csr.hgatp.vmid)))}
203a0301c0dSLemover      }
204a0301c0dSLemover    }.otherwise {
205a0301c0dSLemover      when (sfence.bits.rs2) {
206a0301c0dSLemover        // specific addr but all asid
20745f497a4Shappy-lx        v.zipWithIndex.map{ case (a, i) => a := a & !sfenceHit_noasid(i) }
208a0301c0dSLemover      }.otherwise {
209a0301c0dSLemover        // specific addr and specific asid
210a0301c0dSLemover        v.zipWithIndex.map{ case (a, i) => a := a & !(sfenceHit(i) && !g(i)) }
211a0301c0dSLemover      }
212a0301c0dSLemover    }
213a0301c0dSLemover  }
214a0301c0dSLemover
215d0de7e4aSpeixiaokun  val hfencev_valid = sfence.valid && sfence.bits.hv
216d0de7e4aSpeixiaokun  val hfenceg_valid = sfence.valid && sfence.bits.hg
217d0de7e4aSpeixiaokun  val hfencev = io.sfence
218d0de7e4aSpeixiaokun  val hfencev_vpn = sfence_vpn
21997929664SXiaokun-Pei  val hfencevHit = entries.map(_.hit(hfencev_vpn, hfencev.bits.id, vmid = io.csr.hgatp.vmid, hasS2xlate = true.B))
22097929664SXiaokun-Pei  val hfencevHit_noasid = entries.map(_.hit(hfencev_vpn, 0.U, ignoreAsid = true, vmid = io.csr.hgatp.vmid, hasS2xlate = true.B))
221d0de7e4aSpeixiaokun  when (hfencev_valid) {
222d0de7e4aSpeixiaokun    when (hfencev.bits.rs1) {
223d0de7e4aSpeixiaokun      when (hfencev.bits.rs2) {
22497929664SXiaokun-Pei        v.zipWithIndex.map { case (a, i) => a := a && !(entries(i).s2xlate =/= noS2xlate && entries(i).vmid === io.csr.hgatp.vmid)}
225d0de7e4aSpeixiaokun      }.otherwise {
22697929664SXiaokun-Pei        v.zipWithIndex.map { case (a, i) => a := a && !(!g(i) && (entries(i).s2xlate =/= noS2xlate && entries(i).asid === sfence.bits.id && entries(i).vmid === io.csr.hgatp.vmid))
227d0de7e4aSpeixiaokun        }
228d0de7e4aSpeixiaokun      }
229d0de7e4aSpeixiaokun    }.otherwise {
230d0de7e4aSpeixiaokun      when (hfencev.bits.rs2) {
231d0de7e4aSpeixiaokun        v.zipWithIndex.map{ case (a, i) => a := a && !hfencevHit_noasid(i) }
232d0de7e4aSpeixiaokun      }.otherwise {
233d0de7e4aSpeixiaokun        v.zipWithIndex.map{ case (a, i) => a := a && !(hfencevHit(i) && !g(i)) }
234d0de7e4aSpeixiaokun      }
235d0de7e4aSpeixiaokun    }
236d0de7e4aSpeixiaokun  }
237d0de7e4aSpeixiaokun
238d0de7e4aSpeixiaokun
239d0de7e4aSpeixiaokun  val hfenceg = io.sfence
240887df0f4Speixiaokun  val hfenceg_gvpn = (sfence.bits.addr << 2)(VAddrBits - 1, offLen)
241d0de7e4aSpeixiaokun  when (hfenceg_valid) {
242d0de7e4aSpeixiaokun    when(hfenceg.bits.rs2) {
24382978df9Speixiaokun      v.zipWithIndex.map { case (a, i) => a := a && !(entries(i).s2xlate =/= noS2xlate) }
244d0de7e4aSpeixiaokun    }.otherwise {
24582978df9Speixiaokun      v.zipWithIndex.map { case (a, i) => a := a && !(entries(i).s2xlate =/= noS2xlate && entries(i).vmid === sfence.bits.id) }
246d0de7e4aSpeixiaokun    }
247d0de7e4aSpeixiaokun  }
248d0de7e4aSpeixiaokun
249935edac4STang Haojin  XSPerfAccumulate(s"access", io.r.resp.map(_.valid.asUInt).fold(0.U)(_ + _))
250935edac4STang Haojin  XSPerfAccumulate(s"hit", io.r.resp.map(a => a.valid && a.bits.hit).fold(0.U)(_.asUInt + _.asUInt))
251a0301c0dSLemover
252a0301c0dSLemover  for (i <- 0 until nWays) {
2533889e11eSLemover    XSPerfAccumulate(s"access${i}", io.r.resp.zip(io.access.map(acc => UIntToOH(acc.touch_ways.bits))).map{ case (a, b) =>
254935edac4STang Haojin      a.valid && a.bits.hit && b(i)}.fold(0.U)(_.asUInt + _.asUInt))
255a0301c0dSLemover  }
256a0301c0dSLemover  for (i <- 0 until nWays) {
257a0301c0dSLemover    XSPerfAccumulate(s"refill${i}", io.w.valid && io.w.bits.wayIdx === i.U)
258a0301c0dSLemover  }
259a0301c0dSLemover
260cd365d4cSrvcoresjw  val perfEvents = Seq(
261935edac4STang Haojin    ("tlbstore_access", io.r.resp.map(_.valid.asUInt).fold(0.U)(_ + _)                            ),
262935edac4STang Haojin    ("tlbstore_hit   ", io.r.resp.map(a => a.valid && a.bits.hit).fold(0.U)(_.asUInt + _.asUInt)),
263cd365d4cSrvcoresjw  )
2641ca0e4f3SYinan Xu  generatePerfEvent()
265cd365d4cSrvcoresjw
266cb8f2f2aSLemover  println(s"${parentName} tlb_fa: nSets${nSets} nWays:${nWays}")
267a0301c0dSLemover}
268a0301c0dSLemover
269f9ac118cSHaoyuan Fengclass TLBFakeFA(
270a0301c0dSLemover             ports: Int,
27103efd994Shappy-lx             nDups: Int,
272a0301c0dSLemover             nSets: Int,
273a0301c0dSLemover             nWays: Int,
274e0374b1cSHaoyuan Feng             useDmode: Boolean = false
275e0374b1cSHaoyuan Feng           )(implicit p: Parameters) extends TlbModule with HasCSRConst{
276e0374b1cSHaoyuan Feng
277f9ac118cSHaoyuan Feng  val io = IO(new TlbStorageIO(nSets, nWays, ports, nDups))
278e0374b1cSHaoyuan Feng  io.r.req.map(_.ready := true.B)
279e0374b1cSHaoyuan Feng  val mode = if (useDmode) io.csr.priv.dmode else io.csr.priv.imode
280e0374b1cSHaoyuan Feng  val vmEnable = if (EnbaleTlbDebug) (io.csr.satp.mode === 8.U)
281e0374b1cSHaoyuan Feng    else (io.csr.satp.mode === 8.U && (mode < ModeM))
282e0374b1cSHaoyuan Feng
283e0374b1cSHaoyuan Feng  for (i <- 0 until ports) {
284e0374b1cSHaoyuan Feng    val req = io.r.req(i)
285e0374b1cSHaoyuan Feng    val resp = io.r.resp(i)
286e0374b1cSHaoyuan Feng
287e0374b1cSHaoyuan Feng    val helper = Module(new PTEHelper())
288e0374b1cSHaoyuan Feng    helper.clock := clock
289e0374b1cSHaoyuan Feng    helper.satp := io.csr.satp.ppn
290e0374b1cSHaoyuan Feng    helper.enable := req.fire && vmEnable
291e0374b1cSHaoyuan Feng    helper.vpn := req.bits.vpn
292e0374b1cSHaoyuan Feng
293e0374b1cSHaoyuan Feng    val pte = helper.pte.asTypeOf(new PteBundle)
294e0374b1cSHaoyuan Feng    val ppn = pte.ppn
2955adc4829SYanqin Li    val vpn_reg = RegEnable(req.bits.vpn, req.valid)
296e0374b1cSHaoyuan Feng    val pf = helper.pf
297e0374b1cSHaoyuan Feng    val level = helper.level
298e0374b1cSHaoyuan Feng
2995adc4829SYanqin Li    resp.valid := GatedValidRegNext(req.valid)
300e0374b1cSHaoyuan Feng    resp.bits.hit := true.B
301f9ac118cSHaoyuan Feng    for (d <- 0 until nDups) {
302f9ac118cSHaoyuan Feng      resp.bits.perm(d).pf := pf
303f9ac118cSHaoyuan Feng      resp.bits.perm(d).af := false.B
304f9ac118cSHaoyuan Feng      resp.bits.perm(d).d := pte.perm.d
305f9ac118cSHaoyuan Feng      resp.bits.perm(d).a := pte.perm.a
306f9ac118cSHaoyuan Feng      resp.bits.perm(d).g := pte.perm.g
307f9ac118cSHaoyuan Feng      resp.bits.perm(d).u := pte.perm.u
308f9ac118cSHaoyuan Feng      resp.bits.perm(d).x := pte.perm.x
309f9ac118cSHaoyuan Feng      resp.bits.perm(d).w := pte.perm.w
310f9ac118cSHaoyuan Feng      resp.bits.perm(d).r := pte.perm.r
311002c10a4SYanqin Li      resp.bits.pbmt(d) := pte.pbmt
31245f43e6eSTang Haojin      resp.bits.ppn(d) := MuxLookup(level, 0.U)(Seq(
313e0374b1cSHaoyuan Feng        0.U -> Cat(ppn(ppn.getWidth-1, vpnnLen*2), vpn_reg(vpnnLen*2-1, 0)),
314e0374b1cSHaoyuan Feng        1.U -> Cat(ppn(ppn.getWidth-1, vpnnLen), vpn_reg(vpnnLen-1, 0)),
315e0374b1cSHaoyuan Feng        2.U -> ppn)
316e0374b1cSHaoyuan Feng      )
317e0374b1cSHaoyuan Feng    }
318e0374b1cSHaoyuan Feng  }
319e0374b1cSHaoyuan Feng
320e0374b1cSHaoyuan Feng  io.access := DontCare
321e0374b1cSHaoyuan Feng}
322e0374b1cSHaoyuan Feng
323a0301c0dSLemoverobject TlbStorage {
324a0301c0dSLemover  def apply
325a0301c0dSLemover  (
326cb8f2f2aSLemover    parentName: String,
327a0301c0dSLemover    associative: String,
328a0301c0dSLemover    ports: Int,
32903efd994Shappy-lx    nDups: Int = 1,
330a0301c0dSLemover    nSets: Int,
331a0301c0dSLemover    nWays: Int,
3325cf62c1aSLemover    saveLevel: Boolean = false,
333a0301c0dSLemover    normalPage: Boolean,
334e0374b1cSHaoyuan Feng    superPage: Boolean,
335e0374b1cSHaoyuan Feng    useDmode: Boolean,
336e0374b1cSHaoyuan Feng    SoftTLB: Boolean
337a0301c0dSLemover  )(implicit p: Parameters) = {
338e0374b1cSHaoyuan Feng    if (SoftTLB) {
339f9ac118cSHaoyuan Feng      val storage = Module(new TLBFakeFA(ports, nDups, nSets, nWays, useDmode))
340f9ac118cSHaoyuan Feng      storage.suggestName(s"${parentName}_fake_fa")
341e0374b1cSHaoyuan Feng      storage.io
342e0374b1cSHaoyuan Feng    } else {
343f9ac118cSHaoyuan Feng       val storage = Module(new TLBFA(parentName, ports, nDups, nSets, nWays, saveLevel, normalPage, superPage))
344cb8f2f2aSLemover       storage.suggestName(s"${parentName}_fa")
345a0301c0dSLemover       storage.io
346a0301c0dSLemover    }
347a0301c0dSLemover  }
348e0374b1cSHaoyuan Feng}
349f1fe8698SLemover
35003efd994Shappy-lxclass TlbStorageWrapper(ports: Int, q: TLBParameters, nDups: Int = 1)(implicit p: Parameters) extends TlbModule {
35103efd994Shappy-lx  val io = IO(new TlbStorageWrapperIO(ports, q, nDups))
352f1fe8698SLemover
353f9ac118cSHaoyuan Feng  val page = TlbStorage(
354f9ac118cSHaoyuan Feng    parentName = q.name + "_storage",
355f9ac118cSHaoyuan Feng    associative = q.Associative,
356f1fe8698SLemover    ports = ports,
35703efd994Shappy-lx    nDups = nDups,
358f9ac118cSHaoyuan Feng    nSets = q.NSets,
359f9ac118cSHaoyuan Feng    nWays = q.NWays,
360f1fe8698SLemover    normalPage = true,
361f1fe8698SLemover    superPage = true,
362e0374b1cSHaoyuan Feng    useDmode = q.useDmode,
363e0374b1cSHaoyuan Feng    SoftTLB = coreParams.softTLB
364f1fe8698SLemover  )
365f1fe8698SLemover
366f1fe8698SLemover  for (i <- 0 until ports) {
367f9ac118cSHaoyuan Feng    page.r_req_apply(
368f1fe8698SLemover      valid = io.r.req(i).valid,
369f1fe8698SLemover      vpn = io.r.req(i).bits.vpn,
370d0de7e4aSpeixiaokun      i = i,
371d0de7e4aSpeixiaokun      s2xlate = io.r.req(i).bits.s2xlate
372f1fe8698SLemover    )
373f1fe8698SLemover  }
374f1fe8698SLemover
375f1fe8698SLemover  for (i <- 0 until ports) {
376f9ac118cSHaoyuan Feng    val q = page.r.req(i)
377f9ac118cSHaoyuan Feng    val p = page.r.resp(i)
378f1fe8698SLemover    val rq = io.r.req(i)
379f1fe8698SLemover    val rp = io.r.resp(i)
380f9ac118cSHaoyuan Feng    rq.ready := q.ready // actually, not used
381f9ac118cSHaoyuan Feng    rp.valid := p.valid // actually, not used
382f9ac118cSHaoyuan Feng    rp.bits.hit := p.bits.hit
38303efd994Shappy-lx    for (d <- 0 until nDups) {
384f9ac118cSHaoyuan Feng      rp.bits.ppn(d) := p.bits.ppn(d)
385f9ac118cSHaoyuan Feng      rp.bits.perm(d).pf := p.bits.perm(d).pf
386f9ac118cSHaoyuan Feng      rp.bits.perm(d).af := p.bits.perm(d).af
3877acf8b76SXiaokun-Pei      rp.bits.perm(d).v := p.bits.perm(d).v
388f9ac118cSHaoyuan Feng      rp.bits.perm(d).d := p.bits.perm(d).d
389f9ac118cSHaoyuan Feng      rp.bits.perm(d).a := p.bits.perm(d).a
390f9ac118cSHaoyuan Feng      rp.bits.perm(d).g := p.bits.perm(d).g
391f9ac118cSHaoyuan Feng      rp.bits.perm(d).u := p.bits.perm(d).u
392f9ac118cSHaoyuan Feng      rp.bits.perm(d).x := p.bits.perm(d).x
393f9ac118cSHaoyuan Feng      rp.bits.perm(d).w := p.bits.perm(d).w
394f9ac118cSHaoyuan Feng      rp.bits.perm(d).r := p.bits.perm(d).r
395b436d3b6Speixiaokun      rp.bits.s2xlate(d) := p.bits.s2xlate(d)
396b436d3b6Speixiaokun      rp.bits.g_perm(d) := p.bits.g_perm(d)
397002c10a4SYanqin Li      rp.bits.pbmt(d) := p.bits.pbmt(d)
398002c10a4SYanqin Li      rp.bits.g_pbmt(d) := p.bits.g_pbmt(d)
39903efd994Shappy-lx    }
400f1fe8698SLemover  }
401f1fe8698SLemover
402f9ac118cSHaoyuan Feng  page.sfence <> io.sfence
403f9ac118cSHaoyuan Feng  page.csr <> io.csr
404f1fe8698SLemover
405f9ac118cSHaoyuan Feng  val refill_idx = if (q.outReplace) {
406f9ac118cSHaoyuan Feng    io.replace.page.access <> page.access
407f9ac118cSHaoyuan Feng    io.replace.page.chosen_set := DontCare
408f9ac118cSHaoyuan Feng    io.replace.page.refillIdx
409f1fe8698SLemover  } else {
410f9ac118cSHaoyuan Feng    val re = ReplacementPolicy.fromString(q.Replacer, q.NWays)
411f9ac118cSHaoyuan Feng    re.access(page.access.map(_.touch_ways))
412f1fe8698SLemover    re.way
413f1fe8698SLemover  }
414f1fe8698SLemover
415f9ac118cSHaoyuan Feng  page.w_apply(
416f9ac118cSHaoyuan Feng    valid = io.w.valid,
417f9ac118cSHaoyuan Feng    wayIdx = refill_idx,
418f9ac118cSHaoyuan Feng    data = io.w.bits.data
419f1fe8698SLemover  )
420f1fe8698SLemover
421f1fe8698SLemover    // replacement
422f1fe8698SLemover  def get_access(one_hot: UInt, valid: Bool): Valid[UInt] = {
423f1fe8698SLemover    val res = Wire(Valid(UInt(log2Up(one_hot.getWidth).W)))
424f1fe8698SLemover    res.valid := Cat(one_hot).orR && valid
425f1fe8698SLemover    res.bits := OHToUInt(one_hot)
426f1fe8698SLemover    res
427f1fe8698SLemover  }
428f1fe8698SLemover}
429