DCache.scala 14.4 KB
Newer Older
Y
Yinan Xu 已提交
1
package xiangshan.cache
2 3 4

import chisel3._
import chisel3.util._
L
linjiawei 已提交
5
import freechips.rocketchip.tilelink.{ClientMetadata, TLClientParameters, TLEdgeOut}
6 7
import system.L1CacheErrorInfo
import utils.{Code, ParallelOR, ReplacementPolicy, SRAMTemplate, XSDebug}
8

9
import scala.math.max
A
Allen 已提交
10

11

12 13 14
// DCache specific parameters
// L1 DCache is 64set, 8way-associative, with 64byte block, a total of 32KB
// It's a virtually indexed, physically tagged cache.
L
linjiawei 已提交
15 16
case class DCacheParameters
(
L
ljw 已提交
17 18 19 20 21 22 23 24 25 26 27 28 29 30
  nSets: Int = 64,
  nWays: Int = 8,
  rowBits: Int = 128,
  nTLBEntries: Int = 32,
  tagECC: Option[String] = None,
  dataECC: Option[String] = None,
  replacer: Option[String] = Some("random"),
  nMissEntries: Int = 1,
  nProbeEntries: Int = 1,
  nReleaseEntries: Int = 1,
  nStoreReplayEntries: Int = 1,
  nMMIOEntries: Int = 1,
  nMMIOs: Int = 1,
  blockBytes: Int = 64
L
linjiawei 已提交
31
) extends L1CacheParameters {
32

33
  def tagCode: Code = Code.fromString(tagECC)
L
ljw 已提交
34

35 36 37 38 39 40 41
  def dataCode: Code = Code.fromString(dataECC)
}

trait HasDCacheParameters extends HasL1CacheParameters {
  val cacheParams = dcacheParameters
  val cfg = cacheParams

A
Allen 已提交
42
  def encWordBits = cacheParams.dataCode.width(wordBits)
L
ljw 已提交
43 44 45

  def encRowBits = encWordBits * rowWords

46 47 48 49
  def lrscCycles = LRSCCycles // ISA requires 16-insn LRSC sequences to succeed
  def lrscBackoff = 3 // disallow LRSC reacquisition briefly
  def blockProbeAfterGrantCycles = 8 // give the processor some time to issue a request after a grant
  def nIOMSHRs = cacheParams.nMMIOs
L
ljw 已提交
50

51 52
  def maxUncachedInFlight = cacheParams.nMMIOs

A
Allen 已提交
53
  def nSourceType = 3
L
ljw 已提交
54

A
Allen 已提交
55
  def sourceTypeWidth = log2Up(nSourceType)
L
ljw 已提交
56

A
Allen 已提交
57
  def LOAD_SOURCE = 0
L
ljw 已提交
58

A
Allen 已提交
59
  def STORE_SOURCE = 1
L
ljw 已提交
60

A
Allen 已提交
61
  def AMO_SOURCE = 2
L
ljw 已提交
62

A
Allen 已提交
63
  // each source use a id to distinguish its multiple reqs
A
Allen 已提交
64
  def reqIdWidth = 64
65

66
  require(isPow2(nSets), s"nSets($nSets) must be pow2")
A
Allen 已提交
67 68 69 70
  require(isPow2(nWays), s"nWays($nWays) must be pow2")
  require(full_divide(rowBits, wordBits), s"rowBits($rowBits) must be multiple of wordBits($wordBits)")
  require(full_divide(beatBits, rowBits), s"beatBits($beatBits) must be multiple of rowBits($rowBits)")
  // this is a VIPT L1 cache
71
  require(pgIdxBits >= untagBits, s"page aliasing problem: pgIdxBits($pgIdxBits) < untagBits($untagBits)")
72
  // require(rowWords == 1, "Our DCache Implementation assumes rowWords == 1")
73 74
}

A
Allen 已提交
75
abstract class DCacheModule extends L1CacheModule
76 77
  with HasDCacheParameters

A
Allen 已提交
78
abstract class DCacheBundle extends L1CacheBundle
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
  with HasDCacheParameters

// basic building blocks for L1 DCache
class L1Metadata extends DCacheBundle {
  val coh = new ClientMetadata
  val tag = UInt(tagBits.W)
}

object L1Metadata {
  def apply(tag: Bits, coh: ClientMetadata) = {
    val meta = Wire(new L1Metadata)
    meta.tag := tag
    meta.coh := coh
    meta
  }
}

