ReservationStationNew.scala 22.3 KB
Newer Older
1 2 3 4 5
package xiangshan.backend.issue

import chisel3._
import chisel3.util._
import xiangshan._
6
import utils._
L
LinJiawei 已提交
7 8
import xiangshan.backend.SelImm
import xiangshan.backend.decode.{ImmUnion, Imm_U}
9
import xiangshan.backend.exu.{Exu, ExuConfig}
10
import xiangshan.backend.regfile.RfReadPort
L
LinJiawei 已提交
11

12
import scala.math.max
13

14 15 16 17
class BypassQueue(number: Int) extends XSModule {
  val io = IO(new Bundle {
    val in  = Flipped(ValidIO(new MicroOp))
    val out = ValidIO(new MicroOp)
18
    val redirect = Flipped(ValidIO(new Redirect))
19
  })
20 21 22 23
  if (number < 0) {
    io.out.valid := false.B
    io.out.bits := DontCare
  } else if(number == 0) {
24
    io.in <> io.out
25
    io.out.valid := io.in.valid
26
  } else {
27
    val queue = Seq.fill(number)(RegInit(0.U.asTypeOf(new Bundle{
28 29 30 31 32
      val valid = Bool()
      val bits = new MicroOp
    })))
    queue(0).valid := io.in.valid
    queue(0).bits  := io.in.bits
33
    (0 until (number-1)).map{i =>
34 35 36
      queue(i+1) := queue(i)
      queue(i+1).valid := queue(i).valid && !queue(i).bits.roqIdx.needFlush(io.redirect)
    }
37
    io.out.valid := queue(number-1).valid
38
    io.out.bits := queue(number-1).bits
39
    for (i <- 0 until number) {
40
      XSDebug(queue(i).valid, p"BPQue(${i.U}): pc:${Hexadecimal(queue(i).bits.cf.pc)} roqIdx:${queue(i).bits.roqIdx}" +
41
        p" pdest:${queue(i).bits.pdest} rfWen:${queue(i).bits.ctrl.rfWen} fpWen${queue(i).bits.ctrl.fpWen}\n")
42
    }
Z
ZhangZifei 已提交
43 44
  }
}
45

46
class RSCtrlDataIO(srcNum: Int) extends XSBundle {
47 48 49 50 51 52
  // TODO: current: Ctrl to Data, next: Data to Ctrl
  val enqPtr = Output(UInt(log2Up(IssQueSize).W))
  val deqPtr = ValidIO(UInt(log2Up(IssQueSize).W)) // one cycle earlier
  val enqCtrl = ValidIO(new MicroOp)

  val fuReady   = Input(Bool())
53
  val srcUpdate = Input(Vec(IssQueSize+1, Vec(srcNum, Bool()))) // Note: the last one for enq
54 55
  val redVec    = Input(UInt(IssQueSize.W))
  val feedback  = Input(Vec(IssQueSize+1, Bool())) // Note: the last one for hit
56 57

  override def cloneType: RSCtrlDataIO.this.type = new RSCtrlDataIO(srcNum).asInstanceOf[this.type]
58 59
}

