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