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