Cache.scala 23.5 KB
Newer Older
Z
Zihao Yu 已提交
1 2 3 4
package noop

import chisel3._
import chisel3.util._
5
import chisel3.util.experimental.BoringUtils
Z
Zihao Yu 已提交
6

7
import bus.simplebus._
Z
Zihao Yu 已提交
8
import bus.axi4._
Z
Zihao Yu 已提交
9 10
import utils._

11 12 13 14
case class CacheConfig (
  ro: Boolean = false,
  name: String = "cache",
  userBits: Int = 0,
Z
Zihao Yu 已提交
15
  cacheLevel: Int = 1,
16 17 18 19 20

  totalSize: Int = 32, // Kbytes
  ways: Int = 4
)

21
sealed trait HasCacheConst {
22 23
  implicit val cacheConfig: CacheConfig

24
  val PAddrBits: Int
25
  val XLEN: Int
26

27 28 29 30
  val cacheName = cacheConfig.name
  val userBits = cacheConfig.userBits

  val ro = cacheConfig.ro
31 32
  val hasCoh = !ro
  val hasCohInt = (if (hasCoh) 1 else 0)
Z
Zihao Yu 已提交
33
  val hasPrefetch = cacheName == "l2cache"
34
	
Z
Zihao Yu 已提交
35
  val cacheLevel = cacheConfig.cacheLevel
36 37
  val TotalSize = cacheConfig.totalSize
  val Ways = cacheConfig.ways
38
  val LineSize = XLEN // byte
W
William Wang 已提交
39
  val LineBeats = LineSize / 8 //DATA WIDTH 64
40
  val Sets = TotalSize * 1024 / LineSize / Ways
Z
Zihao Yu 已提交
41 42
  val OffsetBits = log2Up(LineSize)
  val IndexBits = log2Up(Sets)
Z
Zihao Yu 已提交
43
  val WordIndexBits = log2Up(LineBeats)
44
  val TagBits = PAddrBits - OffsetBits - IndexBits
Z
Zihao Yu 已提交
45

46
  val debug = true
Z
Zihao Yu 已提交
47

48 49 50 51
  def addrBundle = new Bundle {
    val tag = UInt(TagBits.W)
    val index = UInt(IndexBits.W)
    val wordIndex = UInt(WordIndexBits.W)
52
    val byteOffset = UInt((if (XLEN == 64) 3 else 2).W)
53 54
  }

55
  def CacheMetaArrayReadBus() = new SRAMReadBus(new MetaBundle, set = Sets, way = Ways)
56
  def CacheDataArrayReadBus() = new SRAMReadBus(new DataBundle, set = Sets * LineBeats, way = Ways)
57
  def CacheMetaArrayWriteBus() = new SRAMWriteBus(new MetaBundle, set = Sets, way = Ways)
58
  def CacheDataArrayWriteBus() = new SRAMWriteBus(new DataBundle, set = Sets * LineBeats, way = Ways)
59

60 61 62
  def getMetaIdx(addr: UInt) = addr.asTypeOf(addrBundle).index
  def getDataIdx(addr: UInt) = Cat(addr.asTypeOf(addrBundle).index, addr.asTypeOf(addrBundle).wordIndex)

63
  def isSameWord(a1: UInt, a2: UInt) = ((a1 >> 2) === (a2 >> 2))
64
  def isSetConflict(a1: UInt, a2: UInt) = (a1.asTypeOf(addrBundle).index === a2.asTypeOf(addrBundle).index)
65 66
}

67 68
sealed abstract class CacheBundle(implicit cacheConfig: CacheConfig) extends Bundle with HasNOOPParameter with HasCacheConst
sealed abstract class CacheModule(implicit cacheConfig: CacheConfig) extends Module with HasNOOPParameter with HasCacheConst
69

70
sealed class MetaBundle(implicit val cacheConfig: CacheConfig) extends CacheBundle {
71 72 73
  val tag = Output(UInt(TagBits.W))
  val valid = Output(Bool())
  val dirty = Output(Bool())
74

75 76 77 78 79 80
  def apply(tag: UInt, valid: Bool, dirty: Bool) = {
    this.tag := tag
    this.valid := valid
    this.dirty := dirty
    this
  }
81 82
}

83
sealed class DataBundle(implicit val cacheConfig: CacheConfig) extends CacheBundle {
84
  val data = Output(UInt(DataBits.W))
85 86 87 88 89

  def apply(data: UInt) = {
    this.data := data
    this
  }
90 91
}

92
sealed class Stage1IO(implicit val cacheConfig: CacheConfig) extends CacheBundle {
93
  val req = new SimpleBusReqBundle(userBits = userBits)
94 95 96
}

