xref: /XiangShan/src/main/scala/xiangshan/mem/lsqueue/LoadQueueData.scala (revision e4f69d78f24895ac36a5a6c704cec53e4af72485)
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