dtlb.scala 18.0 KB
Newer Older
Y
Yinan Xu 已提交
1 2 3 4 5 6
package xiangshan.cache

import chisel3._
import chisel3.util._
import xiangshan._
import utils._
7
import xiangshan.backend.decode.XSTrap
Y
Yinan Xu 已提交
8
import xiangshan.backend.roq.RoqPtr
9
import xiangshan.mem._
Z
ZhangZifei 已提交
10
import xiangshan.backend.fu.HasCSRConst
Z
ZhangZifei 已提交
11
import chisel3.ExcitingUtils._
Y
Yinan Xu 已提交
12

13
trait HasTlbConst extends HasXSParameter {
Z
ZhangZifei 已提交
14 15 16
  val Level = 3

  val offLen  = 12
Z
ZhangZifei 已提交
17 18 19
  val ppnLen  = PAddrBits - offLen
  val vpnnLen = 9
  val vpnLen  = VAddrBits - offLen
Z
ZhangZifei 已提交
20 21
  val flagLen = 8
  val pteResLen = XLEN - ppnLen - 2 - flagLen
Z
ZhangZifei 已提交
22
  val asidLen = 16
Z
ZhangZifei 已提交
23 24 25 26 27

  def vaBundle = new Bundle {
    val vpn  = UInt(vpnLen.W)
    val off  = UInt(offLen.W)
  }
Z
ZhangZifei 已提交
28
  def pteBundle = new Bundle {
Z
ZhangZifei 已提交
29 30 31
    val reserved  = UInt(pteResLen.W)
    val ppn  = UInt(ppnLen.W)
    val rsw  = UInt(2.W)
Z
ZhangZifei 已提交
32
    val perm = new Bundle {
Z
ZhangZifei 已提交
33 34 35 36 37 38 39 40
      val d    = Bool()
      val a    = Bool()
      val g    = Bool()
      val u    = Bool()
      val x    = Bool()
      val w    = Bool()
      val r    = Bool()
      val v    = Bool()
Z
ZhangZifei 已提交
41 42 43 44
    }
  }
}

Z
ZhangZifei 已提交
45 46
abstract class TlbBundle extends XSBundle with HasTlbConst
abstract class TlbModule extends XSModule with HasTlbConst
Z
ZhangZifei 已提交
47 48 49 50 51 52 53 54 55 56

class PermBundle(val hasV: Boolean = true) extends TlbBundle {
  val d = Bool()
  val a = Bool()
  val g = Bool()
  val u = Bool()
  val x = Bool()
  val w = Bool()
  val r = Bool()
  if (hasV) { val v = Bool() }
Z
ZhangZifei 已提交
57 58

  override def toPrintable: Printable = {
59
    p"d:${d} a:${a} g:${g} u:${u} x:${x} w:${w} r:${r}"// +
Z
ZhangZifei 已提交
60 61
    //(if(hasV) (p"v:${v}") else p"")
  }
Z
ZhangZifei 已提交
62 63
}

Y
Yinan Xu 已提交
64 65
class comBundle extends TlbBundle with HasCircularQueuePtrHelper{
  val roqIdx = new RoqPtr
66 67 68
  val valid = Bool()
  val bits = new PtwReq
  def isPrior(that: comBundle): Bool = {
Y
Yinan Xu 已提交
69
    (this.valid && !that.valid) || (this.valid && that.valid && isAfter(that.roqIdx, this.roqIdx))
70 71 72 73 74 75 76 77
  }
}
object Compare {
  def apply[T<:Data](xs: Seq[comBundle]): comBundle = {
    ParallelOperation(xs, (a: comBundle, b: comBundle) => Mux(a isPrior b, a, b))
  }
}

