xref: /XiangShan/src/main/scala/xiangshan/backend/issue/IssueQueue.scala (revision 74fe9f471900d59f6b846940e1f78ef4a5f147bb)
1package xiangshan.backend.issue
2
3import chisel3.{util, _}
4import chisel3.util._
5import utils.{XSDebug, XSInfo}
6import xiangshan._
7import xiangshan.backend.exu.{Exu, ExuConfig}
8import xiangshan.backend.regfile.RfReadPort
9
10class IssueQueue
11(
12  val exuCfg: ExuConfig,
13  val wakeupCnt: Int,
14  val bypassCnt: Int = 0
15) extends XSModule with HasIQConst with NeedImpl {
16  val io = IO(new Bundle() {
17    val redirect = Flipped(ValidIO(new Redirect))
18    val enq = Flipped(DecoupledIO(new MicroOp))
19    val readIntRf = Vec(exuCfg.intSrcCnt, Flipped(new RfReadPort))
20    val readFpRf = Vec(exuCfg.fpSrcCnt, Flipped(new RfReadPort))
21    val deq = DecoupledIO(new ExuInput)
22    val wakeUpPorts = Vec(wakeupCnt, Flipped(ValidIO(new ExuOutput)))
23    val bypassUops = Vec(bypassCnt, Flipped(ValidIO(new MicroOp)))
24    val numExist = Output(UInt(iqIdxWidth.W))
25    // tlb hit, inst can deq
26    val tlbHit = Input(Bool())
27    val replay = Flipped(ValidIO(UInt(RoqIdxWidth.W)))
28  })
29
30  def qsize: Int = IssQueSize
31  def idxWidth = log2Up(qsize)
32  def replayDelay = 16
33
34  require(isPow2(qsize))
35
36  /*
37      invalid --[enq]--> valid --[deq]--> wait --[tlbHit]--> invalid
38                                          wait --[replay]--> replay --[cnt]--> valid
39   */
40  val s_invalid :: s_valid :: s_wait :: s_replay :: Nil = Enum(4)
41
42  val idxQueue = RegInit(VecInit((0 until qsize).map(_.U(idxWidth.W))))
43  val stateQueue = RegInit(VecInit(Seq.fill(qsize)(s_invalid)))
44
45  val uopQueue = Reg(Vec(qsize, new MicroOp))
46  val cntQueue = Reg(Vec(qsize, UInt(log2Up(replayDelay).W)))
47
48  val tailPtr = RegInit(0.U((idxWidth+1).W))
49
50  // real deq
51
52  /*
53    example: realDeqIdx = 2       |  realDeqIdx=0
54             moveMask = 11111100  |  moveMask=11111111
55 */
56  assert(!(io.tlbHit && io.replay.valid), "Error: tlbHit and replay are both true!")
57
58  val firstWait = PriorityEncoder(stateQueue.map(_ === s_wait))
59  val firstBubble = PriorityEncoder(stateQueue.map(_ === s_invalid))
60  val realDeqIdx = Mux(io.tlbHit, firstWait, firstBubble)
61  val realDeqValid = io.tlbHit || ((firstBubble < tailPtr.tail(1)) && !io.replay.valid)
62  val moveMask = {
63    (Fill(qsize, 1.U(1.W)) << realDeqIdx)(qsize-1, 0)
64  } & Fill(qsize, realDeqValid)
65
66  for(i <- 1 until qsize){
67    when(moveMask(i)){
68      idxQueue(i-1) := idxQueue(i)
69      stateQueue(i-1) := stateQueue(i)
70    }
71  }
72  when(realDeqValid){
73    idxQueue.last := idxQueue(realDeqIdx)
74    stateQueue.last := s_invalid
75  }
76
77
78  // wake up
79
80  // select
81  val selectedIdxRegOH = Wire(UInt(qsize.W))
82  val selectMask = WireInit(VecInit(
83    (0 until qsize).map(i =>
84      stateQueue(i)===s_valid && !(selectedIdxRegOH(i) && io.deq.fire())
85    )
86  ))
87  val selectedIdxWire = PriorityEncoder(selectMask)
88  val selectedIdxReg = RegEnable(
89    enable = io.deq.ready,
90    next = selectedIdxWire - moveMask(selectedIdxWire)
91  )
92//  selectedIdxReg := selectedIdxWire - moveMask(selectedIdxWire)
93  selectedIdxRegOH := UIntToOH(selectedIdxReg)
94  XSDebug(
95    p"selMaskWire:${Binary(selectMask.asUInt())} selected:$selectedIdxWire moveMask:${Binary(moveMask)}\n"
96  )
97
98
99  // read regfile
100  val selectedUop = uopQueue(Mux(io.deq.ready, selectedIdxWire, selectedIdxReg))
101  val base, storeData = Wire(UInt(XLEN.W))
102
103  exuCfg match {
104    case Exu.ldExeUnitCfg =>
105      io.readIntRf(0).addr := selectedUop.psrc1 // base
106      base := io.readIntRf(0).data
107      storeData := DontCare
108    case Exu.stExeUnitCfg =>
109      io.readIntRf(0).addr := selectedUop.psrc1 // base
110      io.readIntRf(1).addr := selectedUop.psrc2 // store data (int)
111      io.readFpRf(0).addr := selectedUop.psrc2  // store data (fp)
112      base := io.readIntRf(0).data
113      storeData := Mux(SrcType.isReg(selectedUop.ctrl.src2Type),
114        io.readIntRf(1).data,
115        io.readFpRf(0).data
116      )
117    case _ =>
118      require(requirement = false, "Error: IssueQueue only support ldu and stu!")
119  }
120
121  // (fake) deq to Load/Store unit
122  io.deq.valid := stateQueue(selectedIdxReg)===s_valid
123  io.deq.bits.uop := uopQueue(idxQueue(selectedIdxReg))
124  io.deq.bits.src1 := base
125  io.deq.bits.src2 := storeData
126  io.deq.bits.src3 := DontCare
127
128  when(io.deq.fire()){
129    stateQueue(selectedIdxReg - moveMask(selectedIdxReg)) := s_wait
130    assert(stateQueue(selectedIdxReg) === s_valid, "Dequeue a invalid entry to lsu!")
131  }
132
133  assert(!(tailPtr===0.U && io.tlbHit), "Error: queue is empty but tlbHit is true!")
134
135  val tailAfterRealDeq = tailPtr - moveMask(tailPtr.tail(1))
136  val isFull = tailAfterRealDeq.head(1).asBool() // tailPtr===qsize.U
137
138  // enq
139  io.enq.ready := !isFull && !io.replay.valid && !io.redirect.valid
140  when(io.enq.fire()){
141    stateQueue(tailAfterRealDeq.tail(1)) := s_valid
142    uopQueue(idxQueue(tailPtr.tail(1))) := io.enq.bits
143  }
144
145  tailPtr := tailAfterRealDeq + io.enq.fire()
146
147  XSDebug(
148    realDeqValid,
149    p"firstWait:$firstWait firstBubble:$firstBubble realDeqIdx:$realDeqIdx\n"
150  )
151
152  XSDebug("State Dump: ")
153  stateQueue.reverse.foreach(s =>{
154    XSDebug(false, s===s_invalid, " -")
155    XSDebug(false, s===s_valid, " v")
156    XSDebug(false, s===s_wait, " w")
157    XSDebug(false, s===s_replay, " r")
158  })
159  XSDebug(false, true.B, "\n")
160
161  XSDebug("State Dump: ")
162  idxQueue.reverse.foreach(id =>{
163    XSDebug(false, true.B, p"$id")
164  })
165  XSDebug(false, true.B, "\n")
166
167  assert(!(io.replay.valid && realDeqValid), "Error: realDeqValid should be false when replay valid!")
168  for(i <- 0 until qsize){
169    val uopQIdx = idxQueue(i)
170    val cnt = cntQueue(uopQIdx)
171    val nextIdx = i.U - moveMask(i)
172    when(
173      (io.replay.valid && stateQueue(i)===s_wait) &&
174        uopQueue(uopQIdx).isAfter(io.replay.bits)
175    ){
176      // 'i' is enough because 'realDeqValid' must be false here
177      stateQueue(i) := s_replay
178      cnt := (replayDelay-1).U
179    }
180    when(stateQueue(i)===s_replay){
181      when(cnt === 0.U) {
182        stateQueue(nextIdx) := s_valid
183        if(i == 0) {
184          assert(!moveMask(0), "Error: Attemp to delete a 's_replay' entry!")
185        }
186      }.otherwise({
187        cnt := cnt - 1.U
188      })
189    }
190    when(uopQueue(uopQIdx).needFlush(io.redirect)){
191      stateQueue(nextIdx) := s_invalid
192    }
193  }
194
195
196  // assign outputs
197  io.numExist := Mux(isFull, (qsize-1).U, tailPtr)
198
199  // Debug sigs
200  XSInfo(
201    io.enq.fire(),
202    p"enq fire: pc:${Hexadecimal(io.enq.bits.cf.pc)} roqIdx:${io.enq.bits.roqIdx}\n"
203  )
204  XSInfo(
205    io.deq.fire(),
206    p"deq fire: pc:${Hexadecimal(io.deq.bits.uop.cf.pc)} roqIdx:${io.deq.bits.uop.roqIdx}\n"
207  )
208  XSDebug(p"tailPtr:$tailPtr tailAfterDeq:$tailAfterRealDeq tlbHit:${io.tlbHit}\n")
209
210  XSDebug(false, true.B, "\n")
211}
212