xref: /XiangShan/src/main/scala/xiangshan/mem/lsqueue/LoadQueueData.scala (revision 3c808de005aba6d7539d33be9962c44375b97e6d)
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._
218891a219SYinan Xuimport org.chipsalliance.cde.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
32*3c808de0SAnzoabstract class LqRawDataModule[T <: Data] (
33*3c808de0SAnzo  gen: T,
34*3c808de0SAnzo  numEntries: Int,
35*3c808de0SAnzo  numRead: Int,
36*3c808de0SAnzo  numWrite: Int,
37*3c808de0SAnzo  numWBank: Int,
38*3c808de0SAnzo  numWDelay: Int,
39*3c808de0SAnzo  numCamPort: Int = 0,
40*3c808de0SAnzo  enableCacheLineCheck: Boolean = false
41*3c808de0SAnzo)(implicit p: Parameters) extends XSModule {
42e4f69d78Ssfencevma  val io = IO(new Bundle() {
438a610956Ssfencevma    val ren   = Input(Vec(numRead, Bool()))
44f02b5115SWilliam Wang    val raddr = Input(Vec(numRead, UInt(log2Up(numEntries).W)))
45e4f69d78Ssfencevma    val rdata = Output(Vec(numRead, gen))
46f02b5115SWilliam Wang    val wen   = Input(Vec(numWrite, Bool()))
47f02b5115SWilliam Wang    val waddr = Input(Vec(numWrite, UInt(log2Up(numEntries).W)))
48e4f69d78Ssfencevma    val wdata = Input(Vec(numWrite, gen))
49e4f69d78Ssfencevma    // violation cam: hit if addr is in the same cacheline
50e4f69d78Ssfencevma    val violationMdata = Input(Vec(numCamPort, gen)) // addr
51*3c808de0SAnzo    // This `store` writes the whole `cacheline`.(cbo zero).
52*3c808de0SAnzo    val violationCheckLine = OptionWrapper(enableCacheLineCheck, Input(Vec(numCamPort, Bool())))
53e4f69d78Ssfencevma    val violationMmask = Output(Vec(numCamPort, Vec(numEntries, Bool()))) // cam result mask
54e4f69d78Ssfencevma    // refill cam: hit if addr is in the same cacheline
55e4f69d78Ssfencevma    val releaseMdata = Input(Vec(numCamPort, gen))
56e4f69d78Ssfencevma    val releaseMmask = Output(Vec(numCamPort, Vec(numEntries, Bool())))  // cam result mask
57e4f69d78Ssfencevma    // release violation cam: hit if addr is in the same cacheline
58e4f69d78Ssfencevma    val releaseViolationMdata = Input(Vec(numCamPort, gen))
59e4f69d78Ssfencevma    val releaseViolationMmask = Output(Vec(numCamPort, Vec(numEntries, Bool()))) // cam result mask result
60bf6b6e21SWilliam Wang  })
61bf6b6e21SWilliam Wang
62e4f69d78Ssfencevma  require(isPow2(numWBank), "write bank must be a power of two!")
63e4f69d78Ssfencevma  require(numWBank >= 2, "write bank must be greater than or equal to two!")
64e4f69d78Ssfencevma  require(numWDelay >= 1, "write delay must be greater than or equal to one!")
65e4f69d78Ssfencevma  require(numCamPort >= 0, "camport must be greater than or equal to zero!")
66692e2fafSHuijin Li  require((numEntries % numWBank == 0), "numEntries must be divided by numWBank!")
670a47e4a1SWilliam Wang
68e4f69d78Ssfencevma  val numEntryPerBank = numEntries / numWBank
69*3c808de0SAnzo  val dataWidth = gen.getWidth
700a47e4a1SWilliam Wang
71e4f69d78Ssfencevma  val data = Reg(Vec(numEntries, gen))
72bf6b6e21SWilliam Wang  // read ports
73bf6b6e21SWilliam Wang  for (i <- 0 until numRead) {
748a610956Ssfencevma    io.rdata(i) := RegEnable(data(io.raddr(i)), io.ren(i))
75bf6b6e21SWilliam Wang  }
76bf6b6e21SWilliam Wang
770a47e4a1SWilliam Wang  // write ports
78e4f69d78Ssfencevma  val writeAddrDec = io.waddr.map(a => UIntToOH(a))
790a47e4a1SWilliam Wang  def selectBankMask(in: UInt, bank: Int): UInt = {
800a47e4a1SWilliam Wang    in((bank + 1) * numEntryPerBank - 1, bank * numEntryPerBank)
810a47e4a1SWilliam Wang  }
82e4f69d78Ssfencevma  for (bank <- 0 until numWBank) {
830a47e4a1SWilliam Wang    // write ports
840a47e4a1SWilliam Wang    // s0: write to bank level buffer
85e4f69d78Ssfencevma    val s0_bankWriteAddrDec = writeAddrDec.map(a => selectBankMask(a, bank))
86e4f69d78Ssfencevma    val s0_bankWriteEn = io.wen.zip(s0_bankWriteAddrDec).map(w => w._1 && w._2.orR)
87e4f69d78Ssfencevma    s0_bankWriteAddrDec.zipWithIndex.map(a =>
88e4f69d78Ssfencevma      a._1.suggestName("s0_bankWriteAddrDec" + bank + "_" + a._2)
890a47e4a1SWilliam Wang    )
90e4f69d78Ssfencevma    s0_bankWriteEn.zipWithIndex.map(a =>
91e4f69d78Ssfencevma      a._1.suggestName("s0_bankWriteEn" + bank + "_" + a._2)
920a47e4a1SWilliam Wang    )
93e4f69d78Ssfencevma    // sx: write data to entries
945003e6f8SHuijin Li    val sx_bankWriteAddrDec_resp = (0 until numWrite).map(w => DelayNWithValid(s0_bankWriteAddrDec(w), io.wen(w), numWDelay - 1))
955003e6f8SHuijin Li    val sx_bankWriteAddrDec = (0 until numWrite).map(w => sx_bankWriteAddrDec_resp(w)._2)
96e4f69d78Ssfencevma    val sx_bankWriteEn = s0_bankWriteEn.map(w => DelayN(w, numWDelay - 1))
975003e6f8SHuijin Li     val sx_writeData_resp = (0 until numWrite).map(w => DelayNWithValid(io.wdata(w), io.wen(w), numWDelay - 1))
985003e6f8SHuijin Li     val sx_writeData =  (0 until numWrite).map(w => sx_writeData_resp(w)._2)
995003e6f8SHuijin Li
100e4f69d78Ssfencevma    sx_bankWriteAddrDec.zipWithIndex.map(a =>
101e4f69d78Ssfencevma      a._1.suggestName("sx_bankWriteAddrDec" + bank + "_" + a._2)
1020a47e4a1SWilliam Wang    )
103e4f69d78Ssfencevma    sx_bankWriteEn.zipWithIndex.map(a =>
104e4f69d78Ssfencevma      a._1.suggestName("sx_bankWriteEn" + bank + "_" + a._2)
1050a47e4a1SWilliam Wang    )
106e4f69d78Ssfencevma    sx_writeData.zipWithIndex.map(a =>
107e4f69d78Ssfencevma      a._1.suggestName("sx_writeData" + bank + "_" + a._2)
1080a47e4a1SWilliam Wang    )
1090a47e4a1SWilliam Wang
1100a47e4a1SWilliam Wang    // entry write
1110a47e4a1SWilliam Wang    for (entry <- 0 until numEntryPerBank) {
1120a47e4a1SWilliam Wang      // write ports
113e4f69d78Ssfencevma      val sx_entryWriteEnVec = sx_bankWriteEn.zip(sx_bankWriteAddrDec).map(w => w._1 && w._2(entry))
114e4f69d78Ssfencevma      val sx_entryWriteEn = VecInit(sx_entryWriteEnVec).asUInt.orR
115e4f69d78Ssfencevma      val sx_entryWriteData = Mux1H(sx_entryWriteEnVec, sx_writeData)
116e4f69d78Ssfencevma      when (sx_entryWriteEn) {
117e4f69d78Ssfencevma        data(bank * numEntryPerBank + entry) := sx_entryWriteData
1180a47e4a1SWilliam Wang      }
119e4f69d78Ssfencevma      sx_entryWriteEnVec.zipWithIndex.map(a =>
120e4f69d78Ssfencevma        a._1.suggestName("sx_entryWriteEnVec" + bank + "_" + entry + "_" + a._2)
1210a47e4a1SWilliam Wang      )
122e4f69d78Ssfencevma      sx_entryWriteEn.suggestName("sx_entryWriteEn" + bank + "_" + entry)
123e4f69d78Ssfencevma      sx_entryWriteData.suggestName("sx_entryWriteData" + bank + "_" + entry)
124e4f69d78Ssfencevma    }
125e4f69d78Ssfencevma  }
126e4f69d78Ssfencevma
127e4f69d78Ssfencevma  // DataModuleTemplate should not be used when there're any write conflicts
128e4f69d78Ssfencevma  for (i <- 0 until numWrite) {
129e4f69d78Ssfencevma    for (j <- i+1 until numWrite) {
130e4f69d78Ssfencevma      assert(!(io.wen(i) && io.wen(j) && io.waddr(i) === io.waddr(j)))
131e4f69d78Ssfencevma    }
132e4f69d78Ssfencevma  }
133e4f69d78Ssfencevma}
134e4f69d78Ssfencevma
135e4f69d78Ssfencevma// Load queue physical address module
136e4f69d78Ssfencevmaclass LqPAddrModule[T <: UInt](
137e4f69d78Ssfencevma  gen: T,
138e4f69d78Ssfencevma  numEntries: Int,
139e4f69d78Ssfencevma  numRead: Int,
140e4f69d78Ssfencevma  numWrite: Int,
141e4f69d78Ssfencevma  numWBank: Int,
142e4f69d78Ssfencevma  numWDelay: Int = 1,
143*3c808de0SAnzo  numCamPort: Int = 1,
144*3c808de0SAnzo  enableCacheLineCheck: Boolean = false, // Check the entire cacheline. when enabled, set `paddrOffset` correctly.
145*3c808de0SAnzo  paddrOffset: Int // The least significant `paddrOffset` bits of paddr are neglected.
146*3c808de0SAnzo)(implicit p: Parameters) extends LqRawDataModule(gen, numEntries, numRead, numWrite, numWBank, numWDelay, numCamPort, enableCacheLineCheck)
147e4f69d78Ssfencevma  with HasDCacheParameters
148e4f69d78Ssfencevma{
149e4f69d78Ssfencevma  // content addressed match
150cdbff57cSHaoyuan Feng  // 128-bits aligned
151*3c808de0SAnzo  val needCacheLineCheck = enableCacheLineCheck && DCacheLineOffset > paddrOffset
152e4f69d78Ssfencevma  for (i <- 0 until numCamPort) {
153e4f69d78Ssfencevma    for (j <- 0 until numEntries) {
154*3c808de0SAnzo      if (needCacheLineCheck) {
155*3c808de0SAnzo        val cacheLineOffset = DCacheLineOffset - paddrOffset
156*3c808de0SAnzo        val cacheLineHit    = io.violationMdata(i)(dataWidth - 1, cacheLineOffset) === data(j)(dataWidth - 1, cacheLineOffset)
157*3c808de0SAnzo        val lowAddrHit      = io.violationMdata(i)(cacheLineOffset - 1, 0) === data(j)(cacheLineOffset - 1, 0)
158*3c808de0SAnzo        io.violationMmask(i)(j) := cacheLineHit && (io.violationCheckLine.get(i) || lowAddrHit)
159*3c808de0SAnzo      } else {
160549073a0Scz4e        io.violationMmask(i)(j) := io.violationMdata(i) === data(j)
161bf6b6e21SWilliam Wang      }
162*3c808de0SAnzo
163*3c808de0SAnzo    }
164bf6b6e21SWilliam Wang  }
165bf6b6e21SWilliam Wang
166bf6b6e21SWilliam Wang  // content addressed match
167e4f69d78Ssfencevma  // cacheline aligned
168e4f69d78Ssfencevma  for (i <- 0 until numCamPort) {
169bf6b6e21SWilliam Wang    for (j <- 0 until numEntries) {
170549073a0Scz4e      io.releaseViolationMmask(i)(j) := io.releaseViolationMdata(i) === data(j)
17167682d05SWilliam Wang    }
17267682d05SWilliam Wang  }
173e4f69d78Ssfencevma
174e4f69d78Ssfencevma  // content addressed match
175e4f69d78Ssfencevma  // cacheline aligned
176e4f69d78Ssfencevma  for (i <- 0 until numCamPort) {
17767682d05SWilliam Wang    for (j <- 0 until numEntries) {
178549073a0Scz4e      io.releaseMmask(i)(j) := io.releaseMdata(i) === data(j)
179bf6b6e21SWilliam Wang    }
180bf6b6e21SWilliam Wang  }
181bf6b6e21SWilliam Wang}
182bf6b6e21SWilliam Wang
183e4f69d78Ssfencevma// Load queue data module
184e4f69d78Ssfencevmaclass LqVAddrModule[T <: UInt](
185e4f69d78Ssfencevma  gen: T,
186e4f69d78Ssfencevma  numEntries: Int,
187e4f69d78Ssfencevma  numRead: Int,
188e4f69d78Ssfencevma  numWrite: Int,
189e4f69d78Ssfencevma  numWBank: Int,
190e4f69d78Ssfencevma  numWDelay: Int = 1,
191e4f69d78Ssfencevma  numCamPort: Int = 1)(implicit p: Parameters) extends LqRawDataModule(gen, numEntries, numRead, numWrite, numWBank, numWDelay, numCamPort)
192e4f69d78Ssfencevma  with HasDCacheParameters
193e4f69d78Ssfencevma{
194e4f69d78Ssfencevma  // content addressed match
195e4f69d78Ssfencevma  for (i <- 0 until numCamPort) {
1960a47e4a1SWilliam Wang    for (j <- 0 until numEntries) {
197cdbff57cSHaoyuan Feng      io.violationMmask(i)(j) := io.violationMdata(i)(VAddrBits-1, DCacheVWordOffset) === data(j)(VAddrBits-1, DCacheVWordOffset)
198bf6b6e21SWilliam Wang    }
199bf6b6e21SWilliam Wang  }
200bf6b6e21SWilliam Wang
201e4f69d78Ssfencevma  // content addressed match
202e4f69d78Ssfencevma  for (i <- 0 until numCamPort) {
203e4f69d78Ssfencevma    for (j <- 0 until numEntries) {
204cdbff57cSHaoyuan Feng      io.releaseMmask(i)(j) := io.releaseMdata(i)(VAddrBits-1, DCacheLineOffset) === data(j)(VAddrBits-1, DCacheLineOffset)
205e4f69d78Ssfencevma    }
206e4f69d78Ssfencevma  }
207e4f69d78Ssfencevma}
208e4f69d78Ssfencevma
209e4f69d78Ssfencevma// Load queue mask module
210e4f69d78Ssfencevmaclass LqMaskModule[T <: UInt](
211e4f69d78Ssfencevma  gen: T,
212e4f69d78Ssfencevma  numEntries: Int,
213e4f69d78Ssfencevma  numRead: Int,
214e4f69d78Ssfencevma  numWrite: Int,
215e4f69d78Ssfencevma  numWBank: Int,
216e4f69d78Ssfencevma  numWDelay: Int = 1,
217e4f69d78Ssfencevma  numCamPort: Int = 1)(implicit p: Parameters) extends LqRawDataModule(gen, numEntries, numRead, numWrite, numWBank, numWDelay, numCamPort)
218e4f69d78Ssfencevma  with HasDCacheParameters
219e4f69d78Ssfencevma{
220e4f69d78Ssfencevma  // content addressed match
221e4f69d78Ssfencevma  for (i <- 0 until numCamPort) {
222bf6b6e21SWilliam Wang    for (j <- 0 until numEntries) {
223f02b5115SWilliam Wang      io.violationMmask(i)(j) := (io.violationMdata(i) & data(j)).orR
224bf6b6e21SWilliam Wang    }
225bf6b6e21SWilliam Wang  }
226e4f69d78Ssfencevma  // content addressed match
227e4f69d78Ssfencevma  // cacheline aligned
228e4f69d78Ssfencevma  for (i <- 0 until numCamPort) {
229e4f69d78Ssfencevma    for (j <- 0 until numEntries) {
230e4f69d78Ssfencevma      io.releaseViolationMmask(i)(j) := (io.releaseViolationMdata(i) & data(j)).orR
231f02b5115SWilliam Wang    }
232f02b5115SWilliam Wang  }
233f02b5115SWilliam Wang
234e4f69d78Ssfencevma  // content addressed match
235e4f69d78Ssfencevma  for (i <- 0 until numCamPort) {
236e4f69d78Ssfencevma    for (j <- 0 until numEntries) {
237e4f69d78Ssfencevma      io.releaseMmask(i)(j) := (io.releaseMdata(i) & data(j)).orR
2381c2ecc42SWilliam Wang    }
2391c2ecc42SWilliam Wang  }
2407057673cSWilliam Wang}
241