1c6d43980SLemover/*************************************************************************************** 2c6d43980SLemover* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3f320e0f0SYinan Xu* Copyright (c) 2020-2021 Peng Cheng Laboratory 4c6d43980SLemover* 5c6d43980SLemover* XiangShan is licensed under Mulan PSL v2. 6c6d43980SLemover* You can use this software according to the terms and conditions of the Mulan PSL v2. 7c6d43980SLemover* You may obtain a copy of Mulan PSL v2 at: 8c6d43980SLemover* http://license.coscl.org.cn/MulanPSL2 9c6d43980SLemover* 10c6d43980SLemover* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11c6d43980SLemover* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12c6d43980SLemover* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13c6d43980SLemover* 14c6d43980SLemover* See the Mulan PSL v2 for more details. 15c6d43980SLemover***************************************************************************************/ 16c6d43980SLemover 177057673cSWilliam Wangpackage xiangshan.mem 187057673cSWilliam Wang 197057673cSWilliam Wangimport chisel3._ 207057673cSWilliam Wangimport chisel3.util._ 218891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters 227057673cSWilliam Wangimport xiangshan._ 237057673cSWilliam Wangimport xiangshan.cache._ 246d5ddbceSLemoverimport xiangshan.cache.{DCacheWordIO, DCacheLineIO, MemoryOpConstants} 257057673cSWilliam Wangimport xiangshan.mem._ 269aca92b9SYinan Xuimport xiangshan.backend.rob.RobPtr 27e4f69d78Ssfencevmaimport utils._ 28e4f69d78Ssfencevmaimport utility._ 290a47e4a1SWilliam Wang 30bf6b6e21SWilliam Wang// Data module define 31e4f69d78Ssfencevma// These raw data modules are like SyncDataModuleTemplate, but support cam-like ops 32*3c808de0SAnzoabstract class LqRawDataModule[T <: Data] ( 33*3c808de0SAnzo gen: T, 34*3c808de0SAnzo numEntries: Int, 35*3c808de0SAnzo numRead: Int, 36*3c808de0SAnzo numWrite: Int, 37*3c808de0SAnzo numWBank: Int, 38*3c808de0SAnzo numWDelay: Int, 39*3c808de0SAnzo numCamPort: Int = 0, 40*3c808de0SAnzo enableCacheLineCheck: Boolean = false 41*3c808de0SAnzo)(implicit p: Parameters) extends XSModule { 42e4f69d78Ssfencevma val io = IO(new Bundle() { 438a610956Ssfencevma val ren = Input(Vec(numRead, Bool())) 44f02b5115SWilliam Wang val raddr = Input(Vec(numRead, UInt(log2Up(numEntries).W))) 45e4f69d78Ssfencevma val rdata = Output(Vec(numRead, gen)) 46f02b5115SWilliam Wang val wen = Input(Vec(numWrite, Bool())) 47f02b5115SWilliam Wang val waddr = Input(Vec(numWrite, UInt(log2Up(numEntries).W))) 48e4f69d78Ssfencevma val wdata = Input(Vec(numWrite, gen)) 49e4f69d78Ssfencevma // violation cam: hit if addr is in the same cacheline 50e4f69d78Ssfencevma val violationMdata = Input(Vec(numCamPort, gen)) // addr 51*3c808de0SAnzo // This `store` writes the whole `cacheline`.(cbo zero). 52*3c808de0SAnzo val violationCheckLine = OptionWrapper(enableCacheLineCheck, Input(Vec(numCamPort, Bool()))) 53e4f69d78Ssfencevma val violationMmask = Output(Vec(numCamPort, Vec(numEntries, Bool()))) // cam result mask 54e4f69d78Ssfencevma // refill cam: hit if addr is in the same cacheline 55e4f69d78Ssfencevma val releaseMdata = Input(Vec(numCamPort, gen)) 56e4f69d78Ssfencevma val releaseMmask = Output(Vec(numCamPort, Vec(numEntries, Bool()))) // cam result mask 57e4f69d78Ssfencevma // release violation cam: hit if addr is in the same cacheline 58e4f69d78Ssfencevma val releaseViolationMdata = Input(Vec(numCamPort, gen)) 59e4f69d78Ssfencevma val releaseViolationMmask = Output(Vec(numCamPort, Vec(numEntries, Bool()))) // cam result mask result 60bf6b6e21SWilliam Wang }) 61bf6b6e21SWilliam Wang 62e4f69d78Ssfencevma require(isPow2(numWBank), "write bank must be a power of two!") 63e4f69d78Ssfencevma require(numWBank >= 2, "write bank must be greater than or equal to two!") 64e4f69d78Ssfencevma require(numWDelay >= 1, "write delay must be greater than or equal to one!") 65e4f69d78Ssfencevma require(numCamPort >= 0, "camport must be greater than or equal to zero!") 66692e2fafSHuijin Li require((numEntries % numWBank == 0), "numEntries must be divided by numWBank!") 670a47e4a1SWilliam Wang 68e4f69d78Ssfencevma val numEntryPerBank = numEntries / numWBank 69*3c808de0SAnzo val dataWidth = gen.getWidth 700a47e4a1SWilliam Wang 71e4f69d78Ssfencevma val data = Reg(Vec(numEntries, gen)) 72bf6b6e21SWilliam Wang // read ports 73bf6b6e21SWilliam Wang for (i <- 0 until numRead) { 748a610956Ssfencevma io.rdata(i) := RegEnable(data(io.raddr(i)), io.ren(i)) 75bf6b6e21SWilliam Wang } 76bf6b6e21SWilliam Wang 770a47e4a1SWilliam Wang // write ports 78e4f69d78Ssfencevma val writeAddrDec = io.waddr.map(a => UIntToOH(a)) 790a47e4a1SWilliam Wang def selectBankMask(in: UInt, bank: Int): UInt = { 800a47e4a1SWilliam Wang in((bank + 1) * numEntryPerBank - 1, bank * numEntryPerBank) 810a47e4a1SWilliam Wang } 82e4f69d78Ssfencevma for (bank <- 0 until numWBank) { 830a47e4a1SWilliam Wang // write ports 840a47e4a1SWilliam Wang // s0: write to bank level buffer 85e4f69d78Ssfencevma val s0_bankWriteAddrDec = writeAddrDec.map(a => selectBankMask(a, bank)) 86e4f69d78Ssfencevma val s0_bankWriteEn = io.wen.zip(s0_bankWriteAddrDec).map(w => w._1 && w._2.orR) 87e4f69d78Ssfencevma s0_bankWriteAddrDec.zipWithIndex.map(a => 88e4f69d78Ssfencevma a._1.suggestName("s0_bankWriteAddrDec" + bank + "_" + a._2) 890a47e4a1SWilliam Wang ) 90e4f69d78Ssfencevma s0_bankWriteEn.zipWithIndex.map(a => 91e4f69d78Ssfencevma a._1.suggestName("s0_bankWriteEn" + bank + "_" + a._2) 920a47e4a1SWilliam Wang ) 93e4f69d78Ssfencevma // sx: write data to entries 945003e6f8SHuijin Li val sx_bankWriteAddrDec_resp = (0 until numWrite).map(w => DelayNWithValid(s0_bankWriteAddrDec(w), io.wen(w), numWDelay - 1)) 955003e6f8SHuijin Li val sx_bankWriteAddrDec = (0 until numWrite).map(w => sx_bankWriteAddrDec_resp(w)._2) 96e4f69d78Ssfencevma val sx_bankWriteEn = s0_bankWriteEn.map(w => DelayN(w, numWDelay - 1)) 975003e6f8SHuijin Li val sx_writeData_resp = (0 until numWrite).map(w => DelayNWithValid(io.wdata(w), io.wen(w), numWDelay - 1)) 985003e6f8SHuijin Li val sx_writeData = (0 until numWrite).map(w => sx_writeData_resp(w)._2) 995003e6f8SHuijin Li 100e4f69d78Ssfencevma sx_bankWriteAddrDec.zipWithIndex.map(a => 101e4f69d78Ssfencevma a._1.suggestName("sx_bankWriteAddrDec" + bank + "_" + a._2) 1020a47e4a1SWilliam Wang ) 103e4f69d78Ssfencevma sx_bankWriteEn.zipWithIndex.map(a => 104e4f69d78Ssfencevma a._1.suggestName("sx_bankWriteEn" + bank + "_" + a._2) 1050a47e4a1SWilliam Wang ) 106e4f69d78Ssfencevma sx_writeData.zipWithIndex.map(a => 107e4f69d78Ssfencevma a._1.suggestName("sx_writeData" + bank + "_" + a._2) 1080a47e4a1SWilliam Wang ) 1090a47e4a1SWilliam Wang 1100a47e4a1SWilliam Wang // entry write 1110a47e4a1SWilliam Wang for (entry <- 0 until numEntryPerBank) { 1120a47e4a1SWilliam Wang // write ports 113e4f69d78Ssfencevma val sx_entryWriteEnVec = sx_bankWriteEn.zip(sx_bankWriteAddrDec).map(w => w._1 && w._2(entry)) 114e4f69d78Ssfencevma val sx_entryWriteEn = VecInit(sx_entryWriteEnVec).asUInt.orR 115e4f69d78Ssfencevma val sx_entryWriteData = Mux1H(sx_entryWriteEnVec, sx_writeData) 116e4f69d78Ssfencevma when (sx_entryWriteEn) { 117e4f69d78Ssfencevma data(bank * numEntryPerBank + entry) := sx_entryWriteData 1180a47e4a1SWilliam Wang } 119e4f69d78Ssfencevma sx_entryWriteEnVec.zipWithIndex.map(a => 120e4f69d78Ssfencevma a._1.suggestName("sx_entryWriteEnVec" + bank + "_" + entry + "_" + a._2) 1210a47e4a1SWilliam Wang ) 122e4f69d78Ssfencevma sx_entryWriteEn.suggestName("sx_entryWriteEn" + bank + "_" + entry) 123e4f69d78Ssfencevma sx_entryWriteData.suggestName("sx_entryWriteData" + bank + "_" + entry) 124e4f69d78Ssfencevma } 125e4f69d78Ssfencevma } 126e4f69d78Ssfencevma 127e4f69d78Ssfencevma // DataModuleTemplate should not be used when there're any write conflicts 128e4f69d78Ssfencevma for (i <- 0 until numWrite) { 129e4f69d78Ssfencevma for (j <- i+1 until numWrite) { 130e4f69d78Ssfencevma assert(!(io.wen(i) && io.wen(j) && io.waddr(i) === io.waddr(j))) 131e4f69d78Ssfencevma } 132e4f69d78Ssfencevma } 133e4f69d78Ssfencevma} 134e4f69d78Ssfencevma 135e4f69d78Ssfencevma// Load queue physical address module 136e4f69d78Ssfencevmaclass LqPAddrModule[T <: UInt]( 137e4f69d78Ssfencevma gen: T, 138e4f69d78Ssfencevma numEntries: Int, 139e4f69d78Ssfencevma numRead: Int, 140e4f69d78Ssfencevma numWrite: Int, 141e4f69d78Ssfencevma numWBank: Int, 142e4f69d78Ssfencevma numWDelay: Int = 1, 143*3c808de0SAnzo numCamPort: Int = 1, 144*3c808de0SAnzo enableCacheLineCheck: Boolean = false, // Check the entire cacheline. when enabled, set `paddrOffset` correctly. 145*3c808de0SAnzo paddrOffset: Int // The least significant `paddrOffset` bits of paddr are neglected. 146*3c808de0SAnzo)(implicit p: Parameters) extends LqRawDataModule(gen, numEntries, numRead, numWrite, numWBank, numWDelay, numCamPort, enableCacheLineCheck) 147e4f69d78Ssfencevma with HasDCacheParameters 148e4f69d78Ssfencevma{ 149e4f69d78Ssfencevma // content addressed match 150cdbff57cSHaoyuan Feng // 128-bits aligned 151*3c808de0SAnzo val needCacheLineCheck = enableCacheLineCheck && DCacheLineOffset > paddrOffset 152e4f69d78Ssfencevma for (i <- 0 until numCamPort) { 153e4f69d78Ssfencevma for (j <- 0 until numEntries) { 154*3c808de0SAnzo if (needCacheLineCheck) { 155*3c808de0SAnzo val cacheLineOffset = DCacheLineOffset - paddrOffset 156*3c808de0SAnzo val cacheLineHit = io.violationMdata(i)(dataWidth - 1, cacheLineOffset) === data(j)(dataWidth - 1, cacheLineOffset) 157*3c808de0SAnzo val lowAddrHit = io.violationMdata(i)(cacheLineOffset - 1, 0) === data(j)(cacheLineOffset - 1, 0) 158*3c808de0SAnzo io.violationMmask(i)(j) := cacheLineHit && (io.violationCheckLine.get(i) || lowAddrHit) 159*3c808de0SAnzo } else { 160549073a0Scz4e io.violationMmask(i)(j) := io.violationMdata(i) === data(j) 161bf6b6e21SWilliam Wang } 162*3c808de0SAnzo 163*3c808de0SAnzo } 164bf6b6e21SWilliam Wang } 165bf6b6e21SWilliam Wang 166bf6b6e21SWilliam Wang // content addressed match 167e4f69d78Ssfencevma // cacheline aligned 168e4f69d78Ssfencevma for (i <- 0 until numCamPort) { 169bf6b6e21SWilliam Wang for (j <- 0 until numEntries) { 170549073a0Scz4e io.releaseViolationMmask(i)(j) := io.releaseViolationMdata(i) === data(j) 17167682d05SWilliam Wang } 17267682d05SWilliam Wang } 173e4f69d78Ssfencevma 174e4f69d78Ssfencevma // content addressed match 175e4f69d78Ssfencevma // cacheline aligned 176e4f69d78Ssfencevma for (i <- 0 until numCamPort) { 17767682d05SWilliam Wang for (j <- 0 until numEntries) { 178549073a0Scz4e io.releaseMmask(i)(j) := io.releaseMdata(i) === data(j) 179bf6b6e21SWilliam Wang } 180bf6b6e21SWilliam Wang } 181bf6b6e21SWilliam Wang} 182bf6b6e21SWilliam Wang 183e4f69d78Ssfencevma// Load queue data module 184e4f69d78Ssfencevmaclass LqVAddrModule[T <: UInt]( 185e4f69d78Ssfencevma gen: T, 186e4f69d78Ssfencevma numEntries: Int, 187e4f69d78Ssfencevma numRead: Int, 188e4f69d78Ssfencevma numWrite: Int, 189e4f69d78Ssfencevma numWBank: Int, 190e4f69d78Ssfencevma numWDelay: Int = 1, 191e4f69d78Ssfencevma numCamPort: Int = 1)(implicit p: Parameters) extends LqRawDataModule(gen, numEntries, numRead, numWrite, numWBank, numWDelay, numCamPort) 192e4f69d78Ssfencevma with HasDCacheParameters 193e4f69d78Ssfencevma{ 194e4f69d78Ssfencevma // content addressed match 195e4f69d78Ssfencevma for (i <- 0 until numCamPort) { 1960a47e4a1SWilliam Wang for (j <- 0 until numEntries) { 197cdbff57cSHaoyuan Feng io.violationMmask(i)(j) := io.violationMdata(i)(VAddrBits-1, DCacheVWordOffset) === data(j)(VAddrBits-1, DCacheVWordOffset) 198bf6b6e21SWilliam Wang } 199bf6b6e21SWilliam Wang } 200bf6b6e21SWilliam Wang 201e4f69d78Ssfencevma // content addressed match 202e4f69d78Ssfencevma for (i <- 0 until numCamPort) { 203e4f69d78Ssfencevma for (j <- 0 until numEntries) { 204cdbff57cSHaoyuan Feng io.releaseMmask(i)(j) := io.releaseMdata(i)(VAddrBits-1, DCacheLineOffset) === data(j)(VAddrBits-1, DCacheLineOffset) 205e4f69d78Ssfencevma } 206e4f69d78Ssfencevma } 207e4f69d78Ssfencevma} 208e4f69d78Ssfencevma 209e4f69d78Ssfencevma// Load queue mask module 210e4f69d78Ssfencevmaclass LqMaskModule[T <: UInt]( 211e4f69d78Ssfencevma gen: T, 212e4f69d78Ssfencevma numEntries: Int, 213e4f69d78Ssfencevma numRead: Int, 214e4f69d78Ssfencevma numWrite: Int, 215e4f69d78Ssfencevma numWBank: Int, 216e4f69d78Ssfencevma numWDelay: Int = 1, 217e4f69d78Ssfencevma numCamPort: Int = 1)(implicit p: Parameters) extends LqRawDataModule(gen, numEntries, numRead, numWrite, numWBank, numWDelay, numCamPort) 218e4f69d78Ssfencevma with HasDCacheParameters 219e4f69d78Ssfencevma{ 220e4f69d78Ssfencevma // content addressed match 221e4f69d78Ssfencevma for (i <- 0 until numCamPort) { 222bf6b6e21SWilliam Wang for (j <- 0 until numEntries) { 223f02b5115SWilliam Wang io.violationMmask(i)(j) := (io.violationMdata(i) & data(j)).orR 224bf6b6e21SWilliam Wang } 225bf6b6e21SWilliam Wang } 226e4f69d78Ssfencevma // content addressed match 227e4f69d78Ssfencevma // cacheline aligned 228e4f69d78Ssfencevma for (i <- 0 until numCamPort) { 229e4f69d78Ssfencevma for (j <- 0 until numEntries) { 230e4f69d78Ssfencevma io.releaseViolationMmask(i)(j) := (io.releaseViolationMdata(i) & data(j)).orR 231f02b5115SWilliam Wang } 232f02b5115SWilliam Wang } 233f02b5115SWilliam Wang 234e4f69d78Ssfencevma // content addressed match 235e4f69d78Ssfencevma for (i <- 0 until numCamPort) { 236e4f69d78Ssfencevma for (j <- 0 until numEntries) { 237e4f69d78Ssfencevma io.releaseMmask(i)(j) := (io.releaseMdata(i) & data(j)).orR 2381c2ecc42SWilliam Wang } 2391c2ecc42SWilliam Wang } 2407057673cSWilliam Wang} 241