TLB.scala 22.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
package noop

import chisel3._
import chisel3.util._
import chisel3.util.experimental.BoringUtils

import bus.simplebus._
import bus.axi4._
import utils._

11
trait Sv39Const extends HasNOOPParameter{
12
  val Level = 3
13
  val offLen  = 12
14
  val ppn0Len = 9
15 16
  val ppn1Len = 9
  val ppn2Len = PAddrBits - offLen - ppn0Len - ppn1Len // 2
17
  val ppnLen = ppn2Len + ppn1Len + ppn0Len
18 19 20
  val vpn2Len = 9
  val vpn1Len = 9
  val vpn0Len = 9
21 22
  val vpnLen = vpn2Len + vpn1Len + vpn0Len
  
23 24
  //val paddrLen = PAddrBits
  //val vaddrLen = VAddrBits
25
  val satpLen = XLEN
26 27
  val satpModeLen = 4
  val asidLen = 16
28
  val flagLen = 8
29 30

  val ptEntryLen = XLEN
31 32 33 34
  val satpResLen = XLEN - ppnLen - satpModeLen - asidLen
  //val vaResLen = 25 // unused
  //val paResLen = 25 // unused 
  val pteResLen = XLEN - ppnLen - 2 - flagLen
35 36 37 38 39 40 41 42 43 44 45 46 47

  def vaBundle = new Bundle {
    val vpn2 = UInt(vpn2Len.W)
    val vpn1 = UInt(vpn1Len.W)
    val vpn0 = UInt(vpn0Len.W)
    val off  = UInt( offLen.W)
  }

  def vaBundle2 = new Bundle {
    val vpn  = UInt(vpnLen.W)
    val off  = UInt(offLen.W)
  }

48 49 50 51 52
  def vaBundle3 = new Bundle {
    val vpn = UInt(vpnLen.W)
    val off = UInt(offLen.W)
  }

Z
zhangzifei 已提交
53 54 55 56 57 58
  def vpnBundle = new Bundle {
    val vpn2 = UInt(vpn2Len.W)
    val vpn1 = UInt(vpn1Len.W)
    val vpn0 = UInt(vpn0Len.W)
  }

59 60 61 62 63 64 65 66 67 68 69
  def paBundle = new Bundle {
    val ppn2 = UInt(ppn2Len.W)
    val ppn1 = UInt(ppn1Len.W)
    val ppn0 = UInt(ppn0Len.W)
    val off  = UInt( offLen.W)
  }

  def paBundle2 = new Bundle {
    val ppn  = UInt(ppnLen.W)
    val off  = UInt(offLen.W)
  }
70 71 72

  def paddrApply(ppn: UInt, vpnn: UInt):UInt = {
    Cat(Cat(ppn, vpnn), 0.U(3.W))
Z
zhangzifei 已提交
73 74
  }
  
75
  def pteBundle = new Bundle {
76
    val reserved  = UInt(pteResLen.W)
77 78
    val ppn  = UInt(ppnLen.W)
    val rsw  = UInt(2.W)
79
    val flag = new Bundle {
80 81 82 83 84 85 86 87
      val d    = UInt(1.W)
      val a    = UInt(1.W)
      val g    = UInt(1.W)
      val u    = UInt(1.W)
      val x    = UInt(1.W)
      val w    = UInt(1.W)
      val r    = UInt(1.W)
      val v    = UInt(1.W)
88
    }
89 90 91 92 93
  }

  def satpBundle = new Bundle {
    val mode = UInt(satpModeLen.W)
    val asid = UInt(asidLen.W)
94
    val res = UInt(satpResLen.W)
95 96 97
    val ppn  = UInt(ppnLen.W)
  }

98
  def flagBundle = new Bundle {
99 100 101 102 103 104 105 106
    val d    = Bool()//UInt(1.W)
    val a    = Bool()//UInt(1.W)
    val g    = Bool()//UInt(1.W)
    val u    = Bool()//UInt(1.W)
    val x    = Bool()//UInt(1.W)
    val w    = Bool()//UInt(1.W)
    val r    = Bool()//UInt(1.W)
    val v    = Bool()//UInt(1.W)
107
  }
Z
zhangzifei 已提交
108

Z
zhangzifei 已提交
109
  def maskPaddr(ppn:UInt, vaddr:UInt, mask:UInt) = {
110
    MaskData(vaddr, Cat(ppn, 0.U(offLen.W)), Cat(Fill(ppn2Len, 1.U(1.W)), mask, 0.U(offLen.W)))
Z
zhangzifei 已提交
111 112 113
  }

  def MaskEQ(mask: UInt, pattern: UInt, vpn: UInt) = {
114
    (Cat("h1ff".U(vpn2Len.W), mask) & pattern) === (Cat("h1ff".U(vpn2Len.W), mask) & vpn)
Z
zhangzifei 已提交
115 116
  }

117 118
}