// meta read
97
sealed class CacheStage1(implicit val cacheConfig: CacheConfig) extends CacheModule {
98
  val io = IO(new Bundle {
99
    val in = Flipped(Decoupled(new SimpleBusReqBundle(userBits = userBits)))
100
    val out = Decoupled(new Stage1IO)
101 102
    val metaReadBus = CacheMetaArrayReadBus()
    val dataReadBus = CacheDataArrayReadBus()
103 104

    val s2s3Empty = Input(Bool()) // FIXME: remove me when do not use nut's cache
105 106
  })

107
  if (ro) when (io.in.fire()) { assert(!io.in.bits.isWrite()) }
108
  Debug(){
109 110 111 112
    if (debug) {
      when(io.in.fire()){
        printf("[L1$] " +name+" cache stage1, addr in: %x, user: %x\n", io.in.bits.addr, io.in.bits.user.getOrElse(0.U))
      }
113 114
    }
  }
115

116
  // read meta array and data array
117
  val readBusValid = io.in.valid && io.out.ready
118 119
  io.metaReadBus.apply(valid = readBusValid, setIdx = getMetaIdx(io.in.bits.addr))
  io.dataReadBus.apply(valid = readBusValid, setIdx = getDataIdx(io.in.bits.addr))
120 121

  io.out.bits.req := io.in.bits
122 123
  io.out.valid := io.in.valid && io.metaReadBus.req.ready && io.dataReadBus.req.ready && io.s2s3Empty // FIXME: remove me when do not use nut's cache 
  io.in.ready := (!io.in.valid || io.out.fire()) && io.metaReadBus.req.ready && io.dataReadBus.req.ready && io.s2s3Empty // FIXME: remove me when do not use nut's cache
Z
nothing  
zhanglinjuan 已提交
124

125 126 127 128 129
  Debug() {
    if (debug) {
      printf("%d: [" + cacheName + " stage1]: in.ready = %d, in.valid = %d, out.valid = %d, out.ready = %d, addr = %x, cmd = %x, dataReadBus.req.valid = %d\n",
        GTimer(), io.in.ready, io.in.valid, io.out.valid, io.out.ready, io.in.bits.addr, io.in.bits.cmd, io.dataReadBus.req.valid)
    }
Z
nothing  
zhanglinjuan 已提交
130
  }
131 132
}

133
sealed class Stage2IO(implicit val cacheConfig: CacheConfig) extends CacheBundle {
134
  val req = new SimpleBusReqBundle(userBits = userBits)
135
  val metas = Vec(Ways, new MetaBundle)
136
  val datas = Vec(Ways, new DataBundle)
137 138
  val hit = Output(Bool())
  val waymask = Output(UInt(Ways.W))
Z
Zihao Yu 已提交
139
  val mmio = Output(Bool())
140 141
  val isForwardData = Output(Bool())
  val forwardData = Output(CacheDataArrayWriteBus().req.bits)
142 143 144
}

// check
145
sealed class CacheStage2(implicit val cacheConfig: CacheConfig) extends CacheModule {
146
  val io = IO(new Bundle {
147 148
    val in = Flipped(Decoupled(new Stage1IO))
    val out = Decoupled(new Stage2IO)
149
    val metaReadResp = Flipped(Vec(Ways, new MetaBundle))
150
    val dataReadResp = Flipped(Vec(Ways, new DataBundle))
151 152
    val metaWriteBus = Input(CacheMetaArrayWriteBus())
    val dataWriteBus = Input(CacheDataArrayWriteBus())
153 154 155
  })

  val req = io.in.bits.req
Z
Zihao Yu 已提交
156
  val addr = req.addr.asTypeOf(addrBundle)
157

158 159 160
  val isForwardMeta = io.in.valid && io.metaWriteBus.req.valid && io.metaWriteBus.req.bits.setIdx === getMetaIdx(req.addr)
  val isForwardMetaReg = RegInit(false.B)
  when (isForwardMeta) { isForwardMetaReg := true.B }
161
  when (io.in.fire() || !io.in.valid) { isForwardMetaReg := false.B }
162 163 164
  val forwardMetaReg = RegEnable(io.metaWriteBus.req.bits, isForwardMeta)

  val metaWay = Wire(Vec(Ways, chiselTypeOf(forwardMetaReg.data)))
165
  forwardMetaReg.waymask.getOrElse("b1".U).asBools.zipWithIndex.map { case (w, i) =>
166 167 168 169
    metaWay(i) := Mux(isForwardMetaReg && w, forwardMetaReg.data, io.metaReadResp(i))
  }

