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