class L1MetaReadReq extends DCacheBundle {
L
ljw 已提交
97
  val idx = UInt(idxBits.W)
98
  val way_en = UInt(nWays.W)
L
ljw 已提交
99
  val tag = UInt(tagBits.W)
100 101 102 103 104 105 106
}

class L1MetaWriteReq extends L1MetaReadReq {
  val data = new L1Metadata
}

class L1DataReadReq extends DCacheBundle {
A
Allen 已提交
107
  // you can choose which bank to read to save power
L
ljw 已提交
108
  val rmask = Bits(blockRows.W)
109
  val way_en = Bits(nWays.W)
L
ljw 已提交
110
  val addr = Bits(untagBits.W)
111 112
}

A
Allen 已提交
113
// Now, we can write a cache-block in a single cycle
114
class L1DataWriteReq extends L1DataReadReq {
L
ljw 已提交
115 116
  val wmask = Bits(blockRows.W)
  val data = Vec(blockRows, Bits(rowBits.W))
117
}
118

119 120 121 122 123
class ReplacementAccessBundle extends DCacheBundle {
  val set = UInt(log2Up(nSets).W)
  val way = UInt(log2Up(nWays).W)
}

124
abstract class AbstractDataArray extends DCacheModule {
125
  val io = IO(new DCacheBundle {
L
ljw 已提交
126
    val read = Vec(LoadPipelineWidth, Flipped(DecoupledIO(new L1DataReadReq)))
127
    val write = Flipped(DecoupledIO(new L1DataWriteReq))
128
    val resp = Output(Vec(LoadPipelineWidth, Vec(blockRows, Bits(encRowBits.W))))
129
    val nacks = Output(Vec(LoadPipelineWidth, Bool()))
130
    val errors = Output(Vec(LoadPipelineWidth, new L1CacheErrorInfo))
131 132 133 134 135 136
  })

  def pipeMap[T <: Data](f: Int => T) = VecInit((0 until LoadPipelineWidth).map(f))

  def dumpRead() = {
    (0 until LoadPipelineWidth) map { w =>
L
ljw 已提交
137
      when(io.read(w).valid) {
138 139 140 141 142 143 144
        XSDebug(s"DataArray Read channel: $w valid way_en: %x addr: %x\n",
          io.read(w).bits.way_en, io.read(w).bits.addr)
      }
    }
  }

  def dumpWrite() = {
L
ljw 已提交
145
    when(io.write.valid) {
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
      XSDebug(s"DataArray Write valid way_en: %x addr: %x\n",
        io.write.bits.way_en, io.write.bits.addr)

      (0 until blockRows) map { r =>
        XSDebug(s"cycle: $r data: %x wmask: %x\n",
          io.write.bits.data(r), io.write.bits.wmask(r))
      }
    }
  }

  def dumpResp() = {
    (0 until LoadPipelineWidth) map { w =>
      XSDebug(s"DataArray ReadResp channel: $w\n")
      (0 until blockRows) map { r =>
        XSDebug(s"cycle: $r data: %x\n", io.resp(w)(r))
      }
    }
  }

  def dumpNack() = {
    (0 until LoadPipelineWidth) map { w =>
L
ljw 已提交
167
      when(io.nacks(w)) {
168 169 170 171 172 173 174 175 176 177 178 179 180
        XSDebug(s"DataArray NACK channel: $w\n")
      }
    }
  }

  def dump() = {
    dumpRead
    dumpWrite
    dumpNack
    dumpResp
  }
}

181
class DuplicatedDataArray extends AbstractDataArray {
182
  val singlePort = true
183
  val readHighPriority = false
L
ljw 已提交
184

185 186 187 188 189 190 191 192 193 194 195 196 197 198
  def eccBits = encWordBits - wordBits

  def getECCFromEncWord(encWord: UInt) = {
    require(encWord.getWidth == encWordBits)
    encWord(encWordBits - 1, wordBits)
  }

  def getECCFromRow(row: UInt) = {
    require(row.getWidth == rowBits)
    VecInit((0 until rowWords).map { w =>
      val word = row(wordBits * (w + 1) - 1, wordBits * w)
      getECCFromEncWord(cacheParams.dataCode.encode(word))
    })
  }
L
ljw 已提交
199

200
  val waddr = (io.write.bits.addr >> blockOffBits).asUInt()
201
  val raddrs = io.read.map(r => (r.bits.addr >> blockOffBits).asUInt)
202
  io.write.ready := (if (readHighPriority) {
203
    if (singlePort) {
204
      !VecInit(io.read.map(_.valid)).asUInt.orR
205
    } else {
206
      !(Cat(io.read.zipWithIndex.map { case (r, i) => r.valid && raddrs(i) === waddr }).orR)
207 208 209
    }
  } else {
    true.B
210
  })
211

L
ljw 已提交
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
  // wrap a data row and a ecc row
  class DataSRAMGroup extends Module {
    val io = IO(new Bundle() {
      val wen, ren = Input(Bool())
      val waddr, raddr = Input(UInt())
      val wdata = Input(UInt(rowBits.W))
      val w_way_en, r_way_en = Input(UInt(nWays.W))
      val rdata = Output(UInt())
    })

