DCache.scala 15.5 KB
Newer Older
L
Lemover 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/***************************************************************************************
* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
*
* XiangShan is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*          http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
***************************************************************************************/

Y
Yinan Xu 已提交
16
package xiangshan.cache
17

18
import chipsalliance.rocketchip.config.Parameters
19 20
import chisel3._
import chisel3.util._
L
linjiawei 已提交
21
import freechips.rocketchip.tilelink.{ClientMetadata, TLClientParameters, TLEdgeOut}
22 23
import system.L1CacheErrorInfo
import utils.{Code, ParallelOR, ReplacementPolicy, SRAMTemplate, XSDebug}
24

25
import scala.math.max
A
Allen 已提交
26

27

28 29 30
// 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 已提交
31 32
case class DCacheParameters
(
L
ljw 已提交
33 34 35 36 37 38 39 40 41 42 43 44 45 46
  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 已提交
47
) extends L1CacheParameters {
48

49
  def tagCode: Code = Code.fromString(tagECC)
L
ljw 已提交
50

51 52 53 54 55 56 57
  def dataCode: Code = Code.fromString(dataECC)
}

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

A
Allen 已提交
58
  def encWordBits = cacheParams.dataCode.width(wordBits)
L
ljw 已提交
59 60 61

  def encRowBits = encWordBits * rowWords

62 63 64 65
  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 已提交
66

67 68
  def maxUncachedInFlight = cacheParams.nMMIOs

A
Allen 已提交
69
  def nSourceType = 3
L
ljw 已提交
70

A
Allen 已提交
71
  def sourceTypeWidth = log2Up(nSourceType)
L
ljw 已提交
72

A
Allen 已提交
73
  def LOAD_SOURCE = 0
L
ljw 已提交
74

A
Allen 已提交
75
  def STORE_SOURCE = 1
L
ljw 已提交
76

A
Allen 已提交
77
  def AMO_SOURCE = 2
L
ljw 已提交
78

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

82
  require(isPow2(nSets), s"nSets($nSets) must be pow2")
A
Allen 已提交
83 84 85 86
  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
87
  require(pgIdxBits >= untagBits, s"page aliasing problem: pgIdxBits($pgIdxBits) < untagBits($untagBits)")
88
  // require(rowWords == 1, "Our DCache Implementation assumes rowWords == 1")
89 90
}

91
abstract class DCacheModule(implicit p: Parameters) extends L1CacheModule
92 93
  with HasDCacheParameters

94
abstract class DCacheBundle(implicit p: Parameters) extends L1CacheBundle
95 96 97
  with HasDCacheParameters

// basic building blocks for L1 DCache
98
class L1Metadata(implicit p: Parameters) extends DCacheBundle {
99 100 101 102 103
  val coh = new ClientMetadata
  val tag = UInt(tagBits.W)
}

object L1Metadata {
104
  def apply(tag: Bits, coh: ClientMetadata)(implicit p: Parameters) = {
105 106 107 108 109 110 111
    val meta = Wire(new L1Metadata)
    meta.tag := tag
    meta.coh := coh
    meta
  }
}

112
class L1MetaReadReq(implicit p: Parameters) extends DCacheBundle {
L
ljw 已提交
113
  val idx = UInt(idxBits.W)
114
  val way_en = UInt(nWays.W)
L
ljw 已提交
115
  val tag = UInt(tagBits.W)
116 117
}

118
class L1MetaWriteReq(implicit p: Parameters) extends L1MetaReadReq {
119 120 121
  val data = new L1Metadata
}

122
class L1DataReadReq(implicit p: Parameters) extends DCacheBundle {
A
Allen 已提交
123
  // you can choose which bank to read to save power
L
ljw 已提交
124
  val rmask = Bits(blockRows.W)
125
  val way_en = Bits(nWays.W)
L
ljw 已提交
126
  val addr = Bits(untagBits.W)
127 128
}

A
Allen 已提交
129
// Now, we can write a cache-block in a single cycle
130
class L1DataWriteReq(implicit p: Parameters) extends L1DataReadReq {
L
ljw 已提交
131 132
  val wmask = Bits(blockRows.W)
  val data = Vec(blockRows, Bits(rowBits.W))
133
}
134

135
class ReplacementAccessBundle(implicit p: Parameters) extends DCacheBundle {
136 137 138 139
  val set = UInt(log2Up(nSets).W)
  val way = UInt(log2Up(nWays).W)
}