78
class TlbEntry extends TlbBundle {
Z
ZhangZifei 已提交
79 80
  val vpn = UInt(vpnLen.W) // tag is vpn
  val ppn = UInt(ppnLen.W)
81
  val level = UInt(log2Up(Level).W) // 2 for 4KB, 1 for 2MB, 0 for 1GB
Z
ZhangZifei 已提交
82 83 84 85
  // val asid = UInt(asidLen.W), asid maybe expensive to support, but useless
  // val v = Bool() // v&g is special, may need sperate storage?
  val perm = new PermBundle(hasV = false)

86
  def vpnHit(vpn: UInt):Bool = {
Z
ZhangZifei 已提交
87
    val fullMask = VecInit((Seq.fill(vpnLen)(true.B))).asUInt
88
    val maskLevel = VecInit((Level-1 to 0 by -1).map{i => // NOTE: level 2 for 4KB, 1 for 2MB, 0 for 1GB
89
      Reverse(VecInit(Seq.fill(vpnLen-i*vpnnLen)(true.B) ++ Seq.fill(i*vpnnLen)(false.B)).asUInt)})
Z
ZhangZifei 已提交
90 91 92 93 94 95 96 97
    val mask = maskLevel(level)
    (mask&this.vpn) === (mask&vpn)
  }

  // def asidHit(asid: UInt) = {
  //   this.asid === asid
  // }

98
  def hit(vpn: UInt/*, asid: UInt*/):Bool = {
99
    vpnHit(vpn) // && asidHit(asid)
Z
ZhangZifei 已提交
100 101
  }

102
  def genTlbEntry(pte: UInt, level: UInt, vpn: UInt/*, asid: UInt*/) = {
103
    val e = Wire(new TlbEntry)
Z
ZhangZifei 已提交
104 105 106 107 108 109 110
    e.ppn := pte.asTypeOf(pteBundle).ppn
    e.level := level
    e.vpn := vpn
    e.perm := pte.asTypeOf(pteBundle).perm
    // e.asid := asid
    e
  }
Z
ZhangZifei 已提交
111 112 113 114

  override def toPrintable: Printable = {
    p"vpn:0x${Hexadecimal(vpn)} ppn:0x${Hexadecimal(ppn)} level:${level} perm:${perm}"
  }
Z
ZhangZifei 已提交
115 116
}

117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
class TlbEntires(num: Int, tagLen: Int) extends TlbBundle {
  require(log2Up(num)==log2Down(num))
  /* vpn can be divide into three part */
  // vpn: tagPart + addrPart
  val cutLen  = log2Up(num)

  val tag     = UInt(tagLen.W) // NOTE: high part of vpn
  val level   = UInt(log2Up(Level).W)
  val ppns    = Vec(num, UInt(ppnLen.W))
  val perms    = Vec(num, new PermBundle(hasV = false))
  val vs      = Vec(num, Bool())

  def tagClip(vpn: UInt, level: UInt) = { // full vpn => tagLen
    Mux(level===0.U, Cat(vpn(vpnLen-1, vpnnLen*2+cutLen), 0.U(vpnnLen*2+cutLen)),
    Mux(level===1.U, Cat(vpn(vpnLen-1, vpnnLen*1+cutLen), 0.U(vpnnLen*1+cutLen)),
                     Cat(vpn(vpnLen-1, vpnnLen*0+cutLen), 0.U(vpnnLen*0+cutLen))))(tagLen-1, 0)
  }

  // NOTE: get insize idx
  def idxClip(vpn: UInt, level: UInt) = {
    Mux(level===0.U, vpn(vpnnLen*2+cutLen-1, vpnnLen*2),
    Mux(level===1.U, vpn(vpnnLen*1+cutLen-1, vpnnLen*1),
                     vpn(vpnnLen*0+cutLen-1, vpnnLen*0)))
  }

  def hit(vpn: UInt) = {
    (tag === tagClip(vpn, level)) && vs(idxClip(vpn, level))
  }

