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] (gen: T, numEntries: Int, numRead: Int, numWrite: Int, numWBank: Int, numWDelay: Int, numCamPort: Int = 0)(implicit p: Parameters) extends XSModule { 33 val io = IO(new Bundle() { 34 val ren = Input(Vec(numRead, Bool())) 35 val raddr = Input(Vec(numRead, UInt(log2Up(numEntries).W))) 36 val rdata = Output(Vec(numRead, gen)) 37 val wen = Input(Vec(numWrite, Bool())) 38 val waddr = Input(Vec(numWrite, UInt(log2Up(numEntries).W))) 39 val wdata = Input(Vec(numWrite, gen)) 40 // violation cam: hit if addr is in the same cacheline 41 val violationMdata = Input(Vec(numCamPort, gen)) // addr 42 val violationMmask = Output(Vec(numCamPort, Vec(numEntries, Bool()))) // cam result mask 43 // refill cam: hit if addr is in the same cacheline 44 val releaseMdata = Input(Vec(numCamPort, gen)) 45 val releaseMmask = Output(Vec(numCamPort, Vec(numEntries, Bool()))) // cam result mask 46 // release violation cam: hit if addr is in the same cacheline 47 val releaseViolationMdata = Input(Vec(numCamPort, gen)) 48 val releaseViolationMmask = Output(Vec(numCamPort, Vec(numEntries, Bool()))) // cam result mask result 49 }) 50 51 require(isPow2(numWBank), "write bank must be a power of two!") 52 require(numWBank >= 2, "write bank must be greater than or equal to two!") 53 require(numWDelay >= 1, "write delay must be greater than or equal to one!") 54 require(numCamPort >= 0, "camport must be greater than or equal to zero!") 55 require((numEntries % numWBank == 0), "numEntries must be divided by numWBank!") 56 57 val numEntryPerBank = numEntries / numWBank 58 59 val data = Reg(Vec(numEntries, gen)) 60 // read ports 61 for (i <- 0 until numRead) { 62 io.rdata(i) := RegEnable(data(io.raddr(i)), io.ren(i)) 63 } 64 65 // write ports 66 val writeAddrDec = io.waddr.map(a => UIntToOH(a)) 67 def selectBankMask(in: UInt, bank: Int): UInt = { 68 in((bank + 1) * numEntryPerBank - 1, bank * numEntryPerBank) 69 } 70 for (bank <- 0 until numWBank) { 71 // write ports 72 // s0: write to bank level buffer 73 val s0_bankWriteAddrDec = writeAddrDec.map(a => selectBankMask(a, bank)) 74 val s0_bankWriteEn = io.wen.zip(s0_bankWriteAddrDec).map(w => w._1 && w._2.orR) 75 s0_bankWriteAddrDec.zipWithIndex.map(a => 76 a._1.suggestName("s0_bankWriteAddrDec" + bank + "_" + a._2) 77 ) 78 s0_bankWriteEn.zipWithIndex.map(a => 79 a._1.suggestName("s0_bankWriteEn" + bank + "_" + a._2) 80 ) 81 // sx: write data to entries 82 val sx_bankWriteAddrDec_resp = (0 until numWrite).map(w => DelayNWithValid(s0_bankWriteAddrDec(w), io.wen(w), numWDelay - 1)) 83 val sx_bankWriteAddrDec = (0 until numWrite).map(w => sx_bankWriteAddrDec_resp(w)._2) 84 val sx_bankWriteEn = s0_bankWriteEn.map(w => DelayN(w, numWDelay - 1)) 85 val sx_writeData_resp = (0 until numWrite).map(w => DelayNWithValid(io.wdata(w), io.wen(w), numWDelay - 1)) 86 val sx_writeData = (0 until numWrite).map(w => sx_writeData_resp(w)._2) 87 88 sx_bankWriteAddrDec.zipWithIndex.map(a => 89 a._1.suggestName("sx_bankWriteAddrDec" + bank + "_" + a._2) 90 ) 91 sx_bankWriteEn.zipWithIndex.map(a => 92 a._1.suggestName("sx_bankWriteEn" + bank + "_" + a._2) 93 ) 94 sx_writeData.zipWithIndex.map(a => 95 a._1.suggestName("sx_writeData" + bank + "_" + a._2) 96 ) 97 98 // entry write 99 for (entry <- 0 until numEntryPerBank) { 100 // write ports 101 val sx_entryWriteEnVec = sx_bankWriteEn.zip(sx_bankWriteAddrDec).map(w => w._1 && w._2(entry)) 102 val sx_entryWriteEn = VecInit(sx_entryWriteEnVec).asUInt.orR 103 val sx_entryWriteData = Mux1H(sx_entryWriteEnVec, sx_writeData) 104 when (sx_entryWriteEn) { 105 data(bank * numEntryPerBank + entry) := sx_entryWriteData 106 } 107 sx_entryWriteEnVec.zipWithIndex.map(a => 108 a._1.suggestName("sx_entryWriteEnVec" + bank + "_" + entry + "_" + a._2) 109 ) 110 sx_entryWriteEn.suggestName("sx_entryWriteEn" + bank + "_" + entry) 111 sx_entryWriteData.suggestName("sx_entryWriteData" + bank + "_" + entry) 112 } 113 } 114 115 // DataModuleTemplate should not be used when there're any write conflicts 116 for (i <- 0 until numWrite) { 117 for (j <- i+1 until numWrite) { 118 assert(!(io.wen(i) && io.wen(j) && io.waddr(i) === io.waddr(j))) 119 } 120 } 121} 122 123// Load queue physical address module 124class LqPAddrModule[T <: UInt]( 125 gen: T, 126 numEntries: Int, 127 numRead: Int, 128 numWrite: Int, 129 numWBank: Int, 130 numWDelay: Int = 1, 131 numCamPort: Int = 1)(implicit p: Parameters) extends LqRawDataModule(gen, numEntries, numRead, numWrite, numWBank, numWDelay, numCamPort) 132 with HasDCacheParameters 133{ 134 // content addressed match 135 // 128-bits aligned 136 for (i <- 0 until numCamPort) { 137 for (j <- 0 until numEntries) { 138 io.violationMmask(i)(j) := io.violationMdata(i)(PAddrBits-1, DCacheVWordOffset) === data(j)(PAddrBits-1, DCacheVWordOffset) 139 } 140 } 141 142 // content addressed match 143 // cacheline aligned 144 for (i <- 0 until numCamPort) { 145 for (j <- 0 until numEntries) { 146 io.releaseViolationMmask(i)(j) := io.releaseViolationMdata(i)(PAddrBits-1, DCacheLineOffset) === data(j)(PAddrBits-1, DCacheLineOffset) 147 } 148 } 149 150 // content addressed match 151 // cacheline aligned 152 for (i <- 0 until numCamPort) { 153 for (j <- 0 until numEntries) { 154 io.releaseMmask(i)(j) := io.releaseMdata(i)(PAddrBits-1, DCacheLineOffset) === data(j)(PAddrBits-1, DCacheLineOffset) 155 } 156 } 157} 158 159// Load queue data module 160class LqVAddrModule[T <: UInt]( 161 gen: T, 162 numEntries: Int, 163 numRead: Int, 164 numWrite: Int, 165 numWBank: Int, 166 numWDelay: Int = 1, 167 numCamPort: Int = 1)(implicit p: Parameters) extends LqRawDataModule(gen, numEntries, numRead, numWrite, numWBank, numWDelay, numCamPort) 168 with HasDCacheParameters 169{ 170 // content addressed match 171 for (i <- 0 until numCamPort) { 172 for (j <- 0 until numEntries) { 173 io.violationMmask(i)(j) := io.violationMdata(i)(VAddrBits-1, DCacheVWordOffset) === data(j)(VAddrBits-1, DCacheVWordOffset) 174 } 175 } 176 177 // content addressed match 178 for (i <- 0 until numCamPort) { 179 for (j <- 0 until numEntries) { 180 io.releaseMmask(i)(j) := io.releaseMdata(i)(VAddrBits-1, DCacheLineOffset) === data(j)(VAddrBits-1, DCacheLineOffset) 181 } 182 } 183} 184 185// Load queue mask module 186class LqMaskModule[T <: UInt]( 187 gen: T, 188 numEntries: Int, 189 numRead: Int, 190 numWrite: Int, 191 numWBank: Int, 192 numWDelay: Int = 1, 193 numCamPort: Int = 1)(implicit p: Parameters) extends LqRawDataModule(gen, numEntries, numRead, numWrite, numWBank, numWDelay, numCamPort) 194 with HasDCacheParameters 195{ 196 // content addressed match 197 for (i <- 0 until numCamPort) { 198 for (j <- 0 until numEntries) { 199 io.violationMmask(i)(j) := (io.violationMdata(i) & data(j)).orR 200 } 201 } 202 // content addressed match 203 // cacheline aligned 204 for (i <- 0 until numCamPort) { 205 for (j <- 0 until numEntries) { 206 io.releaseViolationMmask(i)(j) := (io.releaseViolationMdata(i) & data(j)).orR 207 } 208 } 209 210 // content addressed match 211 for (i <- 0 until numCamPort) { 212 for (j <- 0 until numEntries) { 213 io.releaseMmask(i)(j) := (io.releaseMdata(i) & data(j)).orR 214 } 215 } 216} 217