140
abstract class AbstractDataArray(implicit p: Parameters) extends DCacheModule {
141
  val io = IO(new DCacheBundle {
L
ljw 已提交
142
    val read = Vec(LoadPipelineWidth, Flipped(DecoupledIO(new L1DataReadReq)))
143
    val write = Flipped(DecoupledIO(new L1DataWriteReq))
144
    val resp = Output(Vec(LoadPipelineWidth, Vec(blockRows, Bits(encRowBits.W))))
145
    val nacks = Output(Vec(LoadPipelineWidth, Bool()))
146
    val errors = Output(Vec(LoadPipelineWidth, new L1CacheErrorInfo))
147 148 149 150 151 152
  })

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

  def dumpRead() = {
    (0 until LoadPipelineWidth) map { w =>
L
ljw 已提交
153
      when(io.read(w).valid) {
154 155 156 157 158 159 160
        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 已提交
161
    when(io.write.valid) {
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
      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 已提交
183
      when(io.nacks(w)) {
184 185 186 187 188 189 190 191 192 193 194 195 196
        XSDebug(s"DataArray NACK channel: $w\n")
      }
    }
  }

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

197
class DuplicatedDataArray(implicit p: Parameters) extends AbstractDataArray {
198
  val singlePort = true
199
  val readHighPriority = false
L
ljw 已提交
200

201 202 203 204 205 206 207 208 209 210 211 212 213 214
  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 已提交
215

216
  val waddr = (io.write.bits.addr >> blockOffBits).asUInt()
217
  val raddrs = io.read.map(r => (r.bits.addr >> blockOffBits).asUInt)
218
  io.write.ready := (if (readHighPriority) {
219
    if (singlePort) {
220
      !VecInit(io.read.map(_.valid)).asUInt.orR
221
    } else {
222
      !(Cat(io.read.zipWithIndex.map { case (r, i) => r.valid && raddrs(i) === waddr }).orR)
223 224 225
    }
  } else {
    true.B
226
  })
227

L
ljw 已提交
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 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
  // 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
  }

273
  for (j <- 0 until LoadPipelineWidth) {
274
    val raddr = raddrs(j)
275
    val rmask = io.read(j).bits.rmask
276 277 278

    // 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 已提交
279
    val rwhazard = if (singlePort) io.write.valid else io.write.valid && waddr === raddr
280
    io.read(j).ready := (if (readHighPriority) true.B else !rwhazard)
281

282 283 284 285
    // 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)

286
    val row_error = Wire(Vec(blockRows, Vec(rowWords, Bool())))
287
    for (r <- 0 until blockRows) {
288 289 290 291 292 293 294 295 296 297 298 299 300 301
      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 已提交
302
      when(ecc_array.io.w.req.valid) {
303 304
        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")
      }
305 306
      ecc_array.io.r.req.valid := io.read(j).valid && rmask(r)
      ecc_array.io.r.req.bits.apply(setIdx = raddr)
307

L
ljw 已提交
308 309 310 311 312 313 314 315
      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
316

L
ljw 已提交
317 318 319 320 321
      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)
        }
322
      }
L
ljw 已提交
323 324 325
      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)
326 327
      for (k <- 0 until rowWords) {
        ecc_resp_chosen(k) := Mux1H(way_en, ecc_resp(k))
328
      }
L
ljw 已提交
329
      io.resp(j)(r) := Cat((0 until rowWords) reverseMap {
330 331 332 333 334
        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 已提交
335
      })
336 337 338 339
      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)
340
    }
341

342 343 344 345
    io.nacks(j) := false.B
  }
}

346
class L1MetadataArray(onReset: () => L1Metadata)(implicit p: Parameters) extends DCacheModule {
A
Allen 已提交
347
  val rstVal = onReset()
348 349 350
  val metaBits = rstVal.getWidth
  val encMetaBits = cacheParams.tagCode.width(metaBits)

A
Allen 已提交
351 352 353
  val io = IO(new Bundle {
    val read = Flipped(Decoupled(new L1MetaReadReq))
    val write = Flipped(Decoupled(new L1MetaWriteReq))
354
    val resp = Output(Vec(nWays, UInt(encMetaBits.W)))
355
    val error = Output(new L1CacheErrorInfo)
A
Allen 已提交
356
  })
L
ljw 已提交
357
  val rst_cnt = RegInit(0.U(log2Up(nSets + 1).W))
A
Allen 已提交
358 359 360 361 362
  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 已提交
363 364 365
  when(rst) {
    rst_cnt := rst_cnt + 1.U
  }
A
Allen 已提交
366

L
ljw 已提交
367 368
  val tag_array = Module(new SRAMTemplate(UInt(encMetaBits.W), set = nSets, way = nWays,
    shouldReset = false, holdRead = false, singlePort = true))
369 370