  val hitVec = VecInit(metaWay.map(m => m.valid && (m.tag === addr.tag) && io.in.valid)).asUInt
170
  val victimWaymask = if (Ways > 1) (1.U << LFSR64()(log2Up(Ways)-1,0)) else "b1".U
171 172 173 174 175 176 177 178 179
   
  val invalidVec = VecInit(metaWay.map(m => !m.valid)).asUInt
  val hasInvalidWay = invalidVec.orR
  val refillInvalidWaymask = Mux(invalidVec >= 8.U, "b1000".U,
    Mux(invalidVec >= 4.U, "b0100".U,
    Mux(invalidVec >= 2.U, "b0010".U, "b0001".U)))
  
  // val waymask = Mux(io.out.bits.hit, hitVec, victimWaymask)
  val waymask = Mux(io.out.bits.hit, hitVec, Mux(hasInvalidWay, refillInvalidWaymask, victimWaymask))
180
  assert(!(io.in.valid && PopCount(waymask) > 1.U))
181

182
  io.out.bits.metas := metaWay
183 184
  io.out.bits.hit := io.in.valid && hitVec.orR
  io.out.bits.waymask := waymask
185
  io.out.bits.datas := io.dataReadResp
Z
ZhangZifei 已提交
186
  io.out.bits.mmio := xiangshan.AddressSpace.isMMIO(ZeroExt(req.addr, 40)) // FIXME: isMMIO should have PAddrBits Length ??
187

188 189 190 191 192
  val isForwardData = io.in.valid && (io.dataWriteBus.req match { case r =>
    r.valid && r.bits.setIdx === getDataIdx(req.addr)
  })
  val isForwardDataReg = RegInit(false.B)
  when (isForwardData) { isForwardDataReg := true.B }
193
  when (io.in.fire() || !io.in.valid) { isForwardDataReg := false.B }
194
  val forwardDataReg = RegEnable(io.dataWriteBus.req.bits, isForwardData)
195 196
  io.out.bits.isForwardData := isForwardDataReg || isForwardData
  io.out.bits.forwardData := Mux(isForwardData, io.dataWriteBus.req.bits, forwardDataReg)
197

Z
Zihao Yu 已提交
198
  io.out.bits.req <> req
199
  io.out.valid := io.in.valid
Z
Zihao Yu 已提交
200
  io.in.ready := !io.in.valid || io.out.fire()
Z
nothing  
zhanglinjuan 已提交
201

202 203 204 205
  Debug() {
    if (debug) {
      printf("%d: [" + cacheName + " S2]: isFD:%d isFDreg:%d inFire:%d invalid:%d \n", GTimer(), isForwardData, isForwardDataReg, io.in.fire(), io.in.valid)
    }
Z
nothing  
zhanglinjuan 已提交
206
  }
207 208 209
}

// writeback
210
sealed class CacheStage3(implicit val cacheConfig: CacheConfig) extends CacheModule {
211
  val io = IO(new Bundle {
212
    val in = Flipped(Decoupled(new Stage2IO))
213
    val out = Decoupled(new SimpleBusRespBundle(userBits = userBits))
214
    val isFinish = Output(Bool())
215
    val flush = Input(Bool())
216
    val dataReadBus = CacheDataArrayReadBus()
217
    val dataWriteBus = CacheDataArrayWriteBus()
218
    val metaWriteBus = CacheMetaArrayWriteBus()
219

220
    val mem = new SimpleBusUC
Z
Zihao Yu 已提交
221
    val mmio = new SimpleBusUC
222
    val cohResp = Decoupled(new SimpleBusRespBundle)
Z
Zihao Yu 已提交
223 224

    // use to distinguish prefetch request and normal request
Z
Zihao Yu 已提交
225
    val dataReadRespToL1 = Output(Bool())
226
  })
Z
Zihao Yu 已提交
227

228 229 230
  val metaWriteArb = Module(new Arbiter(CacheMetaArrayWriteBus().req.bits, 2))
  val dataWriteArb = Module(new Arbiter(CacheDataArrayWriteBus().req.bits, 2))

231
  val req = io.in.bits.req
Z
Zihao Yu 已提交
232
  val addr = req.addr.asTypeOf(addrBundle)
Z
Zihao Yu 已提交
233
  val mmio = io.in.valid && io.in.bits.mmio
234 235
  val hit = io.in.valid && io.in.bits.hit
  val miss = io.in.valid && !io.in.bits.hit
236
  val probe = io.in.valid && hasCoh.B && req.isProbe()
Z
Zihao Yu 已提交
237
  val hitReadBurst = hit && req.isReadBurst()
238
  val meta = Mux1H(io.in.bits.waymask, io.in.bits.metas)
Z
Zihao Yu 已提交
239
  assert(!(mmio && hit), "MMIO request should not hit in cache")
240

241 242 243 244 245
  // this is ugly
  if (cacheName == "dcache") {
    BoringUtils.addSource(mmio, "lsuMMIO")
  }

246
  val useForwardData = io.in.bits.isForwardData && io.in.bits.waymask === io.in.bits.forwardData.waymask.getOrElse("b1".U)
247
  val dataReadArray = Mux1H(io.in.bits.waymask, io.in.bits.datas).data
248
  val dataRead = Mux(useForwardData, io.in.bits.forwardData.data.data, dataReadArray)
249
  val wordMask = Mux(!ro.B && req.isWrite(), MaskExpand(req.wmask), 0.U(DataBits.W))
250

Z
Zihao Yu 已提交
251 252 253 254
  val writeL2BeatCnt = Counter(LineBeats)
  when(io.out.fire() && (req.cmd === SimpleBusCmd.writeBurst || req.isWriteLast())) {
    writeL2BeatCnt.inc()
  }
Z
zhanglinjuan 已提交
255

256
  val hitWrite = hit && req.isWrite()
257 258
  val dataHitWriteBus = Wire(CacheDataArrayWriteBus()).apply(
    data = Wire(new DataBundle).apply(MaskData(dataRead, req.wdata, wordMask)),
Z
zhanglinjuan 已提交
259
    valid = hitWrite, setIdx = Cat(addr.index, Mux(req.cmd === SimpleBusCmd.writeBurst || req.isWriteLast(), writeL2BeatCnt.value, addr.wordIndex)), waymask = io.in.bits.waymask)
260 261

