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.mem 18 19import chisel3._ 20import chisel3.util._ 21import org.chipsalliance.cde.config.Parameters 22import xiangshan._ 23import xiangshan.cache._ 24import xiangshan.cache.{DCacheWordIO, DCacheLineIO, MemoryOpConstants} 25import xiangshan.mem._ 26import xiangshan.backend.rob.RobPtr 27import utils._ 28import utility._ 29 30// Data module define 31// These raw data modules are like SyncDataModuleTemplate, but support cam-like ops 32abstract class LqRawDataModule[T <: Data] ( 33 gen: T, 34 numEntries: Int, 35 numRead: Int, 36 numWrite: Int, 37 numWBank: Int, 38 numWDelay: Int, 39 numCamPort: Int = 0, 40 enableCacheLineCheck: Boolean = false 41)(implicit p: Parameters) extends XSModule { 42 val io = IO(new Bundle() { 43 val ren = Input(Vec(numRead, Bool())) 44 val raddr = Input(Vec(numRead, UInt(log2Up(numEntries).W))) 45 val rdata = Output(Vec(numRead, gen)) 46 val wen = Input(Vec(numWrite, Bool())) 47 val waddr = Input(Vec(numWrite, UInt(log2Up(numEntries).W))) 48 val wdata = Input(Vec(numWrite, gen)) 49 // violation cam: hit if addr is in the same cacheline 50 val violationMdata = Input(Vec(numCamPort, gen)) // addr 51 // This `store` writes the whole `cacheline`.(cbo zero). 52 val violationCheckLine = OptionWrapper(enableCacheLineCheck, Input(Vec(numCamPort, Bool()))) 53 val violationMmask = Output(Vec(numCamPort, Vec(numEntries, Bool()))) // cam result mask 54 // refill cam: hit if addr is in the same cacheline 55 val releaseMdata = Input(Vec(numCamPort, gen)) 56 val releaseMmask = Output(Vec(numCamPort, Vec(numEntries, Bool()))) // cam result mask 57 // release violation cam: hit if addr is in the same cacheline 58 val releaseViolationMdata = Input(Vec(numCamPort, gen)) 59 val releaseViolationMmask = Output(Vec(numCamPort, Vec(numEntries, Bool()))) // cam result mask result 60 }) 61 62 require(isPow2(numWBank), "write bank must be a power of two!") 63 require(numWBank >= 2, "write bank must be greater than or equal to two!") 64 require(numWDelay >= 1, "write delay must be greater than or equal to one!") 65 require(numCamPort >= 0, "camport must be greater than or equal to zero!") 66 require((numEntries % numWBank == 0), "numEntries must be divided by numWBank!") 67 68 val numEntryPerBank = numEntries / numWBank 69 val dataWidth = gen.getWidth 70 71 val data = Reg(Vec(numEntries, gen)) 72 // read ports 73 for (i <- 0 until numRead) { 74 io.rdata(i) := RegEnable(data(io.raddr(i)), io.ren(i)) 75 } 76 77 // write ports 78 val writeAddrDec = io.waddr.map(a => UIntToOH(a)) 79 def selectBankMask(in: UInt, bank: Int): UInt = { 80 in((bank + 1) * numEntryPerBank - 1, bank * numEntryPerBank) 81 } 82 for (bank <- 0 until numWBank) { 83 // write ports 84 // s0: write to bank level buffer 85 val s0_bankWriteAddrDec = writeAddrDec.map(a => selectBankMask(a, bank)) 86 val s0_bankWriteEn = io.wen.zip(s0_bankWriteAddrDec).map(w => w._1 && w._2.orR) 87 s0_bankWriteAddrDec.zipWithIndex.map(a => 88 a._1.suggestName("s0_bankWriteAddrDec" + bank + "_" + a._2) 89 ) 90 s0_bankWriteEn.zipWithIndex.map(a => 91 a._1.suggestName("s0_bankWriteEn" + bank + "_" + a._2) 92 ) 93 // sx: write data to entries 94 val sx_bankWriteAddrDec_resp = (0 until numWrite).map(w => DelayNWithValid(s0_bankWriteAddrDec(w), io.wen(w), numWDelay - 1)) 95 val sx_bankWriteAddrDec = (0 until numWrite).map(w => sx_bankWriteAddrDec_resp(w)._2) 96 val sx_bankWriteEn = s0_bankWriteEn.map(w => DelayN(w, numWDelay - 1)) 97 val sx_writeData_resp = (0 until numWrite).map(w => DelayNWithValid(io.wdata(w), io.wen(w), numWDelay - 1)) 98 val sx_writeData = (0 until numWrite).map(w => sx_writeData_resp(w)._2) 99 100 sx_bankWriteAddrDec.zipWithIndex.map(a => 101 a._1.suggestName("sx_bankWriteAddrDec" + bank + "_" + a._2) 102 ) 103 sx_bankWriteEn.zipWithIndex.map(a => 104 a._1.suggestName("sx_bankWriteEn" + bank + "_" + a._2) 105 ) 106 sx_writeData.zipWithIndex.map(a => 107 a._1.suggestName("sx_writeData" + bank + "_" + a._2) 108 ) 109 110 // entry write 111 for (entry <- 0 until numEntryPerBank) { 112 // write ports 113 val sx_entryWriteEnVec = sx_bankWriteEn.zip(sx_bankWriteAddrDec).map(w => w._1 && w._2(entry)) 114 val sx_entryWriteEn = VecInit(sx_entryWriteEnVec).asUInt.orR 115 val sx_entryWriteData = Mux1H(sx_entryWriteEnVec, sx_writeData) 116 when (sx_entryWriteEn) { 117 data(bank * numEntryPerBank + entry) := sx_entryWriteData 118 } 119 sx_entryWriteEnVec.zipWithIndex.map(a => 120 a._1.suggestName("sx_entryWriteEnVec" + bank + "_" + entry + "_" + a._2) 121 ) 122 sx_entryWriteEn.suggestName("sx_entryWriteEn" + bank + "_" + entry) 123 sx_entryWriteData.suggestName("sx_entryWriteData" + bank + "_" + entry) 124 } 125 } 126 127 // DataModuleTemplate should not be used when there're any write conflicts 128 for (i <- 0 until numWrite) { 129 for (j <- i+1 until numWrite) { 130 assert(!(io.wen(i) && io.wen(j) && io.waddr(i) === io.waddr(j))) 131 } 132 } 133} 134 135// Load queue physical address module 136class LqPAddrModule[T <: UInt]( 137 gen: T, 138 numEntries: Int, 139 numRead: Int, 140 numWrite: Int, 141 numWBank: Int, 142 numWDelay: Int = 1, 143 numCamPort: Int = 1, 144 enableCacheLineCheck: Boolean = false, // Check the entire cacheline. when enabled, set `paddrOffset` correctly. 145 paddrOffset: Int // The least significant `paddrOffset` bits of paddr are neglected. 146)(implicit p: Parameters) extends LqRawDataModule(gen, numEntries, numRead, numWrite, numWBank, numWDelay, numCamPort, enableCacheLineCheck) 147 with HasDCacheParameters 148{ 149 // content addressed match 150 // 128-bits aligned 151 val needCacheLineCheck = enableCacheLineCheck && DCacheLineOffset > paddrOffset 152 for (i <- 0 until numCamPort) { 153 for (j <- 0 until numEntries) { 154 if (needCacheLineCheck) { 155 val cacheLineOffset = DCacheLineOffset - paddrOffset 156 val cacheLineHit = io.violationMdata(i)(dataWidth - 1, cacheLineOffset) === data(j)(dataWidth - 1, cacheLineOffset) 157 val lowAddrHit = io.violationMdata(i)(cacheLineOffset - 1, 0) === data(j)(cacheLineOffset - 1, 0) 158 io.violationMmask(i)(j) := cacheLineHit && (io.violationCheckLine.get(i) || lowAddrHit) 159 } else { 160 io.violationMmask(i)(j) := io.violationMdata(i) === data(j) 161 } 162 163 } 164 } 165 166 // content addressed match 167 // cacheline aligned 168 for (i <- 0 until numCamPort) { 169 for (j <- 0 until numEntries) { 170 io.releaseViolationMmask(i)(j) := io.releaseViolationMdata(i) === data(j) 171 } 172 } 173 174 // content addressed match 175 // cacheline aligned 176 for (i <- 0 until numCamPort) { 177 for (j <- 0 until numEntries) { 178 io.releaseMmask(i)(j) := io.releaseMdata(i) === data(j) 179 } 180 } 181} 182 183// Load queue data module 184class LqVAddrModule[T <: UInt]( 185 gen: T, 186 numEntries: Int, 187 numRead: Int, 188 numWrite: Int, 189 numWBank: Int, 190 numWDelay: Int = 1, 191 numCamPort: Int = 1)(implicit p: Parameters) extends LqRawDataModule(gen, numEntries, numRead, numWrite, numWBank, numWDelay, numCamPort) 192 with HasDCacheParameters 193{ 194 // content addressed match 195 for (i <- 0 until numCamPort) { 196 for (j <- 0 until numEntries) { 197 io.violationMmask(i)(j) := io.violationMdata(i)(VAddrBits-1, DCacheVWordOffset) === data(j)(VAddrBits-1, DCacheVWordOffset) 198 } 199 } 200 201 // content addressed match 202 for (i <- 0 until numCamPort) { 203 for (j <- 0 until numEntries) { 204 io.releaseMmask(i)(j) := io.releaseMdata(i)(VAddrBits-1, DCacheLineOffset) === data(j)(VAddrBits-1, DCacheLineOffset) 205 } 206 } 207} 208 209// Load queue mask module 210class LqMaskModule[T <: UInt]( 211 gen: T, 212 numEntries: Int, 213 numRead: Int, 214 numWrite: Int, 215 numWBank: Int, 216 numWDelay: Int = 1, 217 numCamPort: Int = 1)(implicit p: Parameters) extends LqRawDataModule(gen, numEntries, numRead, numWrite, numWBank, numWDelay, numCamPort) 218 with HasDCacheParameters 219{ 220 // content addressed match 221 for (i <- 0 until numCamPort) { 222 for (j <- 0 until numEntries) { 223 io.violationMmask(i)(j) := (io.violationMdata(i) & data(j)).orR 224 } 225 } 226 // content addressed match 227 // cacheline aligned 228 for (i <- 0 until numCamPort) { 229 for (j <- 0 until numEntries) { 230 io.releaseViolationMmask(i)(j) := (io.releaseViolationMdata(i) & data(j)).orR 231 } 232 } 233 234 // content addressed match 235 for (i <- 0 until numCamPort) { 236 for (j <- 0 until numEntries) { 237 io.releaseMmask(i)(j) := (io.releaseMdata(i) & data(j)).orR 238 } 239 } 240} 241