  def genEntries(data: UInt, level: UInt, vpn: UInt): TlbEntires = {
    require((data.getWidth / XLEN) == num,
      "input data length must be multiple of pte length")
    assert(level=/=3.U, "level should not be 3")

    val ts = Wire(new TlbEntires(num, tagLen))
    ts.tag := tagClip(vpn, level)
    ts.level := level
    for (i <- 0 until num) {
      val pte = data((i+1)*XLEN-1, i*XLEN).asTypeOf(new PteBundle)
      ts.ppns(i) := pte.ppn
      ts.perms(i):= pte.perm // this.perms has no v
      ts.vs(i)   := !pte.isPf(level) && pte.isLeaf() // legal and leaf, store to l2Tlb
    }

    ts
  }

  def get(vpn: UInt): TlbEntry = {
    val t = Wire(new TlbEntry())
    val idx = idxClip(vpn, level)
    t.vpn := vpn // Note: Use input vpn, not vpn in TlbL2
    t.ppn := ppns(idx)
    t.level := level
    t.perm := perms(idx)
    t
  }

  override def cloneType: this.type = (new TlbEntires(num, tagLen)).asInstanceOf[this.type]
175 176 177 178 179 180 181
  override def toPrintable: Printable = {
    require(num == 4, "if num is not 4, please comment this toPrintable")
    // NOTE: if num is not 4, please comment this toPrintable
    p"tag:${Hexadecimal(tag)} level:${level} ppn(0):${Hexadecimal(ppns(0))} ppn(1):${Hexadecimal(ppns(1))}" +
    p"ppn(2):${Hexadecimal(ppns(2))} ppn(3):${Hexadecimal(ppns(3))} " +
    p"perms(0):${perms(0)} perms(1):${perms(1)} perms(2):${perms(2)} perms(3):${perms(3)} vs:${Binary(vs.asUInt)}"
  }
182 183
}

184 185 186 187 188 189
object TlbCmd {
  def read  = "b00".U
  def write = "b01".U
  def exec  = "b10".U

  def apply() = UInt(2.W)
Z
ZhangZifei 已提交
190 191 192
  def isRead(a: UInt) = a===read
  def isWrite(a: UInt) = a===write
  def isExec(a: UInt) = a===exec
193 194
}

195
class TlbReq extends TlbBundle {
Y
Yinan Xu 已提交
196
  val vaddr = UInt(VAddrBits.W)
197
  val cmd = TlbCmd()
Y
Yinan Xu 已提交
198
  val roqIdx = new RoqPtr
199 200 201
  val debug = new Bundle {
    val pc = UInt(XLEN.W)
  }
Z
ZhangZifei 已提交
202 203

  override def toPrintable: Printable = {
Y
Yinan Xu 已提交
204
    p"vaddr:0x${Hexadecimal(vaddr)} cmd:${cmd} pc:0x${Hexadecimal(debug.pc)} roqIdx:${roqIdx}"
Z
ZhangZifei 已提交
205
  }
Y
Yinan Xu 已提交
206 207
}

208
class TlbResp extends TlbBundle {
Y
Yinan Xu 已提交
209 210
  val paddr = UInt(PAddrBits.W)
  val miss = Bool()
Z
ZhangZifei 已提交
211 212 213 214 215 216 217
  val excp = new Bundle {
    val pf = new Bundle {
      val ld = Bool()
      val st = Bool()
      val instr = Bool()
    }
  }
Z
ZhangZifei 已提交
218 219 220
  override def toPrintable: Printable = {
    p"paddr:0x${Hexadecimal(paddr)} miss:${miss} excp.pf: ld:${excp.pf.ld} st:${excp.pf.st} instr:${excp.pf.instr}"
  }
221 222
}

223
class TlbRequestIO() extends TlbBundle {
224 225
  val req = DecoupledIO(new TlbReq)
  val resp = Flipped(DecoupledIO(new TlbResp))
Y
Yinan Xu 已提交
226 227
}

Z
zhanglinjuan 已提交
228 229 230 231 232
class BlockTlbRequestIO() extends TlbBundle {
  val req = DecoupledIO(new TlbReq)
  val resp = Flipped(DecoupledIO(new TlbResp))
}

