1c6d43980SLemover/*************************************************************************************** 2c6d43980SLemover* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3f320e0f0SYinan Xu* Copyright (c) 2020-2021 Peng Cheng Laboratory 4c6d43980SLemover* 5c6d43980SLemover* XiangShan is licensed under Mulan PSL v2. 6c6d43980SLemover* You can use this software according to the terms and conditions of the Mulan PSL v2. 7c6d43980SLemover* You may obtain a copy of Mulan PSL v2 at: 8c6d43980SLemover* http://license.coscl.org.cn/MulanPSL2 9c6d43980SLemover* 10c6d43980SLemover* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11c6d43980SLemover* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12c6d43980SLemover* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13c6d43980SLemover* 14c6d43980SLemover* See the Mulan PSL v2 for more details. 15c6d43980SLemover***************************************************************************************/ 16c6d43980SLemover 177057673cSWilliam Wangpackage xiangshan.mem 187057673cSWilliam Wang 197057673cSWilliam Wangimport chisel3._ 207057673cSWilliam Wangimport chisel3.util._ 21e4f69d78Ssfencevmaimport chipsalliance.rocketchip.config.Parameters 227057673cSWilliam Wangimport xiangshan._ 237057673cSWilliam Wangimport xiangshan.cache._ 246d5ddbceSLemoverimport xiangshan.cache.{DCacheWordIO, DCacheLineIO, MemoryOpConstants} 257057673cSWilliam Wangimport xiangshan.mem._ 269aca92b9SYinan Xuimport xiangshan.backend.rob.RobPtr 27e4f69d78Ssfencevmaimport utils._ 28e4f69d78Ssfencevmaimport utility._ 290a47e4a1SWilliam Wang 30bf6b6e21SWilliam Wang// Data module define 31e4f69d78Ssfencevma// These raw data modules are like SyncDataModuleTemplate, but support cam-like ops 32e4f69d78Ssfencevmaabstract class LqRawDataModule[T <: Data] (gen: T, numEntries: Int, numRead: Int, numWrite: Int, numWBank: Int, numWDelay: Int, numCamPort: Int = 0)(implicit p: Parameters) extends XSModule { 33e4f69d78Ssfencevma val io = IO(new Bundle() { 34*8a610956Ssfencevma val ren = Input(Vec(numRead, Bool())) 35f02b5115SWilliam Wang val raddr = Input(Vec(numRead, UInt(log2Up(numEntries).W))) 36e4f69d78Ssfencevma val rdata = Output(Vec(numRead, gen)) 37f02b5115SWilliam Wang val wen = Input(Vec(numWrite, Bool())) 38f02b5115SWilliam Wang val waddr = Input(Vec(numWrite, UInt(log2Up(numEntries).W))) 39e4f69d78Ssfencevma val wdata = Input(Vec(numWrite, gen)) 40e4f69d78Ssfencevma // violation cam: hit if addr is in the same cacheline 41e4f69d78Ssfencevma val violationMdata = Input(Vec(numCamPort, gen)) // addr 42e4f69d78Ssfencevma val violationMmask = Output(Vec(numCamPort, Vec(numEntries, Bool()))) // cam result mask 43e4f69d78Ssfencevma // refill cam: hit if addr is in the same cacheline 44e4f69d78Ssfencevma val releaseMdata = Input(Vec(numCamPort, gen)) 45e4f69d78Ssfencevma val releaseMmask = Output(Vec(numCamPort, Vec(numEntries, Bool()))) // cam result mask 46e4f69d78Ssfencevma // release violation cam: hit if addr is in the same cacheline 47e4f69d78Ssfencevma val releaseViolationMdata = Input(Vec(numCamPort, gen)) 48e4f69d78Ssfencevma val releaseViolationMmask = Output(Vec(numCamPort, Vec(numEntries, Bool()))) // cam result mask result 49bf6b6e21SWilliam Wang }) 50bf6b6e21SWilliam Wang 51e4f69d78Ssfencevma require(isPow2(numWBank), "write bank must be a power of two!") 52e4f69d78Ssfencevma require(numWBank >= 2, "write bank must be greater than or equal to two!") 53e4f69d78Ssfencevma require(numWDelay >= 1, "write delay must be greater than or equal to one!") 54e4f69d78Ssfencevma require(numCamPort >= 0, "camport must be greater than or equal to zero!") 550a47e4a1SWilliam Wang 56e4f69d78Ssfencevma val numEntryPerBank = numEntries / numWBank 570a47e4a1SWilliam Wang 58e4f69d78Ssfencevma val data = Reg(Vec(numEntries, gen)) 59bf6b6e21SWilliam Wang // read ports 60bf6b6e21SWilliam Wang for (i <- 0 until numRead) { 61*8a610956Ssfencevma io.rdata(i) := RegEnable(data(io.raddr(i)), io.ren(i)) 62bf6b6e21SWilliam Wang } 63bf6b6e21SWilliam Wang 640a47e4a1SWilliam Wang // write ports 65e4f69d78Ssfencevma val writeAddrDec = io.waddr.map(a => UIntToOH(a)) 660a47e4a1SWilliam Wang def selectBankMask(in: UInt, bank: Int): UInt = { 670a47e4a1SWilliam Wang in((bank + 1) * numEntryPerBank - 1, bank * numEntryPerBank) 680a47e4a1SWilliam Wang } 69e4f69d78Ssfencevma for (bank <- 0 until numWBank) { 700a47e4a1SWilliam Wang // write ports 710a47e4a1SWilliam Wang // s0: write to bank level buffer 72e4f69d78Ssfencevma val s0_bankWriteAddrDec = writeAddrDec.map(a => selectBankMask(a, bank)) 73e4f69d78Ssfencevma val s0_bankWriteEn = io.wen.zip(s0_bankWriteAddrDec).map(w => w._1 && w._2.orR) 74e4f69d78Ssfencevma s0_bankWriteAddrDec.zipWithIndex.map(a => 75e4f69d78Ssfencevma a._1.suggestName("s0_bankWriteAddrDec" + bank + "_" + a._2) 760a47e4a1SWilliam Wang ) 77e4f69d78Ssfencevma s0_bankWriteEn.zipWithIndex.map(a => 78e4f69d78Ssfencevma a._1.suggestName("s0_bankWriteEn" + bank + "_" + a._2) 790a47e4a1SWilliam Wang ) 80e4f69d78Ssfencevma // sx: write data to entries 81e4f69d78Ssfencevma val sx_bankWriteAddrDec = s0_bankWriteAddrDec.map(w => DelayN(w, numWDelay - 1)) 82e4f69d78Ssfencevma val sx_bankWriteEn = s0_bankWriteEn.map(w => DelayN(w, numWDelay - 1)) 83e4f69d78Ssfencevma val sx_writeData = io.wdata.map(w => DelayN(w, numWDelay - 1)) 84e4f69d78Ssfencevma sx_bankWriteAddrDec.zipWithIndex.map(a => 85e4f69d78Ssfencevma a._1.suggestName("sx_bankWriteAddrDec" + bank + "_" + a._2) 860a47e4a1SWilliam Wang ) 87e4f69d78Ssfencevma sx_bankWriteEn.zipWithIndex.map(a => 88e4f69d78Ssfencevma a._1.suggestName("sx_bankWriteEn" + bank + "_" + a._2) 890a47e4a1SWilliam Wang ) 90e4f69d78Ssfencevma sx_writeData.zipWithIndex.map(a => 91e4f69d78Ssfencevma a._1.suggestName("sx_writeData" + bank + "_" + a._2) 920a47e4a1SWilliam Wang ) 930a47e4a1SWilliam Wang 940a47e4a1SWilliam Wang // entry write 950a47e4a1SWilliam Wang for (entry <- 0 until numEntryPerBank) { 960a47e4a1SWilliam Wang // write ports 97e4f69d78Ssfencevma val sx_entryWriteEnVec = sx_bankWriteEn.zip(sx_bankWriteAddrDec).map(w => w._1 && w._2(entry)) 98e4f69d78Ssfencevma val sx_entryWriteEn = VecInit(sx_entryWriteEnVec).asUInt.orR 99e4f69d78Ssfencevma val sx_entryWriteData = Mux1H(sx_entryWriteEnVec, sx_writeData) 100e4f69d78Ssfencevma when (sx_entryWriteEn) { 101e4f69d78Ssfencevma data(bank * numEntryPerBank + entry) := sx_entryWriteData 1020a47e4a1SWilliam Wang } 103e4f69d78Ssfencevma sx_entryWriteEnVec.zipWithIndex.map(a => 104e4f69d78Ssfencevma a._1.suggestName("sx_entryWriteEnVec" + bank + "_" + entry + "_" + a._2) 1050a47e4a1SWilliam Wang ) 106e4f69d78Ssfencevma sx_entryWriteEn.suggestName("sx_entryWriteEn" + bank + "_" + entry) 107e4f69d78Ssfencevma sx_entryWriteData.suggestName("sx_entryWriteData" + bank + "_" + entry) 108e4f69d78Ssfencevma } 109e4f69d78Ssfencevma } 110e4f69d78Ssfencevma 111e4f69d78Ssfencevma // DataModuleTemplate should not be used when there're any write conflicts 112e4f69d78Ssfencevma for (i <- 0 until numWrite) { 113e4f69d78Ssfencevma for (j <- i+1 until numWrite) { 114e4f69d78Ssfencevma assert(!(io.wen(i) && io.wen(j) && io.waddr(i) === io.waddr(j))) 115e4f69d78Ssfencevma } 116e4f69d78Ssfencevma } 117e4f69d78Ssfencevma} 118e4f69d78Ssfencevma 119e4f69d78Ssfencevma// Load queue physical address module 120e4f69d78Ssfencevmaclass LqPAddrModule[T <: UInt]( 121e4f69d78Ssfencevma gen: T, 122e4f69d78Ssfencevma numEntries: Int, 123e4f69d78Ssfencevma numRead: Int, 124e4f69d78Ssfencevma numWrite: Int, 125e4f69d78Ssfencevma numWBank: Int, 126e4f69d78Ssfencevma numWDelay: Int = 1, 127e4f69d78Ssfencevma numCamPort: Int = 1)(implicit p: Parameters) extends LqRawDataModule(gen, numEntries, numRead, numWrite, numWBank, numWDelay, numCamPort) 128e4f69d78Ssfencevma with HasDCacheParameters 129e4f69d78Ssfencevma{ 130e4f69d78Ssfencevma // content addressed match 131e4f69d78Ssfencevma // word aligned 132e4f69d78Ssfencevma for (i <- 0 until numCamPort) { 133e4f69d78Ssfencevma for (j <- 0 until numEntries) { 134e4f69d78Ssfencevma io.violationMmask(i)(j) := io.violationMdata(i)(PAddrBits-1, 3) === data(j)(PAddrBits-1, 3) 135bf6b6e21SWilliam Wang } 136bf6b6e21SWilliam Wang } 137bf6b6e21SWilliam Wang 138bf6b6e21SWilliam Wang // content addressed match 139e4f69d78Ssfencevma // cacheline aligned 140e4f69d78Ssfencevma for (i <- 0 until numCamPort) { 141bf6b6e21SWilliam Wang for (j <- 0 until numEntries) { 142e4f69d78Ssfencevma io.releaseViolationMmask(i)(j) := io.releaseViolationMdata(i)(PAddrBits-1, DCacheLineOffset) === data(j)(PAddrBits-1, DCacheLineOffset) 14367682d05SWilliam Wang } 14467682d05SWilliam Wang } 145e4f69d78Ssfencevma 146e4f69d78Ssfencevma // content addressed match 147e4f69d78Ssfencevma // cacheline aligned 148e4f69d78Ssfencevma for (i <- 0 until numCamPort) { 14967682d05SWilliam Wang for (j <- 0 until numEntries) { 150ef3b5b96SWilliam Wang io.releaseMmask(i)(j) := io.releaseMdata(i)(PAddrBits-1, DCacheLineOffset) === data(j)(PAddrBits-1, DCacheLineOffset) 151bf6b6e21SWilliam Wang } 152bf6b6e21SWilliam Wang } 153bf6b6e21SWilliam Wang} 154bf6b6e21SWilliam Wang 155e4f69d78Ssfencevma// Load queue data module 156e4f69d78Ssfencevmaclass LqVAddrModule[T <: UInt]( 157e4f69d78Ssfencevma gen: T, 158e4f69d78Ssfencevma numEntries: Int, 159e4f69d78Ssfencevma numRead: Int, 160e4f69d78Ssfencevma numWrite: Int, 161e4f69d78Ssfencevma numWBank: Int, 162e4f69d78Ssfencevma numWDelay: Int = 1, 163e4f69d78Ssfencevma numCamPort: Int = 1)(implicit p: Parameters) extends LqRawDataModule(gen, numEntries, numRead, numWrite, numWBank, numWDelay, numCamPort) 164e4f69d78Ssfencevma with HasDCacheParameters 165e4f69d78Ssfencevma{ 166e4f69d78Ssfencevma // content addressed match 167e4f69d78Ssfencevma for (i <- 0 until numCamPort) { 1680a47e4a1SWilliam Wang for (j <- 0 until numEntries) { 169e4f69d78Ssfencevma io.violationMmask(i)(j) := io.violationMdata(i)(VAddrBits-1, 3) === data(j)(VAddrBits-1, 3) 170bf6b6e21SWilliam Wang } 171bf6b6e21SWilliam Wang } 172bf6b6e21SWilliam Wang 173e4f69d78Ssfencevma // content addressed match 174e4f69d78Ssfencevma for (i <- 0 until numCamPort) { 175e4f69d78Ssfencevma for (j <- 0 until numEntries) { 176e4f69d78Ssfencevma io.releaseMmask(i)(j) := io.releaseMdata(i)(VAddrBits-1, 0) === data(j)(VAddrBits-1, 0) 177e4f69d78Ssfencevma } 178e4f69d78Ssfencevma } 179e4f69d78Ssfencevma} 180e4f69d78Ssfencevma 181e4f69d78Ssfencevma// Load queue mask module 182e4f69d78Ssfencevmaclass LqMaskModule[T <: UInt]( 183e4f69d78Ssfencevma gen: T, 184e4f69d78Ssfencevma numEntries: Int, 185e4f69d78Ssfencevma numRead: Int, 186e4f69d78Ssfencevma numWrite: Int, 187e4f69d78Ssfencevma numWBank: Int, 188e4f69d78Ssfencevma numWDelay: Int = 1, 189e4f69d78Ssfencevma numCamPort: Int = 1)(implicit p: Parameters) extends LqRawDataModule(gen, numEntries, numRead, numWrite, numWBank, numWDelay, numCamPort) 190e4f69d78Ssfencevma with HasDCacheParameters 191e4f69d78Ssfencevma{ 192e4f69d78Ssfencevma // content addressed match 193e4f69d78Ssfencevma for (i <- 0 until numCamPort) { 194bf6b6e21SWilliam Wang for (j <- 0 until numEntries) { 195f02b5115SWilliam Wang io.violationMmask(i)(j) := (io.violationMdata(i) & data(j)).orR 196bf6b6e21SWilliam Wang } 197bf6b6e21SWilliam Wang } 198e4f69d78Ssfencevma // content addressed match 199e4f69d78Ssfencevma // cacheline aligned 200e4f69d78Ssfencevma for (i <- 0 until numCamPort) { 201e4f69d78Ssfencevma for (j <- 0 until numEntries) { 202e4f69d78Ssfencevma io.releaseViolationMmask(i)(j) := (io.releaseViolationMdata(i) & data(j)).orR 203f02b5115SWilliam Wang } 204f02b5115SWilliam Wang } 205f02b5115SWilliam Wang 206e4f69d78Ssfencevma // content addressed match 207e4f69d78Ssfencevma for (i <- 0 until numCamPort) { 208e4f69d78Ssfencevma for (j <- 0 until numEntries) { 209e4f69d78Ssfencevma io.releaseMmask(i)(j) := (io.releaseMdata(i) & data(j)).orR 2101c2ecc42SWilliam Wang } 2111c2ecc42SWilliam Wang } 2127057673cSWilliam Wang} 213