60
class ReservationStationCtrl
61 62 63
(
  val exuCfg: ExuConfig,
  wakeupCnt: Int,
64
  extraListenPortsCnt: Int,
65
  feedback: Boolean,
66
  fixedDelay: Int,
67
  replayDelay: Int = 10
Z
ZhangZifei 已提交
68
) extends XSModule with HasCircularQueuePtrHelper {
69 70 71

  val iqSize = IssQueSize
  val iqIdxWidth = log2Up(iqSize)
72
  val fastWakeup = fixedDelay >= 0 // NOTE: if do not enable fastWakeup(bypass), set fixedDelay to -1
73
  val nonBlocked = fastWakeup
74
  val srcNum = max(exuCfg.intSrcCnt, exuCfg.fpSrcCnt)
75 76
  require(srcNum >= 1 && srcNum <= 3)
  println(s"[RsCtrl]  ExuConfig: ${exuCfg.name} (srcNum = $srcNum)")
77 78

  val io = IO(new XSBundle {
79
    // flush
80 81
    val redirect = Flipped(ValidIO(new Redirect))

82
    // enq Ctrl sigs at dispatch-2, only use srcState
83 84
    val enqCtrl = Flipped(DecoupledIO(new MicroOp))

85
    // to DataPart
86
    val data = new RSCtrlDataIO(srcNum)
87 88 89 90 91

    // to Dispatch
    val numExist = Output(UInt(iqIdxWidth.W))
  })

92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
  /* there two kind of data
   * 0 : indexed by indexed queue, such as data queue
   * 1 : indexed like indexed queue
   * TODO : all the queue turn to 0 type except indexed queue
   */

  /* queue in ctrl part
   * index queue : index
   * state queue : use for replay
   * valid queue : from state queue, valid or not
   * empty queue : from state queue, empty or not(not valid and not replay)
   * src   queue : record rdy or not
   * cnt   queue : record replay cycle
   */

107

108 109 110 111 112 113 114 115 116
  val s_idle :: s_valid :: s_selected :: s_bubble :: s_wait :: s_replay :: Nil = Enum(6)
  /* state machine
   * s_idle     : empty slot, init state, set when deq
   * s_valid    : ready to be secleted
   * s_selected : the not bubble that selected
   * s_bubble   : the bubble that selected
   * s_wait     : wait for feedback
   * s_replay   : replay after some particular cycle
   */
117
  val stateQueue    = RegInit(VecInit(Seq.fill(iqSize)(s_idle)))
118 119
  val validQueue    = VecInit(stateQueue.map(_ === s_valid))
  val emptyQueue    = VecInit(stateQueue.map(_ === s_idle))
120
  val srcQueue      = Reg(Vec(iqSize, Vec(srcNum, Bool())))
121
  val cntQueue      = Reg(Vec(iqSize, UInt(log2Up(replayDelay).W)))
Z
ZhangZifei 已提交
122 123

  // rs queue part:
Z
ZhangZifei 已提交
124 125
  // val tailPtr       = RegInit(0.U((iqIdxWidth+1).W))
  val tailPtr       = RegInit(0.U.asTypeOf(new CircularQueuePtr(iqSize)))
126
  val idxQueue      = RegInit(VecInit((0 until iqSize).map(_.U(iqIdxWidth.W))))
127 128 129 130 131 132 133 134 135

  // turn to indexed index
  def widthMap[T <: Data](f: Int => T) = VecInit((0 until iqSize).map(f))
  val stateIdxQue = widthMap(i => stateQueue(idxQueue(i))) // NOTE: only use for debug, remove it later
  val validIdxQue = widthMap(i => validQueue(idxQueue(i)))
  val emptyIdxQue = widthMap(i => emptyQueue(idxQueue(i)))
  val srcIdxQue   = widthMap(i => srcQueue(idxQueue(i)))
  val cntIdxQue   = widthMap(i => cntQueue(idxQueue(i))) // NOTE: only use for debug, remove it later
  val readyIdxQue = VecInit(srcIdxQue.zip(validIdxQue).map{ case (a,b) => Cat(a).andR & b })
136

137
  // redirect
Z
ZhangZifei 已提交
138 139
  val redVec      = io.data.redVec
  val redVecPtr   = widthMap(i => io.data.redVec(idxQueue(i)))
140
  val fbMatchVec = Wire(UInt(iqSize.W))
141
  if (feedback) {
142 143 144
    fbMatchVec := widthMap(i => io.data.feedback(i) && (stateQueue(i) === s_wait || stateQueue(i)===s_valid)).asUInt
  } else {
    fbMatchVec := 0.U
145
  }
146
  val fbHit       = io.data.feedback(IssQueSize)
147

Z
ZhangZifei 已提交
148
  // select ready
Z
ZhangZifei 已提交
149 150
  // for no replay, select just equal to deq (attached)
  // with   replay, select is just two stage with deq.
151
  val issFire = Wire(Bool())
Z
ZhangZifei 已提交
152
  val moveMask = WireInit(0.U(iqSize.W))
153
  val selectMask = WireInit(VecInit((0 until iqSize).map(i => readyIdxQue(i))))
Z
ZhangZifei 已提交
154 155 156
  // val selIdx = ParallelMux(selectMask zip idxQueue) // NOTE: the idx in the idxQueue
  val (selPtr, haveReady) = PriorityEncoderWithFlag(selectMask) // NOTE: the idx of idxQueue
  val selIdx = idxQueue(selPtr)
157
  val selIdxReg = RegNext(selIdx) // NOTE: may dup with other signal, fix it later
Z
ZhangZifei 已提交
158
  val redSel = redVec(selIdx)
159
  val selValid = !redSel && haveReady
160
  val selReg = RegNext(selValid)
161
  val selPtrReg = RegNext(Mux(moveMask(selPtr), selPtr-1.U, selPtr))
Z
ZhangZifei 已提交
162

Z
ZhangZifei 已提交
163
  // sel bubble
164
  val bubMask = WireInit(VecInit((0 until iqSize).map(i => emptyIdxQue(i))))
165
  // val bubIdx = ParallelMux(bubMask zip idxQueue) // NOTE: the idx in the idxQueue
Z
ZhangZifei 已提交
166
  val (bubPtr, findBubble) = PriorityEncoderWithFlag(bubMask) // NOTE: the idx of the idxQueue
167
  val haveBubble = findBubble && (bubPtr < tailPtr.asUInt)
Z
ZhangZifei 已提交
168
  val bubIdx = idxQueue(bubPtr)
169
  val bubIdxReg = RegNext(bubIdx) // NOTE: may dup with other signal, fix it later
170
  val bubValid = haveBubble && (if (feedback) true.B else !selValid)
Z
ZhangZifei 已提交
171
  val bubReg = RegNext(bubValid)
172
  val bubPtrReg = RegNext(Mux(moveMask(bubPtr), bubPtr-1.U, bubPtr))
Z
ZhangZifei 已提交
173 174

  // deq
175 176 177
  val dequeue = if (feedback) bubReg
                else          bubReg || issFire
  val deqPtr =  if (feedback) bubPtrReg
178
                else Mux(selReg, selPtrReg, bubPtrReg)
Z
ZhangZifei 已提交
179
  moveMask := {
Z
ZhangZifei 已提交
180
    (Fill(iqSize, 1.U(1.W)) << deqPtr)(iqSize-1, 0)
181
  } & Fill(iqSize, dequeue)
Z
ZhangZifei 已提交
182

183
  // move, move happens when deq
184
  for(i <- 0 until iqSize-1){
Z
ZhangZifei 已提交
185
    when(moveMask(i)){
186
      idxQueue(i) := idxQueue(i+1)
Z
ZhangZifei 已提交
187 188
    }
  }
189
  when(dequeue){
Z
ZhangZifei 已提交
190
    idxQueue.last := idxQueue(deqPtr)
191
  }
192 193
  when (selValid) {
    stateQueue(selIdx) := s_selected
Z
ZhangZifei 已提交
194
  }
195
  when (bubValid) {
196
    stateQueue(bubIdx) := s_bubble
197 198
  }

Z
ZhangZifei 已提交
199
  // redirect and feedback && wakeup
200
  for (i <- 0 until iqSize) {
201 202 203
    // replay
    val cnt = cntQueue(i)
    when (stateQueue(i) === s_replay) {
204
      cnt := cnt - 1.U
205 206 207 208 209 210 211 212 213 214 215 216 217
      when (cnt === 0.U) { stateQueue(i) := s_valid }
    }
    // feedback
    when (fbMatchVec(i)) {
      stateQueue(i) := Mux(fbHit, s_idle, s_replay)
      cntQueue(i) := Mux(fbHit, cnt, (replayDelay-1).U)
    }
    // wakeup
    val hitVec = io.data.srcUpdate(i)
    for (j <- 0 until srcNum) {
      when (hitVec(j) && validQueue(i)) {
        srcQueue(i)(j) := true.B
        XSDebug(p"srcHit: i:${i.U} j:${j.U} src:${srcQueue(i)(j)}\n")
Z
ZhangZifei 已提交
218
      }
219
    }
220 221 222 223 224 225 226 227 228 229 230 231 232 233
    // mask last selectet slot and deal with the mask
    // TODO: state queu change may have long 'when' chain -> long latency
    when (stateQueue(i) === s_selected) {
      when (io.data.fuReady) {
        if (feedback) {
          stateQueue(i) := s_wait
        }  else {
          stateQueue(i) := s_idle
        }
      }.otherwise { stateQueue(i) := s_valid }
    }
    when (stateQueue(i) === s_bubble) {
      stateQueue(i) := s_idle
    }
Z
ZhangZifei 已提交
234
    // redirect
235
    when (redVec(i) && stateQueue(i) =/= s_idle) {
Z
ZhangZifei 已提交
236
      stateQueue(i) := s_idle
237
    }
238
  }
239

240
  // output
Z
ZhangZifei 已提交
241
  val issValid = selReg && !redVecPtr(selPtrReg)
242 243 244 245 246 247
  if (nonBlocked) {
    issFire := issValid
    assert(RegNext(io.data.fuReady), "if fu wanna fast wakeup, it should not block")
  } else {
    issFire := issValid && io.data.fuReady
  }
Z
ZhangZifei 已提交
248 249

  // enq
Z
ZhangZifei 已提交
250
  val isFull = tailPtr.flag
Y
Yinan Xu 已提交
251
  // agreement with dispatch: don't fire when io.redirect.valid
252 253 254 255
  val enqueue = io.enqCtrl.fire() && !io.redirect.valid
  val tailInc = tailPtr+1.U
  val tailDec = tailPtr-1.U
  tailPtr := Mux(dequeue === enqueue, tailPtr, Mux(dequeue, tailDec, tailInc))
256

Z
ZhangZifei 已提交
257
  io.enqCtrl.ready := !isFull || dequeue
258 259 260
  val enqUop      = io.enqCtrl.bits
  val srcSeq      = Seq(enqUop.psrc1, enqUop.psrc2, enqUop.psrc3)
  val srcTypeSeq  = Seq(enqUop.ctrl.src1Type, enqUop.ctrl.src2Type, enqUop.ctrl.src3Type)
261
  val srcStateSeq = Seq(enqUop.src1State, enqUop.src2State, enqUop.src3State)
262

Z
ZhangZifei 已提交
263
  val enqPtr = Mux(tailPtr.flag, deqPtr, tailPtr.value)
264
  val enqIdx = idxQueue(enqPtr)
265 266 267 268 269 270
  val enqBpVec = io.data.srcUpdate(IssQueSize)

  def stateCheck(src: UInt, srcType: UInt): Bool = {
    (srcType =/= SrcType.reg && srcType =/= SrcType.fp) ||
    (srcType === SrcType.reg && src === 0.U)
  }
271

272
  when (enqueue) {
273 274
    stateQueue(enqIdx) := s_valid
    srcQueue(enqIdx).zipWithIndex.map{ case (s, i) =>
275
      s := Mux(enqBpVec(i) || stateCheck(srcSeq(i), srcTypeSeq(i)), true.B,
Z
ZhangZifei 已提交
276
               srcStateSeq(i)===SrcState.rdy)
277
    }
Z
ZhangZifei 已提交
278
    XSDebug(p"EnqCtrl: roqIdx:${enqUop.roqIdx} pc:0x${Hexadecimal(enqUop.cf.pc)} " +
279
      List.tabulate(srcNum)(i => p"<src$i: ${srcSeq(i)} state$i: ${srcStateSeq(i)} type$i: ${srcTypeSeq(i)}>").reduce(_ + " " + _) + "\n")
Z
ZhangZifei 已提交
280 281
  }

282
  // other to Data
283
  io.data.enqPtr := enqIdx
284
  io.data.deqPtr.valid  := selValid
Z
ZhangZifei 已提交
285
  io.data.deqPtr.bits   := selIdx
286
  io.data.enqCtrl.valid := enqueue
287
  io.data.enqCtrl.bits  := io.enqCtrl.bits
288

289
  // other io
Z
ZhangZifei 已提交
290
  io.numExist := Mux(tailPtr.flag, (iqSize-1).U, tailPtr.value) // NOTE: numExist is iqIdxWidth.W, maybe a bug
291

Z
ZhangZifei 已提交
292
  // assert
Z
ZhangZifei 已提交
293
  assert(RegNext(Mux(tailPtr.flag, tailPtr.value===0.U, true.B)))
Z
ZhangZifei 已提交
294

295 296
  val print = !(tailPtr.asUInt===0.U) || io.enqCtrl.valid || enqueue || dequeue
  XSDebug(print || true.B, p"In(${io.enqCtrl.valid} ${io.enqCtrl.ready}) Out(${issValid} ${io.data.fuReady}) nonBlocked:${nonBlocked.B} needfb:${feedback.B}\n")
297
  XSDebug(print , p"tailPtr:${tailPtr} enq:${enqueue} deq:${dequeue} isFull:${isFull} " +
298
    p"vIdxQue:${Binary(validIdxQue.asUInt)} rIdxQue:${Binary(readyIdxQue.asUInt)}\n")
Z
ZhangZifei 已提交
299
  XSDebug(print && Cat(redVecPtr).orR, p"Redirect: ${Hexadecimal(redVecPtr.asUInt)}\n")
300
  XSDebug(print && Cat(fbMatchVec).orR, p"Feedback: ${Hexadecimal(fbMatchVec.asUInt)} Hit:${fbHit}\n")
301
  XSDebug(print, p"moveMask:${Binary(moveMask)} selMask:${Binary(selectMask.asUInt)} bubMask:${Binary(bubMask.asUInt)}\n")
Z
ZhangZifei 已提交
302
  XSDebug(print, p"selIdxWire:${selPtr} haveReady:${haveReady} redSel:${redSel}" +
303
    p"selV:${selValid} selReg:${selReg} selPtrReg:${selPtrReg} selIdx:${selIdx} selIdxReg:${selIdxReg}\n")
304
  XSDebug(print, p"bubValid:${bubValid} haveBub:${haveBubble} bubPtr:${bubPtr} findBub:${findBubble} " +
305 306
    p"bubReg:${bubReg} bubPtrReg:${bubPtrReg} bubIdx:${bubIdx} bubIdxReg:${bubIdxReg}\n")
  XSDebug(print, p"issValid:${issValid} issueFire:${issFire} dequeue:${dequeue} deqPtr:${deqPtr}\n")
Z
ZhangZifei 已提交
307
  XSDebug(p" :Idx|v|r|s |cnt|s1:s2:s3\n")
Z
ZhangZifei 已提交
308
  for(i <- srcQueue.indices) {
309 310
    XSDebug(p"${i.U}: ${idxQueue(i)}|${validIdxQue(i)}|${readyIdxQue(i)}|${stateIdxQue(i)}|${cntIdxQue(i)}|" +
      List.tabulate(srcNum)(j => p"${srcIdxQue(i)(j)}").reduce(_ + ":" + _) + "\n")
Z
ZhangZifei 已提交
311
  }
312 313 314 315 316 317 318
}