119
case class TLBConfig (
120 121 122
  name: String = "tlb",
  userBits: Int = 0,

Z
zhangzifei 已提交
123 124
  totalEntry: Int = 4,
  ways: Int = 4
125
)
126

127
sealed trait HasTlbConst extends Sv39Const{
128
  implicit val tlbConfig: TLBConfig
129 130

  val AddrBits: Int
131
  val PAddrBits: Int
132
  val VAddrBits: Int
133 134
  val XLEN: Int

135
  val tlbname = tlbConfig.name
136
  val userBits = tlbConfig.userBits
137

Z
zhangzifei 已提交
138
  val maskLen = vpn0Len + vpn1Len  // 18
139
  val metaLen = vpnLen + asidLen + maskLen + flagLen // 27 + 16 + 18 + 8 = 69, is asid necessary 
140
  val dataLen = ppnLen + PAddrBits // 
Z
zhangzifei 已提交
141
  val tlbLen = metaLen + dataLen
Z
zhangzifei 已提交
142 143 144 145 146
  val Ways = tlbConfig.ways
  val TotalEntry = tlbConfig.totalEntry
  val Sets = TotalEntry / Ways
  val IndexBits = log2Up(Sets)
  val TagBits = vpnLen - IndexBits
147

148
  val debug = true //&& tlbname == "dtlb"
149

Z
zhangzifei 已提交
150 151 152 153 154 155
  def vaddrTlbBundle = new Bundle {
    val tag = UInt(TagBits.W)
    val index = UInt(IndexBits.W)
    val off = UInt(offLen.W)
  }

Z
zhangzifei 已提交
156 157 158 159 160 161 162 163 164
  def metaBundle = new Bundle {
    val vpn = UInt(vpnLen.W)
    val asid = UInt(asidLen.W)
    val mask = UInt(maskLen.W) // to support super page
    val flag = UInt(flagLen.W)
  }

  def dataBundle = new Bundle {
    val ppn = UInt(ppnLen.W)
Z
zhangzifei 已提交
165 166 167 168 169 170 171 172 173
    val pteaddr = UInt(PAddrBits.W) // pte addr, used to write back pte when flag changes (flag.d, flag.v)
  }

  def tlbBundle = new Bundle {
    val vpn = UInt(vpnLen.W)
    val asid = UInt(asidLen.W)
    val mask = UInt(maskLen.W)
    val flag = UInt(flagLen.W)
    val ppn = UInt(ppnLen.W)
174
    val pteaddr = UInt(PAddrBits.W)
Z
zhangzifei 已提交
175 176
  }

Z
zhangzifei 已提交
177 178 179 180
  def tlbBundle2 = new Bundle {
    val meta = UInt(metaLen.W)
    val data = UInt(dataLen.W)
  }
181 182 183 184

  def getIndex(vaddr: UInt) : UInt = {
    vaddr.asTypeOf(vaddrTlbBundle).index
  }
185 186
}

187
sealed abstract class TlbBundle(implicit tlbConfig: TLBConfig) extends Bundle with HasNOOPParameter with HasTlbConst with Sv39Const
188
sealed abstract class TlbModule(implicit tlbConfig: TLBConfig) extends Module with HasNOOPParameter with HasTlbConst with Sv39Const with HasCSRConst
189

Z
zhangzifei 已提交
190
class TLBMDWriteBundle (val IndexBits: Int, val Ways: Int, val tlbLen: Int) extends Bundle with HasNOOPParameter with Sv39Const {
191 192 193 194 195 196 197 198 199 200 201 202 203
  val wen = Output(Bool())
  val windex = Output(UInt(IndexBits.W))
  val waymask = Output(UInt(Ways.W))
  val wdata = Output(UInt(tlbLen.W))
  
  def apply(wen: UInt, windex: UInt, waymask: UInt, vpn: UInt, asid: UInt, mask: UInt, flag: UInt, ppn: UInt, pteaddr: UInt) {
    this.wen := wen
    this.windex := windex
    this.waymask := waymask
    this.wdata := Cat(vpn, asid, mask, flag, ppn, pteaddr)
  }
}

