xref: /XiangShan/src/main/scala/xiangshan/mem/lsqueue/StoreQueueData.scala (revision 1b7adedcea009da8b044339900598e3ad2e73203)
1package xiangshan.mem
2
3import chipsalliance.rocketchip.config.Parameters
4import chisel3._
5import chisel3.util._
6import utils._
7import xiangshan._
8import xiangshan.cache._
9import xiangshan.cache.{DCacheWordIO, DCacheLineIO, TlbRequestIO, MemoryOpConstants}
10import xiangshan.mem._
11import xiangshan.backend.roq.RoqPtr
12
13
14// Data module define
15// These data modules are like SyncDataModuleTemplate, but support cam-like ops
16class SQPaddrModule(numEntries: Int, numRead: Int, numWrite: Int, numForward: Int)(implicit p: Parameters) extends XSModule with HasDCacheParameters {
17  val io = IO(new Bundle {
18    val raddr = Input(Vec(numRead, UInt(log2Up(numEntries).W)))
19    val rdata = Output(Vec(numRead, UInt((PAddrBits).W)))
20    val wen   = Input(Vec(numWrite, Bool()))
21    val waddr = Input(Vec(numWrite, UInt(log2Up(numEntries).W)))
22    val wdata = Input(Vec(numWrite, UInt((PAddrBits).W)))
23    val forwardMdata = Input(Vec(numForward, UInt((PAddrBits).W)))
24    val forwardMmask = Output(Vec(numForward, Vec(numEntries, Bool())))
25  })
26
27  val data = Reg(Vec(numEntries, UInt((PAddrBits).W)))
28
29  // read ports
30  for (i <- 0 until numRead) {
31    io.rdata(i) := data(RegNext(io.raddr(i)))
32  }
33
34  // below is the write ports (with priorities)
35  for (i <- 0 until numWrite) {
36    when (io.wen(i)) {
37      data(io.waddr(i)) := io.wdata(i)
38    }
39  }
40
41  // content addressed match
42  for (i <- 0 until numForward) {
43    for (j <- 0 until numEntries) {
44      io.forwardMmask(i)(j) := io.forwardMdata(i)(PAddrBits-1, 3) === data(j)(PAddrBits-1, 3)
45    }
46  }
47
48  // DataModuleTemplate should not be used when there're any write conflicts
49  for (i <- 0 until numWrite) {
50    for (j <- i+1 until numWrite) {
51      assert(!(io.wen(i) && io.wen(j) && io.waddr(i) === io.waddr(j)))
52    }
53  }
54}
55
56class SQData8Entry(implicit p: Parameters) extends XSBundle {
57  // val paddr = UInt(PAddrBits.W)
58  val valid = Bool()
59  val data = UInt((XLEN/8).W)
60}
61
62class SQData8Module(size: Int, numRead: Int, numWrite: Int, numForward: Int)(implicit p: Parameters) extends XSModule with HasDCacheParameters with HasCircularQueuePtrHelper {
63  val io = IO(new Bundle() {
64    val raddr = Vec(numRead,  Input(UInt(log2Up(size).W)))
65    val rdata = Vec(numRead,  Output(new SQData8Entry))
66    val data = new Bundle() {
67      val wen   = Vec(numWrite, Input(Bool()))
68      val waddr = Vec(numWrite, Input(UInt(log2Up(size).W)))
69      val wdata = Vec(numWrite, Input(UInt((XLEN/8).W)))
70    }
71    val mask = new Bundle() {
72      val wen   = Vec(numWrite, Input(Bool()))
73      val waddr = Vec(numWrite, Input(UInt(log2Up(size).W)))
74      val wdata = Vec(numWrite, Input(Bool()))
75    }
76
77    val needForward = Input(Vec(numForward, Vec(2, UInt(size.W))))
78    val forwardValid = Vec(numForward, Output(Bool()))
79    val forwardData = Vec(numForward, Output(UInt(8.W)))
80  })
81
82  io := DontCare
83
84  val data = Reg(Vec(size, new SQData8Entry))
85
86  // writeback to sq
87  (0 until numWrite).map(i => {
88    when(io.data.wen(i)){
89      data(io.data.waddr(i)).data := io.data.wdata(i)
90    }
91  })
92  (0 until numWrite).map(i => {
93    when(io.mask.wen(i)){
94      data(io.mask.waddr(i)).valid := io.mask.wdata(i)
95    }
96  })
97
98  // destorequeue read data
99  (0 until numRead).map(i => {
100      io.rdata(i) := data(RegNext(io.raddr(i)))
101  })
102
103  // DataModuleTemplate should not be used when there're any write conflicts
104  for (i <- 0 until numWrite) {
105    for (j <- i+1 until numWrite) {
106      assert(!(io.data.wen(i) && io.data.wen(j) && io.data.waddr(i) === io.data.waddr(j)))
107    }
108  }
109  for (i <- 0 until numWrite) {
110    for (j <- i+1 until numWrite) {
111      assert(!(io.mask.wen(i) && io.mask.wen(j) && io.mask.waddr(i) === io.mask.waddr(j)))
112    }
113  }
114
115  // forwarding
116  // Compare ringBufferTail (deqPtr) and forward.sqIdx, we have two cases:
117  // (1) if they have the same flag, we need to check range(tail, sqIdx)
118  // (2) if they have different flags, we need to check range(tail, LoadQueueSize) and range(0, sqIdx)
119  // Forward1: Mux(same_flag, range(tail, sqIdx), range(tail, LoadQueueSize))
120  // Forward2: Mux(same_flag, 0.U,                   range(0, sqIdx)    )
121  // i.e. forward1 is the target entries with the same flag bits and forward2 otherwise
122
123  // entry with larger index should have higher priority since it's data is younger
124
125  (0 until numForward).map(i => {
126    // parallel fwd logic
127    val matchResultVec = Wire(Vec(size * 2, new FwdEntry))
128
129    def parallelFwd(xs: Seq[Data]): Data = {
130      ParallelOperation(xs, (a: Data, b: Data) => {
131        val l = a.asTypeOf(new FwdEntry)
132        val r = b.asTypeOf(new FwdEntry)
133        val res = Wire(new FwdEntry)
134        res.valid := l.valid || r.valid
135        res.data := Mux(r.valid, r.data, l.data)
136        res
137      })
138    }
139
140    // paddrMatch is now included in io.needForward
141    // for (j <- 0 until size) {
142    //   paddrMatch(j) := io.forward(i).paddr(PAddrBits - 1, 3) === data(j).paddr(PAddrBits - 1, 3)
143    // }
144
145    for (j <- 0 until size) {
146      val needCheck0 = RegNext(io.needForward(i)(0)(j))
147      val needCheck1 = RegNext(io.needForward(i)(1)(j))
148      (0 until XLEN / 8).foreach(k => {
149        matchResultVec(j).valid := needCheck0 && data(j).valid
150        matchResultVec(j).data := data(j).data
151        matchResultVec(size + j).valid := needCheck1 && data(j).valid
152        matchResultVec(size + j).data := data(j).data
153      })
154    }
155
156    val parallelFwdResult = parallelFwd(matchResultVec).asTypeOf(new FwdEntry)
157
158    io.forwardValid(i) := parallelFwdResult.valid
159    io.forwardData(i) := parallelFwdResult.data
160
161  })
162}
163
164class SQDataEntry(implicit p: Parameters) extends XSBundle {
165  // val paddr = UInt(PAddrBits.W)
166  val mask = UInt(8.W)
167  val data = UInt(XLEN.W)
168}
169
170class SQDataModule(size: Int, numRead: Int, numWrite: Int, numForward: Int)(implicit p: Parameters) extends XSModule with HasDCacheParameters with HasCircularQueuePtrHelper {
171  val io = IO(new Bundle() {
172    val raddr = Vec(numRead,  Input(UInt(log2Up(size).W)))
173    val rdata = Vec(numRead,  Output(new SQDataEntry))
174    val data = new Bundle() {
175      val wen   = Vec(numWrite, Input(Bool()))
176      val waddr = Vec(numWrite, Input(UInt(log2Up(size).W)))
177      val wdata = Vec(numWrite, Input(UInt(XLEN.W)))
178    }
179    val mask = new Bundle() {
180      val wen   = Vec(numWrite, Input(Bool()))
181      val waddr = Vec(numWrite, Input(UInt(log2Up(size).W)))
182      val wdata = Vec(numWrite, Input(UInt(8.W)))
183    }
184
185    val needForward = Input(Vec(numForward, Vec(2, UInt(size.W))))
186    val forwardMask = Vec(numForward, Output(Vec(8, Bool())))
187    val forwardData = Vec(numForward, Output(Vec(8, UInt(8.W))))
188  })
189
190  val data8 = Seq.fill(8)(Module(new SQData8Module(size, numRead, numWrite, numForward)))
191
192  // writeback to lq/sq
193  for (i <- 0 until numWrite) {
194    // write to data8
195    for (j <- 0 until 8) {
196      data8(j).io.mask.waddr(i) := io.mask.waddr(i)
197      data8(j).io.mask.wdata(i) := io.mask.wdata(i)(j)
198      data8(j).io.mask.wen(i)   := io.mask.wen(i)
199      data8(j).io.data.waddr(i) := io.data.waddr(i)
200      data8(j).io.data.wdata(i) := io.data.wdata(i)(8*(j+1)-1, 8*j)
201      data8(j).io.data.wen(i)   := io.data.wen(i)
202    }
203  }
204
205  // destorequeue read data
206  for (i <- 0 until numRead) {
207    for (j <- 0 until 8) {
208      data8(j).io.raddr(i) := io.raddr(i)
209    }
210    io.rdata(i).mask := VecInit((0 until 8).map(j => data8(j).io.rdata(i).valid)).asUInt
211    io.rdata(i).data := VecInit((0 until 8).map(j => data8(j).io.rdata(i).data)).asUInt
212  }
213
214  // DataModuleTemplate should not be used when there're any write conflicts
215  for (i <- 0 until numWrite) {
216    for (j <- i+1 until numWrite) {
217      assert(!(io.data.wen(i) && io.data.wen(j) && io.data.waddr(i) === io.data.waddr(j)))
218    }
219  }
220  for (i <- 0 until numWrite) {
221    for (j <- i+1 until numWrite) {
222      assert(!(io.mask.wen(i) && io.mask.wen(j) && io.mask.waddr(i) === io.mask.waddr(j)))
223    }
224  }
225
226  (0 until numForward).map(i => {
227    // parallel fwd logic
228    for (j <- 0 until 8) {
229      data8(j).io.needForward(i) <> io.needForward(i)
230      io.forwardMask(i) := VecInit((0 until 8).map(j => data8(j).io.forwardValid(i)))
231      io.forwardData(i) := VecInit((0 until 8).map(j => data8(j).io.forwardData(i)))
232    }
233  })
234}
235