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// wrap a sram 78class DataSRAM(bankIdx: Int, wayIdx: Int)(implicit p: Parameters) extends DCacheModule { 79 val io = IO(new Bundle() { 80 val w = new Bundle() { 81 val en = Input(Bool()) 82 val addr = Input(UInt()) 83 val data = Input(UInt(DCacheSRAMRowBits.W)) 84 } 85 86 val r = new Bundle() { 87 val en = Input(Bool()) 88 val addr = Input(UInt()) 89 val data = Output(UInt(DCacheSRAMRowBits.W)) 90 } 91 }) 92 93 // data sram 94 val data_sram = Module(new SRAMTemplate( 95 Bits(DCacheSRAMRowBits.W), 96 set = DCacheSets / DCacheSetDiv, 97 way = 1, 98 shouldReset = false, 99 holdRead = false, 100 singlePort = true 101 )) 102 103 data_sram.io.w.req.valid := io.w.en 104 data_sram.io.w.req.bits.apply( 105 setIdx = io.w.addr, 106 data = io.w.data, 107 waymask = 1.U 108 ) 109 data_sram.io.r.req.valid := io.r.en 110 data_sram.io.r.req.bits.apply(setIdx = io.r.addr) 111 io.r.data := data_sram.io.r.resp.data(0) 112 XSPerfAccumulate("data_sram_read_counter", data_sram.io.r.req.valid) 113 114 def dump_r() = { 115 when(RegNext(io.r.en)) { 116 XSDebug("bank read set %x bank %x way %x data %x\n", 117 RegNext(io.r.addr), 118 bankIdx.U, 119 wayIdx.U, 120 io.r.data 121 ) 122 } 123 } 124 125 def dump_w() = { 126 when(io.w.en) { 127 XSDebug("bank write set %x bank %x way %x data %x\n", 128 io.w.addr, 129 bankIdx.U, 130 wayIdx.U, 131 io.w.data 132 ) 133 } 134 } 135 136 def dump() = { 137 dump_w() 138 dump_r() 139 } 140} 141 142// wrap data rows of 8 ways 143class DataSRAMBank(index: Int)(implicit p: Parameters) extends DCacheModule { 144 val io = IO(new Bundle() { 145 val w = Input(new DataSRAMBankWriteReq) 146 147 val r = new Bundle() { 148 val en = Input(Bool()) 149 val addr = Input(UInt()) 150 val way_en = Input(UInt(DCacheWays.W)) 151 val data = Output(UInt(DCacheSRAMRowBits.W)) 152 } 153 }) 154 155 assert(RegNext(!io.w.en || PopCount(io.w.way_en) <= 1.U)) 156 assert(RegNext(!io.r.en || PopCount(io.r.way_en) <= 1.U)) 157 158 val r_way_en_reg = RegNext(io.r.way_en) 159 160 // external controls do not read and write at the same time 161 val w_info = io.w 162 // val rw_bypass = RegNext(io.w.addr === io.r.addr && io.w.way_en === io.r.way_en && io.w.en) 163 164 // multiway data bank 165 val data_bank = Array.fill(DCacheWays) { 166 Module(new SRAMTemplate( 167 Bits(DCacheSRAMRowBits.W), 168 set = DCacheSets / DCacheSetDiv, 169 way = 1, 170 shouldReset = false, 171 holdRead = false, 172 singlePort = true 173 )) 174 } 175 176 for (w <- 0 until DCacheWays) { 177 val wen = w_info.en && w_info.way_en(w) 178 data_bank(w).io.w.req.valid := wen 179 data_bank(w).io.w.req.bits.apply( 180 setIdx = w_info.addr, 181 data = w_info.data, 182 waymask = 1.U 183 ) 184 data_bank(w).io.r.req.valid := io.r.en 185 data_bank(w).io.r.req.bits.apply(setIdx = io.r.addr) 186 } 187 XSPerfAccumulate("data_read_counter", PopCount(Cat(data_bank.map(_.io.r.req.valid)))) 188 189 val half = nWays / 2 190 val data_read = data_bank.map(_.io.r.resp.data(0)) 191 val data_left = Mux1H(r_way_en_reg.tail(half), data_read.take(half)) 192 val data_right = Mux1H(r_way_en_reg.head(half), data_read.drop(half)) 193 194 val sel_low = r_way_en_reg.tail(half).orR() 195 val row_data = Mux(sel_low, data_left, data_right) 196 197 io.r.data := row_data 198 199 def dump_r() = { 200 when(RegNext(io.r.en)) { 201 XSDebug("bank read addr %x way_en %x data %x\n", 202 RegNext(io.r.addr), 203 RegNext(io.r.way_en), 204 io.r.data 205 ) 206 } 207 } 208 209 def dump_w() = { 210 when(io.w.en) { 211 XSDebug("bank write addr %x way_en %x data %x\n", 212 io.w.addr, 213 io.w.way_en, 214 io.w.data 215 ) 216 } 217 } 218 219 def dump() = { 220 dump_w() 221 dump_r() 222 } 223} 224 225// Banked DCache Data 226// ----------------------------------------------------------------- 227// | Bank0 | Bank1 | Bank2 | Bank3 | Bank4 | Bank5 | Bank6 | Bank7 | 228// ----------------------------------------------------------------- 229// | Way0 | Way0 | Way0 | Way0 | Way0 | Way0 | Way0 | Way0 | 230// | Way1 | Way1 | Way1 | Way1 | Way1 | Way1 | Way1 | Way1 | 231// | .... | .... | .... | .... | .... | .... | .... | .... | 232// ----------------------------------------------------------------- 233abstract class AbstractBankedDataArray(implicit p: Parameters) extends DCacheModule 234{ 235 val ReadlinePortErrorIndex = LoadPipelineWidth 236 val io = IO(new DCacheBundle { 237 // load pipeline read word req 238 val read = Vec(LoadPipelineWidth, Flipped(DecoupledIO(new L1BankedDataReadReq))) 239 // main pipeline read / write line req 240 val readline_intend = Input(Bool()) 241 val readline = Flipped(DecoupledIO(new L1BankedDataReadLineReq)) 242 val write = Flipped(DecoupledIO(new L1BankedDataWriteReq)) 243 val write_dup = Vec(DCacheBanks, Flipped(Decoupled(new L1BankedDataWriteReqCtrl))) 244 // data for readline and loadpipe 245 val readline_resp = Output(Vec(DCacheBanks, new L1BankedDataReadResult())) 246 val readline_error_delayed = Output(Bool()) 247 val read_resp_delayed = Output(Vec(LoadPipelineWidth, new L1BankedDataReadResult())) 248 val read_error_delayed = Output(Vec(LoadPipelineWidth, Bool())) 249 // val nacks = Output(Vec(LoadPipelineWidth, Bool())) 250 // val errors = Output(Vec(LoadPipelineWidth + 1, new L1CacheErrorInfo)) // read ports + readline port 251 // when bank_conflict, read (1) port should be ignored 252 val bank_conflict_slow = Output(Vec(LoadPipelineWidth, Bool())) 253 val disable_ld_fast_wakeup = Output(Vec(LoadPipelineWidth, Bool())) 254 // customized cache op port 255 val cacheOp = Flipped(new L1CacheInnerOpIO) 256 val cacheOp_req_dup = Vec(DCacheDupNum, Flipped(Valid(new CacheCtrlReqInfo))) 257 val cacheOp_req_bits_opCode_dup = Input(Vec(DCacheDupNum, UInt(XLEN.W))) 258 }) 259 260 def pipeMap[T <: Data](f: Int => T) = VecInit((0 until LoadPipelineWidth).map(f)) 261 262 def getECCFromEncWord(encWord: UInt) = { 263 require(encWord.getWidth == encWordBits) 264 encWord(encWordBits - 1, wordBits) 265 } 266 267 def dumpRead() = { 268 (0 until LoadPipelineWidth) map { w => 269 when(io.read(w).valid) { 270 XSDebug(s"DataArray Read channel: $w valid way_en: %x addr: %x\n", 271 io.read(w).bits.way_en, io.read(w).bits.addr) 272 } 273 } 274 when(io.readline.valid) { 275 XSDebug(s"DataArray Read Line, valid way_en: %x addr: %x rmask %x\n", 276 io.readline.bits.way_en, io.readline.bits.addr, io.readline.bits.rmask) 277 } 278 } 279 280 def dumpWrite() = { 281 when(io.write.valid) { 282 XSDebug(s"DataArray Write valid way_en: %x addr: %x\n", 283 io.write.bits.way_en, io.write.bits.addr) 284 285 (0 until DCacheBanks) map { r => 286 XSDebug(s"cycle: $r data: %x wmask: %x\n", 287 io.write.bits.data(r), io.write.bits.wmask(r)) 288 } 289 } 290 } 291 292 def dumpResp() = { 293 XSDebug(s"DataArray ReadeResp channel:\n") 294 (0 until LoadPipelineWidth) map { r => 295 XSDebug(s"cycle: $r data: %x\n", io.read_resp_delayed(r).raw_data) 296 } 297 } 298 299 def dump() = { 300 dumpRead 301 dumpWrite 302 dumpResp 303 } 304} 305 306// the smallest access unit is sram 307class SramedDataArray(implicit p: Parameters) extends AbstractBankedDataArray { 308 println(" DCacheType: SramedDataArray") 309 val ReduceReadlineConflict = false 310 311 io.write.ready := true.B 312 io.write_dup.foreach(_.ready := true.B) 313 314 val data_banks = List.tabulate(DCacheSetDiv)( k => List.tabulate(DCacheBanks)(i => List.tabulate(DCacheWays)(j => Module(new DataSRAM(i,j))))) 315 // ecc_banks also needs to be changed to two-dimensional to align with data_banks 316 val ecc_banks = List.tabulate(DCacheSetDiv)( k => 317 List.tabulate(DCacheWays)(j => 318 List.tabulate(DCacheBanks)(i => 319 Module(new SRAMTemplate( 320 Bits(eccBits.W), 321 set = DCacheSets / DCacheSetDiv, 322 way = 1, 323 shouldReset = false, 324 holdRead = false, 325 singlePort = true 326 )) 327 ))) 328 329 data_banks.map(_.map(_.map(_.dump()))) 330 331 val way_en = Wire(Vec(LoadPipelineWidth, io.read(0).bits.way_en.cloneType)) 332 val set_addrs = Wire(Vec(LoadPipelineWidth, UInt())) 333 val div_addrs = Wire(Vec(LoadPipelineWidth, UInt())) 334 val bank_addrs = Wire(Vec(LoadPipelineWidth, UInt())) 335 336 val line_set_addr = addr_to_dcache_div_set(io.readline.bits.addr) 337 val line_div_addr = addr_to_dcache_div(io.readline.bits.addr) 338 val line_way_en = io.readline.bits.way_en 339 340 val write_bank_mask_reg = RegNext(io.write.bits.wmask) 341 val write_data_reg = RegNext(io.write.bits.data) 342 val write_valid_reg = RegNext(io.write.valid) 343 val write_valid_dup_reg = io.write_dup.map(x => RegNext(x.valid)) 344 val write_wayen_dup_reg = io.write_dup.map(x => RegNext(x.bits.way_en)) 345 val write_set_addr_dup_reg = io.write_dup.map(x => RegNext(addr_to_dcache_div_set(x.bits.addr))) 346 val write_div_addr_dup_reg = io.write_dup.map(x => RegNext(addr_to_dcache_div(x.bits.addr))) 347 348 // read data_banks and ecc_banks 349 // for single port SRAM, do not allow read and write in the same cycle 350 val rrhazard = false.B // io.readline.valid 351 (0 until LoadPipelineWidth).map(rport_index => { 352 div_addrs(rport_index) := addr_to_dcache_div(io.read(rport_index).bits.addr) 353 set_addrs(rport_index) := addr_to_dcache_div_set(io.read(rport_index).bits.addr) 354 bank_addrs(rport_index) := addr_to_dcache_bank(io.read(rport_index).bits.addr) 355 356 // use way_en to select a way after data read out 357 assert(!(RegNext(io.read(rport_index).fire() && PopCount(io.read(rport_index).bits.way_en) > 1.U))) 358 way_en(rport_index) := io.read(rport_index).bits.way_en 359 }) 360 361 // read conflict 362 val rr_bank_conflict = Seq.tabulate(LoadPipelineWidth)(x => Seq.tabulate(LoadPipelineWidth)(y => 363 io.read(x).valid && io.read(y).valid && 364 div_addrs(x) === div_addrs(y) && 365 bank_addrs(x) === bank_addrs(y) && 366 io.read(x).bits.way_en === io.read(y).bits.way_en && 367 set_addrs(x) =/= set_addrs(y) 368 )) 369 val rrl_bank_conflict = Wire(Vec(LoadPipelineWidth, Bool())) 370 val rrl_bank_conflict_intend = Wire(Vec(LoadPipelineWidth, Bool())) 371 (0 until LoadPipelineWidth).foreach { i => 372 val judge = if (ReduceReadlineConflict) io.read(i).valid && io.readline.bits.rmask(bank_addrs(i)) && line_div_addr === div_addrs(i) && io.readline.bits.way_en === way_en(i) && line_set_addr =/= set_addrs(i) 373 else io.read(i).valid && line_div_addr === div_addrs(i) && io.readline.bits.way_en === way_en(i) && line_set_addr =/= set_addrs(i) 374 rrl_bank_conflict(i) := judge && io.readline.valid 375 rrl_bank_conflict_intend(i) := judge && io.readline_intend 376 } 377 val wr_bank_conflict = Seq.tabulate(LoadPipelineWidth)(x => 378 io.read(x).valid && write_valid_reg && 379 div_addrs(x) === write_div_addr_dup_reg.head && 380 way_en(x) === write_wayen_dup_reg.head && 381 write_bank_mask_reg(bank_addrs(x)) 382 ) 383 val wrl_bank_conflict = io.readline.valid && write_valid_reg && line_div_addr === write_div_addr_dup_reg.head && line_way_en === write_wayen_dup_reg.head 384 // ready 385 io.readline.ready := !(wrl_bank_conflict) 386 io.read.zipWithIndex.map { case (x, i) => x.ready := !(wr_bank_conflict(i) || rrhazard) } 387 388 val perf_multi_read = PopCount(io.read.map(_.valid)) >= 2.U 389 val bank_conflict_fast = Wire(Vec(LoadPipelineWidth, Bool())) 390 (0 until LoadPipelineWidth).foreach(i => { 391 bank_conflict_fast(i) := wr_bank_conflict(i) || rrl_bank_conflict(i) || 392 (if (i == 0) 0.B else (0 until i).map(rr_bank_conflict(_)(i)).reduce(_ || _)) 393 io.bank_conflict_slow(i) := RegNext(bank_conflict_fast(i)) 394 io.disable_ld_fast_wakeup(i) := wr_bank_conflict(i) || rrl_bank_conflict_intend(i) || 395 (if (i == 0) 0.B else (0 until i).map(rr_bank_conflict(_)(i)).reduce(_ || _)) 396 }) 397 XSPerfAccumulate("data_array_multi_read", perf_multi_read) 398 (1 until LoadPipelineWidth).foreach(y => (0 until y).foreach(x => 399 XSPerfAccumulate(s"data_array_rr_bank_conflict_${x}_${y}", rr_bank_conflict(x)(y)) 400 )) 401 (0 until LoadPipelineWidth).foreach(i => { 402 XSPerfAccumulate(s"data_array_rrl_bank_conflict_${i}", rrl_bank_conflict(i)) 403 XSPerfAccumulate(s"data_array_rw_bank_conflict_${i}", wr_bank_conflict(i)) 404 XSPerfAccumulate(s"data_array_read_${i}", io.read(i).valid) 405 }) 406 XSPerfAccumulate("data_array_access_total", PopCount(io.read.map(_.valid))) 407 XSPerfAccumulate("data_array_read_line", io.readline.valid) 408 XSPerfAccumulate("data_array_write", io.write.valid) 409 410 val read_result = Wire(Vec(DCacheSetDiv, Vec(DCacheBanks, Vec(DCacheWays,new L1BankedDataReadResult())))) 411 val read_error_delayed_result = Wire(Vec(DCacheSetDiv, Vec(DCacheBanks, Vec(DCacheWays, Bool())))) 412 dontTouch(read_result) 413 dontTouch(read_error_delayed_result) 414 for (div_index <- 0 until DCacheSetDiv){ 415 for (bank_index <- 0 until DCacheBanks) { 416 for (way_index <- 0 until DCacheWays) { 417 // Set Addr & Read Way Mask 418 // 419 // Pipe 0 .... Pipe (n-1) 420 // + .... + 421 // | .... | 422 // +----+---------------+-----+ 423 // X X 424 // X +------+ Bank Addr Match 425 // +---------+----------+ 426 // | 427 // +--------+--------+ 428 // | Data Bank | 429 // +-----------------+ 430 val loadpipe_en = WireInit(VecInit(List.tabulate(LoadPipelineWidth)(i => { 431 io.read(i).valid && div_addrs(i) === div_index.U && bank_addrs(i) === bank_index.U && way_en(i)(way_index) 432 }))) 433 val readline_en = Wire(Bool()) 434 if (ReduceReadlineConflict) { 435 readline_en := io.readline.valid && io.readline.bits.rmask(bank_index) && io.readline.bits.way_en(way_index) && div_index.U === line_div_addr 436 } else { 437 readline_en := io.readline.valid && io.readline.bits.way_en(way_index) && div_index.U === line_div_addr 438 } 439 val sram_set_addr = Mux(readline_en, 440 addr_to_dcache_div_set(io.readline.bits.addr), 441 PriorityMux(Seq.tabulate(LoadPipelineWidth)(i => loadpipe_en(i) -> set_addrs(i))) 442 ) 443 val read_en = loadpipe_en.asUInt.orR || readline_en 444 // read raw data 445 val data_bank = data_banks(div_index)(bank_index)(way_index) 446 data_bank.io.r.en := read_en 447 data_bank.io.r.addr := sram_set_addr 448 val ecc_bank = ecc_banks(div_index)(bank_index)(way_index) 449 ecc_bank.io.r.req.valid := read_en 450 ecc_bank.io.r.req.bits.apply(setIdx = sram_set_addr) 451 452 read_result(div_index)(bank_index)(way_index).raw_data := data_bank.io.r.data 453 read_result(div_index)(bank_index)(way_index).ecc := ecc_bank.io.r.resp.data(0) 454 455 // use ECC to check error 456 val ecc_data = read_result(div_index)(bank_index)(way_index).asECCData() 457 val ecc_data_delayed = RegEnable(ecc_data, RegNext(read_en)) 458 read_result(div_index)(bank_index)(way_index).error_delayed := dcacheParameters.dataCode.decode(ecc_data_delayed).error 459 read_error_delayed_result(div_index)(bank_index)(way_index) := read_result(div_index)(bank_index)(way_index).error_delayed 460 } 461 } 462 } 463 464 // read result: expose banked read result 465 val read_result_delayed = RegNext(read_result) 466 (0 until LoadPipelineWidth).map(i => { 467 // io.read_resp(i) := read_result(RegNext(bank_addrs(i)))(RegNext(OHToUInt(way_en(i)))) 468 val rr_read_fire = RegNext(RegNext(io.read(i).fire)) 469 val rr_div_addr = RegNext(RegNext(div_addrs(i))) 470 val rr_bank_addr = RegNext(RegNext(bank_addrs(i))) 471 val rr_way_addr = RegNext(RegNext(OHToUInt(way_en(i)))) 472 io.read_resp_delayed(i) := read_result_delayed(rr_div_addr)(rr_bank_addr)(rr_way_addr) 473 // error detection 474 // normal read ports 475 io.read_error_delayed(i) := rr_read_fire && read_error_delayed_result(rr_div_addr)(rr_bank_addr)(rr_way_addr) && !RegNext(io.bank_conflict_slow(i)) 476 }) 477 478 // readline port 479 (0 until DCacheBanks).map(i => { 480 io.readline_resp(i) := read_result(RegNext(line_div_addr))(i)(RegNext(OHToUInt(io.readline.bits.way_en))) 481 }) 482 io.readline_error_delayed := RegNext(RegNext(io.readline.fire())) && 483 VecInit((0 until DCacheBanks).map(i => io.readline_resp(i).error_delayed)).asUInt().orR 484 485 // write data_banks & ecc_banks 486 for (div_index <- 0 until DCacheSetDiv) { 487 for (bank_index <- 0 until DCacheBanks) { 488 for (way_index <- 0 until DCacheWays) { 489 // data write 490 val wen_reg = write_bank_mask_reg(bank_index) && 491 write_valid_dup_reg(bank_index) && 492 write_div_addr_dup_reg(bank_index) === div_index.U && 493 write_wayen_dup_reg(bank_index)(way_index) 494 val data_bank = data_banks(div_index)(bank_index)(way_index) 495 data_bank.io.w.en := wen_reg 496 497 data_bank.io.w.addr := write_set_addr_dup_reg(bank_index) 498 data_bank.io.w.data := write_data_reg(bank_index) 499 // ecc write 500 val ecc_bank = ecc_banks(div_index)(bank_index)(way_index) 501 ecc_bank.io.w.req.valid := wen_reg 502 ecc_bank.io.w.req.bits.apply( 503 setIdx = write_set_addr_dup_reg(bank_index), 504 data = RegNext(getECCFromEncWord(cacheParams.dataCode.encode((io.write.bits.data(bank_index))))), 505 waymask = 1.U 506 ) 507 when(ecc_bank.io.w.req.valid) { 508 XSDebug("write in ecc sram: bank %x set %x data %x waymask %x\n", 509 bank_index.U, 510 addr_to_dcache_div_set(io.write.bits.addr), 511 getECCFromEncWord(cacheParams.dataCode.encode((io.write.bits.data(bank_index)))), 512 io.write.bits.way_en 513 ); 514 } 515 } 516 } 517 } 518 519 require(nWays <= 32) 520 io.cacheOp.resp.bits := DontCare 521 val cacheOpShouldResp = WireInit(false.B) 522 val eccReadResult = Wire(Vec(DCacheBanks, UInt(eccBits.W))) 523 // DCacheDupNum is 16 524 // vec: the dupIdx for every bank and every group 525 val rdata_dup_vec = Seq(0,0,1,1,2,2,3,3) 526 val rdataEcc_dup_vec = Seq(4,4,5,5,6,6,7,7) 527 val wdata_dup_vec = Seq(8,8,9,9,10,10,11,11) 528 val wdataEcc_dup_vec = Seq(12,12,13,13,14,14,15,15) 529 val cacheOpDivAddr = set_to_dcache_div(io.cacheOp.req.bits.index) 530 val cacheOpSetAddr = set_to_dcache_div_set(io.cacheOp.req.bits.index) 531 val cacheOpWayNum = io.cacheOp.req.bits.wayNum(4, 0) 532 rdata_dup_vec.zipWithIndex.map{ case(dupIdx, bankIdx) => 533 for (divIdx <- 0 until DCacheSetDiv){ 534 for (wayIdx <- 0 until DCacheWays) { 535 when(io.cacheOp_req_dup(dupIdx).valid && CacheInstrucion.isReadData(io.cacheOp_req_bits_opCode_dup(dupIdx))) { 536 val data_bank = data_banks(divIdx)(bankIdx)(wayIdx) 537 data_bank.io.r.en := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))(wayIdx) && cacheOpDivAddr === divIdx.U 538 data_bank.io.r.addr := cacheOpSetAddr 539 cacheOpShouldResp := true.B 540 } 541 } 542 } 543 } 544 rdataEcc_dup_vec.zipWithIndex.map{ case(dupIdx, bankIdx) => 545 for (divIdx <- 0 until DCacheSetDiv) { 546 for (wayIdx <- 0 until DCacheWays) { 547 when(io.cacheOp_req_dup(dupIdx).valid && CacheInstrucion.isReadDataECC(io.cacheOp_req_bits_opCode_dup(dupIdx))) { 548 val ecc_bank = ecc_banks(divIdx)(bankIdx)(wayIdx) 549 ecc_bank.io.r.req.valid := true.B 550 ecc_bank.io.r.req.bits.setIdx := cacheOpSetAddr 551 cacheOpShouldResp := true.B 552 } 553 } 554 } 555 } 556 wdata_dup_vec.zipWithIndex.map{ case(dupIdx, bankIdx) => 557 for (divIdx <- 0 until DCacheSetDiv) { 558 for (wayIdx <- 0 until DCacheWays) { 559 when(io.cacheOp_req_dup(dupIdx).valid && CacheInstrucion.isWriteData(io.cacheOp_req_bits_opCode_dup(dupIdx))) { 560 val data_bank = data_banks(divIdx)(bankIdx)(wayIdx) 561 data_bank.io.w.en := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))(wayIdx) && cacheOpDivAddr === divIdx.U 562 data_bank.io.w.addr := cacheOpSetAddr 563 data_bank.io.w.data := io.cacheOp.req.bits.write_data_vec(bankIdx) 564 cacheOpShouldResp := true.B 565 } 566 } 567 } 568 } 569 wdataEcc_dup_vec.zipWithIndex.map{ case(dupIdx, bankIdx) => 570 for (divIdx <- 0 until DCacheSetDiv) { 571 for (wayIdx <- 0 until DCacheWays) { 572 when(io.cacheOp_req_dup(dupIdx).valid && CacheInstrucion.isWriteDataECC(io.cacheOp_req_bits_opCode_dup(dupIdx))) { 573 val ecc_bank = ecc_banks(divIdx)(bankIdx)(wayIdx) 574 ecc_bank.io.w.req.valid := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))(wayIdx) && cacheOpDivAddr === divIdx.U 575 ecc_bank.io.w.req.bits.apply( 576 setIdx = cacheOpSetAddr, 577 data = io.cacheOp.req.bits.write_data_ecc, 578 waymask = 1.U 579 ) 580 cacheOpShouldResp := true.B 581 } 582 } 583 } 584 } 585 586 io.cacheOp.resp.valid := RegNext(io.cacheOp.req.valid && cacheOpShouldResp) 587 for (bank_index <- 0 until DCacheBanks) { 588 io.cacheOp.resp.bits.read_data_vec(bank_index) := read_result(RegNext(cacheOpDivAddr))(bank_index)(RegNext(cacheOpWayNum)).raw_data 589 eccReadResult(bank_index) := read_result(RegNext(cacheOpDivAddr))(bank_index)(RegNext(cacheOpWayNum)).ecc 590 } 591 592 io.cacheOp.resp.bits.read_data_ecc := Mux(io.cacheOp.resp.valid, 593 eccReadResult(RegNext(io.cacheOp.req.bits.bank_num)), 594 0.U 595 ) 596 597 val tableName = "BankConflict" + p(XSCoreParamsKey).HartId.toString 598 val siteName = "BankedDataArray" + p(XSCoreParamsKey).HartId.toString 599 val bankConflictTable = ChiselDB.createTable(tableName, new BankConflictDB) 600 val bankConflictData = Wire(new BankConflictDB) 601 for (i <- 0 until LoadPipelineWidth) { 602 bankConflictData.set_index(i) := set_addrs(i) 603 bankConflictData.addr(i) := io.read(i).bits.addr 604 } 605 606 // FIXME: rr_bank_conflict(0)(1) no generalization 607 when(rr_bank_conflict(0)(1)) { 608 bankConflictData.bank_index := bank_addrs(0) 609 bankConflictData.way_index := OHToUInt(way_en(0)) 610 bankConflictData.fake_rr_bank_conflict := set_addrs(0) === set_addrs(1) && div_addrs(0) === div_addrs(1) 611 }.otherwise { 612 bankConflictData.bank_index := 0.U 613 bankConflictData.way_index := 0.U 614 bankConflictData.fake_rr_bank_conflict := false.B 615 } 616 617 val isWriteBankConflictTable = WireInit(Constantin.createRecord("isWriteBankConflictTable" + p(XSCoreParamsKey).HartId.toString)) 618 bankConflictTable.log( 619 data = bankConflictData, 620 en = isWriteBankConflictTable.orR && rr_bank_conflict(0)(1), 621 site = siteName, 622 clock = clock, 623 reset = reset 624 ) 625 626 (1 until LoadPipelineWidth).foreach(y => (0 until y).foreach(x => 627 XSPerfAccumulate(s"data_array_fake_rr_bank_conflict_${x}_${y}", rr_bank_conflict(x)(y) && set_addrs(x)===set_addrs(y)) 628 )) 629 630} 631 632// the smallest access unit is bank 633class BankedDataArray(implicit p: Parameters) extends AbstractBankedDataArray { 634 println(" DCacheType: BankedDataArray") 635 val ReduceReadlineConflict = false 636 637 io.write.ready := true.B 638 io.write_dup.foreach(_.ready := true.B) 639 640 val data_banks = List.fill(DCacheSetDiv)(List.tabulate(DCacheBanks)(i => Module(new DataSRAMBank(i)))) 641 val ecc_banks = List.fill(DCacheSetDiv)(List.fill(DCacheBanks)(Module(new SRAMTemplate( 642 Bits(eccBits.W), 643 set = DCacheSets / DCacheSetDiv, 644 way = DCacheWays, 645 shouldReset = false, 646 holdRead = false, 647 singlePort = true 648 )))) 649 650 data_banks.map(_.map(_.dump())) 651 652 val way_en = Wire(Vec(LoadPipelineWidth, io.read(0).bits.way_en.cloneType)) 653 val set_addrs = Wire(Vec(LoadPipelineWidth, UInt())) 654 val div_addrs = Wire(Vec(LoadPipelineWidth, UInt())) 655 val bank_addrs = Wire(Vec(LoadPipelineWidth, UInt())) 656 val way_en_reg = Wire(Vec(LoadPipelineWidth, io.read(0).bits.way_en.cloneType)) 657 val set_addrs_reg = Wire(Vec(LoadPipelineWidth, UInt())) 658 659 val line_set_addr = addr_to_dcache_div_set(io.readline.bits.addr) 660 val line_div_addr = addr_to_dcache_div(io.readline.bits.addr) 661 val line_way_en = io.readline.bits.way_en 662 663 val write_bank_mask_reg = RegNext(io.write.bits.wmask) 664 val write_data_reg = RegNext(io.write.bits.data) 665 val write_valid_reg = RegNext(io.write.valid) 666 val write_valid_dup_reg = io.write_dup.map(x => RegNext(x.valid)) 667 val write_wayen_dup_reg = io.write_dup.map(x => RegNext(x.bits.way_en)) 668 val write_set_addr_dup_reg = io.write_dup.map(x => RegNext(addr_to_dcache_div_set(x.bits.addr))) 669 val write_div_addr_dup_reg = io.write_dup.map(x => RegNext(addr_to_dcache_div(x.bits.addr))) 670 671 // read data_banks and ecc_banks 672 // for single port SRAM, do not allow read and write in the same cycle 673 val rwhazard = RegNext(io.write.valid) 674 val rrhazard = false.B // io.readline.valid 675 (0 until LoadPipelineWidth).map(rport_index => { 676 div_addrs(rport_index) := addr_to_dcache_div(io.read(rport_index).bits.addr) 677 bank_addrs(rport_index) := addr_to_dcache_bank(io.read(rport_index).bits.addr) 678 set_addrs(rport_index) := addr_to_dcache_div_set(io.read(rport_index).bits.addr) 679 set_addrs_reg(rport_index) := RegNext(addr_to_dcache_div_set(io.read(rport_index).bits.addr)) 680 681 // use way_en to select a way after data read out 682 assert(!(RegNext(io.read(rport_index).fire() && PopCount(io.read(rport_index).bits.way_en) > 1.U))) 683 way_en(rport_index) := io.read(rport_index).bits.way_en 684 way_en_reg(rport_index) := RegNext(io.read(rport_index).bits.way_en) 685 }) 686 687 // read each bank, get bank result 688 val rr_bank_conflict = Seq.tabulate(LoadPipelineWidth)(x => Seq.tabulate(LoadPipelineWidth)(y => 689 io.read(x).valid && io.read(y).valid && 690 div_addrs(x)===div_addrs(y) && 691 bank_addrs(x) === bank_addrs(y) 692 )) 693 val rrl_bank_conflict = Wire(Vec(LoadPipelineWidth, Bool())) 694 val rrl_bank_conflict_intend = Wire(Vec(LoadPipelineWidth, Bool())) 695 (0 until LoadPipelineWidth).foreach { i => 696 val judge = if (ReduceReadlineConflict) io.read(i).valid && io.readline.bits.rmask(bank_addrs(i)) && div_addrs(i)===line_div_addr 697 else io.read(i).valid && div_addrs(i)===line_div_addr 698 rrl_bank_conflict(i) := judge && io.readline.valid 699 rrl_bank_conflict_intend(i) := judge && io.readline_intend 700 } 701 val wr_bank_conflict = Seq.tabulate(LoadPipelineWidth)(x => 702 io.read(x).valid && write_valid_reg && div_addrs(x) === write_div_addr_dup_reg.head && write_bank_mask_reg(bank_addrs(x)) 703 ) 704 val wrl_bank_conflict = io.readline.valid && write_valid_reg && line_div_addr === write_div_addr_dup_reg.head 705 // ready 706 io.readline.ready := !(wrl_bank_conflict) 707 io.read.zipWithIndex.map{case(x, i) => x.ready := !(wr_bank_conflict(i) || rrhazard)} 708 709 val perf_multi_read = PopCount(io.read.map(_.valid)) >= 2.U 710 (0 until LoadPipelineWidth).foreach(i => { 711 // remove fake rr_bank_conflict situation in s2 712 val real_other_bank_conflict_reg = RegNext(wr_bank_conflict(i) || rrl_bank_conflict(i)) 713 val real_rr_bank_conflict_reg = (if (i == 0) 0.B else (0 until i).map{ j => 714 RegNext(rr_bank_conflict(j)(i)) && 715 (way_en_reg(j) =/= way_en_reg(i) || set_addrs_reg(j) =/= set_addrs_reg(i)) 716 }.reduce(_ || _)) 717 io.bank_conflict_slow(i) := real_other_bank_conflict_reg || real_rr_bank_conflict_reg 718 719 // get result in s1 720 io.disable_ld_fast_wakeup(i) := wr_bank_conflict(i) || rrl_bank_conflict_intend(i) || 721 (if (i == 0) 0.B else (0 until i).map(rr_bank_conflict(_)(i)).reduce(_ || _)) 722 }) 723 XSPerfAccumulate("data_array_multi_read", perf_multi_read) 724 (1 until LoadPipelineWidth).foreach(y => (0 until y).foreach(x => 725 XSPerfAccumulate(s"data_array_rr_bank_conflict_${x}_${y}", rr_bank_conflict(x)(y)) 726 )) 727 (0 until LoadPipelineWidth).foreach(i => { 728 XSPerfAccumulate(s"data_array_rrl_bank_conflict_${i}", rrl_bank_conflict(i)) 729 XSPerfAccumulate(s"data_array_rw_bank_conflict_${i}", wr_bank_conflict(i)) 730 XSPerfAccumulate(s"data_array_read_${i}", io.read(i).valid) 731 }) 732 XSPerfAccumulate("data_array_access_total", PopCount(io.read.map(_.valid))) 733 XSPerfAccumulate("data_array_read_line", io.readline.valid) 734 XSPerfAccumulate("data_array_write", io.write.valid) 735 736 val bank_result = Wire(Vec(DCacheSetDiv, Vec(DCacheBanks, new L1BankedDataReadResult()))) 737 val ecc_result = Wire(Vec(DCacheSetDiv, Vec(DCacheBanks, Vec(DCacheWays, UInt(eccBits.W))))) 738 val read_bank_error_delayed = Wire(Vec(DCacheSetDiv, Vec(DCacheBanks, Bool()))) 739 dontTouch(bank_result) 740 dontTouch(read_bank_error_delayed) 741 for (div_index <- 0 until DCacheSetDiv) { 742 for (bank_index <- 0 until DCacheBanks) { 743 // Set Addr & Read Way Mask 744 // 745 // Pipe 0 .... Pipe (n-1) 746 // + .... + 747 // | .... | 748 // +----+---------------+-----+ 749 // X X 750 // X +------+ Bank Addr Match 751 // +---------+----------+ 752 // | 753 // +--------+--------+ 754 // | Data Bank | 755 // +-----------------+ 756 val bank_addr_matchs = WireInit(VecInit(List.tabulate(LoadPipelineWidth)(i => { 757 io.read(i).valid && div_addrs(i) === div_index.U && bank_addrs(i) === bank_index.U 758 }))) 759 val readline_match = Wire(Bool()) 760 if (ReduceReadlineConflict) { 761 readline_match := io.readline.valid && io.readline.bits.rmask(bank_index) && line_div_addr === div_index.U 762 } else { 763 readline_match := io.readline.valid && line_div_addr === div_index.U 764 } 765 val bank_way_en = Mux(readline_match, 766 io.readline.bits.way_en, 767 PriorityMux(Seq.tabulate(LoadPipelineWidth)(i => bank_addr_matchs(i) -> way_en(i))) 768 ) 769 // it is too long of bank_way_en's caculation, so bank_way_en_reg can not be caculated by RegNext(bank_way_en) 770 val bank_way_en_reg = Mux(RegNext(readline_match), 771 RegNext(io.readline.bits.way_en), 772 PriorityMux(Seq.tabulate(LoadPipelineWidth)(i => RegNext(bank_addr_matchs(i)) -> RegNext(way_en(i)))) 773 ) 774 val bank_set_addr = Mux(readline_match, 775 line_set_addr, 776 PriorityMux(Seq.tabulate(LoadPipelineWidth)(i => bank_addr_matchs(i) -> set_addrs(i))) 777 ) 778 779 val read_enable = bank_addr_matchs.asUInt.orR || readline_match 780 781 // read raw data 782 val data_bank = data_banks(div_index)(bank_index) 783 data_bank.io.r.en := read_enable 784 data_bank.io.r.way_en := bank_way_en 785 data_bank.io.r.addr := bank_set_addr 786 bank_result(div_index)(bank_index).raw_data := data_bank.io.r.data 787 788 // read ECC 789 val ecc_bank = ecc_banks(div_index)(bank_index) 790 ecc_bank.io.r.req.valid := read_enable 791 ecc_bank.io.r.req.bits.apply(setIdx = bank_set_addr) 792 ecc_result(div_index)(bank_index) := ecc_bank.io.r.resp.data 793 bank_result(div_index)(bank_index).ecc := Mux1H(bank_way_en_reg, ecc_bank.io.r.resp.data) 794 795 // use ECC to check error 796 val ecc_data = bank_result(div_index)(bank_index).asECCData() 797 val ecc_data_delayed = RegEnable(ecc_data, RegNext(read_enable)) 798 bank_result(div_index)(bank_index).error_delayed := dcacheParameters.dataCode.decode(ecc_data_delayed).error 799 read_bank_error_delayed(div_index)(bank_index) := bank_result(div_index)(bank_index).error_delayed 800 } 801 } 802 803 val bank_result_delayed = RegNext(bank_result) 804 (0 until LoadPipelineWidth).map(i => { 805 val rr_read_fire = RegNext(RegNext(io.read(i).fire)) 806 val rr_div_addr = RegNext(RegNext(div_addrs(i))) 807 val rr_bank_addr = RegNext(RegNext(bank_addrs(i))) 808 val rr_way_addr = RegNext(RegNext(OHToUInt(way_en(i)))) 809 io.read_resp_delayed(i) := bank_result_delayed(rr_div_addr)(rr_bank_addr) 810 // error detection 811 io.read_error_delayed(i) := rr_read_fire && read_bank_error_delayed(rr_div_addr)(rr_bank_addr) && !RegNext(io.bank_conflict_slow(i)) 812 813 }) 814 815 // read result: expose banked read result 816 io.readline_resp := bank_result(RegNext(line_div_addr)) 817 io.readline_error_delayed := RegNext(RegNext(io.readline.fire())) && 818 VecInit((0 until DCacheBanks).map(i => io.readline_resp(i).error_delayed)).asUInt().orR 819 820 // write data_banks & ecc_banks 821 for (div_index <- 0 until DCacheSetDiv) { 822 for (bank_index <- 0 until DCacheBanks) { 823 // data write 824 val wen_reg = write_bank_mask_reg(bank_index) && 825 write_valid_dup_reg(bank_index) && 826 write_div_addr_dup_reg(bank_index) === div_index.U 827 val data_bank = data_banks(div_index)(bank_index) 828 data_bank.io.w.en := wen_reg 829 data_bank.io.w.way_en := write_wayen_dup_reg(bank_index) 830 data_bank.io.w.addr := write_set_addr_dup_reg(bank_index) 831 data_bank.io.w.data := write_data_reg(bank_index) 832 833 // ecc write 834 val ecc_bank = ecc_banks(div_index)(bank_index) 835 ecc_bank.io.w.req.valid := wen_reg 836 ecc_bank.io.w.req.bits.apply( 837 setIdx = write_set_addr_dup_reg(bank_index), 838 data = RegNext(getECCFromEncWord(cacheParams.dataCode.encode((io.write.bits.data(bank_index))))), 839 waymask = write_wayen_dup_reg(bank_index) 840 ) 841 when(ecc_bank.io.w.req.valid) { 842 XSDebug("write in ecc sram: bank %x set %x data %x waymask %x\n", 843 bank_index.U, 844 addr_to_dcache_div_set(io.write.bits.addr), 845 getECCFromEncWord(cacheParams.dataCode.encode((io.write.bits.data(bank_index)))), 846 io.write.bits.way_en 847 ); 848 } 849 } 850 } 851 852 // deal with customized cache op 853 require(nWays <= 32) 854 io.cacheOp.resp.bits := DontCare 855 val cacheOpShouldResp = WireInit(false.B) 856 val eccReadResult = Wire(Vec(DCacheBanks, UInt(eccBits.W))) 857 // DCacheDupNum is 16 858 // vec: the dupIdx for every bank and every group 859 val rdata_dup_vec = Seq(0, 0, 1, 1, 2, 2, 3, 3) 860 val rdataEcc_dup_vec = Seq(4, 4, 5, 5, 6, 6, 7, 7) 861 val wdata_dup_vec = Seq(8, 8, 9, 9, 10, 10, 11, 11) 862 val wdataEcc_dup_vec = Seq(12, 12, 13, 13, 14, 14, 15, 15) 863 val cacheOpDivAddr = set_to_dcache_div(io.cacheOp.req.bits.index) 864 val cacheOpSetAddr = set_to_dcache_div_set(io.cacheOp.req.bits.index) 865 val cacheOpWayMask = UIntToOH(io.cacheOp.req.bits.wayNum(4, 0)) 866 rdata_dup_vec.zipWithIndex.map{ case(dupIdx, bankIdx) => 867 for (divIdx <- 0 until DCacheSetDiv) { 868 when(io.cacheOp_req_dup(dupIdx).valid && CacheInstrucion.isReadData(io.cacheOp_req_bits_opCode_dup(dupIdx))) { 869 val data_bank = data_banks(divIdx)(bankIdx) 870 data_bank.io.r.en := true.B 871 data_bank.io.r.way_en := cacheOpWayMask 872 data_bank.io.r.addr := cacheOpSetAddr 873 cacheOpShouldResp := true.B 874 } 875 } 876 } 877 rdataEcc_dup_vec.zipWithIndex.map{ case(dupIdx, bankIdx) => 878 for (divIdx <- 0 until DCacheSetDiv) { 879 when(io.cacheOp_req_dup(dupIdx).valid && CacheInstrucion.isReadDataECC(io.cacheOp_req_bits_opCode_dup(dupIdx))) { 880 val ecc_bank = ecc_banks(divIdx)(bankIdx) 881 ecc_bank.io.r.req.valid := true.B 882 ecc_bank.io.r.req.bits.setIdx := cacheOpSetAddr 883 cacheOpShouldResp := true.B 884 } 885 } 886 } 887 wdata_dup_vec.zipWithIndex.map{ case(dupIdx, bankIdx) => 888 for (divIdx <- 0 until DCacheSetDiv) { 889 when(io.cacheOp_req_dup(dupIdx).valid && CacheInstrucion.isWriteData(io.cacheOp_req_bits_opCode_dup(dupIdx))) { 890 val data_bank = data_banks(divIdx)(bankIdx) 891 data_bank.io.w.en := cacheOpDivAddr === divIdx.U 892 data_bank.io.w.way_en := cacheOpWayMask 893 data_bank.io.w.addr := cacheOpSetAddr 894 data_bank.io.w.data := io.cacheOp.req.bits.write_data_vec(bankIdx) 895 cacheOpShouldResp := true.B 896 } 897 } 898 } 899 wdataEcc_dup_vec.zipWithIndex.map{ case(dupIdx, bankIdx) => 900 for (divIdx <- 0 until DCacheSetDiv) { 901 when(io.cacheOp_req_dup(dupIdx).valid && CacheInstrucion.isWriteDataECC(io.cacheOp_req_bits_opCode_dup(dupIdx))) { 902 val ecc_bank = ecc_banks(divIdx)(bankIdx) 903 ecc_bank.io.w.req.valid := cacheOpDivAddr === divIdx.U 904 ecc_bank.io.w.req.bits.apply( 905 setIdx = cacheOpSetAddr, 906 data = io.cacheOp.req.bits.write_data_ecc, 907 waymask = cacheOpWayMask 908 ) 909 cacheOpShouldResp := true.B 910 } 911 } 912 } 913 914 io.cacheOp.resp.valid := RegNext(io.cacheOp.req.valid && cacheOpShouldResp) 915 for (bank_index <- 0 until DCacheBanks) { 916 io.cacheOp.resp.bits.read_data_vec(bank_index) := bank_result(RegNext(cacheOpDivAddr))(bank_index).raw_data 917 eccReadResult(bank_index) := Mux1H(RegNext(cacheOpWayMask), ecc_result(RegNext(cacheOpDivAddr))(bank_index)) 918 } 919 920 io.cacheOp.resp.bits.read_data_ecc := Mux(io.cacheOp.resp.valid, 921 eccReadResult(RegNext(io.cacheOp.req.bits.bank_num)), 922 0.U 923 ) 924 925 val tableName = "BankConflict" + p(XSCoreParamsKey).HartId.toString 926 val siteName = "BankedDataArray" + p(XSCoreParamsKey).HartId.toString 927 val bankConflictTable = ChiselDB.createTable(tableName, new BankConflictDB) 928 val bankConflictData = Wire(new BankConflictDB) 929 for (i <- 0 until LoadPipelineWidth) { 930 bankConflictData.set_index(i) := set_addrs(i) 931 bankConflictData.addr(i) := io.read(i).bits.addr 932 } 933 934 // FIXME: rr_bank_conflict(0)(1) no generalization 935 when(rr_bank_conflict(0)(1)) { 936 bankConflictData.bank_index := bank_addrs(0) 937 bankConflictData.way_index := OHToUInt(way_en(0)) 938 bankConflictData.fake_rr_bank_conflict := set_addrs(0) === set_addrs(1) && div_addrs(0) === div_addrs(1) 939 }.otherwise { 940 bankConflictData.bank_index := 0.U 941 bankConflictData.way_index := 0.U 942 bankConflictData.fake_rr_bank_conflict := false.B 943 } 944 945 val isWriteBankConflictTable = WireInit(Constantin.createRecord("isWriteBankConflictTable" + p(XSCoreParamsKey).HartId.toString)) 946 bankConflictTable.log( 947 data = bankConflictData, 948 en = isWriteBankConflictTable.orR && rr_bank_conflict(0)(1), 949 site = siteName, 950 clock = clock, 951 reset = reset 952 ) 953 954 (1 until LoadPipelineWidth).foreach(y => (0 until y).foreach(x => 955 XSPerfAccumulate(s"data_array_fake_rr_bank_conflict_${x}_${y}", rr_bank_conflict(x)(y) && set_addrs(x) === set_addrs(y)) 956 )) 957 958}