xref: /XiangShan/src/main/scala/xiangshan/mem/lsqueue/LoadQueueData.scala (revision 2199a01c65d5a7bf503c4b40771336a50a6f1122)
1package xiangshan.mem
2
3import chisel3._
4import chisel3.util._
5import utils._
6import xiangshan._
7import xiangshan.cache._
8import xiangshan.cache.{DCacheWordIO, DCacheLineIO, TlbRequestIO, MemoryOpConstants}
9import xiangshan.backend.LSUOpType
10import xiangshan.mem._
11import xiangshan.backend.roq.RoqPtr
12
13class LQDataEntry extends XSBundle {
14  // val vaddr = UInt(VAddrBits.W)
15  val paddr = UInt(PAddrBits.W)
16  val mask = UInt(8.W)
17  val data = UInt(XLEN.W)
18  val fwdMask = Vec(8, Bool())
19}
20
21// Data module define
22// These data modules are like SyncDataModuleTemplate, but support cam-like ops
23class PaddrModule(numEntries: Int, numRead: Int, numWrite: Int) extends XSModule with HasDCacheParameters {
24  val io = IO(new Bundle {
25    val raddr = Input(Vec(numRead, UInt(log2Up(numEntries).W)))
26    val rdata = Output(Vec(numRead, UInt((PAddrBits).W)))
27    val wen   = Input(Vec(numWrite, Bool()))
28    val waddr = Input(Vec(numWrite, UInt(log2Up(numEntries).W)))
29    val wdata = Input(Vec(numWrite, UInt((PAddrBits).W)))
30    val violationMdata = Input(Vec(2, UInt((PAddrBits).W)))
31    val violationMmask = Output(Vec(2, Vec(numEntries, Bool())))
32    val refillMdata = Input(UInt((PAddrBits).W))
33    val refillMmask = Output(Vec(numEntries, Bool()))
34  })
35
36  val data = Reg(Vec(numEntries, UInt((PAddrBits).W)))
37
38  // read ports
39  for (i <- 0 until numRead) {
40    io.rdata(i) := data(RegNext(io.raddr(i)))
41  }
42
43  // below is the write ports (with priorities)
44  for (i <- 0 until numWrite) {
45    when (io.wen(i)) {
46      data(io.waddr(i)) := io.wdata(i)
47    }
48  }
49
50  // content addressed match
51  for (i <- 0 until 2) {
52    for (j <- 0 until numEntries) {
53      io.violationMmask(i)(j) := io.violationMdata(i)(PAddrBits-1, 3) === data(j)(PAddrBits-1, 3)
54    }
55  }
56
57  for (j <- 0 until numEntries) {
58    io.refillMmask(j) := get_block_addr(io.refillMdata) === get_block_addr(data(j))
59  }
60
61  // DataModuleTemplate should not be used when there're any write conflicts
62  for (i <- 0 until numWrite) {
63    for (j <- i+1 until numWrite) {
64      assert(!(io.wen(i) && io.wen(j) && io.waddr(i) === io.waddr(j)))
65    }
66  }
67}
68
69class MaskModule(numEntries: Int, numRead: Int, numWrite: Int) extends XSModule {
70  val io = IO(new Bundle {
71    val raddr = Input(Vec(numRead, UInt(log2Up(numEntries).W)))
72    val rdata = Output(Vec(numRead, UInt(8.W)))
73    val wen   = Input(Vec(numWrite, Bool()))
74    val waddr = Input(Vec(numWrite, UInt(log2Up(numEntries).W)))
75    val wdata = Input(Vec(numWrite, UInt(8.W)))
76    val violationMdata = Input(Vec(2, UInt((PAddrBits).W)))
77    val violationMmask = Output(Vec(2, Vec(numEntries, Bool())))
78  })
79
80  val data = Reg(Vec(numEntries, UInt(8.W)))
81
82  // read ports
83  for (i <- 0 until numRead) {
84    io.rdata(i) := data(RegNext(io.raddr(i)))
85  }
86
87  // below is the write ports (with priorities)
88  for (i <- 0 until numWrite) {
89    when (io.wen(i)) {
90      data(io.waddr(i)) := io.wdata(i)
91    }
92  }
93
94  // content addressed match
95  for (i <- 0 until 2) {
96    for (j <- 0 until numEntries) {
97      io.violationMmask(i)(j) := (io.violationMdata(i) & data(j)).orR
98    }
99  }
100
101  // DataModuleTemplate should not be used when there're any write conflicts
102  for (i <- 0 until numWrite) {
103    for (j <- i+1 until numWrite) {
104      assert(!(io.wen(i) && io.wen(j) && io.waddr(i) === io.waddr(j)))
105    }
106  }
107}
108
109class CoredataModule(numEntries: Int, numRead: Int, numWrite: Int) extends XSModule with HasDCacheParameters {
110  val io = IO(new Bundle {
111    // data io
112    // read
113    val raddr = Input(Vec(numRead, UInt(log2Up(numEntries).W)))
114    val rdata = Output(Vec(numRead, UInt(XLEN.W)))
115    // address indexed write
116    val wen   = Input(Vec(numWrite, Bool()))
117    val waddr = Input(Vec(numWrite, UInt(log2Up(numEntries).W)))
118    val wdata = Input(Vec(numWrite, UInt(XLEN.W)))
119    // masked write
120    val mwmask = Input(Vec(numEntries, Bool()))
121    val refillData = Input(UInt((cfg.blockBytes * 8).W))
122
123    // fwdMask io
124    val fwdMaskWdata = Input(Vec(numWrite, UInt(8.W)))
125    val fwdMaskWen = Input(Vec(numWrite, Bool()))
126    // fwdMaskWaddr = waddr
127
128    // paddr io
129    // 3 bits in paddr need to be stored in CoredataModule for refilling
130    val paddrWdata = Input(Vec(numWrite, UInt((PAddrBits).W)))
131    val paddrWen = Input(Vec(numWrite, Bool()))
132  })
133
134  val data = Reg(Vec(numEntries, UInt(XLEN.W)))
135  val fwdMask = Reg(Vec(numEntries, UInt(8.W)))
136  val wordIndex = Reg(Vec(numEntries, UInt((blockOffBits - wordOffBits).W)))
137
138  // read ports
139  for (i <- 0 until numRead) {
140    io.rdata(i) := data(RegNext(io.raddr(i)))
141  }
142
143  // below is the write ports (with priorities)
144  for (i <- 0 until numWrite) {
145    when (io.wen(i)) {
146      data(io.waddr(i)) := io.wdata(i)
147    }
148    when (io.fwdMaskWen(i)) {
149      fwdMask(io.waddr(i)) := io.fwdMaskWdata(i)
150    }
151    when (io.paddrWen(i)) {
152      wordIndex(io.waddr(i)) := get_word(io.paddrWdata(i))
153    }
154  }
155
156
157  // masked write
158  // refill missed load
159  def mergeRefillData(refill: UInt, fwd: UInt, fwdMask: UInt): UInt = {
160    val res = Wire(Vec(8, UInt(8.W)))
161    (0 until 8).foreach(i => {
162      res(i) := Mux(fwdMask(i), fwd(8 * (i + 1) - 1, 8 * i), refill(8 * (i + 1) - 1, 8 * i))
163    })
164    res.asUInt
165  }
166
167  // split dcache result into words
168  val words = VecInit((0 until blockWords) map { i => io.refillData(DataBits * (i + 1) - 1, DataBits * i)})
169
170  // refill data according to matchMask, refillMask and refill.vald
171  for (j <- 0 until numEntries) {
172    when (io.mwmask(j)) {
173      val refillData = words(wordIndex(j)) // TODO
174      data(j) := mergeRefillData(refillData, data(j), fwdMask(j))
175    }
176  }
177
178  // DataModuleTemplate should not be used when there're any write conflicts
179  for (i <- 0 until numWrite) {
180    for (j <- i+1 until numWrite) {
181      assert(!(io.wen(i) && io.wen(j) && io.waddr(i) === io.waddr(j)))
182    }
183  }
184}
185
186class LoadQueueData(size: Int, wbNumRead: Int, wbNumWrite: Int) extends XSModule with HasDCacheParameters with HasCircularQueuePtrHelper {
187  val io = IO(new Bundle() {
188    val wb = new Bundle() {
189      val wen = Vec(wbNumWrite, Input(Bool()))
190      val waddr = Input(Vec(wbNumWrite, UInt(log2Up(size).W)))
191      val wdata = Input(Vec(wbNumWrite, new LQDataEntry))
192      val raddr = Input(Vec(wbNumRead, UInt(log2Up(size).W)))
193      val rdata = Output(Vec(wbNumRead, new LQDataEntry))
194    }
195    val uncache = new Bundle() {
196      val wen = Input(Bool())
197      val waddr = Input(UInt(log2Up(size).W))
198      val wdata = Input(UInt(XLEN.W)) // only write back uncache data
199      val raddr = Input(UInt(log2Up(size).W))
200      val rdata = Output(new LQDataEntry)
201    }
202    val refill = new Bundle() {
203      val valid = Input(Bool())
204      val paddr = Input(UInt(PAddrBits.W))
205      val data = Input(UInt((cfg.blockBytes * 8).W))
206      val refillMask = Input(Vec(size, Bool()))
207      val matchMask = Output(Vec(size, Bool()))
208    }
209    val violation = Vec(StorePipelineWidth, new Bundle() {
210      val paddr = Input(UInt(PAddrBits.W))
211      val mask = Input(UInt(8.W))
212      val violationMask = Output(Vec(size, Bool()))
213    })
214    val debug = Output(Vec(size, new LQDataEntry))
215
216    def wbWrite(channel: Int, waddr: UInt, wdata: LQDataEntry): Unit = {
217      require(channel < wbNumWrite && wbNumWrite >= 0)
218      // need extra "this.wb(channel).wen := true.B"
219      this.wb.waddr(channel) := waddr
220      this.wb.wdata(channel) := wdata
221    }
222
223    def uncacheWrite(waddr: UInt, wdata: UInt): Unit = {
224      // need extra "this.uncache.wen := true.B"
225      this.uncache.waddr := waddr
226      this.uncache.wdata := wdata
227    }
228
229    // def refillWrite(ldIdx: Int): Unit = {
230    // }
231    // use "this.refill.wen(ldIdx) := true.B" instead
232  })
233
234  // val data = Reg(Vec(size, new LQDataEntry))
235  // data module
236  val paddrModule = Module(new PaddrModule(size, numRead = 3, numWrite = 2))
237  val maskModule = Module(new MaskModule(size, numRead = 3, numWrite = 2))
238  val coredataModule = Module(new CoredataModule(size, numRead = 3, numWrite = 3))
239
240  // read data
241  // read port 0 -> wbNumRead-1
242  (0 until wbNumRead).map(i => {
243    paddrModule.io.raddr(i) := io.wb.raddr(i)
244    maskModule.io.raddr(i) := io.wb.raddr(i)
245    coredataModule.io.raddr(i) := io.wb.raddr(i)
246
247    io.wb.rdata(i).paddr := paddrModule.io.rdata(i)
248    io.wb.rdata(i).mask := maskModule.io.rdata(i)
249    io.wb.rdata(i).data := coredataModule.io.rdata(i)
250    io.wb.rdata(i).fwdMask := DontCare
251  })
252
253  // read port wbNumRead
254  paddrModule.io.raddr(wbNumRead) := io.uncache.raddr
255  maskModule.io.raddr(wbNumRead) := io.uncache.raddr
256  coredataModule.io.raddr(wbNumRead) := io.uncache.raddr
257
258  io.uncache.rdata.paddr := paddrModule.io.rdata(wbNumRead)
259  io.uncache.rdata.mask := maskModule.io.rdata(wbNumRead)
260  io.uncache.rdata.data := coredataModule.io.rdata(wbNumRead)
261  io.uncache.rdata.fwdMask := DontCare
262
263  // write data
264  // write port 0 -> wbNumWrite-1
265  (0 until wbNumWrite).map(i => {
266    paddrModule.io.wen(i) := false.B
267    maskModule.io.wen(i) := false.B
268    coredataModule.io.wen(i) := false.B
269    coredataModule.io.fwdMaskWen(i) := false.B
270    coredataModule.io.paddrWen(i) := false.B
271
272    paddrModule.io.waddr(i) := io.wb.waddr(i)
273    maskModule.io.waddr(i) := io.wb.waddr(i)
274    coredataModule.io.waddr(i) := io.wb.waddr(i)
275
276    paddrModule.io.wdata(i) := io.wb.wdata(i).paddr
277    maskModule.io.wdata(i) := io.wb.wdata(i).mask
278    coredataModule.io.wdata(i) := io.wb.wdata(i).data
279    coredataModule.io.fwdMaskWdata(i) := io.wb.wdata(i).fwdMask.asUInt
280    coredataModule.io.paddrWdata(i) := io.wb.wdata(i).paddr
281
282    when(io.wb.wen(i)){
283      paddrModule.io.wen(i) := true.B
284      maskModule.io.wen(i) := true.B
285      coredataModule.io.wen(i) := true.B
286      coredataModule.io.fwdMaskWen(i) := true.B
287      coredataModule.io.paddrWen(i) := true.B
288    }
289  })
290
291  // write port wbNumWrite
292  // exceptionModule.io.wen(wbNumWrite) := false.B
293  coredataModule.io.wen(wbNumWrite) := io.uncache.wen
294  coredataModule.io.fwdMaskWen(wbNumWrite) := false.B
295  coredataModule.io.paddrWen(wbNumWrite) := false.B
296
297  coredataModule.io.waddr(wbNumWrite) := io.uncache.waddr
298
299  coredataModule.io.fwdMaskWdata(wbNumWrite) := DontCare
300  coredataModule.io.paddrWdata(wbNumWrite) := DontCare
301  coredataModule.io.wdata(wbNumWrite) := io.uncache.wdata
302
303  // mem access violation check, gen violationMask
304  (0 until StorePipelineWidth).map(i => {
305    paddrModule.io.violationMdata(i) := io.violation(i).paddr
306    maskModule.io.violationMdata(i) := io.violation(i).mask
307    io.violation(i).violationMask := (paddrModule.io.violationMmask(i).asUInt & maskModule.io.violationMmask(i).asUInt).asBools
308    // VecInit((0 until size).map(j => {
309      // val addrMatch = io.violation(i).paddr(PAddrBits - 1, 3) === data(j).paddr(PAddrBits - 1, 3)
310      // val violationVec = (0 until 8).map(k => data(j).mask(k) && io.violation(i).mask(k))
311      // Cat(violationVec).orR() && addrMatch
312    // }))
313  })
314
315  // refill missed load
316  def mergeRefillData(refill: UInt, fwd: UInt, fwdMask: UInt): UInt = {
317    val res = Wire(Vec(8, UInt(8.W)))
318    (0 until 8).foreach(i => {
319      res(i) := Mux(fwdMask(i), fwd(8 * (i + 1) - 1, 8 * i), refill(8 * (i + 1) - 1, 8 * i))
320    })
321    res.asUInt
322  }
323
324  // gen paddr match mask
325  paddrModule.io.refillMdata := io.refill.paddr
326  (0 until size).map(i => {
327    io.refill.matchMask := paddrModule.io.refillMmask
328    // io.refill.matchMask(i) := get_block_addr(data(i).paddr) === get_block_addr(io.refill.paddr)
329  })
330
331  // refill data according to matchMask, refillMask and refill.valid
332  coredataModule.io.refillData := io.refill.data
333  (0 until size).map(i => {
334    coredataModule.io.mwmask(i) := io.refill.valid && io.refill.matchMask(i) && io.refill.refillMask(i)
335  })
336
337  // debug data read
338  io.debug := DontCare
339}
340