  val metaHitWriteBus = Wire(CacheMetaArrayWriteBus()).apply(
262
    valid = hitWrite && !meta.dirty, setIdx = getMetaIdx(req.addr), waymask = io.in.bits.waymask,
263 264
    data = Wire(new MetaBundle).apply(tag = meta.tag, valid = true.B, dirty = (!ro).B)
  )
Z
Zihao Yu 已提交
265

266 267 268
  val s_idle :: s_memReadReq :: s_memReadResp :: s_memWriteReq :: s_memWriteResp :: s_mmioReq :: s_mmioResp :: s_wait_resp :: s_release :: Nil = Enum(9)
  val state = RegInit(s_idle)
  val needFlush = RegInit(false.B)
Z
zhangzifei 已提交
269

270 271 272
  when (io.flush && (state =/= s_idle)) { needFlush := true.B }
  when (io.out.fire() && needFlush) { needFlush := false.B }

273 274
  val readBeatCnt = Counter(LineBeats)
  val writeBeatCnt = Counter(LineBeats)
Z
Zihao Yu 已提交
275 276

  val s2_idle :: s2_dataReadWait :: s2_dataOK :: Nil = Enum(3)
277
  val state2 = RegInit(s2_idle)
Z
zhanglinjuan 已提交
278

279 280 281 282
  io.dataReadBus.apply(valid = (state === s_memWriteReq || state === s_release) && (state2 === s2_idle),
    setIdx = Cat(addr.index, Mux(state === s_release, readBeatCnt.value, writeBeatCnt.value)))
  val dataWay = RegEnable(io.dataReadBus.resp.data, state2 === s2_dataReadWait)
  val dataHitWay = Mux1H(io.in.bits.waymask, dataWay).data
283 284