class ReservationStationData
(
  val exuCfg: ExuConfig,
  wakeupCnt: Int,
  extraListenPortsCnt: Int,
319
  fixedDelay: Int,
320
  feedback: Boolean,
321 322 323
) extends XSModule {
  val iqSize = IssQueSize
  val iqIdxWidth = log2Up(iqSize)
324 325
  val fastWakeup = fixedDelay >= 0 // NOTE: if do not enable fastWakeup(bypass), set fixedDelay to -1
  val nonBlocked = fastWakeup
326
  val srcNum = max(exuCfg.intSrcCnt, exuCfg.fpSrcCnt)
327 328
  require(srcNum >= 1 && srcNum <= 3)
  println(s"[RsData]  ExuConfig: ${exuCfg.name} (srcNum = $srcNum)")
329 330 331

  val io = IO(new XSBundle {
    // flush
332
    val redirect = Flipped(ValidIO(new Redirect))
333 334

    // send to exu
335
    val deq = DecoupledIO(new ExuInput)
336 337

    // listen to RSCtrl
338
    val ctrl = Flipped(new RSCtrlDataIO(srcNum))
339

340
    // read src op value
341
    val srcRegValue = Vec(srcNum, Input(UInt((XLEN + 1).W)))
L
LinJiawei 已提交
342
    val jumpPc = if(exuCfg == Exu.jumpExeUnitCfg) Input(UInt(VAddrBits.W)) else null
343 344 345 346 347
    // broadcast selected uop to other issue queues
    val selectedUop = ValidIO(new MicroOp)

    // recv broadcasted uops form any relative issue queue,
    // to simplify wake up logic, the uop broadcasted by this queue self
348
    // are also in 'broadcastedUops'
349
    val broadcastedUops = Vec(wakeupCnt, Flipped(ValidIO(new MicroOp)))
350 351

    // listen to write back data bus(certain latency)
352
    // and extra write back(uncertain latency)
353
    val writeBackedData = Vec(wakeupCnt, Input(UInt((XLEN+1).W)))
354 355 356 357
    val extraListenPorts = Vec(extraListenPortsCnt, Flipped(ValidIO(new ExuOutput)))

    // tlb feedback
    val feedback = Flipped(ValidIO(new TlbFeedback))
358 359
  })

360 361
  // Data
  // ------------------------
362
  val data    = List.tabulate(srcNum)(_ => Module(new SyncDataModuleTemplate(UInt((XLEN + 1).W), iqSize, numRead = iqSize + 1, numWrite = iqSize)))
363
  data.foreach(_.io <> DontCare)
364
  data.foreach(_.io.wen.foreach(_ := false.B))
365

366
  // data/uop read/write interface
367 368 369
  // ! warning: reading has 1 cycle delay, so input addr is used in next cycle
  // luckily, for fpga platform, read port has fixed value
  // otherwise, read port has same value as read addr
370 371 372 373 374 375 376
  def dataDebugRead(iqIdx: UInt, srcIdx: Int): UInt = {
    data(srcIdx).io.raddr(iqIdx + 1.U) := iqIdx
    data(srcIdx).io.rdata(iqIdx + 1.U)
  }
  def dataRead(nextIqIdx: UInt, srcIdx: Int): UInt = {
    data(srcIdx).io.raddr(0) := nextIqIdx
    data(srcIdx).io.rdata(0)
377 378 379 380 381 382
  }
  def dataWrite(iqIdx: UInt, srcIdx: Int, wdata: UInt) = {
    data(srcIdx).io.waddr(iqIdx) := iqIdx
    data(srcIdx).io.wdata(iqIdx) := wdata
    data(srcIdx).io.wen(iqIdx) := true.B
  }
383
  // debug data: only for XSDebug log printing!
384
  val debug_data = List.tabulate(srcNum)(i => WireInit(VecInit((0 until iqSize).map(j => dataDebugRead(j.U, i)))))
385 386 387 388 389 390 391 392 393 394

  // Uop
  // ------------------------
  val uopMem     = Module(new SyncDataModuleTemplate(new MicroOp, iqSize, iqSize, 1))
  uopMem.io <> DontCare
  uopMem.io.wen.foreach(_ := false.B)
  
  // uop -- read = iqSize write = 1
  // uopMem 's read ports have fixed values
  uopMem.io.raddr.zipWithIndex.foreach{ case(r, i) => r := i.U }
395 396 397 398 399 400 401 402 403 404
  def uopRead(iqIdx: UInt): MicroOp = {
    uopMem.io.rdata(iqIdx)
  }
  def uopWrite(iqIdx: UInt, wdata: MicroOp) = {
    uopMem.io.waddr(0) := iqIdx
    uopMem.io.wdata(0) := wdata
    uopMem.io.wen(0) := true.B
  }

  val uop = WireInit(VecInit((0 until iqSize).map(i => uopRead(i.U))))
405

406 407 408 409 410
  val enq   = io.ctrl.enqPtr
  val sel   = io.ctrl.deqPtr
  val deq   = RegEnable(sel.bits, sel.valid)
  val enqCtrl = io.ctrl.enqCtrl
  val enqUop = enqCtrl.bits
411
  val enqUopReg = RegEnable(enqUop, enqCtrl.fire())
412 413

  // enq
414
  val enqPtr = enq(log2Up(IssQueSize)-1,0)
Y
Yinan Xu 已提交
415 416
  val enqPtrReg = RegEnable(enqPtr, enqCtrl.valid)
  val enqEn  = enqCtrl.valid
417 418
  val enqEnReg = RegNext(enqEn)
  when (enqEn) {
419
    uopWrite(enqPtr, enqUop)
Z
ZhangZifei 已提交
420 421 422
    XSDebug(p"enqCtrl: enqPtr:${enqPtr} src1:${enqUop.psrc1}|${enqUop.src1State}|${enqUop.ctrl.src1Type}" +
      p" src2:${enqUop.psrc2}|${enqUop.src2State}|${enqUop.ctrl.src2Type} src3:${enqUop.psrc3}|" +
      p"${enqUop.src3State}|${enqUop.ctrl.src3Type} pc:0x${Hexadecimal(enqUop.cf.pc)} roqIdx:${enqUop.roqIdx}\n")
423
  }
424

425
  when (enqEnReg) {
L
LinJiawei 已提交
426 427
    exuCfg match {
      case Exu.jumpExeUnitCfg =>
L
LinJiawei 已提交
428 429 430 431
        val src1Mux = Mux(enqUopReg.ctrl.src1Type === SrcType.pc,
          SignExt(io.jumpPc, XLEN),
          io.srcRegValue(0)
        )
L
LinJiawei 已提交
432
        dataWrite(enqPtrReg, 0, src1Mux)
L
LinJiawei 已提交
433
      case Exu.aluExeUnitCfg =>
L
LinJiawei 已提交
434 435 436 437
        val src1Mux = Mux(enqUopReg.ctrl.src1Type === SrcType.pc,
          SignExt(enqUopReg.cf.pc, XLEN),
          io.srcRegValue(0)
        )
L
LinJiawei 已提交
438
        dataWrite(enqPtrReg, 0, src1Mux)
L
LinJiawei 已提交
439 440 441 442
        // alu only need U type and I type imm
        val imm32 = Mux(enqUopReg.ctrl.selImm === SelImm.IMM_U,
          ImmUnion.U.toImm32(enqUopReg.ctrl.imm),
          ImmUnion.I.toImm32(enqUopReg.ctrl.imm)
L
LinJiawei 已提交
443 444 445 446 447 448 449 450 451 452
        )
        val imm64 = SignExt(imm32, XLEN)
        val src2Mux = Mux(enqUopReg.ctrl.src2Type === SrcType.imm,
          imm64, io.srcRegValue(1)
        )
        dataWrite(enqPtrReg, 1, src2Mux)
      case _ =>
        (0 until srcNum).foreach(i => dataWrite(enqPtrReg, i, io.srcRegValue(i)))
    }

453
    XSDebug(p"${exuCfg.name}: enqPtrReg:${enqPtrReg} pc: ${Hexadecimal(uop(enqPtrReg).cf.pc)}\n")
454
    XSDebug(p"[srcRegValue] " + List.tabulate(srcNum)(idx => p"src$idx: ${Hexadecimal(io.srcRegValue(idx))}").reduce((p1, p2) => p1 + " " + p2) + "\n")
455 456
  }

457
  def wbHit(uop: MicroOp, src: UInt, srctype: UInt): Bool = {
458
    (src === uop.pdest) &&
459 460 461
    ((srctype === SrcType.reg && uop.ctrl.rfWen && src=/=0.U) ||
     (srctype === SrcType.fp  && uop.ctrl.fpWen))
  }
462

463
  // wakeup and bypass
464 465
  def wakeup(src: UInt, srcType: UInt, valid: Bool = true.B) : (Bool, UInt) = {
    val hitVec = io.extraListenPorts.map(port => wbHit(port.bits.uop, src, srcType) && port.valid && valid)
466 467 468 469 470 471
    assert(RegNext(PopCount(hitVec)===0.U || PopCount(hitVec)===1.U))

    val hit = ParallelOR(hitVec)
    (hit, ParallelMux(hitVec zip io.extraListenPorts.map(_.bits.data)))
  }

472 473
  def bypass(src: UInt, srcType: UInt, valid: Bool = true.B) : (Bool, Bool, UInt) = {
    val hitVec = io.broadcastedUops.map(port => wbHit(port.bits, src, srcType) && port.valid && valid)
474 475 476 477 478 479 480 481 482 483
    assert(RegNext(PopCount(hitVec)===0.U || PopCount(hitVec)===1.U))

    val hit = ParallelOR(hitVec)
    (hit, RegNext(hit), ParallelMux(hitVec.map(RegNext(_)) zip io.writeBackedData))
  }

  io.ctrl.srcUpdate.map(a => a.map(_ := false.B))
  for (i <- 0 until iqSize) {
    val srcSeq = Seq(uop(i).psrc1, uop(i).psrc2, uop(i).psrc3)
    val srcTypeSeq = Seq(uop(i).ctrl.src1Type, uop(i).ctrl.src2Type, uop(i).ctrl.src3Type)
484
    for (j <- 0 until srcNum) {
485 486 487
      val (wuHit, wuData) = wakeup(srcSeq(j), srcTypeSeq(j))
      val (bpHit, bpHitReg, bpData) = bypass(srcSeq(j), srcTypeSeq(j))
      when (wuHit || bpHit) { io.ctrl.srcUpdate(i)(j) := true.B }
488 489
      when (wuHit) { /* data(i)(j) := wuData */dataWrite(i.U, j, wuData) }
      when (bpHitReg && !(enqPtrReg===i.U && enqEnReg)) { /* data(i)(j) := bpData */dataWrite(i.U, j, bpData) }
490 491 492 493
      // NOTE: the hit is from data's info, so there is an erro that:
      //       when enq, hit use last instr's info not the enq info.
      //       it will be long latency to add correct here, so add it to ctrl or somewhere else
      //       enq bp is done at below
494 495 496
      XSDebug(wuHit, p"WUHit: (${i.U})(${j.U}) Data:0x${Hexadecimal(wuData)}\n")
      XSDebug(bpHit, p"BPHit: (${i.U})(${j.U})\n")
      XSDebug(bpHitReg, p"BPHitData: (${i.U})(${j.U}) Data:0x${Hexadecimal(bpData)}\n")
497 498 499 500
    }
  }

  // deq
501 502 503
  val exuInput = io.deq.bits
  exuInput := DontCare
  exuInput.uop := uop(deq)
504
  val regValues = List.tabulate(srcNum)(i => dataRead(Mux(sel.valid, sel.bits, deq), i))
505
  XSDebug(io.deq.fire(), p"[regValues] " + List.tabulate(srcNum)(idx => p"reg$idx: ${Hexadecimal(regValues(idx))}").reduce((p1, p2) => p1 + " " + p2) + "\n")
506 507
  exuInput.src1 := regValues(0)
  if (srcNum > 1) exuInput.src2 := regValues(1)
508
  if (srcNum > 2) exuInput.src3 := regValues(2)
509

510
  io.deq.valid := RegNext(sel.valid)
511
  if (nonBlocked) { assert(RegNext(io.deq.ready), s"${name} if fu wanna fast wakeup, it should not block")}
512 513 514 515 516

  // to ctrl
  val srcSeq = Seq(enqUop.psrc1, enqUop.psrc2, enqUop.psrc3)
  val srcTypeSeq = Seq(enqUop.ctrl.src1Type, enqUop.ctrl.src2Type, enqUop.ctrl.src3Type)
  io.ctrl.srcUpdate(IssQueSize).zipWithIndex.map{ case (h, i) =>
Y
Yinan Xu 已提交
517
    val (bpHit, bpHitReg, bpData)= bypass(srcSeq(i), srcTypeSeq(i), enqCtrl.valid)
518
    when (bpHitReg) { /* data(enqPtrReg)(i) := bpData */dataWrite(enqPtrReg, i, bpData) }
519
    h := bpHit
520
    // NOTE: enq bp is done here
521 522 523
    XSDebug(bpHit, p"EnqBPHit: (${i.U})\n")
    XSDebug(bpHitReg, p"EnqBPHitData: (${i.U}) data:${Hexadecimal(bpData)}\n")
  }
524 525
  if (nonBlocked) { io.ctrl.fuReady := true.B }
  else { io.ctrl.fuReady := io.deq.ready }
526
  io.ctrl.redVec   := VecInit(uop.map(_.roqIdx.needFlush(io.redirect))).asUInt
527 528 529

  io.ctrl.feedback := DontCare
  if (feedback) {
530
    (0 until IssQueSize).foreach(i =>
531 532 533 534
      io.ctrl.feedback(i) := uop(i).roqIdx.asUInt === io.feedback.bits.roqIdx.asUInt && io.feedback.valid)
    io.ctrl.feedback(IssQueSize) := io.feedback.bits.hit
  }

535 536

  // bypass send
537 538 539 540 541 542 543 544 545 546 547 548
  io.selectedUop <> DontCare
  if (fastWakeup) {
    val bpQueue = Module(new BypassQueue(fixedDelay))
    bpQueue.io.in.valid := sel.valid // FIXME: error when function is blocked => fu should not be blocked
    bpQueue.io.in.bits := uop(sel.bits)
    bpQueue.io.redirect := io.redirect
    io.selectedUop.valid := bpQueue.io.out.valid
    io.selectedUop.bits  := bpQueue.io.out.bits

    XSDebug(io.selectedUop.valid, p"SelUop: pc:0x${Hexadecimal(io.selectedUop.bits.cf.pc)}" +
      p" roqIdx:${io.selectedUop.bits.roqIdx} pdest:${io.selectedUop.bits.pdest} " +
      p"rfWen:${io.selectedUop.bits.ctrl.rfWen} fpWen:${io.selectedUop.bits.ctrl.fpWen}\n" )
549
  }
550

551

Z
ZhangZifei 已提交
552
  // log
Z
ZhangZifei 已提交
553
  XSDebug(io.ctrl.redVec.orR, p"Red: ${Binary(io.ctrl.redVec)}\n")
554
  XSDebug(io.feedback.valid && feedback.B, p"feedback: roqIdx:${io.feedback.bits.roqIdx} hit:${io.feedback.bits.hit}\n")
555
  XSDebug(true.B, p"out(${io.deq.valid} ${io.deq.ready})\n")
Z
ZhangZifei 已提交
556
  XSDebug(io.deq.valid, p"Deq(${io.deq.valid} ${io.deq.ready}): deqPtr:${deq} pc:${Hexadecimal(io.deq.bits.uop.cf.pc)}" +
557 558
    p" roqIdx:${io.deq.bits.uop.roqIdx} src1:${Hexadecimal(io.deq.bits.src1)} " +
    p" src2:${Hexadecimal(io.deq.bits.src2)} src3:${Hexadecimal(io.deq.bits.src3)}\n")
Z
ZhangZifei 已提交
559
  XSDebug(p"Data:  | src1:data | src2:data | src3:data |hit|pdest:rf:fp| roqIdx | pc\n")
560 561 562
  for (i <- 0 until iqSize) {
    XSDebug(p"${i.U}:|${uop(i).psrc1}:${Hexadecimal(debug_data(0)(i))}|${uop(i).psrc2}:" +
      (if (srcNum > 1) p"${Hexadecimal(debug_data(1)(i))}" else p"null") + p"|${uop(i).psrc3}:" + (if (srcNum > 2) p"${Hexadecimal(debug_data(2)(i))}" else p"null") + p"|" +
Z
ZhangZifei 已提交
563 564
      p"${Binary(io.ctrl.srcUpdate(i).asUInt)}|${uop(i).pdest}:${uop(i).ctrl.rfWen}:" +
      p"${uop(i).ctrl.fpWen}|${uop(i).roqIdx} |${Hexadecimal(uop(i).cf.pc)}\n")
565
  }
566
}