    val r_way_en_reg = RegNext(io.r_way_en)
    val data_array = Array.fill(nWays) {
      Module(new SRAMTemplate(
        Bits(rowBits.W),
        set = nSets,
        way = 1,
        shouldReset = false,
        holdRead = false,
        singlePort = singlePort
      ))
    }

    for (w <- 0 until nWays) {
      val wen = io.wen && io.w_way_en(w)
      data_array(w).io.w.req.valid := wen
      data_array(w).io.w.req.bits.apply(
        setIdx = io.waddr,
        data = io.wdata,
        waymask = 1.U
      )
      data_array(w).io.r.req.valid := io.ren
      data_array(w).io.r.req.bits.apply(setIdx = io.raddr)
    }

    val half = nWays / 2
    val data_read = data_array.map(_.io.r.resp.data(0))
    val data_left = Mux1H(r_way_en_reg.tail(half), data_read.take(half))
    val data_right = Mux1H(r_way_en_reg.head(half), data_read.drop(half))

    val sel_low = r_way_en_reg.tail(half).orR()
    val row_data = Mux(sel_low, data_left, data_right)

    io.rdata := row_data
  }

257
  for (j <- 0 until LoadPipelineWidth) {
258
    val raddr = raddrs(j)
259
    val rmask = io.read(j).bits.rmask
260 261 262

    // for single port SRAM, do not allow read and write in the same cycle
    // for dual port SRAM, raddr === waddr is undefined behavior
L
ljw 已提交
263
    val rwhazard = if (singlePort) io.write.valid else io.write.valid && waddr === raddr
264
    io.read(j).ready := (if (readHighPriority) true.B else !rwhazard)
265

266 267 268 269
    // use way_en to select a way after data read out
    assert(!(RegNext(io.read(j).fire() && PopCount(io.read(j).bits.way_en) > 1.U)))
    val way_en = RegNext(io.read(j).bits.way_en)

270
    val row_error = Wire(Vec(blockRows, Vec(rowWords, Bool())))
271
    for (r <- 0 until blockRows) {
272 273 274 275 276 277 278 279 280 281 282 283 284 285
      val ecc_array = Module(new SRAMTemplate(
        Vec(rowWords, Bits(eccBits.W)),
        set = nSets,
        way = nWays,
        shouldReset = false,
        holdRead = false,
        singlePort = singlePort
      ))
      ecc_array.io.w.req.valid := io.write.valid && io.write.bits.wmask(r)
      ecc_array.io.w.req.bits.apply(
        setIdx = waddr,
        data = getECCFromRow(io.write.bits.data(r)),
        waymask = io.write.bits.way_en
      )
L
ljw 已提交
286
      when(ecc_array.io.w.req.valid) {
287 288
        XSDebug(p"write in ecc sram ${j.U} row ${r.U}: setIdx=${Hexadecimal(ecc_array.io.w.req.bits.setIdx)} ecc(0)=${Hexadecimal(getECCFromRow(io.write.bits.data(r))(0))} ecc(1)=${Hexadecimal(getECCFromRow(io.write.bits.data(r))(1))} waymask=${Hexadecimal(io.write.bits.way_en)}\n")
      }
289 290
      ecc_array.io.r.req.valid := io.read(j).valid && rmask(r)
      ecc_array.io.r.req.bits.apply(setIdx = raddr)
291

L
ljw 已提交
292 293 294 295 296 297 298 299
      val dataGroup = Module(new DataSRAMGroup)
      dataGroup.io.wen := io.write.valid && io.write.bits.wmask(r)
      dataGroup.io.w_way_en := io.write.bits.way_en
      dataGroup.io.waddr := waddr
      dataGroup.io.wdata := io.write.bits.data(r)
      dataGroup.io.ren := io.read(j).valid && io.read(j).bits.rmask(r)
      dataGroup.io.r_way_en := io.read(j).bits.way_en
      dataGroup.io.raddr := raddr
300

L
ljw 已提交
301 302 303 304 305
      val ecc_resp = Wire(Vec(rowWords, Vec(nWays, Bits(eccBits.W))))
      for(w <- 0 until nWays){
        for(k <- 0 until rowWords){
          ecc_resp(k)(w) := ecc_array.io.r.resp.data(w)(k)
        }
306
      }
L
ljw 已提交
307 308 309
      val ecc_resp_chosen = Wire(Vec(rowWords, Bits(eccBits.W)))
      val data_resp_chosen = Wire(Vec(rowWords, Bits(wordBits.W)))
      data_resp_chosen := dataGroup.io.rdata.asTypeOf(data_resp_chosen)
310 311
      for (k <- 0 until rowWords) {
        ecc_resp_chosen(k) := Mux1H(way_en, ecc_resp(k))
312
      }
L
ljw 已提交
313
      io.resp(j)(r) := Cat((0 until rowWords) reverseMap {
314 315 316 317 318
        k => {
          val data = Cat(ecc_resp_chosen(k), data_resp_chosen(k))
          row_error(r)(k) := dcacheParameters.dataCode.decode(data).error && RegNext(rmask(r))
          data
        }
L
ljw 已提交
319
      })
320 321 322 323
      io.errors(j).ecc_error.valid := RegNext(io.read(j).fire()) && Cat(row_error.flatten).orR()
      io.errors(j).ecc_error.bits := true.B
      io.errors(j).paddr.valid := io.errors(j).ecc_error.valid
      io.errors(j).paddr.bits := RegNext(io.read(j).bits.addr)
324
    }
325

326 327 328 329
    io.nacks(j) := false.B
  }
}

