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