xref: /XiangShan/src/main/scala/xiangshan/cache/dcache/data/BankedDataArray.scala (revision 9473e04d5cab97eaf63add958b2392eec3d876a2)
1/***************************************************************************************
2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3* Copyright (c) 2020-2021 Peng Cheng Laboratory
4*
5* XiangShan is licensed under Mulan PSL v2.
6* You can use this software according to the terms and conditions of the Mulan PSL v2.
7* You may obtain a copy of Mulan PSL v2 at:
8*          http://license.coscl.org.cn/MulanPSL2
9*
10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*
14* See the Mulan PSL v2 for more details.
15***************************************************************************************/
16
17package xiangshan.cache
18
19import chipsalliance.rocketchip.config.Parameters
20import chisel3._
21import utils._
22import utility._
23import chisel3.util._
24import freechips.rocketchip.tilelink.{ClientMetadata, TLClientParameters, TLEdgeOut}
25import xiangshan.{L1CacheErrorInfo, XSCoreParamsKey}
26
27import scala.math.max
28
29class BankConflictDB(implicit p: Parameters) extends DCacheBundle{
30  val addr = Vec(LoadPipelineWidth, Bits(PAddrBits.W))
31  val set_index = Vec(LoadPipelineWidth, UInt((DCacheAboveIndexOffset - DCacheSetOffset).W))
32  val bank_index = UInt((DCacheSetOffset - DCacheBankOffset).W)
33  val way_index = UInt(wayBits.W)
34  val fake_rr_bank_conflict = Bool()
35}
36
37class L1BankedDataReadReq(implicit p: Parameters) extends DCacheBundle
38{
39  val way_en = Bits(DCacheWays.W)
40  val addr = Bits(PAddrBits.W)
41}
42
43class L1BankedDataReadLineReq(implicit p: Parameters) extends L1BankedDataReadReq
44{
45  val rmask = Bits(DCacheBanks.W)
46}
47
48// Now, we can write a cache-block in a single cycle
49class L1BankedDataWriteReq(implicit p: Parameters) extends L1BankedDataReadReq
50{
51  val wmask = Bits(DCacheBanks.W)
52  val data = Vec(DCacheBanks, Bits(DCacheSRAMRowBits.W))
53}
54
55// cache-block write request without data
56class L1BankedDataWriteReqCtrl(implicit p: Parameters) extends L1BankedDataReadReq
57
58class L1BankedDataReadResult(implicit p: Parameters) extends DCacheBundle
59{
60  // you can choose which bank to read to save power
61  val ecc = Bits(eccBits.W)
62  val raw_data = Bits(DCacheSRAMRowBits.W)
63  val error_delayed = Bool() // 1 cycle later than data resp
64
65  def asECCData() = {
66    Cat(ecc, raw_data)
67  }
68}
69
70class DataSRAMBankWriteReq(implicit p: Parameters) extends DCacheBundle {
71  val en = Bool()
72  val addr = UInt()
73  val way_en = UInt(DCacheWays.W)
74  val data = UInt(DCacheSRAMRowBits.W)
75}
76
77//                     Banked DCache Data
78// -----------------------------------------------------------------
79// | Bank0 | Bank1 | Bank2 | Bank3 | Bank4 | Bank5 | Bank6 | Bank7 |
80// -----------------------------------------------------------------
81// | Way0  | Way0  | Way0  | Way0  | Way0  | Way0  | Way0  | Way0  |
82// | Way1  | Way1  | Way1  | Way1  | Way1  | Way1  | Way1  | Way1  |
83// | ....  | ....  | ....  | ....  | ....  | ....  | ....  | ....  |
84// -----------------------------------------------------------------
85abstract class AbstractBankedDataArray(implicit p: Parameters) extends DCacheModule
86{
87  val ReadlinePortErrorIndex = LoadPipelineWidth
88  val io = IO(new DCacheBundle {
89    // load pipeline read word req
90    val read = Vec(LoadPipelineWidth, Flipped(DecoupledIO(new L1BankedDataReadReq)))
91    // main pipeline read / write line req
92    val readline_intend = Input(Bool())
93    val readline = Flipped(DecoupledIO(new L1BankedDataReadLineReq))
94    val write = Flipped(DecoupledIO(new L1BankedDataWriteReq))
95    val write_dup = Vec(DCacheBanks, Flipped(Decoupled(new L1BankedDataWriteReqCtrl)))
96    // data for readline and loadpipe
97    val readline_resp = Output(Vec(DCacheBanks, new L1BankedDataReadResult()))
98    val readline_error_delayed = Output(Bool())
99    val read_resp_delayed = Output(Vec(LoadPipelineWidth, new L1BankedDataReadResult()))
100    val read_error_delayed = Output(Vec(LoadPipelineWidth, Bool()))
101    // val nacks = Output(Vec(LoadPipelineWidth, Bool()))
102    // val errors = Output(Vec(LoadPipelineWidth + 1, new L1CacheErrorInfo)) // read ports + readline port
103    // when bank_conflict, read (1) port should be ignored
104    val bank_conflict_slow = Output(Vec(LoadPipelineWidth, Bool()))
105    val bank_conflict_fast = Output(Vec(LoadPipelineWidth, Bool()))
106    val disable_ld_fast_wakeup = Output(Vec(LoadPipelineWidth, Bool()))
107    // customized cache op port
108    val cacheOp = Flipped(new L1CacheInnerOpIO)
109    val cacheOp_req_dup = Vec(11, Flipped(Valid(new CacheCtrlReqInfo)))
110    val cacheOp_req_bits_opCode_dup = Input(Vec(11, UInt(XLEN.W)))
111  })
112
113  def pipeMap[T <: Data](f: Int => T) = VecInit((0 until LoadPipelineWidth).map(f))
114
115  def dumpRead() = {
116    (0 until LoadPipelineWidth) map { w =>
117      when(io.read(w).valid) {
118        XSDebug(s"DataArray Read channel: $w valid way_en: %x addr: %x\n",
119          io.read(w).bits.way_en, io.read(w).bits.addr)
120      }
121    }
122    when(io.readline.valid) {
123      XSDebug(s"DataArray Read Line, valid way_en: %x addr: %x rmask %x\n",
124        io.readline.bits.way_en, io.readline.bits.addr, io.readline.bits.rmask)
125    }
126  }
127
128  def dumpWrite() = {
129    when(io.write.valid) {
130      XSDebug(s"DataArray Write valid way_en: %x addr: %x\n",
131        io.write.bits.way_en, io.write.bits.addr)
132
133      (0 until DCacheBanks) map { r =>
134        XSDebug(s"cycle: $r data: %x wmask: %x\n",
135          io.write.bits.data(r), io.write.bits.wmask(r))
136      }
137    }
138  }
139
140  def dumpResp() = {
141    XSDebug(s"DataArray ReadeResp channel:\n")
142    (0 until LoadPipelineWidth) map { r =>
143      XSDebug(s"cycle: $r data: %x\n", io.read_resp_delayed(r).raw_data)
144    }
145  }
146
147  def dump() = {
148    dumpRead
149    dumpWrite
150    dumpResp
151  }
152}
153
154class BankedDataArray(implicit p: Parameters) extends AbstractBankedDataArray {
155  def getECCFromEncWord(encWord: UInt) = {
156    require(encWord.getWidth == encWordBits)
157    encWord(encWordBits - 1, wordBits)
158  }
159
160  val ReduceReadlineConflict = false
161
162  io.write.ready := true.B
163  io.write_dup.foreach(_.ready := true.B)
164
165  // wrap a sram
166  class DataSRAM(bankIdx:Int, wayIdx:Int) extends Module {
167    val io = IO(new Bundle() {
168      val w = new Bundle() {
169        val en = Input(Bool())
170        val addr = Input(UInt())
171        val data = Input(UInt(DCacheSRAMRowBits.W))
172      }
173
174      val r = new Bundle() {
175        val en = Input(Bool())
176        val addr = Input(UInt())
177        val data = Output(UInt(DCacheSRAMRowBits.W))
178      }
179    })
180
181    // data sram
182    val data_sram = Module(new SRAMTemplate(
183      Bits(DCacheSRAMRowBits.W),
184      set = DCacheSets,
185      way = 1,
186      shouldReset = false,
187      holdRead = false,
188      singlePort = true
189    ))
190
191    val wenReg = RegNext(io.w.en)
192    val waddrReg = RegNext(io.w.addr)
193    val wdataReg = RegNext(io.w.data)
194    data_sram.io.w.req.valid := wenReg
195    data_sram.io.w.req.bits.apply(
196      setIdx = waddrReg,
197      data = wdataReg,
198      waymask = 1.U
199    )
200    data_sram.io.r.req.valid := io.r.en
201    data_sram.io.r.req.bits.apply(setIdx = io.r.addr)
202    io.r.data := data_sram.io.r.resp.data(0)
203
204    def dump_r() = {
205      when(RegNext(io.r.en)) {
206        XSDebug("bank read set %x bank %x way %x data %x\n",
207          RegNext(io.r.addr),
208          bankIdx.U,
209          wayIdx.U,
210          io.r.data
211        )
212      }
213    }
214
215    def dump_w() = {
216      when(io.w.en) {
217        XSDebug("bank write set %x bank %x way %x data %x\n",
218          io.w.addr,
219          bankIdx.U,
220          wayIdx.U,
221          io.w.data
222        )
223      }
224    }
225
226    def dump() = {
227      dump_w()
228      dump_r()
229    }
230  }
231
232  val data_banks = List.tabulate(DCacheBanks)(i => List.tabulate(DCacheWays)(j => Module(new DataSRAM(i,j))))
233  // ecc_banks also needs to be changed to two-dimensional to align with data_banks
234  val ecc_banks = List.tabulate(DCacheBanks)(i => List.tabulate(DCacheWays)(j => Module(new SRAMTemplate(
235    Bits(eccBits.W),
236    set = DCacheSets,
237    way = 1,
238    shouldReset = false,
239    holdRead = false,
240    singlePort = true
241    ))))
242
243  data_banks.map(_.map(_.dump()))
244
245  val way_en = Wire(Vec(LoadPipelineWidth, io.read(0).bits.way_en.cloneType))
246  val way_en_reg = RegNext(way_en)
247  val set_addrs = Wire(Vec(LoadPipelineWidth, UInt()))
248  val bank_addrs = Wire(Vec(LoadPipelineWidth, UInt()))
249
250  // read data_banks and ecc_banks
251  // for single port SRAM, do not allow read and write in the same cycle
252  val rwhazard = RegNext(io.write.valid)
253  val rrhazard = false.B // io.readline.valid
254  (0 until LoadPipelineWidth).map(rport_index => {
255    set_addrs(rport_index) := addr_to_dcache_set(io.read(rport_index).bits.addr)
256    bank_addrs(rport_index) := addr_to_dcache_bank(io.read(rport_index).bits.addr)
257
258    io.read(rport_index).ready := !(rwhazard || rrhazard)
259
260    // use way_en to select a way after data read out
261    assert(!(RegNext(io.read(rport_index).fire() && PopCount(io.read(rport_index).bits.way_en) > 1.U)))
262    way_en(rport_index) := io.read(rport_index).bits.way_en
263  })
264  io.readline.ready := !(rwhazard)
265
266  // read conflict
267  val rr_bank_conflict = Seq.tabulate(LoadPipelineWidth)(x => Seq.tabulate(LoadPipelineWidth)(y =>
268    bank_addrs(x) === bank_addrs(y) && io.read(x).valid && io.read(y).valid && io.read(x).bits.way_en === io.read(y).bits.way_en && set_addrs(x) =/= set_addrs(y)
269  ))
270  val rrl_bank_conflict = Wire(Vec(LoadPipelineWidth, Bool()))
271  if (ReduceReadlineConflict) {
272    (0 until LoadPipelineWidth).foreach(i => rrl_bank_conflict(i) := io.read(i).valid && io.readline.valid && io.readline.bits.rmask(bank_addrs(i)))
273  } else {
274    (0 until LoadPipelineWidth).foreach(i => rrl_bank_conflict(i) := io.read(i).valid && io.readline.valid && io.readline.bits.way_en === way_en(i) && addr_to_dcache_set(io.readline.bits.addr)=/=set_addrs(i))
275  }
276  val rrl_bank_conflict_intend = Wire(Vec(LoadPipelineWidth, Bool()))
277  if (ReduceReadlineConflict) {
278    (0 until LoadPipelineWidth).foreach(i => rrl_bank_conflict_intend(i) := io.read(i).valid && io.readline_intend && io.readline.bits.rmask(bank_addrs(i)))
279  } else {
280    (0 until LoadPipelineWidth).foreach(i => rrl_bank_conflict_intend(i) := io.read(i).valid && io.readline_intend && io.readline.bits.way_en === way_en(i) && addr_to_dcache_set(io.readline.bits.addr)=/=set_addrs(i))
281  }
282
283  val rw_bank_conflict = VecInit(Seq.tabulate(LoadPipelineWidth)(io.read(_).valid && rwhazard))
284  val perf_multi_read = PopCount(io.read.map(_.valid)) >= 2.U
285  (0 until LoadPipelineWidth).foreach(i => {
286    io.bank_conflict_fast(i) := rw_bank_conflict(i) || rrl_bank_conflict(i) ||
287      (if (i == 0) 0.B else (0 until i).map(rr_bank_conflict(_)(i)).reduce(_ || _))
288    io.bank_conflict_slow(i) := RegNext(io.bank_conflict_fast(i))
289    io.disable_ld_fast_wakeup(i) := rw_bank_conflict(i) || rrl_bank_conflict_intend(i) ||
290      (if (i == 0) 0.B else (0 until i).map(rr_bank_conflict(_)(i)).reduce(_ || _))
291  })
292  XSPerfAccumulate("data_array_multi_read", perf_multi_read)
293  (1 until LoadPipelineWidth).foreach(y => (0 until y).foreach(x =>
294    XSPerfAccumulate(s"data_array_rr_bank_conflict_${x}_${y}", rr_bank_conflict(x)(y))
295  ))
296  (0 until LoadPipelineWidth).foreach(i => {
297    XSPerfAccumulate(s"data_array_rrl_bank_conflict_${i}", rrl_bank_conflict(i))
298    XSPerfAccumulate(s"data_array_rw_bank_conflict_${i}", rw_bank_conflict(i))
299    XSPerfAccumulate(s"data_array_read_${i}", io.read(i).valid)
300  })
301  XSPerfAccumulate("data_array_access_total", PopCount(io.read.map(_.valid)))
302  XSPerfAccumulate("data_array_read_line", io.readline.valid)
303  XSPerfAccumulate("data_array_write", io.write.valid)
304
305  val read_result = Wire(Vec(DCacheBanks, Vec(DCacheWays,new L1BankedDataReadResult())))
306  val read_error_delayed_result = Wire(Vec(DCacheBanks, Vec(DCacheWays, Bool())))
307  dontTouch(read_result)
308  dontTouch(read_error_delayed_result)
309  for (bank_index <- 0 until DCacheBanks) {
310    for (way_index <- 0 until DCacheWays) {
311      //     Set Addr & Read Way Mask
312      //
313      //    Pipe 0   ....  Pipe (n-1)
314      //      +      ....     +
315      //      |      ....     |
316      // +----+---------------+-----+
317      //  X                        X
318      //   X                      +------+ Bank Addr Match
319      //    +---------+----------+
320      //              |
321      //     +--------+--------+
322      //     |    Data Bank    |
323      //     +-----------------+
324      val loadpipe_en = WireInit(VecInit(List.tabulate(LoadPipelineWidth)(i => {
325        bank_addrs(i) === bank_index.U && io.read(i).valid && way_en(i)(way_index)
326      })))
327      val readline_en = Wire(Bool())
328      if (ReduceReadlineConflict) {
329        readline_en := io.readline.valid && io.readline.bits.rmask(bank_index) && io.readline.bits.way_en(way_index)
330      } else {
331        readline_en := io.readline.valid && io.readline.bits.way_en(way_index)
332      }
333      val sram_set_addr = Mux(readline_en,
334        addr_to_dcache_set(io.readline.bits.addr),
335        PriorityMux(Seq.tabulate(LoadPipelineWidth)(i => loadpipe_en(i) -> set_addrs(i)))
336      )
337      val read_en = loadpipe_en.asUInt.orR || readline_en
338      // read raw data
339      val data_bank = data_banks(bank_index)(way_index)
340      data_bank.io.r.en := read_en
341      data_bank.io.r.addr := sram_set_addr
342      val ecc_bank = ecc_banks(bank_index)(way_index)
343      ecc_bank.io.r.req.valid := read_en
344      ecc_bank.io.r.req.bits.apply(setIdx = sram_set_addr)
345
346      read_result(bank_index)(way_index).raw_data := data_bank.io.r.data
347      read_result(bank_index)(way_index).ecc := ecc_bank.io.r.resp.data(0)
348
349      // use ECC to check error
350      val ecc_data = read_result(bank_index)(way_index).asECCData()
351      val ecc_data_delayed = RegEnable(ecc_data, RegNext(read_en))
352      read_result(bank_index)(way_index).error_delayed := dcacheParameters.dataCode.decode(ecc_data_delayed).error
353      read_error_delayed_result(bank_index)(way_index) := read_result(bank_index)(way_index).error_delayed
354    }
355  }
356
357  // read result: expose banked read result
358  /*
359  (0 until LoadPipelineWidth).map(i => {
360    io.read_resp(i) := read_result(RegNext(bank_addrs(i)))(RegNext(OHToUInt(way_en(i))))
361   })
362  */
363  val read_result_delayed = RegNext(read_result)
364  (0 until LoadPipelineWidth).map(i => {
365    io.read_resp_delayed(i) := read_result_delayed(RegNext(RegNext(bank_addrs(i))))(RegNext(RegNext(OHToUInt(way_en(i)))))
366  })
367  (0 until DCacheBanks).map(i => {
368    io.readline_resp(i) := read_result(i)(RegNext(OHToUInt(io.readline.bits.way_en)))
369  })
370
371  // error detection
372  // normal read ports
373  (0 until LoadPipelineWidth).map(rport_index => {
374    io.read_error_delayed(rport_index) := RegNext(RegNext(io.read(rport_index).fire())) &&
375      read_error_delayed_result(RegNext(RegNext(bank_addrs(rport_index))))(RegNext(RegNext(OHToUInt(way_en(rport_index))))) &&
376      !RegNext(io.bank_conflict_slow(rport_index))
377  })
378  // readline port
379  io.readline_error_delayed := RegNext(RegNext(io.readline.fire())) &&
380    VecInit((0 until DCacheBanks).map(i => io.readline_resp(i).error_delayed)).asUInt().orR
381
382  // write data_banks & ecc_banks
383  val sram_waddr = addr_to_dcache_set(io.write.bits.addr)
384  val sram_waddr_dup = io.write_dup.map(x => addr_to_dcache_set(x.bits.addr))
385  for (bank_index <- 0 until DCacheBanks) {
386    for (way_index <- 0 until DCacheWays) {
387      // data write
388      val data_bank = data_banks(bank_index)(way_index)
389      data_bank.io.w.en := io.write_dup(bank_index).valid && io.write.bits.wmask(bank_index) && io.write_dup(bank_index).bits.way_en(way_index)
390      data_bank.io.w.addr := sram_waddr_dup(bank_index)
391      data_bank.io.w.data := io.write.bits.data(bank_index)
392      // ecc write
393      val ecc_bank = ecc_banks(bank_index)(way_index)
394      ecc_bank.io.w.req.valid := RegNext(io.write_dup(bank_index).valid && io.write.bits.wmask(bank_index) && io.write_dup(bank_index).bits.way_en(way_index))
395      ecc_bank.io.w.req.bits.apply(
396        setIdx = RegNext(sram_waddr_dup(bank_index)),
397        data = RegNext(getECCFromEncWord(cacheParams.dataCode.encode((io.write.bits.data(bank_index))))),
398        waymask = 1.U
399      )
400      when(ecc_bank.io.w.req.valid) {
401        XSDebug("write in ecc sram: bank %x set %x data %x waymask %x\n",
402          bank_index.U,
403          sram_waddr,
404          getECCFromEncWord(cacheParams.dataCode.encode((io.write.bits.data(bank_index)))),
405          io.write.bits.way_en
406        );
407      }
408    }
409  }
410
411  // deal with customized cache op
412  require(nWays <= 32)
413  io.cacheOp.resp.bits := DontCare
414  val cacheOpShouldResp = WireInit(false.B)
415  val eccReadResult = Wire(Vec(DCacheBanks, UInt(eccBits.W)))
416
417  when (io.cacheOp.req.valid && CacheInstrucion.isReadData(io.cacheOp.req.bits.opCode)) {
418    for (bank_index <- 0 until (DCacheBanks / 3)) {
419      for(way_index <- 0 until DCacheWays){
420        val data_bank = data_banks(bank_index)(way_index)
421        data_bank.io.r.en := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))(way_index)
422        data_bank.io.r.addr := io.cacheOp.req.bits.index
423      }
424    }
425    cacheOpShouldResp := true.B
426  }
427  when (io.cacheOp_req_dup(0).valid && CacheInstrucion.isReadDataECC(io.cacheOp_req_bits_opCode_dup(0))) {
428    for (bank_index <- 0 until (DCacheBanks / 3)) {
429      for(way_index <- 0 until DCacheWays){
430        val ecc_bank = ecc_banks(bank_index)(way_index)
431        ecc_bank.io.r.req.valid := true.B
432        ecc_bank.io.r.req.bits.setIdx := io.cacheOp.req.bits.index
433      }
434    }
435    cacheOpShouldResp := true.B
436  }
437  when(io.cacheOp_req_dup(1).valid && CacheInstrucion.isWriteData(io.cacheOp_req_bits_opCode_dup(1))){
438    for (bank_index <- 0 until (DCacheBanks / 3)) {
439      for(way_index <- 0 until DCacheWays){
440        val data_bank = data_banks(bank_index)(way_index)
441        data_bank.io.w.en := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))(way_index)
442        data_bank.io.w.addr := io.cacheOp.req.bits.index
443        data_bank.io.w.data := io.cacheOp.req.bits.write_data_vec(bank_index)
444      }
445    }
446    cacheOpShouldResp := true.B
447  }
448  when(io.cacheOp_req_dup(2).valid && CacheInstrucion.isWriteDataECC(io.cacheOp_req_bits_opCode_dup(2))){
449    for (bank_index <- 0 until (DCacheBanks / 3)) {
450      for(way_index <- 0 until DCacheWays){
451        val ecc_bank = ecc_banks(bank_index)(way_index)
452        ecc_bank.io.w.req.valid := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))(way_index)
453        ecc_bank.io.w.req.bits.apply(
454          setIdx = io.cacheOp.req.bits.index,
455          data = io.cacheOp.req.bits.write_data_ecc,
456          waymask = 1.U
457        )
458      }
459    }
460    cacheOpShouldResp := true.B
461  }
462
463
464  when (io.cacheOp_req_dup(3).valid && CacheInstrucion.isReadData(io.cacheOp_req_bits_opCode_dup(3))) {
465    for (bank_index <- (DCacheBanks / 3) until ((DCacheBanks / 3) * 2)) {
466      for (way_index <- 0 until DCacheWays) {
467        val data_bank = data_banks(bank_index)(way_index)
468        data_bank.io.r.en := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))(way_index)
469        data_bank.io.r.addr := io.cacheOp.req.bits.index
470      }
471    }
472    cacheOpShouldResp := true.B
473  }
474  when (io.cacheOp_req_dup(4).valid && CacheInstrucion.isReadDataECC(io.cacheOp_req_bits_opCode_dup(4))) {
475    for (bank_index <- (DCacheBanks / 3) until ((DCacheBanks / 3) * 2)) {
476      for(way_index <- 0 until DCacheWays){
477        val ecc_bank = ecc_banks(bank_index)(way_index)
478        ecc_bank.io.r.req.valid := true.B
479        ecc_bank.io.r.req.bits.setIdx := io.cacheOp.req.bits.index
480      }
481    }
482    cacheOpShouldResp := true.B
483  }
484  when(io.cacheOp_req_dup(5).valid && CacheInstrucion.isWriteData(io.cacheOp_req_bits_opCode_dup(5))){
485    for (bank_index <- (DCacheBanks / 3) until ((DCacheBanks / 3) * 2)) {
486      for (way_index <- 0 until DCacheWays) {
487        val data_bank = data_banks(bank_index)(way_index)
488        data_bank.io.w.en := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))(way_index)
489        data_bank.io.w.addr := io.cacheOp.req.bits.index
490        data_bank.io.w.data := io.cacheOp.req.bits.write_data_vec(bank_index)
491      }
492    }
493    cacheOpShouldResp := true.B
494  }
495  when(io.cacheOp_req_dup(6).valid && CacheInstrucion.isWriteDataECC(io.cacheOp_req_bits_opCode_dup(6))){
496    for (bank_index <- (DCacheBanks / 3) until ((DCacheBanks / 3) * 2)) {
497      for(way_index <- 0 until DCacheWays){
498        val ecc_bank = ecc_banks(bank_index)(way_index)
499        ecc_bank.io.w.req.valid := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))(way_index)
500        ecc_bank.io.w.req.bits.apply(
501          setIdx = io.cacheOp.req.bits.index,
502          data = io.cacheOp.req.bits.write_data_ecc,
503          waymask = 1.U
504        )
505      }
506    }
507    cacheOpShouldResp := true.B
508  }
509
510  when (io.cacheOp_req_dup(7).valid && CacheInstrucion.isReadData(io.cacheOp_req_bits_opCode_dup(7))) {
511    for (bank_index <- ((DCacheBanks / 3) * 2) until DCacheBanks) {
512      for (way_index <- 0 until DCacheWays) {
513        val data_bank = data_banks(bank_index)(way_index)
514        data_bank.io.r.en := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))(way_index)
515        data_bank.io.r.addr := io.cacheOp.req.bits.index
516      }
517    }
518    cacheOpShouldResp := true.B
519  }
520  when (io.cacheOp_req_dup(8).valid && CacheInstrucion.isReadDataECC(io.cacheOp_req_bits_opCode_dup(8))) {
521    for (bank_index <- ((DCacheBanks / 3) * 2) until DCacheBanks) {
522      for(way_index <- 0 until DCacheWays){
523        val ecc_bank = ecc_banks(bank_index)(way_index)
524        ecc_bank.io.r.req.valid := true.B
525        ecc_bank.io.r.req.bits.setIdx := io.cacheOp.req.bits.index
526      }
527    }
528    cacheOpShouldResp := true.B
529  }
530  when(io.cacheOp_req_dup(9).valid && CacheInstrucion.isWriteData(io.cacheOp_req_bits_opCode_dup(9))){
531    for (bank_index <- ((DCacheBanks / 3) * 2) until DCacheBanks) {
532      for (way_index <- 0 until DCacheWays) {
533        val data_bank = data_banks(bank_index)(way_index)
534        data_bank.io.w.en := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))(way_index)
535        data_bank.io.w.addr := io.cacheOp.req.bits.index
536        data_bank.io.w.data := io.cacheOp.req.bits.write_data_vec(bank_index)
537      }
538    }
539    cacheOpShouldResp := true.B
540  }
541  when(io.cacheOp_req_dup(10).valid && CacheInstrucion.isWriteDataECC(io.cacheOp_req_bits_opCode_dup(10))){
542    for (bank_index <- ((DCacheBanks / 3) * 2) until DCacheBanks) {
543      for(way_index <- 0 until DCacheWays){
544        val ecc_bank = ecc_banks(bank_index)(way_index)
545        ecc_bank.io.w.req.valid := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))(way_index)
546        ecc_bank.io.w.req.bits.apply(
547          setIdx = io.cacheOp.req.bits.index,
548          data = io.cacheOp.req.bits.write_data_ecc,
549          waymask = 1.U
550        )
551      }
552    }
553    cacheOpShouldResp := true.B
554  }
555
556  io.cacheOp.resp.valid := RegNext(io.cacheOp.req.valid && cacheOpShouldResp)
557  for (bank_index <- 0 until DCacheBanks) {
558    io.cacheOp.resp.bits.read_data_vec(bank_index) := read_result(bank_index)(RegNext(io.cacheOp.req.bits.wayNum(4, 0))).raw_data
559	  eccReadResult(bank_index) := read_result(bank_index)(RegNext(io.cacheOp.req.bits.wayNum(4, 0))).ecc
560  }
561  io.cacheOp.resp.bits.read_data_ecc := Mux(io.cacheOp.resp.valid,
562    eccReadResult(RegNext(io.cacheOp.req.bits.bank_num)),
563    0.U
564  )
565
566  val tableName =  "BankConflict" + p(XSCoreParamsKey).HartId.toString
567  val siteName = "BankedDataArray" + p(XSCoreParamsKey).HartId.toString
568  val bankConflictTable = ChiselDB.createTable(tableName, new BankConflictDB)
569  val bankConflictData = Wire(new BankConflictDB)
570  for (i <- 0 until LoadPipelineWidth) {
571    bankConflictData.set_index(i) := set_addrs(i)
572    bankConflictData.addr(i) := io.read(i).bits.addr
573  }
574
575  // FIXME: rr_bank_conflict(0)(1) no generalization
576  when(rr_bank_conflict(0)(1)) {
577    bankConflictData.bank_index := bank_addrs(0)
578    bankConflictData.way_index  := OHToUInt(way_en(0))
579    bankConflictData.fake_rr_bank_conflict := set_addrs(0) === set_addrs(1)
580  }.otherwise {
581    bankConflictData.bank_index := 0.U
582    bankConflictData.way_index := 0.U
583    bankConflictData.fake_rr_bank_conflict := false.B
584  }
585
586  bankConflictTable.log(
587    data = bankConflictData,
588    en = rr_bank_conflict(0)(1),
589    site = siteName,
590    clock = clock,
591    reset = reset
592  )
593
594  (1 until LoadPipelineWidth).foreach(y => (0 until y).foreach(x =>
595    XSPerfAccumulate(s"data_array_fake_rr_bank_conflict_${x}_${y}", rr_bank_conflict(x)(y) && set_addrs(x)===set_addrs(y))
596  ))
597
598}