330
class L1MetadataArray(onReset: () => L1Metadata) extends DCacheModule {
A
Allen 已提交
331
  val rstVal = onReset()
332 333 334
  val metaBits = rstVal.getWidth
  val encMetaBits = cacheParams.tagCode.width(metaBits)

A
Allen 已提交
335 336 337
  val io = IO(new Bundle {
    val read = Flipped(Decoupled(new L1MetaReadReq))
    val write = Flipped(Decoupled(new L1MetaWriteReq))
338
    val resp = Output(Vec(nWays, UInt(encMetaBits.W)))
339
    val error = Output(new L1CacheErrorInfo)
A
Allen 已提交
340
  })
L
ljw 已提交
341
  val rst_cnt = RegInit(0.U(log2Up(nSets + 1).W))
A
Allen 已提交
342 343 344 345 346
  val rst = rst_cnt < nSets.U
  val waddr = Mux(rst, rst_cnt, io.write.bits.idx)
  val wdata = Mux(rst, rstVal, io.write.bits.data).asUInt
  val wmask = Mux(rst || (nWays == 1).B, (-1).asSInt, io.write.bits.way_en.asSInt).asBools
  val rmask = Mux(rst || (nWays == 1).B, (-1).asSInt, io.read.bits.way_en.asSInt).asBools
L
ljw 已提交
347 348 349
  when(rst) {
    rst_cnt := rst_cnt + 1.U
  }
A
Allen 已提交
350

L
ljw 已提交
351 352
  val tag_array = Module(new SRAMTemplate(UInt(encMetaBits.W), set = nSets, way = nWays,
    shouldReset = false, holdRead = false, singlePort = true))
353 354

  // tag write
355
  val wen = rst || io.write.valid
356 357
  tag_array.io.w.req.valid := wen
  tag_array.io.w.req.bits.apply(
L
ljw 已提交
358 359 360
    setIdx = waddr,
    data = cacheParams.tagCode.encode(wdata),
    waymask = VecInit(wmask).asUInt)
361 362

  // tag read
363 364
  val ren = io.read.fire()
  tag_array.io.r.req.valid := ren
L
ljw 已提交
365
  tag_array.io.r.req.bits.apply(setIdx = io.read.bits.idx)
366
  io.resp := tag_array.io.r.resp.data
367 368 369 370 371 372 373
  val ecc_errors = tag_array.io.r.resp.data.zipWithIndex.map({ case (d, w) =>
    cacheParams.tagCode.decode(d).error && RegNext(io.read.bits.way_en(w))
  })
  io.error.ecc_error.valid := RegNext(io.read.fire()) && Cat(ecc_errors).orR()
  io.error.ecc_error.bits := true.B
  io.error.paddr.valid := io.error.ecc_error.valid
  io.error.paddr.bits := Cat(io.read.bits.idx, 0.U(pgUntagBits.W))
A
Allen 已提交
374

375 376
  io.write.ready := !rst
  io.read.ready := !wen
A
Allen 已提交
377 378