Z
ZhangZifei 已提交
233
class TlbPtwIO extends TlbBundle {
Z
ZhangZifei 已提交
234 235
  val req = DecoupledIO(new PtwReq)
  val resp = Flipped(DecoupledIO(new PtwResp))
Y
Yinan Xu 已提交
236 237
}

238
class TlbIO(Width: Int) extends TlbBundle {
239
  val requestor = Vec(Width, Flipped(new TlbRequestIO))
240
  val ptw = new TlbPtwIO
L
LinJiawei 已提交
241
  val sfence = Input(new SfenceBundle)
L
LinJiawei 已提交
242
  val csr = Input(new TlbCsrBundle)
243 244

  override def cloneType: this.type = (new TlbIO(Width)).asInstanceOf[this.type]
Y
Yinan Xu 已提交
245 246 247
}


Z
ZhangZifei 已提交
248
class TLB(Width: Int, isDtlb: Boolean) extends TlbModule with HasCSRConst{
249
  val io = IO(new TlbIO(Width))
Z
ZhangZifei 已提交
250

251 252
  val req    = io.requestor.map(_.req)
  val resp   = io.requestor.map(_.resp)
253
  val ptw    = io.ptw
254

L
LinJiawei 已提交
255
  val sfence = io.sfence
L
LinJiawei 已提交
256
  val csr    = io.csr
257 258
  val satp   = csr.satp
  val priv   = csr.priv
Z
ZhangZifei 已提交
259 260
  val ifecth = if (isDtlb) false.B else true.B
  val mode   = if (isDtlb) priv.dmode else priv.imode
Z
ZhangZifei 已提交
261 262
  // val vmEnable = satp.mode === 8.U // && (mode < ModeM) // FIXME: fix me when boot xv6/linux...
  val vmEnable = satp.mode === 8.U && (mode < ModeM)
263

264
  val reqAddr = req.map(_.bits.vaddr.asTypeOf(vaBundle))
265 266
  val cmd     = req.map(_.bits.cmd)
  val valid   = req.map(_.valid)
Z
ZhangZifei 已提交
267

268 269 270
  def widthMapSeq[T <: Seq[Data]](f: Int => T) = (0 until Width).map(f)
  def widthMap[T <: Data](f: Int => T) = (0 until Width).map(f)

271
  val v = RegInit(0.U(TlbEntrySize.W))
272
  val pf = RegInit(0.U(TlbEntrySize.W)) // TODO: when ptw resp a pf(now only page not found), store here
273
  val entry = Reg(Vec(TlbEntrySize, new TlbEntry))
274
  val g = VecInit(entry.map(_.perm.g)).asUInt // TODO: need check if reverse is needed
Z
ZhangZifei 已提交
275

276 277 278 279 280 281 282
  val entryHitVec = widthMapSeq{i => VecInit(entry.map(_.hit(reqAddr(i).vpn/*, satp.asid*/))) }
  val hitVec  = widthMapSeq{ i => (v.asBools zip entryHitVec(i)).map{ case (a,b) => a&b } }
  val pfHitVec   = widthMapSeq{ i => (pf.asBools zip entryHitVec(i)).map{ case (a,b) => a&b } }
  val pfArray = widthMap{ i => ParallelOR(pfHitVec(i)).asBool && valid(i) && vmEnable }
  val hit     = widthMap{ i => ParallelOR(hitVec(i)).asBool && valid(i) && vmEnable && ~pfArray(i) }
  val miss    = widthMap{ i => !hit(i) && valid(i) && vmEnable && ~pfArray(i) }
  val hitppn  = widthMap{ i => ParallelMux(hitVec(i) zip entry.map(_.ppn)) }
283
  val hitPerm = widthMap{ i => ParallelMux(hitVec(i) zip entry.map(_.perm)) }
284
  val hitLevel= widthMap{ i => ParallelMux(hitVec(i) zip entry.map(_.level)) }
Z
ZhangZifei 已提交
285
  val multiHit = {
286
    val hitSum = widthMap{ i => PopCount(hitVec(i)) }
287 288
    val pfHitSum = widthMap{ i => PopCount(pfHitVec(i)) }
    ParallelOR(widthMap{ i => !(hitSum(i)===0.U || hitSum(i)===1.U) || !(pfHitSum(i)===0.U || pfHitSum(i)===1.U)})
Z
ZhangZifei 已提交
289 290
  }

Z
ZhangZifei 已提交
291
  // resp  // TODO: A/D has not being concerned
292
  for(i <- 0 until Width) {
293
    val paddr = LookupTreeDefault(hitLevel(i), Cat(hitppn(i), reqAddr(i).off), List(
294
      0.U -> Cat(hitppn(i)(ppnLen - 1, 2*vpnnLen), reqAddr(i).vpn(2*vpnnLen - 1, 0), reqAddr(i).off),
295
      1.U -> Cat(hitppn(i)(ppnLen - 1, vpnnLen), reqAddr(i).vpn(vpnnLen - 1, 0), reqAddr(i).off),
296
      2.U -> Cat(hitppn(i), reqAddr(i).off)
297 298
    ))

299
    req(i).ready := resp(i).ready
300
    resp(i).valid := valid(i)
301
    resp(i).bits.paddr := Mux(vmEnable, paddr, SignExt(req(i).bits.vaddr, PAddrBits))
Z
ZhangZifei 已提交
302 303 304
    resp(i).bits.miss := miss(i)

    val perm = hitPerm(i) // NOTE: given the excp, the out module choose one to use?
305
    val update = false.B && hit(i) && (!hitPerm(i).a || !hitPerm(i).d && TlbCmd.isWrite(cmd(i))) // update A/D through exception
Z
ZhangZifei 已提交
306
    val modeCheck = !(mode === ModeU && !perm.u || mode === ModeS && perm.u && (!priv.sum || ifecth))
307 308 309 310 311 312
    val ldPf = (pfArray(i) && TlbCmd.isRead(cmd(i)) && true.B /*!isAMO*/) || hit(i) && !(modeCheck && (perm.r || priv.mxr && perm.x)) && (TlbCmd.isRead(cmd(i)) && true.B/*!isAMO*/) // TODO: handle isAMO
    val stPf = (pfArray(i) && TlbCmd.isWrite(cmd(i)) || false.B /*isAMO*/ ) || hit(i) && !(modeCheck && perm.w) && (TlbCmd.isWrite(cmd(i)) || false.B/*TODO isAMO. */)
    val instrPf = (pfArray(i) && TlbCmd.isExec(cmd(i))) || hit(i) && !(modeCheck && perm.x) && TlbCmd.isExec(cmd(i))
    resp(i).bits.excp.pf.ld    := ldPf || update
    resp(i).bits.excp.pf.st    := stPf || update
    resp(i).bits.excp.pf.instr := instrPf || update
Z
ZhangZifei 已提交
313 314 315
  }