  switch (state2) {
285 286
    is (s2_idle) { when (io.dataReadBus.req.fire()) { state2 := s2_dataReadWait } }
    is (s2_dataReadWait) { state2 := s2_dataOK }
287
    is (s2_dataOK) { when (io.mem.req.fire() || io.cohResp.fire() || hitReadBurst && io.out.ready) { state2 := s2_idle } }
288 289
  }

290
  // critical word first read
291 292
  val raddr = (if (XLEN == 64) Cat(req.addr(PAddrBits-1,3), 0.U(3.W))
                          else Cat(req.addr(PAddrBits-1,2), 0.U(2.W)))
293
  // dirty block addr
294
  val waddr = Cat(meta.tag, addr.index, 0.U(OffsetBits.W))
295 296 297 298
  val cmd = Mux(state === s_memReadReq, SimpleBusCmd.readBurst,
    Mux((writeBeatCnt.value === (LineBeats - 1).U), SimpleBusCmd.writeLast, SimpleBusCmd.writeBurst))
  io.mem.req.bits.apply(addr = Mux(state === s_memReadReq, raddr, waddr),
    cmd = cmd, size = (if (XLEN == 64) "b11".U else "b10".U),
299
    wdata = dataHitWay, wmask = Fill(DataBytes, 1.U))
Z
Zihao Yu 已提交
300

301
  io.mem.resp.ready := true.B
302
  io.mem.req.valid := (state === s_memReadReq) || ((state === s_memWriteReq) && (state2 === s2_dataOK))
303

Z
Zihao Yu 已提交
304
  // mmio
305
  io.mmio.req.bits := req
Z
Zihao Yu 已提交
306 307 308
  io.mmio.resp.ready := true.B
  io.mmio.req.valid := (state === s_mmioReq)

309 310
  val afterFirstRead = RegInit(false.B)
  val alreadyOutFire = RegEnable(true.B, init = false.B, io.out.fire())
311
  val readingFirst = !afterFirstRead && io.mem.resp.fire() && (state === s_memReadResp)
Z
Zihao Yu 已提交
312 313
  val inRdataRegDemand = RegEnable(Mux(mmio, io.mmio.resp.bits.rdata, io.mem.resp.bits.rdata),
                                   Mux(mmio, state === s_mmioResp, readingFirst))
314

315 316 317 318 319
  // probe
  io.cohResp.valid := ((state === s_idle) && probe) ||
                      ((state === s_release) && (state2 === s2_dataOK))
  io.cohResp.bits.rdata := dataHitWay
  val releaseLast = Counter(state === s_release && io.cohResp.fire(), LineBeats)._2
Z
Zihao Yu 已提交
320
  io.cohResp.bits.cmd := Mux(state === s_release, Mux(releaseLast, SimpleBusCmd.readLast, 0.U),
321
    Mux(hit, SimpleBusCmd.probeHit, SimpleBusCmd.probeMiss))
Z
Zihao Yu 已提交
322 323 324 325

