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