xref: /XiangShan/src/main/scala/xiangshan/cache/mmu/MMUBundle.scala (revision 6d5ddbce72c9c67dcf0ec08cc682a9545ceb5f6c)
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}