Z
zhangzifei 已提交
204
class TLBMD(implicit val tlbConfig: TLBConfig) extends TlbModule {
205
  val io = IO(new Bundle {
Z
zhangzifei 已提交
206
    val tlbmd = Output(Vec(Ways, UInt(tlbLen.W)))
207 208
    val write = Flipped(new TLBMDWriteBundle(IndexBits = IndexBits, Ways = Ways, tlbLen = tlbLen))
    val rindex = Input(UInt(IndexBits.W))
209
    val ready = Output(Bool())
210
  })
211

Z
zhangzifei 已提交
212 213
  //val tlbmd = Reg(Vec(Ways, UInt(tlbLen.W)))
  val tlbmd = Mem(Sets, Vec(Ways, UInt(tlbLen.W)))
214
  io.tlbmd := tlbmd(io.rindex)
215

216 217
  //val reset = WireInit(false.B)
  val resetState = RegInit(true.B)//RegEnable(true.B, init = true.B, reset)
218
  val (resetSet, resetFinish) = Counter(resetState, Sets)
Z
zhangzifei 已提交
219
  when (resetFinish) { resetState := false.B }
220

221
  val writeWen = io.write.wen//WireInit(false.B)
222
  val writeSetIdx = io.write.windex
223
  val writeWayMask = io.write.waymask
224
  val writeData = io.write.wdata
225

Z
zhangzifei 已提交
226
  val wen = Mux(resetState, true.B, writeWen)
227 228 229 230
  val setIdx = Mux(resetState, resetSet, writeSetIdx)
  val waymask = Mux(resetState, Fill(Ways, "b1".U), writeWayMask)
  val dataword = Mux(resetState, 0.U, writeData)
  val wdata = VecInit(Seq.fill(Ways)(dataword))
231

232
  when (wen) { tlbmd.write(setIdx, wdata, waymask.asBools) }
233

234
  io.ready := !resetState
Z
zhangzifei 已提交
235 236 237
  def rready() = !resetState
  def wready() = !resetState
}
238

Z
zhangzifei 已提交
239
class TLB(implicit val tlbConfig: TLBConfig) extends TlbModule{
240
  val io = IO(new Bundle {
241
    val in = Flipped(new SimpleBusUC(userBits = userBits, addrBits = VAddrBits))
242
    val out = new SimpleBusUC(userBits = userBits)
243

244
    val mem = new SimpleBusUC(userBits = userBits)
Z
zhangzifei 已提交
245 246 247
    val flush = Input(Bool()) 
    val csrMMU = new MMUIO
    val cacheEmpty = Input(Bool())
248
    val ipf = Output(Bool())
249 250
  })

251 252 253
  val satp = WireInit(0.U(XLEN.W))
  BoringUtils.addSink(satp, "CSRSATP")

Z
zhangzifei 已提交
254 255
  // tlb exec
  val tlbExec = Module(new TLBExec)
256
  val tlbEmpty = Module(new TLBEmpty)
257
  val mdTLB = Module(new TLBMD)
Z
zhangzifei 已提交
258
  val mdUpdate = Wire(Bool())
259
  
Z
zhangzifei 已提交
260
  tlbExec.io.flush := io.flush
261
  tlbExec.io.satp := satp
Z
zhangzifei 已提交
262 263
  tlbExec.io.mem <> io.mem
  tlbExec.io.pf <> io.csrMMU
264 265 266 267 268
  tlbExec.io.md <> RegEnable(mdTLB.io.tlbmd, mdUpdate)
  tlbExec.io.mdReady := mdTLB.io.ready
  mdTLB.io.rindex := getIndex(io.in.req.bits.addr)
  mdTLB.io.write <> tlbExec.io.mdWrite
  
269
  io.ipf := false.B
270 271 272 273 274 275 276 277 278 279
  
  // meta reset
  val flushTLB = WireInit(false.B)
  BoringUtils.addSink(flushTLB, "MOUFlushTLB")
  mdTLB.reset := reset.asBool || flushTLB
  Debug() {
    when(flushTLB && GTimer() > 77437080.U) {
      printf("%d sfence_vma req.pc:%x valid:%d\n", GTimer(), io.in.req.bits.addr, io.in.req.valid)
    }
  }
Z
zhangzifei 已提交
280 281

