xref: /XiangShan/src/main/scala/xiangshan/cache/dcache/data/BankedDataArray.scala (revision 602aa9f1a8fb63310bea30e8b3e247e5aca5f123)
11f0e2dc7SJiawei Lin/***************************************************************************************
2e3da8badSTang Haojin* Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC)
3e3da8badSTang Haojin* Copyright (c) 2020-2024 Institute of Computing Technology, Chinese Academy of Sciences
41f0e2dc7SJiawei Lin* Copyright (c) 2020-2021 Peng Cheng Laboratory
51f0e2dc7SJiawei Lin*
61f0e2dc7SJiawei Lin* XiangShan is licensed under Mulan PSL v2.
71f0e2dc7SJiawei Lin* You can use this software according to the terms and conditions of the Mulan PSL v2.
81f0e2dc7SJiawei Lin* You may obtain a copy of Mulan PSL v2 at:
91f0e2dc7SJiawei Lin*          http://license.coscl.org.cn/MulanPSL2
101f0e2dc7SJiawei Lin*
111f0e2dc7SJiawei Lin* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
121f0e2dc7SJiawei Lin* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
131f0e2dc7SJiawei Lin* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
141f0e2dc7SJiawei Lin*
151f0e2dc7SJiawei Lin* See the Mulan PSL v2 for more details.
16c49ebec8SHaoyuan Feng*
17c49ebec8SHaoyuan Feng*
18c49ebec8SHaoyuan Feng* Acknowledgement
19c49ebec8SHaoyuan Feng*
20c49ebec8SHaoyuan Feng* This implementation is inspired by several key papers:
21c49ebec8SHaoyuan Feng* [1] Gurindar S. Sohi, and Manoj Franklin. "[High-bandwidth data memory systems for superscalar processors.]
22c49ebec8SHaoyuan Feng* (https://doi.org/10.1145/106972.106980)" 4th International Conference on Architectural Support for Programming
23c49ebec8SHaoyuan Feng* Languages and Operating Systems (ASPLOS). 1991.
241f0e2dc7SJiawei Lin***************************************************************************************/
251f0e2dc7SJiawei Lin
261f0e2dc7SJiawei Linpackage xiangshan.cache
271f0e2dc7SJiawei Lin
288891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters
291f0e2dc7SJiawei Linimport chisel3._
300f59c834SWilliam Wangimport utils._
313c02ee8fSwakafaimport utility._
3211269ca7STang Haojinimport utility.sram.SRAMTemplate
331f0e2dc7SJiawei Linimport chisel3.util._
344b2c87baS梁森 Liang Senimport utility.mbist.MbistPipeline
358ffb12e4SAnzoimport xiangshan.mem.LqPtr
36144422dcSMaxpicca-Liimport xiangshan.{L1CacheErrorInfo, XSCoreParamsKey}
371f0e2dc7SJiawei Lin
381f0e2dc7SJiawei Linimport scala.math.max
391f0e2dc7SJiawei Lin
40144422dcSMaxpicca-Liclass BankConflictDB(implicit p: Parameters) extends DCacheBundle{
41144422dcSMaxpicca-Li  val addr = Vec(LoadPipelineWidth, Bits(PAddrBits.W))
42144422dcSMaxpicca-Li  val set_index = Vec(LoadPipelineWidth, UInt((DCacheAboveIndexOffset - DCacheSetOffset).W))
43cdbff57cSHaoyuan Feng  val bank_index = Vec(VLEN/DCacheSRAMRowBits, UInt((DCacheSetOffset - DCacheBankOffset).W))
44144422dcSMaxpicca-Li  val way_index = UInt(wayBits.W)
45144422dcSMaxpicca-Li  val fake_rr_bank_conflict = Bool()
46144422dcSMaxpicca-Li}
47144422dcSMaxpicca-Li
481f0e2dc7SJiawei Linclass L1BankedDataReadReq(implicit p: Parameters) extends DCacheBundle
491f0e2dc7SJiawei Lin{
501f0e2dc7SJiawei Lin  val way_en = Bits(DCacheWays.W)
511f0e2dc7SJiawei Lin  val addr = Bits(PAddrBits.W)
521f0e2dc7SJiawei Lin}
531f0e2dc7SJiawei Lin
54cdbff57cSHaoyuan Fengclass L1BankedDataReadReqWithMask(implicit p: Parameters) extends DCacheBundle
55cdbff57cSHaoyuan Feng{
56cdbff57cSHaoyuan Feng  val way_en = Bits(DCacheWays.W)
57cdbff57cSHaoyuan Feng  val addr = Bits(PAddrBits.W)
58fa5e530dScz4e  val addr_dup = Bits(PAddrBits.W)
59cdbff57cSHaoyuan Feng  val bankMask = Bits(DCacheBanks.W)
60a5f58fbcSlixin  val kill = Bool()
618ffb12e4SAnzo  val lqIdx = new LqPtr
62cdbff57cSHaoyuan Feng}
63cdbff57cSHaoyuan Feng
641f0e2dc7SJiawei Linclass L1BankedDataReadLineReq(implicit p: Parameters) extends L1BankedDataReadReq
651f0e2dc7SJiawei Lin{
661f0e2dc7SJiawei Lin  val rmask = Bits(DCacheBanks.W)
671f0e2dc7SJiawei Lin}
681f0e2dc7SJiawei Lin
691f0e2dc7SJiawei Lin// Now, we can write a cache-block in a single cycle
701f0e2dc7SJiawei Linclass L1BankedDataWriteReq(implicit p: Parameters) extends L1BankedDataReadReq
711f0e2dc7SJiawei Lin{
721f0e2dc7SJiawei Lin  val wmask = Bits(DCacheBanks.W)
731f0e2dc7SJiawei Lin  val data = Vec(DCacheBanks, Bits(DCacheSRAMRowBits.W))
741f0e2dc7SJiawei Lin}
751f0e2dc7SJiawei Lin
766c7e5e86Szhanglinjuan// cache-block write request without data
776c7e5e86Szhanglinjuanclass L1BankedDataWriteReqCtrl(implicit p: Parameters) extends L1BankedDataReadReq
786c7e5e86Szhanglinjuan
791f0e2dc7SJiawei Linclass L1BankedDataReadResult(implicit p: Parameters) extends DCacheBundle
801f0e2dc7SJiawei Lin{
811f0e2dc7SJiawei Lin  // you can choose which bank to read to save power
82b34797bcScz4e  val ecc = Bits(dataECCBits.W)
831f0e2dc7SJiawei Lin  val raw_data = Bits(DCacheSRAMRowBits.W)
846786cfb7SWilliam Wang  val error_delayed = Bool() // 1 cycle later than data resp
851f0e2dc7SJiawei Lin
861f0e2dc7SJiawei Lin  def asECCData() = {
871f0e2dc7SJiawei Lin    Cat(ecc, raw_data)
881f0e2dc7SJiawei Lin  }
891f0e2dc7SJiawei Lin}
901f0e2dc7SJiawei Lin
91ea329fc7Szhanglinjuanclass DataSRAMBankWriteReq(implicit p: Parameters) extends DCacheBundle {
92ea329fc7Szhanglinjuan  val en = Bool()
93ea329fc7Szhanglinjuan  val addr = UInt()
94ea329fc7Szhanglinjuan  val way_en = UInt(DCacheWays.W)
95b34797bcScz4e  val data = UInt(encDataBits.W)
96ea329fc7Szhanglinjuan}
97ea329fc7Szhanglinjuan
987dbf3a33SMaxpicca-Li// wrap a sram
997dbf3a33SMaxpicca-Liclass DataSRAM(bankIdx: Int, wayIdx: Int)(implicit p: Parameters) extends DCacheModule {
1007dbf3a33SMaxpicca-Li  val io = IO(new Bundle() {
1017dbf3a33SMaxpicca-Li    val w = new Bundle() {
1027dbf3a33SMaxpicca-Li      val en = Input(Bool())
1037dbf3a33SMaxpicca-Li      val addr = Input(UInt())
104b34797bcScz4e      val data = Input(UInt(encDataBits.W))
1057dbf3a33SMaxpicca-Li    }
1067dbf3a33SMaxpicca-Li
1077dbf3a33SMaxpicca-Li    val r = new Bundle() {
1087dbf3a33SMaxpicca-Li      val en = Input(Bool())
1097dbf3a33SMaxpicca-Li      val addr = Input(UInt())
110b34797bcScz4e      val data = Output(UInt(encDataBits.W))
1117dbf3a33SMaxpicca-Li    }
1127dbf3a33SMaxpicca-Li  })
1137dbf3a33SMaxpicca-Li
1147dbf3a33SMaxpicca-Li  // data sram
1157dbf3a33SMaxpicca-Li  val data_sram = Module(new SRAMTemplate(
116b34797bcScz4e    Bits(encDataBits.W),
1173eeae490SMaxpicca-Li    set = DCacheSets / DCacheSetDiv,
1187dbf3a33SMaxpicca-Li    way = 1,
1197dbf3a33SMaxpicca-Li    shouldReset = false,
1207dbf3a33SMaxpicca-Li    holdRead = false,
1214b2c87baS梁森 Liang Sen    singlePort = true,
122*602aa9f1Scz4e    hasMbist = hasMbist,
123*602aa9f1Scz4e    hasSramCtl = hasSramCtl
1247dbf3a33SMaxpicca-Li  ))
1257dbf3a33SMaxpicca-Li
1263eeae490SMaxpicca-Li  data_sram.io.w.req.valid := io.w.en
1277dbf3a33SMaxpicca-Li  data_sram.io.w.req.bits.apply(
1283eeae490SMaxpicca-Li    setIdx = io.w.addr,
1293eeae490SMaxpicca-Li    data = io.w.data,
1307dbf3a33SMaxpicca-Li    waymask = 1.U
1317dbf3a33SMaxpicca-Li  )
1327dbf3a33SMaxpicca-Li  data_sram.io.r.req.valid := io.r.en
1337dbf3a33SMaxpicca-Li  data_sram.io.r.req.bits.apply(setIdx = io.r.addr)
1347dbf3a33SMaxpicca-Li  io.r.data := data_sram.io.r.resp.data(0)
13504665835SMaxpicca-Li  XSPerfAccumulate("part_data_read_counter", data_sram.io.r.req.valid)
1367dbf3a33SMaxpicca-Li
1377dbf3a33SMaxpicca-Li  def dump_r() = {
1388b33cd30Sklin02    XSDebug(RegNext(io.r.en),
1398b33cd30Sklin02      "bank read set %x bank %x way %x data %x\n",
1404a0e27ecSYanqin Li      RegEnable(io.r.addr, io.r.en),
1417dbf3a33SMaxpicca-Li      bankIdx.U,
1427dbf3a33SMaxpicca-Li      wayIdx.U,
1437dbf3a33SMaxpicca-Li      io.r.data
1447dbf3a33SMaxpicca-Li    )
1457dbf3a33SMaxpicca-Li  }
1467dbf3a33SMaxpicca-Li
1477dbf3a33SMaxpicca-Li  def dump_w() = {
1488b33cd30Sklin02    XSDebug(io.w.en,
1498b33cd30Sklin02      "bank write set %x bank %x way %x data %x\n",
1507dbf3a33SMaxpicca-Li      io.w.addr,
1517dbf3a33SMaxpicca-Li      bankIdx.U,
1527dbf3a33SMaxpicca-Li      wayIdx.U,
1537dbf3a33SMaxpicca-Li      io.w.data
1547dbf3a33SMaxpicca-Li    )
1557dbf3a33SMaxpicca-Li  }
1567dbf3a33SMaxpicca-Li
1577dbf3a33SMaxpicca-Li  def dump() = {
1587dbf3a33SMaxpicca-Li    dump_w()
1597dbf3a33SMaxpicca-Li    dump_r()
1607dbf3a33SMaxpicca-Li  }
1617dbf3a33SMaxpicca-Li}
1627dbf3a33SMaxpicca-Li
1637dbf3a33SMaxpicca-Li// wrap data rows of 8 ways
1647dbf3a33SMaxpicca-Liclass DataSRAMBank(index: Int)(implicit p: Parameters) extends DCacheModule {
1657dbf3a33SMaxpicca-Li  val io = IO(new Bundle() {
1667dbf3a33SMaxpicca-Li    val w = Input(new DataSRAMBankWriteReq)
1677dbf3a33SMaxpicca-Li
1687dbf3a33SMaxpicca-Li    val r = new Bundle() {
1697dbf3a33SMaxpicca-Li      val en = Input(Bool())
1707dbf3a33SMaxpicca-Li      val addr = Input(UInt())
171b34797bcScz4e      val data = Output(Vec(DCacheWays, UInt(encDataBits.W)))
1727dbf3a33SMaxpicca-Li    }
1737dbf3a33SMaxpicca-Li  })
1747dbf3a33SMaxpicca-Li
1757dbf3a33SMaxpicca-Li  assert(RegNext(!io.w.en || PopCount(io.w.way_en) <= 1.U))
1767dbf3a33SMaxpicca-Li
1773eeae490SMaxpicca-Li  // external controls do not read and write at the same time
1783eeae490SMaxpicca-Li  val w_info = io.w
1797dbf3a33SMaxpicca-Li  // val rw_bypass = RegNext(io.w.addr === io.r.addr && io.w.way_en === io.r.way_en && io.w.en)
1807dbf3a33SMaxpicca-Li
1817dbf3a33SMaxpicca-Li  // multiway data bank
182e3da8badSTang Haojin  val data_bank = Seq.fill(DCacheWays) {
1837dbf3a33SMaxpicca-Li    Module(new SRAMTemplate(
184b34797bcScz4e      Bits(encDataBits.W),
1853eeae490SMaxpicca-Li      set = DCacheSets / DCacheSetDiv,
1867dbf3a33SMaxpicca-Li      way = 1,
1877dbf3a33SMaxpicca-Li      shouldReset = false,
1887dbf3a33SMaxpicca-Li      holdRead = false,
189452b5843SHuijin Li      singlePort = true,
1904b2c87baS梁森 Liang Sen      withClockGate = true,
191ebe07d61S梁森 Liang Sen      hasMbist = hasMbist,
192*602aa9f1Scz4e      hasSramCtl = hasSramCtl,
193ebe07d61S梁森 Liang Sen      suffix = Some("dcsh_dat")
1947dbf3a33SMaxpicca-Li    ))
1957dbf3a33SMaxpicca-Li  }
1967dbf3a33SMaxpicca-Li
1977dbf3a33SMaxpicca-Li  for (w <- 0 until DCacheWays) {
1983eeae490SMaxpicca-Li    val wen = w_info.en && w_info.way_en(w)
1997dbf3a33SMaxpicca-Li    data_bank(w).io.w.req.valid := wen
2007dbf3a33SMaxpicca-Li    data_bank(w).io.w.req.bits.apply(
2013eeae490SMaxpicca-Li      setIdx = w_info.addr,
2023eeae490SMaxpicca-Li      data = w_info.data,
2037dbf3a33SMaxpicca-Li      waymask = 1.U
2047dbf3a33SMaxpicca-Li    )
2057dbf3a33SMaxpicca-Li    data_bank(w).io.r.req.valid := io.r.en
2067dbf3a33SMaxpicca-Li    data_bank(w).io.r.req.bits.apply(setIdx = io.r.addr)
2077dbf3a33SMaxpicca-Li  }
20804665835SMaxpicca-Li  XSPerfAccumulate("part_data_read_counter", PopCount(Cat(data_bank.map(_.io.r.req.valid))))
2097dbf3a33SMaxpicca-Li
2107bd3dbddShappy-lx  io.r.data := data_bank.map(_.io.r.resp.data(0))
2117dbf3a33SMaxpicca-Li
2127dbf3a33SMaxpicca-Li  def dump_r() = {
2138b33cd30Sklin02    XSDebug(RegNext(io.r.en),
2148b33cd30Sklin02      "bank read addr %x data %x\n",
2154a0e27ecSYanqin Li      RegEnable(io.r.addr, io.r.en),
2167bd3dbddShappy-lx      io.r.data.asUInt
2177dbf3a33SMaxpicca-Li    )
2187dbf3a33SMaxpicca-Li  }
2197dbf3a33SMaxpicca-Li
2207dbf3a33SMaxpicca-Li  def dump_w() = {
2218b33cd30Sklin02    XSDebug(io.w.en,
2228b33cd30Sklin02      "bank write addr %x way_en %x data %x\n",
2237dbf3a33SMaxpicca-Li      io.w.addr,
2247dbf3a33SMaxpicca-Li      io.w.way_en,
2257dbf3a33SMaxpicca-Li      io.w.data
2267dbf3a33SMaxpicca-Li    )
2277dbf3a33SMaxpicca-Li  }
2287dbf3a33SMaxpicca-Li
2297dbf3a33SMaxpicca-Li  def dump() = {
2307dbf3a33SMaxpicca-Li    dump_w()
2317dbf3a33SMaxpicca-Li    dump_r()
2327dbf3a33SMaxpicca-Li  }
2337dbf3a33SMaxpicca-Li}
2347dbf3a33SMaxpicca-Li
235cd2ff98bShappy-lxcase object HasDataEccParam
236cd2ff98bShappy-lx
2371f0e2dc7SJiawei Lin//                     Banked DCache Data
2381f0e2dc7SJiawei Lin// -----------------------------------------------------------------
2391f0e2dc7SJiawei Lin// | Bank0 | Bank1 | Bank2 | Bank3 | Bank4 | Bank5 | Bank6 | Bank7 |
2401f0e2dc7SJiawei Lin// -----------------------------------------------------------------
2411f0e2dc7SJiawei Lin// | Way0  | Way0  | Way0  | Way0  | Way0  | Way0  | Way0  | Way0  |
2421f0e2dc7SJiawei Lin// | Way1  | Way1  | Way1  | Way1  | Way1  | Way1  | Way1  | Way1  |
2431f0e2dc7SJiawei Lin// | ....  | ....  | ....  | ....  | ....  | ....  | ....  | ....  |
2441f0e2dc7SJiawei Lin// -----------------------------------------------------------------
2451f0e2dc7SJiawei Linabstract class AbstractBankedDataArray(implicit p: Parameters) extends DCacheModule
2461f0e2dc7SJiawei Lin{
247cd2ff98bShappy-lx  val DataEccParam = if(EnableDataEcc) Some(HasDataEccParam) else None
248026615fcSWilliam Wang  val ReadlinePortErrorIndex = LoadPipelineWidth
2491f0e2dc7SJiawei Lin  val io = IO(new DCacheBundle {
2501f0e2dc7SJiawei Lin    // load pipeline read word req
251cdbff57cSHaoyuan Feng    val read = Vec(LoadPipelineWidth, Flipped(DecoupledIO(new L1BankedDataReadReqWithMask)))
252cdbff57cSHaoyuan Feng    val is128Req = Input(Vec(LoadPipelineWidth, Bool()))
2531f0e2dc7SJiawei Lin    // main pipeline read / write line req
2547a5caa97Szhanglinjuan    val readline_intend = Input(Bool())
2551f0e2dc7SJiawei Lin    val readline = Flipped(DecoupledIO(new L1BankedDataReadLineReq))
256ebe07d61S梁森 Liang Sen    val readline_can_go = Input(Bool())
257ebe07d61S梁森 Liang Sen    val readline_stall = Input(Bool())
258ebe07d61S梁森 Liang Sen    val readline_can_resp = Input(Bool())
2591f0e2dc7SJiawei Lin    val write = Flipped(DecoupledIO(new L1BankedDataWriteReq))
2606c7e5e86Szhanglinjuan    val write_dup = Vec(DCacheBanks, Flipped(Decoupled(new L1BankedDataWriteReqCtrl)))
261144422dcSMaxpicca-Li    // data for readline and loadpipe
262144422dcSMaxpicca-Li    val readline_resp = Output(Vec(DCacheBanks, new L1BankedDataReadResult()))
263144422dcSMaxpicca-Li    val readline_error_delayed = Output(Bool())
264d4564868Sweiding liu    val read_resp          = Output(Vec(LoadPipelineWidth, Vec(VLEN/DCacheSRAMRowBits, new L1BankedDataReadResult())))
265cdbff57cSHaoyuan Feng    val read_error_delayed = Output(Vec(LoadPipelineWidth,Vec(VLEN/DCacheSRAMRowBits, Bool())))
2661f0e2dc7SJiawei Lin    // val nacks = Output(Vec(LoadPipelineWidth, Bool()))
2670184a80eSYanqin Li    // val errors = Output(Vec(LoadPipelineWidth + 1, ValidIO(new L1CacheErrorInfo))) // read ports + readline port
2681f0e2dc7SJiawei Lin    // when bank_conflict, read (1) port should be ignored
2691f0e2dc7SJiawei Lin    val bank_conflict_slow = Output(Vec(LoadPipelineWidth, Bool()))
2707a5caa97Szhanglinjuan    val disable_ld_fast_wakeup = Output(Vec(LoadPipelineWidth, Bool()))
27172dab974Scz4e    val pseudo_error = Flipped(DecoupledIO(Vec(DCacheBanks, new CtrlUnitSignalingBundle)))
2721f0e2dc7SJiawei Lin  })
2731f0e2dc7SJiawei Lin
274fa5e530dScz4e  // bank (0, 1, 2, 3) each way use duplicate addr
275fa5e530dScz4e  def DuplicatedQueryBankSeq = Seq(0, 1, 2, 3)
276fa5e530dScz4e
2771f0e2dc7SJiawei Lin  def pipeMap[T <: Data](f: Int => T) = VecInit((0 until LoadPipelineWidth).map(f))
2781f0e2dc7SJiawei Lin
2797dbf3a33SMaxpicca-Li  def getECCFromEncWord(encWord: UInt) = {
280b34797bcScz4e    if (EnableDataEcc) {
281b34797bcScz4e      require(encWord.getWidth == encDataBits, s"encDataBits=$encDataBits != encDataBits=$encDataBits!")
282b34797bcScz4e      encWord(encDataBits-1, DCacheSRAMRowBits)
283b34797bcScz4e    } else {
284b34797bcScz4e      0.U
285b34797bcScz4e    }
286b34797bcScz4e  }
287b34797bcScz4e
288b34797bcScz4e  def getDataFromEncWord(encWord: UInt) = {
289b34797bcScz4e    encWord(DCacheSRAMRowBits-1, 0)
290b34797bcScz4e  }
291b34797bcScz4e
292b34797bcScz4e  def asECCData(ecc: UInt, data: UInt) = {
293b34797bcScz4e    if (EnableDataEcc) {
294b34797bcScz4e      Cat(ecc, data)
295b34797bcScz4e    } else {
296b34797bcScz4e      data
297b34797bcScz4e    }
2987dbf3a33SMaxpicca-Li  }
2997dbf3a33SMaxpicca-Li
300e3da8badSTang Haojin  def dumpRead = {
3011f0e2dc7SJiawei Lin    (0 until LoadPipelineWidth) map { w =>
3028b33cd30Sklin02      XSDebug(io.read(w).valid,
3038b33cd30Sklin02        s"DataArray Read channel: $w valid way_en: %x addr: %x\n",
3041f0e2dc7SJiawei Lin        io.read(w).bits.way_en, io.read(w).bits.addr)
3051f0e2dc7SJiawei Lin    }
3068b33cd30Sklin02    XSDebug(io.readline.valid,
3078b33cd30Sklin02      s"DataArray Read Line, valid way_en: %x addr: %x rmask %x\n",
3081f0e2dc7SJiawei Lin      io.readline.bits.way_en, io.readline.bits.addr, io.readline.bits.rmask)
3091f0e2dc7SJiawei Lin  }
3101f0e2dc7SJiawei Lin
311e3da8badSTang Haojin  def dumpWrite = {
3128b33cd30Sklin02    XSDebug(io.write.valid,
3138b33cd30Sklin02      s"DataArray Write valid way_en: %x addr: %x\n",
3141f0e2dc7SJiawei Lin      io.write.bits.way_en, io.write.bits.addr)
3151f0e2dc7SJiawei Lin
3161f0e2dc7SJiawei Lin    (0 until DCacheBanks) map { r =>
3178b33cd30Sklin02      XSDebug(io.write.valid,
3188b33cd30Sklin02        s"cycle: $r data: %x wmask: %x\n",
3191f0e2dc7SJiawei Lin        io.write.bits.data(r), io.write.bits.wmask(r))
3201f0e2dc7SJiawei Lin    }
3211f0e2dc7SJiawei Lin  }
3221f0e2dc7SJiawei Lin
323e3da8badSTang Haojin  def dumpResp = {
3241f0e2dc7SJiawei Lin    XSDebug(s"DataArray ReadeResp channel:\n")
325144422dcSMaxpicca-Li    (0 until LoadPipelineWidth) map { r =>
326cdbff57cSHaoyuan Feng      XSDebug(s"cycle: $r data: %x\n", Mux(io.is128Req(r),
327d4564868Sweiding liu        Cat(io.read_resp(r)(1).raw_data,io.read_resp(r)(0).raw_data),
328d4564868Sweiding liu        io.read_resp(r)(0).raw_data))
3291f0e2dc7SJiawei Lin    }
3301f0e2dc7SJiawei Lin  }
3311f0e2dc7SJiawei Lin
3321f0e2dc7SJiawei Lin  def dump() = {
3331f0e2dc7SJiawei Lin    dumpRead
3341f0e2dc7SJiawei Lin    dumpWrite
3351f0e2dc7SJiawei Lin    dumpResp
3361f0e2dc7SJiawei Lin  }
3378ffb12e4SAnzo
3388ffb12e4SAnzo  def selcetOldestPort(valid: Seq[Bool], bits: Seq[LqPtr], index: Seq[UInt]):((Bool, LqPtr), UInt) = {
3398ffb12e4SAnzo    require(valid.length == bits.length &&  bits.length == index.length, s"length must eq, valid:${valid.length}, bits:${bits.length}, index:${index.length}")
3408ffb12e4SAnzo    ParallelOperation(valid zip bits zip index,
3418ffb12e4SAnzo      (a: ((Bool, LqPtr), UInt), b: ((Bool, LqPtr), UInt)) => {
3428ffb12e4SAnzo        val au = a._1._2
3438ffb12e4SAnzo        val bu = b._1._2
3448ffb12e4SAnzo        val aValid = a._1._1
3458ffb12e4SAnzo        val bValid = b._1._1
3468ffb12e4SAnzo        val bSel = au > bu
3478ffb12e4SAnzo        val bits = Mux(
3488ffb12e4SAnzo          aValid && bValid,
3498ffb12e4SAnzo          Mux(bSel, b._1._2, a._1._2),
3508ffb12e4SAnzo          Mux(aValid && !bValid, a._1._2, b._1._2)
3518ffb12e4SAnzo        )
3528ffb12e4SAnzo        val idx = Mux(
3538ffb12e4SAnzo          aValid && bValid,
3548ffb12e4SAnzo          Mux(bSel, b._2, a._2),
3558ffb12e4SAnzo          Mux(aValid && !bValid, a._2, b._2)
3568ffb12e4SAnzo        )
3578ffb12e4SAnzo        ((aValid || bValid, bits), idx)
3588ffb12e4SAnzo      }
3598ffb12e4SAnzo    )
3608ffb12e4SAnzo  }
3618ffb12e4SAnzo
3621f0e2dc7SJiawei Lin}
3631f0e2dc7SJiawei Lin
3647dbf3a33SMaxpicca-Li// the smallest access unit is sram
3657dbf3a33SMaxpicca-Liclass SramedDataArray(implicit p: Parameters) extends AbstractBankedDataArray {
3667dbf3a33SMaxpicca-Li  println("  DCacheType: SramedDataArray")
367300ded30SWilliam Wang  val ReduceReadlineConflict = false
368300ded30SWilliam Wang
3691f0e2dc7SJiawei Lin  io.write.ready := true.B
3706c7e5e86Szhanglinjuan  io.write_dup.foreach(_.ready := true.B)
3711f0e2dc7SJiawei Lin
3724b2c87baS梁森 Liang Sen  val data_banks = List.tabulate(DCacheSetDiv)( k => {
3734b2c87baS梁森 Liang Sen    val banks = List.tabulate(DCacheBanks)(i => List.tabulate(DCacheWays)(j => Module(new DataSRAM(i,j))))
3744b2c87baS梁森 Liang Sen    val mbistPl = MbistPipeline.PlaceMbistPipeline(1, s"MbistPipeDataSet$k", hasMbist)
3754b2c87baS梁森 Liang Sen    banks
3764b2c87baS梁森 Liang Sen  })
3773eeae490SMaxpicca-Li  data_banks.map(_.map(_.map(_.dump())))
3781f0e2dc7SJiawei Lin
3791f0e2dc7SJiawei Lin  val way_en = Wire(Vec(LoadPipelineWidth, io.read(0).bits.way_en.cloneType))
3801f0e2dc7SJiawei Lin  val set_addrs = Wire(Vec(LoadPipelineWidth, UInt()))
3813eeae490SMaxpicca-Li  val div_addrs = Wire(Vec(LoadPipelineWidth, UInt()))
382cdbff57cSHaoyuan Feng  val bank_addrs = Wire(Vec(LoadPipelineWidth, Vec(VLEN/DCacheSRAMRowBits, UInt())))
3831f0e2dc7SJiawei Lin
3843eeae490SMaxpicca-Li  val line_set_addr = addr_to_dcache_div_set(io.readline.bits.addr)
3853eeae490SMaxpicca-Li  val line_div_addr = addr_to_dcache_div(io.readline.bits.addr)
38604665835SMaxpicca-Li  // when WPU is enabled, line_way_en is all enabled when read data
38704665835SMaxpicca-Li  val line_way_en = Fill(DCacheWays, 1.U) // val line_way_en = io.readline.bits.way_en
3884a0e27ecSYanqin Li  val line_way_en_reg = RegEnable(io.readline.bits.way_en, 0.U(DCacheWays.W),io.readline.valid)
3893eeae490SMaxpicca-Li
3904a0e27ecSYanqin Li  val write_bank_mask_reg = RegEnable(io.write.bits.wmask, 0.U(DCacheBanks.W), io.write.valid)
3915adc4829SYanqin Li  val write_data_reg = RegEnable(io.write.bits.data, io.write.valid)
3923eeae490SMaxpicca-Li  val write_valid_reg = RegNext(io.write.valid)
3933eeae490SMaxpicca-Li  val write_valid_dup_reg = io.write_dup.map(x => RegNext(x.valid))
3944a0e27ecSYanqin Li  val write_wayen_dup_reg = io.write_dup.map(x => RegEnable(x.bits.way_en, 0.U(DCacheWays.W), x.valid))
3955adc4829SYanqin Li  val write_set_addr_dup_reg = io.write_dup.map(x => RegEnable(addr_to_dcache_div_set(x.bits.addr), x.valid))
3965adc4829SYanqin Li  val write_div_addr_dup_reg = io.write_dup.map(x => RegEnable(addr_to_dcache_div(x.bits.addr), x.valid))
3973eeae490SMaxpicca-Li
3981f0e2dc7SJiawei Lin  // read data_banks and ecc_banks
3991f0e2dc7SJiawei Lin  // for single port SRAM, do not allow read and write in the same cycle
4001f0e2dc7SJiawei Lin  val rrhazard = false.B // io.readline.valid
4011f0e2dc7SJiawei Lin  (0 until LoadPipelineWidth).map(rport_index => {
4023eeae490SMaxpicca-Li    div_addrs(rport_index) := addr_to_dcache_div(io.read(rport_index).bits.addr)
4033eeae490SMaxpicca-Li    set_addrs(rport_index) := addr_to_dcache_div_set(io.read(rport_index).bits.addr)
404cdbff57cSHaoyuan Feng    bank_addrs(rport_index)(0) := addr_to_dcache_bank(io.read(rport_index).bits.addr)
405cdbff57cSHaoyuan Feng    bank_addrs(rport_index)(1) := bank_addrs(rport_index)(0) + 1.U
4061f0e2dc7SJiawei Lin
4071f0e2dc7SJiawei Lin    // use way_en to select a way after data read out
408935edac4STang Haojin    assert(!(RegNext(io.read(rport_index).fire && PopCount(io.read(rport_index).bits.way_en) > 1.U)))
4091f0e2dc7SJiawei Lin    way_en(rport_index) := io.read(rport_index).bits.way_en
4101f0e2dc7SJiawei Lin  })
4111f0e2dc7SJiawei Lin
412144422dcSMaxpicca-Li  // read conflict
4138ffb12e4SAnzo  val rr_bank_conflict = Seq.tabulate(LoadPipelineWidth)(x => Seq.tabulate(LoadPipelineWidth)(y => {
4148ffb12e4SAnzo    if (x == y) {
4158ffb12e4SAnzo      false.B
4168ffb12e4SAnzo    } else {
4173eeae490SMaxpicca-Li      io.read(x).valid && io.read(y).valid &&
4183eeae490SMaxpicca-Li        div_addrs(x) === div_addrs(y) &&
419cdbff57cSHaoyuan Feng        (io.read(x).bits.bankMask & io.read(y).bits.bankMask) =/= 0.U &&
4203eeae490SMaxpicca-Li        io.read(x).bits.way_en === io.read(y).bits.way_en &&
4213eeae490SMaxpicca-Li        set_addrs(x) =/= set_addrs(y)
4228ffb12e4SAnzo    }
4238ffb12e4SAnzo  }))
4248ffb12e4SAnzo  val load_req_with_bank_conflict = rr_bank_conflict.map(_.reduce(_ || _))
4258ffb12e4SAnzo  val load_req_valid = io.read.map(_.valid)
4268ffb12e4SAnzo  val load_req_lqIdx = io.read.map(_.bits.lqIdx)
4278ffb12e4SAnzo  val load_req_index = (0 until LoadPipelineWidth).map(_.asUInt)
4288ffb12e4SAnzo
4298ffb12e4SAnzo
430c5a867ffSAnzo  val load_req_bank_conflict_selcet = selcetOldestPort(load_req_with_bank_conflict, load_req_lqIdx, load_req_index)
4318ffb12e4SAnzo  val load_req_bank_select_port  = UIntToOH(load_req_bank_conflict_selcet._2).asBools
4328ffb12e4SAnzo
4338ffb12e4SAnzo  val rr_bank_conflict_oldest = (0 until LoadPipelineWidth).map(i =>
4348ffb12e4SAnzo    !load_req_bank_select_port(i) && load_req_with_bank_conflict(i)
4358ffb12e4SAnzo  )
4368ffb12e4SAnzo
43746f74b57SHaojin Tang  val rrl_bank_conflict = Wire(Vec(LoadPipelineWidth, Bool()))
4387a5caa97Szhanglinjuan  val rrl_bank_conflict_intend = Wire(Vec(LoadPipelineWidth, Bool()))
4393eeae490SMaxpicca-Li  (0 until LoadPipelineWidth).foreach { i =>
44004665835SMaxpicca-Li    val judge = if (ReduceReadlineConflict) io.read(i).valid && (io.readline.bits.rmask & io.read(i).bits.bankMask) =/= 0.U && line_div_addr === div_addrs(i) && line_set_addr =/= set_addrs(i)
44104665835SMaxpicca-Li                else io.read(i).valid && line_div_addr === div_addrs(i) && line_set_addr =/= set_addrs(i)
4423eeae490SMaxpicca-Li    rrl_bank_conflict(i) := judge && io.readline.valid
4433eeae490SMaxpicca-Li    rrl_bank_conflict_intend(i) := judge && io.readline_intend
4447a5caa97Szhanglinjuan  }
4453eeae490SMaxpicca-Li  val wr_bank_conflict = Seq.tabulate(LoadPipelineWidth)(x =>
4463eeae490SMaxpicca-Li    io.read(x).valid && write_valid_reg &&
4473eeae490SMaxpicca-Li    div_addrs(x) === write_div_addr_dup_reg.head &&
448e9ed1022SMaxpicca-Li    way_en(x) === write_wayen_dup_reg.head &&
449cdbff57cSHaoyuan Feng    (write_bank_mask_reg(bank_addrs(x)(0)) || write_bank_mask_reg(bank_addrs(x)(1)) && io.is128Req(x))
4503eeae490SMaxpicca-Li  )
45104665835SMaxpicca-Li  val wrl_bank_conflict = io.readline.valid && write_valid_reg && line_div_addr === write_div_addr_dup_reg.head
4523eeae490SMaxpicca-Li  // ready
4533eeae490SMaxpicca-Li  io.readline.ready := !(wrl_bank_conflict)
4543eeae490SMaxpicca-Li  io.read.zipWithIndex.map { case (x, i) => x.ready := !(wr_bank_conflict(i) || rrhazard) }
455300ded30SWilliam Wang
45646f74b57SHaojin Tang  val perf_multi_read = PopCount(io.read.map(_.valid)) >= 2.U
45713f2ff1cSMaxpicca-Li  val bank_conflict_fast = Wire(Vec(LoadPipelineWidth, Bool()))
45846f74b57SHaojin Tang  (0 until LoadPipelineWidth).foreach(i => {
45913f2ff1cSMaxpicca-Li    bank_conflict_fast(i) := wr_bank_conflict(i) || rrl_bank_conflict(i) ||
4608ffb12e4SAnzo    rr_bank_conflict_oldest(i)
46113f2ff1cSMaxpicca-Li    io.bank_conflict_slow(i) := RegNext(bank_conflict_fast(i))
4623eeae490SMaxpicca-Li    io.disable_ld_fast_wakeup(i) := wr_bank_conflict(i) || rrl_bank_conflict_intend(i) ||
4637a5caa97Szhanglinjuan      (if (i == 0) 0.B else (0 until i).map(rr_bank_conflict(_)(i)).reduce(_ || _))
46446f74b57SHaojin Tang  })
4651f0e2dc7SJiawei Lin  XSPerfAccumulate("data_array_multi_read", perf_multi_read)
46646f74b57SHaojin Tang  (1 until LoadPipelineWidth).foreach(y => (0 until y).foreach(x =>
46746f74b57SHaojin Tang    XSPerfAccumulate(s"data_array_rr_bank_conflict_${x}_${y}", rr_bank_conflict(x)(y))
46846f74b57SHaojin Tang  ))
46946f74b57SHaojin Tang  (0 until LoadPipelineWidth).foreach(i => {
47046f74b57SHaojin Tang    XSPerfAccumulate(s"data_array_rrl_bank_conflict_${i}", rrl_bank_conflict(i))
4713eeae490SMaxpicca-Li    XSPerfAccumulate(s"data_array_rw_bank_conflict_${i}", wr_bank_conflict(i))
47246f74b57SHaojin Tang    XSPerfAccumulate(s"data_array_read_${i}", io.read(i).valid)
47346f74b57SHaojin Tang  })
47446f74b57SHaojin Tang  XSPerfAccumulate("data_array_access_total", PopCount(io.read.map(_.valid)))
4751f0e2dc7SJiawei Lin  XSPerfAccumulate("data_array_read_line", io.readline.valid)
4761f0e2dc7SJiawei Lin  XSPerfAccumulate("data_array_write", io.write.valid)
4771f0e2dc7SJiawei Lin
4783eeae490SMaxpicca-Li  val read_result = Wire(Vec(DCacheSetDiv, Vec(DCacheBanks, Vec(DCacheWays,new L1BankedDataReadResult()))))
4794a0e27ecSYanqin Li  val read_result_delayed = Wire(Vec(DCacheSetDiv, Vec(DCacheBanks, Vec(DCacheWays,new L1BankedDataReadResult()))))
4803eeae490SMaxpicca-Li  val read_error_delayed_result = Wire(Vec(DCacheSetDiv, Vec(DCacheBanks, Vec(DCacheWays, Bool()))))
48172dab974Scz4e  dontTouch(read_result)
48272dab974Scz4e  dontTouch(read_error_delayed_result)
48372dab974Scz4e
48472dab974Scz4e  val pseudo_data_toggle_mask = io.pseudo_error.bits.map {
48572dab974Scz4e    case bank =>
48672dab974Scz4e      Mux(io.pseudo_error.valid && bank.valid, bank.mask, 0.U)
48772dab974Scz4e  }
48872dab974Scz4e  val readline_hit = io.readline.fire &&
48972dab974Scz4e                     (io.readline.bits.rmask & VecInit(io.pseudo_error.bits.map(_.valid)).asUInt).orR
49072dab974Scz4e  val readbank_hit = io.read.zip(bank_addrs.zip(io.is128Req)).zipWithIndex.map {
49172dab974Scz4e                          case ((read, (bank_addr, is128Req)), i) =>
49272dab974Scz4e                            val error_bank0 = io.pseudo_error.bits(bank_addr(0))
49372dab974Scz4e                            val error_bank1 = io.pseudo_error.bits(bank_addr(1))
49472dab974Scz4e                            read.fire && (error_bank0.valid || error_bank1.valid && is128Req) && !io.bank_conflict_slow(i)
49572dab974Scz4e                      }.reduce(_|_)
49672dab974Scz4e  io.pseudo_error.ready := RegNext(readline_hit || readbank_hit)
4978ffb12e4SAnzo
4983eeae490SMaxpicca-Li  for (div_index <- 0 until DCacheSetDiv){
4991f0e2dc7SJiawei Lin    for (bank_index <- 0 until DCacheBanks) {
500144422dcSMaxpicca-Li      for (way_index <- 0 until DCacheWays) {
5011f0e2dc7SJiawei Lin        //     Set Addr & Read Way Mask
5021f0e2dc7SJiawei Lin        //
50346f74b57SHaojin Tang        //    Pipe 0   ....  Pipe (n-1)
50446f74b57SHaojin Tang        //      +      ....     +
50546f74b57SHaojin Tang        //      |      ....     |
50646f74b57SHaojin Tang        // +----+---------------+-----+
5071f0e2dc7SJiawei Lin        //  X                        X
5081f0e2dc7SJiawei Lin        //   X                      +------+ Bank Addr Match
5091f0e2dc7SJiawei Lin        //    +---------+----------+
5101f0e2dc7SJiawei Lin        //              |
5111f0e2dc7SJiawei Lin        //     +--------+--------+
5121f0e2dc7SJiawei Lin        //     |    Data Bank    |
5131f0e2dc7SJiawei Lin        //     +-----------------+
514144422dcSMaxpicca-Li        val loadpipe_en = WireInit(VecInit(List.tabulate(LoadPipelineWidth)(i => {
5158ffb12e4SAnzo          io.read(i).valid && div_addrs(i) === div_index.U && (bank_addrs(i)(0) === bank_index.U || bank_addrs(i)(1) === bank_index.U && io.is128Req(i)) &&
5168ffb12e4SAnzo          way_en(i)(way_index) &&
5178ffb12e4SAnzo          !rr_bank_conflict_oldest(i)
5181f0e2dc7SJiawei Lin        })))
519144422dcSMaxpicca-Li        val readline_en = Wire(Bool())
520300ded30SWilliam Wang        if (ReduceReadlineConflict) {
52104665835SMaxpicca-Li          readline_en := io.readline.valid && io.readline.bits.rmask(bank_index) && line_way_en(way_index) && div_index.U === line_div_addr
522300ded30SWilliam Wang        } else {
52304665835SMaxpicca-Li          readline_en := io.readline.valid && line_way_en(way_index) && div_index.U === line_div_addr
524300ded30SWilliam Wang        }
525144422dcSMaxpicca-Li        val sram_set_addr = Mux(readline_en,
5263eeae490SMaxpicca-Li          addr_to_dcache_div_set(io.readline.bits.addr),
527144422dcSMaxpicca-Li          PriorityMux(Seq.tabulate(LoadPipelineWidth)(i => loadpipe_en(i) -> set_addrs(i)))
5281f0e2dc7SJiawei Lin        )
529144422dcSMaxpicca-Li        val read_en = loadpipe_en.asUInt.orR || readline_en
5301f0e2dc7SJiawei Lin        // read raw data
5313eeae490SMaxpicca-Li        val data_bank = data_banks(div_index)(bank_index)(way_index)
532144422dcSMaxpicca-Li        data_bank.io.r.en := read_en
533144422dcSMaxpicca-Li        data_bank.io.r.addr := sram_set_addr
5341f0e2dc7SJiawei Lin
535b34797bcScz4e        read_result(div_index)(bank_index)(way_index).ecc := getECCFromEncWord(data_bank.io.r.data)
53672dab974Scz4e        read_result(div_index)(bank_index)(way_index).raw_data := getDataFromEncWord(data_bank.io.r.data) ^ pseudo_data_toggle_mask(bank_index)
5371f0e2dc7SJiawei Lin
538b34797bcScz4e        if (EnableDataEcc) {
5393eeae490SMaxpicca-Li          val ecc_data = read_result(div_index)(bank_index)(way_index).asECCData()
540144422dcSMaxpicca-Li          val ecc_data_delayed = RegEnable(ecc_data, RegNext(read_en))
5413eeae490SMaxpicca-Li          read_result(div_index)(bank_index)(way_index).error_delayed := dcacheParameters.dataCode.decode(ecc_data_delayed).error
5423eeae490SMaxpicca-Li          read_error_delayed_result(div_index)(bank_index)(way_index) := read_result(div_index)(bank_index)(way_index).error_delayed
543b34797bcScz4e        } else {
544cd2ff98bShappy-lx          read_result(div_index)(bank_index)(way_index).error_delayed := false.B
545cd2ff98bShappy-lx          read_error_delayed_result(div_index)(bank_index)(way_index) := false.B
546cd2ff98bShappy-lx        }
547b34797bcScz4e
548b34797bcScz4e        read_result_delayed(div_index)(bank_index)(way_index) := RegEnable(read_result(div_index)(bank_index)(way_index), RegNext(read_en))
5493eeae490SMaxpicca-Li      }
550144422dcSMaxpicca-Li    }
5511f0e2dc7SJiawei Lin  }
5521f0e2dc7SJiawei Lin
55304665835SMaxpicca-Li  val data_read_oh = WireInit(VecInit(Seq.fill(DCacheSetDiv * DCacheBanks * DCacheWays)(0.U(1.W))))
55404665835SMaxpicca-Li  for(div_index <- 0 until DCacheSetDiv){
55504665835SMaxpicca-Li    for (bank_index <- 0 until DCacheBanks) {
55604665835SMaxpicca-Li      for (way_index <- 0 until DCacheWays) {
5574a0e27ecSYanqin Li        data_read_oh(div_index *  DCacheBanks * DCacheWays + bank_index * DCacheWays + way_index) := data_banks(div_index)(bank_index)(way_index).io.r.en
55804665835SMaxpicca-Li      }
55904665835SMaxpicca-Li    }
56004665835SMaxpicca-Li  }
56104665835SMaxpicca-Li  XSPerfAccumulate("data_read_counter", PopCount(Cat(data_read_oh)))
56204665835SMaxpicca-Li
563026615fcSWilliam Wang  // read result: expose banked read result
564d4564868Sweiding liu  // TODO: clock gate
565144422dcSMaxpicca-Li  (0 until LoadPipelineWidth).map(i => {
5663eeae490SMaxpicca-Li    // io.read_resp(i) := read_result(RegNext(bank_addrs(i)))(RegNext(OHToUInt(way_en(i))))
5674a0e27ecSYanqin Li    val r_read_fire = RegNext(io.read(i).fire)
568d4564868Sweiding liu    val r_div_addr  = RegEnable(div_addrs(i), io.read(i).fire)
569d4564868Sweiding liu    val r_bank_addr = RegEnable(bank_addrs(i), io.read(i).fire)
570d4564868Sweiding liu    val r_way_addr  = RegNext(OHToUInt(way_en(i)))
5713eeae490SMaxpicca-Li    val rr_read_fire = RegNext(RegNext(io.read(i).fire))
5724a0e27ecSYanqin Li    val rr_div_addr = RegEnable(RegEnable(div_addrs(i), io.read(i).fire), r_read_fire)
5734a0e27ecSYanqin Li    val rr_bank_addr = RegEnable(RegEnable(bank_addrs(i), io.read(i).fire), r_read_fire)
5744a0e27ecSYanqin Li    val rr_way_addr = RegEnable(RegEnable(OHToUInt(way_en(i)), io.read(i).fire), r_read_fire)
575cdbff57cSHaoyuan Feng    (0 until VLEN/DCacheSRAMRowBits).map( j =>{
576d4564868Sweiding liu      io.read_resp(i)(j) := read_result(r_div_addr)(r_bank_addr(j))(r_way_addr)
577026615fcSWilliam Wang      // error detection
578026615fcSWilliam Wang      // normal read ports
579cdbff57cSHaoyuan Feng      io.read_error_delayed(i)(j) := rr_read_fire && read_error_delayed_result(rr_div_addr)(rr_bank_addr(j))(rr_way_addr) && !RegNext(io.bank_conflict_slow(i))
580cdbff57cSHaoyuan Feng    })
5811f0e2dc7SJiawei Lin  })
5823eeae490SMaxpicca-Li
583026615fcSWilliam Wang  // readline port
58498d2aaa1Scz4e  val readline_error_delayed = Wire(Vec(DCacheBanks, Bool()))
58598d2aaa1Scz4e  val readline_r_way_addr = RegEnable(OHToUInt(io.readline.bits.way_en), io.readline.valid)
58698d2aaa1Scz4e  val readline_rr_way_addr = RegEnable(readline_r_way_addr, RegNext(io.readline.valid))
58798d2aaa1Scz4e  val readline_r_div_addr = RegEnable(line_div_addr, io.readline.valid)
58898d2aaa1Scz4e  val readline_rr_div_addr = RegEnable(readline_r_div_addr, RegNext(io.readline.valid))
5893eeae490SMaxpicca-Li  (0 until DCacheBanks).map(i => {
59098d2aaa1Scz4e    io.readline_resp(i) := read_result(readline_r_div_addr)(i)(readline_r_way_addr)
59198d2aaa1Scz4e    readline_error_delayed(i) := read_result(readline_rr_div_addr)(i)(readline_rr_way_addr).error_delayed
5923eeae490SMaxpicca-Li  })
59398d2aaa1Scz4e  io.readline_error_delayed := RegNext(RegNext(io.readline.fire)) && readline_error_delayed.asUInt.orR
5941f0e2dc7SJiawei Lin
5951f0e2dc7SJiawei Lin  // write data_banks & ecc_banks
5963eeae490SMaxpicca-Li  for (div_index <- 0 until DCacheSetDiv) {
5971f0e2dc7SJiawei Lin    for (bank_index <- 0 until DCacheBanks) {
598144422dcSMaxpicca-Li      for (way_index <- 0 until DCacheWays) {
5991f0e2dc7SJiawei Lin        // data write
6003eeae490SMaxpicca-Li        val wen_reg = write_bank_mask_reg(bank_index) &&
6013eeae490SMaxpicca-Li          write_valid_dup_reg(bank_index) &&
6023eeae490SMaxpicca-Li          write_div_addr_dup_reg(bank_index) === div_index.U &&
6033eeae490SMaxpicca-Li          write_wayen_dup_reg(bank_index)(way_index)
604b34797bcScz4e        val write_ecc_reg = RegEnable(getECCFromEncWord(cacheParams.dataCode.encode(io.write.bits.data(bank_index))), io.write.valid)
6053eeae490SMaxpicca-Li        val data_bank = data_banks(div_index)(bank_index)(way_index)
6063eeae490SMaxpicca-Li        data_bank.io.w.en := wen_reg
6073eeae490SMaxpicca-Li        data_bank.io.w.addr := write_set_addr_dup_reg(bank_index)
608b34797bcScz4e        data_bank.io.w.data := asECCData(write_ecc_reg, write_data_reg(bank_index))
6091f0e2dc7SJiawei Lin      }
610144422dcSMaxpicca-Li    }
6113eeae490SMaxpicca-Li  }
6121f0e2dc7SJiawei Lin
613144422dcSMaxpicca-Li  val tableName =  "BankConflict" + p(XSCoreParamsKey).HartId.toString
614144422dcSMaxpicca-Li  val siteName = "BankedDataArray" + p(XSCoreParamsKey).HartId.toString
615144422dcSMaxpicca-Li  val bankConflictTable = ChiselDB.createTable(tableName, new BankConflictDB)
616144422dcSMaxpicca-Li  val bankConflictData = Wire(new BankConflictDB)
617144422dcSMaxpicca-Li  for (i <- 0 until LoadPipelineWidth) {
618144422dcSMaxpicca-Li    bankConflictData.set_index(i) := set_addrs(i)
619144422dcSMaxpicca-Li    bankConflictData.addr(i) := io.read(i).bits.addr
620144422dcSMaxpicca-Li  }
621144422dcSMaxpicca-Li
622144422dcSMaxpicca-Li  // FIXME: rr_bank_conflict(0)(1) no generalization
623144422dcSMaxpicca-Li  when(rr_bank_conflict(0)(1)) {
624cdbff57cSHaoyuan Feng    (0 until (VLEN/DCacheSRAMRowBits)).map(i => {
625cdbff57cSHaoyuan Feng      bankConflictData.bank_index(i) := bank_addrs(0)(i)
626cdbff57cSHaoyuan Feng    })
627144422dcSMaxpicca-Li    bankConflictData.way_index  := OHToUInt(way_en(0))
62813f2ff1cSMaxpicca-Li    bankConflictData.fake_rr_bank_conflict := set_addrs(0) === set_addrs(1) && div_addrs(0) === div_addrs(1)
629144422dcSMaxpicca-Li  }.otherwise {
630cdbff57cSHaoyuan Feng    (0 until (VLEN/DCacheSRAMRowBits)).map(i => {
631cdbff57cSHaoyuan Feng      bankConflictData.bank_index(i) := 0.U
632cdbff57cSHaoyuan Feng    })
633144422dcSMaxpicca-Li    bankConflictData.way_index := 0.U
634144422dcSMaxpicca-Li    bankConflictData.fake_rr_bank_conflict := false.B
635144422dcSMaxpicca-Li  }
636144422dcSMaxpicca-Li
637c686adcdSYinan Xu  val isWriteBankConflictTable = Constantin.createRecord(s"isWriteBankConflictTable${p(XSCoreParamsKey).HartId}")
638144422dcSMaxpicca-Li  bankConflictTable.log(
639144422dcSMaxpicca-Li    data = bankConflictData,
640da3bf434SMaxpicca-Li    en = isWriteBankConflictTable.orR && rr_bank_conflict(0)(1),
641144422dcSMaxpicca-Li    site = siteName,
642144422dcSMaxpicca-Li    clock = clock,
643144422dcSMaxpicca-Li    reset = reset
644144422dcSMaxpicca-Li  )
645144422dcSMaxpicca-Li
646144422dcSMaxpicca-Li  (1 until LoadPipelineWidth).foreach(y => (0 until y).foreach(x =>
64704665835SMaxpicca-Li    XSPerfAccumulate(s"data_array_fake_rr_bank_conflict_${x}_${y}", rr_bank_conflict(x)(y) && set_addrs(x)===set_addrs(y) && div_addrs(x) === div_addrs(y))
648144422dcSMaxpicca-Li  ))
649144422dcSMaxpicca-Li
6508ffb12e4SAnzo  if (backendParams.debugEn){
6518ffb12e4SAnzo    load_req_with_bank_conflict.map(dontTouch(_))
6528ffb12e4SAnzo    dontTouch(read_result)
6538ffb12e4SAnzo    dontTouch(read_error_delayed_result)
6548ffb12e4SAnzo  }
6551f0e2dc7SJiawei Lin}
6567dbf3a33SMaxpicca-Li
6577dbf3a33SMaxpicca-Li// the smallest access unit is bank
6587dbf3a33SMaxpicca-Liclass BankedDataArray(implicit p: Parameters) extends AbstractBankedDataArray {
6597dbf3a33SMaxpicca-Li  println("  DCacheType: BankedDataArray")
6607dbf3a33SMaxpicca-Li  val ReduceReadlineConflict = false
6617dbf3a33SMaxpicca-Li
6627dbf3a33SMaxpicca-Li  io.write.ready := true.B
6637dbf3a33SMaxpicca-Li  io.write_dup.foreach(_.ready := true.B)
6647dbf3a33SMaxpicca-Li
665ebe07d61S梁森 Liang Sen  val data_banks = Seq.tabulate(DCacheSetDiv, DCacheBanks)({(k, i) => Module(new DataSRAMBank(i))})
666ebe07d61S梁森 Liang Sen  val mbistPl = MbistPipeline.PlaceMbistPipeline(1, s"MbistPipeDCacheData", hasMbist)
667ebe07d61S梁森 Liang Sen  val mbistSramPorts = mbistPl.map(pl => Seq.tabulate(DCacheSetDiv, DCacheBanks, DCacheWays) ({ (i, j, k) =>
668ebe07d61S梁森 Liang Sen    pl.toSRAM(i * DCacheBanks * DCacheWays + j * DCacheWays + k)
669ebe07d61S梁森 Liang Sen  }))
6703eeae490SMaxpicca-Li  data_banks.map(_.map(_.dump()))
6717dbf3a33SMaxpicca-Li
6727dbf3a33SMaxpicca-Li  val way_en = Wire(Vec(LoadPipelineWidth, io.read(0).bits.way_en.cloneType))
6737dbf3a33SMaxpicca-Li  val set_addrs = Wire(Vec(LoadPipelineWidth, UInt()))
674fa5e530dScz4e  val set_addrs_dup = Wire(Vec(LoadPipelineWidth, UInt()))
6753eeae490SMaxpicca-Li  val div_addrs = Wire(Vec(LoadPipelineWidth, UInt()))
676fa5e530dScz4e  val div_addrs_dup = Wire(Vec(LoadPipelineWidth, UInt()))
677cdbff57cSHaoyuan Feng  val bank_addrs = Wire(Vec(LoadPipelineWidth, Vec(VLEN/DCacheSRAMRowBits, UInt())))
678fa5e530dScz4e  val bank_addrs_dup = Wire(Vec(LoadPipelineWidth, Vec(VLEN/DCacheSRAMRowBits, UInt())))
67913f2ff1cSMaxpicca-Li  val way_en_reg = Wire(Vec(LoadPipelineWidth, io.read(0).bits.way_en.cloneType))
68013f2ff1cSMaxpicca-Li  val set_addrs_reg = Wire(Vec(LoadPipelineWidth, UInt()))
681fa5e530dScz4e  val set_addrs_dup_reg = Wire(Vec(LoadPipelineWidth, UInt()))
6827dbf3a33SMaxpicca-Li
6833eeae490SMaxpicca-Li  val line_set_addr = addr_to_dcache_div_set(io.readline.bits.addr)
6843eeae490SMaxpicca-Li  val line_div_addr = addr_to_dcache_div(io.readline.bits.addr)
6853eeae490SMaxpicca-Li  val line_way_en = io.readline.bits.way_en
6863eeae490SMaxpicca-Li
6874a0e27ecSYanqin Li  val write_bank_mask_reg = RegEnable(io.write.bits.wmask, io.write.valid)
6885adc4829SYanqin Li  val write_data_reg = RegEnable(io.write.bits.data, io.write.valid)
6893eeae490SMaxpicca-Li  val write_valid_reg = RegNext(io.write.valid)
6903eeae490SMaxpicca-Li  val write_valid_dup_reg = io.write_dup.map(x => RegNext(x.valid))
6914a0e27ecSYanqin Li  val write_wayen_dup_reg = io.write_dup.map(x => RegEnable(x.bits.way_en, x.valid))
6925adc4829SYanqin Li  val write_set_addr_dup_reg = io.write_dup.map(x => RegEnable(addr_to_dcache_div_set(x.bits.addr), x.valid))
6935adc4829SYanqin Li  val write_div_addr_dup_reg = io.write_dup.map(x => RegEnable(addr_to_dcache_div(x.bits.addr), x.valid))
6943eeae490SMaxpicca-Li
6957dbf3a33SMaxpicca-Li  // read data_banks and ecc_banks
6967dbf3a33SMaxpicca-Li  // for single port SRAM, do not allow read and write in the same cycle
6977dbf3a33SMaxpicca-Li  val rwhazard = RegNext(io.write.valid)
6987dbf3a33SMaxpicca-Li  val rrhazard = false.B // io.readline.valid
6997dbf3a33SMaxpicca-Li  (0 until LoadPipelineWidth).map(rport_index => {
7003eeae490SMaxpicca-Li    div_addrs(rport_index) := addr_to_dcache_div(io.read(rport_index).bits.addr)
701fa5e530dScz4e    div_addrs_dup(rport_index) := addr_to_dcache_div(io.read(rport_index).bits.addr_dup)
702cdbff57cSHaoyuan Feng    bank_addrs(rport_index)(0) := addr_to_dcache_bank(io.read(rport_index).bits.addr)
70308b0bc30Shappy-lx    bank_addrs(rport_index)(1) := Mux(io.is128Req(rport_index), bank_addrs(rport_index)(0) + 1.U, bank_addrs(rport_index)(0))
704fa5e530dScz4e    bank_addrs_dup(rport_index)(0) := addr_to_dcache_bank(io.read(rport_index).bits.addr_dup)
705fa5e530dScz4e    bank_addrs_dup(rport_index)(1) := Mux(io.is128Req(rport_index), bank_addrs_dup(rport_index)(0) + 1.U, bank_addrs_dup(rport_index)(0))
70613f2ff1cSMaxpicca-Li    set_addrs(rport_index) := addr_to_dcache_div_set(io.read(rport_index).bits.addr)
707fa5e530dScz4e    set_addrs_dup(rport_index) := addr_to_dcache_div_set(io.read(rport_index).bits.addr_dup)
7085adc4829SYanqin Li    set_addrs_reg(rport_index) := RegEnable(addr_to_dcache_div_set(io.read(rport_index).bits.addr), io.read(rport_index).valid)
709fa5e530dScz4e    set_addrs_dup_reg(rport_index) := RegEnable(addr_to_dcache_div_set(io.read(rport_index).bits.addr_dup), io.read(rport_index).valid)
7107dbf3a33SMaxpicca-Li
7117dbf3a33SMaxpicca-Li    // use way_en to select a way after data read out
712935edac4STang Haojin    assert(!(RegNext(io.read(rport_index).fire && PopCount(io.read(rport_index).bits.way_en) > 1.U)))
7137dbf3a33SMaxpicca-Li    way_en(rport_index) := io.read(rport_index).bits.way_en
7145adc4829SYanqin Li    way_en_reg(rport_index) := RegEnable(io.read(rport_index).bits.way_en, io.read(rport_index).valid)
7157dbf3a33SMaxpicca-Li  })
7167dbf3a33SMaxpicca-Li
7177dbf3a33SMaxpicca-Li  // read each bank, get bank result
7188ffb12e4SAnzo  val rr_bank_conflict = Seq.tabulate(LoadPipelineWidth)(x => Seq.tabulate(LoadPipelineWidth)(y => {
7198ffb12e4SAnzo    if (x == y) {
7208ffb12e4SAnzo      false.B
7218ffb12e4SAnzo    } else {
7223eeae490SMaxpicca-Li      io.read(x).valid && io.read(y).valid &&
7233eeae490SMaxpicca-Li      div_addrs(x) === div_addrs(y) &&
7248ffb12e4SAnzo      (io.read(x).bits.bankMask & io.read(y).bits.bankMask) =/= 0.U &&
7258ffb12e4SAnzo      set_addrs(x) =/= set_addrs(y)
7268ffb12e4SAnzo    }
7278ffb12e4SAnzo  }
7287dbf3a33SMaxpicca-Li  ))
7298ffb12e4SAnzo
7308ffb12e4SAnzo  val load_req_with_bank_conflict = rr_bank_conflict.map(_.reduce(_ || _))
7318ffb12e4SAnzo  val load_req_valid = io.read.map(_.valid)
7328ffb12e4SAnzo  val load_req_lqIdx = io.read.map(_.bits.lqIdx)
7338ffb12e4SAnzo  val load_req_index = (0 until LoadPipelineWidth).map(_.asUInt)
7348ffb12e4SAnzo
735c5a867ffSAnzo  val load_req_bank_conflict_selcet = selcetOldestPort(load_req_with_bank_conflict, load_req_lqIdx, load_req_index)
7368ffb12e4SAnzo  val load_req_bank_select_port  = UIntToOH(load_req_bank_conflict_selcet._2).asBools
7378ffb12e4SAnzo
7388ffb12e4SAnzo  val rr_bank_conflict_oldest = (0 until LoadPipelineWidth).map(i =>
7398ffb12e4SAnzo    !load_req_bank_select_port(i) && load_req_with_bank_conflict(i)
7408ffb12e4SAnzo  )
7418ffb12e4SAnzo
7427dbf3a33SMaxpicca-Li  val rrl_bank_conflict = Wire(Vec(LoadPipelineWidth, Bool()))
7437dbf3a33SMaxpicca-Li  val rrl_bank_conflict_intend = Wire(Vec(LoadPipelineWidth, Bool()))
7443eeae490SMaxpicca-Li  (0 until LoadPipelineWidth).foreach { i =>
745cdbff57cSHaoyuan Feng    val judge = if (ReduceReadlineConflict) io.read(i).valid && (io.readline.bits.rmask & io.read(i).bits.bankMask) =/= 0.U && div_addrs(i) === line_div_addr
7463eeae490SMaxpicca-Li                else io.read(i).valid && div_addrs(i)===line_div_addr
7473eeae490SMaxpicca-Li    rrl_bank_conflict(i) := judge && io.readline.valid
7483eeae490SMaxpicca-Li    rrl_bank_conflict_intend(i) := judge && io.readline_intend
7497dbf3a33SMaxpicca-Li  }
7503eeae490SMaxpicca-Li  val wr_bank_conflict = Seq.tabulate(LoadPipelineWidth)(x =>
751cdbff57cSHaoyuan Feng    io.read(x).valid &&
752cdbff57cSHaoyuan Feng    write_valid_reg &&
753cdbff57cSHaoyuan Feng    div_addrs(x) === write_div_addr_dup_reg.head &&
754cdbff57cSHaoyuan Feng    (write_bank_mask_reg(bank_addrs(x)(0)) || write_bank_mask_reg(bank_addrs(x)(1)) && io.is128Req(x))
7553eeae490SMaxpicca-Li  )
7563eeae490SMaxpicca-Li  val wrl_bank_conflict = io.readline.valid && write_valid_reg && line_div_addr === write_div_addr_dup_reg.head
7573eeae490SMaxpicca-Li  // ready
7583eeae490SMaxpicca-Li  io.readline.ready := !(wrl_bank_conflict)
7593eeae490SMaxpicca-Li  io.read.zipWithIndex.map{case(x, i) => x.ready := !(wr_bank_conflict(i) || rrhazard)}
7607dbf3a33SMaxpicca-Li
7617dbf3a33SMaxpicca-Li  val perf_multi_read = PopCount(io.read.map(_.valid)) >= 2.U
7627dbf3a33SMaxpicca-Li  (0 until LoadPipelineWidth).foreach(i => {
76313f2ff1cSMaxpicca-Li    // remove fake rr_bank_conflict situation in s2
76413f2ff1cSMaxpicca-Li    val real_other_bank_conflict_reg = RegNext(wr_bank_conflict(i) || rrl_bank_conflict(i))
7658ffb12e4SAnzo    val real_rr_bank_conflict_reg = RegNext(rr_bank_conflict_oldest(i))
76613f2ff1cSMaxpicca-Li    io.bank_conflict_slow(i) := real_other_bank_conflict_reg || real_rr_bank_conflict_reg
76713f2ff1cSMaxpicca-Li
76813f2ff1cSMaxpicca-Li    // get result in s1
7693eeae490SMaxpicca-Li    io.disable_ld_fast_wakeup(i) := wr_bank_conflict(i) || rrl_bank_conflict_intend(i) ||
7707dbf3a33SMaxpicca-Li      (if (i == 0) 0.B else (0 until i).map(rr_bank_conflict(_)(i)).reduce(_ || _))
7717dbf3a33SMaxpicca-Li  })
7727dbf3a33SMaxpicca-Li  XSPerfAccumulate("data_array_multi_read", perf_multi_read)
7737dbf3a33SMaxpicca-Li  (1 until LoadPipelineWidth).foreach(y => (0 until y).foreach(x =>
7747dbf3a33SMaxpicca-Li    XSPerfAccumulate(s"data_array_rr_bank_conflict_${x}_${y}", rr_bank_conflict(x)(y))
7757dbf3a33SMaxpicca-Li  ))
7767dbf3a33SMaxpicca-Li  (0 until LoadPipelineWidth).foreach(i => {
7777dbf3a33SMaxpicca-Li    XSPerfAccumulate(s"data_array_rrl_bank_conflict_${i}", rrl_bank_conflict(i))
7783eeae490SMaxpicca-Li    XSPerfAccumulate(s"data_array_rw_bank_conflict_${i}", wr_bank_conflict(i))
7797dbf3a33SMaxpicca-Li    XSPerfAccumulate(s"data_array_read_${i}", io.read(i).valid)
7807dbf3a33SMaxpicca-Li  })
7817dbf3a33SMaxpicca-Li  XSPerfAccumulate("data_array_access_total", PopCount(io.read.map(_.valid)))
7827dbf3a33SMaxpicca-Li  XSPerfAccumulate("data_array_read_line", io.readline.valid)
7837dbf3a33SMaxpicca-Li  XSPerfAccumulate("data_array_write", io.write.valid)
7847dbf3a33SMaxpicca-Li
7857bd3dbddShappy-lx  val bank_result = Wire(Vec(DCacheSetDiv, Vec(DCacheBanks, Vec(DCacheWays, new L1BankedDataReadResult()))))
7867bd3dbddShappy-lx  val bank_result_delayed = Wire(Vec(DCacheSetDiv, Vec(DCacheBanks, Vec(DCacheWays, new L1BankedDataReadResult()))))
7877bd3dbddShappy-lx  val read_bank_error_delayed = Wire(Vec(DCacheSetDiv, Vec(DCacheBanks, Vec(DCacheWays, Bool()))))
7888ffb12e4SAnzo
78972dab974Scz4e  val pseudo_data_toggle_mask = io.pseudo_error.bits.map {
79072dab974Scz4e    case bank =>
79172dab974Scz4e      Mux(io.pseudo_error.valid && bank.valid, bank.mask, 0.U)
79272dab974Scz4e  }
79372dab974Scz4e  val readline_hit = io.readline.fire &&
79472dab974Scz4e                     (io.readline.bits.rmask & VecInit(io.pseudo_error.bits.map(_.valid)).asUInt).orR
79572dab974Scz4e  val readbank_hit = io.read.zip(bank_addrs.zip(io.is128Req)).zipWithIndex.map {
79672dab974Scz4e                          case ((read, (bank_addr, is128Req)), i) =>
79772dab974Scz4e                            val error_bank0 = io.pseudo_error.bits(bank_addr(0))
79872dab974Scz4e                            val error_bank1 = io.pseudo_error.bits(bank_addr(1))
79972dab974Scz4e                            read.fire && (error_bank0.valid || error_bank1.valid && is128Req) && !io.bank_conflict_slow(i)
80072dab974Scz4e                      }.reduce(_|_)
80172dab974Scz4e  io.pseudo_error.ready := RegNext(readline_hit || readbank_hit)
80272dab974Scz4e
8033eeae490SMaxpicca-Li  for (div_index <- 0 until DCacheSetDiv) {
8047dbf3a33SMaxpicca-Li    for (bank_index <- 0 until DCacheBanks) {
8057dbf3a33SMaxpicca-Li      //     Set Addr & Read Way Mask
8067dbf3a33SMaxpicca-Li      //
8077dbf3a33SMaxpicca-Li      //    Pipe 0   ....  Pipe (n-1)
8087dbf3a33SMaxpicca-Li      //      +      ....     +
8097dbf3a33SMaxpicca-Li      //      |      ....     |
8107dbf3a33SMaxpicca-Li      // +----+---------------+-----+
8117dbf3a33SMaxpicca-Li      //  X                        X
8127dbf3a33SMaxpicca-Li      //   X                      +------+ Bank Addr Match
8137dbf3a33SMaxpicca-Li      //    +---------+----------+
8147dbf3a33SMaxpicca-Li      //              |
8157dbf3a33SMaxpicca-Li      //     +--------+--------+
8167dbf3a33SMaxpicca-Li      //     |    Data Bank    |
8177dbf3a33SMaxpicca-Li      //     +-----------------+
8187dbf3a33SMaxpicca-Li      val bank_addr_matchs = WireInit(VecInit(List.tabulate(LoadPipelineWidth)(i => {
8198ffb12e4SAnzo        io.read(i).valid && div_addrs(i) === div_index.U && (bank_addrs(i)(0) === bank_index.U || bank_addrs(i)(1) === bank_index.U && io.is128Req(i)) &&
8208ffb12e4SAnzo          !rr_bank_conflict_oldest(i)
8217dbf3a33SMaxpicca-Li      })))
822fa5e530dScz4e      val bank_addr_matchs_dup = WireInit(VecInit(List.tabulate(LoadPipelineWidth)(i => {
823fa5e530dScz4e        io.read(i).valid && div_addrs_dup(i) === div_index.U && (bank_addrs_dup(i)(0) === bank_index.U || bank_addrs_dup(i)(1) === bank_index.U && io.is128Req(i)) &&
824fa5e530dScz4e          !rr_bank_conflict_oldest(i)
825fa5e530dScz4e      })))
8267dbf3a33SMaxpicca-Li      val readline_match = Wire(Bool())
8277dbf3a33SMaxpicca-Li      if (ReduceReadlineConflict) {
8283eeae490SMaxpicca-Li        readline_match := io.readline.valid && io.readline.bits.rmask(bank_index) && line_div_addr === div_index.U
8297dbf3a33SMaxpicca-Li      } else {
8303eeae490SMaxpicca-Li        readline_match := io.readline.valid && line_div_addr === div_index.U
8317dbf3a33SMaxpicca-Li      }
8327bd3dbddShappy-lx
8337dbf3a33SMaxpicca-Li      val bank_set_addr = Mux(readline_match,
8343eeae490SMaxpicca-Li        line_set_addr,
8357dbf3a33SMaxpicca-Li        PriorityMux(Seq.tabulate(LoadPipelineWidth)(i => bank_addr_matchs(i) -> set_addrs(i)))
8367dbf3a33SMaxpicca-Li      )
837fa5e530dScz4e      val bank_set_addr_dup = Mux(readline_match,
838fa5e530dScz4e        line_set_addr,
839fa5e530dScz4e        PriorityMux(Seq.tabulate(LoadPipelineWidth)(i => bank_addr_matchs_dup(i) -> set_addrs_dup(i)))
840fa5e530dScz4e      )
8417dbf3a33SMaxpicca-Li      val read_enable = bank_addr_matchs.asUInt.orR || readline_match
8427dbf3a33SMaxpicca-Li
8437dbf3a33SMaxpicca-Li      // read raw data
8443eeae490SMaxpicca-Li      val data_bank = data_banks(div_index)(bank_index)
8457dbf3a33SMaxpicca-Li      data_bank.io.r.en := read_enable
846fa5e530dScz4e
847fa5e530dScz4e      if (DuplicatedQueryBankSeq.contains(bank_index)) {
848fa5e530dScz4e        data_bank.io.r.addr := bank_set_addr_dup
849fa5e530dScz4e      } else {
8507dbf3a33SMaxpicca-Li        data_bank.io.r.addr := bank_set_addr
851fa5e530dScz4e      }
8527bd3dbddShappy-lx      for (way_index <- 0 until DCacheWays) {
853ebe07d61S梁森 Liang Sen        val mbistAck = mbistSramPorts.map(_(div_index)(bank_index)(way_index).ack).getOrElse(false.B)
854b34797bcScz4e        bank_result(div_index)(bank_index)(way_index).ecc := getECCFromEncWord(data_bank.io.r.data(way_index))
855ebe07d61S梁森 Liang Sen        bank_result(div_index)(bank_index)(way_index).raw_data := getDataFromEncWord(data_bank.io.r.data(way_index)) ^ Mux(mbistAck, 0.U, pseudo_data_toggle_mask(bank_index))
8567dbf3a33SMaxpicca-Li
857b34797bcScz4e        if (EnableDataEcc) {
8587bd3dbddShappy-lx          val ecc_data = bank_result(div_index)(bank_index)(way_index).asECCData()
8597dbf3a33SMaxpicca-Li          val ecc_data_delayed = RegEnable(ecc_data, RegNext(read_enable))
8607bd3dbddShappy-lx          bank_result(div_index)(bank_index)(way_index).error_delayed := dcacheParameters.dataCode.decode(ecc_data_delayed).error
8617bd3dbddShappy-lx          read_bank_error_delayed(div_index)(bank_index)(way_index) := bank_result(div_index)(bank_index)(way_index).error_delayed
862b34797bcScz4e        } else {
8637bd3dbddShappy-lx          bank_result(div_index)(bank_index)(way_index).error_delayed := false.B
8647bd3dbddShappy-lx          read_bank_error_delayed(div_index)(bank_index)(way_index) := false.B
8657bd3dbddShappy-lx        }
866b34797bcScz4e        bank_result_delayed(div_index)(bank_index)(way_index) := RegEnable(bank_result(div_index)(bank_index)(way_index), RegNext(read_enable))
867cd2ff98bShappy-lx      }
8683eeae490SMaxpicca-Li    }
8697dbf3a33SMaxpicca-Li  }
8707dbf3a33SMaxpicca-Li
87104665835SMaxpicca-Li  val data_read_oh = WireInit(VecInit(Seq.fill(DCacheSetDiv)(0.U(XLEN.W))))
87204665835SMaxpicca-Li  for (div_index <- 0 until DCacheSetDiv){
87304665835SMaxpicca-Li    val temp = WireInit(VecInit(Seq.fill(DCacheBanks)(0.U(XLEN.W))))
87404665835SMaxpicca-Li    for (bank_index <- 0 until DCacheBanks) {
87504665835SMaxpicca-Li      temp(bank_index) := PopCount(Fill(DCacheWays, data_banks(div_index)(bank_index).io.r.en.asUInt))
87604665835SMaxpicca-Li    }
87704665835SMaxpicca-Li    data_read_oh(div_index) := temp.reduce(_ + _)
87804665835SMaxpicca-Li  }
87904665835SMaxpicca-Li  XSPerfAccumulate("data_read_counter", data_read_oh.foldLeft(0.U)(_ + _))
88004665835SMaxpicca-Li
8817dbf3a33SMaxpicca-Li  (0 until LoadPipelineWidth).map(i => {
8827bd3dbddShappy-lx    // 1 cycle after read fire(load s2)
8835adc4829SYanqin Li    val r_read_fire = RegNext(io.read(i).fire)
884d4564868Sweiding liu    val r_div_addr = RegEnable(div_addrs(i), io.read(i).fire)
885d4564868Sweiding liu    val r_bank_addr = RegEnable(bank_addrs(i), io.read(i).fire)
8867bd3dbddShappy-lx    val r_way_addr = RegEnable(OHToUInt(way_en(i)), io.read(i).fire)
8877bd3dbddShappy-lx    // 2 cycles after read fire(load s3)
8885adc4829SYanqin Li    val rr_read_fire = RegNext(r_read_fire)
8895adc4829SYanqin Li    val rr_div_addr = RegEnable(RegEnable(div_addrs(i), io.read(i).fire), r_read_fire)
8905adc4829SYanqin Li    val rr_bank_addr = RegEnable(RegEnable(bank_addrs(i), io.read(i).fire), r_read_fire)
8915adc4829SYanqin Li    val rr_way_addr = RegEnable(RegEnable(OHToUInt(way_en(i)), io.read(i).fire), r_read_fire)
892cdbff57cSHaoyuan Feng    (0 until VLEN/DCacheSRAMRowBits).map( j =>{
8937bd3dbddShappy-lx      io.read_resp(i)(j)          := bank_result(r_div_addr)(r_bank_addr(j))(r_way_addr)
8943eeae490SMaxpicca-Li      // error detection
8957bd3dbddShappy-lx      io.read_error_delayed(i)(j) := rr_read_fire && read_bank_error_delayed(rr_div_addr)(rr_bank_addr(j))(rr_way_addr) && !RegNext(io.bank_conflict_slow(i))
896cdbff57cSHaoyuan Feng    })
8977dbf3a33SMaxpicca-Li  })
8987dbf3a33SMaxpicca-Li
8993eeae490SMaxpicca-Li  // read result: expose banked read result
900ebe07d61S梁森 Liang Sen  private val mbist_r_way = OHToUInt(mbistSramPorts.map(_.flatMap(_.map(w => Cat(w.map(_.re).reverse))).reduce(_ | _)).getOrElse(0.U(DCacheWays.W)))
901ebe07d61S梁森 Liang Sen  private val mbist_r_div = OHToUInt(mbistSramPorts.map(_.map(d => Cat(d.flatMap(w => w.map(_.re))).orR)).getOrElse(Seq.fill(DCacheSetDiv)(false.B)))
902ebe07d61S梁森 Liang Sen  private val mbist_ack = mbistPl.map(_.mbist.ack).getOrElse(false.B)
903ebe07d61S梁森 Liang Sen
90498d2aaa1Scz4e  val readline_error_delayed = Wire(Vec(DCacheBanks, Bool()))
905ebe07d61S梁森 Liang Sen  val readline_r_way_addr = RegEnable(Mux(mbist_ack, mbist_r_way, OHToUInt(io.readline.bits.way_en)), io.readline.valid | mbist_ack)
90698d2aaa1Scz4e  val readline_rr_way_addr = RegEnable(readline_r_way_addr, RegNext(io.readline.valid))
907ebe07d61S梁森 Liang Sen  val readline_r_div_addr = RegEnable(Mux(mbist_ack, mbist_r_div, line_div_addr), io.readline.valid | mbist_ack)
90898d2aaa1Scz4e  val readline_rr_div_addr = RegEnable(readline_r_div_addr, RegNext(io.readline.valid))
909ebe07d61S梁森 Liang Sen  val readline_resp = Wire(io.readline_resp.cloneType)
910ebe07d61S梁森 Liang Sen  (0 until DCacheBanks).foreach(i => {
911ebe07d61S梁森 Liang Sen    mbistSramPorts.foreach(_.foreach(_(i).foreach(_.rdata := Cat(io.readline_resp(i).ecc, io.readline_resp(i).raw_data))))
912ebe07d61S梁森 Liang Sen    readline_resp(i) := Mux(
913ebe07d61S梁森 Liang Sen      io.readline_can_go | mbist_ack,
914ebe07d61S梁森 Liang Sen      bank_result(readline_r_div_addr)(i)(readline_r_way_addr),
915ebe07d61S梁森 Liang Sen      RegEnable(readline_resp(i), io.readline_stall | mbist_ack)
916ebe07d61S梁森 Liang Sen    )
91798d2aaa1Scz4e    readline_error_delayed(i) := bank_result(readline_rr_div_addr)(i)(readline_rr_way_addr).error_delayed
9187bd3dbddShappy-lx  })
919ebe07d61S梁森 Liang Sen  io.readline_resp := RegEnable(readline_resp, io.readline_can_resp | mbist_ack)
92098d2aaa1Scz4e  io.readline_error_delayed := RegNext(RegNext(io.readline.fire)) && readline_error_delayed.asUInt.orR
9217dbf3a33SMaxpicca-Li
9227dbf3a33SMaxpicca-Li  // write data_banks & ecc_banks
9233eeae490SMaxpicca-Li  for (div_index <- 0 until DCacheSetDiv) {
9247dbf3a33SMaxpicca-Li    for (bank_index <- 0 until DCacheBanks) {
9257dbf3a33SMaxpicca-Li      // data write
9263eeae490SMaxpicca-Li      val wen_reg = write_bank_mask_reg(bank_index) &&
9273eeae490SMaxpicca-Li        write_valid_dup_reg(bank_index) &&
9284a0e27ecSYanqin Li        write_div_addr_dup_reg(bank_index) === div_index.U && RegNext(io.write.valid)
929b34797bcScz4e      val write_ecc_reg = RegEnable(getECCFromEncWord(cacheParams.dataCode.encode(io.write.bits.data(bank_index))), io.write.valid)
9303eeae490SMaxpicca-Li      val data_bank = data_banks(div_index)(bank_index)
9313eeae490SMaxpicca-Li      data_bank.io.w.en := wen_reg
9323eeae490SMaxpicca-Li      data_bank.io.w.way_en := write_wayen_dup_reg(bank_index)
9333eeae490SMaxpicca-Li      data_bank.io.w.addr := write_set_addr_dup_reg(bank_index)
934b34797bcScz4e      data_bank.io.w.data := asECCData(write_ecc_reg, write_data_reg(bank_index))
9357dbf3a33SMaxpicca-Li    }
9363eeae490SMaxpicca-Li  }
9377dbf3a33SMaxpicca-Li
9387dbf3a33SMaxpicca-Li  val tableName = "BankConflict" + p(XSCoreParamsKey).HartId.toString
9397dbf3a33SMaxpicca-Li  val siteName = "BankedDataArray" + p(XSCoreParamsKey).HartId.toString
9407dbf3a33SMaxpicca-Li  val bankConflictTable = ChiselDB.createTable(tableName, new BankConflictDB)
9417dbf3a33SMaxpicca-Li  val bankConflictData = Wire(new BankConflictDB)
9427dbf3a33SMaxpicca-Li  for (i <- 0 until LoadPipelineWidth) {
9437dbf3a33SMaxpicca-Li    bankConflictData.set_index(i) := set_addrs(i)
9447dbf3a33SMaxpicca-Li    bankConflictData.addr(i) := io.read(i).bits.addr
9457dbf3a33SMaxpicca-Li  }
9467dbf3a33SMaxpicca-Li
9477dbf3a33SMaxpicca-Li  // FIXME: rr_bank_conflict(0)(1) no generalization
9487dbf3a33SMaxpicca-Li  when(rr_bank_conflict(0)(1)) {
949cdbff57cSHaoyuan Feng    (0 until (VLEN/DCacheSRAMRowBits)).map(i => {
950cdbff57cSHaoyuan Feng      bankConflictData.bank_index(i) := bank_addrs(0)(i)
951cdbff57cSHaoyuan Feng    })
9527dbf3a33SMaxpicca-Li    bankConflictData.way_index := OHToUInt(way_en(0))
95313f2ff1cSMaxpicca-Li    bankConflictData.fake_rr_bank_conflict := set_addrs(0) === set_addrs(1) && div_addrs(0) === div_addrs(1)
9547dbf3a33SMaxpicca-Li  }.otherwise {
955cdbff57cSHaoyuan Feng    (0 until (VLEN/DCacheSRAMRowBits)).map(i => {
956cdbff57cSHaoyuan Feng      bankConflictData.bank_index(i) := 0.U
957cdbff57cSHaoyuan Feng    })
9587dbf3a33SMaxpicca-Li    bankConflictData.way_index := 0.U
9597dbf3a33SMaxpicca-Li    bankConflictData.fake_rr_bank_conflict := false.B
9607dbf3a33SMaxpicca-Li  }
9617dbf3a33SMaxpicca-Li
962c686adcdSYinan Xu  val isWriteBankConflictTable = Constantin.createRecord(s"isWriteBankConflictTable${p(XSCoreParamsKey).HartId}")
9637dbf3a33SMaxpicca-Li  bankConflictTable.log(
9647dbf3a33SMaxpicca-Li    data = bankConflictData,
9657dbf3a33SMaxpicca-Li    en = isWriteBankConflictTable.orR && rr_bank_conflict(0)(1),
9667dbf3a33SMaxpicca-Li    site = siteName,
9677dbf3a33SMaxpicca-Li    clock = clock,
9687dbf3a33SMaxpicca-Li    reset = reset
9697dbf3a33SMaxpicca-Li  )
9707dbf3a33SMaxpicca-Li
9717dbf3a33SMaxpicca-Li  (1 until LoadPipelineWidth).foreach(y => (0 until y).foreach(x =>
97204665835SMaxpicca-Li    XSPerfAccumulate(s"data_array_fake_rr_bank_conflict_${x}_${y}", rr_bank_conflict(x)(y) && set_addrs(x) === set_addrs(y) && div_addrs(x) === div_addrs(y))
9737dbf3a33SMaxpicca-Li  ))
9747dbf3a33SMaxpicca-Li
9758ffb12e4SAnzo  if (backendParams.debugEn){
9768ffb12e4SAnzo    load_req_with_bank_conflict.map(dontTouch(_))
9778ffb12e4SAnzo    dontTouch(bank_result)
9788ffb12e4SAnzo    dontTouch(read_bank_error_delayed)
9798ffb12e4SAnzo  }
9807dbf3a33SMaxpicca-Li}
981