  val respToL1Fire = hitReadBurst && io.out.ready && state2 === s2_dataOK
  val respToL1Last = Counter((state === s_idle || state === s_release && state2 === s2_dataOK) && hitReadBurst && io.out.ready, LineBeats)._2

Z
Zihao Yu 已提交
326
  switch (state) {
327
    is (s_idle) {
328 329
      afterFirstRead := false.B
      alreadyOutFire := false.B
330

331 332 333 334 335
      when (probe) {
        when (io.cohResp.fire()) {
          state := Mux(hit, s_release, s_idle)
          readBeatCnt.value := addr.wordIndex
        }
Z
Zihao Yu 已提交
336 337 338 339
      } .elsewhen (hitReadBurst && io.out.ready) {
        state := s_release
        readBeatCnt.value := Mux(addr.wordIndex === (LineBeats - 1).U, 0.U, (addr.wordIndex + 1.U))
      } .elsewhen ((miss || mmio) && !io.flush) {
Z
Zihao Yu 已提交
340 341
        state := Mux(mmio, s_mmioReq, Mux(!ro.B && meta.dirty, s_memWriteReq, s_memReadReq))
      }
Z
Zihao Yu 已提交
342
    }
Z
Zihao Yu 已提交
343 344 345 346

    is (s_mmioReq) { when (io.mmio.req.fire()) { state := s_mmioResp } }
    is (s_mmioResp) { when (io.mmio.resp.fire()) { state := s_wait_resp } }

347
    is (s_release) {
348 349
      when (io.cohResp.fire() || respToL1Fire) { readBeatCnt.inc() }
      when (probe && io.cohResp.fire() && releaseLast || respToL1Fire && respToL1Last) { state := s_idle }
Z
Zihao Yu 已提交
350
    }
351

352
    is (s_memReadReq) { when (io.mem.req.fire()) {
353 354 355
      state := s_memReadResp
      readBeatCnt.value := addr.wordIndex
    }}
Z
Zihao Yu 已提交
356

357
    is (s_memReadResp) {
358
      when (io.mem.resp.fire()) {
359
        afterFirstRead := true.B
Z
Zihao Yu 已提交
360
        readBeatCnt.inc()
Z
Zihao Yu 已提交
361
        when (req.cmd === SimpleBusCmd.writeBurst) { writeL2BeatCnt.value := 0.U }
362
        when (io.mem.resp.bits.isReadLast()) { state := s_wait_resp }
Z
Zihao Yu 已提交
363
      }
Z
Zihao Yu 已提交
364 365
    }

366
    is (s_memWriteReq) {
367
      when (io.mem.req.fire()) { writeBeatCnt.inc() }
368
      when (io.mem.req.bits.isWriteLast() && io.mem.req.fire()) { state := s_memWriteResp }
Z
Zihao Yu 已提交
369 370
    }

371
    is (s_memWriteResp) { when (io.mem.resp.fire()) { state := s_memReadReq } }
372
    is (s_wait_resp) { when (io.out.fire() || needFlush || alreadyOutFire) { state := s_idle } }
Z
Zihao Yu 已提交
373 374
  }

375 376 377 378
  val dataRefill = MaskData(io.mem.resp.bits.rdata, req.wdata, Mux(readingFirst, wordMask, 0.U(DataBits.W)))
  val dataRefillWriteBus = Wire(CacheDataArrayWriteBus).apply(
    valid = (state === s_memReadResp) && io.mem.resp.fire(), setIdx = Cat(addr.index, readBeatCnt.value),
    data = Wire(new DataBundle).apply(dataRefill), waymask = io.in.bits.waymask)
379

380 381 382
  dataWriteArb.io.in(0) <> dataHitWriteBus.req
  dataWriteArb.io.in(1) <> dataRefillWriteBus.req
  io.dataWriteBus.req <> dataWriteArb.io.out
383

384 385 386
  val metaRefillWriteBus = Wire(CacheMetaArrayWriteBus()).apply(
    valid = (state === s_memReadResp) && io.mem.resp.fire() && io.mem.resp.bits.isReadLast(),
    data = Wire(new MetaBundle).apply(valid = true.B, tag = addr.tag, dirty = !ro.B && req.isWrite()),
387
    setIdx = getMetaIdx(req.addr), waymask = io.in.bits.waymask
388
  )
389

390 391 392
  metaWriteArb.io.in(0) <> metaHitWriteBus.req
  metaWriteArb.io.in(1) <> metaRefillWriteBus.req
  io.metaWriteBus.req <> metaWriteArb.io.out
393

394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
  if (cacheLevel == 2) {
    when ((state === s_memReadResp) && io.mem.resp.fire() && req.isReadBurst()) {
      // readBurst request miss
      io.out.bits.rdata := dataRefill
      io.out.bits.cmd := Mux(io.mem.resp.bits.isReadLast(), SimpleBusCmd.readLast, SimpleBusCmd.readBurst)
    }.elsewhen (req.isWriteLast() || req.cmd === SimpleBusCmd.writeBurst) {
      // writeBurst/writeLast request, no matter hit or miss
      io.out.bits.rdata := Mux(hit, dataRead, inRdataRegDemand)
      io.out.bits.cmd := DontCare
    }.elsewhen (hitReadBurst && state === s_release) {
      // readBurst request hit
      io.out.bits.rdata := dataHitWay
      io.out.bits.cmd := Mux(respToL1Last, SimpleBusCmd.readLast, SimpleBusCmd.readBurst)
    }.otherwise {
      io.out.bits.rdata := Mux(hit, dataRead, inRdataRegDemand)
      io.out.bits.cmd := req.cmd
    }
  } else {
Z
Zihao Yu 已提交
412
    io.out.bits.rdata := Mux(hit, dataRead, inRdataRegDemand)
Z
Zihao Yu 已提交
413
    io.out.bits.cmd := Mux(io.in.bits.req.isRead(), SimpleBusCmd.readLast, Mux(io.in.bits.req.isWrite(), SimpleBusCmd.writeResp, DontCare))//DontCare, added by lemover
Z
Zihao Yu 已提交
414
  }
415
  io.out.bits.user.zip(req.user).map { case (o,i) => o := i }
Z
Zihao Yu 已提交
416

Z
Zihao Yu 已提交
417 418 419 420 421
  io.out.valid := io.in.valid && Mux(req.isBurst() && (cacheLevel == 2).B,
    Mux(req.isWrite() && (hit || !hit && state === s_wait_resp), true.B, (state === s_memReadResp && io.mem.resp.fire() && req.cmd === SimpleBusCmd.readBurst)) || (respToL1Fire && respToL1Last && state === s_release),
    Mux(probe, false.B, Mux(hit, true.B, Mux(req.isWrite() || mmio, state === s_wait_resp, afterFirstRead && !alreadyOutFire)))
  )

422 423 424
  // With critical-word first, the pipeline registers between
  // s2 and s3 can not be overwritten before a missing request
  // is totally handled. We use io.isFinish to indicate when the
Z
Zihao Yu 已提交
425
  // request really ends.
426 427 428
  io.isFinish := Mux(probe, io.cohResp.fire() && Mux(miss, state === s_idle, (state === s_release) && releaseLast),
    Mux(hit || req.isWrite(), io.out.fire(), (state === s_wait_resp) && (io.out.fire() || alreadyOutFire))
  )
429

Z
zhanglinjuan 已提交
430
  io.in.ready := io.out.ready && (state === s_idle && !hitReadBurst) && !miss && !probe
Z
Zihao Yu 已提交
431
  io.dataReadRespToL1 := hitReadBurst && (state === s_idle && io.out.ready || state === s_release && state2 === s2_dataOK)
432

Z
Zihao Yu 已提交
433
  assert(!(metaHitWriteBus.req.valid && metaRefillWriteBus.req.valid))
434
  assert(!(dataHitWriteBus.req.valid && dataRefillWriteBus.req.valid))
435
  assert(!(!ro.B && io.flush), "only allow to flush icache")
436 437
  Debug() {
    if (debug) {
438 439
    printf("%d: [" + cacheName + " S3]: in.ready = %d, in.valid = %d, hit = %x, state = %d, addr = %x cmd:%d probe:%d isFinish:%d\n",
    GTimer(), io.in.ready, io.in.valid, hit, state, req.addr, req.cmd, probe, io.isFinish)
Z
Zihao Yu 已提交
440 441 442 443 444 445
    printf("%d: [" + cacheName + " S3]: out.valid:%d rdata:%x cmd:%d user:%x \n", 
    GTimer(), io.out.valid, io.out.bits.rdata, io.out.bits.cmd, io.out.bits.user.getOrElse(0.U))
    printf("%d: [" + cacheName + " S3]: DHW: (%d, %d), data:%x MHW:(%d, %d)\n", 
    GTimer(), dataHitWriteBus.req.valid, dataHitWriteBus.req.ready, dataHitWriteBus.req.bits.data.asUInt, metaHitWriteBus.req.valid, metaHitWriteBus.req.ready)
    printf("%d: [" + cacheName + " S3]: useFD:%d isFD:%d FD:%x DreadArray:%x dataRead:%x inwaymask:%x FDwaymask:%x \n", 
    GTimer(), useForwardData, io.in.bits.isForwardData, io.in.bits.forwardData.data.data, dataReadArray, dataRead, io.in.bits.waymask, io.in.bits.forwardData.waymask.getOrElse("b1".U))
446
    }
447 448 449
  }
}