  // VM enable && io
282
  val vmEnable = satp.asTypeOf(satpBundle).mode === 8.U && (io.csrMMU.priviledgeMode < ModeM)
283

284
  def PipelineConnectTLB[T <: Data](left: DecoupledIO[T], right: DecoupledIO[T], update: Bool, rightOutFire: Bool, isFlush: Bool, vmEnable: Bool) = {
285 286 287 288 289 290 291 292
    val valid = RegInit(false.B)
    when (rightOutFire) { valid := false.B }
    when (left.valid && right.ready && vmEnable) { valid := true.B }
    when (isFlush) { valid := false.B }

    left.ready := right.ready
    right.bits <> RegEnable(left.bits, left.valid && right.ready)
    right.valid := valid //&& !isFlush
293 294

    update := left.valid && right.ready
295 296
  }

Z
zhangzifei 已提交
297 298
  tlbEmpty.io.in <> DontCare
  tlbEmpty.io.out.ready := DontCare
299
  PipelineConnectTLB(io.in.req, tlbExec.io.in, mdUpdate, tlbExec.io.isFinish, io.flush, vmEnable)
300
  if(tlbname == "dtlb") {
Z
zhangzifei 已提交
301
    PipelineConnect(tlbExec.io.out, tlbEmpty.io.in, tlbEmpty.io.out.fire(), io.flush)
302
  }
303 304
  when(!vmEnable) {
    tlbExec.io.out.ready := true.B // let existed request go out
305
    if( tlbname == "dtlb") { tlbEmpty.io.out.ready := true.B }
306 307 308 309 310 311 312 313
    io.out.req.valid := io.in.req.valid
    io.in.req.ready := io.out.req.ready
    io.out.req.bits.addr := io.in.req.bits.addr(PAddrBits-1, 0)
    io.out.req.bits.size := io.in.req.bits.size
    io.out.req.bits.cmd := io.in.req.bits.cmd
    io.out.req.bits.wmask := io.in.req.bits.wmask
    io.out.req.bits.wdata := io.in.req.bits.wdata
    io.out.req.bits.user.map(_ := io.in.req.bits.user.getOrElse(0.U))
314
  }.otherwise {
315 316
    if (tlbname == "dtlb") { io.out.req <> tlbEmpty.io.out}
    else { io.out.req <> tlbExec.io.out }
317
  }
318
  io.out.resp <> io.in.resp
319

Z
zhangzifei 已提交
320 321 322 323 324 325
  // lsu need dtlb signals
  if(tlbname == "dtlb") {
    val alreadyOutFinish = RegEnable(true.B, init=false.B, tlbExec.io.out.valid && !tlbExec.io.out.ready)
    when(alreadyOutFinish && tlbExec.io.out.fire()) { alreadyOutFinish := false.B}
    val tlbFinish = (tlbExec.io.out.valid && !alreadyOutFinish) || tlbExec.io.pf.isPF()
    BoringUtils.addSource(tlbFinish, "DTLBFINISH")
326
    BoringUtils.addSource(io.csrMMU.isPF(), "DTLBPF")
Z
zhangzifei 已提交
327 328 329 330
    BoringUtils.addSource(vmEnable, "DTLBENABLE")
  }

  // instruction page fault
331 332 333 334
  if (tlbname == "itlb") {
    when (tlbExec.io.ipf && vmEnable) {
      tlbExec.io.out.ready := io.cacheEmpty && io.in.resp.ready
      io.out.req.valid := false.B
335 336 337
    }

    when (tlbExec.io.ipf && vmEnable && io.cacheEmpty) {
338 339 340
      io.in.resp.valid := true.B
      io.in.resp.bits.rdata := 0.U
      io.in.resp.bits.cmd := SimpleBusCmd.readLast
341
      io.in.resp.bits.user.map(_ := tlbExec.io.in.bits.user.getOrElse(0.U))
342
      io.ipf := tlbExec.io.ipf
343 344
    }
  }
345

346 347 348 349 350 351
  Debug() {
    if (debug) {
      printf("[TLB-"  + tlbname+ "]: Timer:%d---------\n", GTimer())
      printf("[TLB-"  + tlbname+ "]: InReq(%d, %d) InResp(%d, %d) OutReq(%d, %d) OutResp(%d, %d) vmEnable:%d mode:%d\n", io.in.req.valid, io.in.req.ready, io.in.resp.valid, io.in.resp.ready, io.out.req.valid, io.out.req.ready, io.out.resp.valid, io.out.resp.ready, vmEnable, io.csrMMU.priviledgeMode)
      printf("[TLB-"  + tlbname+ "]: InReq: addr:%x cmd:%d wdata:%x OutReq: addr:%x cmd:%x wdata:%x\n", io.in.req.bits.addr, io.in.req.bits.cmd, io.in.req.bits.wdata, io.out.req.bits.addr, io.out.req.bits.cmd, io.out.req.bits.wdata)
      printf("[TLB-"  + tlbname+ "]: OutResp: rdata:%x cmd:%x Inresp: rdata:%x cmd:%x\n", io.out.resp.bits.rdata, io.out.resp.bits.cmd, io.in.resp.bits.rdata, io.in.resp.bits.cmd)
352
      printf("[TLB-"  + tlbname+ "]: satp:%x flush:%d cacheEmpty:%d instrPF:%d loadPF:%d storePF:%d \n", satp, io.flush, io.cacheEmpty, io.ipf, io.csrMMU.loadPF, io.csrMMU.storePF)
353 354 355
    }
  }  

356 357
}