  // ptw
Z
ZhangZifei 已提交
316 317
  val state_idle :: state_wait :: Nil = Enum(2)
  val state = RegInit(state_idle)
Z
ZhangZifei 已提交
318

319
  ptw <> DontCare // TODO: need check it
320
  ptw.req.valid := ParallelOR(miss).asBool && state===state_idle && !sfence.valid
321
  ptw.resp.ready := state===state_wait
322

323 324 325 326
  // val ptwReqSeq = Wire(Seq.fill(Width)(new comBundle()))
  val ptwReqSeq = Seq.fill(Width)(Wire(new comBundle()))
  for (i <- 0 until Width) {
    ptwReqSeq(i).valid := valid(i) && miss(i)
Z
ZhangZifei 已提交
327
    ptwReqSeq(i).roqIdx := req(i).bits.roqIdx
328 329 330 331
    ptwReqSeq(i).bits.vpn := reqAddr(i).vpn
  }
  ptw.req.bits := Compare(ptwReqSeq).bits

Z
ZhangZifei 已提交
332
  switch (state) {
Z
ZhangZifei 已提交
333
    is (state_idle) {
Z
ZhangZifei 已提交
334
      when (ParallelOR(miss).asBool && ptw.req.fire()) {
335
        state := state_wait
Z
ZhangZifei 已提交
336
      }
337
      assert(!ptw.resp.valid)
Z
ZhangZifei 已提交
338
    }
339

Z
ZhangZifei 已提交
340
    is (state_wait) {
341
      when (ptw.resp.fire()) {
Z
ZhangZifei 已提交
342
        state := state_idle
Z
ZhangZifei 已提交
343
      }
A
Allen 已提交
344
    }
Z
ZhangZifei 已提交
345 346
  }

347
  // reset pf when pf hit
348
  val pfHitReset = ParallelOR(widthMap{i => Mux(resp(i).fire(), VecInit(pfHitVec(i)).asUInt, 0.U) })
Z
ZhangZifei 已提交
349
  val pfHitRefill = ParallelOR(pfHitReset.asBools)
350

Z
ZhangZifei 已提交
351
  // refill
352
  val refill = ptw.resp.fire()
353
  val randIdx = LFSR64()(log2Up(TlbEntrySize)-1,0)
Z
ZhangZifei 已提交
354
  val priorIdx = PriorityEncoder(~(v|pf))
Z
ZhangZifei 已提交
355 356 357
  val tlbfull = ParallelAND((v|pf).asBools)
  val refillIdx = Mux(tlbfull, randIdx, priorIdx)
  val re2OH = UIntToOH(refillIdx)
Z
ZhangZifei 已提交
358
  when (refill) {
Z
ZhangZifei 已提交
359
    v := Mux(ptw.resp.bits.pf, v & ~re2OH, v | re2OH)
Z
ZhangZifei 已提交
360
    entry(refillIdx) := ptw.resp.bits.entry
361
    XSDebug(p"Refill: idx:${refillIdx} entry:${ptw.resp.bits.entry}\n")
Z
ZhangZifei 已提交
362
  }
Z
ZhangZifei 已提交
363

364
  // pf update
Z
ZhangZifei 已提交
365 366 367 368 369 370 371 372 373 374 375 376 377
  when (refill) {
    when (pfHitRefill) {
      pf := Mux(ptw.resp.bits.pf, pf | re2OH, pf & ~re2OH) & ~pfHitReset
    } .otherwise {
      pf := Mux(ptw.resp.bits.pf, pf | re2OH, pf & ~re2OH)
    }
  } .otherwise {
    when (pfHitRefill) {
      pf := pf & ~pfHitReset
    }
  }
  when (PopCount(pf) > 10.U) { // when too much pf, just clear
    pf := Mux(refill && ptw.resp.bits.pf, re2OH, 0.U)
378 379 380 381
  }

