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