Z
zhangzifei 已提交
358
class TLBExec(implicit val tlbConfig: TLBConfig) extends TlbModule{
359
  val io = IO(new Bundle {
360 361
    val in = Flipped(Decoupled(new SimpleBusReqBundle(userBits = userBits, addrBits = VAddrBits)))
    val out = Decoupled(new SimpleBusReqBundle(userBits = userBits))
Z
zhangzifei 已提交
362

363 364 365
    val md = Input(Vec(Ways, UInt(tlbLen.W)))
    val mdWrite = new TLBMDWriteBundle(IndexBits = IndexBits, Ways = Ways, tlbLen = tlbLen)
    val mdReady = Input(Bool())
Z
zhangzifei 已提交
366

367
    val mem = new SimpleBusUC(userBits = userBits)
Z
zhangzifei 已提交
368
    val flush = Input(Bool()) 
369
    val satp = Input(UInt(XLEN.W))
Z
zhangzifei 已提交
370 371
    val pf = new MMUIO
    val ipf = Output(Bool())
372
    val isFinish = Output(Bool())
373 374
  })

375 376
  val md = io.md//RegEnable(mdTLB.io.tlbmd, io.in.ready)
  
Z
zhangzifei 已提交
377 378 379 380
  // lazy renaming
  val req = io.in.bits
  val vpn = req.addr.asTypeOf(vaBundle2).vpn.asTypeOf(vpnBundle)
  val pf = io.pf
381
  val satp = io.satp.asTypeOf(satpBundle)
Z
zhangzifei 已提交
382 383 384 385 386 387 388

  // pf init
  pf.loadPF := false.B
  pf.storePF := false.B
  pf.addr := req.addr

