11f0e2dc7SJiawei Lin/*************************************************************************************** 2e3da8badSTang Haojin* Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC) 3e3da8badSTang Haojin* Copyright (c) 2020-2024 Institute of Computing Technology, Chinese Academy of Sciences 41f0e2dc7SJiawei Lin* Copyright (c) 2020-2021 Peng Cheng Laboratory 51f0e2dc7SJiawei Lin* 61f0e2dc7SJiawei Lin* XiangShan is licensed under Mulan PSL v2. 71f0e2dc7SJiawei Lin* You can use this software according to the terms and conditions of the Mulan PSL v2. 81f0e2dc7SJiawei Lin* You may obtain a copy of Mulan PSL v2 at: 91f0e2dc7SJiawei Lin* http://license.coscl.org.cn/MulanPSL2 101f0e2dc7SJiawei Lin* 111f0e2dc7SJiawei Lin* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 121f0e2dc7SJiawei Lin* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 131f0e2dc7SJiawei Lin* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 141f0e2dc7SJiawei Lin* 151f0e2dc7SJiawei Lin* See the Mulan PSL v2 for more details. 16c49ebec8SHaoyuan Feng* 17c49ebec8SHaoyuan Feng* 18c49ebec8SHaoyuan Feng* Acknowledgement 19c49ebec8SHaoyuan Feng* 20c49ebec8SHaoyuan Feng* This implementation is inspired by several key papers: 21c49ebec8SHaoyuan Feng* [1] Gurindar S. Sohi, and Manoj Franklin. "[High-bandwidth data memory systems for superscalar processors.] 22c49ebec8SHaoyuan Feng* (https://doi.org/10.1145/106972.106980)" 4th International Conference on Architectural Support for Programming 23c49ebec8SHaoyuan Feng* Languages and Operating Systems (ASPLOS). 1991. 241f0e2dc7SJiawei Lin***************************************************************************************/ 251f0e2dc7SJiawei Lin 261f0e2dc7SJiawei Linpackage xiangshan.cache 271f0e2dc7SJiawei Lin 288891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters 291f0e2dc7SJiawei Linimport chisel3._ 300f59c834SWilliam Wangimport utils._ 313c02ee8fSwakafaimport utility._ 3211269ca7STang Haojinimport utility.sram.SRAMTemplate 331f0e2dc7SJiawei Linimport chisel3.util._ 344b2c87baS梁森 Liang Senimport utility.mbist.MbistPipeline 358ffb12e4SAnzoimport xiangshan.mem.LqPtr 36144422dcSMaxpicca-Liimport xiangshan.{L1CacheErrorInfo, XSCoreParamsKey} 371f0e2dc7SJiawei Lin 381f0e2dc7SJiawei Linimport scala.math.max 391f0e2dc7SJiawei Lin 40144422dcSMaxpicca-Liclass BankConflictDB(implicit p: Parameters) extends DCacheBundle{ 41144422dcSMaxpicca-Li val addr = Vec(LoadPipelineWidth, Bits(PAddrBits.W)) 42144422dcSMaxpicca-Li val set_index = Vec(LoadPipelineWidth, UInt((DCacheAboveIndexOffset - DCacheSetOffset).W)) 43cdbff57cSHaoyuan Feng val bank_index = Vec(VLEN/DCacheSRAMRowBits, UInt((DCacheSetOffset - DCacheBankOffset).W)) 44144422dcSMaxpicca-Li val way_index = UInt(wayBits.W) 45144422dcSMaxpicca-Li val fake_rr_bank_conflict = Bool() 46144422dcSMaxpicca-Li} 47144422dcSMaxpicca-Li 481f0e2dc7SJiawei Linclass L1BankedDataReadReq(implicit p: Parameters) extends DCacheBundle 491f0e2dc7SJiawei Lin{ 501f0e2dc7SJiawei Lin val way_en = Bits(DCacheWays.W) 511f0e2dc7SJiawei Lin val addr = Bits(PAddrBits.W) 521f0e2dc7SJiawei Lin} 531f0e2dc7SJiawei Lin 54cdbff57cSHaoyuan Fengclass L1BankedDataReadReqWithMask(implicit p: Parameters) extends DCacheBundle 55cdbff57cSHaoyuan Feng{ 56cdbff57cSHaoyuan Feng val way_en = Bits(DCacheWays.W) 57cdbff57cSHaoyuan Feng val addr = Bits(PAddrBits.W) 58fa5e530dScz4e val addr_dup = Bits(PAddrBits.W) 59cdbff57cSHaoyuan Feng val bankMask = Bits(DCacheBanks.W) 60a5f58fbcSlixin val kill = Bool() 618ffb12e4SAnzo val lqIdx = new LqPtr 62cdbff57cSHaoyuan Feng} 63cdbff57cSHaoyuan Feng 641f0e2dc7SJiawei Linclass L1BankedDataReadLineReq(implicit p: Parameters) extends L1BankedDataReadReq 651f0e2dc7SJiawei Lin{ 661f0e2dc7SJiawei Lin val rmask = Bits(DCacheBanks.W) 671f0e2dc7SJiawei Lin} 681f0e2dc7SJiawei Lin 691f0e2dc7SJiawei Lin// Now, we can write a cache-block in a single cycle 701f0e2dc7SJiawei Linclass L1BankedDataWriteReq(implicit p: Parameters) extends L1BankedDataReadReq 711f0e2dc7SJiawei Lin{ 721f0e2dc7SJiawei Lin val wmask = Bits(DCacheBanks.W) 731f0e2dc7SJiawei Lin val data = Vec(DCacheBanks, Bits(DCacheSRAMRowBits.W)) 741f0e2dc7SJiawei Lin} 751f0e2dc7SJiawei Lin 766c7e5e86Szhanglinjuan// cache-block write request without data 776c7e5e86Szhanglinjuanclass L1BankedDataWriteReqCtrl(implicit p: Parameters) extends L1BankedDataReadReq 786c7e5e86Szhanglinjuan 791f0e2dc7SJiawei Linclass L1BankedDataReadResult(implicit p: Parameters) extends DCacheBundle 801f0e2dc7SJiawei Lin{ 811f0e2dc7SJiawei Lin // you can choose which bank to read to save power 82b34797bcScz4e val ecc = Bits(dataECCBits.W) 831f0e2dc7SJiawei Lin val raw_data = Bits(DCacheSRAMRowBits.W) 846786cfb7SWilliam Wang val error_delayed = Bool() // 1 cycle later than data resp 851f0e2dc7SJiawei Lin 861f0e2dc7SJiawei Lin def asECCData() = { 871f0e2dc7SJiawei Lin Cat(ecc, raw_data) 881f0e2dc7SJiawei Lin } 891f0e2dc7SJiawei Lin} 901f0e2dc7SJiawei Lin 91ea329fc7Szhanglinjuanclass DataSRAMBankWriteReq(implicit p: Parameters) extends DCacheBundle { 92ea329fc7Szhanglinjuan val en = Bool() 93ea329fc7Szhanglinjuan val addr = UInt() 94ea329fc7Szhanglinjuan val way_en = UInt(DCacheWays.W) 95b34797bcScz4e val data = UInt(encDataBits.W) 96ea329fc7Szhanglinjuan} 97ea329fc7Szhanglinjuan 987dbf3a33SMaxpicca-Li// wrap a sram 997dbf3a33SMaxpicca-Liclass DataSRAM(bankIdx: Int, wayIdx: Int)(implicit p: Parameters) extends DCacheModule { 1007dbf3a33SMaxpicca-Li val io = IO(new Bundle() { 1017dbf3a33SMaxpicca-Li val w = new Bundle() { 1027dbf3a33SMaxpicca-Li val en = Input(Bool()) 1037dbf3a33SMaxpicca-Li val addr = Input(UInt()) 104b34797bcScz4e val data = Input(UInt(encDataBits.W)) 1057dbf3a33SMaxpicca-Li } 1067dbf3a33SMaxpicca-Li 1077dbf3a33SMaxpicca-Li val r = new Bundle() { 1087dbf3a33SMaxpicca-Li val en = Input(Bool()) 1097dbf3a33SMaxpicca-Li val addr = Input(UInt()) 110b34797bcScz4e val data = Output(UInt(encDataBits.W)) 1117dbf3a33SMaxpicca-Li } 1127dbf3a33SMaxpicca-Li }) 1137dbf3a33SMaxpicca-Li 1147dbf3a33SMaxpicca-Li // data sram 1157dbf3a33SMaxpicca-Li val data_sram = Module(new SRAMTemplate( 116b34797bcScz4e Bits(encDataBits.W), 1173eeae490SMaxpicca-Li set = DCacheSets / DCacheSetDiv, 1187dbf3a33SMaxpicca-Li way = 1, 1197dbf3a33SMaxpicca-Li shouldReset = false, 1207dbf3a33SMaxpicca-Li holdRead = false, 1214b2c87baS梁森 Liang Sen singlePort = true, 122*602aa9f1Scz4e hasMbist = hasMbist, 123*602aa9f1Scz4e hasSramCtl = hasSramCtl 1247dbf3a33SMaxpicca-Li )) 1257dbf3a33SMaxpicca-Li 1263eeae490SMaxpicca-Li data_sram.io.w.req.valid := io.w.en 1277dbf3a33SMaxpicca-Li data_sram.io.w.req.bits.apply( 1283eeae490SMaxpicca-Li setIdx = io.w.addr, 1293eeae490SMaxpicca-Li data = io.w.data, 1307dbf3a33SMaxpicca-Li waymask = 1.U 1317dbf3a33SMaxpicca-Li ) 1327dbf3a33SMaxpicca-Li data_sram.io.r.req.valid := io.r.en 1337dbf3a33SMaxpicca-Li data_sram.io.r.req.bits.apply(setIdx = io.r.addr) 1347dbf3a33SMaxpicca-Li io.r.data := data_sram.io.r.resp.data(0) 13504665835SMaxpicca-Li XSPerfAccumulate("part_data_read_counter", data_sram.io.r.req.valid) 1367dbf3a33SMaxpicca-Li 1377dbf3a33SMaxpicca-Li def dump_r() = { 1388b33cd30Sklin02 XSDebug(RegNext(io.r.en), 1398b33cd30Sklin02 "bank read set %x bank %x way %x data %x\n", 1404a0e27ecSYanqin Li RegEnable(io.r.addr, io.r.en), 1417dbf3a33SMaxpicca-Li bankIdx.U, 1427dbf3a33SMaxpicca-Li wayIdx.U, 1437dbf3a33SMaxpicca-Li io.r.data 1447dbf3a33SMaxpicca-Li ) 1457dbf3a33SMaxpicca-Li } 1467dbf3a33SMaxpicca-Li 1477dbf3a33SMaxpicca-Li def dump_w() = { 1488b33cd30Sklin02 XSDebug(io.w.en, 1498b33cd30Sklin02 "bank write set %x bank %x way %x data %x\n", 1507dbf3a33SMaxpicca-Li io.w.addr, 1517dbf3a33SMaxpicca-Li bankIdx.U, 1527dbf3a33SMaxpicca-Li wayIdx.U, 1537dbf3a33SMaxpicca-Li io.w.data 1547dbf3a33SMaxpicca-Li ) 1557dbf3a33SMaxpicca-Li } 1567dbf3a33SMaxpicca-Li 1577dbf3a33SMaxpicca-Li def dump() = { 1587dbf3a33SMaxpicca-Li dump_w() 1597dbf3a33SMaxpicca-Li dump_r() 1607dbf3a33SMaxpicca-Li } 1617dbf3a33SMaxpicca-Li} 1627dbf3a33SMaxpicca-Li 1637dbf3a33SMaxpicca-Li// wrap data rows of 8 ways 1647dbf3a33SMaxpicca-Liclass DataSRAMBank(index: Int)(implicit p: Parameters) extends DCacheModule { 1657dbf3a33SMaxpicca-Li val io = IO(new Bundle() { 1667dbf3a33SMaxpicca-Li val w = Input(new DataSRAMBankWriteReq) 1677dbf3a33SMaxpicca-Li 1687dbf3a33SMaxpicca-Li val r = new Bundle() { 1697dbf3a33SMaxpicca-Li val en = Input(Bool()) 1707dbf3a33SMaxpicca-Li val addr = Input(UInt()) 171b34797bcScz4e val data = Output(Vec(DCacheWays, UInt(encDataBits.W))) 1727dbf3a33SMaxpicca-Li } 1737dbf3a33SMaxpicca-Li }) 1747dbf3a33SMaxpicca-Li 1757dbf3a33SMaxpicca-Li assert(RegNext(!io.w.en || PopCount(io.w.way_en) <= 1.U)) 1767dbf3a33SMaxpicca-Li 1773eeae490SMaxpicca-Li // external controls do not read and write at the same time 1783eeae490SMaxpicca-Li val w_info = io.w 1797dbf3a33SMaxpicca-Li // val rw_bypass = RegNext(io.w.addr === io.r.addr && io.w.way_en === io.r.way_en && io.w.en) 1807dbf3a33SMaxpicca-Li 1817dbf3a33SMaxpicca-Li // multiway data bank 182e3da8badSTang Haojin val data_bank = Seq.fill(DCacheWays) { 1837dbf3a33SMaxpicca-Li Module(new SRAMTemplate( 184b34797bcScz4e Bits(encDataBits.W), 1853eeae490SMaxpicca-Li set = DCacheSets / DCacheSetDiv, 1867dbf3a33SMaxpicca-Li way = 1, 1877dbf3a33SMaxpicca-Li shouldReset = false, 1887dbf3a33SMaxpicca-Li holdRead = false, 189452b5843SHuijin Li singlePort = true, 1904b2c87baS梁森 Liang Sen withClockGate = true, 191ebe07d61S梁森 Liang Sen hasMbist = hasMbist, 192*602aa9f1Scz4e hasSramCtl = hasSramCtl, 193ebe07d61S梁森 Liang Sen suffix = Some("dcsh_dat") 1947dbf3a33SMaxpicca-Li )) 1957dbf3a33SMaxpicca-Li } 1967dbf3a33SMaxpicca-Li 1977dbf3a33SMaxpicca-Li for (w <- 0 until DCacheWays) { 1983eeae490SMaxpicca-Li val wen = w_info.en && w_info.way_en(w) 1997dbf3a33SMaxpicca-Li data_bank(w).io.w.req.valid := wen 2007dbf3a33SMaxpicca-Li data_bank(w).io.w.req.bits.apply( 2013eeae490SMaxpicca-Li setIdx = w_info.addr, 2023eeae490SMaxpicca-Li data = w_info.data, 2037dbf3a33SMaxpicca-Li waymask = 1.U 2047dbf3a33SMaxpicca-Li ) 2057dbf3a33SMaxpicca-Li data_bank(w).io.r.req.valid := io.r.en 2067dbf3a33SMaxpicca-Li data_bank(w).io.r.req.bits.apply(setIdx = io.r.addr) 2077dbf3a33SMaxpicca-Li } 20804665835SMaxpicca-Li XSPerfAccumulate("part_data_read_counter", PopCount(Cat(data_bank.map(_.io.r.req.valid)))) 2097dbf3a33SMaxpicca-Li 2107bd3dbddShappy-lx io.r.data := data_bank.map(_.io.r.resp.data(0)) 2117dbf3a33SMaxpicca-Li 2127dbf3a33SMaxpicca-Li def dump_r() = { 2138b33cd30Sklin02 XSDebug(RegNext(io.r.en), 2148b33cd30Sklin02 "bank read addr %x data %x\n", 2154a0e27ecSYanqin Li RegEnable(io.r.addr, io.r.en), 2167bd3dbddShappy-lx io.r.data.asUInt 2177dbf3a33SMaxpicca-Li ) 2187dbf3a33SMaxpicca-Li } 2197dbf3a33SMaxpicca-Li 2207dbf3a33SMaxpicca-Li def dump_w() = { 2218b33cd30Sklin02 XSDebug(io.w.en, 2228b33cd30Sklin02 "bank write addr %x way_en %x data %x\n", 2237dbf3a33SMaxpicca-Li io.w.addr, 2247dbf3a33SMaxpicca-Li io.w.way_en, 2257dbf3a33SMaxpicca-Li io.w.data 2267dbf3a33SMaxpicca-Li ) 2277dbf3a33SMaxpicca-Li } 2287dbf3a33SMaxpicca-Li 2297dbf3a33SMaxpicca-Li def dump() = { 2307dbf3a33SMaxpicca-Li dump_w() 2317dbf3a33SMaxpicca-Li dump_r() 2327dbf3a33SMaxpicca-Li } 2337dbf3a33SMaxpicca-Li} 2347dbf3a33SMaxpicca-Li 235cd2ff98bShappy-lxcase object HasDataEccParam 236cd2ff98bShappy-lx 2371f0e2dc7SJiawei Lin// Banked DCache Data 2381f0e2dc7SJiawei Lin// ----------------------------------------------------------------- 2391f0e2dc7SJiawei Lin// | Bank0 | Bank1 | Bank2 | Bank3 | Bank4 | Bank5 | Bank6 | Bank7 | 2401f0e2dc7SJiawei Lin// ----------------------------------------------------------------- 2411f0e2dc7SJiawei Lin// | Way0 | Way0 | Way0 | Way0 | Way0 | Way0 | Way0 | Way0 | 2421f0e2dc7SJiawei Lin// | Way1 | Way1 | Way1 | Way1 | Way1 | Way1 | Way1 | Way1 | 2431f0e2dc7SJiawei Lin// | .... | .... | .... | .... | .... | .... | .... | .... | 2441f0e2dc7SJiawei Lin// ----------------------------------------------------------------- 2451f0e2dc7SJiawei Linabstract class AbstractBankedDataArray(implicit p: Parameters) extends DCacheModule 2461f0e2dc7SJiawei Lin{ 247cd2ff98bShappy-lx val DataEccParam = if(EnableDataEcc) Some(HasDataEccParam) else None 248026615fcSWilliam Wang val ReadlinePortErrorIndex = LoadPipelineWidth 2491f0e2dc7SJiawei Lin val io = IO(new DCacheBundle { 2501f0e2dc7SJiawei Lin // load pipeline read word req 251cdbff57cSHaoyuan Feng val read = Vec(LoadPipelineWidth, Flipped(DecoupledIO(new L1BankedDataReadReqWithMask))) 252cdbff57cSHaoyuan Feng val is128Req = Input(Vec(LoadPipelineWidth, Bool())) 2531f0e2dc7SJiawei Lin // main pipeline read / write line req 2547a5caa97Szhanglinjuan val readline_intend = Input(Bool()) 2551f0e2dc7SJiawei Lin val readline = Flipped(DecoupledIO(new L1BankedDataReadLineReq)) 256ebe07d61S梁森 Liang Sen val readline_can_go = Input(Bool()) 257ebe07d61S梁森 Liang Sen val readline_stall = Input(Bool()) 258ebe07d61S梁森 Liang Sen val readline_can_resp = Input(Bool()) 2591f0e2dc7SJiawei Lin val write = Flipped(DecoupledIO(new L1BankedDataWriteReq)) 2606c7e5e86Szhanglinjuan val write_dup = Vec(DCacheBanks, Flipped(Decoupled(new L1BankedDataWriteReqCtrl))) 261144422dcSMaxpicca-Li // data for readline and loadpipe 262144422dcSMaxpicca-Li val readline_resp = Output(Vec(DCacheBanks, new L1BankedDataReadResult())) 263144422dcSMaxpicca-Li val readline_error_delayed = Output(Bool()) 264d4564868Sweiding liu val read_resp = Output(Vec(LoadPipelineWidth, Vec(VLEN/DCacheSRAMRowBits, new L1BankedDataReadResult()))) 265cdbff57cSHaoyuan Feng val read_error_delayed = Output(Vec(LoadPipelineWidth,Vec(VLEN/DCacheSRAMRowBits, Bool()))) 2661f0e2dc7SJiawei Lin // val nacks = Output(Vec(LoadPipelineWidth, Bool())) 2670184a80eSYanqin Li // val errors = Output(Vec(LoadPipelineWidth + 1, ValidIO(new L1CacheErrorInfo))) // read ports + readline port 2681f0e2dc7SJiawei Lin // when bank_conflict, read (1) port should be ignored 2691f0e2dc7SJiawei Lin val bank_conflict_slow = Output(Vec(LoadPipelineWidth, Bool())) 2707a5caa97Szhanglinjuan val disable_ld_fast_wakeup = Output(Vec(LoadPipelineWidth, Bool())) 27172dab974Scz4e val pseudo_error = Flipped(DecoupledIO(Vec(DCacheBanks, new CtrlUnitSignalingBundle))) 2721f0e2dc7SJiawei Lin }) 2731f0e2dc7SJiawei Lin 274fa5e530dScz4e // bank (0, 1, 2, 3) each way use duplicate addr 275fa5e530dScz4e def DuplicatedQueryBankSeq = Seq(0, 1, 2, 3) 276fa5e530dScz4e 2771f0e2dc7SJiawei Lin def pipeMap[T <: Data](f: Int => T) = VecInit((0 until LoadPipelineWidth).map(f)) 2781f0e2dc7SJiawei Lin 2797dbf3a33SMaxpicca-Li def getECCFromEncWord(encWord: UInt) = { 280b34797bcScz4e if (EnableDataEcc) { 281b34797bcScz4e require(encWord.getWidth == encDataBits, s"encDataBits=$encDataBits != encDataBits=$encDataBits!") 282b34797bcScz4e encWord(encDataBits-1, DCacheSRAMRowBits) 283b34797bcScz4e } else { 284b34797bcScz4e 0.U 285b34797bcScz4e } 286b34797bcScz4e } 287b34797bcScz4e 288b34797bcScz4e def getDataFromEncWord(encWord: UInt) = { 289b34797bcScz4e encWord(DCacheSRAMRowBits-1, 0) 290b34797bcScz4e } 291b34797bcScz4e 292b34797bcScz4e def asECCData(ecc: UInt, data: UInt) = { 293b34797bcScz4e if (EnableDataEcc) { 294b34797bcScz4e Cat(ecc, data) 295b34797bcScz4e } else { 296b34797bcScz4e data 297b34797bcScz4e } 2987dbf3a33SMaxpicca-Li } 2997dbf3a33SMaxpicca-Li 300e3da8badSTang Haojin def dumpRead = { 3011f0e2dc7SJiawei Lin (0 until LoadPipelineWidth) map { w => 3028b33cd30Sklin02 XSDebug(io.read(w).valid, 3038b33cd30Sklin02 s"DataArray Read channel: $w valid way_en: %x addr: %x\n", 3041f0e2dc7SJiawei Lin io.read(w).bits.way_en, io.read(w).bits.addr) 3051f0e2dc7SJiawei Lin } 3068b33cd30Sklin02 XSDebug(io.readline.valid, 3078b33cd30Sklin02 s"DataArray Read Line, valid way_en: %x addr: %x rmask %x\n", 3081f0e2dc7SJiawei Lin io.readline.bits.way_en, io.readline.bits.addr, io.readline.bits.rmask) 3091f0e2dc7SJiawei Lin } 3101f0e2dc7SJiawei Lin 311e3da8badSTang Haojin def dumpWrite = { 3128b33cd30Sklin02 XSDebug(io.write.valid, 3138b33cd30Sklin02 s"DataArray Write valid way_en: %x addr: %x\n", 3141f0e2dc7SJiawei Lin io.write.bits.way_en, io.write.bits.addr) 3151f0e2dc7SJiawei Lin 3161f0e2dc7SJiawei Lin (0 until DCacheBanks) map { r => 3178b33cd30Sklin02 XSDebug(io.write.valid, 3188b33cd30Sklin02 s"cycle: $r data: %x wmask: %x\n", 3191f0e2dc7SJiawei Lin io.write.bits.data(r), io.write.bits.wmask(r)) 3201f0e2dc7SJiawei Lin } 3211f0e2dc7SJiawei Lin } 3221f0e2dc7SJiawei Lin 323e3da8badSTang Haojin def dumpResp = { 3241f0e2dc7SJiawei Lin XSDebug(s"DataArray ReadeResp channel:\n") 325144422dcSMaxpicca-Li (0 until LoadPipelineWidth) map { r => 326cdbff57cSHaoyuan Feng XSDebug(s"cycle: $r data: %x\n", Mux(io.is128Req(r), 327d4564868Sweiding liu Cat(io.read_resp(r)(1).raw_data,io.read_resp(r)(0).raw_data), 328d4564868Sweiding liu io.read_resp(r)(0).raw_data)) 3291f0e2dc7SJiawei Lin } 3301f0e2dc7SJiawei Lin } 3311f0e2dc7SJiawei Lin 3321f0e2dc7SJiawei Lin def dump() = { 3331f0e2dc7SJiawei Lin dumpRead 3341f0e2dc7SJiawei Lin dumpWrite 3351f0e2dc7SJiawei Lin dumpResp 3361f0e2dc7SJiawei Lin } 3378ffb12e4SAnzo 3388ffb12e4SAnzo def selcetOldestPort(valid: Seq[Bool], bits: Seq[LqPtr], index: Seq[UInt]):((Bool, LqPtr), UInt) = { 3398ffb12e4SAnzo require(valid.length == bits.length && bits.length == index.length, s"length must eq, valid:${valid.length}, bits:${bits.length}, index:${index.length}") 3408ffb12e4SAnzo ParallelOperation(valid zip bits zip index, 3418ffb12e4SAnzo (a: ((Bool, LqPtr), UInt), b: ((Bool, LqPtr), UInt)) => { 3428ffb12e4SAnzo val au = a._1._2 3438ffb12e4SAnzo val bu = b._1._2 3448ffb12e4SAnzo val aValid = a._1._1 3458ffb12e4SAnzo val bValid = b._1._1 3468ffb12e4SAnzo val bSel = au > bu 3478ffb12e4SAnzo val bits = Mux( 3488ffb12e4SAnzo aValid && bValid, 3498ffb12e4SAnzo Mux(bSel, b._1._2, a._1._2), 3508ffb12e4SAnzo Mux(aValid && !bValid, a._1._2, b._1._2) 3518ffb12e4SAnzo ) 3528ffb12e4SAnzo val idx = Mux( 3538ffb12e4SAnzo aValid && bValid, 3548ffb12e4SAnzo Mux(bSel, b._2, a._2), 3558ffb12e4SAnzo Mux(aValid && !bValid, a._2, b._2) 3568ffb12e4SAnzo ) 3578ffb12e4SAnzo ((aValid || bValid, bits), idx) 3588ffb12e4SAnzo } 3598ffb12e4SAnzo ) 3608ffb12e4SAnzo } 3618ffb12e4SAnzo 3621f0e2dc7SJiawei Lin} 3631f0e2dc7SJiawei Lin 3647dbf3a33SMaxpicca-Li// the smallest access unit is sram 3657dbf3a33SMaxpicca-Liclass SramedDataArray(implicit p: Parameters) extends AbstractBankedDataArray { 3667dbf3a33SMaxpicca-Li println(" DCacheType: SramedDataArray") 367300ded30SWilliam Wang val ReduceReadlineConflict = false 368300ded30SWilliam Wang 3691f0e2dc7SJiawei Lin io.write.ready := true.B 3706c7e5e86Szhanglinjuan io.write_dup.foreach(_.ready := true.B) 3711f0e2dc7SJiawei Lin 3724b2c87baS梁森 Liang Sen val data_banks = List.tabulate(DCacheSetDiv)( k => { 3734b2c87baS梁森 Liang Sen val banks = List.tabulate(DCacheBanks)(i => List.tabulate(DCacheWays)(j => Module(new DataSRAM(i,j)))) 3744b2c87baS梁森 Liang Sen val mbistPl = MbistPipeline.PlaceMbistPipeline(1, s"MbistPipeDataSet$k", hasMbist) 3754b2c87baS梁森 Liang Sen banks 3764b2c87baS梁森 Liang Sen }) 3773eeae490SMaxpicca-Li data_banks.map(_.map(_.map(_.dump()))) 3781f0e2dc7SJiawei Lin 3791f0e2dc7SJiawei Lin val way_en = Wire(Vec(LoadPipelineWidth, io.read(0).bits.way_en.cloneType)) 3801f0e2dc7SJiawei Lin val set_addrs = Wire(Vec(LoadPipelineWidth, UInt())) 3813eeae490SMaxpicca-Li val div_addrs = Wire(Vec(LoadPipelineWidth, UInt())) 382cdbff57cSHaoyuan Feng val bank_addrs = Wire(Vec(LoadPipelineWidth, Vec(VLEN/DCacheSRAMRowBits, UInt()))) 3831f0e2dc7SJiawei Lin 3843eeae490SMaxpicca-Li val line_set_addr = addr_to_dcache_div_set(io.readline.bits.addr) 3853eeae490SMaxpicca-Li val line_div_addr = addr_to_dcache_div(io.readline.bits.addr) 38604665835SMaxpicca-Li // when WPU is enabled, line_way_en is all enabled when read data 38704665835SMaxpicca-Li val line_way_en = Fill(DCacheWays, 1.U) // val line_way_en = io.readline.bits.way_en 3884a0e27ecSYanqin Li val line_way_en_reg = RegEnable(io.readline.bits.way_en, 0.U(DCacheWays.W),io.readline.valid) 3893eeae490SMaxpicca-Li 3904a0e27ecSYanqin Li val write_bank_mask_reg = RegEnable(io.write.bits.wmask, 0.U(DCacheBanks.W), io.write.valid) 3915adc4829SYanqin Li val write_data_reg = RegEnable(io.write.bits.data, io.write.valid) 3923eeae490SMaxpicca-Li val write_valid_reg = RegNext(io.write.valid) 3933eeae490SMaxpicca-Li val write_valid_dup_reg = io.write_dup.map(x => RegNext(x.valid)) 3944a0e27ecSYanqin Li val write_wayen_dup_reg = io.write_dup.map(x => RegEnable(x.bits.way_en, 0.U(DCacheWays.W), x.valid)) 3955adc4829SYanqin Li val write_set_addr_dup_reg = io.write_dup.map(x => RegEnable(addr_to_dcache_div_set(x.bits.addr), x.valid)) 3965adc4829SYanqin Li val write_div_addr_dup_reg = io.write_dup.map(x => RegEnable(addr_to_dcache_div(x.bits.addr), x.valid)) 3973eeae490SMaxpicca-Li 3981f0e2dc7SJiawei Lin // read data_banks and ecc_banks 3991f0e2dc7SJiawei Lin // for single port SRAM, do not allow read and write in the same cycle 4001f0e2dc7SJiawei Lin val rrhazard = false.B // io.readline.valid 4011f0e2dc7SJiawei Lin (0 until LoadPipelineWidth).map(rport_index => { 4023eeae490SMaxpicca-Li div_addrs(rport_index) := addr_to_dcache_div(io.read(rport_index).bits.addr) 4033eeae490SMaxpicca-Li set_addrs(rport_index) := addr_to_dcache_div_set(io.read(rport_index).bits.addr) 404cdbff57cSHaoyuan Feng bank_addrs(rport_index)(0) := addr_to_dcache_bank(io.read(rport_index).bits.addr) 405cdbff57cSHaoyuan Feng bank_addrs(rport_index)(1) := bank_addrs(rport_index)(0) + 1.U 4061f0e2dc7SJiawei Lin 4071f0e2dc7SJiawei Lin // use way_en to select a way after data read out 408935edac4STang Haojin assert(!(RegNext(io.read(rport_index).fire && PopCount(io.read(rport_index).bits.way_en) > 1.U))) 4091f0e2dc7SJiawei Lin way_en(rport_index) := io.read(rport_index).bits.way_en 4101f0e2dc7SJiawei Lin }) 4111f0e2dc7SJiawei Lin 412144422dcSMaxpicca-Li // read conflict 4138ffb12e4SAnzo val rr_bank_conflict = Seq.tabulate(LoadPipelineWidth)(x => Seq.tabulate(LoadPipelineWidth)(y => { 4148ffb12e4SAnzo if (x == y) { 4158ffb12e4SAnzo false.B 4168ffb12e4SAnzo } else { 4173eeae490SMaxpicca-Li io.read(x).valid && io.read(y).valid && 4183eeae490SMaxpicca-Li div_addrs(x) === div_addrs(y) && 419cdbff57cSHaoyuan Feng (io.read(x).bits.bankMask & io.read(y).bits.bankMask) =/= 0.U && 4203eeae490SMaxpicca-Li io.read(x).bits.way_en === io.read(y).bits.way_en && 4213eeae490SMaxpicca-Li set_addrs(x) =/= set_addrs(y) 4228ffb12e4SAnzo } 4238ffb12e4SAnzo })) 4248ffb12e4SAnzo val load_req_with_bank_conflict = rr_bank_conflict.map(_.reduce(_ || _)) 4258ffb12e4SAnzo val load_req_valid = io.read.map(_.valid) 4268ffb12e4SAnzo val load_req_lqIdx = io.read.map(_.bits.lqIdx) 4278ffb12e4SAnzo val load_req_index = (0 until LoadPipelineWidth).map(_.asUInt) 4288ffb12e4SAnzo 4298ffb12e4SAnzo 430c5a867ffSAnzo val load_req_bank_conflict_selcet = selcetOldestPort(load_req_with_bank_conflict, load_req_lqIdx, load_req_index) 4318ffb12e4SAnzo val load_req_bank_select_port = UIntToOH(load_req_bank_conflict_selcet._2).asBools 4328ffb12e4SAnzo 4338ffb12e4SAnzo val rr_bank_conflict_oldest = (0 until LoadPipelineWidth).map(i => 4348ffb12e4SAnzo !load_req_bank_select_port(i) && load_req_with_bank_conflict(i) 4358ffb12e4SAnzo ) 4368ffb12e4SAnzo 43746f74b57SHaojin Tang val rrl_bank_conflict = Wire(Vec(LoadPipelineWidth, Bool())) 4387a5caa97Szhanglinjuan val rrl_bank_conflict_intend = Wire(Vec(LoadPipelineWidth, Bool())) 4393eeae490SMaxpicca-Li (0 until LoadPipelineWidth).foreach { i => 44004665835SMaxpicca-Li val judge = if (ReduceReadlineConflict) io.read(i).valid && (io.readline.bits.rmask & io.read(i).bits.bankMask) =/= 0.U && line_div_addr === div_addrs(i) && line_set_addr =/= set_addrs(i) 44104665835SMaxpicca-Li else io.read(i).valid && line_div_addr === div_addrs(i) && line_set_addr =/= set_addrs(i) 4423eeae490SMaxpicca-Li rrl_bank_conflict(i) := judge && io.readline.valid 4433eeae490SMaxpicca-Li rrl_bank_conflict_intend(i) := judge && io.readline_intend 4447a5caa97Szhanglinjuan } 4453eeae490SMaxpicca-Li val wr_bank_conflict = Seq.tabulate(LoadPipelineWidth)(x => 4463eeae490SMaxpicca-Li io.read(x).valid && write_valid_reg && 4473eeae490SMaxpicca-Li div_addrs(x) === write_div_addr_dup_reg.head && 448e9ed1022SMaxpicca-Li way_en(x) === write_wayen_dup_reg.head && 449cdbff57cSHaoyuan Feng (write_bank_mask_reg(bank_addrs(x)(0)) || write_bank_mask_reg(bank_addrs(x)(1)) && io.is128Req(x)) 4503eeae490SMaxpicca-Li ) 45104665835SMaxpicca-Li val wrl_bank_conflict = io.readline.valid && write_valid_reg && line_div_addr === write_div_addr_dup_reg.head 4523eeae490SMaxpicca-Li // ready 4533eeae490SMaxpicca-Li io.readline.ready := !(wrl_bank_conflict) 4543eeae490SMaxpicca-Li io.read.zipWithIndex.map { case (x, i) => x.ready := !(wr_bank_conflict(i) || rrhazard) } 455300ded30SWilliam Wang 45646f74b57SHaojin Tang val perf_multi_read = PopCount(io.read.map(_.valid)) >= 2.U 45713f2ff1cSMaxpicca-Li val bank_conflict_fast = Wire(Vec(LoadPipelineWidth, Bool())) 45846f74b57SHaojin Tang (0 until LoadPipelineWidth).foreach(i => { 45913f2ff1cSMaxpicca-Li bank_conflict_fast(i) := wr_bank_conflict(i) || rrl_bank_conflict(i) || 4608ffb12e4SAnzo rr_bank_conflict_oldest(i) 46113f2ff1cSMaxpicca-Li io.bank_conflict_slow(i) := RegNext(bank_conflict_fast(i)) 4623eeae490SMaxpicca-Li io.disable_ld_fast_wakeup(i) := wr_bank_conflict(i) || rrl_bank_conflict_intend(i) || 4637a5caa97Szhanglinjuan (if (i == 0) 0.B else (0 until i).map(rr_bank_conflict(_)(i)).reduce(_ || _)) 46446f74b57SHaojin Tang }) 4651f0e2dc7SJiawei Lin XSPerfAccumulate("data_array_multi_read", perf_multi_read) 46646f74b57SHaojin Tang (1 until LoadPipelineWidth).foreach(y => (0 until y).foreach(x => 46746f74b57SHaojin Tang XSPerfAccumulate(s"data_array_rr_bank_conflict_${x}_${y}", rr_bank_conflict(x)(y)) 46846f74b57SHaojin Tang )) 46946f74b57SHaojin Tang (0 until LoadPipelineWidth).foreach(i => { 47046f74b57SHaojin Tang XSPerfAccumulate(s"data_array_rrl_bank_conflict_${i}", rrl_bank_conflict(i)) 4713eeae490SMaxpicca-Li XSPerfAccumulate(s"data_array_rw_bank_conflict_${i}", wr_bank_conflict(i)) 47246f74b57SHaojin Tang XSPerfAccumulate(s"data_array_read_${i}", io.read(i).valid) 47346f74b57SHaojin Tang }) 47446f74b57SHaojin Tang XSPerfAccumulate("data_array_access_total", PopCount(io.read.map(_.valid))) 4751f0e2dc7SJiawei Lin XSPerfAccumulate("data_array_read_line", io.readline.valid) 4761f0e2dc7SJiawei Lin XSPerfAccumulate("data_array_write", io.write.valid) 4771f0e2dc7SJiawei Lin 4783eeae490SMaxpicca-Li val read_result = Wire(Vec(DCacheSetDiv, Vec(DCacheBanks, Vec(DCacheWays,new L1BankedDataReadResult())))) 4794a0e27ecSYanqin Li val read_result_delayed = Wire(Vec(DCacheSetDiv, Vec(DCacheBanks, Vec(DCacheWays,new L1BankedDataReadResult())))) 4803eeae490SMaxpicca-Li val read_error_delayed_result = Wire(Vec(DCacheSetDiv, Vec(DCacheBanks, Vec(DCacheWays, Bool())))) 48172dab974Scz4e dontTouch(read_result) 48272dab974Scz4e dontTouch(read_error_delayed_result) 48372dab974Scz4e 48472dab974Scz4e val pseudo_data_toggle_mask = io.pseudo_error.bits.map { 48572dab974Scz4e case bank => 48672dab974Scz4e Mux(io.pseudo_error.valid && bank.valid, bank.mask, 0.U) 48772dab974Scz4e } 48872dab974Scz4e val readline_hit = io.readline.fire && 48972dab974Scz4e (io.readline.bits.rmask & VecInit(io.pseudo_error.bits.map(_.valid)).asUInt).orR 49072dab974Scz4e val readbank_hit = io.read.zip(bank_addrs.zip(io.is128Req)).zipWithIndex.map { 49172dab974Scz4e case ((read, (bank_addr, is128Req)), i) => 49272dab974Scz4e val error_bank0 = io.pseudo_error.bits(bank_addr(0)) 49372dab974Scz4e val error_bank1 = io.pseudo_error.bits(bank_addr(1)) 49472dab974Scz4e read.fire && (error_bank0.valid || error_bank1.valid && is128Req) && !io.bank_conflict_slow(i) 49572dab974Scz4e }.reduce(_|_) 49672dab974Scz4e io.pseudo_error.ready := RegNext(readline_hit || readbank_hit) 4978ffb12e4SAnzo 4983eeae490SMaxpicca-Li for (div_index <- 0 until DCacheSetDiv){ 4991f0e2dc7SJiawei Lin for (bank_index <- 0 until DCacheBanks) { 500144422dcSMaxpicca-Li for (way_index <- 0 until DCacheWays) { 5011f0e2dc7SJiawei Lin // Set Addr & Read Way Mask 5021f0e2dc7SJiawei Lin // 50346f74b57SHaojin Tang // Pipe 0 .... Pipe (n-1) 50446f74b57SHaojin Tang // + .... + 50546f74b57SHaojin Tang // | .... | 50646f74b57SHaojin Tang // +----+---------------+-----+ 5071f0e2dc7SJiawei Lin // X X 5081f0e2dc7SJiawei Lin // X +------+ Bank Addr Match 5091f0e2dc7SJiawei Lin // +---------+----------+ 5101f0e2dc7SJiawei Lin // | 5111f0e2dc7SJiawei Lin // +--------+--------+ 5121f0e2dc7SJiawei Lin // | Data Bank | 5131f0e2dc7SJiawei Lin // +-----------------+ 514144422dcSMaxpicca-Li val loadpipe_en = WireInit(VecInit(List.tabulate(LoadPipelineWidth)(i => { 5158ffb12e4SAnzo io.read(i).valid && div_addrs(i) === div_index.U && (bank_addrs(i)(0) === bank_index.U || bank_addrs(i)(1) === bank_index.U && io.is128Req(i)) && 5168ffb12e4SAnzo way_en(i)(way_index) && 5178ffb12e4SAnzo !rr_bank_conflict_oldest(i) 5181f0e2dc7SJiawei Lin }))) 519144422dcSMaxpicca-Li val readline_en = Wire(Bool()) 520300ded30SWilliam Wang if (ReduceReadlineConflict) { 52104665835SMaxpicca-Li readline_en := io.readline.valid && io.readline.bits.rmask(bank_index) && line_way_en(way_index) && div_index.U === line_div_addr 522300ded30SWilliam Wang } else { 52304665835SMaxpicca-Li readline_en := io.readline.valid && line_way_en(way_index) && div_index.U === line_div_addr 524300ded30SWilliam Wang } 525144422dcSMaxpicca-Li val sram_set_addr = Mux(readline_en, 5263eeae490SMaxpicca-Li addr_to_dcache_div_set(io.readline.bits.addr), 527144422dcSMaxpicca-Li PriorityMux(Seq.tabulate(LoadPipelineWidth)(i => loadpipe_en(i) -> set_addrs(i))) 5281f0e2dc7SJiawei Lin ) 529144422dcSMaxpicca-Li val read_en = loadpipe_en.asUInt.orR || readline_en 5301f0e2dc7SJiawei Lin // read raw data 5313eeae490SMaxpicca-Li val data_bank = data_banks(div_index)(bank_index)(way_index) 532144422dcSMaxpicca-Li data_bank.io.r.en := read_en 533144422dcSMaxpicca-Li data_bank.io.r.addr := sram_set_addr 5341f0e2dc7SJiawei Lin 535b34797bcScz4e read_result(div_index)(bank_index)(way_index).ecc := getECCFromEncWord(data_bank.io.r.data) 53672dab974Scz4e read_result(div_index)(bank_index)(way_index).raw_data := getDataFromEncWord(data_bank.io.r.data) ^ pseudo_data_toggle_mask(bank_index) 5371f0e2dc7SJiawei Lin 538b34797bcScz4e if (EnableDataEcc) { 5393eeae490SMaxpicca-Li val ecc_data = read_result(div_index)(bank_index)(way_index).asECCData() 540144422dcSMaxpicca-Li val ecc_data_delayed = RegEnable(ecc_data, RegNext(read_en)) 5413eeae490SMaxpicca-Li read_result(div_index)(bank_index)(way_index).error_delayed := dcacheParameters.dataCode.decode(ecc_data_delayed).error 5423eeae490SMaxpicca-Li read_error_delayed_result(div_index)(bank_index)(way_index) := read_result(div_index)(bank_index)(way_index).error_delayed 543b34797bcScz4e } else { 544cd2ff98bShappy-lx read_result(div_index)(bank_index)(way_index).error_delayed := false.B 545cd2ff98bShappy-lx read_error_delayed_result(div_index)(bank_index)(way_index) := false.B 546cd2ff98bShappy-lx } 547b34797bcScz4e 548b34797bcScz4e read_result_delayed(div_index)(bank_index)(way_index) := RegEnable(read_result(div_index)(bank_index)(way_index), RegNext(read_en)) 5493eeae490SMaxpicca-Li } 550144422dcSMaxpicca-Li } 5511f0e2dc7SJiawei Lin } 5521f0e2dc7SJiawei Lin 55304665835SMaxpicca-Li val data_read_oh = WireInit(VecInit(Seq.fill(DCacheSetDiv * DCacheBanks * DCacheWays)(0.U(1.W)))) 55404665835SMaxpicca-Li for(div_index <- 0 until DCacheSetDiv){ 55504665835SMaxpicca-Li for (bank_index <- 0 until DCacheBanks) { 55604665835SMaxpicca-Li for (way_index <- 0 until DCacheWays) { 5574a0e27ecSYanqin Li data_read_oh(div_index * DCacheBanks * DCacheWays + bank_index * DCacheWays + way_index) := data_banks(div_index)(bank_index)(way_index).io.r.en 55804665835SMaxpicca-Li } 55904665835SMaxpicca-Li } 56004665835SMaxpicca-Li } 56104665835SMaxpicca-Li XSPerfAccumulate("data_read_counter", PopCount(Cat(data_read_oh))) 56204665835SMaxpicca-Li 563026615fcSWilliam Wang // read result: expose banked read result 564d4564868Sweiding liu // TODO: clock gate 565144422dcSMaxpicca-Li (0 until LoadPipelineWidth).map(i => { 5663eeae490SMaxpicca-Li // io.read_resp(i) := read_result(RegNext(bank_addrs(i)))(RegNext(OHToUInt(way_en(i)))) 5674a0e27ecSYanqin Li val r_read_fire = RegNext(io.read(i).fire) 568d4564868Sweiding liu val r_div_addr = RegEnable(div_addrs(i), io.read(i).fire) 569d4564868Sweiding liu val r_bank_addr = RegEnable(bank_addrs(i), io.read(i).fire) 570d4564868Sweiding liu val r_way_addr = RegNext(OHToUInt(way_en(i))) 5713eeae490SMaxpicca-Li val rr_read_fire = RegNext(RegNext(io.read(i).fire)) 5724a0e27ecSYanqin Li val rr_div_addr = RegEnable(RegEnable(div_addrs(i), io.read(i).fire), r_read_fire) 5734a0e27ecSYanqin Li val rr_bank_addr = RegEnable(RegEnable(bank_addrs(i), io.read(i).fire), r_read_fire) 5744a0e27ecSYanqin Li val rr_way_addr = RegEnable(RegEnable(OHToUInt(way_en(i)), io.read(i).fire), r_read_fire) 575cdbff57cSHaoyuan Feng (0 until VLEN/DCacheSRAMRowBits).map( j =>{ 576d4564868Sweiding liu io.read_resp(i)(j) := read_result(r_div_addr)(r_bank_addr(j))(r_way_addr) 577026615fcSWilliam Wang // error detection 578026615fcSWilliam Wang // normal read ports 579cdbff57cSHaoyuan Feng io.read_error_delayed(i)(j) := rr_read_fire && read_error_delayed_result(rr_div_addr)(rr_bank_addr(j))(rr_way_addr) && !RegNext(io.bank_conflict_slow(i)) 580cdbff57cSHaoyuan Feng }) 5811f0e2dc7SJiawei Lin }) 5823eeae490SMaxpicca-Li 583026615fcSWilliam Wang // readline port 58498d2aaa1Scz4e val readline_error_delayed = Wire(Vec(DCacheBanks, Bool())) 58598d2aaa1Scz4e val readline_r_way_addr = RegEnable(OHToUInt(io.readline.bits.way_en), io.readline.valid) 58698d2aaa1Scz4e val readline_rr_way_addr = RegEnable(readline_r_way_addr, RegNext(io.readline.valid)) 58798d2aaa1Scz4e val readline_r_div_addr = RegEnable(line_div_addr, io.readline.valid) 58898d2aaa1Scz4e val readline_rr_div_addr = RegEnable(readline_r_div_addr, RegNext(io.readline.valid)) 5893eeae490SMaxpicca-Li (0 until DCacheBanks).map(i => { 59098d2aaa1Scz4e io.readline_resp(i) := read_result(readline_r_div_addr)(i)(readline_r_way_addr) 59198d2aaa1Scz4e readline_error_delayed(i) := read_result(readline_rr_div_addr)(i)(readline_rr_way_addr).error_delayed 5923eeae490SMaxpicca-Li }) 59398d2aaa1Scz4e io.readline_error_delayed := RegNext(RegNext(io.readline.fire)) && readline_error_delayed.asUInt.orR 5941f0e2dc7SJiawei Lin 5951f0e2dc7SJiawei Lin // write data_banks & ecc_banks 5963eeae490SMaxpicca-Li for (div_index <- 0 until DCacheSetDiv) { 5971f0e2dc7SJiawei Lin for (bank_index <- 0 until DCacheBanks) { 598144422dcSMaxpicca-Li for (way_index <- 0 until DCacheWays) { 5991f0e2dc7SJiawei Lin // data write 6003eeae490SMaxpicca-Li val wen_reg = write_bank_mask_reg(bank_index) && 6013eeae490SMaxpicca-Li write_valid_dup_reg(bank_index) && 6023eeae490SMaxpicca-Li write_div_addr_dup_reg(bank_index) === div_index.U && 6033eeae490SMaxpicca-Li write_wayen_dup_reg(bank_index)(way_index) 604b34797bcScz4e val write_ecc_reg = RegEnable(getECCFromEncWord(cacheParams.dataCode.encode(io.write.bits.data(bank_index))), io.write.valid) 6053eeae490SMaxpicca-Li val data_bank = data_banks(div_index)(bank_index)(way_index) 6063eeae490SMaxpicca-Li data_bank.io.w.en := wen_reg 6073eeae490SMaxpicca-Li data_bank.io.w.addr := write_set_addr_dup_reg(bank_index) 608b34797bcScz4e data_bank.io.w.data := asECCData(write_ecc_reg, write_data_reg(bank_index)) 6091f0e2dc7SJiawei Lin } 610144422dcSMaxpicca-Li } 6113eeae490SMaxpicca-Li } 6121f0e2dc7SJiawei Lin 613144422dcSMaxpicca-Li val tableName = "BankConflict" + p(XSCoreParamsKey).HartId.toString 614144422dcSMaxpicca-Li val siteName = "BankedDataArray" + p(XSCoreParamsKey).HartId.toString 615144422dcSMaxpicca-Li val bankConflictTable = ChiselDB.createTable(tableName, new BankConflictDB) 616144422dcSMaxpicca-Li val bankConflictData = Wire(new BankConflictDB) 617144422dcSMaxpicca-Li for (i <- 0 until LoadPipelineWidth) { 618144422dcSMaxpicca-Li bankConflictData.set_index(i) := set_addrs(i) 619144422dcSMaxpicca-Li bankConflictData.addr(i) := io.read(i).bits.addr 620144422dcSMaxpicca-Li } 621144422dcSMaxpicca-Li 622144422dcSMaxpicca-Li // FIXME: rr_bank_conflict(0)(1) no generalization 623144422dcSMaxpicca-Li when(rr_bank_conflict(0)(1)) { 624cdbff57cSHaoyuan Feng (0 until (VLEN/DCacheSRAMRowBits)).map(i => { 625cdbff57cSHaoyuan Feng bankConflictData.bank_index(i) := bank_addrs(0)(i) 626cdbff57cSHaoyuan Feng }) 627144422dcSMaxpicca-Li bankConflictData.way_index := OHToUInt(way_en(0)) 62813f2ff1cSMaxpicca-Li bankConflictData.fake_rr_bank_conflict := set_addrs(0) === set_addrs(1) && div_addrs(0) === div_addrs(1) 629144422dcSMaxpicca-Li }.otherwise { 630cdbff57cSHaoyuan Feng (0 until (VLEN/DCacheSRAMRowBits)).map(i => { 631cdbff57cSHaoyuan Feng bankConflictData.bank_index(i) := 0.U 632cdbff57cSHaoyuan Feng }) 633144422dcSMaxpicca-Li bankConflictData.way_index := 0.U 634144422dcSMaxpicca-Li bankConflictData.fake_rr_bank_conflict := false.B 635144422dcSMaxpicca-Li } 636144422dcSMaxpicca-Li 637c686adcdSYinan Xu val isWriteBankConflictTable = Constantin.createRecord(s"isWriteBankConflictTable${p(XSCoreParamsKey).HartId}") 638144422dcSMaxpicca-Li bankConflictTable.log( 639144422dcSMaxpicca-Li data = bankConflictData, 640da3bf434SMaxpicca-Li en = isWriteBankConflictTable.orR && rr_bank_conflict(0)(1), 641144422dcSMaxpicca-Li site = siteName, 642144422dcSMaxpicca-Li clock = clock, 643144422dcSMaxpicca-Li reset = reset 644144422dcSMaxpicca-Li ) 645144422dcSMaxpicca-Li 646144422dcSMaxpicca-Li (1 until LoadPipelineWidth).foreach(y => (0 until y).foreach(x => 64704665835SMaxpicca-Li XSPerfAccumulate(s"data_array_fake_rr_bank_conflict_${x}_${y}", rr_bank_conflict(x)(y) && set_addrs(x)===set_addrs(y) && div_addrs(x) === div_addrs(y)) 648144422dcSMaxpicca-Li )) 649144422dcSMaxpicca-Li 6508ffb12e4SAnzo if (backendParams.debugEn){ 6518ffb12e4SAnzo load_req_with_bank_conflict.map(dontTouch(_)) 6528ffb12e4SAnzo dontTouch(read_result) 6538ffb12e4SAnzo dontTouch(read_error_delayed_result) 6548ffb12e4SAnzo } 6551f0e2dc7SJiawei Lin} 6567dbf3a33SMaxpicca-Li 6577dbf3a33SMaxpicca-Li// the smallest access unit is bank 6587dbf3a33SMaxpicca-Liclass BankedDataArray(implicit p: Parameters) extends AbstractBankedDataArray { 6597dbf3a33SMaxpicca-Li println(" DCacheType: BankedDataArray") 6607dbf3a33SMaxpicca-Li val ReduceReadlineConflict = false 6617dbf3a33SMaxpicca-Li 6627dbf3a33SMaxpicca-Li io.write.ready := true.B 6637dbf3a33SMaxpicca-Li io.write_dup.foreach(_.ready := true.B) 6647dbf3a33SMaxpicca-Li 665ebe07d61S梁森 Liang Sen val data_banks = Seq.tabulate(DCacheSetDiv, DCacheBanks)({(k, i) => Module(new DataSRAMBank(i))}) 666ebe07d61S梁森 Liang Sen val mbistPl = MbistPipeline.PlaceMbistPipeline(1, s"MbistPipeDCacheData", hasMbist) 667ebe07d61S梁森 Liang Sen val mbistSramPorts = mbistPl.map(pl => Seq.tabulate(DCacheSetDiv, DCacheBanks, DCacheWays) ({ (i, j, k) => 668ebe07d61S梁森 Liang Sen pl.toSRAM(i * DCacheBanks * DCacheWays + j * DCacheWays + k) 669ebe07d61S梁森 Liang Sen })) 6703eeae490SMaxpicca-Li data_banks.map(_.map(_.dump())) 6717dbf3a33SMaxpicca-Li 6727dbf3a33SMaxpicca-Li val way_en = Wire(Vec(LoadPipelineWidth, io.read(0).bits.way_en.cloneType)) 6737dbf3a33SMaxpicca-Li val set_addrs = Wire(Vec(LoadPipelineWidth, UInt())) 674fa5e530dScz4e val set_addrs_dup = Wire(Vec(LoadPipelineWidth, UInt())) 6753eeae490SMaxpicca-Li val div_addrs = Wire(Vec(LoadPipelineWidth, UInt())) 676fa5e530dScz4e val div_addrs_dup = Wire(Vec(LoadPipelineWidth, UInt())) 677cdbff57cSHaoyuan Feng val bank_addrs = Wire(Vec(LoadPipelineWidth, Vec(VLEN/DCacheSRAMRowBits, UInt()))) 678fa5e530dScz4e val bank_addrs_dup = Wire(Vec(LoadPipelineWidth, Vec(VLEN/DCacheSRAMRowBits, UInt()))) 67913f2ff1cSMaxpicca-Li val way_en_reg = Wire(Vec(LoadPipelineWidth, io.read(0).bits.way_en.cloneType)) 68013f2ff1cSMaxpicca-Li val set_addrs_reg = Wire(Vec(LoadPipelineWidth, UInt())) 681fa5e530dScz4e val set_addrs_dup_reg = Wire(Vec(LoadPipelineWidth, UInt())) 6827dbf3a33SMaxpicca-Li 6833eeae490SMaxpicca-Li val line_set_addr = addr_to_dcache_div_set(io.readline.bits.addr) 6843eeae490SMaxpicca-Li val line_div_addr = addr_to_dcache_div(io.readline.bits.addr) 6853eeae490SMaxpicca-Li val line_way_en = io.readline.bits.way_en 6863eeae490SMaxpicca-Li 6874a0e27ecSYanqin Li val write_bank_mask_reg = RegEnable(io.write.bits.wmask, io.write.valid) 6885adc4829SYanqin Li val write_data_reg = RegEnable(io.write.bits.data, io.write.valid) 6893eeae490SMaxpicca-Li val write_valid_reg = RegNext(io.write.valid) 6903eeae490SMaxpicca-Li val write_valid_dup_reg = io.write_dup.map(x => RegNext(x.valid)) 6914a0e27ecSYanqin Li val write_wayen_dup_reg = io.write_dup.map(x => RegEnable(x.bits.way_en, x.valid)) 6925adc4829SYanqin Li val write_set_addr_dup_reg = io.write_dup.map(x => RegEnable(addr_to_dcache_div_set(x.bits.addr), x.valid)) 6935adc4829SYanqin Li val write_div_addr_dup_reg = io.write_dup.map(x => RegEnable(addr_to_dcache_div(x.bits.addr), x.valid)) 6943eeae490SMaxpicca-Li 6957dbf3a33SMaxpicca-Li // read data_banks and ecc_banks 6967dbf3a33SMaxpicca-Li // for single port SRAM, do not allow read and write in the same cycle 6977dbf3a33SMaxpicca-Li val rwhazard = RegNext(io.write.valid) 6987dbf3a33SMaxpicca-Li val rrhazard = false.B // io.readline.valid 6997dbf3a33SMaxpicca-Li (0 until LoadPipelineWidth).map(rport_index => { 7003eeae490SMaxpicca-Li div_addrs(rport_index) := addr_to_dcache_div(io.read(rport_index).bits.addr) 701fa5e530dScz4e div_addrs_dup(rport_index) := addr_to_dcache_div(io.read(rport_index).bits.addr_dup) 702cdbff57cSHaoyuan Feng bank_addrs(rport_index)(0) := addr_to_dcache_bank(io.read(rport_index).bits.addr) 70308b0bc30Shappy-lx bank_addrs(rport_index)(1) := Mux(io.is128Req(rport_index), bank_addrs(rport_index)(0) + 1.U, bank_addrs(rport_index)(0)) 704fa5e530dScz4e bank_addrs_dup(rport_index)(0) := addr_to_dcache_bank(io.read(rport_index).bits.addr_dup) 705fa5e530dScz4e bank_addrs_dup(rport_index)(1) := Mux(io.is128Req(rport_index), bank_addrs_dup(rport_index)(0) + 1.U, bank_addrs_dup(rport_index)(0)) 70613f2ff1cSMaxpicca-Li set_addrs(rport_index) := addr_to_dcache_div_set(io.read(rport_index).bits.addr) 707fa5e530dScz4e set_addrs_dup(rport_index) := addr_to_dcache_div_set(io.read(rport_index).bits.addr_dup) 7085adc4829SYanqin Li set_addrs_reg(rport_index) := RegEnable(addr_to_dcache_div_set(io.read(rport_index).bits.addr), io.read(rport_index).valid) 709fa5e530dScz4e set_addrs_dup_reg(rport_index) := RegEnable(addr_to_dcache_div_set(io.read(rport_index).bits.addr_dup), io.read(rport_index).valid) 7107dbf3a33SMaxpicca-Li 7117dbf3a33SMaxpicca-Li // use way_en to select a way after data read out 712935edac4STang Haojin assert(!(RegNext(io.read(rport_index).fire && PopCount(io.read(rport_index).bits.way_en) > 1.U))) 7137dbf3a33SMaxpicca-Li way_en(rport_index) := io.read(rport_index).bits.way_en 7145adc4829SYanqin Li way_en_reg(rport_index) := RegEnable(io.read(rport_index).bits.way_en, io.read(rport_index).valid) 7157dbf3a33SMaxpicca-Li }) 7167dbf3a33SMaxpicca-Li 7177dbf3a33SMaxpicca-Li // read each bank, get bank result 7188ffb12e4SAnzo val rr_bank_conflict = Seq.tabulate(LoadPipelineWidth)(x => Seq.tabulate(LoadPipelineWidth)(y => { 7198ffb12e4SAnzo if (x == y) { 7208ffb12e4SAnzo false.B 7218ffb12e4SAnzo } else { 7223eeae490SMaxpicca-Li io.read(x).valid && io.read(y).valid && 7233eeae490SMaxpicca-Li div_addrs(x) === div_addrs(y) && 7248ffb12e4SAnzo (io.read(x).bits.bankMask & io.read(y).bits.bankMask) =/= 0.U && 7258ffb12e4SAnzo set_addrs(x) =/= set_addrs(y) 7268ffb12e4SAnzo } 7278ffb12e4SAnzo } 7287dbf3a33SMaxpicca-Li )) 7298ffb12e4SAnzo 7308ffb12e4SAnzo val load_req_with_bank_conflict = rr_bank_conflict.map(_.reduce(_ || _)) 7318ffb12e4SAnzo val load_req_valid = io.read.map(_.valid) 7328ffb12e4SAnzo val load_req_lqIdx = io.read.map(_.bits.lqIdx) 7338ffb12e4SAnzo val load_req_index = (0 until LoadPipelineWidth).map(_.asUInt) 7348ffb12e4SAnzo 735c5a867ffSAnzo val load_req_bank_conflict_selcet = selcetOldestPort(load_req_with_bank_conflict, load_req_lqIdx, load_req_index) 7368ffb12e4SAnzo val load_req_bank_select_port = UIntToOH(load_req_bank_conflict_selcet._2).asBools 7378ffb12e4SAnzo 7388ffb12e4SAnzo val rr_bank_conflict_oldest = (0 until LoadPipelineWidth).map(i => 7398ffb12e4SAnzo !load_req_bank_select_port(i) && load_req_with_bank_conflict(i) 7408ffb12e4SAnzo ) 7418ffb12e4SAnzo 7427dbf3a33SMaxpicca-Li val rrl_bank_conflict = Wire(Vec(LoadPipelineWidth, Bool())) 7437dbf3a33SMaxpicca-Li val rrl_bank_conflict_intend = Wire(Vec(LoadPipelineWidth, Bool())) 7443eeae490SMaxpicca-Li (0 until LoadPipelineWidth).foreach { i => 745cdbff57cSHaoyuan Feng val judge = if (ReduceReadlineConflict) io.read(i).valid && (io.readline.bits.rmask & io.read(i).bits.bankMask) =/= 0.U && div_addrs(i) === line_div_addr 7463eeae490SMaxpicca-Li else io.read(i).valid && div_addrs(i)===line_div_addr 7473eeae490SMaxpicca-Li rrl_bank_conflict(i) := judge && io.readline.valid 7483eeae490SMaxpicca-Li rrl_bank_conflict_intend(i) := judge && io.readline_intend 7497dbf3a33SMaxpicca-Li } 7503eeae490SMaxpicca-Li val wr_bank_conflict = Seq.tabulate(LoadPipelineWidth)(x => 751cdbff57cSHaoyuan Feng io.read(x).valid && 752cdbff57cSHaoyuan Feng write_valid_reg && 753cdbff57cSHaoyuan Feng div_addrs(x) === write_div_addr_dup_reg.head && 754cdbff57cSHaoyuan Feng (write_bank_mask_reg(bank_addrs(x)(0)) || write_bank_mask_reg(bank_addrs(x)(1)) && io.is128Req(x)) 7553eeae490SMaxpicca-Li ) 7563eeae490SMaxpicca-Li val wrl_bank_conflict = io.readline.valid && write_valid_reg && line_div_addr === write_div_addr_dup_reg.head 7573eeae490SMaxpicca-Li // ready 7583eeae490SMaxpicca-Li io.readline.ready := !(wrl_bank_conflict) 7593eeae490SMaxpicca-Li io.read.zipWithIndex.map{case(x, i) => x.ready := !(wr_bank_conflict(i) || rrhazard)} 7607dbf3a33SMaxpicca-Li 7617dbf3a33SMaxpicca-Li val perf_multi_read = PopCount(io.read.map(_.valid)) >= 2.U 7627dbf3a33SMaxpicca-Li (0 until LoadPipelineWidth).foreach(i => { 76313f2ff1cSMaxpicca-Li // remove fake rr_bank_conflict situation in s2 76413f2ff1cSMaxpicca-Li val real_other_bank_conflict_reg = RegNext(wr_bank_conflict(i) || rrl_bank_conflict(i)) 7658ffb12e4SAnzo val real_rr_bank_conflict_reg = RegNext(rr_bank_conflict_oldest(i)) 76613f2ff1cSMaxpicca-Li io.bank_conflict_slow(i) := real_other_bank_conflict_reg || real_rr_bank_conflict_reg 76713f2ff1cSMaxpicca-Li 76813f2ff1cSMaxpicca-Li // get result in s1 7693eeae490SMaxpicca-Li io.disable_ld_fast_wakeup(i) := wr_bank_conflict(i) || rrl_bank_conflict_intend(i) || 7707dbf3a33SMaxpicca-Li (if (i == 0) 0.B else (0 until i).map(rr_bank_conflict(_)(i)).reduce(_ || _)) 7717dbf3a33SMaxpicca-Li }) 7727dbf3a33SMaxpicca-Li XSPerfAccumulate("data_array_multi_read", perf_multi_read) 7737dbf3a33SMaxpicca-Li (1 until LoadPipelineWidth).foreach(y => (0 until y).foreach(x => 7747dbf3a33SMaxpicca-Li XSPerfAccumulate(s"data_array_rr_bank_conflict_${x}_${y}", rr_bank_conflict(x)(y)) 7757dbf3a33SMaxpicca-Li )) 7767dbf3a33SMaxpicca-Li (0 until LoadPipelineWidth).foreach(i => { 7777dbf3a33SMaxpicca-Li XSPerfAccumulate(s"data_array_rrl_bank_conflict_${i}", rrl_bank_conflict(i)) 7783eeae490SMaxpicca-Li XSPerfAccumulate(s"data_array_rw_bank_conflict_${i}", wr_bank_conflict(i)) 7797dbf3a33SMaxpicca-Li XSPerfAccumulate(s"data_array_read_${i}", io.read(i).valid) 7807dbf3a33SMaxpicca-Li }) 7817dbf3a33SMaxpicca-Li XSPerfAccumulate("data_array_access_total", PopCount(io.read.map(_.valid))) 7827dbf3a33SMaxpicca-Li XSPerfAccumulate("data_array_read_line", io.readline.valid) 7837dbf3a33SMaxpicca-Li XSPerfAccumulate("data_array_write", io.write.valid) 7847dbf3a33SMaxpicca-Li 7857bd3dbddShappy-lx val bank_result = Wire(Vec(DCacheSetDiv, Vec(DCacheBanks, Vec(DCacheWays, new L1BankedDataReadResult())))) 7867bd3dbddShappy-lx val bank_result_delayed = Wire(Vec(DCacheSetDiv, Vec(DCacheBanks, Vec(DCacheWays, new L1BankedDataReadResult())))) 7877bd3dbddShappy-lx val read_bank_error_delayed = Wire(Vec(DCacheSetDiv, Vec(DCacheBanks, Vec(DCacheWays, Bool())))) 7888ffb12e4SAnzo 78972dab974Scz4e val pseudo_data_toggle_mask = io.pseudo_error.bits.map { 79072dab974Scz4e case bank => 79172dab974Scz4e Mux(io.pseudo_error.valid && bank.valid, bank.mask, 0.U) 79272dab974Scz4e } 79372dab974Scz4e val readline_hit = io.readline.fire && 79472dab974Scz4e (io.readline.bits.rmask & VecInit(io.pseudo_error.bits.map(_.valid)).asUInt).orR 79572dab974Scz4e val readbank_hit = io.read.zip(bank_addrs.zip(io.is128Req)).zipWithIndex.map { 79672dab974Scz4e case ((read, (bank_addr, is128Req)), i) => 79772dab974Scz4e val error_bank0 = io.pseudo_error.bits(bank_addr(0)) 79872dab974Scz4e val error_bank1 = io.pseudo_error.bits(bank_addr(1)) 79972dab974Scz4e read.fire && (error_bank0.valid || error_bank1.valid && is128Req) && !io.bank_conflict_slow(i) 80072dab974Scz4e }.reduce(_|_) 80172dab974Scz4e io.pseudo_error.ready := RegNext(readline_hit || readbank_hit) 80272dab974Scz4e 8033eeae490SMaxpicca-Li for (div_index <- 0 until DCacheSetDiv) { 8047dbf3a33SMaxpicca-Li for (bank_index <- 0 until DCacheBanks) { 8057dbf3a33SMaxpicca-Li // Set Addr & Read Way Mask 8067dbf3a33SMaxpicca-Li // 8077dbf3a33SMaxpicca-Li // Pipe 0 .... Pipe (n-1) 8087dbf3a33SMaxpicca-Li // + .... + 8097dbf3a33SMaxpicca-Li // | .... | 8107dbf3a33SMaxpicca-Li // +----+---------------+-----+ 8117dbf3a33SMaxpicca-Li // X X 8127dbf3a33SMaxpicca-Li // X +------+ Bank Addr Match 8137dbf3a33SMaxpicca-Li // +---------+----------+ 8147dbf3a33SMaxpicca-Li // | 8157dbf3a33SMaxpicca-Li // +--------+--------+ 8167dbf3a33SMaxpicca-Li // | Data Bank | 8177dbf3a33SMaxpicca-Li // +-----------------+ 8187dbf3a33SMaxpicca-Li val bank_addr_matchs = WireInit(VecInit(List.tabulate(LoadPipelineWidth)(i => { 8198ffb12e4SAnzo io.read(i).valid && div_addrs(i) === div_index.U && (bank_addrs(i)(0) === bank_index.U || bank_addrs(i)(1) === bank_index.U && io.is128Req(i)) && 8208ffb12e4SAnzo !rr_bank_conflict_oldest(i) 8217dbf3a33SMaxpicca-Li }))) 822fa5e530dScz4e val bank_addr_matchs_dup = WireInit(VecInit(List.tabulate(LoadPipelineWidth)(i => { 823fa5e530dScz4e io.read(i).valid && div_addrs_dup(i) === div_index.U && (bank_addrs_dup(i)(0) === bank_index.U || bank_addrs_dup(i)(1) === bank_index.U && io.is128Req(i)) && 824fa5e530dScz4e !rr_bank_conflict_oldest(i) 825fa5e530dScz4e }))) 8267dbf3a33SMaxpicca-Li val readline_match = Wire(Bool()) 8277dbf3a33SMaxpicca-Li if (ReduceReadlineConflict) { 8283eeae490SMaxpicca-Li readline_match := io.readline.valid && io.readline.bits.rmask(bank_index) && line_div_addr === div_index.U 8297dbf3a33SMaxpicca-Li } else { 8303eeae490SMaxpicca-Li readline_match := io.readline.valid && line_div_addr === div_index.U 8317dbf3a33SMaxpicca-Li } 8327bd3dbddShappy-lx 8337dbf3a33SMaxpicca-Li val bank_set_addr = Mux(readline_match, 8343eeae490SMaxpicca-Li line_set_addr, 8357dbf3a33SMaxpicca-Li PriorityMux(Seq.tabulate(LoadPipelineWidth)(i => bank_addr_matchs(i) -> set_addrs(i))) 8367dbf3a33SMaxpicca-Li ) 837fa5e530dScz4e val bank_set_addr_dup = Mux(readline_match, 838fa5e530dScz4e line_set_addr, 839fa5e530dScz4e PriorityMux(Seq.tabulate(LoadPipelineWidth)(i => bank_addr_matchs_dup(i) -> set_addrs_dup(i))) 840fa5e530dScz4e ) 8417dbf3a33SMaxpicca-Li val read_enable = bank_addr_matchs.asUInt.orR || readline_match 8427dbf3a33SMaxpicca-Li 8437dbf3a33SMaxpicca-Li // read raw data 8443eeae490SMaxpicca-Li val data_bank = data_banks(div_index)(bank_index) 8457dbf3a33SMaxpicca-Li data_bank.io.r.en := read_enable 846fa5e530dScz4e 847fa5e530dScz4e if (DuplicatedQueryBankSeq.contains(bank_index)) { 848fa5e530dScz4e data_bank.io.r.addr := bank_set_addr_dup 849fa5e530dScz4e } else { 8507dbf3a33SMaxpicca-Li data_bank.io.r.addr := bank_set_addr 851fa5e530dScz4e } 8527bd3dbddShappy-lx for (way_index <- 0 until DCacheWays) { 853ebe07d61S梁森 Liang Sen val mbistAck = mbistSramPorts.map(_(div_index)(bank_index)(way_index).ack).getOrElse(false.B) 854b34797bcScz4e bank_result(div_index)(bank_index)(way_index).ecc := getECCFromEncWord(data_bank.io.r.data(way_index)) 855ebe07d61S梁森 Liang Sen bank_result(div_index)(bank_index)(way_index).raw_data := getDataFromEncWord(data_bank.io.r.data(way_index)) ^ Mux(mbistAck, 0.U, pseudo_data_toggle_mask(bank_index)) 8567dbf3a33SMaxpicca-Li 857b34797bcScz4e if (EnableDataEcc) { 8587bd3dbddShappy-lx val ecc_data = bank_result(div_index)(bank_index)(way_index).asECCData() 8597dbf3a33SMaxpicca-Li val ecc_data_delayed = RegEnable(ecc_data, RegNext(read_enable)) 8607bd3dbddShappy-lx bank_result(div_index)(bank_index)(way_index).error_delayed := dcacheParameters.dataCode.decode(ecc_data_delayed).error 8617bd3dbddShappy-lx read_bank_error_delayed(div_index)(bank_index)(way_index) := bank_result(div_index)(bank_index)(way_index).error_delayed 862b34797bcScz4e } else { 8637bd3dbddShappy-lx bank_result(div_index)(bank_index)(way_index).error_delayed := false.B 8647bd3dbddShappy-lx read_bank_error_delayed(div_index)(bank_index)(way_index) := false.B 8657bd3dbddShappy-lx } 866b34797bcScz4e bank_result_delayed(div_index)(bank_index)(way_index) := RegEnable(bank_result(div_index)(bank_index)(way_index), RegNext(read_enable)) 867cd2ff98bShappy-lx } 8683eeae490SMaxpicca-Li } 8697dbf3a33SMaxpicca-Li } 8707dbf3a33SMaxpicca-Li 87104665835SMaxpicca-Li val data_read_oh = WireInit(VecInit(Seq.fill(DCacheSetDiv)(0.U(XLEN.W)))) 87204665835SMaxpicca-Li for (div_index <- 0 until DCacheSetDiv){ 87304665835SMaxpicca-Li val temp = WireInit(VecInit(Seq.fill(DCacheBanks)(0.U(XLEN.W)))) 87404665835SMaxpicca-Li for (bank_index <- 0 until DCacheBanks) { 87504665835SMaxpicca-Li temp(bank_index) := PopCount(Fill(DCacheWays, data_banks(div_index)(bank_index).io.r.en.asUInt)) 87604665835SMaxpicca-Li } 87704665835SMaxpicca-Li data_read_oh(div_index) := temp.reduce(_ + _) 87804665835SMaxpicca-Li } 87904665835SMaxpicca-Li XSPerfAccumulate("data_read_counter", data_read_oh.foldLeft(0.U)(_ + _)) 88004665835SMaxpicca-Li 8817dbf3a33SMaxpicca-Li (0 until LoadPipelineWidth).map(i => { 8827bd3dbddShappy-lx // 1 cycle after read fire(load s2) 8835adc4829SYanqin Li val r_read_fire = RegNext(io.read(i).fire) 884d4564868Sweiding liu val r_div_addr = RegEnable(div_addrs(i), io.read(i).fire) 885d4564868Sweiding liu val r_bank_addr = RegEnable(bank_addrs(i), io.read(i).fire) 8867bd3dbddShappy-lx val r_way_addr = RegEnable(OHToUInt(way_en(i)), io.read(i).fire) 8877bd3dbddShappy-lx // 2 cycles after read fire(load s3) 8885adc4829SYanqin Li val rr_read_fire = RegNext(r_read_fire) 8895adc4829SYanqin Li val rr_div_addr = RegEnable(RegEnable(div_addrs(i), io.read(i).fire), r_read_fire) 8905adc4829SYanqin Li val rr_bank_addr = RegEnable(RegEnable(bank_addrs(i), io.read(i).fire), r_read_fire) 8915adc4829SYanqin Li val rr_way_addr = RegEnable(RegEnable(OHToUInt(way_en(i)), io.read(i).fire), r_read_fire) 892cdbff57cSHaoyuan Feng (0 until VLEN/DCacheSRAMRowBits).map( j =>{ 8937bd3dbddShappy-lx io.read_resp(i)(j) := bank_result(r_div_addr)(r_bank_addr(j))(r_way_addr) 8943eeae490SMaxpicca-Li // error detection 8957bd3dbddShappy-lx io.read_error_delayed(i)(j) := rr_read_fire && read_bank_error_delayed(rr_div_addr)(rr_bank_addr(j))(rr_way_addr) && !RegNext(io.bank_conflict_slow(i)) 896cdbff57cSHaoyuan Feng }) 8977dbf3a33SMaxpicca-Li }) 8987dbf3a33SMaxpicca-Li 8993eeae490SMaxpicca-Li // read result: expose banked read result 900ebe07d61S梁森 Liang Sen private val mbist_r_way = OHToUInt(mbistSramPorts.map(_.flatMap(_.map(w => Cat(w.map(_.re).reverse))).reduce(_ | _)).getOrElse(0.U(DCacheWays.W))) 901ebe07d61S梁森 Liang Sen private val mbist_r_div = OHToUInt(mbistSramPorts.map(_.map(d => Cat(d.flatMap(w => w.map(_.re))).orR)).getOrElse(Seq.fill(DCacheSetDiv)(false.B))) 902ebe07d61S梁森 Liang Sen private val mbist_ack = mbistPl.map(_.mbist.ack).getOrElse(false.B) 903ebe07d61S梁森 Liang Sen 90498d2aaa1Scz4e val readline_error_delayed = Wire(Vec(DCacheBanks, Bool())) 905ebe07d61S梁森 Liang Sen val readline_r_way_addr = RegEnable(Mux(mbist_ack, mbist_r_way, OHToUInt(io.readline.bits.way_en)), io.readline.valid | mbist_ack) 90698d2aaa1Scz4e val readline_rr_way_addr = RegEnable(readline_r_way_addr, RegNext(io.readline.valid)) 907ebe07d61S梁森 Liang Sen val readline_r_div_addr = RegEnable(Mux(mbist_ack, mbist_r_div, line_div_addr), io.readline.valid | mbist_ack) 90898d2aaa1Scz4e val readline_rr_div_addr = RegEnable(readline_r_div_addr, RegNext(io.readline.valid)) 909ebe07d61S梁森 Liang Sen val readline_resp = Wire(io.readline_resp.cloneType) 910ebe07d61S梁森 Liang Sen (0 until DCacheBanks).foreach(i => { 911ebe07d61S梁森 Liang Sen mbistSramPorts.foreach(_.foreach(_(i).foreach(_.rdata := Cat(io.readline_resp(i).ecc, io.readline_resp(i).raw_data)))) 912ebe07d61S梁森 Liang Sen readline_resp(i) := Mux( 913ebe07d61S梁森 Liang Sen io.readline_can_go | mbist_ack, 914ebe07d61S梁森 Liang Sen bank_result(readline_r_div_addr)(i)(readline_r_way_addr), 915ebe07d61S梁森 Liang Sen RegEnable(readline_resp(i), io.readline_stall | mbist_ack) 916ebe07d61S梁森 Liang Sen ) 91798d2aaa1Scz4e readline_error_delayed(i) := bank_result(readline_rr_div_addr)(i)(readline_rr_way_addr).error_delayed 9187bd3dbddShappy-lx }) 919ebe07d61S梁森 Liang Sen io.readline_resp := RegEnable(readline_resp, io.readline_can_resp | mbist_ack) 92098d2aaa1Scz4e io.readline_error_delayed := RegNext(RegNext(io.readline.fire)) && readline_error_delayed.asUInt.orR 9217dbf3a33SMaxpicca-Li 9227dbf3a33SMaxpicca-Li // write data_banks & ecc_banks 9233eeae490SMaxpicca-Li for (div_index <- 0 until DCacheSetDiv) { 9247dbf3a33SMaxpicca-Li for (bank_index <- 0 until DCacheBanks) { 9257dbf3a33SMaxpicca-Li // data write 9263eeae490SMaxpicca-Li val wen_reg = write_bank_mask_reg(bank_index) && 9273eeae490SMaxpicca-Li write_valid_dup_reg(bank_index) && 9284a0e27ecSYanqin Li write_div_addr_dup_reg(bank_index) === div_index.U && RegNext(io.write.valid) 929b34797bcScz4e val write_ecc_reg = RegEnable(getECCFromEncWord(cacheParams.dataCode.encode(io.write.bits.data(bank_index))), io.write.valid) 9303eeae490SMaxpicca-Li val data_bank = data_banks(div_index)(bank_index) 9313eeae490SMaxpicca-Li data_bank.io.w.en := wen_reg 9323eeae490SMaxpicca-Li data_bank.io.w.way_en := write_wayen_dup_reg(bank_index) 9333eeae490SMaxpicca-Li data_bank.io.w.addr := write_set_addr_dup_reg(bank_index) 934b34797bcScz4e data_bank.io.w.data := asECCData(write_ecc_reg, write_data_reg(bank_index)) 9357dbf3a33SMaxpicca-Li } 9363eeae490SMaxpicca-Li } 9377dbf3a33SMaxpicca-Li 9387dbf3a33SMaxpicca-Li val tableName = "BankConflict" + p(XSCoreParamsKey).HartId.toString 9397dbf3a33SMaxpicca-Li val siteName = "BankedDataArray" + p(XSCoreParamsKey).HartId.toString 9407dbf3a33SMaxpicca-Li val bankConflictTable = ChiselDB.createTable(tableName, new BankConflictDB) 9417dbf3a33SMaxpicca-Li val bankConflictData = Wire(new BankConflictDB) 9427dbf3a33SMaxpicca-Li for (i <- 0 until LoadPipelineWidth) { 9437dbf3a33SMaxpicca-Li bankConflictData.set_index(i) := set_addrs(i) 9447dbf3a33SMaxpicca-Li bankConflictData.addr(i) := io.read(i).bits.addr 9457dbf3a33SMaxpicca-Li } 9467dbf3a33SMaxpicca-Li 9477dbf3a33SMaxpicca-Li // FIXME: rr_bank_conflict(0)(1) no generalization 9487dbf3a33SMaxpicca-Li when(rr_bank_conflict(0)(1)) { 949cdbff57cSHaoyuan Feng (0 until (VLEN/DCacheSRAMRowBits)).map(i => { 950cdbff57cSHaoyuan Feng bankConflictData.bank_index(i) := bank_addrs(0)(i) 951cdbff57cSHaoyuan Feng }) 9527dbf3a33SMaxpicca-Li bankConflictData.way_index := OHToUInt(way_en(0)) 95313f2ff1cSMaxpicca-Li bankConflictData.fake_rr_bank_conflict := set_addrs(0) === set_addrs(1) && div_addrs(0) === div_addrs(1) 9547dbf3a33SMaxpicca-Li }.otherwise { 955cdbff57cSHaoyuan Feng (0 until (VLEN/DCacheSRAMRowBits)).map(i => { 956cdbff57cSHaoyuan Feng bankConflictData.bank_index(i) := 0.U 957cdbff57cSHaoyuan Feng }) 9587dbf3a33SMaxpicca-Li bankConflictData.way_index := 0.U 9597dbf3a33SMaxpicca-Li bankConflictData.fake_rr_bank_conflict := false.B 9607dbf3a33SMaxpicca-Li } 9617dbf3a33SMaxpicca-Li 962c686adcdSYinan Xu val isWriteBankConflictTable = Constantin.createRecord(s"isWriteBankConflictTable${p(XSCoreParamsKey).HartId}") 9637dbf3a33SMaxpicca-Li bankConflictTable.log( 9647dbf3a33SMaxpicca-Li data = bankConflictData, 9657dbf3a33SMaxpicca-Li en = isWriteBankConflictTable.orR && rr_bank_conflict(0)(1), 9667dbf3a33SMaxpicca-Li site = siteName, 9677dbf3a33SMaxpicca-Li clock = clock, 9687dbf3a33SMaxpicca-Li reset = reset 9697dbf3a33SMaxpicca-Li ) 9707dbf3a33SMaxpicca-Li 9717dbf3a33SMaxpicca-Li (1 until LoadPipelineWidth).foreach(y => (0 until y).foreach(x => 97204665835SMaxpicca-Li XSPerfAccumulate(s"data_array_fake_rr_bank_conflict_${x}_${y}", rr_bank_conflict(x)(y) && set_addrs(x) === set_addrs(y) && div_addrs(x) === div_addrs(y)) 9737dbf3a33SMaxpicca-Li )) 9747dbf3a33SMaxpicca-Li 9758ffb12e4SAnzo if (backendParams.debugEn){ 9768ffb12e4SAnzo load_req_with_bank_conflict.map(dontTouch(_)) 9778ffb12e4SAnzo dontTouch(bank_result) 9788ffb12e4SAnzo dontTouch(read_bank_error_delayed) 9798ffb12e4SAnzo } 9807dbf3a33SMaxpicca-Li} 981