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