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