16d5ddbceSLemover/*************************************************************************************** 26d5ddbceSLemover* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3f320e0f0SYinan Xu* Copyright (c) 2020-2021 Peng Cheng Laboratory 46d5ddbceSLemover* 56d5ddbceSLemover* XiangShan is licensed under Mulan PSL v2. 66d5ddbceSLemover* You can use this software according to the terms and conditions of the Mulan PSL v2. 76d5ddbceSLemover* You may obtain a copy of Mulan PSL v2 at: 86d5ddbceSLemover* http://license.coscl.org.cn/MulanPSL2 96d5ddbceSLemover* 106d5ddbceSLemover* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 116d5ddbceSLemover* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 126d5ddbceSLemover* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 136d5ddbceSLemover* 146d5ddbceSLemover* See the Mulan PSL v2 for more details. 156d5ddbceSLemover***************************************************************************************/ 166d5ddbceSLemover 176d5ddbceSLemoverpackage xiangshan.cache.mmu 186d5ddbceSLemover 198891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters 206d5ddbceSLemoverimport chisel3._ 216d5ddbceSLemoverimport chisel3.util._ 226d5ddbceSLemoverimport xiangshan._ 236d5ddbceSLemoverimport utils._ 243c02ee8fSwakafaimport utility._ 259aca92b9SYinan Xuimport xiangshan.backend.rob.RobPtr 266d5ddbceSLemoverimport xiangshan.backend.fu.util.HasCSRConst 276d5ddbceSLemoverimport freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} 286d5ddbceSLemoverimport freechips.rocketchip.tilelink._ 295b7ef044SLemoverimport xiangshan.backend.fu.{PMPReqBundle, PMPConfig} 30f1fe8698SLemoverimport xiangshan.backend.fu.PMPBundle 315b7ef044SLemover 326d5ddbceSLemover 336d5ddbceSLemoverabstract class TlbBundle(implicit p: Parameters) extends XSBundle with HasTlbConst 346d5ddbceSLemoverabstract class TlbModule(implicit p: Parameters) extends XSModule with HasTlbConst 356d5ddbceSLemover 36a0301c0dSLemover 376d5ddbceSLemoverclass PtePermBundle(implicit p: Parameters) extends TlbBundle { 386d5ddbceSLemover val d = Bool() 396d5ddbceSLemover val a = Bool() 406d5ddbceSLemover val g = Bool() 416d5ddbceSLemover val u = Bool() 426d5ddbceSLemover val x = Bool() 436d5ddbceSLemover val w = Bool() 446d5ddbceSLemover val r = Bool() 456d5ddbceSLemover 466d5ddbceSLemover override def toPrintable: Printable = { 476d5ddbceSLemover p"d:${d} a:${a} g:${g} u:${u} x:${x} w:${w} r:${r}"// + 486d5ddbceSLemover //(if(hasV) (p"v:${v}") else p"") 496d5ddbceSLemover } 506d5ddbceSLemover} 516d5ddbceSLemover 525b7ef044SLemoverclass TlbPMBundle(implicit p: Parameters) extends TlbBundle { 535b7ef044SLemover val r = Bool() 545b7ef044SLemover val w = Bool() 555b7ef044SLemover val x = Bool() 565b7ef044SLemover val c = Bool() 575b7ef044SLemover val atomic = Bool() 585b7ef044SLemover 595b7ef044SLemover def assign_ap(pm: PMPConfig) = { 605b7ef044SLemover r := pm.r 615b7ef044SLemover w := pm.w 625b7ef044SLemover x := pm.x 635b7ef044SLemover c := pm.c 645b7ef044SLemover atomic := pm.atomic 655b7ef044SLemover } 665b7ef044SLemover} 675b7ef044SLemover 686d5ddbceSLemoverclass TlbPermBundle(implicit p: Parameters) extends TlbBundle { 696d5ddbceSLemover val pf = Bool() // NOTE: if this is true, just raise pf 70b6982e83SLemover val af = Bool() // NOTE: if this is true, just raise af 716d5ddbceSLemover // pagetable perm (software defined) 726d5ddbceSLemover val d = Bool() 736d5ddbceSLemover val a = Bool() 746d5ddbceSLemover val g = Bool() 756d5ddbceSLemover val u = Bool() 766d5ddbceSLemover val x = Bool() 776d5ddbceSLemover val w = Bool() 786d5ddbceSLemover val r = Bool() 796d5ddbceSLemover 80f9ac118cSHaoyuan Feng def apply(item: PtwSectorResp) = { 81b0fa7106SHaoyuan Feng val ptePerm = item.entry.perm.get.asTypeOf(new PtePermBundle().cloneType) 82b0fa7106SHaoyuan Feng this.pf := item.pf 83b0fa7106SHaoyuan Feng this.af := item.af 84b0fa7106SHaoyuan Feng this.d := ptePerm.d 85b0fa7106SHaoyuan Feng this.a := ptePerm.a 86b0fa7106SHaoyuan Feng this.g := ptePerm.g 87b0fa7106SHaoyuan Feng this.u := ptePerm.u 88b0fa7106SHaoyuan Feng this.x := ptePerm.x 89b0fa7106SHaoyuan Feng this.w := ptePerm.w 90b0fa7106SHaoyuan Feng this.r := ptePerm.r 91b0fa7106SHaoyuan Feng 92b0fa7106SHaoyuan Feng this 93b0fa7106SHaoyuan Feng } 94*d0de7e4aSpeixiaokun 95*d0de7e4aSpeixiaokun def applyS2(item: HptwResp, pm: PMPConfig) = { 96*d0de7e4aSpeixiaokun val ptePerm = item.entry.perm.get.asTypeOf(new PtePermBundle().cloneType) 97*d0de7e4aSpeixiaokun this.pf := item.gpf 98*d0de7e4aSpeixiaokun this.af := item.gaf 99*d0de7e4aSpeixiaokun this.d := ptePerm.d 100*d0de7e4aSpeixiaokun this.a := ptePerm.a 101*d0de7e4aSpeixiaokun this.g := ptePerm.g 102*d0de7e4aSpeixiaokun this.u := ptePerm.u 103*d0de7e4aSpeixiaokun this.x := ptePerm.x 104*d0de7e4aSpeixiaokun this.w := ptePerm.w 105*d0de7e4aSpeixiaokun this.r := ptePerm.r 106*d0de7e4aSpeixiaokun 107*d0de7e4aSpeixiaokun this 108*d0de7e4aSpeixiaokun } 109b0fa7106SHaoyuan Feng override def toPrintable: Printable = { 110f9ac118cSHaoyuan Feng p"pf:${pf} af:${af} d:${d} a:${a} g:${g} u:${u} x:${x} w:${w} r:${r} " 111b0fa7106SHaoyuan Feng } 112b0fa7106SHaoyuan Feng} 113b0fa7106SHaoyuan Feng 114b0fa7106SHaoyuan Fengclass TlbSectorPermBundle(implicit p: Parameters) extends TlbBundle { 115b0fa7106SHaoyuan Feng val pf = Bool() // NOTE: if this is true, just raise pf 116b0fa7106SHaoyuan Feng val af = Bool() // NOTE: if this is true, just raise af 117b0fa7106SHaoyuan Feng // pagetable perm (software defined) 118b0fa7106SHaoyuan Feng val d = Bool() 119b0fa7106SHaoyuan Feng val a = Bool() 120b0fa7106SHaoyuan Feng val g = Bool() 121b0fa7106SHaoyuan Feng val u = Bool() 122b0fa7106SHaoyuan Feng val x = Bool() 123b0fa7106SHaoyuan Feng val w = Bool() 124b0fa7106SHaoyuan Feng val r = Bool() 125b0fa7106SHaoyuan Feng 126f9ac118cSHaoyuan Feng def apply(item: PtwSectorResp) = { 127f1fe8698SLemover val ptePerm = item.entry.perm.get.asTypeOf(new PtePermBundle().cloneType) 128f1fe8698SLemover this.pf := item.pf 129f1fe8698SLemover this.af := item.af 130f1fe8698SLemover this.d := ptePerm.d 131f1fe8698SLemover this.a := ptePerm.a 132f1fe8698SLemover this.g := ptePerm.g 133f1fe8698SLemover this.u := ptePerm.u 134f1fe8698SLemover this.x := ptePerm.x 135f1fe8698SLemover this.w := ptePerm.w 136f1fe8698SLemover this.r := ptePerm.r 137f1fe8698SLemover 138f1fe8698SLemover this 139f1fe8698SLemover } 1406d5ddbceSLemover override def toPrintable: Printable = { 141f9ac118cSHaoyuan Feng p"pf:${pf} af:${af} d:${d} a:${a} g:${g} u:${u} x:${x} w:${w} r:${r} " 1426d5ddbceSLemover } 1436d5ddbceSLemover} 1446d5ddbceSLemover 1456d5ddbceSLemover// multi-read && single-write 1466d5ddbceSLemover// input is data, output is hot-code(not one-hot) 1476d5ddbceSLemoverclass CAMTemplate[T <: Data](val gen: T, val set: Int, val readWidth: Int)(implicit p: Parameters) extends TlbModule { 1486d5ddbceSLemover val io = IO(new Bundle { 1496d5ddbceSLemover val r = new Bundle { 1506d5ddbceSLemover val req = Input(Vec(readWidth, gen)) 1516d5ddbceSLemover val resp = Output(Vec(readWidth, Vec(set, Bool()))) 1526d5ddbceSLemover } 1536d5ddbceSLemover val w = Input(new Bundle { 1546d5ddbceSLemover val valid = Bool() 1556d5ddbceSLemover val bits = new Bundle { 1566d5ddbceSLemover val index = UInt(log2Up(set).W) 1576d5ddbceSLemover val data = gen 1586d5ddbceSLemover } 1596d5ddbceSLemover }) 1606d5ddbceSLemover }) 1616d5ddbceSLemover 1626d5ddbceSLemover val wordType = UInt(gen.getWidth.W) 1636d5ddbceSLemover val array = Reg(Vec(set, wordType)) 1646d5ddbceSLemover 1656d5ddbceSLemover io.r.resp.zipWithIndex.map{ case (a,i) => 1666d5ddbceSLemover a := array.map(io.r.req(i).asUInt === _) 1676d5ddbceSLemover } 1686d5ddbceSLemover 1696d5ddbceSLemover when (io.w.valid) { 17076e02f07SLingrui98 array(io.w.bits.index) := io.w.bits.data.asUInt 1716d5ddbceSLemover } 1726d5ddbceSLemover} 1736d5ddbceSLemover 174a0301c0dSLemoverclass TlbEntry(pageNormal: Boolean, pageSuper: Boolean)(implicit p: Parameters) extends TlbBundle { 175a0301c0dSLemover require(pageNormal || pageSuper) 176a0301c0dSLemover 177a0301c0dSLemover val tag = if (!pageNormal) UInt((vpnLen - vpnnLen).W) 178b0fa7106SHaoyuan Feng else UInt(vpnLen.W) 179b0fa7106SHaoyuan Feng val asid = UInt(asidLen.W) 180b0fa7106SHaoyuan Feng val level = if (!pageNormal) Some(UInt(1.W)) 181b0fa7106SHaoyuan Feng else if (!pageSuper) None 182b0fa7106SHaoyuan Feng else Some(UInt(2.W)) 183b0fa7106SHaoyuan Feng val ppn = if (!pageNormal) UInt((ppnLen - vpnnLen).W) 184b0fa7106SHaoyuan Feng else UInt(ppnLen.W) 185b0fa7106SHaoyuan Feng val perm = new TlbPermBundle 186b0fa7106SHaoyuan Feng 187*d0de7e4aSpeixiaokun val ppnS2 = UInt(ppnLen.W) 188*d0de7e4aSpeixiaokun val gvpn = if (!pageNormal) UInt((gvpnLen - vpnnLen).W) 189*d0de7e4aSpeixiaokun else UInt(gvpnLen.W) 190*d0de7e4aSpeixiaokun val g_level = UInt(2.W) 191*d0de7e4aSpeixiaokun val g_perm = new TlbPermBundle 192*d0de7e4aSpeixiaokun val vmid = UInt(vmidLen.W) 193*d0de7e4aSpeixiaokun val s2xlate = UInt(2.U) 194*d0de7e4aSpeixiaokun 195*d0de7e4aSpeixiaokun /** s2xlate usage: 196*d0de7e4aSpeixiaokun * bits0 0: disable s2xlate 197*d0de7e4aSpeixiaokun * 1: enable s2xlate 198*d0de7e4aSpeixiaokun * bits1 0: stage 1 and stage 2 if bits0 is 1 199*d0de7e4aSpeixiaokun * 1: Only stage 2 if bits0 is 1 200*d0de7e4aSpeixiaokun * */ 201*d0de7e4aSpeixiaokun 202b0fa7106SHaoyuan Feng /** level usage: 203b0fa7106SHaoyuan Feng * !PageSuper: page is only normal, level is None, match all the tag 204b0fa7106SHaoyuan Feng * !PageNormal: page is only super, level is a Bool(), match high 9*2 parts 205b0fa7106SHaoyuan Feng * bits0 0: need mid 9bits 206b0fa7106SHaoyuan Feng * 1: no need mid 9bits 207b0fa7106SHaoyuan Feng * PageSuper && PageNormal: page hold all the three type, 208b0fa7106SHaoyuan Feng * bits0 0: need low 9bits 209b0fa7106SHaoyuan Feng * bits1 0: need mid 9bits 210b0fa7106SHaoyuan Feng */ 211b0fa7106SHaoyuan Feng 212*d0de7e4aSpeixiaokun def hit_S2(gvpn_in: UInt, vmid: UInt, ignoreVmid: Boolean = false): Bool = { 213*d0de7e4aSpeixiaokun val vmid_hit = if (ignoreVmid) true.B else this.vmid === vmid 214*d0de7e4aSpeixiaokun val gvpn_match_hi = gvpn(gvpnLen - 1, vpnnLen * 2) === gvpn_in(gvpnLen - 1, vpnnLen * 2) 215*d0de7e4aSpeixiaokun val gvpn_match_mi = gvpn(vpnnLen * 2 - 1, vpnnLen * 1) === gvpn_in(vpnnLen * 2 - 1, vpnnLen * 1) 216*d0de7e4aSpeixiaokun val gvpn_match_lo = gvpn(vpnnLen - 1, 0) === gvpn_in(vpnnLen - 1, 0) 217*d0de7e4aSpeixiaokun vmid_hit && gvpn_match_hi && (g_level(1) || gvpn_match_mi) && (g_level(0) || gvpn_match_lo) 218*d0de7e4aSpeixiaokun } 219*d0de7e4aSpeixiaokun 220*d0de7e4aSpeixiaokun def hit(vpn: UInt, asid: UInt, nSets: Int = 1, ignoreAsid: Boolean = false, vmid: UInt, s2xlate: Bool): Bool = { 221b0fa7106SHaoyuan Feng val asid_hit = if (ignoreAsid) true.B else (this.asid === asid) 222*d0de7e4aSpeixiaokun val vmid_hit = Mux(s2xlate, this.vmid === vmid, true.B) 223b0fa7106SHaoyuan Feng 224b0fa7106SHaoyuan Feng // NOTE: for timing, dont care low set index bits at hit check 225b0fa7106SHaoyuan Feng // do not need store the low bits actually 226*d0de7e4aSpeixiaokun if (!pageSuper) asid_hit && drop_set_equal(vpn, tag, nSets) && vmid_hit 227b0fa7106SHaoyuan Feng else if (!pageNormal) { 228b0fa7106SHaoyuan Feng val tag_match_hi = tag(vpnnLen*2-1, vpnnLen) === vpn(vpnnLen*3-1, vpnnLen*2) 229b0fa7106SHaoyuan Feng val tag_match_mi = tag(vpnnLen-1, 0) === vpn(vpnnLen*2-1, vpnnLen) 230935edac4STang Haojin val tag_match = tag_match_hi && (level.get.asBool || tag_match_mi) 231*d0de7e4aSpeixiaokun asid_hit && tag_match && vmid_hit 232b0fa7106SHaoyuan Feng } 233b0fa7106SHaoyuan Feng else { 234b0fa7106SHaoyuan Feng val tmp_level = level.get 235b0fa7106SHaoyuan Feng val tag_match_hi = tag(vpnnLen*3-1, vpnnLen*2) === vpn(vpnnLen*3-1, vpnnLen*2) 236b0fa7106SHaoyuan Feng val tag_match_mi = tag(vpnnLen*2-1, vpnnLen) === vpn(vpnnLen*2-1, vpnnLen) 237b0fa7106SHaoyuan Feng val tag_match_lo = tag(vpnnLen-1, 0) === vpn(vpnnLen-1, 0) // if pageNormal is false, this will always be false 238b0fa7106SHaoyuan Feng val tag_match = tag_match_hi && (tmp_level(1) || tag_match_mi) && (tmp_level(0) || tag_match_lo) 239*d0de7e4aSpeixiaokun asid_hit && tag_match && vmid_hit 240b0fa7106SHaoyuan Feng } 241b0fa7106SHaoyuan Feng } 242b0fa7106SHaoyuan Feng 243*d0de7e4aSpeixiaokun def apply(item: PtwRespS2, pm: PMPConfig): TlbEntry = { 244*d0de7e4aSpeixiaokun this.tag := {if (pageNormal) Cat(item.s1.entry.tag, OHToUInt(item.s1.pteidx)) else item.s1.entry.tag(sectorvpnLen - 1, vpnnLen - sectortlbwidth)} 245*d0de7e4aSpeixiaokun this.asid := item.s1.entry.asid 246b0fa7106SHaoyuan Feng val inner_level = item.entry.level.getOrElse(0.U) 24745f43e6eSTang Haojin this.level.map(_ := { if (pageNormal && pageSuper) MuxLookup(inner_level, 0.U)(Seq( 248b0fa7106SHaoyuan Feng 0.U -> 3.U, 249b0fa7106SHaoyuan Feng 1.U -> 1.U, 250b0fa7106SHaoyuan Feng 2.U -> 0.U )) 251b0fa7106SHaoyuan Feng else if (pageSuper) ~inner_level(0) 252b0fa7106SHaoyuan Feng else 0.U }) 253*d0de7e4aSpeixiaokun this.ppn := { if (!pageNormal) item.s1.entry.ppn(sectorppnLen - 1, vpnnLen - sectortlbwidth) 254*d0de7e4aSpeixiaokun else Cat(item.s1.entry.ppn, item.s1.ppn_low(OHToUInt(item.s1.pteidx))) } 255*d0de7e4aSpeixiaokun this.perm.apply(item.s1) 256*d0de7e4aSpeixiaokun this.vmid := item.s1.entry.vmid 257*d0de7e4aSpeixiaokun this.gvpn := { if (!pageNormal) item.s2.entry.tag(gvpnLen - 1, vpnnLen) 258*d0de7e4aSpeixiaokun else item.s2.entry.tag} 259*d0de7e4aSpeixiaokun this.g_perm.applyS2(item.s2, pm) 260*d0de7e4aSpeixiaokun this.ppnS2 := item.s2.entry.ppn 261*d0de7e4aSpeixiaokun val g_inner_level = item.s2.entry.level.getOrElse(0.U) 262*d0de7e4aSpeixiaokun this.g_level := { 263*d0de7e4aSpeixiaokun MuxLookup(g_inner_level, 0.U,Seq( 264*d0de7e4aSpeixiaokun 0.U -> 3.U, 265*d0de7e4aSpeixiaokun 1.U -> 1.U, 266*d0de7e4aSpeixiaokun 2.U -> 0.U)) 267*d0de7e4aSpeixiaokun } 268b0fa7106SHaoyuan Feng this 269b0fa7106SHaoyuan Feng } 270b0fa7106SHaoyuan Feng 271b0fa7106SHaoyuan Feng // 4KB is normal entry, 2MB/1GB is considered as super entry 272b0fa7106SHaoyuan Feng def is_normalentry(): Bool = { 273b0fa7106SHaoyuan Feng if (!pageSuper) { true.B } 274b0fa7106SHaoyuan Feng else if (!pageNormal) { false.B } 275b0fa7106SHaoyuan Feng else { level.get === 0.U } 276b0fa7106SHaoyuan Feng } 277b0fa7106SHaoyuan Feng 278*d0de7e4aSpeixiaokun def genGVPN(saveLevel: Boolean = false, valid: Bool = false.B)(vpn: UInt): UInt = { 279*d0de7e4aSpeixiaokun val inner_level = level.getOrElse(0.U) 280*d0de7e4aSpeixiaokun val gvpn_res = if (!pageSuper) gvpn 281*d0de7e4aSpeixiaokun else if (!pageNormal) Cat(gvpn(gvpnLen - vpnnLen - 1, vpnnLen), 282*d0de7e4aSpeixiaokun Mux(inner_level(0), vpn(vpnnLen * 2 - 1, vpnnLen), gvpn(vpnnLen - 1, 0)), 283*d0de7e4aSpeixiaokun vpn(vpnnLen - 1, 0)) 284*d0de7e4aSpeixiaokun else Cat(gvpn(gvpnLen - 1, vpnnLen * 2), 285*d0de7e4aSpeixiaokun Mux(inner_level(1), vpn(vpnnLen * 2 - 1, vpnnLen), gvpn(vpnnLen * 2 - 1, vpnnLen)), 286*d0de7e4aSpeixiaokun Mux(inner_level(0), vpn(vpnnLen - 1, 0), gvpn(vpnnLen - 1, 0))) 287*d0de7e4aSpeixiaokun 288*d0de7e4aSpeixiaokun if (saveLevel) Cat(gvpn(gvpn.getWidth - 1, vpnnLen * 2), RegEnable(gvpn_res(vpnnLen * 2 - 1, 0), valid)) 289*d0de7e4aSpeixiaokun else gvpn_res 290*d0de7e4aSpeixiaokun } 291*d0de7e4aSpeixiaokun 292*d0de7e4aSpeixiaokun def genPPNS2(vpn: UInt, gvpn_in: UInt, OnlyS2: Bool) = { 293*d0de7e4aSpeixiaokun val inner_level = level.getOrElse(0.U) 294*d0de7e4aSpeixiaokun val gvpn_tmp = if (!pageSuper) gvpn 295*d0de7e4aSpeixiaokun else if (!pageNormal) Cat(gvpn(gvpnLen - vpnnLen - 1, vpnnLen), 296*d0de7e4aSpeixiaokun Mux(inner_level(0), vpn(vpnnLen * 2 - 1, vpnnLen), gvpn(vpnnLen - 1, 0)), 297*d0de7e4aSpeixiaokun vpn(vpnnLen - 1, 0)) 298*d0de7e4aSpeixiaokun else Cat(gvpn(gvpnLen - 1, vpnnLen * 2), 299*d0de7e4aSpeixiaokun Mux(inner_level(1), vpn(vpnnLen * 2 - 1, vpnnLen), gvpn(vpnnLen * 2 - 1, vpnnLen)), 300*d0de7e4aSpeixiaokun Mux(inner_level(0), vpn(vpnnLen - 1, 0), gvpn(vpnnLen - 1, 0))) 301*d0de7e4aSpeixiaokun 302*d0de7e4aSpeixiaokun val gvpn_res = Mux(OnlyS2, gvpn_in, gvpn_tmp) 303*d0de7e4aSpeixiaokun val ppn_res = Cat(ppn(ppnLen - 1, vpnnLen * 2), 304*d0de7e4aSpeixiaokun Mux(g_level(1), gvpn_res(vpnnLen * 2 - 1, vpnnLen), ppn(vpnnLen * 2 - 1, vpnnLen)), 305*d0de7e4aSpeixiaokun Mux(g_level(0), vpn(vpnnLen - 1, 0), ppn(vpnnLen - 1, 0))) 306*d0de7e4aSpeixiaokun 307*d0de7e4aSpeixiaokun ppn_res 308*d0de7e4aSpeixiaokun } 309*d0de7e4aSpeixiaokun 310b0fa7106SHaoyuan Feng def genPPN(saveLevel: Boolean = false, valid: Bool = false.B)(vpn: UInt) : UInt = { 311b0fa7106SHaoyuan Feng val inner_level = level.getOrElse(0.U) 312b0fa7106SHaoyuan Feng val ppn_res = if (!pageSuper) ppn 313b0fa7106SHaoyuan Feng else if (!pageNormal) Cat(ppn(ppnLen-vpnnLen-1, vpnnLen), 314b0fa7106SHaoyuan Feng Mux(inner_level(0), vpn(vpnnLen*2-1, vpnnLen), ppn(vpnnLen-1,0)), 315b0fa7106SHaoyuan Feng vpn(vpnnLen-1, 0)) 316b0fa7106SHaoyuan Feng else Cat(ppn(ppnLen-1, vpnnLen*2), 317b0fa7106SHaoyuan Feng Mux(inner_level(1), vpn(vpnnLen*2-1, vpnnLen), ppn(vpnnLen*2-1, vpnnLen)), 318b0fa7106SHaoyuan Feng Mux(inner_level(0), vpn(vpnnLen-1, 0), ppn(vpnnLen-1, 0))) 319b0fa7106SHaoyuan Feng 320b0fa7106SHaoyuan Feng if (saveLevel) Cat(ppn(ppn.getWidth-1, vpnnLen*2), RegEnable(ppn_res(vpnnLen*2-1, 0), valid)) 321b0fa7106SHaoyuan Feng else ppn_res 322b0fa7106SHaoyuan Feng } 323b0fa7106SHaoyuan Feng 324b0fa7106SHaoyuan Feng override def toPrintable: Printable = { 325b0fa7106SHaoyuan Feng val inner_level = level.getOrElse(2.U) 326b0fa7106SHaoyuan Feng p"asid: ${asid} level:${inner_level} vpn:${Hexadecimal(tag)} ppn:${Hexadecimal(ppn)} perm:${perm}" 327b0fa7106SHaoyuan Feng } 328b0fa7106SHaoyuan Feng 329b0fa7106SHaoyuan Feng} 330b0fa7106SHaoyuan Feng 331b0fa7106SHaoyuan Fengclass TlbSectorEntry(pageNormal: Boolean, pageSuper: Boolean)(implicit p: Parameters) extends TlbBundle { 332b0fa7106SHaoyuan Feng require(pageNormal || pageSuper) 333b0fa7106SHaoyuan Feng 334b0fa7106SHaoyuan Feng val tag = if (!pageNormal) UInt((vpnLen - vpnnLen).W) 33563632028SHaoyuan Feng else UInt(sectorvpnLen.W) 33645f497a4Shappy-lx val asid = UInt(asidLen.W) 337a0301c0dSLemover val level = if (!pageNormal) Some(UInt(1.W)) 338a0301c0dSLemover else if (!pageSuper) None 339a0301c0dSLemover else Some(UInt(2.W)) 340a0301c0dSLemover val ppn = if (!pageNormal) UInt((ppnLen - vpnnLen).W) 341*d0de7e4aSpeixiaokun else UInt(sectorppnLen.W) //only used when disable s2xlate 342b0fa7106SHaoyuan Feng val perm = new TlbSectorPermBundle 34363632028SHaoyuan Feng val valididx = Vec(tlbcontiguous, Bool()) 344b0fa7106SHaoyuan Feng val pteidx = Vec(tlbcontiguous, Bool()) 345*d0de7e4aSpeixiaokun val ppn_low = Vec(tlbcontiguous, UInt(sectortlbwidth.W)) // it is gvpn_low when enable s2xlate 346*d0de7e4aSpeixiaokun 347*d0de7e4aSpeixiaokun val ppnS2 = UInt(ppnLen.W) //only used when enable s2xlate 348*d0de7e4aSpeixiaokun val gvpn = if (!pageNormal) UInt((gvpnLen - vpnnLen).W) 349*d0de7e4aSpeixiaokun else UInt(sectorgvpnLen.W) 350*d0de7e4aSpeixiaokun val g_level = UInt(2.W) 351*d0de7e4aSpeixiaokun val g_perm = new TlbPermBundle 352*d0de7e4aSpeixiaokun val vmid = UInt(vmidLen.W) 353*d0de7e4aSpeixiaokun val s2xlate = UInt(2.U) 354*d0de7e4aSpeixiaokun 355*d0de7e4aSpeixiaokun /** s2xlate usage: 356*d0de7e4aSpeixiaokun * bits0 0: disable s2xlate 357*d0de7e4aSpeixiaokun * 1: enable s2xlate 358*d0de7e4aSpeixiaokun * bits1 0: stage 1 and stage 2 if bits0 is 1 359*d0de7e4aSpeixiaokun * 1: Only stage 2 if bits0 is 1 360*d0de7e4aSpeixiaokun * */ 361a0301c0dSLemover 36256728e73SLemover /** level usage: 36356728e73SLemover * !PageSuper: page is only normal, level is None, match all the tag 36456728e73SLemover * !PageNormal: page is only super, level is a Bool(), match high 9*2 parts 36556728e73SLemover * bits0 0: need mid 9bits 36656728e73SLemover * 1: no need mid 9bits 36756728e73SLemover * PageSuper && PageNormal: page hold all the three type, 36856728e73SLemover * bits0 0: need low 9bits 36956728e73SLemover * bits1 0: need mid 9bits 37056728e73SLemover */ 37156728e73SLemover 372*d0de7e4aSpeixiaokun // for Only stage 2 translation 373*d0de7e4aSpeixiaokun def hit_S2(gvpn_in: UInt, vmid: UInt, ignoreVmid: Boolean = false): Bool = { 374*d0de7e4aSpeixiaokun val vmid_hit = if (ignoreVmid) true.B else this.vmid === vmid 375*d0de7e4aSpeixiaokun val inner_gvpn = Cat(gvpn, ppn_low(OHToUInt(pteidx))) 376*d0de7e4aSpeixiaokun val gvpn_match_hi = inner_gvpn(gvpnLen - 1, vpnnLen * 2) === gvpn_in(gvpnLen - 1, vpnnLen * 2) 377*d0de7e4aSpeixiaokun val gvpn_match_mi = inner_gvpn(vpnnLen * 2 - 1, vpnnLen * 1) === gvpn_in(vpnnLen * 2 - 1, vpnnLen * 1) 378*d0de7e4aSpeixiaokun val gvpn_match_lo = inner_gvpn(vpnnLen - 1, 0) === gvpn_in(vpnnLen - 1, 0) 379*d0de7e4aSpeixiaokun vmid_hit && gvpn_match_hi && (g_level(1) || gvpn_match_mi) && (g_level(0) || gvpn_match_lo) 380*d0de7e4aSpeixiaokun } 381*d0de7e4aSpeixiaokun 382*d0de7e4aSpeixiaokun def hit(vpn: UInt, asid: UInt, nSets: Int = 1, ignoreAsid: Boolean = false, vmid: UInt, s2xlate: Bool): Bool = { 38345f497a4Shappy-lx val asid_hit = if (ignoreAsid) true.B else (this.asid === asid) 38463632028SHaoyuan Feng val addr_low_hit = valididx(vpn(2, 0)) 385*d0de7e4aSpeixiaokun val vmid_hit = Mux(s2xlate, this.vmid === vmid, true.B) 386*d0de7e4aSpeixiaokun 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 387e9092fe2SLemover // NOTE: for timing, dont care low set index bits at hit check 388e9092fe2SLemover // do not need store the low bits actually 389*d0de7e4aSpeixiaokun if (!pageSuper) asid_hit && drop_set_equal(vpn(vpn.getWidth - 1, sectortlbwidth), tag, nSets) && addr_low_hit && vmid_hit && pteidx_hit 39056728e73SLemover else if (!pageNormal) { 39156728e73SLemover val tag_match_hi = tag(vpnnLen * 2 - 1, vpnnLen) === vpn(vpnnLen * 3 - 1, vpnnLen * 2) 39256728e73SLemover val tag_match_mi = tag(vpnnLen - 1, 0) === vpn(vpnnLen * 2 - 1, vpnnLen) 393935edac4STang Haojin val tag_match = tag_match_hi && (level.get.asBool || tag_match_mi) 394*d0de7e4aSpeixiaokun asid_hit && tag_match && addr_low_hit && vmid_hit && pteidx_hit 39556728e73SLemover } 39656728e73SLemover else { 39756728e73SLemover val tmp_level = level.get 39863632028SHaoyuan Feng val tag_match_hi = tag(vpnnLen * 3 - sectortlbwidth - 1, vpnnLen * 2 - sectortlbwidth) === vpn(vpnnLen * 3 - 1, vpnnLen * 2) 39963632028SHaoyuan Feng val tag_match_mi = tag(vpnnLen * 2 - sectortlbwidth - 1, vpnnLen - sectortlbwidth) === vpn(vpnnLen * 2 - 1, vpnnLen) 40063632028SHaoyuan Feng val tag_match_lo = tag(vpnnLen - sectortlbwidth - 1, 0) === vpn(vpnnLen - 1, sectortlbwidth) // if pageNormal is false, this will always be false 40156728e73SLemover val tag_match = tag_match_hi && (tmp_level(1) || tag_match_mi) && (tmp_level(0) || tag_match_lo) 402*d0de7e4aSpeixiaokun asid_hit && tag_match && addr_low_hit && vmid_hit && pteidx_hit 40356728e73SLemover } 404a0301c0dSLemover } 405a0301c0dSLemover 40663632028SHaoyuan Feng def wbhit(data: PtwSectorResp, asid: UInt, nSets: Int = 1, ignoreAsid: Boolean = false): Bool = { 40763632028SHaoyuan Feng val vpn = Cat(data.entry.tag, 0.U(sectortlbwidth.W)) 40863632028SHaoyuan Feng val asid_hit = if (ignoreAsid) true.B else (this.asid === asid) 40963632028SHaoyuan Feng val vpn_hit = Wire(Bool()) 41063632028SHaoyuan Feng val index_hit = Wire(Vec(tlbcontiguous, Bool())) 41163632028SHaoyuan Feng 41263632028SHaoyuan Feng // NOTE: for timing, dont care low set index bits at hit check 41363632028SHaoyuan Feng // do not need store the low bits actually 41463632028SHaoyuan Feng if (!pageSuper) { 41563632028SHaoyuan Feng vpn_hit := asid_hit && drop_set_equal(vpn(vpn.getWidth - 1, sectortlbwidth), tag, nSets) 41663632028SHaoyuan Feng } 41763632028SHaoyuan Feng else if (!pageNormal) { 41863632028SHaoyuan Feng val tag_match_hi = tag(vpnnLen * 2 - 1, vpnnLen - sectortlbwidth) === vpn(vpnnLen * 3 - 1, vpnnLen * 2) 41963632028SHaoyuan Feng val tag_match_mi = tag(vpnnLen - 1, 0) === vpn(vpnnLen * 2 - 1, vpnnLen) 420935edac4STang Haojin val tag_match = tag_match_hi && (level.get.asBool || tag_match_mi) 42163632028SHaoyuan Feng vpn_hit := asid_hit && tag_match 42263632028SHaoyuan Feng } 42363632028SHaoyuan Feng else { 42463632028SHaoyuan Feng val tmp_level = level.get 42563632028SHaoyuan Feng val tag_match_hi = tag(vpnnLen * 3 - sectortlbwidth - 1, vpnnLen * 2 - sectortlbwidth) === vpn(vpnnLen * 3 - 1, vpnnLen * 2) 42663632028SHaoyuan Feng val tag_match_mi = tag(vpnnLen * 2 - sectortlbwidth - 1, vpnnLen - sectortlbwidth) === vpn(vpnnLen * 2 - 1, vpnnLen) 42763632028SHaoyuan Feng val tag_match_lo = tag(vpnnLen - sectortlbwidth - 1, 0) === vpn(vpnnLen - 1, sectortlbwidth) // if pageNormal is false, this will always be false 42863632028SHaoyuan Feng val tag_match = tag_match_hi && (tmp_level(1) || tag_match_mi) && (tmp_level(0) || tag_match_lo) 42963632028SHaoyuan Feng vpn_hit := asid_hit && tag_match 43063632028SHaoyuan Feng } 43163632028SHaoyuan Feng 43263632028SHaoyuan Feng for (i <- 0 until tlbcontiguous) { 43363632028SHaoyuan Feng index_hit(i) := data.valididx(i) && valididx(i) 43463632028SHaoyuan Feng } 43563632028SHaoyuan Feng 43663632028SHaoyuan Feng // For example, tlb req to page cache with vpn 0x10 43763632028SHaoyuan Feng // At this time, 0x13 has not been paged, so page cache only resp 0x10 43863632028SHaoyuan Feng // When 0x13 refill to page cache, previous item will be flushed 43963632028SHaoyuan Feng // Now 0x10 and 0x13 are both valid in page cache 44063632028SHaoyuan Feng // However, when 0x13 refill to tlb, will trigger multi hit 44163632028SHaoyuan Feng // So will only trigger multi-hit when PopCount(data.valididx) = 1 44263632028SHaoyuan Feng vpn_hit && index_hit.reduce(_ || _) && PopCount(data.valididx) === 1.U 44363632028SHaoyuan Feng } 44463632028SHaoyuan Feng 445*d0de7e4aSpeixiaokun def apply(item: PtwRespS2): TlbSectorEntry = { 446*d0de7e4aSpeixiaokun this.tag := {if (pageNormal) item.s1.entry.tag else item.s1.entry.tag(sectorvpnLen - 1, vpnnLen - sectortlbwidth)} 447*d0de7e4aSpeixiaokun this.asid := item.s1.entry.asid 448*d0de7e4aSpeixiaokun val inner_level = item.s1.entry.level.getOrElse(0.U) 44945f43e6eSTang Haojin this.level.map(_ := { if (pageNormal && pageSuper) MuxLookup(inner_level, 0.U)(Seq( 45056728e73SLemover 0.U -> 3.U, 45156728e73SLemover 1.U -> 1.U, 45256728e73SLemover 2.U -> 0.U )) 45356728e73SLemover else if (pageSuper) ~inner_level(0) 454a0301c0dSLemover else 0.U }) 455*d0de7e4aSpeixiaokun this.ppn := {if (!pageNormal) item.s1.entry.ppn(sectorppnLen - 1, vpnnLen - sectortlbwidth) else item.s1.entry.ppn} 456*d0de7e4aSpeixiaokun this.perm.apply(item.s1) 457*d0de7e4aSpeixiaokun this.ppn_low := item.s1.ppn_low 458*d0de7e4aSpeixiaokun this.valididx := item.s1.valididx 459*d0de7e4aSpeixiaokun this.pteidx := item.s1.pteidx 460*d0de7e4aSpeixiaokun 461*d0de7e4aSpeixiaokun this.vmid := item.s1.entry.vmid 462*d0de7e4aSpeixiaokun this.gvpn := {if (!pageNormal) item.s2.entry.tag(sectorgvpnLen - 1, vpnnLen - sectortlbwidth) else item.s2.entry.tag(sectorgvpnLen - 1, sectortlbwidth)} 463*d0de7e4aSpeixiaokun this.g_perm.applyS2(item.s2, pm(0)) 464*d0de7e4aSpeixiaokun this.ppnS2 := item.s2.entry.ppn 465*d0de7e4aSpeixiaokun val g_inner_level = item.s2.entry.level.getOrElse(0.U) 466*d0de7e4aSpeixiaokun this.g_level := { 467*d0de7e4aSpeixiaokun MuxLookup(g_inner_level, 0.U, Seq( 468*d0de7e4aSpeixiaokun 0.U -> 3.U, 469*d0de7e4aSpeixiaokun 1.U -> 1.U, 470*d0de7e4aSpeixiaokun 2.U -> 0.U)) 471*d0de7e4aSpeixiaokun } 472a0301c0dSLemover this 473a0301c0dSLemover } 474a0301c0dSLemover 47556728e73SLemover // 4KB is normal entry, 2MB/1GB is considered as super entry 47656728e73SLemover def is_normalentry(): Bool = { 47756728e73SLemover if (!pageSuper) { true.B } 47856728e73SLemover else if (!pageNormal) { false.B } 47956728e73SLemover else { level.get === 0.U } 48056728e73SLemover } 4815cf62c1aSLemover 482*d0de7e4aSpeixiaokun def genGVPN(saveLevel: Boolean = false, valid: Bool = false.B)(vpn: UInt): UInt = { 483*d0de7e4aSpeixiaokun val inner_level = level.getOrElse(0.U) 484*d0de7e4aSpeixiaokun val gvpn_res = if (!pageSuper) Cat(gvpn, ppn_low(vpn(sectortlbwidth - 1, 0))) 485*d0de7e4aSpeixiaokun else if (!pageNormal) Cat(gvpn(gvpnLen - vpnnLen - 1, vpnnLen), 486*d0de7e4aSpeixiaokun Mux(inner_level(0), vpn(vpnnLen * 2 - 1, vpnnLen), gvpn(vpnnLen - 1, 0)), 487*d0de7e4aSpeixiaokun vpn(vpnnLen - 1, 0)) 488*d0de7e4aSpeixiaokun else Cat(gvpn(sectorgvpnLen - 1, vpnnLen * 2 - sectortlbwidth), 489*d0de7e4aSpeixiaokun Mux(inner_level(1), vpn(vpnnLen * 2 - 1, vpnnLen), gvpn(vpnnLen * 2 - sectortlbwidth - 1, vpnnLen - sectortlbwidth)), 490*d0de7e4aSpeixiaokun Mux(inner_level(0), vpn(vpnnLen - 1, 0), Cat(gvpn(vpnnLen - sectortlbwidth - 1, 0), ppn_low(vpn(sectortlbwidth - 1, 0))))) 491*d0de7e4aSpeixiaokun 492*d0de7e4aSpeixiaokun if (saveLevel) { 493*d0de7e4aSpeixiaokun if (gvpn.getWidth == gvpnLen - vpnnLen) { 494*d0de7e4aSpeixiaokun Cat(gvpn(gvpn.getWidth - 1, vpnnLen * 2), RegEnable(gvpn_res(vpnnLen * 2 - 1, 0), valid)) 495*d0de7e4aSpeixiaokun } else { 496*d0de7e4aSpeixiaokun require(gvpn.getWidth == sectorgvpnLen) 497*d0de7e4aSpeixiaokun Cat(gvpn(gvpn.getWidth - 1, vpnnLen * 2 - sectortlbwidth), RegEnable(gvpn_res(vpnnLen * 2 - 1, 0), valid)) 498*d0de7e4aSpeixiaokun } 499*d0de7e4aSpeixiaokun } 500*d0de7e4aSpeixiaokun else gvpn_res 501*d0de7e4aSpeixiaokun } 502*d0de7e4aSpeixiaokun 503*d0de7e4aSpeixiaokun def genPPNS2(vpn:UInt, gvpn_in: UInt, OnlyS2: Bool) = { 504*d0de7e4aSpeixiaokun val inner_level = level.getOrElse(0.U) 505*d0de7e4aSpeixiaokun val gvpn_tmp = if (!pageSuper) Cat(gvpn, ppn_low(vpn(sectortlbwidth - 1, 0))) 506*d0de7e4aSpeixiaokun else if (!pageNormal) Cat(gvpn(gvpnLen - vpnnLen - 1, vpnnLen), 507*d0de7e4aSpeixiaokun Mux(inner_level(0), vpn(vpnnLen * 2 - 1, vpnnLen), gvpn(vpnnLen - 1, 0)), 508*d0de7e4aSpeixiaokun vpn(vpnnLen - 1, 0)) 509*d0de7e4aSpeixiaokun else Cat(gvpn(sectorgvpnLen - 1, vpnnLen * 2 - sectortlbwidth), 510*d0de7e4aSpeixiaokun Mux(inner_level(1), vpn(vpnnLen * 2 - 1, vpnnLen), gvpn(vpnnLen * 2 - sectortlbwidth - 1, vpnnLen - sectortlbwidth)), 511*d0de7e4aSpeixiaokun Mux(inner_level(0), vpn(vpnnLen - 1, 0), Cat(gvpn(vpnnLen - sectortlbwidth - 1, 0), ppn_low(vpn(sectortlbwidth - 1, 0))))) 512*d0de7e4aSpeixiaokun 513*d0de7e4aSpeixiaokun val gvpn_res = Mux(OnlyS2, gvpn_in, gvpn_tmp) 514*d0de7e4aSpeixiaokun val ppn_res = Cat(ppn(ppnLen - 1, vpnnLen * 2), 515*d0de7e4aSpeixiaokun Mux(g_level(1), gvpn_res(vpnnLen * 2 - 1, vpnnLen), ppn(vpnnLen * 2 - 1, vpnnLen)), 516*d0de7e4aSpeixiaokun Mux(g_level(0), vpn(vpnnLen - 1, 0), ppn(vpnnLen - 1, 0))) 517*d0de7e4aSpeixiaokun 518*d0de7e4aSpeixiaokun ppn_res 519*d0de7e4aSpeixiaokun } 520*d0de7e4aSpeixiaokun 52156728e73SLemover def genPPN(saveLevel: Boolean = false, valid: Bool = false.B)(vpn: UInt) : UInt = { 52256728e73SLemover val inner_level = level.getOrElse(0.U) 52363632028SHaoyuan Feng val ppn_res = if (!pageSuper) Cat(ppn, ppn_low(vpn(sectortlbwidth - 1, 0))) 52456728e73SLemover else if (!pageNormal) Cat(ppn(ppnLen - vpnnLen - 1, vpnnLen), 52556728e73SLemover Mux(inner_level(0), vpn(vpnnLen * 2 - 1, vpnnLen), ppn(vpnnLen - 1,0)), 52656728e73SLemover vpn(vpnnLen - 1, 0)) 52763632028SHaoyuan Feng else Cat(ppn(sectorppnLen - 1, vpnnLen * 2 - sectortlbwidth), 52863632028SHaoyuan Feng Mux(inner_level(1), vpn(vpnnLen * 2 - 1, vpnnLen), ppn(vpnnLen * 2 - sectortlbwidth - 1, vpnnLen - sectortlbwidth)), 52963632028SHaoyuan Feng Mux(inner_level(0), vpn(vpnnLen - 1, 0), Cat(ppn(vpnnLen - sectortlbwidth - 1, 0), ppn_low(vpn(sectortlbwidth - 1, 0))))) 53056728e73SLemover 53163632028SHaoyuan Feng if (saveLevel) { 53263632028SHaoyuan Feng if (ppn.getWidth == ppnLen - vpnnLen) { 53363632028SHaoyuan Feng Cat(ppn(ppn.getWidth - 1, vpnnLen * 2), RegEnable(ppn_res(vpnnLen * 2 - 1, 0), valid)) 53463632028SHaoyuan Feng } else { 53563632028SHaoyuan Feng require(ppn.getWidth == sectorppnLen) 53663632028SHaoyuan Feng Cat(ppn(ppn.getWidth - 1, vpnnLen * 2 - sectortlbwidth), RegEnable(ppn_res(vpnnLen * 2 - 1, 0), valid)) 53763632028SHaoyuan Feng } 53863632028SHaoyuan Feng } 5395cf62c1aSLemover else ppn_res 540a0301c0dSLemover } 541a0301c0dSLemover 542a0301c0dSLemover override def toPrintable: Printable = { 543a0301c0dSLemover val inner_level = level.getOrElse(2.U) 54445f497a4Shappy-lx p"asid: ${asid} level:${inner_level} vpn:${Hexadecimal(tag)} ppn:${Hexadecimal(ppn)} perm:${perm}" 545a0301c0dSLemover } 546a0301c0dSLemover 547a0301c0dSLemover} 548a0301c0dSLemover 5496d5ddbceSLemoverobject TlbCmd { 5506d5ddbceSLemover def read = "b00".U 5516d5ddbceSLemover def write = "b01".U 5526d5ddbceSLemover def exec = "b10".U 5536d5ddbceSLemover 5546d5ddbceSLemover def atom_read = "b100".U // lr 5556d5ddbceSLemover def atom_write = "b101".U // sc / amo 5566d5ddbceSLemover 5576d5ddbceSLemover def apply() = UInt(3.W) 5586d5ddbceSLemover def isRead(a: UInt) = a(1,0)===read 5596d5ddbceSLemover def isWrite(a: UInt) = a(1,0)===write 5606d5ddbceSLemover def isExec(a: UInt) = a(1,0)===exec 5616d5ddbceSLemover 5626d5ddbceSLemover def isAtom(a: UInt) = a(2) 563a79fef67Swakafa def isAmo(a: UInt) = a===atom_write // NOTE: sc mixed 5646d5ddbceSLemover} 5656d5ddbceSLemover 56603efd994Shappy-lxclass TlbStorageIO(nSets: Int, nWays: Int, ports: Int, nDups: Int = 1)(implicit p: Parameters) extends MMUIOBaseBundle { 567a0301c0dSLemover val r = new Bundle { 568a0301c0dSLemover val req = Vec(ports, Flipped(DecoupledIO(new Bundle { 569a0301c0dSLemover val vpn = Output(UInt(vpnLen.W)) 570*d0de7e4aSpeixiaokun val vpn_extend = Output(UInt(extendVpnBits.W)) // for gvpn, gvpn is longer than vpn 571*d0de7e4aSpeixiaokun 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 572a0301c0dSLemover }))) 573a0301c0dSLemover val resp = Vec(ports, ValidIO(new Bundle{ 574a0301c0dSLemover val hit = Output(Bool()) 57503efd994Shappy-lx val ppn = Vec(nDups, Output(UInt(ppnLen.W))) 576b0fa7106SHaoyuan Feng val perm = Vec(nDups, Output(new TlbSectorPermBundle())) 577*d0de7e4aSpeixiaokun val gvpn = Vec(nDups, Output(UInt(gvpnLen.W))) 578*d0de7e4aSpeixiaokun val g_perm = Vec(nDups, Output(new TlbPermBundle())) 579*d0de7e4aSpeixiaokun val s2xlate = Vec(nDups, Output(UInt(2.W))) 580a0301c0dSLemover })) 581a0301c0dSLemover } 582a0301c0dSLemover val w = Flipped(ValidIO(new Bundle { 583a0301c0dSLemover val wayIdx = Output(UInt(log2Up(nWays).W)) 584*d0de7e4aSpeixiaokun val data = Output(new PtwRespS2) 585a0301c0dSLemover })) 5863889e11eSLemover val access = Vec(ports, new ReplaceAccessBundle(nSets, nWays)) 587a0301c0dSLemover 588*d0de7e4aSpeixiaokun def r_req_apply(valid: Bool, vpn: UInt, i: Int, vpn_extend: UInt, s2xlate:UInt): Unit = { 589a0301c0dSLemover this.r.req(i).valid := valid 590a0301c0dSLemover this.r.req(i).bits.vpn := vpn 591*d0de7e4aSpeixiaokun this.r.req(i).bits.vpn_extend := vpn(gvpnLen, vpnLen - 1) 592*d0de7e4aSpeixiaokun this.r.req(i).bits.s2xlate := s2xlate 593*d0de7e4aSpeixiaokun 594a0301c0dSLemover } 595a0301c0dSLemover 596a0301c0dSLemover def r_resp_apply(i: Int) = { 597*d0de7e4aSpeixiaokun (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) 598a0301c0dSLemover } 599a0301c0dSLemover 600*d0de7e4aSpeixiaokun def w_apply(valid: Bool, wayIdx: UInt, data: PtwRespS2): Unit = { 601a0301c0dSLemover this.w.valid := valid 602a0301c0dSLemover this.w.bits.wayIdx := wayIdx 603a0301c0dSLemover this.w.bits.data := data 604a0301c0dSLemover } 605a0301c0dSLemover 606a0301c0dSLemover} 607a0301c0dSLemover 60803efd994Shappy-lxclass TlbStorageWrapperIO(ports: Int, q: TLBParameters, nDups: Int = 1)(implicit p: Parameters) extends MMUIOBaseBundle { 609f1fe8698SLemover val r = new Bundle { 610f1fe8698SLemover val req = Vec(ports, Flipped(DecoupledIO(new Bundle { 611f1fe8698SLemover val vpn = Output(UInt(vpnLen.W)) 612*d0de7e4aSpeixiaokun val vpn_extend = Output(UInt(extendVpnBits.W)) 613*d0de7e4aSpeixiaokun val s2xlate = Output(UInt(2.W)) 614f1fe8698SLemover }))) 615f1fe8698SLemover val resp = Vec(ports, ValidIO(new Bundle{ 616f1fe8698SLemover val hit = Output(Bool()) 61703efd994Shappy-lx val ppn = Vec(nDups, Output(UInt(ppnLen.W))) 61803efd994Shappy-lx val perm = Vec(nDups, Output(new TlbPermBundle())) 619*d0de7e4aSpeixiaokun val g_perm = Vec(nDups, Output(new TlbPermBundle())) 620*d0de7e4aSpeixiaokun val s2xlate = Vec(nDups, Output(UInt(2.W))) 621f1fe8698SLemover })) 622f1fe8698SLemover } 623f1fe8698SLemover val w = Flipped(ValidIO(new Bundle { 624*d0de7e4aSpeixiaokun val data = Output(new PtwRespS2) 625f1fe8698SLemover })) 626f1fe8698SLemover val replace = if (q.outReplace) Flipped(new TlbReplaceIO(ports, q)) else null 627f1fe8698SLemover 628*d0de7e4aSpeixiaokun def r_req_apply(valid: Bool, vpn: UInt, i: Int, s2xlate: UInt): Unit = { 629f1fe8698SLemover this.r.req(i).valid := valid 630f1fe8698SLemover this.r.req(i).bits.vpn := vpn 631*d0de7e4aSpeixiaokun this.r.req(i).bits.vpn_extend := vpn(gvpnLen, vpnLen - 1) 632*d0de7e4aSpeixiaokun this.r.req(i).bits.s2xlate := s2xlate 633f1fe8698SLemover } 634f1fe8698SLemover 635f1fe8698SLemover def r_resp_apply(i: Int) = { 636*d0de7e4aSpeixiaokun (this.r.resp(i).bits.hit, this.r.resp(i).bits.ppn, this.r.resp(i).bits.perm, 637*d0de7e4aSpeixiaokun this.r.resp(i).bits.super_hit, this.r.resp(i).bits.super_ppn, this.r.resp(i).bits.spm, 638*d0de7e4aSpeixiaokun this.r.resp(i).bits.gvpn, this.r.resp(i).bits.g_perm, this.r.resp(i).bits.s2xlate) 639f1fe8698SLemover } 640f1fe8698SLemover 641*d0de7e4aSpeixiaokun def w_apply(valid: Bool, data: PtwRespS2): Unit = { 642f1fe8698SLemover this.w.valid := valid 643f1fe8698SLemover this.w.bits.data := data 644f1fe8698SLemover } 645f1fe8698SLemover} 646f1fe8698SLemover 6473889e11eSLemoverclass ReplaceAccessBundle(nSets: Int, nWays: Int)(implicit p: Parameters) extends TlbBundle { 6483889e11eSLemover val sets = Output(UInt(log2Up(nSets).W)) 6493889e11eSLemover val touch_ways = ValidIO(Output(UInt(log2Up(nWays).W))) 6503889e11eSLemover} 6513889e11eSLemover 652a0301c0dSLemoverclass ReplaceIO(Width: Int, nSets: Int, nWays: Int)(implicit p: Parameters) extends TlbBundle { 6533889e11eSLemover val access = Vec(Width, Flipped(new ReplaceAccessBundle(nSets, nWays))) 654a0301c0dSLemover 655a0301c0dSLemover val refillIdx = Output(UInt(log2Up(nWays).W)) 656a0301c0dSLemover val chosen_set = Flipped(Output(UInt(log2Up(nSets).W))) 657a0301c0dSLemover 658a0301c0dSLemover def apply_sep(in: Seq[ReplaceIO], vpn: UInt): Unit = { 65953b8f1a7SLemover for ((ac_rep, ac_tlb) <- access.zip(in.map(a => a.access.map(b => b)).flatten)) { 66053b8f1a7SLemover ac_rep := ac_tlb 661a0301c0dSLemover } 66253b8f1a7SLemover this.chosen_set := get_set_idx(vpn, nSets) 66353b8f1a7SLemover in.map(a => a.refillIdx := this.refillIdx) 664a0301c0dSLemover } 665a0301c0dSLemover} 666a0301c0dSLemover 667a0301c0dSLemoverclass TlbReplaceIO(Width: Int, q: TLBParameters)(implicit p: Parameters) extends 668a0301c0dSLemover TlbBundle { 669f9ac118cSHaoyuan Feng val page = new ReplaceIO(Width, q.NSets, q.NWays) 670a0301c0dSLemover 671a0301c0dSLemover def apply_sep(in: Seq[TlbReplaceIO], vpn: UInt) = { 672f9ac118cSHaoyuan Feng this.page.apply_sep(in.map(_.page), vpn) 673a0301c0dSLemover } 674a0301c0dSLemover 675a0301c0dSLemover} 676a0301c0dSLemover 6778744445eSMaxpicca-Liclass MemBlockidxBundle(implicit p: Parameters) extends TlbBundle { 6788744445eSMaxpicca-Li val is_ld = Bool() 6798744445eSMaxpicca-Li val is_st = Bool() 6808744445eSMaxpicca-Li val idx = 681e4f69d78Ssfencevma if (VirtualLoadQueueSize >= StoreQueueSize) { 682e4f69d78Ssfencevma val idx = UInt(log2Ceil(VirtualLoadQueueSize).W) 6838744445eSMaxpicca-Li idx 6848744445eSMaxpicca-Li } else { 6858744445eSMaxpicca-Li val idx = UInt(log2Ceil(StoreQueueSize).W) 6868744445eSMaxpicca-Li idx 6878744445eSMaxpicca-Li } 6888744445eSMaxpicca-Li} 6898744445eSMaxpicca-Li 6906d5ddbceSLemoverclass TlbReq(implicit p: Parameters) extends TlbBundle { 691ca2f90a6SLemover val vaddr = Output(UInt(VAddrBits.W)) 692ca2f90a6SLemover val cmd = Output(TlbCmd()) 693*d0de7e4aSpeixiaokun val hyperinst = Output(Bool()) 694*d0de7e4aSpeixiaokun val hlvx = Output(Bool()) 695ca2f90a6SLemover val size = Output(UInt(log2Ceil(log2Ceil(XLEN/8)+1).W)) 696f1fe8698SLemover val kill = Output(Bool()) // Use for blocked tlb that need sync with other module like icache 6978744445eSMaxpicca-Li val memidx = Output(new MemBlockidxBundle) 698b52348aeSWilliam Wang // do not translate, but still do pmp/pma check 699b52348aeSWilliam Wang val no_translate = Output(Bool()) 7006d5ddbceSLemover val debug = new Bundle { 701ca2f90a6SLemover val pc = Output(UInt(XLEN.W)) 702f1fe8698SLemover val robIdx = Output(new RobPtr) 703ca2f90a6SLemover val isFirstIssue = Output(Bool()) 7046d5ddbceSLemover } 7056d5ddbceSLemover 706f1fe8698SLemover // Maybe Block req needs a kill: for itlb, itlb and icache may not sync, itlb should wait icache to go ahead 7076d5ddbceSLemover override def toPrintable: Printable = { 708f1fe8698SLemover p"vaddr:0x${Hexadecimal(vaddr)} cmd:${cmd} kill:${kill} pc:0x${Hexadecimal(debug.pc)} robIdx:${debug.robIdx}" 7096d5ddbceSLemover } 7106d5ddbceSLemover} 7116d5ddbceSLemover 712b6982e83SLemoverclass TlbExceptionBundle(implicit p: Parameters) extends TlbBundle { 713b6982e83SLemover val ld = Output(Bool()) 714b6982e83SLemover val st = Output(Bool()) 715b6982e83SLemover val instr = Output(Bool()) 716b6982e83SLemover} 717b6982e83SLemover 71803efd994Shappy-lxclass TlbResp(nDups: Int = 1)(implicit p: Parameters) extends TlbBundle { 71903efd994Shappy-lx val paddr = Vec(nDups, Output(UInt(PAddrBits.W))) 720*d0de7e4aSpeixiaokun val gpaddr = Vec(nDups, Output(UInt(GPAddrBits.W))) 721ca2f90a6SLemover val miss = Output(Bool()) 72203efd994Shappy-lx val excp = Vec(nDups, new Bundle { 723*d0de7e4aSpeixiaokun val gpf = new TlbExceptionBundle() 724b6982e83SLemover val pf = new TlbExceptionBundle() 725b6982e83SLemover val af = new TlbExceptionBundle() 72603efd994Shappy-lx }) 727ca2f90a6SLemover val ptwBack = Output(Bool()) // when ptw back, wake up replay rs's state 7288744445eSMaxpicca-Li val memidx = Output(new MemBlockidxBundle) 7296d5ddbceSLemover 7308744445eSMaxpicca-Li val debug = new Bundle { 7318744445eSMaxpicca-Li val robIdx = Output(new RobPtr) 7328744445eSMaxpicca-Li val isFirstIssue = Output(Bool()) 7338744445eSMaxpicca-Li } 7346d5ddbceSLemover override def toPrintable: Printable = { 73503efd994Shappy-lx 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}" 7366d5ddbceSLemover } 7376d5ddbceSLemover} 7386d5ddbceSLemover 73903efd994Shappy-lxclass TlbRequestIO(nRespDups: Int = 1)(implicit p: Parameters) extends TlbBundle { 7406d5ddbceSLemover val req = DecoupledIO(new TlbReq) 741c3b763d0SYinan Xu val req_kill = Output(Bool()) 74203efd994Shappy-lx val resp = Flipped(DecoupledIO(new TlbResp(nRespDups))) 7436d5ddbceSLemover} 7446d5ddbceSLemover 7456d5ddbceSLemoverclass TlbPtwIO(Width: Int = 1)(implicit p: Parameters) extends TlbBundle { 7466d5ddbceSLemover val req = Vec(Width, DecoupledIO(new PtwReq)) 747*d0de7e4aSpeixiaokun val resp = Flipped(DecoupledIO(new PtwRespS2)) 7486d5ddbceSLemover 7496d5ddbceSLemover 7506d5ddbceSLemover override def toPrintable: Printable = { 7516d5ddbceSLemover p"req(0):${req(0).valid} ${req(0).ready} ${req(0).bits} | resp:${resp.valid} ${resp.ready} ${resp.bits}" 7526d5ddbceSLemover } 7536d5ddbceSLemover} 7546d5ddbceSLemover 7558744445eSMaxpicca-Liclass TlbPtwIOwithMemIdx(Width: Int = 1)(implicit p: Parameters) extends TlbBundle { 7568744445eSMaxpicca-Li val req = Vec(Width, DecoupledIO(new PtwReqwithMemIdx)) 757*d0de7e4aSpeixiaokun val resp = Flipped(DecoupledIO(new PtwRespS2withMemIdx())) 7588744445eSMaxpicca-Li 7598744445eSMaxpicca-Li 7608744445eSMaxpicca-Li override def toPrintable: Printable = { 7618744445eSMaxpicca-Li p"req(0):${req(0).valid} ${req(0).ready} ${req(0).bits} | resp:${resp.valid} ${resp.ready} ${resp.bits}" 7628744445eSMaxpicca-Li } 7638744445eSMaxpicca-Li} 7648744445eSMaxpicca-Li 765185e6164SHaoyuan Fengclass TlbHintReq(implicit p: Parameters) extends TlbBundle { 766185e6164SHaoyuan Feng val id = Output(UInt(log2Up(loadfiltersize).W)) 767185e6164SHaoyuan Feng val full = Output(Bool()) 768185e6164SHaoyuan Feng} 769185e6164SHaoyuan Feng 770185e6164SHaoyuan Fengclass TLBHintResp(implicit p: Parameters) extends TlbBundle { 771185e6164SHaoyuan Feng val id = Output(UInt(log2Up(loadfiltersize).W)) 772185e6164SHaoyuan Feng // When there are multiple matching entries for PTW resp in filter 773185e6164SHaoyuan Feng // e.g. vaddr 0, 0x80000000. vaddr 1, 0x80010000 774185e6164SHaoyuan Feng // these two vaddrs are not in a same 4K Page, so will send to ptw twice 775185e6164SHaoyuan Feng // However, when ptw resp, if they are in a 1G or 2M huge page 776185e6164SHaoyuan Feng // The two entries will both hit, and both need to replay 777185e6164SHaoyuan Feng val replay_all = Output(Bool()) 778185e6164SHaoyuan Feng} 779185e6164SHaoyuan Feng 780185e6164SHaoyuan Fengclass TlbHintIO(implicit p: Parameters) extends TlbBundle { 781185e6164SHaoyuan Feng val req = Vec(exuParameters.LduCnt, new TlbHintReq) 782185e6164SHaoyuan Feng val resp = ValidIO(new TLBHintResp) 783185e6164SHaoyuan Feng} 784185e6164SHaoyuan Feng 78545f497a4Shappy-lxclass MMUIOBaseBundle(implicit p: Parameters) extends TlbBundle { 786b052b972SLemover val sfence = Input(new SfenceBundle) 787b052b972SLemover val csr = Input(new TlbCsrBundle) 788f1fe8698SLemover 789f1fe8698SLemover def base_connect(sfence: SfenceBundle, csr: TlbCsrBundle): Unit = { 790f1fe8698SLemover this.sfence <> sfence 791f1fe8698SLemover this.csr <> csr 792f1fe8698SLemover } 793f1fe8698SLemover 794f1fe8698SLemover // overwrite satp. write satp will cause flushpipe but csr.priv won't 795f1fe8698SLemover // satp will be dealyed several cycles from writing, but csr.priv won't 796f1fe8698SLemover // so inside mmu, these two signals should be divided 797f1fe8698SLemover def base_connect(sfence: SfenceBundle, csr: TlbCsrBundle, satp: TlbSatpBundle) = { 798f1fe8698SLemover this.sfence <> sfence 799f1fe8698SLemover this.csr <> csr 800f1fe8698SLemover this.csr.satp := satp 801f1fe8698SLemover } 802a0301c0dSLemover} 8036d5ddbceSLemover 8048744445eSMaxpicca-Liclass TlbRefilltoMemIO()(implicit p: Parameters) extends TlbBundle { 8058744445eSMaxpicca-Li val valid = Bool() 8068744445eSMaxpicca-Li val memidx = new MemBlockidxBundle 8078744445eSMaxpicca-Li} 8088744445eSMaxpicca-Li 80903efd994Shappy-lxclass TlbIO(Width: Int, nRespDups: Int = 1, q: TLBParameters)(implicit p: Parameters) extends 81045f497a4Shappy-lx MMUIOBaseBundle { 811f57f7f2aSYangyu Chen val hartId = Input(UInt(hartIdLen.W)) 81203efd994Shappy-lx val requestor = Vec(Width, Flipped(new TlbRequestIO(nRespDups))) 813f1fe8698SLemover val flushPipe = Vec(Width, Input(Bool())) 8148744445eSMaxpicca-Li val ptw = new TlbPtwIOwithMemIdx(Width) 8158744445eSMaxpicca-Li val refill_to_mem = Output(new TlbRefilltoMemIO()) 816a0301c0dSLemover val replace = if (q.outReplace) Flipped(new TlbReplaceIO(Width, q)) else null 817b6982e83SLemover val pmp = Vec(Width, ValidIO(new PMPReqBundle())) 818185e6164SHaoyuan Feng val tlbreplay = Vec(Width, Output(Bool())) 819a0301c0dSLemover} 820a0301c0dSLemover 821f1fe8698SLemoverclass VectorTlbPtwIO(Width: Int)(implicit p: Parameters) extends TlbBundle { 8228744445eSMaxpicca-Li val req = Vec(Width, DecoupledIO(new PtwReqwithMemIdx())) 823a0301c0dSLemover val resp = Flipped(DecoupledIO(new Bundle { 824*d0de7e4aSpeixiaokun val data = new PtwRespS2withMemIdx 825a0301c0dSLemover val vector = Output(Vec(Width, Bool())) 826a0301c0dSLemover })) 827a0301c0dSLemover 8288744445eSMaxpicca-Li def connect(normal: TlbPtwIOwithMemIdx): Unit = { 829f1fe8698SLemover req <> normal.req 830f1fe8698SLemover resp.ready := normal.resp.ready 831f1fe8698SLemover normal.resp.bits := resp.bits.data 832f1fe8698SLemover normal.resp.valid := resp.valid 833a0301c0dSLemover } 8346d5ddbceSLemover} 8356d5ddbceSLemover 83692e3bfefSLemover/**************************** L2TLB *************************************/ 8376d5ddbceSLemoverabstract class PtwBundle(implicit p: Parameters) extends XSBundle with HasPtwConst 83892e3bfefSLemoverabstract class PtwModule(outer: L2TLB) extends LazyModuleImp(outer) 8396d5ddbceSLemover with HasXSParameter with HasPtwConst 8406d5ddbceSLemover 8416d5ddbceSLemoverclass PteBundle(implicit p: Parameters) extends PtwBundle{ 8426d5ddbceSLemover val reserved = UInt(pteResLen.W) 8430d94d540SHaoyuan Feng val ppn_high = UInt(ppnHignLen.W) 8446d5ddbceSLemover val ppn = UInt(ppnLen.W) 8456d5ddbceSLemover val rsw = UInt(2.W) 8466d5ddbceSLemover val perm = new Bundle { 8476d5ddbceSLemover val d = Bool() 8486d5ddbceSLemover val a = Bool() 8496d5ddbceSLemover val g = Bool() 8506d5ddbceSLemover val u = Bool() 8516d5ddbceSLemover val x = Bool() 8526d5ddbceSLemover val w = Bool() 8536d5ddbceSLemover val r = Bool() 8546d5ddbceSLemover val v = Bool() 8556d5ddbceSLemover } 8566d5ddbceSLemover 8576d5ddbceSLemover def unaligned(level: UInt) = { 8586d5ddbceSLemover isLeaf() && !(level === 2.U || 8596d5ddbceSLemover level === 1.U && ppn(vpnnLen-1, 0) === 0.U || 8606d5ddbceSLemover level === 0.U && ppn(vpnnLen*2-1, 0) === 0.U) 8616d5ddbceSLemover } 8626d5ddbceSLemover 8636d5ddbceSLemover def isPf(level: UInt) = { 8646d5ddbceSLemover !perm.v || (!perm.r && perm.w) || unaligned(level) 8656d5ddbceSLemover } 8666d5ddbceSLemover 8670d94d540SHaoyuan Feng // paddr of Xiangshan is 36 bits but ppn of sv39 is 44 bits 8680d94d540SHaoyuan Feng // access fault will be raised when ppn >> ppnLen is not zero 8690d94d540SHaoyuan Feng def isAf() = { 8700d94d540SHaoyuan Feng !(ppn_high === 0.U) 8710d94d540SHaoyuan Feng } 8720d94d540SHaoyuan Feng 8736d5ddbceSLemover def isLeaf() = { 8746d5ddbceSLemover perm.r || perm.x || perm.w 8756d5ddbceSLemover } 8766d5ddbceSLemover 8776d5ddbceSLemover def getPerm() = { 8786d5ddbceSLemover val pm = Wire(new PtePermBundle) 8796d5ddbceSLemover pm.d := perm.d 8806d5ddbceSLemover pm.a := perm.a 8816d5ddbceSLemover pm.g := perm.g 8826d5ddbceSLemover pm.u := perm.u 8836d5ddbceSLemover pm.x := perm.x 8846d5ddbceSLemover pm.w := perm.w 8856d5ddbceSLemover pm.r := perm.r 8866d5ddbceSLemover pm 8876d5ddbceSLemover } 8886d5ddbceSLemover 8896d5ddbceSLemover override def toPrintable: Printable = { 8906d5ddbceSLemover p"ppn:0x${Hexadecimal(ppn)} perm:b${Binary(perm.asUInt)}" 8916d5ddbceSLemover } 8926d5ddbceSLemover} 8936d5ddbceSLemover 8946d5ddbceSLemoverclass PtwEntry(tagLen: Int, hasPerm: Boolean = false, hasLevel: Boolean = false)(implicit p: Parameters) extends PtwBundle { 8956d5ddbceSLemover val tag = UInt(tagLen.W) 89645f497a4Shappy-lx val asid = UInt(asidLen.W) 897*d0de7e4aSpeixiaokun val vmid = if (HasHExtension) Some(UInt(vmidLen.W)) else None 8986d5ddbceSLemover val ppn = UInt(ppnLen.W) 8996d5ddbceSLemover val perm = if (hasPerm) Some(new PtePermBundle) else None 9006d5ddbceSLemover val level = if (hasLevel) Some(UInt(log2Up(Level).W)) else None 901bc063562SLemover val prefetch = Bool() 9028d8ac704SLemover val v = Bool() 9036d5ddbceSLemover 90456728e73SLemover def is_normalentry(): Bool = { 90556728e73SLemover if (!hasLevel) true.B 90656728e73SLemover else level.get === 2.U 90756728e73SLemover } 90856728e73SLemover 909f1fe8698SLemover def genPPN(vpn: UInt): UInt = { 910f1fe8698SLemover if (!hasLevel) ppn 91145f43e6eSTang Haojin else MuxLookup(level.get, 0.U)(Seq( 912f1fe8698SLemover 0.U -> Cat(ppn(ppn.getWidth-1, vpnnLen*2), vpn(vpnnLen*2-1, 0)), 913f1fe8698SLemover 1.U -> Cat(ppn(ppn.getWidth-1, vpnnLen), vpn(vpnnLen-1, 0)), 914f1fe8698SLemover 2.U -> ppn) 915f1fe8698SLemover ) 916f1fe8698SLemover } 917f1fe8698SLemover 918*d0de7e4aSpeixiaokun //s2xlate control whether compare vmid or not 919*d0de7e4aSpeixiaokun def hit(vpn: UInt, asid: UInt, vmid: UInt, allType: Boolean = false, ignoreAsid: Boolean = false, s2xlate: Bool, isGvpn: Bool) = { 920*d0de7e4aSpeixiaokun require(vpn.getWidth == vpnLen || vpn.getWidth == gvpnLen) 921cccfc98dSLemover// require(this.asid.getWidth <= asid.getWidth) 92245f497a4Shappy-lx val asid_hit = if (ignoreAsid) true.B else (this.asid === asid) 923*d0de7e4aSpeixiaokun val vmid_hit = Mux(s2xlate, this.vmid === vmid, true.B) 9246d5ddbceSLemover if (allType) { 9256d5ddbceSLemover require(hasLevel) 9266d5ddbceSLemover val hit0 = tag(tagLen - 1, vpnnLen*2) === vpn(tagLen - 1, vpnnLen*2) 9276d5ddbceSLemover val hit1 = tag(vpnnLen*2 - 1, vpnnLen) === vpn(vpnnLen*2 - 1, vpnnLen) 9286d5ddbceSLemover val hit2 = tag(vpnnLen - 1, 0) === vpn(vpnnLen - 1, 0) 92945f497a4Shappy-lx 930*d0de7e4aSpeixiaokun asid_hit && vmid_hit && Mux(level.getOrElse(0.U) === 2.U, hit2 && hit1 && hit0, Mux(level.getOrElse(0.U) === 1.U, hit1 && hit0, hit0)) 9316d5ddbceSLemover } else if (hasLevel) { 932*d0de7e4aSpeixiaokun val hit0 = tag(tagLen - 1, tagLen - vpnnLen) === Mux(isGvpn, vpn(gvpnLen - 1, gvpnLen - vpnnLen), vpn(vpnLen - 1, vpnLen - vpnnLen)) 933*d0de7e4aSpeixiaokun 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)) 93445f497a4Shappy-lx 935*d0de7e4aSpeixiaokun asid_hit && vmid_hit && Mux(level.getOrElse(0.U) === 0.U, hit0, hit0 && hit1) 9366d5ddbceSLemover } else { 937*d0de7e4aSpeixiaokun asid_hit && vmid_hit && tag === Mux(isGvpn, vpn(gvpnLen - 1, vpnLen - tagLen), vpn(vpnLen - 1, vpnLen - tagLen)) 9386d5ddbceSLemover } 9396d5ddbceSLemover } 9406d5ddbceSLemover 941*d0de7e4aSpeixiaokun def refill(vpn: UInt, asid: UInt, vmid: UInt, pte: UInt, level: UInt = 0.U, prefetch: Bool, valid: Bool = false.B) { 94245f497a4Shappy-lx require(this.asid.getWidth <= asid.getWidth) // maybe equal is better, but ugly outside 94345f497a4Shappy-lx 9446d5ddbceSLemover tag := vpn(vpnLen - 1, vpnLen - tagLen) 945a0301c0dSLemover ppn := pte.asTypeOf(new PteBundle().cloneType).ppn 946a0301c0dSLemover perm.map(_ := pte.asTypeOf(new PteBundle().cloneType).perm) 94745f497a4Shappy-lx this.asid := asid 948*d0de7e4aSpeixiaokun this.vmid := vmid 949bc063562SLemover this.prefetch := prefetch 9508d8ac704SLemover this.v := valid 9516d5ddbceSLemover this.level.map(_ := level) 9526d5ddbceSLemover } 9536d5ddbceSLemover 9548d8ac704SLemover def genPtwEntry(vpn: UInt, asid: UInt, pte: UInt, level: UInt = 0.U, prefetch: Bool, valid: Bool = false.B) = { 9556d5ddbceSLemover val e = Wire(new PtwEntry(tagLen, hasPerm, hasLevel)) 9568d8ac704SLemover e.refill(vpn, asid, pte, level, prefetch, valid) 9576d5ddbceSLemover e 9586d5ddbceSLemover } 9596d5ddbceSLemover 9606d5ddbceSLemover 961f1fe8698SLemover 9626d5ddbceSLemover override def toPrintable: Printable = { 9636d5ddbceSLemover // p"tag:0x${Hexadecimal(tag)} ppn:0x${Hexadecimal(ppn)} perm:${perm}" 9646d5ddbceSLemover p"tag:0x${Hexadecimal(tag)} ppn:0x${Hexadecimal(ppn)} " + 9656d5ddbceSLemover (if (hasPerm) p"perm:${perm.getOrElse(0.U.asTypeOf(new PtePermBundle))} " else p"") + 966bc063562SLemover (if (hasLevel) p"level:${level.getOrElse(0.U)}" else p"") + 967bc063562SLemover p"prefetch:${prefetch}" 9686d5ddbceSLemover } 9696d5ddbceSLemover} 9706d5ddbceSLemover 97163632028SHaoyuan Fengclass PtwSectorEntry(tagLen: Int, hasPerm: Boolean = false, hasLevel: Boolean = false)(implicit p: Parameters) extends PtwEntry(tagLen, hasPerm, hasLevel) { 97263632028SHaoyuan Feng override val ppn = UInt(sectorppnLen.W) 97363632028SHaoyuan Feng} 97463632028SHaoyuan Feng 97563632028SHaoyuan Fengclass PtwMergeEntry(tagLen: Int, hasPerm: Boolean = false, hasLevel: Boolean = false)(implicit p: Parameters) extends PtwSectorEntry(tagLen, hasPerm, hasLevel) { 97663632028SHaoyuan Feng val ppn_low = UInt(sectortlbwidth.W) 97763632028SHaoyuan Feng val af = Bool() 97863632028SHaoyuan Feng val pf = Bool() 97963632028SHaoyuan Feng} 98063632028SHaoyuan Feng 981*d0de7e4aSpeixiaokunclass HptwMergeEntry(tagLen: Int, hasPerm: Boolean = false, hasLevel: Boolean = false)(implicit p: Parameters) extends PtwMergeEntry(tagLen, hasPerm, hasLevel) { 982*d0de7e4aSpeixiaokun val vmid = UInt(vmidLen.W) 983*d0de7e4aSpeixiaokun} 984*d0de7e4aSpeixiaokun 9856d5ddbceSLemoverclass PtwEntries(num: Int, tagLen: Int, level: Int, hasPerm: Boolean)(implicit p: Parameters) extends PtwBundle { 9866d5ddbceSLemover require(log2Up(num)==log2Down(num)) 9871f4a7c0cSLemover // NOTE: hasPerm means that is leaf or not. 9886d5ddbceSLemover 9896d5ddbceSLemover val tag = UInt(tagLen.W) 99045f497a4Shappy-lx val asid = UInt(asidLen.W) 991*d0de7e4aSpeixiaokun val vmid = if (HasHExtension) Some(UInt(vmidLen.W)) else None 992*d0de7e4aSpeixiaokun val ppns = if (HasHExtension) Vec(num, UInt(gvpnLen.W)) else Vec(num, UInt(ppnLen.W)) 9936d5ddbceSLemover val vs = Vec(num, Bool()) 9946d5ddbceSLemover val perms = if (hasPerm) Some(Vec(num, new PtePermBundle)) else None 995bc063562SLemover val prefetch = Bool() 9966d5ddbceSLemover // println(s"PtwEntries: tag:1*${tagLen} ppns:${num}*${ppnLen} vs:${num}*1") 9971f4a7c0cSLemover // NOTE: vs is used for different usage: 9981f4a7c0cSLemover // for l3, which store the leaf(leaves), vs is page fault or not. 9991f4a7c0cSLemover // for l2, which shoule not store leaf, vs is valid or not, that will anticipate in hit check 10001f4a7c0cSLemover // Because, l2 should not store leaf(no perm), it doesn't store perm. 10011f4a7c0cSLemover // If l2 hit a leaf, the perm is still unavailble. Should still page walk. Complex but nothing helpful. 10021f4a7c0cSLemover // TODO: divide vs into validVec and pfVec 10031f4a7c0cSLemover // for l2: may valid but pf, so no need for page walk, return random pte with pf. 10046d5ddbceSLemover 1005*d0de7e4aSpeixiaokun def tagClip(vpn: UInt, isGvpn: Bool) = { 1006*d0de7e4aSpeixiaokun require(vpn.getWidth == vpnLen || vpn.getWidth == gvpnLen) 1007*d0de7e4aSpeixiaokun when(isGvpn){ 1008*d0de7e4aSpeixiaokun vpn(gvpnLen - 1, gvpnLen - tagLen) 1009*d0de7e4aSpeixiaokun }.otherwise{ 10106d5ddbceSLemover vpn(vpnLen - 1, vpnLen - tagLen) 10116d5ddbceSLemover } 1012*d0de7e4aSpeixiaokun } 10136d5ddbceSLemover 10146d5ddbceSLemover def sectorIdxClip(vpn: UInt, level: Int) = { 10156d5ddbceSLemover getVpnClip(vpn, level)(log2Up(num) - 1, 0) 10166d5ddbceSLemover } 10176d5ddbceSLemover 1018*d0de7e4aSpeixiaokun def hit(vpn: UInt, asid: UInt, vmid:UInt, ignoreAsid: Boolean = false, s2xlate: Bool, isGvpn: Bool) = { 101945f497a4Shappy-lx val asid_hit = if (ignoreAsid) true.B else (this.asid === asid) 1020*d0de7e4aSpeixiaokun val vmid_hit = Mux(s2xlate, this.vmid === vmid, true.B) 1021*d0de7e4aSpeixiaokun asid_hit && vmid_hit && tag === tagClip(vpn, isGvpn) && (if (hasPerm) true.B else vs(sectorIdxClip(vpn, level))) 10226d5ddbceSLemover } 10236d5ddbceSLemover 1024*d0de7e4aSpeixiaokun def genEntries(vpn: UInt, asid: UInt, vmid: UInt, data: UInt, levelUInt: UInt, prefetch: Bool) = { 10256d5ddbceSLemover require((data.getWidth / XLEN) == num, 10265854c1edSLemover s"input data length must be multiple of pte length: data.length:${data.getWidth} num:${num}") 10276d5ddbceSLemover 10286d5ddbceSLemover val ps = Wire(new PtwEntries(num, tagLen, level, hasPerm)) 10296d5ddbceSLemover ps.tag := tagClip(vpn) 103045f497a4Shappy-lx ps.asid := asid 1031*d0de7e4aSpeixiaokun ps.vmid := vmid 1032bc063562SLemover ps.prefetch := prefetch 10336d5ddbceSLemover for (i <- 0 until num) { 10346d5ddbceSLemover val pte = data((i+1)*XLEN-1, i*XLEN).asTypeOf(new PteBundle) 10356d5ddbceSLemover ps.ppns(i) := pte.ppn 10366d5ddbceSLemover ps.vs(i) := !pte.isPf(levelUInt) && (if (hasPerm) pte.isLeaf() else !pte.isLeaf()) 10376d5ddbceSLemover ps.perms.map(_(i) := pte.perm) 10386d5ddbceSLemover } 10396d5ddbceSLemover ps 10406d5ddbceSLemover } 10416d5ddbceSLemover 10426d5ddbceSLemover override def toPrintable: Printable = { 10436d5ddbceSLemover // require(num == 4, "if num is not 4, please comment this toPrintable") 10446d5ddbceSLemover // NOTE: if num is not 4, please comment this toPrintable 10456d5ddbceSLemover val permsInner = perms.getOrElse(0.U.asTypeOf(Vec(num, new PtePermBundle))) 104645f497a4Shappy-lx p"asid: ${Hexadecimal(asid)} tag:0x${Hexadecimal(tag)} ppns:${printVec(ppns)} vs:${Binary(vs.asUInt)} " + 10476d5ddbceSLemover (if (hasPerm) p"perms:${printVec(permsInner)}" else p"") 10486d5ddbceSLemover } 10496d5ddbceSLemover} 10506d5ddbceSLemover 10517196f5a2SLemoverclass PTWEntriesWithEcc(eccCode: Code, num: Int, tagLen: Int, level: Int, hasPerm: Boolean)(implicit p: Parameters) extends PtwBundle { 10527196f5a2SLemover val entries = new PtwEntries(num, tagLen, level, hasPerm) 10537196f5a2SLemover 10543889e11eSLemover val ecc_block = XLEN 10553889e11eSLemover val ecc_info = get_ecc_info() 10563889e11eSLemover val ecc = UInt(ecc_info._1.W) 10573889e11eSLemover 10583889e11eSLemover def get_ecc_info(): (Int, Int, Int, Int) = { 10593889e11eSLemover val eccBits_per = eccCode.width(ecc_block) - ecc_block 10603889e11eSLemover 10613889e11eSLemover val data_length = entries.getWidth 10623889e11eSLemover val data_align_num = data_length / ecc_block 10633889e11eSLemover val data_not_align = (data_length % ecc_block) != 0 // ugly code 10643889e11eSLemover val data_unalign_length = data_length - data_align_num * ecc_block 10653889e11eSLemover val eccBits_unalign = eccCode.width(data_unalign_length) - data_unalign_length 10663889e11eSLemover 10673889e11eSLemover val eccBits = eccBits_per * data_align_num + eccBits_unalign 10683889e11eSLemover (eccBits, eccBits_per, data_align_num, data_unalign_length) 10693889e11eSLemover } 10703889e11eSLemover 10713889e11eSLemover def encode() = { 1072935edac4STang Haojin val data = entries.asUInt 10733889e11eSLemover val ecc_slices = Wire(Vec(ecc_info._3, UInt(ecc_info._2.W))) 10743889e11eSLemover for (i <- 0 until ecc_info._3) { 10753889e11eSLemover ecc_slices(i) := eccCode.encode(data((i+1)*ecc_block-1, i*ecc_block)) >> ecc_block 10763889e11eSLemover } 10773889e11eSLemover if (ecc_info._4 != 0) { 10783889e11eSLemover val ecc_unaligned = eccCode.encode(data(data.getWidth-1, ecc_info._3*ecc_block)) >> ecc_info._4 1079935edac4STang Haojin ecc := Cat(ecc_unaligned, ecc_slices.asUInt) 1080935edac4STang Haojin } else { ecc := ecc_slices.asUInt } 10813889e11eSLemover } 10823889e11eSLemover 10833889e11eSLemover def decode(): Bool = { 1084935edac4STang Haojin val data = entries.asUInt 10853889e11eSLemover val res = Wire(Vec(ecc_info._3 + 1, Bool())) 10863889e11eSLemover for (i <- 0 until ecc_info._3) { 10875197bac8SZiyue-Zhang 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} 10883889e11eSLemover } 10895197bac8SZiyue-Zhang if (ecc_info._2 != 0 && ecc_info._4 != 0) { 10903889e11eSLemover res(ecc_info._3) := eccCode.decode( 10913889e11eSLemover Cat(ecc(ecc_info._1-1, ecc_info._2*ecc_info._3), data(data.getWidth-1, ecc_info._3*ecc_block))).error 10923889e11eSLemover } else { res(ecc_info._3) := false.B } 10933889e11eSLemover 10943889e11eSLemover Cat(res).orR 10953889e11eSLemover } 10963889e11eSLemover 1097*d0de7e4aSpeixiaokun def gen(vpn: UInt, asid: UInt, vmid: UInt, data: UInt, levelUInt: UInt, prefetch: Bool) = { 1098*d0de7e4aSpeixiaokun this.entries := entries.genEntries(vpn, asid, vmid, data, levelUInt, prefetch) 10993889e11eSLemover this.encode() 11003889e11eSLemover } 11017196f5a2SLemover} 11027196f5a2SLemover 11036d5ddbceSLemoverclass PtwReq(implicit p: Parameters) extends PtwBundle { 11046d5ddbceSLemover val vpn = UInt(vpnLen.W) 1105*d0de7e4aSpeixiaokun val gvpn = UInt(gvpnLen.W) 1106*d0de7e4aSpeixiaokun val s2xlate = UInt(2.W) // 0 bit: s2xlate, 1 bit: stage 1 or stage 2 11076d5ddbceSLemover override def toPrintable: Printable = { 11086d5ddbceSLemover p"vpn:0x${Hexadecimal(vpn)}" 11096d5ddbceSLemover } 11106d5ddbceSLemover} 11116d5ddbceSLemover 11128744445eSMaxpicca-Liclass PtwReqwithMemIdx(implicit p: Parameters) extends PtwReq { 11138744445eSMaxpicca-Li val memidx = new MemBlockidxBundle 11148744445eSMaxpicca-Li} 11158744445eSMaxpicca-Li 11166d5ddbceSLemoverclass PtwResp(implicit p: Parameters) extends PtwBundle { 11176d5ddbceSLemover val entry = new PtwEntry(tagLen = vpnLen, hasPerm = true, hasLevel = true) 11186d5ddbceSLemover val pf = Bool() 1119b6982e83SLemover val af = Bool() 11206d5ddbceSLemover 112145f497a4Shappy-lx def apply(pf: Bool, af: Bool, level: UInt, pte: PteBundle, vpn: UInt, asid: UInt) = { 11225854c1edSLemover this.entry.level.map(_ := level) 11235854c1edSLemover this.entry.tag := vpn 11245854c1edSLemover this.entry.perm.map(_ := pte.getPerm()) 11255854c1edSLemover this.entry.ppn := pte.ppn 1126bc063562SLemover this.entry.prefetch := DontCare 112745f497a4Shappy-lx this.entry.asid := asid 11288d8ac704SLemover this.entry.v := !pf 11295854c1edSLemover this.pf := pf 1130b6982e83SLemover this.af := af 11315854c1edSLemover } 11325854c1edSLemover 11336d5ddbceSLemover override def toPrintable: Printable = { 1134b6982e83SLemover p"entry:${entry} pf:${pf} af:${af}" 11356d5ddbceSLemover } 11366d5ddbceSLemover} 11376d5ddbceSLemover 1138*d0de7e4aSpeixiaokunclass HptwResp(implicit p: Parameters) extends PtwBundle { 1139*d0de7e4aSpeixiaokun val entry = new PtwEntry(tagLen = gvpnLen, hasPerm = true, hasLevel = true) 1140*d0de7e4aSpeixiaokun val gpf = Bool() 1141*d0de7e4aSpeixiaokun val gaf = Bool() 1142*d0de7e4aSpeixiaokun 1143*d0de7e4aSpeixiaokun def apply(gpf: Bool, gaf: Bool, level: UInt, pte: PteBundle, vpn: UInt, vmid: UInt) = { 1144*d0de7e4aSpeixiaokun this.entry.level.map(_ := level) 1145*d0de7e4aSpeixiaokun this.entry.tag := vpn 1146*d0de7e4aSpeixiaokun this.entry.perm.map(_ := pte.getPerm()) 1147*d0de7e4aSpeixiaokun this.entry.ppn := pte.ppn 1148*d0de7e4aSpeixiaokun this.entry.prefetch := DontCare 1149*d0de7e4aSpeixiaokun this.entry.asid := DontCare 1150*d0de7e4aSpeixiaokun this.entry.vmid := vmid 1151*d0de7e4aSpeixiaokun this.entry.v := !gpf 1152*d0de7e4aSpeixiaokun this.gpf := gpf 1153*d0de7e4aSpeixiaokun this.gaf := gaf 1154*d0de7e4aSpeixiaokun } 1155*d0de7e4aSpeixiaokun 1156*d0de7e4aSpeixiaokun def genPPNS2(): UInt = { 1157*d0de7e4aSpeixiaokun MuxLookup(entry.level.get, 0.U, Seq( 1158*d0de7e4aSpeixiaokun 0.U -> Cat(entry.ppn(entry.ppn.getWidth - 1, vpnnLen * 2), entry.tag(vpnnLen * 2 - 1, 0)), 1159*d0de7e4aSpeixiaokun 1.U -> Cat(entry.ppn(entry.ppn.getWidth - 1, vpnnLen), entry.tag(vpnnLen - 1, 0)), 1160*d0de7e4aSpeixiaokun 2.U -> Cat(entry.ppn(entry.ppn.getWidth - 1, 0)) 1161*d0de7e4aSpeixiaokun )) 1162*d0de7e4aSpeixiaokun } 1163*d0de7e4aSpeixiaokun 1164*d0de7e4aSpeixiaokun def hit(gvpn: UInt, vmid: UInt): Bool = { 1165*d0de7e4aSpeixiaokun require(gvpn.getWidth == gvpnLen) 1166*d0de7e4aSpeixiaokun val vmid_hit = this.entry.vmid === vmid 1167*d0de7e4aSpeixiaokun val hit0 = entry.tag(gvpnLen - 1, vpnnLen * 2) === gvpn(gvpnLen - 1, vpnnLen * 2) 1168*d0de7e4aSpeixiaokun val hit1 = entry.tag(vpnnLen * 2 - 1, vpnnLen) === gvpn(vpnnLen * 2 - 1, vpnnLen) 1169*d0de7e4aSpeixiaokun val hit2 = entry.tag(vpnnLen - 1, 0) === gvpn(vpnnLen - 1, 0) 1170*d0de7e4aSpeixiaokun 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*d0de7e4aSpeixiaokun } 1172*d0de7e4aSpeixiaokun} 1173*d0de7e4aSpeixiaokun 117463632028SHaoyuan Fengclass PtwResptomerge (implicit p: Parameters) extends PtwBundle { 117563632028SHaoyuan Feng val entry = UInt(blockBits.W) 117663632028SHaoyuan Feng val vpn = UInt(vpnLen.W) 117763632028SHaoyuan Feng val level = UInt(log2Up(Level).W) 117863632028SHaoyuan Feng val pf = Bool() 117963632028SHaoyuan Feng val af = Bool() 118063632028SHaoyuan Feng val asid = UInt(asidLen.W) 118163632028SHaoyuan Feng 118263632028SHaoyuan Feng def apply(pf: Bool, af: Bool, level: UInt, pte: UInt, vpn: UInt, asid: UInt) = { 118363632028SHaoyuan Feng this.entry := pte 118463632028SHaoyuan Feng this.pf := pf 118563632028SHaoyuan Feng this.af := af 118663632028SHaoyuan Feng this.level := level 118763632028SHaoyuan Feng this.vpn := vpn 118863632028SHaoyuan Feng this.asid := asid 118963632028SHaoyuan Feng } 119063632028SHaoyuan Feng 119163632028SHaoyuan Feng override def toPrintable: Printable = { 119263632028SHaoyuan Feng p"entry:${entry} pf:${pf} af:${af}" 119363632028SHaoyuan Feng } 119463632028SHaoyuan Feng} 119563632028SHaoyuan Feng 11968744445eSMaxpicca-Liclass PtwRespwithMemIdx(implicit p: Parameters) extends PtwResp { 11978744445eSMaxpicca-Li val memidx = new MemBlockidxBundle 11988744445eSMaxpicca-Li} 11998744445eSMaxpicca-Li 120063632028SHaoyuan Fengclass PtwSectorRespwithMemIdx(implicit p: Parameters) extends PtwSectorResp { 120163632028SHaoyuan Feng val memidx = new MemBlockidxBundle 120263632028SHaoyuan Feng} 120363632028SHaoyuan Feng 120463632028SHaoyuan Fengclass PtwSectorResp(implicit p: Parameters) extends PtwBundle { 120563632028SHaoyuan Feng val entry = new PtwSectorEntry(tagLen = sectorvpnLen, hasPerm = true, hasLevel = true) 120663632028SHaoyuan Feng val addr_low = UInt(sectortlbwidth.W) 120763632028SHaoyuan Feng val ppn_low = Vec(tlbcontiguous, UInt(sectortlbwidth.W)) 120863632028SHaoyuan Feng val valididx = Vec(tlbcontiguous, Bool()) 1209b0fa7106SHaoyuan Feng val pteidx = Vec(tlbcontiguous, Bool()) 121063632028SHaoyuan Feng val pf = Bool() 121163632028SHaoyuan Feng val af = Bool() 121263632028SHaoyuan Feng 1213*d0de7e4aSpeixiaokun 121463632028SHaoyuan Feng def genPPN(vpn: UInt): UInt = { 121545f43e6eSTang Haojin MuxLookup(entry.level.get, 0.U)(Seq( 121663632028SHaoyuan Feng 0.U -> Cat(entry.ppn(entry.ppn.getWidth-1, vpnnLen * 2 - sectortlbwidth), vpn(vpnnLen*2-1, 0)), 121763632028SHaoyuan Feng 1.U -> Cat(entry.ppn(entry.ppn.getWidth-1, vpnnLen - sectortlbwidth), vpn(vpnnLen-1, 0)), 121863632028SHaoyuan Feng 2.U -> Cat(entry.ppn(entry.ppn.getWidth-1, 0), ppn_low(vpn(sectortlbwidth - 1, 0)))) 121963632028SHaoyuan Feng ) 122063632028SHaoyuan Feng } 122163632028SHaoyuan Feng 1222*d0de7e4aSpeixiaokun def hit(vpn: UInt, asid: UInt, vmid: UInt, allType: Boolean = false, ignoreAsid: Boolean = false, s2xlate: Bool): Bool = { 122363632028SHaoyuan Feng require(vpn.getWidth == vpnLen) 122463632028SHaoyuan Feng // require(this.asid.getWidth <= asid.getWidth) 122563632028SHaoyuan Feng val asid_hit = if (ignoreAsid) true.B else (this.entry.asid === asid) 1226*d0de7e4aSpeixiaokun val vmid_hit = Mux(s2xlate, this.entry.vmid === vmid, true.B) 122763632028SHaoyuan Feng if (allType) { 122863632028SHaoyuan Feng val hit0 = entry.tag(sectorvpnLen - 1, vpnnLen * 2 - sectortlbwidth) === vpn(vpnLen - 1, vpnnLen * 2) 122963632028SHaoyuan Feng val hit1 = entry.tag(vpnnLen * 2 - sectortlbwidth - 1, vpnnLen - sectortlbwidth) === vpn(vpnnLen * 2 - 1, vpnnLen) 123063632028SHaoyuan Feng val hit2 = entry.tag(vpnnLen - sectortlbwidth - 1, 0) === vpn(vpnnLen - 1, sectortlbwidth) 123163632028SHaoyuan Feng val addr_low_hit = valididx(vpn(sectortlbwidth - 1, 0)) 123263632028SHaoyuan Feng 1233*d0de7e4aSpeixiaokun 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 123463632028SHaoyuan Feng } else { 123563632028SHaoyuan Feng val hit0 = entry.tag(sectorvpnLen - 1, sectorvpnLen - vpnnLen) === vpn(vpnLen - 1, vpnLen - vpnnLen) 123663632028SHaoyuan Feng val hit1 = entry.tag(sectorvpnLen - vpnnLen - 1, sectorvpnLen - vpnnLen * 2) === vpn(vpnLen - vpnnLen - 1, vpnLen - vpnnLen * 2) 123763632028SHaoyuan Feng val addr_low_hit = valididx(vpn(sectortlbwidth - 1, 0)) 123863632028SHaoyuan Feng 1239*d0de7e4aSpeixiaokun asid_hit && vmid_hit && Mux(entry.level.getOrElse(0.U) === 0.U, hit0, hit0 && hit1) && addr_low_hit 124063632028SHaoyuan Feng } 124163632028SHaoyuan Feng } 124263632028SHaoyuan Feng} 124363632028SHaoyuan Feng 124463632028SHaoyuan Fengclass PtwMergeResp(implicit p: Parameters) extends PtwBundle { 124563632028SHaoyuan Feng val entry = Vec(tlbcontiguous, new PtwMergeEntry(tagLen = sectorvpnLen, hasPerm = true, hasLevel = true)) 124663632028SHaoyuan Feng val pteidx = Vec(tlbcontiguous, Bool()) 124763632028SHaoyuan Feng val not_super = Bool() 124863632028SHaoyuan Feng 1249*d0de7e4aSpeixiaokun def apply(pf: Bool, af: Bool, level: UInt, pte: PteBundle, vpn: UInt, asid: UInt, vmid:UInt, addr_low : UInt, not_super : Boolean = true) = { 125063632028SHaoyuan Feng assert(tlbcontiguous == 8, "Only support tlbcontiguous = 8!") 125163632028SHaoyuan Feng 125263632028SHaoyuan Feng val ptw_resp = Wire(new PtwMergeEntry(tagLen = sectorvpnLen, hasPerm = true, hasLevel = true)) 125363632028SHaoyuan Feng ptw_resp.ppn := pte.ppn(ppnLen - 1, sectortlbwidth) 125463632028SHaoyuan Feng ptw_resp.ppn_low := pte.ppn(sectortlbwidth - 1, 0) 125563632028SHaoyuan Feng ptw_resp.level.map(_ := level) 125663632028SHaoyuan Feng ptw_resp.perm.map(_ := pte.getPerm()) 125763632028SHaoyuan Feng ptw_resp.tag := vpn(vpnLen - 1, sectortlbwidth) 125863632028SHaoyuan Feng ptw_resp.pf := pf 125963632028SHaoyuan Feng ptw_resp.af := af 126063632028SHaoyuan Feng ptw_resp.v := !pf 126163632028SHaoyuan Feng ptw_resp.prefetch := DontCare 126263632028SHaoyuan Feng ptw_resp.asid := asid 126363632028SHaoyuan Feng this.pteidx := UIntToOH(addr_low).asBools 126463632028SHaoyuan Feng this.not_super := not_super.B 1265*d0de7e4aSpeixiaokun 1266*d0de7e4aSpeixiaokun 126763632028SHaoyuan Feng for (i <- 0 until tlbcontiguous) { 126863632028SHaoyuan Feng this.entry(i) := ptw_resp 126963632028SHaoyuan Feng } 127063632028SHaoyuan Feng } 127163632028SHaoyuan Feng} 12728744445eSMaxpicca-Li 1273*d0de7e4aSpeixiaokunclass HptwMergeResp(implicit p: Parameters) extends PtwBundle { 1274*d0de7e4aSpeixiaokun val entry = Vec(tlbcontiguous, new HptwMergeEntry(tagLen = sectorvpnLen, hasPerm = true, hasLevel = true)) 1275*d0de7e4aSpeixiaokun val pteidx = Vec(tlbcontiguous, Bool()) 1276*d0de7e4aSpeixiaokun val not_super = Bool() 1277*d0de7e4aSpeixiaokun 1278*d0de7e4aSpeixiaokun def genPPN(): UInt = { 1279*d0de7e4aSpeixiaokun val idx = OHToUInt(pteidx) 1280*d0de7e4aSpeixiaokun MuxLookup(entry(idx).level.get, 0.U, Seq( 1281*d0de7e4aSpeixiaokun 0.U -> Cat(entry(idx).ppn(entry(idx).ppn.getWidth - 1, vpnnLen * 2 - sectortlbwidth), vpn(vpnnLen * 2 - 1, 0)), 1282*d0de7e4aSpeixiaokun 1.U -> Cat(entry(idx).ppn(entry(idx).ppn.getWidth - 1, vpnnLen - sectortlbwidth), vpn(vpnnLen - 1, 0)), 1283*d0de7e4aSpeixiaokun 2.U -> Cat(entry(idx).ppn(entry(idx).ppn.getWidth - 1, 0), entry(idx).ppn_low)) 1284*d0de7e4aSpeixiaokun ) 1285*d0de7e4aSpeixiaokun } 1286*d0de7e4aSpeixiaokun 1287*d0de7e4aSpeixiaokun def isAf(): Bool = { 1288*d0de7e4aSpeixiaokun val idx = OHToUInt(pteidx) 1289*d0de7e4aSpeixiaokun entry(idx).af 1290*d0de7e4aSpeixiaokun } 1291*d0de7e4aSpeixiaokun 1292*d0de7e4aSpeixiaokun def isPf(): Bool = { 1293*d0de7e4aSpeixiaokun val idx = OHToUInt(pteidx) 1294*d0de7e4aSpeixiaokun entry(idx).pf 1295*d0de7e4aSpeixiaokun } 1296*d0de7e4aSpeixiaokun 1297*d0de7e4aSpeixiaokun def MergeRespToPte(): PteBundle = { 1298*d0de7e4aSpeixiaokun val idx = OHToUInt(pteidx) 1299*d0de7e4aSpeixiaokun val resp = Wire(new PteBundle()) 1300*d0de7e4aSpeixiaokun resp.ppn := Cat(entry(idx).ppn, entry(idx).ppn_low) 1301*d0de7e4aSpeixiaokun resp.perm := entry(idx).perm 1302*d0de7e4aSpeixiaokun resp 1303*d0de7e4aSpeixiaokun } 1304*d0de7e4aSpeixiaokun 1305*d0de7e4aSpeixiaokun def apply(pf: Bool, af: Bool, level: UInt, pte: PteBundle, vpn: UInt, vmid: UInt, addr_low: UInt, not_super: Boolean = true) = { 1306*d0de7e4aSpeixiaokun assert(tlbcontiguous == 8, "Only support tlbcontiguous = 8!") 1307*d0de7e4aSpeixiaokun 1308*d0de7e4aSpeixiaokun val ptw_resp = Wire(new HptwMergeEntry(tagLen = sectorvpnLen, hasPerm = true, hasLevel = true)) 1309*d0de7e4aSpeixiaokun ptw_resp.ppn := pte.ppn(ppnLen - 1, sectortlbwidth) 1310*d0de7e4aSpeixiaokun ptw_resp.ppn_low := pte.ppn(sectortlbwidth - 1, 0) 1311*d0de7e4aSpeixiaokun ptw_resp.level.map(_ := level) 1312*d0de7e4aSpeixiaokun ptw_resp.perm.map(_ := pte.getPerm()) 1313*d0de7e4aSpeixiaokun ptw_resp.tag := vpn(vpnLen - 1, sectortlbwidth) 1314*d0de7e4aSpeixiaokun ptw_resp.pf := pf 1315*d0de7e4aSpeixiaokun ptw_resp.af := af 1316*d0de7e4aSpeixiaokun ptw_resp.v := !pf 1317*d0de7e4aSpeixiaokun ptw_resp.prefetch := DontCare 1318*d0de7e4aSpeixiaokun ptw_resp.vmid := vmid 1319*d0de7e4aSpeixiaokun this.pteidx := UIntToOH(addr_low).asBools 1320*d0de7e4aSpeixiaokun this.not_super := not_super.B 1321*d0de7e4aSpeixiaokun 1322*d0de7e4aSpeixiaokun 1323*d0de7e4aSpeixiaokun for (i <- 0 until tlbcontiguous) { 1324*d0de7e4aSpeixiaokun this.entry(i) := ptw_resp 1325*d0de7e4aSpeixiaokun } 1326*d0de7e4aSpeixiaokun } 1327*d0de7e4aSpeixiaokun} 1328*d0de7e4aSpeixiaokun 1329*d0de7e4aSpeixiaokunclass PtwRespS2(implicit p: Parameters) extends PtwBundle { 1330*d0de7e4aSpeixiaokun val s2xlate = UInt(2.W) 1331*d0de7e4aSpeixiaokun val s1 = new PtwSectorResp() 1332*d0de7e4aSpeixiaokun val s2 = new HptwResp() 1333*d0de7e4aSpeixiaokun} 1334*d0de7e4aSpeixiaokun 1335*d0de7e4aSpeixiaokunclass PtwRespS2withMemIdx(implicit p: Parameters) extends PtwRespS2 { 1336*d0de7e4aSpeixiaokun val memidx = new MemBlockidxBundle() 1337*d0de7e4aSpeixiaokun} 1338*d0de7e4aSpeixiaokun 133992e3bfefSLemoverclass L2TLBIO(implicit p: Parameters) extends PtwBundle { 1340f57f7f2aSYangyu Chen val hartId = Input(UInt(hartIdLen.W)) 13416d5ddbceSLemover val tlb = Vec(PtwWidth, Flipped(new TlbPtwIO)) 13426d5ddbceSLemover val sfence = Input(new SfenceBundle) 1343b6982e83SLemover val csr = new Bundle { 1344b6982e83SLemover val tlb = Input(new TlbCsrBundle) 1345b6982e83SLemover val distribute_csr = Flipped(new DistributedCSRIO) 1346b6982e83SLemover } 13476d5ddbceSLemover} 13486d5ddbceSLemover 1349b848eea5SLemoverclass L2TlbMemReqBundle(implicit p: Parameters) extends PtwBundle { 1350b848eea5SLemover val addr = UInt(PAddrBits.W) 1351b848eea5SLemover val id = UInt(bMemID.W) 1352b848eea5SLemover} 135345f497a4Shappy-lx 135445f497a4Shappy-lxclass L2TlbInnerBundle(implicit p: Parameters) extends PtwReq { 135545f497a4Shappy-lx val source = UInt(bSourceWidth.W) 135645f497a4Shappy-lx} 1357f1fe8698SLemover 1358f1fe8698SLemover 1359f1fe8698SLemoverobject ValidHoldBypass{ 1360f1fe8698SLemover def apply(infire: Bool, outfire: Bool, flush: Bool = false.B) = { 1361f1fe8698SLemover val valid = RegInit(false.B) 1362f1fe8698SLemover when (infire) { valid := true.B } 1363f1fe8698SLemover when (outfire) { valid := false.B } // ATTENTION: order different with ValidHold 1364f1fe8698SLemover when (flush) { valid := false.B } // NOTE: the flush will flush in & out, is that ok? 1365f1fe8698SLemover valid || infire 1366f1fe8698SLemover } 1367f1fe8698SLemover} 13685afdf73cSHaoyuan Feng 13695afdf73cSHaoyuan Fengclass L1TlbDB(implicit p: Parameters) extends TlbBundle { 13705afdf73cSHaoyuan Feng val vpn = UInt(vpnLen.W) 13715afdf73cSHaoyuan Feng} 13725afdf73cSHaoyuan Feng 13735afdf73cSHaoyuan Fengclass PageCacheDB(implicit p: Parameters) extends TlbBundle with HasPtwConst { 13745afdf73cSHaoyuan Feng val vpn = UInt(vpnLen.W) 13755afdf73cSHaoyuan Feng val source = UInt(bSourceWidth.W) 13765afdf73cSHaoyuan Feng val bypassed = Bool() 13775afdf73cSHaoyuan Feng val is_first = Bool() 13785afdf73cSHaoyuan Feng val prefetched = Bool() 13795afdf73cSHaoyuan Feng val prefetch = Bool() 13805afdf73cSHaoyuan Feng val l2Hit = Bool() 13815afdf73cSHaoyuan Feng val l1Hit = Bool() 13825afdf73cSHaoyuan Feng val hit = Bool() 13835afdf73cSHaoyuan Feng} 13845afdf73cSHaoyuan Feng 13855afdf73cSHaoyuan Fengclass PTWDB(implicit p: Parameters) extends TlbBundle with HasPtwConst { 13865afdf73cSHaoyuan Feng val vpn = UInt(vpnLen.W) 13875afdf73cSHaoyuan Feng val source = UInt(bSourceWidth.W) 13885afdf73cSHaoyuan Feng} 13895afdf73cSHaoyuan Feng 13905afdf73cSHaoyuan Fengclass L2TlbPrefetchDB(implicit p: Parameters) extends TlbBundle { 13915afdf73cSHaoyuan Feng val vpn = UInt(vpnLen.W) 13925afdf73cSHaoyuan Feng} 13935afdf73cSHaoyuan Feng 13945afdf73cSHaoyuan Fengclass L2TlbMissQueueDB(implicit p: Parameters) extends TlbBundle { 13955afdf73cSHaoyuan Feng val vpn = UInt(vpnLen.W) 13965afdf73cSHaoyuan Feng} 1397