  // sfence (flush)
  when (sfence.valid) {
382 383
    state := state_idle
    ptw.req.valid := false.B
384 385
    when (sfence.bits.rs1) { // virtual address *.rs1 <- (rs1===0.U)
      when (sfence.bits.rs2) { // asid, but i do not want to support asid, *.rs2 <- (rs2===0.U)
386 387
        // all addr and all asid
        v := 0.U
388
        pf := 0.U
389 390 391 392
      }.otherwise {
        // all addr but specific asid
        v := v & g // TODO: need check if reverse is needed
        pf := pf & g
393
      }
394 395 396 397 398 399 400 401 402
    }.otherwise {
      when (sfence.bits.rs2) {
        // specific addr but all asid
        v := v & ~VecInit(entry.map(_.hit(sfence.bits.addr.asTypeOf(vaBundle).vpn))).asUInt
        pf := pf & ~VecInit(entry.map(_.hit(sfence.bits.addr.asTypeOf(vaBundle).vpn))).asUInt
      }.otherwise {
        // specific addr and specific asid
        v := v & ~VecInit(entry.map(e => e.hit(sfence.bits.addr.asTypeOf(vaBundle).vpn) && (/*e.asid === sfence.bits.asid && */!e.perm.g))).asUInt
        pf := pf & ~VecInit(entry.map(e => e.hit(sfence.bits.addr.asTypeOf(vaBundle).vpn) && (/*e.asid === sfence.bits.asid && */!e.perm.g))).asUInt
403 404 405 406
      }
    }
  }

Z
zhanglinjuan 已提交
407
  if (!env.FPGAPlatform && isDtlb) {
Z
ZhangZifei 已提交
408 409 410 411 412 413 414 415 416 417
    ExcitingUtils.addSource(valid(0)/* && vmEnable*/, "perfCntDtlbReqCnt0", Perf)
    ExcitingUtils.addSource(valid(1)/* && vmEnable*/, "perfCntDtlbReqCnt1", Perf)
    ExcitingUtils.addSource(valid(2)/* && vmEnable*/, "perfCntDtlbReqCnt2", Perf)
    ExcitingUtils.addSource(valid(3)/* && vmEnable*/, "perfCntDtlbReqCnt3", Perf)
    ExcitingUtils.addSource(valid(0)/* && vmEnable*/ && miss(0), "perfCntDtlbMissCnt0", Perf)
    ExcitingUtils.addSource(valid(1)/* && vmEnable*/ && miss(1), "perfCntDtlbMissCnt1", Perf)
    ExcitingUtils.addSource(valid(2)/* && vmEnable*/ && miss(2), "perfCntDtlbMissCnt2", Perf)
    ExcitingUtils.addSource(valid(3)/* && vmEnable*/ && miss(3), "perfCntDtlbMissCnt3", Perf)
  }

Z
zhanglinjuan 已提交
418 419 420 421 422
  if (!env.FPGAPlatform && !isDtlb) {
    ExcitingUtils.addSource(valid(0)/* && vmEnable*/, "perfCntItlbReqCnt0", Perf)
    ExcitingUtils.addSource(valid(0)/* && vmEnable*/ && miss(0), "perfCntItlbMissCnt0", Perf)
  }

423
  // Log
Z
ZhangZifei 已提交
424
  for(i <- 0 until Width) {
425 426
    XSDebug(req(i).valid, p"req(${i.U}): (${req(i).valid} ${req(i).ready}) ${req(i).bits}\n")
    XSDebug(resp(i).valid, p"resp(${i.U}): (${resp(i).valid} ${resp(i).ready}) ${resp(i).bits}\n")
Z
ZhangZifei 已提交
427 428 429
  }

