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 = s0_bankWriteAddrDec.map(w => DelayN(w, numWDelay - 1)) 83 val sx_bankWriteEn = s0_bankWriteEn.map(w => DelayN(w, numWDelay - 1)) 84 val sx_writeData = io.wdata.map(w => DelayN(w, numWDelay - 1)) 85 sx_bankWriteAddrDec.zipWithIndex.map(a => 86 a._1.suggestName("sx_bankWriteAddrDec" + bank + "_" + a._2) 87 ) 88 sx_bankWriteEn.zipWithIndex.map(a => 89 a._1.suggestName("sx_bankWriteEn" + bank + "_" + a._2) 90 ) 91 sx_writeData.zipWithIndex.map(a => 92 a._1.suggestName("sx_writeData" + bank + "_" + a._2) 93 ) 94 95 // entry write 96 for (entry <- 0 until numEntryPerBank) { 97 // write ports 98 val sx_entryWriteEnVec = sx_bankWriteEn.zip(sx_bankWriteAddrDec).map(w => w._1 && w._2(entry)) 99 val sx_entryWriteEn = VecInit(sx_entryWriteEnVec).asUInt.orR 100 val sx_entryWriteData = Mux1H(sx_entryWriteEnVec, sx_writeData) 101 when (sx_entryWriteEn) { 102 data(bank * numEntryPerBank + entry) := sx_entryWriteData 103 } 104 sx_entryWriteEnVec.zipWithIndex.map(a => 105 a._1.suggestName("sx_entryWriteEnVec" + bank + "_" + entry + "_" + a._2) 106 ) 107 sx_entryWriteEn.suggestName("sx_entryWriteEn" + bank + "_" + entry) 108 sx_entryWriteData.suggestName("sx_entryWriteData" + bank + "_" + entry) 109 } 110 } 111 112 // DataModuleTemplate should not be used when there're any write conflicts 113 for (i <- 0 until numWrite) { 114 for (j <- i+1 until numWrite) { 115 assert(!(io.wen(i) && io.wen(j) && io.waddr(i) === io.waddr(j))) 116 } 117 } 118} 119 120// Load queue physical address module 121class LqPAddrModule[T <: UInt]( 122 gen: T, 123 numEntries: Int, 124 numRead: Int, 125 numWrite: Int, 126 numWBank: Int, 127 numWDelay: Int = 1, 128 numCamPort: Int = 1)(implicit p: Parameters) extends LqRawDataModule(gen, numEntries, numRead, numWrite, numWBank, numWDelay, numCamPort) 129 with HasDCacheParameters 130{ 131 // content addressed match 132 // 128-bits aligned 133 for (i <- 0 until numCamPort) { 134 for (j <- 0 until numEntries) { 135 io.violationMmask(i)(j) := io.violationMdata(i)(PAddrBits-1, DCacheVWordOffset) === data(j)(PAddrBits-1, DCacheVWordOffset) 136 } 137 } 138 139 // content addressed match 140 // cacheline aligned 141 for (i <- 0 until numCamPort) { 142 for (j <- 0 until numEntries) { 143 io.releaseViolationMmask(i)(j) := io.releaseViolationMdata(i)(PAddrBits-1, DCacheLineOffset) === data(j)(PAddrBits-1, DCacheLineOffset) 144 } 145 } 146 147 // content addressed match 148 // cacheline aligned 149 for (i <- 0 until numCamPort) { 150 for (j <- 0 until numEntries) { 151 io.releaseMmask(i)(j) := io.releaseMdata(i)(PAddrBits-1, DCacheLineOffset) === data(j)(PAddrBits-1, DCacheLineOffset) 152 } 153 } 154} 155 156// Load queue data module 157class LqVAddrModule[T <: UInt]( 158 gen: T, 159 numEntries: Int, 160 numRead: Int, 161 numWrite: Int, 162 numWBank: Int, 163 numWDelay: Int = 1, 164 numCamPort: Int = 1)(implicit p: Parameters) extends LqRawDataModule(gen, numEntries, numRead, numWrite, numWBank, numWDelay, numCamPort) 165 with HasDCacheParameters 166{ 167 // content addressed match 168 for (i <- 0 until numCamPort) { 169 for (j <- 0 until numEntries) { 170 io.violationMmask(i)(j) := io.violationMdata(i)(VAddrBits-1, DCacheVWordOffset) === data(j)(VAddrBits-1, DCacheVWordOffset) 171 } 172 } 173 174 // content addressed match 175 for (i <- 0 until numCamPort) { 176 for (j <- 0 until numEntries) { 177 io.releaseMmask(i)(j) := io.releaseMdata(i)(VAddrBits-1, DCacheLineOffset) === data(j)(VAddrBits-1, DCacheLineOffset) 178 } 179 } 180} 181 182// Load queue mask module 183class LqMaskModule[T <: UInt]( 184 gen: T, 185 numEntries: Int, 186 numRead: Int, 187 numWrite: Int, 188 numWBank: Int, 189 numWDelay: Int = 1, 190 numCamPort: Int = 1)(implicit p: Parameters) extends LqRawDataModule(gen, numEntries, numRead, numWrite, numWBank, numWDelay, numCamPort) 191 with HasDCacheParameters 192{ 193 // content addressed match 194 for (i <- 0 until numCamPort) { 195 for (j <- 0 until numEntries) { 196 io.violationMmask(i)(j) := (io.violationMdata(i) & data(j)).orR 197 } 198 } 199 // content addressed match 200 // cacheline aligned 201 for (i <- 0 until numCamPort) { 202 for (j <- 0 until numEntries) { 203 io.releaseViolationMmask(i)(j) := (io.releaseViolationMdata(i) & data(j)).orR 204 } 205 } 206 207 // content addressed match 208 for (i <- 0 until numCamPort) { 209 for (j <- 0 until numEntries) { 210 io.releaseMmask(i)(j) := (io.releaseMdata(i) & data(j)).orR 211 } 212 } 213} 214