xref: /XiangShan/src/main/scala/xiangshan/backend/issue/IssueQueue.scala (revision 054d37b64f79badfcbf058d4e0e69b573fa93adc)
1package xiangshan.backend.issue
2
3import chisel3.{util, _}
4import chisel3.util._
5import utils.{XSDebug, XSInfo}
6import xiangshan._
7import xiangshan.backend.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 = Reg(UInt(log2Up(qsize).W))
89  selectedIdxReg := selectedIdxWire - moveMask(selectedIdxWire)
90  selectedIdxRegOH := UIntToOH(selectedIdxReg)
91  XSDebug(
92    p"selMaskWire:${Binary(selectMask.asUInt())} selected:$selectedIdxWire moveMask:${Binary(moveMask)}\n"
93  )
94
95  // read data && (fake) deq
96  io.deq.valid := stateQueue(selectedIdxReg)===s_valid
97  io.deq.bits.uop := uopQueue(idxQueue(selectedIdxReg))
98  when(io.deq.fire()){
99    stateQueue(selectedIdxReg - moveMask(selectedIdxReg)) := s_wait
100    assert(stateQueue(selectedIdxReg) === s_valid, "Dequeue a invalid entry to lsu!")
101  }
102
103  assert(!(tailPtr===0.U && io.tlbHit), "Error: queue is empty but tlbHit is true!")
104
105  val tailAfterRealDeq = tailPtr - moveMask(tailPtr.tail(1))
106  val isFull = tailAfterRealDeq.head(1).asBool() // tailPtr===qsize.U
107
108  // enq
109  io.enq.ready := !isFull && !io.replay.valid && !io.redirect.valid
110  when(io.enq.fire()){
111    stateQueue(tailAfterRealDeq.tail(1)) := s_valid
112    uopQueue(idxQueue(tailPtr.tail(1))) := io.enq.bits
113  }
114
115  tailPtr := tailAfterRealDeq + io.enq.fire()
116
117  XSDebug(
118    realDeqValid,
119    p"firstWait:$firstWait firstBubble:$firstBubble realDeqIdx:$realDeqIdx\n"
120  )
121
122  XSDebug("State Dump: ")
123  stateQueue.reverse.foreach(s =>{
124    XSDebug(false, s===s_invalid, " -")
125    XSDebug(false, s===s_valid, " v")
126    XSDebug(false, s===s_wait, " w")
127    XSDebug(false, s===s_replay, " r")
128  })
129  XSDebug(false, true.B, "\n")
130
131  XSDebug("State Dump: ")
132  idxQueue.reverse.foreach(id =>{
133    XSDebug(false, true.B, p"$id")
134  })
135  XSDebug(false, true.B, "\n")
136
137  assert(!(io.replay.valid && realDeqValid), "Error: realDeqValid should be false when replay valid!")
138  for(i <- 0 until qsize){
139    val uopQIdx = idxQueue(i)
140    val cnt = cntQueue(uopQIdx)
141    val nextIdx = i.U - moveMask(i)
142    when(
143      (io.replay.valid && stateQueue(i)===s_wait) &&
144        uopQueue(uopQIdx).isAfter(io.replay.bits)
145    ){
146      // 'i' is enough because 'realDeqValid' must be false here
147      stateQueue(i) := s_replay
148      cnt := (replayDelay-1).U
149    }
150    when(stateQueue(i)===s_replay){
151      when(cnt === 0.U) {
152        stateQueue(nextIdx) := s_valid
153        if(i == 0) {
154          assert(!moveMask(0), "Error: Attemp to delete a 's_replay' entry!")
155        }
156      }.otherwise({
157        cnt := cnt - 1.U
158      })
159    }
160    when(uopQueue(uopQIdx).needFlush(io.redirect)){
161      stateQueue(nextIdx) := s_invalid
162    }
163  }
164
165
166  // Debug sigs
167  XSInfo(
168    io.enq.fire(),
169    p"enq fire: pc:${Hexadecimal(io.enq.bits.cf.pc)} roqIdx:${io.enq.bits.roqIdx}\n"
170  )
171  XSInfo(
172    io.deq.fire(),
173    p"deq fire: pc:${Hexadecimal(io.deq.bits.uop.cf.pc)} roqIdx:${io.deq.bits.uop.roqIdx}\n"
174  )
175  XSDebug(p"tailPtr:$tailPtr tailAfterDeq:$tailAfterRealDeq tlbHit:${io.tlbHit}\n")
176
177  XSDebug(false, true.B, "\n")
178}
179