  XSDebug(sfence.valid, p"Sfence: ${sfence}\n")
430
  XSDebug(ParallelOR(valid)|| ptw.resp.valid, p"CSR: ${csr}\n")
431
  XSDebug(ParallelOR(valid) || ptw.resp.valid, p"vmEnable:${vmEnable} hit:${Binary(VecInit(hit).asUInt)} miss:${Binary(VecInit(miss).asUInt)} v:${Hexadecimal(v)} pf:${Hexadecimal(pf)} state:${state}\n")
Z
ZhangZifei 已提交
432
  XSDebug(ptw.req.fire(), p"PTW req:${ptw.req.bits}\n")
433 434
  XSDebug(ptw.resp.valid, p"PTW resp:${ptw.resp.bits} (v:${ptw.resp.valid}r:${ptw.resp.ready}) \n")

Y
Yinan Xu 已提交
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
  // // assert check, can be remove when tlb can work
  // for(i <- 0 until Width) {
  //   assert((hit(i)&pfArray(i))===false.B, "hit(%d):%d pfArray(%d):%d v:0x%x pf:0x%x", i.U, hit(i), i.U, pfArray(i), v, pf)
  // }
  // for(i <- 0 until Width) {
  //   XSDebug(multiHit, p"vpn:0x${Hexadecimal(reqAddr(i).vpn)} hitVec:0x${Hexadecimal(VecInit(hitVec(i)).asUInt)} pfHitVec:0x${Hexadecimal(VecInit(pfHitVec(i)).asUInt)}\n")
  // }
  // for(i <- 0 until TlbEntrySize) {
  //   XSDebug(multiHit, p"entry(${i.U}): v:${v(i)} ${entry(i)}\n")
  // }
  // assert(!multiHit) // add multiHit here, later it should be removed (maybe), turn to miss and flush

