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