xref: /XiangShan/src/main/scala/xiangshan/mem/lsqueue/StoreQueueData.scala (revision e786ff3f795d4330ea986d008421797eff7d5349)
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
13
14class SQDataEntry extends XSBundle {
15//   val vaddr = UInt(VAddrBits.W) // TODO: need opt
16  val paddr = UInt(PAddrBits.W)
17  val mask = UInt(8.W)
18  val data = UInt(XLEN.W)
19//   val exception = UInt(16.W) // TODO: opt size
20}
21
22class StoreQueueData(size: Int, numRead: Int, numWrite: Int, numForward: Int) extends XSModule with HasDCacheParameters with HasCircularQueuePtrHelper {
23  val io = IO(new Bundle() {
24    val raddr = Vec(numRead,  Input(UInt(log2Up(size).W)))
25    val rdata = Vec(numRead,  Output(new SQDataEntry))
26    val wen   = Vec(numWrite, Input(Bool()))
27    val waddr = Vec(numWrite, Input(UInt(log2Up(size).W)))
28    val wdata = Vec(numWrite, Input(new SQDataEntry))
29    val debug = Vec(size, Output(new SQDataEntry))
30
31    val needForward = Input(Vec(numForward, Vec(2, UInt(size.W))))
32    val forward = Vec(numForward, Flipped(new LoadForwardQueryIO))
33
34    def forwardQuery(numForward: Int, paddr: UInt, needForward1: Data, needForward2: Data): Unit = {
35      this.needForward(numForward)(0) := needForward1
36      this.needForward(numForward)(1) := needForward2
37      this.forward(numForward).paddr := paddr
38    }
39  })
40
41  io := DontCare
42
43  val data = Reg(Vec(size, new SQDataEntry))
44
45  // writeback to lq/sq
46  (0 until numWrite).map(i => {
47    when(io.wen(i)){
48      data(io.waddr(i)) := io.wdata(i)
49    }
50  })
51
52  // destorequeue read data
53  (0 until numRead).map(i => {
54      io.rdata(i) := data(io.raddr(i))
55  })
56
57  // DataModuleTemplate should not be used when there're any write conflicts
58  for (i <- 0 until numWrite) {
59    for (j <- i+1 until numWrite) {
60      assert(!(io.wen(i) && io.wen(j) && io.waddr(i) === io.waddr(j)))
61    }
62  }
63
64  // forwarding
65  // Compare ringBufferTail (deqPtr) and forward.sqIdx, we have two cases:
66  // (1) if they have the same flag, we need to check range(tail, sqIdx)
67  // (2) if they have different flags, we need to check range(tail, LoadQueueSize) and range(0, sqIdx)
68  // Forward1: Mux(same_flag, range(tail, sqIdx), range(tail, LoadQueueSize))
69  // Forward2: Mux(same_flag, 0.U,                   range(0, sqIdx)    )
70  // i.e. forward1 is the target entries with the same flag bits and forward2 otherwise
71
72  // entry with larger index should have higher priority since it's data is younger
73
74  (0 until numForward).map(i => {
75    val forwardMask1 = WireInit(VecInit(Seq.fill(8)(false.B)))
76    val forwardData1 = WireInit(VecInit(Seq.fill(8)(0.U(8.W))))
77    val forwardMask2 = WireInit(VecInit(Seq.fill(8)(false.B)))
78    val forwardData2 = WireInit(VecInit(Seq.fill(8)(0.U(8.W))))
79
80    for (j <- 0 until size) {
81      val needCheck = io.forward(i).paddr(PAddrBits - 1, 3) === data(j).paddr(PAddrBits - 1, 3)
82      (0 until XLEN / 8).foreach(k => {
83        when (needCheck && data(j).mask(k)) {
84          when (io.needForward(i)(0)(j)) {
85            forwardMask1(k) := true.B
86            forwardData1(k) := data(j).data(8 * (k + 1) - 1, 8 * k)
87          }
88          when (io.needForward(i)(1)(j)) {
89            forwardMask2(k) := true.B
90            forwardData2(k) := data(j).data(8 * (k + 1) - 1, 8 * k)
91          }
92          XSDebug(io.needForward(i)(0)(j) || io.needForward(i)(1)(j),
93            p"forwarding $k-th byte ${Hexadecimal(data(j).data(8 * (k + 1) - 1, 8 * k))} " +
94            p"from ptr $j\n")
95        }
96      })
97    }
98
99    // parallel fwd logic
100    val paddrMatch = Wire(Vec(size, Bool()))
101    val matchResultVec = Wire(Vec(size * 2, new FwdEntry))
102
103    def parallelFwd(xs: Seq[Data]): Data = {
104      ParallelOperation(xs, (a: Data, b: Data) => {
105        val l = a.asTypeOf(new FwdEntry)
106        val r = b.asTypeOf(new FwdEntry)
107        val res = Wire(new FwdEntry)
108        (0 until 8).map(p => {
109          res.mask(p) := l.mask(p) || r.mask(p)
110          res.data(p) := Mux(r.mask(p), r.data(p), l.data(p))
111        })
112        res
113      })
114    }
115
116    for (j <- 0 until size) {
117      paddrMatch(j) := io.forward(i).paddr(PAddrBits - 1, 3) === data(j).paddr(PAddrBits - 1, 3)
118    }
119
120    for (j <- 0 until size) {
121      val needCheck0 = RegNext(paddrMatch(j) && io.needForward(i)(0)(j))
122      val needCheck1 = RegNext(paddrMatch(j) && io.needForward(i)(1)(j))
123      (0 until XLEN / 8).foreach(k => {
124        matchResultVec(j).mask(k) := needCheck0 && data(j).mask(k)
125        matchResultVec(j).data(k) := data(j).data(8 * (k + 1) - 1, 8 * k)
126        matchResultVec(size + j).mask(k) := needCheck1 && data(j).mask(k)
127        matchResultVec(size + j).data(k) := data(j).data(8 * (k + 1) - 1, 8 * k)
128      })
129    }
130
131    val parallelFwdResult = parallelFwd(matchResultVec).asTypeOf(new FwdEntry)
132
133    io.forward(i).forwardMask := parallelFwdResult.mask
134    io.forward(i).forwardData := parallelFwdResult.data
135
136  })
137
138  io.debug := data
139}