450
class Cache(implicit val cacheConfig: CacheConfig) extends CacheModule {
451
  val io = IO(new Bundle {
452
    val in = Flipped(new SimpleBusUC(userBits = userBits))
453
    val flush = Input(UInt(2.W))
454
    val out = new SimpleBusC
Z
Zihao Yu 已提交
455
    val mmio = new SimpleBusUC
456
    val empty = Output(Bool())
457 458
  })

459
  // cpu pipeline
460 461 462
  val s1 = Module(new CacheStage1)
  val s2 = Module(new CacheStage2)
  val s3 = Module(new CacheStage3)
463
  val metaArray = Module(new SRAMTemplateWithArbiter(nRead = 1, new MetaBundle, set = Sets, way = Ways, shouldReset = true))
464
  val dataArray = Module(new SRAMTemplateWithArbiter(nRead = 2, new DataBundle, set = Sets * LineBeats, way = Ways))
465

466
  if (cacheName == "icache") {
Z
Zihao Yu 已提交
467 468 469 470 471 472
    // flush icache when executing fence.i
    val flushICache = WireInit(false.B)
    BoringUtils.addSink(flushICache, "MOUFlushICache")
    metaArray.reset := reset.asBool || flushICache
  }

473 474 475 476
  val arb = Module(new Arbiter(new SimpleBusReqBundle(userBits = userBits), hasCohInt + 1))
  arb.io.in(hasCohInt + 0) <> io.in.req