  // tag write
371
  val wen = rst || io.write.valid
372 373
  tag_array.io.w.req.valid := wen
  tag_array.io.w.req.bits.apply(
L
ljw 已提交
374 375 376
    setIdx = waddr,
    data = cacheParams.tagCode.encode(wdata),
    waymask = VecInit(wmask).asUInt)
377 378

  // tag read
379 380
  val ren = io.read.fire()
  tag_array.io.r.req.valid := ren
L
ljw 已提交
381
  tag_array.io.r.req.bits.apply(setIdx = io.read.bits.idx)
382
  io.resp := tag_array.io.r.resp.data
383 384 385 386 387 388 389
  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 已提交
390

391 392
  io.write.ready := !rst
  io.read.ready := !wen
A
Allen 已提交
393 394

  def dumpRead() = {
L
ljw 已提交
395
    when(io.read.fire()) {
A
Allen 已提交
396 397 398 399 400 401
      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 已提交
402
    when(io.write.fire()) {
A
Allen 已提交
403 404 405 406 407
      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)
    }
  }

408 409 410 411 412 413
  // 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 已提交
414 415 416 417

  def dump() = {
    dumpRead
    dumpWrite
418
    // dumpResp
A
Allen 已提交
419 420 421
  }
}

422
class DuplicatedMetaArray(implicit p: Parameters) extends DCacheModule {
423
  def onReset = L1Metadata(0.U, ClientMetadata.onReset)
L
ljw 已提交
424

425 426 427
  val metaBits = onReset.getWidth
  val encMetaBits = cacheParams.tagCode.width(metaBits)

A
Allen 已提交
428
  val io = IO(new DCacheBundle {
L
ljw 已提交
429
    val read = Vec(LoadPipelineWidth, Flipped(DecoupledIO(new L1MetaReadReq)))
A
Allen 已提交
430
    val write = Flipped(DecoupledIO(new L1MetaWriteReq))
L
ljw 已提交
431
    val resp = Output(Vec(LoadPipelineWidth, Vec(nWays, UInt(encMetaBits.W))))
432
    val errors = Output(Vec(LoadPipelineWidth, new L1CacheErrorInfo))
A
Allen 已提交
433
  })
L
ljw 已提交
434 435 436
  val meta = Seq.fill(LoadPipelineWidth) {
    Module(new L1MetadataArray(onReset _))
  }
A
Allen 已提交
437

438
  for (w <- 0 until LoadPipelineWidth) {
439 440 441
    // meta(w).io.write <> io.write
    meta(w).io.write.valid := io.write.valid
    meta(w).io.write.bits := io.write.bits
L
ljw 已提交
442
    meta(w).io.read <> io.read(w)
443
    io.resp(w) <> meta(w).io.resp
444
    io.errors(w) <> meta(w).io.error
A
Allen 已提交
445
  }
446 447
  // io.write.ready := VecInit(meta.map(_.io.write.ready)).asUInt.andR
  io.write.ready := true.B
A
Allen 已提交
448

449
  def dumpRead() = {
450
    (0 until LoadPipelineWidth) map { w =>
L
ljw 已提交
451
      when(io.read(w).fire()) {
452
        XSDebug(s"MetaArray Read channel: $w idx: %d way_en: %x tag: %x\n",
453 454 455 456 457 458
          io.read(w).bits.idx, io.read(w).bits.way_en, io.read(w).bits.tag)
      }
    }
  }

  def dumpWrite() = {
L
ljw 已提交
459
    when(io.write.fire()) {
460 461
      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 已提交
462 463
    }
  }
464

465 466 467 468 469 470 471 472
  // 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)
  //     }
  //   }
  // }
473 474 475 476

  def dump() = {
    dumpRead
    dumpWrite
477
    // dumpResp
478
  }
A
Allen 已提交
479
}