1*6d5ddbceSLemover/*************************************************************************************** 2*6d5ddbceSLemover* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3*6d5ddbceSLemover* 4*6d5ddbceSLemover* XiangShan is licensed under Mulan PSL v2. 5*6d5ddbceSLemover* You can use this software according to the terms and conditions of the Mulan PSL v2. 6*6d5ddbceSLemover* You may obtain a copy of Mulan PSL v2 at: 7*6d5ddbceSLemover* http://license.coscl.org.cn/MulanPSL2 8*6d5ddbceSLemover* 9*6d5ddbceSLemover* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 10*6d5ddbceSLemover* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 11*6d5ddbceSLemover* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 12*6d5ddbceSLemover* 13*6d5ddbceSLemover* See the Mulan PSL v2 for more details. 14*6d5ddbceSLemover***************************************************************************************/ 15*6d5ddbceSLemover 16*6d5ddbceSLemoverpackage xiangshan.cache.mmu 17*6d5ddbceSLemover 18*6d5ddbceSLemoverimport chipsalliance.rocketchip.config.Parameters 19*6d5ddbceSLemoverimport chisel3._ 20*6d5ddbceSLemoverimport chisel3.util._ 21*6d5ddbceSLemoverimport xiangshan._ 22*6d5ddbceSLemoverimport utils._ 23*6d5ddbceSLemoverimport xiangshan.backend.roq.RoqPtr 24*6d5ddbceSLemoverimport xiangshan.backend.fu.util.HasCSRConst 25*6d5ddbceSLemoverimport freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} 26*6d5ddbceSLemoverimport freechips.rocketchip.tilelink._ 27*6d5ddbceSLemover 28*6d5ddbceSLemoverabstract class TlbBundle(implicit p: Parameters) extends XSBundle with HasTlbConst 29*6d5ddbceSLemoverabstract class TlbModule(implicit p: Parameters) extends XSModule with HasTlbConst 30*6d5ddbceSLemover 31*6d5ddbceSLemoverclass PtePermBundle(implicit p: Parameters) extends TlbBundle { 32*6d5ddbceSLemover val d = Bool() 33*6d5ddbceSLemover val a = Bool() 34*6d5ddbceSLemover val g = Bool() 35*6d5ddbceSLemover val u = Bool() 36*6d5ddbceSLemover val x = Bool() 37*6d5ddbceSLemover val w = Bool() 38*6d5ddbceSLemover val r = Bool() 39*6d5ddbceSLemover 40*6d5ddbceSLemover override def toPrintable: Printable = { 41*6d5ddbceSLemover p"d:${d} a:${a} g:${g} u:${u} x:${x} w:${w} r:${r}"// + 42*6d5ddbceSLemover //(if(hasV) (p"v:${v}") else p"") 43*6d5ddbceSLemover } 44*6d5ddbceSLemover} 45*6d5ddbceSLemover 46*6d5ddbceSLemoverclass TlbPermBundle(implicit p: Parameters) extends TlbBundle { 47*6d5ddbceSLemover val pf = Bool() // NOTE: if this is true, just raise pf 48*6d5ddbceSLemover // pagetable perm (software defined) 49*6d5ddbceSLemover val d = Bool() 50*6d5ddbceSLemover val a = Bool() 51*6d5ddbceSLemover val g = Bool() 52*6d5ddbceSLemover val u = Bool() 53*6d5ddbceSLemover val x = Bool() 54*6d5ddbceSLemover val w = Bool() 55*6d5ddbceSLemover val r = Bool() 56*6d5ddbceSLemover // pma perm (hardwired) 57*6d5ddbceSLemover val pr = Bool() //readable 58*6d5ddbceSLemover val pw = Bool() //writeable 59*6d5ddbceSLemover val pe = Bool() //executable 60*6d5ddbceSLemover val pa = Bool() //atom op permitted 61*6d5ddbceSLemover val pi = Bool() //icacheable 62*6d5ddbceSLemover val pd = Bool() //dcacheable 63*6d5ddbceSLemover 64*6d5ddbceSLemover override def toPrintable: Printable = { 65*6d5ddbceSLemover p"pf:${pf} d:${d} a:${a} g:${g} u:${u} x:${x} w:${w} r:${r}" 66*6d5ddbceSLemover } 67*6d5ddbceSLemover} 68*6d5ddbceSLemover 69*6d5ddbceSLemover// multi-read && single-write 70*6d5ddbceSLemover// input is data, output is hot-code(not one-hot) 71*6d5ddbceSLemoverclass CAMTemplate[T <: Data](val gen: T, val set: Int, val readWidth: Int)(implicit p: Parameters) extends TlbModule { 72*6d5ddbceSLemover val io = IO(new Bundle { 73*6d5ddbceSLemover val r = new Bundle { 74*6d5ddbceSLemover val req = Input(Vec(readWidth, gen)) 75*6d5ddbceSLemover val resp = Output(Vec(readWidth, Vec(set, Bool()))) 76*6d5ddbceSLemover } 77*6d5ddbceSLemover val w = Input(new Bundle { 78*6d5ddbceSLemover val valid = Bool() 79*6d5ddbceSLemover val bits = new Bundle { 80*6d5ddbceSLemover val index = UInt(log2Up(set).W) 81*6d5ddbceSLemover val data = gen 82*6d5ddbceSLemover } 83*6d5ddbceSLemover }) 84*6d5ddbceSLemover }) 85*6d5ddbceSLemover 86*6d5ddbceSLemover val wordType = UInt(gen.getWidth.W) 87*6d5ddbceSLemover val array = Reg(Vec(set, wordType)) 88*6d5ddbceSLemover 89*6d5ddbceSLemover io.r.resp.zipWithIndex.map{ case (a,i) => 90*6d5ddbceSLemover a := array.map(io.r.req(i).asUInt === _) 91*6d5ddbceSLemover } 92*6d5ddbceSLemover 93*6d5ddbceSLemover when (io.w.valid) { 94*6d5ddbceSLemover array(io.w.bits.index) := io.w.bits.data 95*6d5ddbceSLemover } 96*6d5ddbceSLemover} 97*6d5ddbceSLemover 98*6d5ddbceSLemoverclass TlbSPMeta(implicit p: Parameters) extends TlbBundle { 99*6d5ddbceSLemover val tag = UInt(vpnLen.W) // tag is vpn 100*6d5ddbceSLemover val level = UInt(1.W) // 1 for 2MB, 0 for 1GB 101*6d5ddbceSLemover 102*6d5ddbceSLemover def hit(vpn: UInt): Bool = { 103*6d5ddbceSLemover val a = tag(vpnnLen*3-1, vpnnLen*2) === vpn(vpnnLen*3-1, vpnnLen*2) 104*6d5ddbceSLemover val b = tag(vpnnLen*2-1, vpnnLen*1) === vpn(vpnnLen*2-1, vpnnLen*1) 105*6d5ddbceSLemover XSDebug(Mux(level.asBool, a&b, a), p"Hit superpage: hit:${Mux(level.asBool, a&b, a)} tag:${Hexadecimal(tag)} level:${level} a:${a} b:${b} vpn:${Hexadecimal(vpn)}\n") 106*6d5ddbceSLemover Mux(level.asBool, a&b, a) 107*6d5ddbceSLemover } 108*6d5ddbceSLemover 109*6d5ddbceSLemover def apply(vpn: UInt, level: UInt) = { 110*6d5ddbceSLemover this.tag := vpn 111*6d5ddbceSLemover this.level := level(0) 112*6d5ddbceSLemover 113*6d5ddbceSLemover this 114*6d5ddbceSLemover } 115*6d5ddbceSLemover 116*6d5ddbceSLemover} 117*6d5ddbceSLemover 118*6d5ddbceSLemoverclass TlbData(superpage: Boolean = false)(implicit p: Parameters) extends TlbBundle { 119*6d5ddbceSLemover val level = if(superpage) Some(UInt(1.W)) else None // /*2 for 4KB,*/ 1 for 2MB, 0 for 1GB 120*6d5ddbceSLemover val ppn = UInt(ppnLen.W) 121*6d5ddbceSLemover val perm = new TlbPermBundle 122*6d5ddbceSLemover 123*6d5ddbceSLemover def genPPN(vpn: UInt): UInt = { 124*6d5ddbceSLemover if (superpage) { 125*6d5ddbceSLemover val insideLevel = level.getOrElse(0.U) 126*6d5ddbceSLemover Mux(insideLevel.asBool, Cat(ppn(ppn.getWidth-1, vpnnLen*1), vpn(vpnnLen*1-1, 0)), 127*6d5ddbceSLemover Cat(ppn(ppn.getWidth-1, vpnnLen*2), vpn(vpnnLen*2-1, 0))) 128*6d5ddbceSLemover } else { 129*6d5ddbceSLemover ppn 130*6d5ddbceSLemover } 131*6d5ddbceSLemover } 132*6d5ddbceSLemover 133*6d5ddbceSLemover def apply(ppn: UInt, level: UInt, perm: UInt, pf: Bool) = { 134*6d5ddbceSLemover this.level.map(_ := level(0)) 135*6d5ddbceSLemover this.ppn := ppn 136*6d5ddbceSLemover // refill pagetable perm 137*6d5ddbceSLemover val ptePerm = perm.asTypeOf(new PtePermBundle) 138*6d5ddbceSLemover this.perm.pf:= pf 139*6d5ddbceSLemover this.perm.d := ptePerm.d 140*6d5ddbceSLemover this.perm.a := ptePerm.a 141*6d5ddbceSLemover this.perm.g := ptePerm.g 142*6d5ddbceSLemover this.perm.u := ptePerm.u 143*6d5ddbceSLemover this.perm.x := ptePerm.x 144*6d5ddbceSLemover this.perm.w := ptePerm.w 145*6d5ddbceSLemover this.perm.r := ptePerm.r 146*6d5ddbceSLemover 147*6d5ddbceSLemover // get pma perm 148*6d5ddbceSLemover val (pmaMode, accessWidth) = AddressSpace.memmapAddrMatch(Cat(ppn, 0.U(12.W))) 149*6d5ddbceSLemover this.perm.pr := PMAMode.read(pmaMode) 150*6d5ddbceSLemover this.perm.pw := PMAMode.write(pmaMode) 151*6d5ddbceSLemover this.perm.pe := PMAMode.execute(pmaMode) 152*6d5ddbceSLemover this.perm.pa := PMAMode.atomic(pmaMode) 153*6d5ddbceSLemover this.perm.pi := PMAMode.icache(pmaMode) 154*6d5ddbceSLemover this.perm.pd := PMAMode.dcache(pmaMode) 155*6d5ddbceSLemover 156*6d5ddbceSLemover this 157*6d5ddbceSLemover } 158*6d5ddbceSLemover 159*6d5ddbceSLemover override def toPrintable: Printable = { 160*6d5ddbceSLemover val insideLevel = level.getOrElse(0.U) 161*6d5ddbceSLemover p"level:${insideLevel} ppn:${Hexadecimal(ppn)} perm:${perm}" 162*6d5ddbceSLemover } 163*6d5ddbceSLemover 164*6d5ddbceSLemover override def cloneType: this.type = (new TlbData(superpage)).asInstanceOf[this.type] 165*6d5ddbceSLemover} 166*6d5ddbceSLemover 167*6d5ddbceSLemoverobject TlbCmd { 168*6d5ddbceSLemover def read = "b00".U 169*6d5ddbceSLemover def write = "b01".U 170*6d5ddbceSLemover def exec = "b10".U 171*6d5ddbceSLemover 172*6d5ddbceSLemover def atom_read = "b100".U // lr 173*6d5ddbceSLemover def atom_write = "b101".U // sc / amo 174*6d5ddbceSLemover 175*6d5ddbceSLemover def apply() = UInt(3.W) 176*6d5ddbceSLemover def isRead(a: UInt) = a(1,0)===read 177*6d5ddbceSLemover def isWrite(a: UInt) = a(1,0)===write 178*6d5ddbceSLemover def isExec(a: UInt) = a(1,0)===exec 179*6d5ddbceSLemover 180*6d5ddbceSLemover def isAtom(a: UInt) = a(2) 181*6d5ddbceSLemover} 182*6d5ddbceSLemover 183*6d5ddbceSLemoverclass TlbReq(implicit p: Parameters) extends TlbBundle { 184*6d5ddbceSLemover val vaddr = UInt(VAddrBits.W) 185*6d5ddbceSLemover val cmd = TlbCmd() 186*6d5ddbceSLemover val roqIdx = new RoqPtr 187*6d5ddbceSLemover val debug = new Bundle { 188*6d5ddbceSLemover val pc = UInt(XLEN.W) 189*6d5ddbceSLemover val isFirstIssue = Bool() 190*6d5ddbceSLemover } 191*6d5ddbceSLemover 192*6d5ddbceSLemover override def toPrintable: Printable = { 193*6d5ddbceSLemover p"vaddr:0x${Hexadecimal(vaddr)} cmd:${cmd} pc:0x${Hexadecimal(debug.pc)} roqIdx:${roqIdx}" 194*6d5ddbceSLemover } 195*6d5ddbceSLemover} 196*6d5ddbceSLemover 197*6d5ddbceSLemoverclass TlbResp(implicit p: Parameters) extends TlbBundle { 198*6d5ddbceSLemover val paddr = UInt(PAddrBits.W) 199*6d5ddbceSLemover val miss = Bool() 200*6d5ddbceSLemover val mmio = Bool() 201*6d5ddbceSLemover val excp = new Bundle { 202*6d5ddbceSLemover val pf = new Bundle { 203*6d5ddbceSLemover val ld = Bool() 204*6d5ddbceSLemover val st = Bool() 205*6d5ddbceSLemover val instr = Bool() 206*6d5ddbceSLemover } 207*6d5ddbceSLemover val af = new Bundle { 208*6d5ddbceSLemover val ld = Bool() 209*6d5ddbceSLemover val st = Bool() 210*6d5ddbceSLemover val instr = Bool() 211*6d5ddbceSLemover } 212*6d5ddbceSLemover } 213*6d5ddbceSLemover val ptwBack = Bool() // when ptw back, wake up replay rs's state 214*6d5ddbceSLemover 215*6d5ddbceSLemover override def toPrintable: Printable = { 216*6d5ddbceSLemover p"paddr:0x${Hexadecimal(paddr)} miss:${miss} excp.pf: ld:${excp.pf.ld} st:${excp.pf.st} instr:${excp.pf.instr} ptwBack:${ptwBack}" 217*6d5ddbceSLemover } 218*6d5ddbceSLemover} 219*6d5ddbceSLemover 220*6d5ddbceSLemoverclass TlbRequestIO()(implicit p: Parameters) extends TlbBundle { 221*6d5ddbceSLemover val req = DecoupledIO(new TlbReq) 222*6d5ddbceSLemover val resp = Flipped(DecoupledIO(new TlbResp)) 223*6d5ddbceSLemover} 224*6d5ddbceSLemover 225*6d5ddbceSLemoverclass BlockTlbRequestIO()(implicit p: Parameters) extends TlbBundle { 226*6d5ddbceSLemover val req = DecoupledIO(new TlbReq) 227*6d5ddbceSLemover val resp = Flipped(DecoupledIO(new TlbResp)) 228*6d5ddbceSLemover} 229*6d5ddbceSLemover 230*6d5ddbceSLemoverclass TlbPtwIO(Width: Int = 1)(implicit p: Parameters) extends TlbBundle { 231*6d5ddbceSLemover val req = Vec(Width, DecoupledIO(new PtwReq)) 232*6d5ddbceSLemover val resp = Flipped(DecoupledIO(new PtwResp)) 233*6d5ddbceSLemover 234*6d5ddbceSLemover override def cloneType: this.type = (new TlbPtwIO(Width)).asInstanceOf[this.type] 235*6d5ddbceSLemover 236*6d5ddbceSLemover override def toPrintable: Printable = { 237*6d5ddbceSLemover p"req(0):${req(0).valid} ${req(0).ready} ${req(0).bits} | resp:${resp.valid} ${resp.ready} ${resp.bits}" 238*6d5ddbceSLemover } 239*6d5ddbceSLemover} 240*6d5ddbceSLemover 241*6d5ddbceSLemoverclass TlbIO(Width: Int)(implicit p: Parameters) extends TlbBundle { 242*6d5ddbceSLemover val requestor = Vec(Width, Flipped(new TlbRequestIO)) 243*6d5ddbceSLemover val ptw = new TlbPtwIO(Width) 244*6d5ddbceSLemover val sfence = Input(new SfenceBundle) 245*6d5ddbceSLemover val csr = Input(new TlbCsrBundle) 246*6d5ddbceSLemover 247*6d5ddbceSLemover override def cloneType: this.type = (new TlbIO(Width)).asInstanceOf[this.type] 248*6d5ddbceSLemover} 249*6d5ddbceSLemover 250*6d5ddbceSLemover 251*6d5ddbceSLemover/**************************** PTW *************************************/ 252*6d5ddbceSLemoverabstract class PtwBundle(implicit p: Parameters) extends XSBundle with HasPtwConst 253*6d5ddbceSLemoverabstract class PtwModule(outer: PTW) extends LazyModuleImp(outer) 254*6d5ddbceSLemover with HasXSParameter with HasPtwConst 255*6d5ddbceSLemover 256*6d5ddbceSLemoverclass PteBundle(implicit p: Parameters) extends PtwBundle{ 257*6d5ddbceSLemover val reserved = UInt(pteResLen.W) 258*6d5ddbceSLemover val ppn = UInt(ppnLen.W) 259*6d5ddbceSLemover val rsw = UInt(2.W) 260*6d5ddbceSLemover val perm = new Bundle { 261*6d5ddbceSLemover val d = Bool() 262*6d5ddbceSLemover val a = Bool() 263*6d5ddbceSLemover val g = Bool() 264*6d5ddbceSLemover val u = Bool() 265*6d5ddbceSLemover val x = Bool() 266*6d5ddbceSLemover val w = Bool() 267*6d5ddbceSLemover val r = Bool() 268*6d5ddbceSLemover val v = Bool() 269*6d5ddbceSLemover } 270*6d5ddbceSLemover 271*6d5ddbceSLemover def unaligned(level: UInt) = { 272*6d5ddbceSLemover isLeaf() && !(level === 2.U || 273*6d5ddbceSLemover level === 1.U && ppn(vpnnLen-1, 0) === 0.U || 274*6d5ddbceSLemover level === 0.U && ppn(vpnnLen*2-1, 0) === 0.U) 275*6d5ddbceSLemover } 276*6d5ddbceSLemover 277*6d5ddbceSLemover def isPf(level: UInt) = { 278*6d5ddbceSLemover !perm.v || (!perm.r && perm.w) || unaligned(level) 279*6d5ddbceSLemover } 280*6d5ddbceSLemover 281*6d5ddbceSLemover def isLeaf() = { 282*6d5ddbceSLemover perm.r || perm.x || perm.w 283*6d5ddbceSLemover } 284*6d5ddbceSLemover 285*6d5ddbceSLemover def getPerm() = { 286*6d5ddbceSLemover val pm = Wire(new PtePermBundle) 287*6d5ddbceSLemover pm.d := perm.d 288*6d5ddbceSLemover pm.a := perm.a 289*6d5ddbceSLemover pm.g := perm.g 290*6d5ddbceSLemover pm.u := perm.u 291*6d5ddbceSLemover pm.x := perm.x 292*6d5ddbceSLemover pm.w := perm.w 293*6d5ddbceSLemover pm.r := perm.r 294*6d5ddbceSLemover pm 295*6d5ddbceSLemover } 296*6d5ddbceSLemover 297*6d5ddbceSLemover override def toPrintable: Printable = { 298*6d5ddbceSLemover p"ppn:0x${Hexadecimal(ppn)} perm:b${Binary(perm.asUInt)}" 299*6d5ddbceSLemover } 300*6d5ddbceSLemover} 301*6d5ddbceSLemover 302*6d5ddbceSLemoverclass PtwEntry(tagLen: Int, hasPerm: Boolean = false, hasLevel: Boolean = false)(implicit p: Parameters) extends PtwBundle { 303*6d5ddbceSLemover val tag = UInt(tagLen.W) 304*6d5ddbceSLemover val ppn = UInt(ppnLen.W) 305*6d5ddbceSLemover val perm = if (hasPerm) Some(new PtePermBundle) else None 306*6d5ddbceSLemover val level = if (hasLevel) Some(UInt(log2Up(Level).W)) else None 307*6d5ddbceSLemover 308*6d5ddbceSLemover def hit(vpn: UInt, allType: Boolean = false) = { 309*6d5ddbceSLemover require(vpn.getWidth == vpnLen) 310*6d5ddbceSLemover if (allType) { 311*6d5ddbceSLemover require(hasLevel) 312*6d5ddbceSLemover val hit0 = tag(tagLen - 1, vpnnLen*2) === vpn(tagLen - 1, vpnnLen*2) 313*6d5ddbceSLemover val hit1 = tag(vpnnLen*2 - 1, vpnnLen) === vpn(vpnnLen*2 - 1, vpnnLen) 314*6d5ddbceSLemover val hit2 = tag(vpnnLen - 1, 0) === vpn(vpnnLen - 1, 0) 315*6d5ddbceSLemover Mux(level.getOrElse(0.U) === 2.U, hit2 && hit1 && hit0, Mux(level.getOrElse(0.U) === 1.U, hit1 && hit0, hit0)) 316*6d5ddbceSLemover } else if (hasLevel) { 317*6d5ddbceSLemover val hit0 = tag(tagLen - 1, tagLen - vpnnLen) === vpn(vpnLen - 1, vpnLen - vpnnLen) 318*6d5ddbceSLemover val hit1 = tag(tagLen - vpnnLen - 1, tagLen - vpnnLen * 2) === vpn(vpnLen - vpnnLen - 1, vpnLen - vpnnLen * 2) 319*6d5ddbceSLemover Mux(level.getOrElse(0.U) === 0.U, hit0, hit0 && hit1) 320*6d5ddbceSLemover } else { 321*6d5ddbceSLemover tag === vpn(vpnLen - 1, vpnLen - tagLen) 322*6d5ddbceSLemover } 323*6d5ddbceSLemover } 324*6d5ddbceSLemover 325*6d5ddbceSLemover def refill(vpn: UInt, pte: UInt, level: UInt = 0.U) { 326*6d5ddbceSLemover tag := vpn(vpnLen - 1, vpnLen - tagLen) 327*6d5ddbceSLemover ppn := pte.asTypeOf(pteBundle).ppn 328*6d5ddbceSLemover perm.map(_ := pte.asTypeOf(pteBundle).perm) 329*6d5ddbceSLemover this.level.map(_ := level) 330*6d5ddbceSLemover } 331*6d5ddbceSLemover 332*6d5ddbceSLemover def genPtwEntry(vpn: UInt, pte: UInt, level: UInt = 0.U) = { 333*6d5ddbceSLemover val e = Wire(new PtwEntry(tagLen, hasPerm, hasLevel)) 334*6d5ddbceSLemover e.refill(vpn, pte, level) 335*6d5ddbceSLemover e 336*6d5ddbceSLemover } 337*6d5ddbceSLemover 338*6d5ddbceSLemover override def cloneType: this.type = (new PtwEntry(tagLen, hasPerm, hasLevel)).asInstanceOf[this.type] 339*6d5ddbceSLemover 340*6d5ddbceSLemover override def toPrintable: Printable = { 341*6d5ddbceSLemover // p"tag:0x${Hexadecimal(tag)} ppn:0x${Hexadecimal(ppn)} perm:${perm}" 342*6d5ddbceSLemover p"tag:0x${Hexadecimal(tag)} ppn:0x${Hexadecimal(ppn)} " + 343*6d5ddbceSLemover (if (hasPerm) p"perm:${perm.getOrElse(0.U.asTypeOf(new PtePermBundle))} " else p"") + 344*6d5ddbceSLemover (if (hasLevel) p"level:${level.getOrElse(0.U)}" else p"") 345*6d5ddbceSLemover } 346*6d5ddbceSLemover} 347*6d5ddbceSLemover 348*6d5ddbceSLemoverclass PtwEntries(num: Int, tagLen: Int, level: Int, hasPerm: Boolean)(implicit p: Parameters) extends PtwBundle { 349*6d5ddbceSLemover require(log2Up(num)==log2Down(num)) 350*6d5ddbceSLemover 351*6d5ddbceSLemover val tag = UInt(tagLen.W) 352*6d5ddbceSLemover val ppns = Vec(num, UInt(ppnLen.W)) 353*6d5ddbceSLemover val vs = Vec(num, Bool()) 354*6d5ddbceSLemover val perms = if (hasPerm) Some(Vec(num, new PtePermBundle)) else None 355*6d5ddbceSLemover // println(s"PtwEntries: tag:1*${tagLen} ppns:${num}*${ppnLen} vs:${num}*1") 356*6d5ddbceSLemover 357*6d5ddbceSLemover def tagClip(vpn: UInt) = { 358*6d5ddbceSLemover require(vpn.getWidth == vpnLen) 359*6d5ddbceSLemover vpn(vpnLen - 1, vpnLen - tagLen) 360*6d5ddbceSLemover } 361*6d5ddbceSLemover 362*6d5ddbceSLemover def sectorIdxClip(vpn: UInt, level: Int) = { 363*6d5ddbceSLemover getVpnClip(vpn, level)(log2Up(num) - 1, 0) 364*6d5ddbceSLemover } 365*6d5ddbceSLemover 366*6d5ddbceSLemover def hit(vpn: UInt) = { 367*6d5ddbceSLemover tag === tagClip(vpn) && vs(sectorIdxClip(vpn, level)) // TODO: optimize this. don't need to compare each with tag 368*6d5ddbceSLemover } 369*6d5ddbceSLemover 370*6d5ddbceSLemover def genEntries(vpn: UInt, data: UInt, levelUInt: UInt) = { 371*6d5ddbceSLemover require((data.getWidth / XLEN) == num, 372*6d5ddbceSLemover "input data length must be multiple of pte length") 373*6d5ddbceSLemover 374*6d5ddbceSLemover val ps = Wire(new PtwEntries(num, tagLen, level, hasPerm)) 375*6d5ddbceSLemover ps.tag := tagClip(vpn) 376*6d5ddbceSLemover for (i <- 0 until num) { 377*6d5ddbceSLemover val pte = data((i+1)*XLEN-1, i*XLEN).asTypeOf(new PteBundle) 378*6d5ddbceSLemover ps.ppns(i) := pte.ppn 379*6d5ddbceSLemover ps.vs(i) := !pte.isPf(levelUInt) && (if (hasPerm) pte.isLeaf() else !pte.isLeaf()) 380*6d5ddbceSLemover ps.perms.map(_(i) := pte.perm) 381*6d5ddbceSLemover } 382*6d5ddbceSLemover ps 383*6d5ddbceSLemover } 384*6d5ddbceSLemover 385*6d5ddbceSLemover override def cloneType: this.type = (new PtwEntries(num, tagLen, level, hasPerm)).asInstanceOf[this.type] 386*6d5ddbceSLemover override def toPrintable: Printable = { 387*6d5ddbceSLemover // require(num == 4, "if num is not 4, please comment this toPrintable") 388*6d5ddbceSLemover // NOTE: if num is not 4, please comment this toPrintable 389*6d5ddbceSLemover val permsInner = perms.getOrElse(0.U.asTypeOf(Vec(num, new PtePermBundle))) 390*6d5ddbceSLemover p"tag:0x${Hexadecimal(tag)} ppns:${printVec(ppns)} vs:${Binary(vs.asUInt)} " + 391*6d5ddbceSLemover (if (hasPerm) p"perms:${printVec(permsInner)}" else p"") 392*6d5ddbceSLemover } 393*6d5ddbceSLemover} 394*6d5ddbceSLemover 395*6d5ddbceSLemoverclass PtwReq(implicit p: Parameters) extends PtwBundle { 396*6d5ddbceSLemover val vpn = UInt(vpnLen.W) 397*6d5ddbceSLemover 398*6d5ddbceSLemover override def toPrintable: Printable = { 399*6d5ddbceSLemover p"vpn:0x${Hexadecimal(vpn)}" 400*6d5ddbceSLemover } 401*6d5ddbceSLemover} 402*6d5ddbceSLemover 403*6d5ddbceSLemoverclass PtwResp(implicit p: Parameters) extends PtwBundle { 404*6d5ddbceSLemover val entry = new PtwEntry(tagLen = vpnLen, hasPerm = true, hasLevel = true) 405*6d5ddbceSLemover val pf = Bool() 406*6d5ddbceSLemover 407*6d5ddbceSLemover override def toPrintable: Printable = { 408*6d5ddbceSLemover p"entry:${entry} pf:${pf}" 409*6d5ddbceSLemover } 410*6d5ddbceSLemover} 411*6d5ddbceSLemover 412*6d5ddbceSLemoverclass PtwIO(implicit p: Parameters) extends PtwBundle { 413*6d5ddbceSLemover val tlb = Vec(PtwWidth, Flipped(new TlbPtwIO)) 414*6d5ddbceSLemover val sfence = Input(new SfenceBundle) 415*6d5ddbceSLemover val csr = Input(new TlbCsrBundle) 416*6d5ddbceSLemover} 417*6d5ddbceSLemover 418*6d5ddbceSLemoverobject ValidHold { 419*6d5ddbceSLemover def apply(infire: Bool, outfire: Bool, flush: Bool = false.B ) = { 420*6d5ddbceSLemover val valid = RegInit(false.B) 421*6d5ddbceSLemover when (outfire) { valid := false.B } 422*6d5ddbceSLemover when (infire) { valid := true.B } 423*6d5ddbceSLemover when (flush) { valid := false.B } // NOTE: the flush will flush in & out, is that ok? 424*6d5ddbceSLemover valid 425*6d5ddbceSLemover } 426*6d5ddbceSLemover} 427*6d5ddbceSLemover 428*6d5ddbceSLemoverobject OneCycleValid { 429*6d5ddbceSLemover def apply(fire: Bool, flush: Bool = false.B) = { 430*6d5ddbceSLemover val valid = RegInit(false.B) 431*6d5ddbceSLemover when (valid) { valid := false.B } 432*6d5ddbceSLemover when (fire) { valid := true.B } 433*6d5ddbceSLemover when (flush) { valid := false.B } 434*6d5ddbceSLemover valid 435*6d5ddbceSLemover } 436*6d5ddbceSLemover}