  s1.io.in <> arb.io.out
477 478 479 480 481
  /*
  val s2BlockByPrefetch = if (cacheLevel == 2) {
      s2.io.out.valid && s3.io.in.valid && s3.io.in.bits.req.isPrefetch() && !s3.io.in.ready
    } else { false.B }
  */
482
  PipelineConnect(s1.io.out, s2.io.in, s2.io.out.fire(), io.flush(0))
483
  PipelineConnect(s2.io.out, s3.io.in, s3.io.isFinish, io.flush(1) || s2.io.out.bits.mmio && s2.io.out.bits.req.isPrefetch()/* || s2BlockByPrefetch*/)
484
  io.in.resp <> s3.io.out
485
  s3.io.flush := io.flush(1)
486
  io.out.mem <> s3.io.mem
Z
Zihao Yu 已提交
487
  io.mmio <> s3.io.mmio
488
  io.empty := !s2.io.in.valid && !s3.io.in.valid
489
  s1.io.s2s3Empty := io.empty // FIXME: remove me when do not use nut's cache
490

Z
zhanglinjuan 已提交
491
  io.in.resp.valid := Mux(s3.io.out.valid && s3.io.out.bits.isPrefetch(), false.B, s3.io.out.valid || s3.io.dataReadRespToL1)
492

493
  if (hasCoh) {
494 495 496 497 498 499 500 501
    val cohReq = io.out.coh.req.bits
    // coh does not have user signal, any better code?
    val coh = Wire(new SimpleBusReqBundle(userBits = userBits))
    coh.apply(addr = cohReq.addr, cmd = cohReq.cmd, size = cohReq.cmd, wdata = cohReq.wdata, wmask = cohReq.wmask)
    arb.io.in(0).bits := coh
    arb.io.in(0).valid := io.out.coh.req.valid
    io.out.coh.req.ready := arb.io.in(0).ready
    io.out.coh.resp <> s3.io.cohResp
502 503 504 505
  } else {
    io.out.coh.req.ready := true.B
    io.out.coh.resp := DontCare
    io.out.coh.resp.valid := false.B
506
    s3.io.cohResp.ready := true.B
507
  }
508

509
  metaArray.io.r(0) <> s1.io.metaReadBus
510 511
  dataArray.io.r(0) <> s1.io.dataReadBus
  dataArray.io.r(1) <> s3.io.dataReadBus
512

513 514
  metaArray.io.w <> s3.io.metaWriteBus
  dataArray.io.w <> s3.io.dataWriteBus
515

516
  s2.io.metaReadResp := s1.io.metaReadBus.resp.data
517
  s2.io.dataReadResp := s1.io.dataReadBus.resp.data
518 519
  s2.io.dataWriteBus := s3.io.dataWriteBus
  s2.io.metaWriteBus := s3.io.metaWriteBus
520

521
  BoringUtils.addSource(s3.io.in.valid && s3.io.in.bits.hit, "perfCntCondM" + cacheName + "Hit")
522

523 524
  Debug() {
    if (debug) {
525
    when(true.B) {
526
      io.in.dump(cacheName + ".in")
527
      printf("%d:" + cacheName + "InReq(%d, %d) InResp(%d, %d) \n", GTimer(), io.in.req.valid, io.in.req.ready, io.in.resp.valid, io.in.resp.ready)
528 529
      printf("%d:" + cacheName + " {IN s1:(%d,%d), s2:(%d,%d), s3:(%d,%d)} {OUT s1:(%d,%d), s2:(%d,%d), s3:(%d,%d)}\n",
        GTimer(), s1.io.in.valid, s1.io.in.ready, s2.io.in.valid, s2.io.in.ready, s3.io.in.valid, s3.io.in.ready, s1.io.out.valid, s1.io.out.ready, s2.io.out.valid, s2.io.out.ready, s3.io.out.valid, s3.io.out.ready)
530 531 532
      when (s1.io.in.valid) { printf("%d ", GTimer()) ; printf(p"[${cacheName}.S1]: ${s1.io.in.bits}\n") }
      when (s2.io.in.valid) { printf("%d ", GTimer()) ; printf(p"[${cacheName}.S2]: ${s2.io.in.bits.req}\n") }
      when (s3.io.in.valid) { printf("%d ", GTimer()) ; printf(p"[${cacheName}.S3]: ${s3.io.in.bits.req}\n") }
533
      // s3.io.mem.dump(cacheName + ".mem")
534
    }}
Z
Zihao Yu 已提交
535 536
  }
}
Z
Zihao Yu 已提交
537 538

object Cache {
Z
Zihao Yu 已提交
539
  def apply(in: SimpleBusUC, mmio: Seq[SimpleBusUC], flush: UInt, empty: Bool, enable: Boolean = true)(implicit cacheConfig: CacheConfig) = {
Z
Zihao Yu 已提交
540 541
    if (enable) {
      val cache = Module(new Cache)
Z
Zihao Yu 已提交
542
      cache.io.flush := flush
Z
Zihao Yu 已提交
543
      cache.io.in <> in
544
      mmio(0) <> cache.io.mmio
545
      empty := cache.io.empty
Z
Zihao Yu 已提交
546 547
      cache.io.out
    } else {
548
      assert(false, "XiangShan should not reach here!")
Z
Zihao Yu 已提交
549 550 551
      val addrspace = List(AddressSpace.dram) ++ AddressSpace.mmio
      val xbar = Module(new SimpleBusCrossbar1toN(addrspace))
      val busC = WireInit(0.U.asTypeOf(new SimpleBusC))
Z
Zihao Yu 已提交
552
      busC.mem <> xbar.io.out(0)
Z
Zihao Yu 已提交
553
      xbar.io.in <> in
554 555 556
      (mmio zip xbar.io.out.drop(1)) foreach { case (mmio_in, xbar_out) =>
        mmio_in <> xbar_out
      }
557
      empty := false.B
Z
Zihao Yu 已提交
558 559
      busC
    }
Z
Zihao Yu 已提交
560 561
  }
}