  def dumpRead() = {
L
ljw 已提交
379
    when(io.read.fire()) {
A
Allen 已提交
380 381 382 383 384 385
      XSDebug("MetaArray Read: idx: %d way_en: %x tag: %x\n",
        io.read.bits.idx, io.read.bits.way_en, io.read.bits.tag)
    }
  }

  def dumpWrite() = {
L
ljw 已提交
386
    when(io.write.fire()) {
A
Allen 已提交
387 388 389 390 391
      XSDebug("MetaArray Write: idx: %d way_en: %x tag: %x new_tag: %x new_coh: %x\n",
        io.write.bits.idx, io.write.bits.way_en, io.write.bits.tag, io.write.bits.data.tag, io.write.bits.data.coh.state)
    }
  }

392 393 394 395 396 397
  // def dumpResp() = {
  //   (0 until nWays) map { i =>
  //     XSDebug(s"MetaArray Resp: way: $i tag: %x coh: %x\n",
  //       io.resp(i).tag, io.resp(i).coh.state)
  //   }
  // }
A
Allen 已提交
398 399 400 401

  def dump() = {
    dumpRead
    dumpWrite
402
    // dumpResp
A
Allen 已提交
403 404 405 406
  }
}

class DuplicatedMetaArray extends DCacheModule {
407
  def onReset = L1Metadata(0.U, ClientMetadata.onReset)
L
ljw 已提交
408

409 410 411
  val metaBits = onReset.getWidth
  val encMetaBits = cacheParams.tagCode.width(metaBits)

A
Allen 已提交
412
  val io = IO(new DCacheBundle {
L
ljw 已提交
413
    val read = Vec(LoadPipelineWidth, Flipped(DecoupledIO(new L1MetaReadReq)))
A
Allen 已提交
414
    val write = Flipped(DecoupledIO(new L1MetaWriteReq))
L
ljw 已提交
415
    val resp = Output(Vec(LoadPipelineWidth, Vec(nWays, UInt(encMetaBits.W))))
416
    val errors = Output(Vec(LoadPipelineWidth, new L1CacheErrorInfo))
A
Allen 已提交
417
  })
L
ljw 已提交
418 419 420
  val meta = Seq.fill(LoadPipelineWidth) {
    Module(new L1MetadataArray(onReset _))
  }
A
Allen 已提交
421

422
  for (w <- 0 until LoadPipelineWidth) {
423 424 425
    // meta(w).io.write <> io.write
    meta(w).io.write.valid := io.write.valid
    meta(w).io.write.bits := io.write.bits
L
ljw 已提交
426
    meta(w).io.read <> io.read(w)
427
    io.resp(w) <> meta(w).io.resp
428
    io.errors(w) <> meta(w).io.error
A
Allen 已提交
429
  }
430 431
  // io.write.ready := VecInit(meta.map(_.io.write.ready)).asUInt.andR
  io.write.ready := true.B
A
Allen 已提交
432

433
  def dumpRead() = {
434
    (0 until LoadPipelineWidth) map { w =>
L
ljw 已提交
435
      when(io.read(w).fire()) {
436
        XSDebug(s"MetaArray Read channel: $w idx: %d way_en: %x tag: %x\n",
437 438 439 440 441 442
          io.read(w).bits.idx, io.read(w).bits.way_en, io.read(w).bits.tag)
      }
    }
  }

  def dumpWrite() = {
L
ljw 已提交
443
    when(io.write.fire()) {
444 445
      XSDebug("MetaArray Write: idx: %d way_en: %x tag: %x new_tag: %x new_coh: %x\n",
        io.write.bits.idx, io.write.bits.way_en, io.write.bits.tag, io.write.bits.data.tag, io.write.bits.data.coh.state)
A
Allen 已提交
446 447
    }
  }
448

449 450 451 452 453 454 455 456
  // def dumpResp() = {
  //   (0 until LoadPipelineWidth) map { w =>
  //     (0 until nWays) map { i =>
  //       XSDebug(s"MetaArray Resp: channel: $w way: $i tag: %x coh: %x\n",
  //         io.resp(w)(i).tag, io.resp(w)(i).coh.state)
  //     }
  //   }
  // }
457 458 459 460

  def dump() = {
    dumpRead
    dumpWrite
461
    // dumpResp
462
  }
A
Allen 已提交
463
}