  // check hit or miss
Z
zhangzifei 已提交
389
  val hitVec = VecInit(md.map(m => m.asTypeOf(tlbBundle).flag.asTypeOf(flagBundle).v && (m.asTypeOf(tlbBundle).asid === satp.asid) && MaskEQ(m.asTypeOf(tlbBundle).mask, m.asTypeOf(tlbBundle).vpn, vpn.asUInt))).asUInt
Z
zhangzifei 已提交
390 391
  val hit = io.in.valid && hitVec.orR
  val miss = io.in.valid && !hitVec.orR
392

Z
zhangzifei 已提交
393
  val victimWaymask = if (Ways > 1) (1.U << LFSR64()(log2Up(Ways)-1,0)) else "b1".U
Z
zhangzifei 已提交
394 395
  val waymask = Mux(hit, hitVec, victimWaymask)

396 397 398
  val loadPF = WireInit(false.B)
  val storePF = WireInit(false.B)

Z
zhangzifei 已提交
399
  // hit
Z
zhangzifei 已提交
400 401
  val hitMeta = Mux1H(waymask, md).asTypeOf(tlbBundle2).meta.asTypeOf(metaBundle)
  val hitData = Mux1H(waymask, md).asTypeOf(tlbBundle2).data.asTypeOf(dataBundle)
Z
zhangzifei 已提交
402 403 404
  val hitFlag = hitMeta.flag.asTypeOf(flagBundle)
  val hitMask = hitMeta.mask
  // hit write back pte.flag
405
  val hitinstrPF = WireInit(false.B)
406
  val hitWB = hit && (!hitFlag.a || !hitFlag.d && req.isWrite()) && !hitinstrPF && !(loadPF || storePF || io.pf.isPF())
407
  val hitRefillFlag = Cat(req.isWrite().asUInt, 1.U(1.W), 0.U(6.W)) | hitFlag.asUInt
Z
zhangzifei 已提交
408
  val hitWBStore = RegEnable(Cat(0.U(10.W), hitData.ppn, 0.U(2.W), hitRefillFlag), hitWB)
409

Z
zhangzifei 已提交
410 411 412 413 414 415
  // hit permission check
  val hitCheck = hit /*&& hitFlag.v */&& !(pf.priviledgeMode === ModeU && !hitFlag.u) && !(pf.priviledgeMode === ModeS && hitFlag.u && !pf.status_sum)
  val hitExec = hitCheck && hitFlag.x
  val hitLoad = hitCheck && (hitFlag.r || pf.status_mxr && hitFlag.x)
  val hitStore = hitCheck && hitFlag.w
  
416 417 418 419 420
  val isAMO = WireInit(false.B)
  if (tlbname == "dtlb") {
    BoringUtils.addSink(isAMO, "ISAMO")
  }

421 422
  io.pf.loadPF := RegNext(loadPF, init =false.B)
  io.pf.storePF := RegNext(storePF, init = false.B)
423

424
  if (tlbname == "itlb") { hitinstrPF := !hitExec  && hit}
425
  if (tlbname == "dtlb") { 
426 427
    loadPF := !hitLoad && req.isRead() && hit && !isAMO
    storePF := (!hitStore && req.isWrite() && hit) || (!hitLoad && req.isRead() && hit && isAMO)
428
  }
429

Z
zhangzifei 已提交
430
  // miss
431
  val s_idle :: s_memReadReq :: s_memReadResp :: s_write_pte :: s_wait_resp :: s_miss_slpf :: Nil = Enum(6)
432
  val state = RegInit(s_idle)
Z
zhangzifei 已提交
433 434
  val level = RegInit(Level.U(log2Up(Level).W))
  
435
  val memRespStore = Reg(UInt(XLEN.W))
436 437
  val missMask = WireInit("h3ffff".U(maskLen.W))
  val missMaskStore = Reg(UInt(maskLen.W))
Z
zhangzifei 已提交
438 439 440
  val missMetaRefill = WireInit(false.B)
  val missRefillFlag = WireInit(0.U(8.W))
  val memRdata = io.mem.resp.bits.rdata.asTypeOf(pteBundle)
441
  val raddr = Reg(UInt(PAddrBits.W))
442 443
  val alreadyOutFire = RegEnable(true.B, init = false.B, io.out.fire)

Z
zhangzifei 已提交
444 445
  //handle flush
  val needFlush = RegInit(false.B)
446
  val ioFlush = io.flush
447 448
  val isFlush = needFlush || ioFlush
  when (ioFlush && (state =/= s_idle)) { needFlush := true.B}
449
  when (io.out.fire() && needFlush) { needFlush := false.B}
450

Z
zhangzifei 已提交
451
  val missIPF = RegInit(false.B)
452

Z
zhangzifei 已提交
453
  // state machine to handle miss(ptw) and pte-writing-back
454 455
  switch (state) {
    is (s_idle) {
456
      when (!ioFlush && hitWB) {
457 458
        state := s_write_pte
        needFlush := false.B
459
        alreadyOutFire := false.B
460
      }.elsewhen (miss && !ioFlush) {
461
        state := s_memReadReq
462 463
        raddr := paddrApply(satp.ppn, vpn.vpn2) //
        level := Level.U
464
        needFlush := false.B
465
        alreadyOutFire := false.B
466 467 468
      }
    }

469
    is (s_memReadReq) { 
470 471 472 473
      when (isFlush) {
        state := s_idle
        needFlush := false.B
      }.elsewhen (io.mem.req.fire()) { state := s_memReadResp}
474
    }
475

476
    is (s_memReadResp) { 
Z
zhangzifei 已提交
477
      val missflag = memRdata.flag.asTypeOf(flagBundle)
478 479 480 481
      when (io.mem.resp.fire()) {
        when (isFlush) {
          state := s_idle
          needFlush := false.B
482
        }.elsewhen (!(missflag.r || missflag.x) && (level===3.U || level===2.U)) {
Z
zhangzifei 已提交
483
          when(!missflag.v || (!missflag.r && missflag.w)) { //TODO: fix needflush
484
            if(tlbname == "itlb") { state := s_wait_resp } else { state := s_miss_slpf }
Z
zhangzifei 已提交
485
            if(tlbname == "itlb") { missIPF := true.B }
486
            if(tlbname == "dtlb") { 
487 488
              loadPF := req.isRead() && !isAMO 
              storePF := req.isWrite() || isAMO 
489
            }  
490 491 492 493 494 495 496
            Debug() {
              if(debug) {
                printf("%d " + tlbname +" tlbException!!! ", GTimer())
                printf(p" req:${req}  Memreq:${io.mem.req}  MemResp:${io.mem.resp}")
                printf(" level:%d",level)
                printf("\n")
              }
Z
zhangzifei 已提交
497 498 499 500
            }
          }.otherwise {
            state := s_memReadReq
            raddr := paddrApply(memRdata.ppn, Mux(level === 3.U, vpn.vpn1, vpn.vpn0))
501
          }
Z
zhangzifei 已提交
502
        }.elsewhen (level =/= 0.U) { //TODO: fix needFlush
503
          val permCheck = missflag.v && !(pf.priviledgeMode === ModeU && !missflag.u) && !(pf.priviledgeMode === ModeS && missflag.u && !pf.status_sum)
Z
zhangzifei 已提交
504 505 506
          val permExec = permCheck && missflag.x
          val permLoad = permCheck && (missflag.r || pf.status_mxr && missflag.x)
          val permStore = permCheck && missflag.w
507
          val updateAD = !missflag.a || (!missflag.d && req.isWrite())
Z
zhangzifei 已提交
508
          val updateData = Cat( 0.U(56.W), req.isWrite(), 1.U(1.W), 0.U(6.W) )
Z
zhangzifei 已提交
509
          missRefillFlag := Cat(req.isWrite(), 1.U(1.W), 0.U(6.W)) | missflag.asUInt
Z
zhangzifei 已提交
510 511
          memRespStore := io.mem.resp.bits.rdata | updateData 
          if(tlbname == "itlb") {
Z
zhangzifei 已提交
512
            when (!permExec) { missIPF := true.B ; state := s_wait_resp}
Z
zhangzifei 已提交
513 514
            .otherwise { 
              state := Mux(updateAD, s_write_pte, s_wait_resp)
Z
zhangzifei 已提交
515
              missMetaRefill := true.B
Z
zhangzifei 已提交
516
            }
517
          }
Z
zhangzifei 已提交
518 519
          if(tlbname == "dtlb") {
            when((!permLoad && req.isRead()) || (!permStore && req.isWrite())) { 
520 521 522
              state := s_miss_slpf
              loadPF := req.isRead() && !isAMO
              storePF := req.isWrite() || isAMO
Z
zhangzifei 已提交
523 524
            }.otherwise {
              state := Mux(updateAD, s_write_pte, s_wait_resp)
Z
zhangzifei 已提交
525
              missMetaRefill := true.B
Z
zhangzifei 已提交
526
            }
527
          }
Z
zhangzifei 已提交
528
          missMask := Mux(level===3.U, 0.U(maskLen.W), Mux(level===2.U, "h3fe00".U(maskLen.W), "h3ffff".U(maskLen.W)))
Z
zhangzifei 已提交
529
          missMaskStore := missMask
530
        }
Z
zhangzifei 已提交
531
        level := level - 1.U
532
      }
Z
zhangzifei 已提交
533
    }
534

535 536 537 538 539 540 541
    is (s_write_pte) {
      when (isFlush) {
        state := s_idle
        needFlush := false.B
      }.elsewhen (io.mem.req.fire()) { state := s_wait_resp }
    }

542
    is (s_wait_resp) { when (io.out.fire() || ioFlush || alreadyOutFire){
543
      state := s_idle
Z
zhangzifei 已提交
544
      missIPF := false.B
545
      alreadyOutFire := false.B
546
    }}
547 548 549 550

    is (s_miss_slpf) {
      state := s_idle
    }
551
  }
552

Z
zhangzifei 已提交
553
  // mem
554
  val cmd = Mux(state === s_write_pte, SimpleBusCmd.write, SimpleBusCmd.read)
Z
zhangzifei 已提交
555
  io.mem.req.bits.apply(addr = Mux(hitWB, hitData.pteaddr, raddr), cmd = cmd, size = (if (XLEN == 64) "b11".U else "b10".U), wdata =  Mux( hitWB, hitWBStore, memRespStore), wmask = 0xff.U)
556
  io.mem.req.valid := ((state === s_memReadReq || state === s_write_pte) && !isFlush)
Z
zhangzifei 已提交
557
  io.mem.resp.ready := true.B
558

559
  // tlb refill
560
  io.mdWrite.apply(wen = RegNext((missMetaRefill && !isFlush) || (hitWB && state === s_idle && !isFlush), init = false.B), 
Z
zhangzifei 已提交
561
    windex = RegNext(getIndex(req.addr)), waymask = RegNext(waymask), vpn = RegNext(vpn.asUInt), 
562 563 564
    asid = RegNext(Mux(hitWB, hitMeta.asid, satp.asid)), mask = RegNext(Mux(hitWB, hitMask, missMask)), 
    flag = RegNext(Mux(hitWB, hitRefillFlag, missRefillFlag)), ppn = RegNext(Mux(hitWB, hitData.ppn, memRdata.ppn)), 
    pteaddr = RegNext((Mux(hitWB, hitData.pteaddr, raddr))))
565

Z
zhangzifei 已提交
566
  // io
567
  io.out.bits := req
568
  io.out.bits.addr := Mux(hit, maskPaddr(hitData.ppn, req.addr(PAddrBits-1, 0), hitMask), maskPaddr(memRespStore.asTypeOf(pteBundle).ppn, req.addr(PAddrBits-1, 0), missMaskStore))
569
  io.out.valid := io.in.valid && Mux(hit && !hitWB, !(io.pf.isPF() || loadPF || storePF), state === s_wait_resp)// && !alreadyOutFire
570
  
571
  io.in.ready := io.out.ready && (state === s_idle) && !miss && !hitWB && io.mdReady && (!io.pf.isPF() && !loadPF && !storePF)//maybe be optimized
572

573
  io.ipf := Mux(hit, hitinstrPF, missIPF)
574
  io.isFinish := io.out.fire() || io.pf.isPF()
575 576 577 578 579

