1/*************************************************************************************** 2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3* Copyright (c) 2020-2021 Peng Cheng Laboratory 4* 5* XiangShan is licensed under Mulan PSL v2. 6* You can use this software according to the terms and conditions of the Mulan PSL v2. 7* You may obtain a copy of Mulan PSL v2 at: 8* http://license.coscl.org.cn/MulanPSL2 9* 10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13* 14* See the Mulan PSL v2 for more details. 15***************************************************************************************/ 16 17package xiangshan.cache.mmu 18 19import org.chipsalliance.cde.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import xiangshan._ 23import utils._ 24import utility._ 25import xiangshan.backend.rob.RobPtr 26import xiangshan.backend.fu.util.HasCSRConst 27import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} 28import freechips.rocketchip.tilelink._ 29import xiangshan.backend.fu.{PMPReqBundle, PMPConfig} 30import xiangshan.backend.fu.PMPBundle 31 32 33abstract class TlbBundle(implicit p: Parameters) extends XSBundle with HasTlbConst 34abstract class TlbModule(implicit p: Parameters) extends XSModule with HasTlbConst 35 36 37class PtePermBundle(implicit p: Parameters) extends TlbBundle { 38 val d = Bool() 39 val a = Bool() 40 val g = Bool() 41 val u = Bool() 42 val x = Bool() 43 val w = Bool() 44 val r = Bool() 45 46 override def toPrintable: Printable = { 47 p"d:${d} a:${a} g:${g} u:${u} x:${x} w:${w} r:${r}"// + 48 //(if(hasV) (p"v:${v}") else p"") 49 } 50} 51 52class TlbPMBundle(implicit p: Parameters) extends TlbBundle { 53 val r = Bool() 54 val w = Bool() 55 val x = Bool() 56 val c = Bool() 57 val atomic = Bool() 58 59 def assign_ap(pm: PMPConfig) = { 60 r := pm.r 61 w := pm.w 62 x := pm.x 63 c := pm.c 64 atomic := pm.atomic 65 } 66} 67 68class TlbPermBundle(implicit p: Parameters) extends TlbBundle { 69 val pf = Bool() // NOTE: if this is true, just raise pf 70 val af = Bool() // NOTE: if this is true, just raise af 71 // pagetable perm (software defined) 72 val d = Bool() 73 val a = Bool() 74 val g = Bool() 75 val u = Bool() 76 val x = Bool() 77 val w = Bool() 78 val r = Bool() 79 80 def apply(item: PtwSectorResp) = { 81 val ptePerm = item.entry.perm.get.asTypeOf(new PtePermBundle().cloneType) 82 this.pf := item.pf 83 this.af := item.af 84 this.d := ptePerm.d 85 this.a := ptePerm.a 86 this.g := ptePerm.g 87 this.u := ptePerm.u 88 this.x := ptePerm.x 89 this.w := ptePerm.w 90 this.r := ptePerm.r 91 92 this 93 } 94 95 def applyS2(item: HptwResp, pm: PMPConfig) = { 96 val ptePerm = item.entry.perm.get.asTypeOf(new PtePermBundle().cloneType) 97 this.pf := item.gpf 98 this.af := item.gaf 99 this.d := ptePerm.d 100 this.a := ptePerm.a 101 this.g := ptePerm.g 102 this.u := ptePerm.u 103 this.x := ptePerm.x 104 this.w := ptePerm.w 105 this.r := ptePerm.r 106 107 this 108 } 109 override def toPrintable: Printable = { 110 p"pf:${pf} af:${af} d:${d} a:${a} g:${g} u:${u} x:${x} w:${w} r:${r} " 111 } 112} 113 114class TlbSectorPermBundle(implicit p: Parameters) extends TlbBundle { 115 val pf = Bool() // NOTE: if this is true, just raise pf 116 val af = Bool() // NOTE: if this is true, just raise af 117 // pagetable perm (software defined) 118 val d = Bool() 119 val a = Bool() 120 val g = Bool() 121 val u = Bool() 122 val x = Bool() 123 val w = Bool() 124 val r = Bool() 125 126 def apply(item: PtwSectorResp) = { 127 val ptePerm = item.entry.perm.get.asTypeOf(new PtePermBundle().cloneType) 128 this.pf := item.pf 129 this.af := item.af 130 this.d := ptePerm.d 131 this.a := ptePerm.a 132 this.g := ptePerm.g 133 this.u := ptePerm.u 134 this.x := ptePerm.x 135 this.w := ptePerm.w 136 this.r := ptePerm.r 137 138 this 139 } 140 override def toPrintable: Printable = { 141 p"pf:${pf} af:${af} d:${d} a:${a} g:${g} u:${u} x:${x} w:${w} r:${r} " 142 } 143} 144 145// multi-read && single-write 146// input is data, output is hot-code(not one-hot) 147class CAMTemplate[T <: Data](val gen: T, val set: Int, val readWidth: Int)(implicit p: Parameters) extends TlbModule { 148 val io = IO(new Bundle { 149 val r = new Bundle { 150 val req = Input(Vec(readWidth, gen)) 151 val resp = Output(Vec(readWidth, Vec(set, Bool()))) 152 } 153 val w = Input(new Bundle { 154 val valid = Bool() 155 val bits = new Bundle { 156 val index = UInt(log2Up(set).W) 157 val data = gen 158 } 159 }) 160 }) 161 162 val wordType = UInt(gen.getWidth.W) 163 val array = Reg(Vec(set, wordType)) 164 165 io.r.resp.zipWithIndex.map{ case (a,i) => 166 a := array.map(io.r.req(i).asUInt === _) 167 } 168 169 when (io.w.valid) { 170 array(io.w.bits.index) := io.w.bits.data.asUInt 171 } 172} 173 174class TlbEntry(pageNormal: Boolean, pageSuper: Boolean)(implicit p: Parameters) extends TlbBundle { 175 require(pageNormal || pageSuper) 176 177 val tag = if (!pageNormal) UInt((vpnLen - vpnnLen).W) 178 else UInt(vpnLen.W) 179 val asid = UInt(asidLen.W) 180 val level = if (!pageNormal) Some(UInt(1.W)) 181 else if (!pageSuper) None 182 else Some(UInt(2.W)) 183 val ppn = if (!pageNormal) UInt((ppnLen - vpnnLen).W) 184 else UInt(ppnLen.W) 185 val perm = new TlbPermBundle 186 187 val ppnS2 = UInt(ppnLen.W) 188 val gvpn = if (!pageNormal) UInt((gvpnLen - vpnnLen).W) 189 else UInt(gvpnLen.W) 190 val g_level = UInt(2.W) 191 val g_perm = new TlbPermBundle 192 val vmid = UInt(vmidLen.W) 193 val s2xlate = UInt(2.U) 194 195 /** s2xlate usage: 196 * bits0 0: disable s2xlate 197 * 1: enable s2xlate 198 * bits1 0: stage 1 and stage 2 if bits0 is 1 199 * 1: Only stage 2 if bits0 is 1 200 * */ 201 202 /** level usage: 203 * !PageSuper: page is only normal, level is None, match all the tag 204 * !PageNormal: page is only super, level is a Bool(), match high 9*2 parts 205 * bits0 0: need mid 9bits 206 * 1: no need mid 9bits 207 * PageSuper && PageNormal: page hold all the three type, 208 * bits0 0: need low 9bits 209 * bits1 0: need mid 9bits 210 */ 211 212 def hit_S2(gvpn_in: UInt, vmid: UInt, ignoreVmid: Boolean = false): Bool = { 213 val vmid_hit = if (ignoreVmid) true.B else this.vmid === vmid 214 val gvpn_match_hi = gvpn(gvpnLen - 1, vpnnLen * 2) === gvpn_in(gvpnLen - 1, vpnnLen * 2) 215 val gvpn_match_mi = gvpn(vpnnLen * 2 - 1, vpnnLen * 1) === gvpn_in(vpnnLen * 2 - 1, vpnnLen * 1) 216 val gvpn_match_lo = gvpn(vpnnLen - 1, 0) === gvpn_in(vpnnLen - 1, 0) 217 vmid_hit && gvpn_match_hi && (g_level(1) || gvpn_match_mi) && (g_level(0) || gvpn_match_lo) 218 } 219 220 def hit(vpn: UInt, asid: UInt, nSets: Int = 1, ignoreAsid: Boolean = false, vmid: UInt, s2xlate: Bool): Bool = { 221 val asid_hit = if (ignoreAsid) true.B else (this.asid === asid) 222 val vmid_hit = Mux(s2xlate, this.vmid === vmid, true.B) 223 224 // NOTE: for timing, dont care low set index bits at hit check 225 // do not need store the low bits actually 226 if (!pageSuper) asid_hit && drop_set_equal(vpn, tag, nSets) && vmid_hit 227 else if (!pageNormal) { 228 val tag_match_hi = tag(vpnnLen*2-1, vpnnLen) === vpn(vpnnLen*3-1, vpnnLen*2) 229 val tag_match_mi = tag(vpnnLen-1, 0) === vpn(vpnnLen*2-1, vpnnLen) 230 val tag_match = tag_match_hi && (level.get.asBool || tag_match_mi) 231 asid_hit && tag_match && vmid_hit 232 } 233 else { 234 val tmp_level = level.get 235 val tag_match_hi = tag(vpnnLen*3-1, vpnnLen*2) === vpn(vpnnLen*3-1, vpnnLen*2) 236 val tag_match_mi = tag(vpnnLen*2-1, vpnnLen) === vpn(vpnnLen*2-1, vpnnLen) 237 val tag_match_lo = tag(vpnnLen-1, 0) === vpn(vpnnLen-1, 0) // if pageNormal is false, this will always be false 238 val tag_match = tag_match_hi && (tmp_level(1) || tag_match_mi) && (tmp_level(0) || tag_match_lo) 239 asid_hit && tag_match && vmid_hit 240 } 241 } 242 243 def apply(item: PtwRespS2, pm: PMPConfig): TlbEntry = { 244 this.tag := {if (pageNormal) Cat(item.s1.entry.tag, OHToUInt(item.s1.pteidx)) else item.s1.entry.tag(sectorvpnLen - 1, vpnnLen - sectortlbwidth)} 245 this.asid := item.s1.entry.asid 246 val inner_level = item.entry.level.getOrElse(0.U) 247 this.level.map(_ := { if (pageNormal && pageSuper) MuxLookup(inner_level, 0.U)(Seq( 248 0.U -> 3.U, 249 1.U -> 1.U, 250 2.U -> 0.U )) 251 else if (pageSuper) ~inner_level(0) 252 else 0.U }) 253 this.ppn := { if (!pageNormal) item.s1.entry.ppn(sectorppnLen - 1, vpnnLen - sectortlbwidth) 254 else Cat(item.s1.entry.ppn, item.s1.ppn_low(OHToUInt(item.s1.pteidx))) } 255 this.perm.apply(item.s1) 256 this.vmid := item.s1.entry.vmid 257 this.gvpn := { if (!pageNormal) item.s2.entry.tag(gvpnLen - 1, vpnnLen) 258 else item.s2.entry.tag} 259 this.g_perm.applyS2(item.s2, pm) 260 this.ppnS2 := item.s2.entry.ppn 261 val g_inner_level = item.s2.entry.level.getOrElse(0.U) 262 this.g_level := { 263 MuxLookup(g_inner_level, 0.U,Seq( 264 0.U -> 3.U, 265 1.U -> 1.U, 266 2.U -> 0.U)) 267 } 268 this 269 } 270 271 // 4KB is normal entry, 2MB/1GB is considered as super entry 272 def is_normalentry(): Bool = { 273 if (!pageSuper) { true.B } 274 else if (!pageNormal) { false.B } 275 else { level.get === 0.U } 276 } 277 278 def genGVPN(saveLevel: Boolean = false, valid: Bool = false.B)(vpn: UInt): UInt = { 279 val inner_level = level.getOrElse(0.U) 280 val gvpn_res = if (!pageSuper) gvpn 281 else if (!pageNormal) Cat(gvpn(gvpnLen - vpnnLen - 1, vpnnLen), 282 Mux(inner_level(0), vpn(vpnnLen * 2 - 1, vpnnLen), gvpn(vpnnLen - 1, 0)), 283 vpn(vpnnLen - 1, 0)) 284 else Cat(gvpn(gvpnLen - 1, vpnnLen * 2), 285 Mux(inner_level(1), vpn(vpnnLen * 2 - 1, vpnnLen), gvpn(vpnnLen * 2 - 1, vpnnLen)), 286 Mux(inner_level(0), vpn(vpnnLen - 1, 0), gvpn(vpnnLen - 1, 0))) 287 288 if (saveLevel) Cat(gvpn(gvpn.getWidth - 1, vpnnLen * 2), RegEnable(gvpn_res(vpnnLen * 2 - 1, 0), valid)) 289 else gvpn_res 290 } 291 292 def genPPNS2(vpn: UInt, gvpn_in: UInt, OnlyS2: Bool) = { 293 val inner_level = level.getOrElse(0.U) 294 val gvpn_tmp = if (!pageSuper) gvpn 295 else if (!pageNormal) Cat(gvpn(gvpnLen - vpnnLen - 1, vpnnLen), 296 Mux(inner_level(0), vpn(vpnnLen * 2 - 1, vpnnLen), gvpn(vpnnLen - 1, 0)), 297 vpn(vpnnLen - 1, 0)) 298 else Cat(gvpn(gvpnLen - 1, vpnnLen * 2), 299 Mux(inner_level(1), vpn(vpnnLen * 2 - 1, vpnnLen), gvpn(vpnnLen * 2 - 1, vpnnLen)), 300 Mux(inner_level(0), vpn(vpnnLen - 1, 0), gvpn(vpnnLen - 1, 0))) 301 302 val gvpn_res = Mux(OnlyS2, gvpn_in, gvpn_tmp) 303 val ppn_res = Cat(ppn(ppnLen - 1, vpnnLen * 2), 304 Mux(g_level(1), gvpn_res(vpnnLen * 2 - 1, vpnnLen), ppn(vpnnLen * 2 - 1, vpnnLen)), 305 Mux(g_level(0), vpn(vpnnLen - 1, 0), ppn(vpnnLen - 1, 0))) 306 307 ppn_res 308 } 309 310 def genPPN(saveLevel: Boolean = false, valid: Bool = false.B)(vpn: UInt) : UInt = { 311 val inner_level = level.getOrElse(0.U) 312 val ppn_res = if (!pageSuper) ppn 313 else if (!pageNormal) Cat(ppn(ppnLen-vpnnLen-1, vpnnLen), 314 Mux(inner_level(0), vpn(vpnnLen*2-1, vpnnLen), ppn(vpnnLen-1,0)), 315 vpn(vpnnLen-1, 0)) 316 else Cat(ppn(ppnLen-1, vpnnLen*2), 317 Mux(inner_level(1), vpn(vpnnLen*2-1, vpnnLen), ppn(vpnnLen*2-1, vpnnLen)), 318 Mux(inner_level(0), vpn(vpnnLen-1, 0), ppn(vpnnLen-1, 0))) 319 320 if (saveLevel) Cat(ppn(ppn.getWidth-1, vpnnLen*2), RegEnable(ppn_res(vpnnLen*2-1, 0), valid)) 321 else ppn_res 322 } 323 324 override def toPrintable: Printable = { 325 val inner_level = level.getOrElse(2.U) 326 p"asid: ${asid} level:${inner_level} vpn:${Hexadecimal(tag)} ppn:${Hexadecimal(ppn)} perm:${perm}" 327 } 328 329} 330 331class TlbSectorEntry(pageNormal: Boolean, pageSuper: Boolean)(implicit p: Parameters) extends TlbBundle { 332 require(pageNormal || pageSuper) 333 334 val tag = if (!pageNormal) UInt((vpnLen - vpnnLen).W) 335 else UInt(sectorvpnLen.W) 336 val asid = UInt(asidLen.W) 337 val level = if (!pageNormal) Some(UInt(1.W)) 338 else if (!pageSuper) None 339 else Some(UInt(2.W)) 340 val ppn = if (!pageNormal) UInt((ppnLen - vpnnLen).W) 341 else UInt(sectorppnLen.W) //only used when disable s2xlate 342 val perm = new TlbSectorPermBundle 343 val valididx = Vec(tlbcontiguous, Bool()) 344 val pteidx = Vec(tlbcontiguous, Bool()) 345 val ppn_low = Vec(tlbcontiguous, UInt(sectortlbwidth.W)) // it is gvpn_low when enable s2xlate 346 347 val ppnS2 = UInt(ppnLen.W) //only used when enable s2xlate 348 val gvpn = if (!pageNormal) UInt((gvpnLen - vpnnLen).W) 349 else UInt(sectorgvpnLen.W) 350 val g_level = UInt(2.W) 351 val g_perm = new TlbPermBundle 352 val vmid = UInt(vmidLen.W) 353 val s2xlate = UInt(2.U) 354 355 /** s2xlate usage: 356 * bits0 0: disable s2xlate 357 * 1: enable s2xlate 358 * bits1 0: stage 1 and stage 2 if bits0 is 1 359 * 1: Only stage 2 if bits0 is 1 360 * */ 361 362 /** level usage: 363 * !PageSuper: page is only normal, level is None, match all the tag 364 * !PageNormal: page is only super, level is a Bool(), match high 9*2 parts 365 * bits0 0: need mid 9bits 366 * 1: no need mid 9bits 367 * PageSuper && PageNormal: page hold all the three type, 368 * bits0 0: need low 9bits 369 * bits1 0: need mid 9bits 370 */ 371 372 // for Only stage 2 translation 373 def hit_S2(gvpn_in: UInt, vmid: UInt, ignoreVmid: Boolean = false): Bool = { 374 val vmid_hit = if (ignoreVmid) true.B else this.vmid === vmid 375 val inner_gvpn = Cat(gvpn, ppn_low(OHToUInt(pteidx))) 376 val gvpn_match_hi = inner_gvpn(gvpnLen - 1, vpnnLen * 2) === gvpn_in(gvpnLen - 1, vpnnLen * 2) 377 val gvpn_match_mi = inner_gvpn(vpnnLen * 2 - 1, vpnnLen * 1) === gvpn_in(vpnnLen * 2 - 1, vpnnLen * 1) 378 val gvpn_match_lo = inner_gvpn(vpnnLen - 1, 0) === gvpn_in(vpnnLen - 1, 0) 379 vmid_hit && gvpn_match_hi && (g_level(1) || gvpn_match_mi) && (g_level(0) || gvpn_match_lo) 380 } 381 382 def hit(vpn: UInt, asid: UInt, nSets: Int = 1, ignoreAsid: Boolean = false, vmid: UInt, s2xlate: Bool): Bool = { 383 val asid_hit = if (ignoreAsid) true.B else (this.asid === asid) 384 val addr_low_hit = valididx(vpn(2, 0)) 385 val vmid_hit = Mux(s2xlate, this.vmid === vmid, true.B) 386 val pteidx_hit = Mux(s2xlate, pteidx(vpn(2, 0)), true.B) // stage 2 pte only map to the stage 1 pte that pteidx point to 387 // NOTE: for timing, dont care low set index bits at hit check 388 // do not need store the low bits actually 389 if (!pageSuper) asid_hit && drop_set_equal(vpn(vpn.getWidth - 1, sectortlbwidth), tag, nSets) && addr_low_hit && vmid_hit && pteidx_hit 390 else if (!pageNormal) { 391 val tag_match_hi = tag(vpnnLen * 2 - 1, vpnnLen) === vpn(vpnnLen * 3 - 1, vpnnLen * 2) 392 val tag_match_mi = tag(vpnnLen - 1, 0) === vpn(vpnnLen * 2 - 1, vpnnLen) 393 val tag_match = tag_match_hi && (level.get.asBool || tag_match_mi) 394 asid_hit && tag_match && addr_low_hit && vmid_hit && pteidx_hit 395 } 396 else { 397 val tmp_level = level.get 398 val tag_match_hi = tag(vpnnLen * 3 - sectortlbwidth - 1, vpnnLen * 2 - sectortlbwidth) === vpn(vpnnLen * 3 - 1, vpnnLen * 2) 399 val tag_match_mi = tag(vpnnLen * 2 - sectortlbwidth - 1, vpnnLen - sectortlbwidth) === vpn(vpnnLen * 2 - 1, vpnnLen) 400 val tag_match_lo = tag(vpnnLen - sectortlbwidth - 1, 0) === vpn(vpnnLen - 1, sectortlbwidth) // if pageNormal is false, this will always be false 401 val tag_match = tag_match_hi && (tmp_level(1) || tag_match_mi) && (tmp_level(0) || tag_match_lo) 402 asid_hit && tag_match && addr_low_hit && vmid_hit && pteidx_hit 403 } 404 } 405 406 def wbhit(data: PtwSectorResp, asid: UInt, nSets: Int = 1, ignoreAsid: Boolean = false): Bool = { 407 val vpn = Cat(data.entry.tag, 0.U(sectortlbwidth.W)) 408 val asid_hit = if (ignoreAsid) true.B else (this.asid === asid) 409 val vpn_hit = Wire(Bool()) 410 val index_hit = Wire(Vec(tlbcontiguous, Bool())) 411 412 // NOTE: for timing, dont care low set index bits at hit check 413 // do not need store the low bits actually 414 if (!pageSuper) { 415 vpn_hit := asid_hit && drop_set_equal(vpn(vpn.getWidth - 1, sectortlbwidth), tag, nSets) 416 } 417 else if (!pageNormal) { 418 val tag_match_hi = tag(vpnnLen * 2 - 1, vpnnLen - sectortlbwidth) === vpn(vpnnLen * 3 - 1, vpnnLen * 2) 419 val tag_match_mi = tag(vpnnLen - 1, 0) === vpn(vpnnLen * 2 - 1, vpnnLen) 420 val tag_match = tag_match_hi && (level.get.asBool || tag_match_mi) 421 vpn_hit := asid_hit && tag_match 422 } 423 else { 424 val tmp_level = level.get 425 val tag_match_hi = tag(vpnnLen * 3 - sectortlbwidth - 1, vpnnLen * 2 - sectortlbwidth) === vpn(vpnnLen * 3 - 1, vpnnLen * 2) 426 val tag_match_mi = tag(vpnnLen * 2 - sectortlbwidth - 1, vpnnLen - sectortlbwidth) === vpn(vpnnLen * 2 - 1, vpnnLen) 427 val tag_match_lo = tag(vpnnLen - sectortlbwidth - 1, 0) === vpn(vpnnLen - 1, sectortlbwidth) // if pageNormal is false, this will always be false 428 val tag_match = tag_match_hi && (tmp_level(1) || tag_match_mi) && (tmp_level(0) || tag_match_lo) 429 vpn_hit := asid_hit && tag_match 430 } 431 432 for (i <- 0 until tlbcontiguous) { 433 index_hit(i) := data.valididx(i) && valididx(i) 434 } 435 436 // For example, tlb req to page cache with vpn 0x10 437 // At this time, 0x13 has not been paged, so page cache only resp 0x10 438 // When 0x13 refill to page cache, previous item will be flushed 439 // Now 0x10 and 0x13 are both valid in page cache 440 // However, when 0x13 refill to tlb, will trigger multi hit 441 // So will only trigger multi-hit when PopCount(data.valididx) = 1 442 vpn_hit && index_hit.reduce(_ || _) && PopCount(data.valididx) === 1.U 443 } 444 445 def apply(item: PtwRespS2): TlbSectorEntry = { 446 this.tag := {if (pageNormal) item.s1.entry.tag else item.s1.entry.tag(sectorvpnLen - 1, vpnnLen - sectortlbwidth)} 447 this.asid := item.s1.entry.asid 448 val inner_level = item.s1.entry.level.getOrElse(0.U) 449 this.level.map(_ := { if (pageNormal && pageSuper) MuxLookup(inner_level, 0.U)(Seq( 450 0.U -> 3.U, 451 1.U -> 1.U, 452 2.U -> 0.U )) 453 else if (pageSuper) ~inner_level(0) 454 else 0.U }) 455 this.ppn := {if (!pageNormal) item.s1.entry.ppn(sectorppnLen - 1, vpnnLen - sectortlbwidth) else item.s1.entry.ppn} 456 this.perm.apply(item.s1) 457 this.ppn_low := item.s1.ppn_low 458 this.valididx := item.s1.valididx 459 this.pteidx := item.s1.pteidx 460 461 this.vmid := item.s1.entry.vmid 462 this.gvpn := {if (!pageNormal) item.s2.entry.tag(sectorgvpnLen - 1, vpnnLen - sectortlbwidth) else item.s2.entry.tag(sectorgvpnLen - 1, sectortlbwidth)} 463 this.g_perm.applyS2(item.s2, pm(0)) 464 this.ppnS2 := item.s2.entry.ppn 465 val g_inner_level = item.s2.entry.level.getOrElse(0.U) 466 this.g_level := { 467 MuxLookup(g_inner_level, 0.U, Seq( 468 0.U -> 3.U, 469 1.U -> 1.U, 470 2.U -> 0.U)) 471 } 472 this 473 } 474 475 // 4KB is normal entry, 2MB/1GB is considered as super entry 476 def is_normalentry(): Bool = { 477 if (!pageSuper) { true.B } 478 else if (!pageNormal) { false.B } 479 else { level.get === 0.U } 480 } 481 482 def genGVPN(saveLevel: Boolean = false, valid: Bool = false.B)(vpn: UInt): UInt = { 483 val inner_level = level.getOrElse(0.U) 484 val gvpn_res = if (!pageSuper) Cat(gvpn, ppn_low(vpn(sectortlbwidth - 1, 0))) 485 else if (!pageNormal) Cat(gvpn(gvpnLen - vpnnLen - 1, vpnnLen), 486 Mux(inner_level(0), vpn(vpnnLen * 2 - 1, vpnnLen), gvpn(vpnnLen - 1, 0)), 487 vpn(vpnnLen - 1, 0)) 488 else Cat(gvpn(sectorgvpnLen - 1, vpnnLen * 2 - sectortlbwidth), 489 Mux(inner_level(1), vpn(vpnnLen * 2 - 1, vpnnLen), gvpn(vpnnLen * 2 - sectortlbwidth - 1, vpnnLen - sectortlbwidth)), 490 Mux(inner_level(0), vpn(vpnnLen - 1, 0), Cat(gvpn(vpnnLen - sectortlbwidth - 1, 0), ppn_low(vpn(sectortlbwidth - 1, 0))))) 491 492 if (saveLevel) { 493 if (gvpn.getWidth == gvpnLen - vpnnLen) { 494 Cat(gvpn(gvpn.getWidth - 1, vpnnLen * 2), RegEnable(gvpn_res(vpnnLen * 2 - 1, 0), valid)) 495 } else { 496 require(gvpn.getWidth == sectorgvpnLen) 497 Cat(gvpn(gvpn.getWidth - 1, vpnnLen * 2 - sectortlbwidth), RegEnable(gvpn_res(vpnnLen * 2 - 1, 0), valid)) 498 } 499 } 500 else gvpn_res 501 } 502 503 def genPPNS2(vpn:UInt, gvpn_in: UInt, OnlyS2: Bool) = { 504 val inner_level = level.getOrElse(0.U) 505 val gvpn_tmp = if (!pageSuper) Cat(gvpn, ppn_low(vpn(sectortlbwidth - 1, 0))) 506 else if (!pageNormal) Cat(gvpn(gvpnLen - vpnnLen - 1, vpnnLen), 507 Mux(inner_level(0), vpn(vpnnLen * 2 - 1, vpnnLen), gvpn(vpnnLen - 1, 0)), 508 vpn(vpnnLen - 1, 0)) 509 else Cat(gvpn(sectorgvpnLen - 1, vpnnLen * 2 - sectortlbwidth), 510 Mux(inner_level(1), vpn(vpnnLen * 2 - 1, vpnnLen), gvpn(vpnnLen * 2 - sectortlbwidth - 1, vpnnLen - sectortlbwidth)), 511 Mux(inner_level(0), vpn(vpnnLen - 1, 0), Cat(gvpn(vpnnLen - sectortlbwidth - 1, 0), ppn_low(vpn(sectortlbwidth - 1, 0))))) 512 513 val gvpn_res = Mux(OnlyS2, gvpn_in, gvpn_tmp) 514 val ppn_res = Cat(ppn(ppnLen - 1, vpnnLen * 2), 515 Mux(g_level(1), gvpn_res(vpnnLen * 2 - 1, vpnnLen), ppn(vpnnLen * 2 - 1, vpnnLen)), 516 Mux(g_level(0), vpn(vpnnLen - 1, 0), ppn(vpnnLen - 1, 0))) 517 518 ppn_res 519 } 520 521 def genPPN(saveLevel: Boolean = false, valid: Bool = false.B)(vpn: UInt) : UInt = { 522 val inner_level = level.getOrElse(0.U) 523 val ppn_res = if (!pageSuper) Cat(ppn, ppn_low(vpn(sectortlbwidth - 1, 0))) 524 else if (!pageNormal) Cat(ppn(ppnLen - vpnnLen - 1, vpnnLen), 525 Mux(inner_level(0), vpn(vpnnLen * 2 - 1, vpnnLen), ppn(vpnnLen - 1,0)), 526 vpn(vpnnLen - 1, 0)) 527 else Cat(ppn(sectorppnLen - 1, vpnnLen * 2 - sectortlbwidth), 528 Mux(inner_level(1), vpn(vpnnLen * 2 - 1, vpnnLen), ppn(vpnnLen * 2 - sectortlbwidth - 1, vpnnLen - sectortlbwidth)), 529 Mux(inner_level(0), vpn(vpnnLen - 1, 0), Cat(ppn(vpnnLen - sectortlbwidth - 1, 0), ppn_low(vpn(sectortlbwidth - 1, 0))))) 530 531 if (saveLevel) { 532 if (ppn.getWidth == ppnLen - vpnnLen) { 533 Cat(ppn(ppn.getWidth - 1, vpnnLen * 2), RegEnable(ppn_res(vpnnLen * 2 - 1, 0), valid)) 534 } else { 535 require(ppn.getWidth == sectorppnLen) 536 Cat(ppn(ppn.getWidth - 1, vpnnLen * 2 - sectortlbwidth), RegEnable(ppn_res(vpnnLen * 2 - 1, 0), valid)) 537 } 538 } 539 else ppn_res 540 } 541 542 override def toPrintable: Printable = { 543 val inner_level = level.getOrElse(2.U) 544 p"asid: ${asid} level:${inner_level} vpn:${Hexadecimal(tag)} ppn:${Hexadecimal(ppn)} perm:${perm}" 545 } 546 547} 548 549object TlbCmd { 550 def read = "b00".U 551 def write = "b01".U 552 def exec = "b10".U 553 554 def atom_read = "b100".U // lr 555 def atom_write = "b101".U // sc / amo 556 557 def apply() = UInt(3.W) 558 def isRead(a: UInt) = a(1,0)===read 559 def isWrite(a: UInt) = a(1,0)===write 560 def isExec(a: UInt) = a(1,0)===exec 561 562 def isAtom(a: UInt) = a(2) 563 def isAmo(a: UInt) = a===atom_write // NOTE: sc mixed 564} 565 566class TlbStorageIO(nSets: Int, nWays: Int, ports: Int, nDups: Int = 1)(implicit p: Parameters) extends MMUIOBaseBundle { 567 val r = new Bundle { 568 val req = Vec(ports, Flipped(DecoupledIO(new Bundle { 569 val vpn = Output(UInt(vpnLen.W)) 570 val vpn_extend = Output(UInt(extendVpnBits.W)) // for gvpn, gvpn is longer than vpn 571 val s2xlate = Output(UInt(2.W)) // 0 bit: has s2xlate, 1 bit: Only valid when 0 bit is 1. If 0, all stage; if 1, only stage 2 572 }))) 573 val resp = Vec(ports, ValidIO(new Bundle{ 574 val hit = Output(Bool()) 575 val ppn = Vec(nDups, Output(UInt(ppnLen.W))) 576 val perm = Vec(nDups, Output(new TlbSectorPermBundle())) 577 val gvpn = Vec(nDups, Output(UInt(gvpnLen.W))) 578 val g_perm = Vec(nDups, Output(new TlbPermBundle())) 579 val s2xlate = Vec(nDups, Output(UInt(2.W))) 580 })) 581 } 582 val w = Flipped(ValidIO(new Bundle { 583 val wayIdx = Output(UInt(log2Up(nWays).W)) 584 val data = Output(new PtwRespS2) 585 })) 586 val access = Vec(ports, new ReplaceAccessBundle(nSets, nWays)) 587 588 def r_req_apply(valid: Bool, vpn: UInt, i: Int, vpn_extend: UInt, s2xlate:UInt): Unit = { 589 this.r.req(i).valid := valid 590 this.r.req(i).bits.vpn := vpn 591 this.r.req(i).bits.vpn_extend := vpn(gvpnLen, vpnLen - 1) 592 this.r.req(i).bits.s2xlate := s2xlate 593 594 } 595 596 def r_resp_apply(i: Int) = { 597 (this.r.resp(i).bits.hit, this.r.resp(i).bits.ppn, this.r.resp(i).bits.perm, this.r.resp(i).bits.gvpn, this.r.resp(i).bits.g_perm) 598 } 599 600 def w_apply(valid: Bool, wayIdx: UInt, data: PtwRespS2): Unit = { 601 this.w.valid := valid 602 this.w.bits.wayIdx := wayIdx 603 this.w.bits.data := data 604 } 605 606} 607 608class TlbStorageWrapperIO(ports: Int, q: TLBParameters, nDups: Int = 1)(implicit p: Parameters) extends MMUIOBaseBundle { 609 val r = new Bundle { 610 val req = Vec(ports, Flipped(DecoupledIO(new Bundle { 611 val vpn = Output(UInt(vpnLen.W)) 612 val vpn_extend = Output(UInt(extendVpnBits.W)) 613 val s2xlate = Output(UInt(2.W)) 614 }))) 615 val resp = Vec(ports, ValidIO(new Bundle{ 616 val hit = Output(Bool()) 617 val ppn = Vec(nDups, Output(UInt(ppnLen.W))) 618 val perm = Vec(nDups, Output(new TlbPermBundle())) 619 val g_perm = Vec(nDups, Output(new TlbPermBundle())) 620 val s2xlate = Vec(nDups, Output(UInt(2.W))) 621 })) 622 } 623 val w = Flipped(ValidIO(new Bundle { 624 val data = Output(new PtwRespS2) 625 })) 626 val replace = if (q.outReplace) Flipped(new TlbReplaceIO(ports, q)) else null 627 628 def r_req_apply(valid: Bool, vpn: UInt, i: Int, s2xlate: UInt): Unit = { 629 this.r.req(i).valid := valid 630 this.r.req(i).bits.vpn := vpn 631 this.r.req(i).bits.vpn_extend := vpn(gvpnLen, vpnLen - 1) 632 this.r.req(i).bits.s2xlate := s2xlate 633 } 634 635 def r_resp_apply(i: Int) = { 636 (this.r.resp(i).bits.hit, this.r.resp(i).bits.ppn, this.r.resp(i).bits.perm, 637 this.r.resp(i).bits.super_hit, this.r.resp(i).bits.super_ppn, this.r.resp(i).bits.spm, 638 this.r.resp(i).bits.gvpn, this.r.resp(i).bits.g_perm, this.r.resp(i).bits.s2xlate) 639 } 640 641 def w_apply(valid: Bool, data: PtwRespS2): Unit = { 642 this.w.valid := valid 643 this.w.bits.data := data 644 } 645} 646 647class ReplaceAccessBundle(nSets: Int, nWays: Int)(implicit p: Parameters) extends TlbBundle { 648 val sets = Output(UInt(log2Up(nSets).W)) 649 val touch_ways = ValidIO(Output(UInt(log2Up(nWays).W))) 650} 651 652class ReplaceIO(Width: Int, nSets: Int, nWays: Int)(implicit p: Parameters) extends TlbBundle { 653 val access = Vec(Width, Flipped(new ReplaceAccessBundle(nSets, nWays))) 654 655 val refillIdx = Output(UInt(log2Up(nWays).W)) 656 val chosen_set = Flipped(Output(UInt(log2Up(nSets).W))) 657 658 def apply_sep(in: Seq[ReplaceIO], vpn: UInt): Unit = { 659 for ((ac_rep, ac_tlb) <- access.zip(in.map(a => a.access.map(b => b)).flatten)) { 660 ac_rep := ac_tlb 661 } 662 this.chosen_set := get_set_idx(vpn, nSets) 663 in.map(a => a.refillIdx := this.refillIdx) 664 } 665} 666 667class TlbReplaceIO(Width: Int, q: TLBParameters)(implicit p: Parameters) extends 668 TlbBundle { 669 val page = new ReplaceIO(Width, q.NSets, q.NWays) 670 671 def apply_sep(in: Seq[TlbReplaceIO], vpn: UInt) = { 672 this.page.apply_sep(in.map(_.page), vpn) 673 } 674 675} 676 677class MemBlockidxBundle(implicit p: Parameters) extends TlbBundle { 678 val is_ld = Bool() 679 val is_st = Bool() 680 val idx = 681 if (VirtualLoadQueueSize >= StoreQueueSize) { 682 val idx = UInt(log2Ceil(VirtualLoadQueueSize).W) 683 idx 684 } else { 685 val idx = UInt(log2Ceil(StoreQueueSize).W) 686 idx 687 } 688} 689 690class TlbReq(implicit p: Parameters) extends TlbBundle { 691 val vaddr = Output(UInt(VAddrBits.W)) 692 val cmd = Output(TlbCmd()) 693 val hyperinst = Output(Bool()) 694 val hlvx = Output(Bool()) 695 val size = Output(UInt(log2Ceil(log2Ceil(XLEN/8)+1).W)) 696 val kill = Output(Bool()) // Use for blocked tlb that need sync with other module like icache 697 val memidx = Output(new MemBlockidxBundle) 698 // do not translate, but still do pmp/pma check 699 val no_translate = Output(Bool()) 700 val debug = new Bundle { 701 val pc = Output(UInt(XLEN.W)) 702 val robIdx = Output(new RobPtr) 703 val isFirstIssue = Output(Bool()) 704 } 705 706 // Maybe Block req needs a kill: for itlb, itlb and icache may not sync, itlb should wait icache to go ahead 707 override def toPrintable: Printable = { 708 p"vaddr:0x${Hexadecimal(vaddr)} cmd:${cmd} kill:${kill} pc:0x${Hexadecimal(debug.pc)} robIdx:${debug.robIdx}" 709 } 710} 711 712class TlbExceptionBundle(implicit p: Parameters) extends TlbBundle { 713 val ld = Output(Bool()) 714 val st = Output(Bool()) 715 val instr = Output(Bool()) 716} 717 718class TlbResp(nDups: Int = 1)(implicit p: Parameters) extends TlbBundle { 719 val paddr = Vec(nDups, Output(UInt(PAddrBits.W))) 720 val gpaddr = Vec(nDups, Output(UInt(GPAddrBits.W))) 721 val miss = Output(Bool()) 722 val excp = Vec(nDups, new Bundle { 723 val gpf = new TlbExceptionBundle() 724 val pf = new TlbExceptionBundle() 725 val af = new TlbExceptionBundle() 726 }) 727 val ptwBack = Output(Bool()) // when ptw back, wake up replay rs's state 728 val memidx = Output(new MemBlockidxBundle) 729 730 val debug = new Bundle { 731 val robIdx = Output(new RobPtr) 732 val isFirstIssue = Output(Bool()) 733 } 734 override def toPrintable: Printable = { 735 p"paddr:0x${Hexadecimal(paddr(0))} miss:${miss} excp.pf: ld:${excp(0).pf.ld} st:${excp(0).pf.st} instr:${excp(0).pf.instr} ptwBack:${ptwBack}" 736 } 737} 738 739class TlbRequestIO(nRespDups: Int = 1)(implicit p: Parameters) extends TlbBundle { 740 val req = DecoupledIO(new TlbReq) 741 val req_kill = Output(Bool()) 742 val resp = Flipped(DecoupledIO(new TlbResp(nRespDups))) 743} 744 745class TlbPtwIO(Width: Int = 1)(implicit p: Parameters) extends TlbBundle { 746 val req = Vec(Width, DecoupledIO(new PtwReq)) 747 val resp = Flipped(DecoupledIO(new PtwRespS2)) 748 749 750 override def toPrintable: Printable = { 751 p"req(0):${req(0).valid} ${req(0).ready} ${req(0).bits} | resp:${resp.valid} ${resp.ready} ${resp.bits}" 752 } 753} 754 755class TlbPtwIOwithMemIdx(Width: Int = 1)(implicit p: Parameters) extends TlbBundle { 756 val req = Vec(Width, DecoupledIO(new PtwReqwithMemIdx)) 757 val resp = Flipped(DecoupledIO(new PtwRespS2withMemIdx())) 758 759 760 override def toPrintable: Printable = { 761 p"req(0):${req(0).valid} ${req(0).ready} ${req(0).bits} | resp:${resp.valid} ${resp.ready} ${resp.bits}" 762 } 763} 764 765class TlbHintReq(implicit p: Parameters) extends TlbBundle { 766 val id = Output(UInt(log2Up(loadfiltersize).W)) 767 val full = Output(Bool()) 768} 769 770class TLBHintResp(implicit p: Parameters) extends TlbBundle { 771 val id = Output(UInt(log2Up(loadfiltersize).W)) 772 // When there are multiple matching entries for PTW resp in filter 773 // e.g. vaddr 0, 0x80000000. vaddr 1, 0x80010000 774 // these two vaddrs are not in a same 4K Page, so will send to ptw twice 775 // However, when ptw resp, if they are in a 1G or 2M huge page 776 // The two entries will both hit, and both need to replay 777 val replay_all = Output(Bool()) 778} 779 780class TlbHintIO(implicit p: Parameters) extends TlbBundle { 781 val req = Vec(exuParameters.LduCnt, new TlbHintReq) 782 val resp = ValidIO(new TLBHintResp) 783} 784 785class MMUIOBaseBundle(implicit p: Parameters) extends TlbBundle { 786 val sfence = Input(new SfenceBundle) 787 val csr = Input(new TlbCsrBundle) 788 789 def base_connect(sfence: SfenceBundle, csr: TlbCsrBundle): Unit = { 790 this.sfence <> sfence 791 this.csr <> csr 792 } 793 794 // overwrite satp. write satp will cause flushpipe but csr.priv won't 795 // satp will be dealyed several cycles from writing, but csr.priv won't 796 // so inside mmu, these two signals should be divided 797 def base_connect(sfence: SfenceBundle, csr: TlbCsrBundle, satp: TlbSatpBundle) = { 798 this.sfence <> sfence 799 this.csr <> csr 800 this.csr.satp := satp 801 } 802} 803 804class TlbRefilltoMemIO()(implicit p: Parameters) extends TlbBundle { 805 val valid = Bool() 806 val memidx = new MemBlockidxBundle 807} 808 809class TlbIO(Width: Int, nRespDups: Int = 1, q: TLBParameters)(implicit p: Parameters) extends 810 MMUIOBaseBundle { 811 val hartId = Input(UInt(hartIdLen.W)) 812 val requestor = Vec(Width, Flipped(new TlbRequestIO(nRespDups))) 813 val flushPipe = Vec(Width, Input(Bool())) 814 val ptw = new TlbPtwIOwithMemIdx(Width) 815 val refill_to_mem = Output(new TlbRefilltoMemIO()) 816 val replace = if (q.outReplace) Flipped(new TlbReplaceIO(Width, q)) else null 817 val pmp = Vec(Width, ValidIO(new PMPReqBundle())) 818 val tlbreplay = Vec(Width, Output(Bool())) 819} 820 821class VectorTlbPtwIO(Width: Int)(implicit p: Parameters) extends TlbBundle { 822 val req = Vec(Width, DecoupledIO(new PtwReqwithMemIdx())) 823 val resp = Flipped(DecoupledIO(new Bundle { 824 val data = new PtwRespS2withMemIdx 825 val vector = Output(Vec(Width, Bool())) 826 })) 827 828 def connect(normal: TlbPtwIOwithMemIdx): Unit = { 829 req <> normal.req 830 resp.ready := normal.resp.ready 831 normal.resp.bits := resp.bits.data 832 normal.resp.valid := resp.valid 833 } 834} 835 836/**************************** L2TLB *************************************/ 837abstract class PtwBundle(implicit p: Parameters) extends XSBundle with HasPtwConst 838abstract class PtwModule(outer: L2TLB) extends LazyModuleImp(outer) 839 with HasXSParameter with HasPtwConst 840 841class PteBundle(implicit p: Parameters) extends PtwBundle{ 842 val reserved = UInt(pteResLen.W) 843 val ppn_high = UInt(ppnHignLen.W) 844 val ppn = UInt(ppnLen.W) 845 val rsw = UInt(2.W) 846 val perm = new Bundle { 847 val d = Bool() 848 val a = Bool() 849 val g = Bool() 850 val u = Bool() 851 val x = Bool() 852 val w = Bool() 853 val r = Bool() 854 val v = Bool() 855 } 856 857 def unaligned(level: UInt) = { 858 isLeaf() && !(level === 2.U || 859 level === 1.U && ppn(vpnnLen-1, 0) === 0.U || 860 level === 0.U && ppn(vpnnLen*2-1, 0) === 0.U) 861 } 862 863 def isPf(level: UInt) = { 864 !perm.v || (!perm.r && perm.w) || unaligned(level) 865 } 866 867 // paddr of Xiangshan is 36 bits but ppn of sv39 is 44 bits 868 // access fault will be raised when ppn >> ppnLen is not zero 869 def isAf() = { 870 !(ppn_high === 0.U) 871 } 872 873 def isLeaf() = { 874 perm.r || perm.x || perm.w 875 } 876 877 def getPerm() = { 878 val pm = Wire(new PtePermBundle) 879 pm.d := perm.d 880 pm.a := perm.a 881 pm.g := perm.g 882 pm.u := perm.u 883 pm.x := perm.x 884 pm.w := perm.w 885 pm.r := perm.r 886 pm 887 } 888 889 override def toPrintable: Printable = { 890 p"ppn:0x${Hexadecimal(ppn)} perm:b${Binary(perm.asUInt)}" 891 } 892} 893 894class PtwEntry(tagLen: Int, hasPerm: Boolean = false, hasLevel: Boolean = false)(implicit p: Parameters) extends PtwBundle { 895 val tag = UInt(tagLen.W) 896 val asid = UInt(asidLen.W) 897 val vmid = if (HasHExtension) Some(UInt(vmidLen.W)) else None 898 val ppn = UInt(ppnLen.W) 899 val perm = if (hasPerm) Some(new PtePermBundle) else None 900 val level = if (hasLevel) Some(UInt(log2Up(Level).W)) else None 901 val prefetch = Bool() 902 val v = Bool() 903 904 def is_normalentry(): Bool = { 905 if (!hasLevel) true.B 906 else level.get === 2.U 907 } 908 909 def genPPN(vpn: UInt): UInt = { 910 if (!hasLevel) ppn 911 else MuxLookup(level.get, 0.U)(Seq( 912 0.U -> Cat(ppn(ppn.getWidth-1, vpnnLen*2), vpn(vpnnLen*2-1, 0)), 913 1.U -> Cat(ppn(ppn.getWidth-1, vpnnLen), vpn(vpnnLen-1, 0)), 914 2.U -> ppn) 915 ) 916 } 917 918 //s2xlate control whether compare vmid or not 919 def hit(vpn: UInt, asid: UInt, vmid: UInt, allType: Boolean = false, ignoreAsid: Boolean = false, s2xlate: Bool, isGvpn: Bool) = { 920 require(vpn.getWidth == vpnLen || vpn.getWidth == gvpnLen) 921// require(this.asid.getWidth <= asid.getWidth) 922 val asid_hit = if (ignoreAsid) true.B else (this.asid === asid) 923 val vmid_hit = Mux(s2xlate, this.vmid === vmid, true.B) 924 if (allType) { 925 require(hasLevel) 926 val hit0 = tag(tagLen - 1, vpnnLen*2) === vpn(tagLen - 1, vpnnLen*2) 927 val hit1 = tag(vpnnLen*2 - 1, vpnnLen) === vpn(vpnnLen*2 - 1, vpnnLen) 928 val hit2 = tag(vpnnLen - 1, 0) === vpn(vpnnLen - 1, 0) 929 930 asid_hit && vmid_hit && Mux(level.getOrElse(0.U) === 2.U, hit2 && hit1 && hit0, Mux(level.getOrElse(0.U) === 1.U, hit1 && hit0, hit0)) 931 } else if (hasLevel) { 932 val hit0 = tag(tagLen - 1, tagLen - vpnnLen) === Mux(isGvpn, vpn(gvpnLen - 1, gvpnLen - vpnnLen), vpn(vpnLen - 1, vpnLen - vpnnLen)) 933 val hit1 = tag(tagLen - vpnnLen - 1, tagLen - vpnnLen * 2) === Mux(isGvpn, vpn(gvpnLen - vpnnLen - 1, gvpnLen - vpnnLen * 2), vpn(vpnLen - vpnnLen - 1, vpnLen - vpnnLen * 2)) 934 935 asid_hit && vmid_hit && Mux(level.getOrElse(0.U) === 0.U, hit0, hit0 && hit1) 936 } else { 937 asid_hit && vmid_hit && tag === Mux(isGvpn, vpn(gvpnLen - 1, vpnLen - tagLen), vpn(vpnLen - 1, vpnLen - tagLen)) 938 } 939 } 940 941 def refill(vpn: UInt, asid: UInt, vmid: UInt, pte: UInt, level: UInt = 0.U, prefetch: Bool, valid: Bool = false.B) { 942 require(this.asid.getWidth <= asid.getWidth) // maybe equal is better, but ugly outside 943 944 tag := vpn(vpnLen - 1, vpnLen - tagLen) 945 ppn := pte.asTypeOf(new PteBundle().cloneType).ppn 946 perm.map(_ := pte.asTypeOf(new PteBundle().cloneType).perm) 947 this.asid := asid 948 this.vmid := vmid 949 this.prefetch := prefetch 950 this.v := valid 951 this.level.map(_ := level) 952 } 953 954 def genPtwEntry(vpn: UInt, asid: UInt, pte: UInt, level: UInt = 0.U, prefetch: Bool, valid: Bool = false.B) = { 955 val e = Wire(new PtwEntry(tagLen, hasPerm, hasLevel)) 956 e.refill(vpn, asid, pte, level, prefetch, valid) 957 e 958 } 959 960 961 962 override def toPrintable: Printable = { 963 // p"tag:0x${Hexadecimal(tag)} ppn:0x${Hexadecimal(ppn)} perm:${perm}" 964 p"tag:0x${Hexadecimal(tag)} ppn:0x${Hexadecimal(ppn)} " + 965 (if (hasPerm) p"perm:${perm.getOrElse(0.U.asTypeOf(new PtePermBundle))} " else p"") + 966 (if (hasLevel) p"level:${level.getOrElse(0.U)}" else p"") + 967 p"prefetch:${prefetch}" 968 } 969} 970 971class PtwSectorEntry(tagLen: Int, hasPerm: Boolean = false, hasLevel: Boolean = false)(implicit p: Parameters) extends PtwEntry(tagLen, hasPerm, hasLevel) { 972 override val ppn = UInt(sectorppnLen.W) 973} 974 975class PtwMergeEntry(tagLen: Int, hasPerm: Boolean = false, hasLevel: Boolean = false)(implicit p: Parameters) extends PtwSectorEntry(tagLen, hasPerm, hasLevel) { 976 val ppn_low = UInt(sectortlbwidth.W) 977 val af = Bool() 978 val pf = Bool() 979} 980 981class HptwMergeEntry(tagLen: Int, hasPerm: Boolean = false, hasLevel: Boolean = false)(implicit p: Parameters) extends PtwMergeEntry(tagLen, hasPerm, hasLevel) { 982 val vmid = UInt(vmidLen.W) 983} 984 985class PtwEntries(num: Int, tagLen: Int, level: Int, hasPerm: Boolean)(implicit p: Parameters) extends PtwBundle { 986 require(log2Up(num)==log2Down(num)) 987 // NOTE: hasPerm means that is leaf or not. 988 989 val tag = UInt(tagLen.W) 990 val asid = UInt(asidLen.W) 991 val vmid = if (HasHExtension) Some(UInt(vmidLen.W)) else None 992 val ppns = if (HasHExtension) Vec(num, UInt(gvpnLen.W)) else Vec(num, UInt(ppnLen.W)) 993 val vs = Vec(num, Bool()) 994 val perms = if (hasPerm) Some(Vec(num, new PtePermBundle)) else None 995 val prefetch = Bool() 996 // println(s"PtwEntries: tag:1*${tagLen} ppns:${num}*${ppnLen} vs:${num}*1") 997 // NOTE: vs is used for different usage: 998 // for l3, which store the leaf(leaves), vs is page fault or not. 999 // for l2, which shoule not store leaf, vs is valid or not, that will anticipate in hit check 1000 // Because, l2 should not store leaf(no perm), it doesn't store perm. 1001 // If l2 hit a leaf, the perm is still unavailble. Should still page walk. Complex but nothing helpful. 1002 // TODO: divide vs into validVec and pfVec 1003 // for l2: may valid but pf, so no need for page walk, return random pte with pf. 1004 1005 def tagClip(vpn: UInt, isGvpn: Bool) = { 1006 require(vpn.getWidth == vpnLen || vpn.getWidth == gvpnLen) 1007 when(isGvpn){ 1008 vpn(gvpnLen - 1, gvpnLen - tagLen) 1009 }.otherwise{ 1010 vpn(vpnLen - 1, vpnLen - tagLen) 1011 } 1012 } 1013 1014 def sectorIdxClip(vpn: UInt, level: Int) = { 1015 getVpnClip(vpn, level)(log2Up(num) - 1, 0) 1016 } 1017 1018 def hit(vpn: UInt, asid: UInt, vmid:UInt, ignoreAsid: Boolean = false, s2xlate: Bool, isGvpn: Bool) = { 1019 val asid_hit = if (ignoreAsid) true.B else (this.asid === asid) 1020 val vmid_hit = Mux(s2xlate, this.vmid === vmid, true.B) 1021 asid_hit && vmid_hit && tag === tagClip(vpn, isGvpn) && (if (hasPerm) true.B else vs(sectorIdxClip(vpn, level))) 1022 } 1023 1024 def genEntries(vpn: UInt, asid: UInt, vmid: UInt, data: UInt, levelUInt: UInt, prefetch: Bool) = { 1025 require((data.getWidth / XLEN) == num, 1026 s"input data length must be multiple of pte length: data.length:${data.getWidth} num:${num}") 1027 1028 val ps = Wire(new PtwEntries(num, tagLen, level, hasPerm)) 1029 ps.tag := tagClip(vpn) 1030 ps.asid := asid 1031 ps.vmid := vmid 1032 ps.prefetch := prefetch 1033 for (i <- 0 until num) { 1034 val pte = data((i+1)*XLEN-1, i*XLEN).asTypeOf(new PteBundle) 1035 ps.ppns(i) := pte.ppn 1036 ps.vs(i) := !pte.isPf(levelUInt) && (if (hasPerm) pte.isLeaf() else !pte.isLeaf()) 1037 ps.perms.map(_(i) := pte.perm) 1038 } 1039 ps 1040 } 1041 1042 override def toPrintable: Printable = { 1043 // require(num == 4, "if num is not 4, please comment this toPrintable") 1044 // NOTE: if num is not 4, please comment this toPrintable 1045 val permsInner = perms.getOrElse(0.U.asTypeOf(Vec(num, new PtePermBundle))) 1046 p"asid: ${Hexadecimal(asid)} tag:0x${Hexadecimal(tag)} ppns:${printVec(ppns)} vs:${Binary(vs.asUInt)} " + 1047 (if (hasPerm) p"perms:${printVec(permsInner)}" else p"") 1048 } 1049} 1050 1051class PTWEntriesWithEcc(eccCode: Code, num: Int, tagLen: Int, level: Int, hasPerm: Boolean)(implicit p: Parameters) extends PtwBundle { 1052 val entries = new PtwEntries(num, tagLen, level, hasPerm) 1053 1054 val ecc_block = XLEN 1055 val ecc_info = get_ecc_info() 1056 val ecc = UInt(ecc_info._1.W) 1057 1058 def get_ecc_info(): (Int, Int, Int, Int) = { 1059 val eccBits_per = eccCode.width(ecc_block) - ecc_block 1060 1061 val data_length = entries.getWidth 1062 val data_align_num = data_length / ecc_block 1063 val data_not_align = (data_length % ecc_block) != 0 // ugly code 1064 val data_unalign_length = data_length - data_align_num * ecc_block 1065 val eccBits_unalign = eccCode.width(data_unalign_length) - data_unalign_length 1066 1067 val eccBits = eccBits_per * data_align_num + eccBits_unalign 1068 (eccBits, eccBits_per, data_align_num, data_unalign_length) 1069 } 1070 1071 def encode() = { 1072 val data = entries.asUInt 1073 val ecc_slices = Wire(Vec(ecc_info._3, UInt(ecc_info._2.W))) 1074 for (i <- 0 until ecc_info._3) { 1075 ecc_slices(i) := eccCode.encode(data((i+1)*ecc_block-1, i*ecc_block)) >> ecc_block 1076 } 1077 if (ecc_info._4 != 0) { 1078 val ecc_unaligned = eccCode.encode(data(data.getWidth-1, ecc_info._3*ecc_block)) >> ecc_info._4 1079 ecc := Cat(ecc_unaligned, ecc_slices.asUInt) 1080 } else { ecc := ecc_slices.asUInt } 1081 } 1082 1083 def decode(): Bool = { 1084 val data = entries.asUInt 1085 val res = Wire(Vec(ecc_info._3 + 1, Bool())) 1086 for (i <- 0 until ecc_info._3) { 1087 res(i) := {if (ecc_info._2 != 0) eccCode.decode(Cat(ecc((i+1)*ecc_info._2-1, i*ecc_info._2), data((i+1)*ecc_block-1, i*ecc_block))).error else false.B} 1088 } 1089 if (ecc_info._2 != 0 && ecc_info._4 != 0) { 1090 res(ecc_info._3) := eccCode.decode( 1091 Cat(ecc(ecc_info._1-1, ecc_info._2*ecc_info._3), data(data.getWidth-1, ecc_info._3*ecc_block))).error 1092 } else { res(ecc_info._3) := false.B } 1093 1094 Cat(res).orR 1095 } 1096 1097 def gen(vpn: UInt, asid: UInt, vmid: UInt, data: UInt, levelUInt: UInt, prefetch: Bool) = { 1098 this.entries := entries.genEntries(vpn, asid, vmid, data, levelUInt, prefetch) 1099 this.encode() 1100 } 1101} 1102 1103class PtwReq(implicit p: Parameters) extends PtwBundle { 1104 val vpn = UInt(vpnLen.W) 1105 val gvpn = UInt(gvpnLen.W) 1106 val s2xlate = UInt(2.W) // 0 bit: s2xlate, 1 bit: stage 1 or stage 2 1107 override def toPrintable: Printable = { 1108 p"vpn:0x${Hexadecimal(vpn)}" 1109 } 1110} 1111 1112class PtwReqwithMemIdx(implicit p: Parameters) extends PtwReq { 1113 val memidx = new MemBlockidxBundle 1114} 1115 1116class PtwResp(implicit p: Parameters) extends PtwBundle { 1117 val entry = new PtwEntry(tagLen = vpnLen, hasPerm = true, hasLevel = true) 1118 val pf = Bool() 1119 val af = Bool() 1120 1121 def apply(pf: Bool, af: Bool, level: UInt, pte: PteBundle, vpn: UInt, asid: UInt) = { 1122 this.entry.level.map(_ := level) 1123 this.entry.tag := vpn 1124 this.entry.perm.map(_ := pte.getPerm()) 1125 this.entry.ppn := pte.ppn 1126 this.entry.prefetch := DontCare 1127 this.entry.asid := asid 1128 this.entry.v := !pf 1129 this.pf := pf 1130 this.af := af 1131 } 1132 1133 override def toPrintable: Printable = { 1134 p"entry:${entry} pf:${pf} af:${af}" 1135 } 1136} 1137 1138class HptwResp(implicit p: Parameters) extends PtwBundle { 1139 val entry = new PtwEntry(tagLen = gvpnLen, hasPerm = true, hasLevel = true) 1140 val gpf = Bool() 1141 val gaf = Bool() 1142 1143 def apply(gpf: Bool, gaf: Bool, level: UInt, pte: PteBundle, vpn: UInt, vmid: UInt) = { 1144 this.entry.level.map(_ := level) 1145 this.entry.tag := vpn 1146 this.entry.perm.map(_ := pte.getPerm()) 1147 this.entry.ppn := pte.ppn 1148 this.entry.prefetch := DontCare 1149 this.entry.asid := DontCare 1150 this.entry.vmid := vmid 1151 this.entry.v := !gpf 1152 this.gpf := gpf 1153 this.gaf := gaf 1154 } 1155 1156 def genPPNS2(): UInt = { 1157 MuxLookup(entry.level.get, 0.U, Seq( 1158 0.U -> Cat(entry.ppn(entry.ppn.getWidth - 1, vpnnLen * 2), entry.tag(vpnnLen * 2 - 1, 0)), 1159 1.U -> Cat(entry.ppn(entry.ppn.getWidth - 1, vpnnLen), entry.tag(vpnnLen - 1, 0)), 1160 2.U -> Cat(entry.ppn(entry.ppn.getWidth - 1, 0)) 1161 )) 1162 } 1163 1164 def hit(gvpn: UInt, vmid: UInt): Bool = { 1165 require(gvpn.getWidth == gvpnLen) 1166 val vmid_hit = this.entry.vmid === vmid 1167 val hit0 = entry.tag(gvpnLen - 1, vpnnLen * 2) === gvpn(gvpnLen - 1, vpnnLen * 2) 1168 val hit1 = entry.tag(vpnnLen * 2 - 1, vpnnLen) === gvpn(vpnnLen * 2 - 1, vpnnLen) 1169 val hit2 = entry.tag(vpnnLen - 1, 0) === gvpn(vpnnLen - 1, 0) 1170 vmid_hit && Mux(entry.level.getOrElse(0.U) === 2.U, hit2 && hit1 && hit0, Mux(entry.level.getOrElse(0.U) === 1.U, hit1 && hit0, hit0)) 1171 } 1172} 1173 1174class PtwResptomerge (implicit p: Parameters) extends PtwBundle { 1175 val entry = UInt(blockBits.W) 1176 val vpn = UInt(vpnLen.W) 1177 val level = UInt(log2Up(Level).W) 1178 val pf = Bool() 1179 val af = Bool() 1180 val asid = UInt(asidLen.W) 1181 1182 def apply(pf: Bool, af: Bool, level: UInt, pte: UInt, vpn: UInt, asid: UInt) = { 1183 this.entry := pte 1184 this.pf := pf 1185 this.af := af 1186 this.level := level 1187 this.vpn := vpn 1188 this.asid := asid 1189 } 1190 1191 override def toPrintable: Printable = { 1192 p"entry:${entry} pf:${pf} af:${af}" 1193 } 1194} 1195 1196class PtwRespwithMemIdx(implicit p: Parameters) extends PtwResp { 1197 val memidx = new MemBlockidxBundle 1198} 1199 1200class PtwSectorRespwithMemIdx(implicit p: Parameters) extends PtwSectorResp { 1201 val memidx = new MemBlockidxBundle 1202} 1203 1204class PtwSectorResp(implicit p: Parameters) extends PtwBundle { 1205 val entry = new PtwSectorEntry(tagLen = sectorvpnLen, hasPerm = true, hasLevel = true) 1206 val addr_low = UInt(sectortlbwidth.W) 1207 val ppn_low = Vec(tlbcontiguous, UInt(sectortlbwidth.W)) 1208 val valididx = Vec(tlbcontiguous, Bool()) 1209 val pteidx = Vec(tlbcontiguous, Bool()) 1210 val pf = Bool() 1211 val af = Bool() 1212 1213 1214 def genPPN(vpn: UInt): UInt = { 1215 MuxLookup(entry.level.get, 0.U)(Seq( 1216 0.U -> Cat(entry.ppn(entry.ppn.getWidth-1, vpnnLen * 2 - sectortlbwidth), vpn(vpnnLen*2-1, 0)), 1217 1.U -> Cat(entry.ppn(entry.ppn.getWidth-1, vpnnLen - sectortlbwidth), vpn(vpnnLen-1, 0)), 1218 2.U -> Cat(entry.ppn(entry.ppn.getWidth-1, 0), ppn_low(vpn(sectortlbwidth - 1, 0)))) 1219 ) 1220 } 1221 1222 def hit(vpn: UInt, asid: UInt, vmid: UInt, allType: Boolean = false, ignoreAsid: Boolean = false, s2xlate: Bool): Bool = { 1223 require(vpn.getWidth == vpnLen) 1224 // require(this.asid.getWidth <= asid.getWidth) 1225 val asid_hit = if (ignoreAsid) true.B else (this.entry.asid === asid) 1226 val vmid_hit = Mux(s2xlate, this.entry.vmid === vmid, true.B) 1227 if (allType) { 1228 val hit0 = entry.tag(sectorvpnLen - 1, vpnnLen * 2 - sectortlbwidth) === vpn(vpnLen - 1, vpnnLen * 2) 1229 val hit1 = entry.tag(vpnnLen * 2 - sectortlbwidth - 1, vpnnLen - sectortlbwidth) === vpn(vpnnLen * 2 - 1, vpnnLen) 1230 val hit2 = entry.tag(vpnnLen - sectortlbwidth - 1, 0) === vpn(vpnnLen - 1, sectortlbwidth) 1231 val addr_low_hit = valididx(vpn(sectortlbwidth - 1, 0)) 1232 1233 asid_hit && vmid_hit && Mux(entry.level.getOrElse(0.U) === 2.U, hit2 && hit1 && hit0, Mux(entry.level.getOrElse(0.U) === 1.U, hit1 && hit0, hit0)) && addr_low_hit 1234 } else { 1235 val hit0 = entry.tag(sectorvpnLen - 1, sectorvpnLen - vpnnLen) === vpn(vpnLen - 1, vpnLen - vpnnLen) 1236 val hit1 = entry.tag(sectorvpnLen - vpnnLen - 1, sectorvpnLen - vpnnLen * 2) === vpn(vpnLen - vpnnLen - 1, vpnLen - vpnnLen * 2) 1237 val addr_low_hit = valididx(vpn(sectortlbwidth - 1, 0)) 1238 1239 asid_hit && vmid_hit && Mux(entry.level.getOrElse(0.U) === 0.U, hit0, hit0 && hit1) && addr_low_hit 1240 } 1241 } 1242} 1243 1244class PtwMergeResp(implicit p: Parameters) extends PtwBundle { 1245 val entry = Vec(tlbcontiguous, new PtwMergeEntry(tagLen = sectorvpnLen, hasPerm = true, hasLevel = true)) 1246 val pteidx = Vec(tlbcontiguous, Bool()) 1247 val not_super = Bool() 1248 1249 def apply(pf: Bool, af: Bool, level: UInt, pte: PteBundle, vpn: UInt, asid: UInt, vmid:UInt, addr_low : UInt, not_super : Boolean = true) = { 1250 assert(tlbcontiguous == 8, "Only support tlbcontiguous = 8!") 1251 1252 val ptw_resp = Wire(new PtwMergeEntry(tagLen = sectorvpnLen, hasPerm = true, hasLevel = true)) 1253 ptw_resp.ppn := pte.ppn(ppnLen - 1, sectortlbwidth) 1254 ptw_resp.ppn_low := pte.ppn(sectortlbwidth - 1, 0) 1255 ptw_resp.level.map(_ := level) 1256 ptw_resp.perm.map(_ := pte.getPerm()) 1257 ptw_resp.tag := vpn(vpnLen - 1, sectortlbwidth) 1258 ptw_resp.pf := pf 1259 ptw_resp.af := af 1260 ptw_resp.v := !pf 1261 ptw_resp.prefetch := DontCare 1262 ptw_resp.asid := asid 1263 this.pteidx := UIntToOH(addr_low).asBools 1264 this.not_super := not_super.B 1265 1266 1267 for (i <- 0 until tlbcontiguous) { 1268 this.entry(i) := ptw_resp 1269 } 1270 } 1271} 1272 1273class HptwMergeResp(implicit p: Parameters) extends PtwBundle { 1274 val entry = Vec(tlbcontiguous, new HptwMergeEntry(tagLen = sectorvpnLen, hasPerm = true, hasLevel = true)) 1275 val pteidx = Vec(tlbcontiguous, Bool()) 1276 val not_super = Bool() 1277 1278 def genPPN(): UInt = { 1279 val idx = OHToUInt(pteidx) 1280 MuxLookup(entry(idx).level.get, 0.U, Seq( 1281 0.U -> Cat(entry(idx).ppn(entry(idx).ppn.getWidth - 1, vpnnLen * 2 - sectortlbwidth), vpn(vpnnLen * 2 - 1, 0)), 1282 1.U -> Cat(entry(idx).ppn(entry(idx).ppn.getWidth - 1, vpnnLen - sectortlbwidth), vpn(vpnnLen - 1, 0)), 1283 2.U -> Cat(entry(idx).ppn(entry(idx).ppn.getWidth - 1, 0), entry(idx).ppn_low)) 1284 ) 1285 } 1286 1287 def isAf(): Bool = { 1288 val idx = OHToUInt(pteidx) 1289 entry(idx).af 1290 } 1291 1292 def isPf(): Bool = { 1293 val idx = OHToUInt(pteidx) 1294 entry(idx).pf 1295 } 1296 1297 def MergeRespToPte(): PteBundle = { 1298 val idx = OHToUInt(pteidx) 1299 val resp = Wire(new PteBundle()) 1300 resp.ppn := Cat(entry(idx).ppn, entry(idx).ppn_low) 1301 resp.perm := entry(idx).perm 1302 resp 1303 } 1304 1305 def apply(pf: Bool, af: Bool, level: UInt, pte: PteBundle, vpn: UInt, vmid: UInt, addr_low: UInt, not_super: Boolean = true) = { 1306 assert(tlbcontiguous == 8, "Only support tlbcontiguous = 8!") 1307 1308 val ptw_resp = Wire(new HptwMergeEntry(tagLen = sectorvpnLen, hasPerm = true, hasLevel = true)) 1309 ptw_resp.ppn := pte.ppn(ppnLen - 1, sectortlbwidth) 1310 ptw_resp.ppn_low := pte.ppn(sectortlbwidth - 1, 0) 1311 ptw_resp.level.map(_ := level) 1312 ptw_resp.perm.map(_ := pte.getPerm()) 1313 ptw_resp.tag := vpn(vpnLen - 1, sectortlbwidth) 1314 ptw_resp.pf := pf 1315 ptw_resp.af := af 1316 ptw_resp.v := !pf 1317 ptw_resp.prefetch := DontCare 1318 ptw_resp.vmid := vmid 1319 this.pteidx := UIntToOH(addr_low).asBools 1320 this.not_super := not_super.B 1321 1322 1323 for (i <- 0 until tlbcontiguous) { 1324 this.entry(i) := ptw_resp 1325 } 1326 } 1327} 1328 1329class PtwRespS2(implicit p: Parameters) extends PtwBundle { 1330 val s2xlate = UInt(2.W) 1331 val s1 = new PtwSectorResp() 1332 val s2 = new HptwResp() 1333} 1334 1335class PtwRespS2withMemIdx(implicit p: Parameters) extends PtwRespS2 { 1336 val memidx = new MemBlockidxBundle() 1337} 1338 1339class L2TLBIO(implicit p: Parameters) extends PtwBundle { 1340 val hartId = Input(UInt(hartIdLen.W)) 1341 val tlb = Vec(PtwWidth, Flipped(new TlbPtwIO)) 1342 val sfence = Input(new SfenceBundle) 1343 val csr = new Bundle { 1344 val tlb = Input(new TlbCsrBundle) 1345 val distribute_csr = Flipped(new DistributedCSRIO) 1346 } 1347} 1348 1349class L2TlbMemReqBundle(implicit p: Parameters) extends PtwBundle { 1350 val addr = UInt(PAddrBits.W) 1351 val id = UInt(bMemID.W) 1352} 1353 1354class L2TlbInnerBundle(implicit p: Parameters) extends PtwReq { 1355 val source = UInt(bSourceWidth.W) 1356} 1357 1358 1359object ValidHoldBypass{ 1360 def apply(infire: Bool, outfire: Bool, flush: Bool = false.B) = { 1361 val valid = RegInit(false.B) 1362 when (infire) { valid := true.B } 1363 when (outfire) { valid := false.B } // ATTENTION: order different with ValidHold 1364 when (flush) { valid := false.B } // NOTE: the flush will flush in & out, is that ok? 1365 valid || infire 1366 } 1367} 1368 1369class L1TlbDB(implicit p: Parameters) extends TlbBundle { 1370 val vpn = UInt(vpnLen.W) 1371} 1372 1373class PageCacheDB(implicit p: Parameters) extends TlbBundle with HasPtwConst { 1374 val vpn = UInt(vpnLen.W) 1375 val source = UInt(bSourceWidth.W) 1376 val bypassed = Bool() 1377 val is_first = Bool() 1378 val prefetched = Bool() 1379 val prefetch = Bool() 1380 val l2Hit = Bool() 1381 val l1Hit = Bool() 1382 val hit = Bool() 1383} 1384 1385class PTWDB(implicit p: Parameters) extends TlbBundle with HasPtwConst { 1386 val vpn = UInt(vpnLen.W) 1387 val source = UInt(bSourceWidth.W) 1388} 1389 1390class L2TlbPrefetchDB(implicit p: Parameters) extends TlbBundle { 1391 val vpn = UInt(vpnLen.W) 1392} 1393 1394class L2TlbMissQueueDB(implicit p: Parameters) extends TlbBundle { 1395 val vpn = UInt(vpnLen.W) 1396} 1397