xref: /XiangShan/src/main/scala/xiangshan/cache/dcache/data/BankedDataArray.scala (revision 67ba96b4871c459c09df20e3052738174021a830)
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
26
27import scala.math.max
28
29class L1BankedDataReadReq(implicit p: Parameters) extends DCacheBundle
30{
31  val way_en = Bits(DCacheWays.W)
32  val addr = Bits(PAddrBits.W)
33}
34
35class L1BankedDataReadLineReq(implicit p: Parameters) extends L1BankedDataReadReq
36{
37  val rmask = Bits(DCacheBanks.W)
38}
39
40// Now, we can write a cache-block in a single cycle
41class L1BankedDataWriteReq(implicit p: Parameters) extends L1BankedDataReadReq
42{
43  val wmask = Bits(DCacheBanks.W)
44  val data = Vec(DCacheBanks, Bits(DCacheSRAMRowBits.W))
45}
46
47// cache-block write request without data
48class L1BankedDataWriteReqCtrl(implicit p: Parameters) extends L1BankedDataReadReq
49
50class L1BankedDataReadResult(implicit p: Parameters) extends DCacheBundle
51{
52  // you can choose which bank to read to save power
53  val ecc = Bits(eccBits.W)
54  val raw_data = Bits(DCacheSRAMRowBits.W)
55  val error_delayed = Bool() // 1 cycle later than data resp
56
57  def asECCData() = {
58    Cat(ecc, raw_data)
59  }
60}
61
62class DataSRAMBankWriteReq(implicit p: Parameters) extends DCacheBundle {
63  val en = Bool()
64  val addr = UInt()
65  val way_en = UInt(DCacheWays.W)
66  val data = UInt(DCacheSRAMRowBits.W)
67}
68
69//                     Banked DCache Data
70// -----------------------------------------------------------------
71// | Bank0 | Bank1 | Bank2 | Bank3 | Bank4 | Bank5 | Bank6 | Bank7 |
72// -----------------------------------------------------------------
73// | Way0  | Way0  | Way0  | Way0  | Way0  | Way0  | Way0  | Way0  |
74// | Way1  | Way1  | Way1  | Way1  | Way1  | Way1  | Way1  | Way1  |
75// | ....  | ....  | ....  | ....  | ....  | ....  | ....  | ....  |
76// -----------------------------------------------------------------
77abstract class AbstractBankedDataArray(implicit p: Parameters) extends DCacheModule
78{
79  val ReadlinePortErrorIndex = LoadPipelineWidth
80  val io = IO(new DCacheBundle {
81    // load pipeline read word req
82    val read = Vec(LoadPipelineWidth, Flipped(DecoupledIO(new L1BankedDataReadReq)))
83    // main pipeline read / write line req
84    val readline_intend = Input(Bool())
85    val readline = Flipped(DecoupledIO(new L1BankedDataReadLineReq))
86    val write = Flipped(DecoupledIO(new L1BankedDataWriteReq))
87    val write_dup = Vec(DCacheBanks, Flipped(Decoupled(new L1BankedDataWriteReqCtrl)))
88    // data bank read resp (all banks)
89    val resp = Output(Vec(DCacheBanks, new L1BankedDataReadResult()))
90    // val nacks = Output(Vec(LoadPipelineWidth, Bool()))
91    // val errors = Output(Vec(LoadPipelineWidth + 1, new L1CacheErrorInfo)) // read ports + readline port
92    val read_error_delayed = Output(Vec(LoadPipelineWidth, Bool()))
93    val readline_error_delayed = Output(Bool())
94    // when bank_conflict, read (1) port should be ignored
95    val bank_conflict_slow = Output(Vec(LoadPipelineWidth, Bool()))
96    val bank_conflict_fast = Output(Vec(LoadPipelineWidth, Bool()))
97    val disable_ld_fast_wakeup = Output(Vec(LoadPipelineWidth, Bool()))
98    // customized cache op port
99    val cacheOp = Flipped(new L1CacheInnerOpIO)
100    val cacheOp_req_dup = Vec(11, Flipped(Valid(new CacheCtrlReqInfo)))
101    val cacheOp_req_bits_opCode_dup = Input(Vec(11, UInt(XLEN.W)))
102  })
103
104  def pipeMap[T <: Data](f: Int => T) = VecInit((0 until LoadPipelineWidth).map(f))
105
106  def dumpRead() = {
107    (0 until LoadPipelineWidth) map { w =>
108      when(io.read(w).valid) {
109        XSDebug(s"DataArray Read channel: $w valid way_en: %x addr: %x\n",
110          io.read(w).bits.way_en, io.read(w).bits.addr)
111      }
112    }
113    when(io.readline.valid) {
114      XSDebug(s"DataArray Read Line, valid way_en: %x addr: %x rmask %x\n",
115        io.readline.bits.way_en, io.readline.bits.addr, io.readline.bits.rmask)
116    }
117  }
118
119  def dumpWrite() = {
120    when(io.write.valid) {
121      XSDebug(s"DataArray Write valid way_en: %x addr: %x\n",
122        io.write.bits.way_en, io.write.bits.addr)
123
124      (0 until DCacheBanks) map { r =>
125        XSDebug(s"cycle: $r data: %x wmask: %x\n",
126          io.write.bits.data(r), io.write.bits.wmask(r))
127      }
128    }
129  }
130
131  def dumpResp() = {
132    XSDebug(s"DataArray ReadeResp channel:\n")
133    (0 until DCacheBanks) map { r =>
134      XSDebug(s"cycle: $r data: %x\n", io.resp(r).raw_data)
135    }
136  }
137
138  def dump() = {
139    dumpRead
140    dumpWrite
141    dumpResp
142  }
143}
144
145class BankedDataArray(implicit p: Parameters) extends AbstractBankedDataArray {
146  def getECCFromEncWord(encWord: UInt) = {
147    require(encWord.getWidth == encWordBits)
148    encWord(encWordBits - 1, wordBits)
149  }
150
151  val ReduceReadlineConflict = false
152
153  io.write.ready := true.B
154  io.write_dup.foreach(_.ready := true.B)
155
156  // wrap data rows of 8 ways
157  class DataSRAMBank(index: Int) extends Module {
158    val io = IO(new Bundle() {
159      val w = Input(new DataSRAMBankWriteReq)
160
161      val r = new Bundle() {
162        val en = Input(Bool())
163        val addr = Input(UInt())
164        val way_en = Input(UInt(DCacheWays.W))
165        val data = Output(UInt(DCacheSRAMRowBits.W))
166      }
167    })
168
169    assert(RegNext(!io.w.en || PopCount(io.w.way_en) <= 1.U))
170    assert(RegNext(!io.r.en || PopCount(io.r.way_en) <= 1.U))
171
172    val r_way_en_reg = RegNext(io.r.way_en)
173
174    val w_reg = RegNext(io.w)
175    // val rw_bypass = RegNext(io.w.addr === io.r.addr && io.w.way_en === io.r.way_en && io.w.en)
176
177    // multiway data bank
178    val data_bank = Array.fill(DCacheWays) {
179      Module(new SRAMTemplate(
180        Bits(DCacheSRAMRowBits.W),
181        set = DCacheSets,
182        way = 1,
183        shouldReset = false,
184        holdRead = false,
185        singlePort = true
186      ))
187    }
188
189    for (w <- 0 until DCacheWays) {
190      val wen = w_reg.en && w_reg.way_en(w)
191      data_bank(w).io.w.req.valid := wen
192      data_bank(w).io.w.req.bits.apply(
193        setIdx = w_reg.addr,
194        data = w_reg.data,
195        waymask = 1.U
196      )
197      data_bank(w).io.r.req.valid := io.r.en
198      data_bank(w).io.r.req.bits.apply(setIdx = io.r.addr)
199    }
200
201    val half = nWays / 2
202    val data_read = data_bank.map(_.io.r.resp.data(0))
203    val data_left = Mux1H(r_way_en_reg.tail(half), data_read.take(half))
204    val data_right = Mux1H(r_way_en_reg.head(half), data_read.drop(half))
205
206    val sel_low = r_way_en_reg.tail(half).orR()
207    val row_data = Mux(sel_low, data_left, data_right)
208
209    io.r.data := row_data
210
211    def dump_r() = {
212      when(RegNext(io.r.en)) {
213        XSDebug("bank read addr %x way_en %x data %x\n",
214          RegNext(io.r.addr),
215          RegNext(io.r.way_en),
216          io.r.data
217        )
218      }
219    }
220
221    def dump_w() = {
222      when(io.w.en) {
223        XSDebug("bank write addr %x way_en %x data %x\n",
224          io.w.addr,
225          io.w.way_en,
226          io.w.data
227        )
228      }
229    }
230
231    def dump() = {
232      dump_w()
233      dump_r()
234    }
235  }
236
237  val data_banks = List.tabulate(DCacheBanks)(i => Module(new DataSRAMBank(i)))
238  val ecc_banks = List.fill(DCacheBanks)(Module(new SRAMTemplate(
239    Bits(eccBits.W),
240    set = DCacheSets,
241    way = DCacheWays,
242    shouldReset = false,
243    holdRead = false,
244    singlePort = true
245  )))
246
247  data_banks.map(_.dump())
248
249  val way_en = Wire(Vec(LoadPipelineWidth, io.read(0).bits.way_en.cloneType))
250  val way_en_reg = RegNext(way_en)
251  val set_addrs = Wire(Vec(LoadPipelineWidth, UInt()))
252  val bank_addrs = Wire(Vec(LoadPipelineWidth, UInt()))
253
254  // read data_banks and ecc_banks
255  // for single port SRAM, do not allow read and write in the same cycle
256  val rwhazard = RegNext(io.write.valid)
257  val rrhazard = false.B // io.readline.valid
258  (0 until LoadPipelineWidth).map(rport_index => {
259    set_addrs(rport_index) := addr_to_dcache_set(io.read(rport_index).bits.addr)
260    bank_addrs(rport_index) := addr_to_dcache_bank(io.read(rport_index).bits.addr)
261
262    io.read(rport_index).ready := !(rwhazard || rrhazard)
263
264    // use way_en to select a way after data read out
265    assert(!(RegNext(io.read(rport_index).fire() && PopCount(io.read(rport_index).bits.way_en) > 1.U)))
266    way_en(rport_index) := io.read(rport_index).bits.way_en
267  })
268  io.readline.ready := !(rwhazard)
269
270  // read each bank, get bank result
271  val bank_result = Wire(Vec(DCacheBanks, new L1BankedDataReadResult()))
272  dontTouch(bank_result)
273  val read_bank_error_delayed = Wire(Vec(DCacheBanks, Bool()))
274  dontTouch(read_bank_error_delayed)
275  val rr_bank_conflict = Seq.tabulate(LoadPipelineWidth)(x => Seq.tabulate(LoadPipelineWidth)(y =>
276    bank_addrs(x) === bank_addrs(y) && io.read(x).valid && io.read(y).valid
277  ))
278  val rrl_bank_conflict = Wire(Vec(LoadPipelineWidth, Bool()))
279  if (ReduceReadlineConflict) {
280    (0 until LoadPipelineWidth).foreach(i => rrl_bank_conflict(i) := io.read(i).valid && io.readline.valid && io.readline.bits.rmask(bank_addrs(i)))
281  } else {
282    (0 until LoadPipelineWidth).foreach(i => rrl_bank_conflict(i) := io.read(i).valid && io.readline.valid)
283  }
284  val rrl_bank_conflict_intend = Wire(Vec(LoadPipelineWidth, Bool()))
285  if (ReduceReadlineConflict) {
286    (0 until LoadPipelineWidth).foreach(i => rrl_bank_conflict_intend(i) := io.read(i).valid && io.readline_intend && io.readline.bits.rmask(bank_addrs(i)))
287  } else {
288    (0 until LoadPipelineWidth).foreach(i => rrl_bank_conflict_intend(i) := io.read(i).valid && io.readline_intend)
289  }
290
291  val rw_bank_conflict = VecInit(Seq.tabulate(LoadPipelineWidth)(io.read(_).valid && rwhazard))
292  val perf_multi_read = PopCount(io.read.map(_.valid)) >= 2.U
293  (0 until LoadPipelineWidth).foreach(i => {
294    io.bank_conflict_fast(i) := rw_bank_conflict(i) || rrl_bank_conflict(i) ||
295      (if (i == 0) 0.B else (0 until i).map(rr_bank_conflict(_)(i)).reduce(_ || _))
296    io.bank_conflict_slow(i) := RegNext(io.bank_conflict_fast(i))
297    io.disable_ld_fast_wakeup(i) := rw_bank_conflict(i) || rrl_bank_conflict_intend(i) ||
298      (if (i == 0) 0.B else (0 until i).map(rr_bank_conflict(_)(i)).reduce(_ || _))
299  })
300  XSPerfAccumulate("data_array_multi_read", perf_multi_read)
301  (1 until LoadPipelineWidth).foreach(y => (0 until y).foreach(x =>
302    XSPerfAccumulate(s"data_array_rr_bank_conflict_${x}_${y}", rr_bank_conflict(x)(y))
303  ))
304  (0 until LoadPipelineWidth).foreach(i => {
305    XSPerfAccumulate(s"data_array_rrl_bank_conflict_${i}", rrl_bank_conflict(i))
306    XSPerfAccumulate(s"data_array_rw_bank_conflict_${i}", rw_bank_conflict(i))
307    XSPerfAccumulate(s"data_array_read_${i}", io.read(i).valid)
308  })
309  XSPerfAccumulate("data_array_access_total", PopCount(io.read.map(_.valid)))
310  XSPerfAccumulate("data_array_read_line", io.readline.valid)
311  XSPerfAccumulate("data_array_write", io.write.valid)
312
313  for (bank_index <- 0 until DCacheBanks) {
314    //     Set Addr & Read Way Mask
315    //
316    //    Pipe 0   ....  Pipe (n-1)
317    //      +      ....     +
318    //      |      ....     |
319    // +----+---------------+-----+
320    //  X                        X
321    //   X                      +------+ Bank Addr Match
322    //    +---------+----------+
323    //              |
324    //     +--------+--------+
325    //     |    Data Bank    |
326    //     +-----------------+
327    val bank_addr_matchs = WireInit(VecInit(List.tabulate(LoadPipelineWidth)(i => {
328      bank_addrs(i) === bank_index.U && io.read(i).valid
329    })))
330    val readline_match = Wire(Bool())
331    if (ReduceReadlineConflict) {
332      readline_match := io.readline.valid && io.readline.bits.rmask(bank_index)
333    } else {
334      readline_match := io.readline.valid
335    }
336    val bank_way_en = Mux(readline_match,
337      io.readline.bits.way_en,
338      PriorityMux(Seq.tabulate(LoadPipelineWidth)(i => bank_addr_matchs(i) -> way_en(i)))
339    )
340    val bank_set_addr = Mux(readline_match,
341      addr_to_dcache_set(io.readline.bits.addr),
342      PriorityMux(Seq.tabulate(LoadPipelineWidth)(i => bank_addr_matchs(i) -> set_addrs(i)))
343    )
344
345    val read_enable = bank_addr_matchs.asUInt.orR || readline_match
346
347    // read raw data
348    val data_bank = data_banks(bank_index)
349    data_bank.io.r.en := read_enable
350    data_bank.io.r.way_en := bank_way_en
351    data_bank.io.r.addr := bank_set_addr
352    bank_result(bank_index).raw_data := data_bank.io.r.data
353
354    // read ECC
355    val ecc_bank = ecc_banks(bank_index)
356    ecc_bank.io.r.req.valid := read_enable
357    ecc_bank.io.r.req.bits.apply(setIdx = bank_set_addr)
358    bank_result(bank_index).ecc := Mux1H(RegNext(bank_way_en), ecc_bank.io.r.resp.data)
359
360    // use ECC to check error
361    val ecc_data = bank_result(bank_index).asECCData()
362    val ecc_data_delayed = RegEnable(ecc_data, RegNext(read_enable))
363    bank_result(bank_index).error_delayed := dcacheParameters.dataCode.decode(ecc_data_delayed).error
364    read_bank_error_delayed(bank_index) := bank_result(bank_index).error_delayed
365  }
366
367  // read result: expose banked read result
368  io.resp := bank_result
369
370  // error detection
371  // normal read ports
372  (0 until LoadPipelineWidth).map(rport_index => {
373    io.read_error_delayed(rport_index) := RegNext(RegNext(io.read(rport_index).fire())) &&
374      read_bank_error_delayed(RegNext(RegNext(bank_addrs(rport_index)))) &&
375      !RegNext(io.bank_conflict_slow(rport_index))
376  })
377  // readline port
378  io.readline_error_delayed := RegNext(RegNext(io.readline.fire())) &&
379    VecInit((0 until DCacheBanks).map(i => io.resp(i).error_delayed)).asUInt().orR
380
381  // write data_banks & ecc_banks
382  val sram_waddr = addr_to_dcache_set(io.write.bits.addr)
383  val sram_waddr_dup = io.write_dup.map(x => addr_to_dcache_set(x.bits.addr))
384  for (bank_index <- 0 until DCacheBanks) {
385    // data write
386    val data_bank = data_banks(bank_index)
387    data_bank.io.w.en := io.write_dup(bank_index).valid && io.write.bits.wmask(bank_index)
388    data_bank.io.w.way_en := io.write_dup(bank_index).bits.way_en
389    data_bank.io.w.addr := sram_waddr_dup(bank_index)
390    data_bank.io.w.data := io.write.bits.data(bank_index)
391
392    // ecc write
393    val ecc_bank = ecc_banks(bank_index)
394    ecc_bank.io.w.req.valid := RegNext(io.write_dup(bank_index).valid && io.write.bits.wmask(bank_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 = RegNext(io.write_dup(bank_index).bits.way_en)
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  // deal with customized cache op
411  require(nWays <= 32)
412  io.cacheOp.resp.bits := DontCare
413  val cacheOpShouldResp = WireInit(false.B)
414  val eccReadResult = Wire(Vec(DCacheBanks, UInt(eccBits.W)))
415
416  when (io.cacheOp.req.valid && CacheInstrucion.isReadData(io.cacheOp.req.bits.opCode)) {
417    for (bank_index <- 0 until (DCacheBanks / 3)) {
418      val data_bank = data_banks(bank_index)
419      data_bank.io.r.en := true.B
420      data_bank.io.r.way_en := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))
421      data_bank.io.r.addr := io.cacheOp.req.bits.index
422    }
423    cacheOpShouldResp := true.B
424  }
425  when (io.cacheOp_req_dup(0).valid && CacheInstrucion.isReadDataECC(io.cacheOp_req_bits_opCode_dup(0))) {
426    for (bank_index <- 0 until (DCacheBanks / 3)) {
427      val ecc_bank = ecc_banks(bank_index)
428      ecc_bank.io.r.req.valid := true.B
429      ecc_bank.io.r.req.bits.setIdx := io.cacheOp.req.bits.index
430    }
431    cacheOpShouldResp := true.B
432  }
433  when(io.cacheOp_req_dup(1).valid && CacheInstrucion.isWriteData(io.cacheOp_req_bits_opCode_dup(1))){
434    for (bank_index <- 0 until (DCacheBanks / 3)) {
435      val data_bank = data_banks(bank_index)
436      data_bank.io.w.en := true.B
437      data_bank.io.w.way_en := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))
438      data_bank.io.w.addr := io.cacheOp.req.bits.index
439      data_bank.io.w.data := io.cacheOp.req.bits.write_data_vec(bank_index)
440    }
441    cacheOpShouldResp := true.B
442  }
443  when(io.cacheOp_req_dup(2).valid && CacheInstrucion.isWriteDataECC(io.cacheOp_req_bits_opCode_dup(2))){
444    for (bank_index <- 0 until (DCacheBanks / 3)) {
445      val ecc_bank = ecc_banks(bank_index)
446      ecc_bank.io.w.req.valid := true.B
447      ecc_bank.io.w.req.bits.apply(
448        setIdx = io.cacheOp.req.bits.index,
449        data = io.cacheOp.req.bits.write_data_ecc,
450        waymask = UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))
451      )
452    }
453    cacheOpShouldResp := true.B
454  }
455
456
457  when (io.cacheOp_req_dup(3).valid && CacheInstrucion.isReadData(io.cacheOp_req_bits_opCode_dup(3))) {
458    for (bank_index <- (DCacheBanks / 3) until ((DCacheBanks / 3) * 2)) {
459      val data_bank = data_banks(bank_index)
460      data_bank.io.r.en := true.B
461      data_bank.io.r.way_en := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))
462      data_bank.io.r.addr := io.cacheOp.req.bits.index
463    }
464    cacheOpShouldResp := true.B
465  }
466  when (io.cacheOp_req_dup(4).valid && CacheInstrucion.isReadDataECC(io.cacheOp_req_bits_opCode_dup(4))) {
467    for (bank_index <- (DCacheBanks / 3) until ((DCacheBanks / 3) * 2)) {
468      val ecc_bank = ecc_banks(bank_index)
469      ecc_bank.io.r.req.valid := true.B
470      ecc_bank.io.r.req.bits.setIdx := io.cacheOp.req.bits.index
471    }
472    cacheOpShouldResp := true.B
473  }
474  when(io.cacheOp_req_dup(5).valid && CacheInstrucion.isWriteData(io.cacheOp_req_bits_opCode_dup(5))){
475    for (bank_index <- (DCacheBanks / 3) until ((DCacheBanks / 3) * 2)) {
476      val data_bank = data_banks(bank_index)
477      data_bank.io.w.en := true.B
478      data_bank.io.w.way_en := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))
479      data_bank.io.w.addr := io.cacheOp.req.bits.index
480      data_bank.io.w.data := io.cacheOp.req.bits.write_data_vec(bank_index)
481    }
482    cacheOpShouldResp := true.B
483  }
484  when(io.cacheOp_req_dup(6).valid && CacheInstrucion.isWriteDataECC(io.cacheOp_req_bits_opCode_dup(6))){
485    for (bank_index <- (DCacheBanks / 3) until ((DCacheBanks / 3) * 2)) {
486      val ecc_bank = ecc_banks(bank_index)
487      ecc_bank.io.w.req.valid := true.B
488      ecc_bank.io.w.req.bits.apply(
489        setIdx = io.cacheOp.req.bits.index,
490        data = io.cacheOp.req.bits.write_data_ecc,
491        waymask = UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))
492      )
493    }
494    cacheOpShouldResp := true.B
495  }
496
497  when (io.cacheOp_req_dup(7).valid && CacheInstrucion.isReadData(io.cacheOp_req_bits_opCode_dup(7))) {
498    for (bank_index <- ((DCacheBanks / 3) * 2) until DCacheBanks) {
499      val data_bank = data_banks(bank_index)
500      data_bank.io.r.en := true.B
501      data_bank.io.r.way_en := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))
502      data_bank.io.r.addr := io.cacheOp.req.bits.index
503    }
504    cacheOpShouldResp := true.B
505  }
506  when (io.cacheOp_req_dup(8).valid && CacheInstrucion.isReadDataECC(io.cacheOp_req_bits_opCode_dup(8))) {
507    for (bank_index <- ((DCacheBanks / 3) * 2) until DCacheBanks) {
508      val ecc_bank = ecc_banks(bank_index)
509      ecc_bank.io.r.req.valid := true.B
510      ecc_bank.io.r.req.bits.setIdx := io.cacheOp.req.bits.index
511    }
512      cacheOpShouldResp := true.B
513  }
514  when(io.cacheOp_req_dup(9).valid && CacheInstrucion.isWriteData(io.cacheOp_req_bits_opCode_dup(9))){
515    for (bank_index <- ((DCacheBanks / 3) * 2) until DCacheBanks) {
516      val data_bank = data_banks(bank_index)
517      data_bank.io.w.en := true.B
518      data_bank.io.w.way_en := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))
519      data_bank.io.w.addr := io.cacheOp.req.bits.index
520      data_bank.io.w.data := io.cacheOp.req.bits.write_data_vec(bank_index)
521    }
522    cacheOpShouldResp := true.B
523  }
524  when(io.cacheOp_req_dup(10).valid && CacheInstrucion.isWriteDataECC(io.cacheOp_req_bits_opCode_dup(10))){
525    for (bank_index <- ((DCacheBanks / 3) * 2) until DCacheBanks) {
526      val ecc_bank = ecc_banks(bank_index)
527      ecc_bank.io.w.req.valid := true.B
528      ecc_bank.io.w.req.bits.apply(
529        setIdx = io.cacheOp.req.bits.index,
530        data = io.cacheOp.req.bits.write_data_ecc,
531        waymask = UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))
532      )
533    }
534    cacheOpShouldResp := true.B
535  }
536
537  io.cacheOp.resp.valid := RegNext(io.cacheOp.req.valid && cacheOpShouldResp)
538  for (bank_index <- 0 until DCacheBanks) {
539    io.cacheOp.resp.bits.read_data_vec(bank_index) := bank_result(bank_index).raw_data
540	eccReadResult(bank_index) := ecc_banks(bank_index).io.r.resp.data(RegNext(io.cacheOp.req.bits.wayNum(4, 0)))
541  }
542  io.cacheOp.resp.bits.read_data_ecc := Mux(io.cacheOp.resp.valid,
543    eccReadResult(RegNext(io.cacheOp.req.bits.bank_num)),
544    0.U
545  )
546}
547