  // for (i <- 0 until Width) {
  //   XSDebug(resp(i).valid && hit(i) && !(req(i).bits.vaddr===resp(i).bits.paddr), p"vaddr:0x${Hexadecimal(req(i).bits.vaddr)} paddr:0x${Hexadecimal(resp(i).bits.paddr)} hitVec:0x${Hexadecimal(VecInit(hitVec(i)).asUInt)}}\n")
  //   when (resp(i).valid && hit(i) && !(req(i).bits.vaddr===resp(i).bits.paddr)) {
  //     for (j <- 0 until TlbEntrySize) {
  //       XSDebug(true.B, p"TLBEntry(${j.U}): v:${v(j)} ${entry(j)}\n")
  //     }
  //   } // FIXME: remove me when tlb may be ok
  //   when(resp(i).valid && hit(i)) {
  //     assert(req(i).bits.vaddr===resp(i).bits.paddr, "vaddr:0x%x paddr:0x%x hitVec:%x ", req(i).bits.vaddr, resp(i).bits.paddr, VecInit(hitVec(i)).asUInt)
  //   } // FIXME: remove me when tlb may be ok
  // }
458

Y
Yinan Xu 已提交
459
  // assert((v&pf)===0.U, "v and pf can't be true at same time: v:0x%x pf:0x%x", v, pf)
Y
Yinan Xu 已提交
460
}
Z
zhanglinjuan 已提交
461 462

object TLB {
L
LinJiawei 已提交
463 464 465 466
  def apply
  (
    in: Seq[BlockTlbRequestIO],
    sfence: SfenceBundle,
L
LinJiawei 已提交
467
    csr: TlbCsrBundle,
L
LinJiawei 已提交
468 469 470 471
    width: Int,
    isDtlb: Boolean,
    shouldBlock: Boolean
  ) = {
Z
zhanglinjuan 已提交
472
    require(in.length == width)
473

Z
zhanglinjuan 已提交
474
    val tlb = Module(new TLB(width, isDtlb))
L
LinJiawei 已提交
475 476

    tlb.io.sfence <> sfence
L
LinJiawei 已提交
477
    tlb.io.csr <> csr
478

Z
zhanglinjuan 已提交
479 480
    if (!shouldBlock) { // dtlb
      for (i <- 0 until width) {
481 482 483 484 485 486 487 488
        tlb.io.requestor(i) <> in(i)
        // tlb.io.requestor(i).req.valid := in(i).req.valid
        // tlb.io.requestor(i).req.bits := in(i).req.bits
        // in(i).req.ready := tlb.io.requestor(i).req.ready

        // in(i).resp.valid := tlb.io.requestor(i).resp.valid
        // in(i).resp.bits := tlb.io.requestor(i).resp.bits
        // tlb.io.requestor(i).resp.ready := in(i).resp.ready
Z
zhanglinjuan 已提交
489 490 491 492
      }
    } else { // itlb
      require(width == 1)
      tlb.io.requestor(0).req.valid := in(0).req.valid
Z
zhanglinjuan 已提交
493
      tlb.io.requestor(0).req.bits := in(0).req.bits
494
      in(0).req.ready := !tlb.io.requestor(0).resp.bits.miss && in(0).resp.ready && tlb.io.requestor(0).req.ready
Z
zhanglinjuan 已提交
495 496 497

      in(0).resp.valid := tlb.io.requestor(0).resp.valid && !tlb.io.requestor(0).resp.bits.miss
      in(0).resp.bits := tlb.io.requestor(0).resp.bits
498
      tlb.io.requestor(0).resp.ready := in(0).resp.ready
Z
zhanglinjuan 已提交
499 500 501 502 503
    }

    tlb.io.ptw
  }
}