  Debug() {
    if (debug) {
      printf("[TLBExec-"  + tlbname+ "]: Timer:%d---------\n", GTimer())
      printf("[TLBExec-"  + tlbname+ "]: In(%d, %d) Out(%d, %d) InAddr:%x OutAddr:%x cmd:%d \n", io.in.valid, io.in.ready, io.out.valid, io.out.ready, req.addr, io.out.bits.addr, req.cmd)
580
      printf("[TLBExec-"  + tlbname+ "]: isAMO:%d io.Flush:%d needFlush:%d alreadyOutFire:%d isFinish:%d\n",isAMO, io.flush, needFlush, alreadyOutFire, io.isFinish)
581 582
      printf("[TLBExec-"  + tlbname+ "]: hit:%d hitWB:%d hitVPN:%x hitFlag:%x hitPPN:%x hitRefillFlag:%x hitWBStore:%x hitCheck:%d hitExec:%d hitLoad:%d hitStore:%d\n", hit, hitWB, hitMeta.vpn, hitFlag.asUInt, hitData.ppn, hitRefillFlag, hitWBStore, hitCheck, hitExec, hitLoad, hitStore)
      printf("[TLBExec-"  + tlbname+ "]: miss:%d state:%d level:%d raddr:%x memRdata:%x missMask:%x missRefillFlag:%x missMetaRefill:%d\n", miss, state, level, raddr, memRdata.asUInt, missMask, missRefillFlag, missMetaRefill)
583 584
      printf("[TLBExec-"  + tlbname+ "]: meta/data: (0)%x|%b|%x (1)%x|%b|%x (2)%x|%b|%x (3)%x|%b|%x rread:%d\n", md(0).asTypeOf(tlbBundle).vpn, md(0).asTypeOf(tlbBundle).flag, md(0).asTypeOf(tlbBundle).ppn, md(1).asTypeOf(tlbBundle).vpn, md(1).asTypeOf(tlbBundle).flag, md(1).asTypeOf(tlbBundle).ppn, md(2).asTypeOf(tlbBundle).vpn, md(2).asTypeOf(tlbBundle).flag, md(2).asTypeOf(tlbBundle).ppn, md(3).asTypeOf(tlbBundle).vpn, md(3).asTypeOf(tlbBundle).flag, md(3).asTypeOf(tlbBundle).ppn, io.mdReady)
      printf("[TLBExec-"  + tlbname+ "]: md: wen:%d windex:%x waymask:%x vpn:%x asid:%x mask:%x flag:%x asid:%x ppn:%x pteaddr:%x\n", io.mdWrite.wen, io.mdWrite.windex, io.mdWrite.waymask, io.mdWrite.wdata.asTypeOf(tlbBundle).vpn, io.mdWrite.wdata.asTypeOf(tlbBundle).asid, io.mdWrite.wdata.asTypeOf(tlbBundle).mask, io.mdWrite.wdata.asTypeOf(tlbBundle).flag, io.mdWrite.wdata.asTypeOf(tlbBundle).asid, io.mdWrite.wdata.asTypeOf(tlbBundle).ppn, io.mdWrite.wdata.asTypeOf(tlbBundle).pteaddr)
585
      printf("[TLBExec-"  + tlbname+ "]: MemReq(%d, %d) MemResp(%d, %d) addr:%x cmd:%d rdata:%x cmd:%d\n", io.mem.req.valid, io.mem.req.ready, io.mem.resp.valid, io.mem.resp.ready, io.mem.req.bits.addr, io.mem.req.bits.cmd, io.mem.resp.bits.rdata, io.mem.resp.bits.cmd)
586
      printf("[TLBExec-"  + tlbname+ "]: io.ipf:%d hitinstrPF:%d missIPF:%d pf.loadPF:%d pf.storePF:%d loadPF:%d storePF:%d\n", io.ipf, hitinstrPF, missIPF, io.pf.loadPF, io.pf.storePF, loadPF, storePF)
587 588
    }
  }
589
}
Z
zhangzifei 已提交
590

591 592 593 594 595 596 597 598 599
class TLBEmpty(implicit val tlbConfig: TLBConfig) extends TlbModule {
  val io = IO(new Bundle {
    val in = Flipped(Decoupled(new SimpleBusReqBundle(userBits = userBits)))
    val out = Decoupled(new SimpleBusReqBundle(userBits = userBits))
  })

  io.out <> io.in
}

600
object TLB {
601
  def apply(in: SimpleBusUC, mem: SimpleBusUC, flush: Bool, csrMMU: MMUIO)(implicit tlbConfig: TLBConfig) = {
602
    val tlb = Module(new TLB)
603 604 605 606
    tlb.io.in <> in
    tlb.io.mem <> mem
    tlb.io.flush := flush
    tlb.io.csrMMU <> csrMMU
607 608
    tlb
  }
609
}