Dispatch1.scala 9.3 KB
Newer Older
1 2 3 4
package xiangshan.backend.dispatch

import chisel3._
import chisel3.util._
Y
Yinan Xu 已提交
5
import chisel3.ExcitingUtils._
6
import xiangshan._
7
import utils.{XSDebug, XSError, XSInfo}
Y
Yinan Xu 已提交
8
import xiangshan.backend.roq.{RoqPtr, RoqEnqIO}
9
import xiangshan.backend.rename.RenameBypassInfo
Y
Yinan Xu 已提交
10
import xiangshan.mem.LsqEnqIO
11

12
// read rob and enqueue
13
class Dispatch1 extends XSModule {
14 15 16
  val io = IO(new Bundle() {
    // from rename
    val fromRename = Vec(RenameWidth, Flipped(DecoupledIO(new MicroOp)))
17
    val renameBypass = Input(new RenameBypassInfo)
18 19
    val recv = Output(Vec(RenameWidth, Bool()))
    // enq Roq
Y
Yinan Xu 已提交
20
    val enqRoq = Flipped(new RoqEnqIO)
Y
Yinan Xu 已提交
21
    // enq Lsq
Y
Yinan Xu 已提交
22
    val enqLsq = Flipped(new LsqEnqIO)
Y
Yinan Xu 已提交
23
    val allocPregs = Vec(RenameWidth, Output(new ReplayPregReq))
24
    // to dispatch queue
25 26 27 28 29 30 31 32 33 34 35 36
    val toIntDq = new Bundle {
      val canAccept = Input(Bool())
      val req = Vec(RenameWidth, ValidIO(new MicroOp))
    }
    val toFpDq = new Bundle {
      val canAccept = Input(Bool())
      val req = Vec(RenameWidth, ValidIO(new MicroOp))
    }
    val toLsDq = new Bundle {
      val canAccept = Input(Bool())
      val req = Vec(RenameWidth, ValidIO(new MicroOp))
    }
37
  })
38 39


40 41 42 43
  /**
    * Part 1: choose the target dispatch queue and the corresponding write ports
    */
  // valid bits for different dispatch queues
44 45 46 47
  val isInt   = VecInit(io.fromRename.map(req => FuType.isIntExu(req.bits.ctrl.fuType)))
  val isFp    = VecInit(io.fromRename.map(req => FuType.isFpExu (req.bits.ctrl.fuType)))
  val isLs    = VecInit(io.fromRename.map(req => FuType.isMemExu(req.bits.ctrl.fuType)))
  val isStore = VecInit(io.fromRename.map(req => FuType.isStoreExu(req.bits.ctrl.fuType)))
Y
Yinan Xu 已提交
48
  val isAMO = VecInit(io.fromRename.map(req => req.bits.ctrl.fuType === FuType.mou))
49 50
  val isBlockBackward = VecInit(io.fromRename.map(_.bits.ctrl.blockBackward))
  val isNoSpecExec    = VecInit(io.fromRename.map(_.bits.ctrl.noSpecExec))
51

52
  /**
53
    * Part 2:
54 55 56 57 58 59 60 61 62 63
    *   Update commitType, psrc1, psrc2, psrc3, old_pdest for the uops
    */
  val updatedUop = Wire(Vec(RenameWidth, new MicroOp))
  val updatedCommitType = Wire(Vec(RenameWidth, CommitType()))
  val updatedPsrc1 = Wire(Vec(RenameWidth, UInt(PhyRegIdxWidth.W)))
  val updatedPsrc2 = Wire(Vec(RenameWidth, UInt(PhyRegIdxWidth.W)))
  val updatedPsrc3 = Wire(Vec(RenameWidth, UInt(PhyRegIdxWidth.W)))
  val updatedOldPdest = Wire(Vec(RenameWidth, UInt(PhyRegIdxWidth.W)))

  for (i <- 0 until RenameWidth) {
Y
Yinan Xu 已提交
64
    updatedCommitType(i) := Cat(isLs(i) && !isAMO(i), isStore(i) | isFp(i))
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
    updatedPsrc1(i) := io.fromRename.take(i).map(_.bits.pdest)
      .zip(if (i == 0) Seq() else io.renameBypass.lsrc1_bypass(i-1).asBools)
      .foldLeft(io.fromRename(i).bits.psrc1) {
        (z, next) => Mux(next._2, next._1, z)
      }
    updatedPsrc2(i) := io.fromRename.take(i).map(_.bits.pdest)
      .zip(if (i == 0) Seq() else io.renameBypass.lsrc2_bypass(i-1).asBools)
      .foldLeft(io.fromRename(i).bits.psrc2) {
        (z, next) => Mux(next._2, next._1, z)
      }
    updatedPsrc3(i) := io.fromRename.take(i).map(_.bits.pdest)
      .zip(if (i == 0) Seq() else io.renameBypass.lsrc3_bypass(i-1).asBools)
      .foldLeft(io.fromRename(i).bits.psrc3) {
        (z, next) => Mux(next._2, next._1, z)
      }
    updatedOldPdest(i) := io.fromRename.take(i).map(_.bits.pdest)
      .zip(if (i == 0) Seq() else io.renameBypass.ldest_bypass(i-1).asBools)
      .foldLeft(io.fromRename(i).bits.old_pdest) {
        (z, next) => Mux(next._2, next._1, z)
      }

    updatedUop(i) := io.fromRename(i).bits
    // update bypass psrc1/psrc2/psrc3/old_pdest
    updatedUop(i).psrc1 := updatedPsrc1(i)
    updatedUop(i).psrc2 := updatedPsrc2(i)
    updatedUop(i).psrc3 := updatedPsrc3(i)
    updatedUop(i).old_pdest := updatedOldPdest(i)
    // update commitType
    updatedUop(i).ctrl.commitType := updatedCommitType(i)
  }


  /**
    * Part 3:
99 100
    *   acquire ROQ (all), LSQ (load/store only) and dispatch queue slots
    *   only set valid when all of them provides enough entries
101
    */
102
  val allResourceReady = io.enqLsq.canAccept && io.enqRoq.canAccept && io.toIntDq.canAccept && io.toFpDq.canAccept && io.toLsDq.canAccept
103 104

  // Instructions should enter dispatch queues in order.
Y
Yinan Xu 已提交
105
  // thisIsBlocked: this instruction is blocked by itself (based on noSpecExec)
106
  // nextCanOut: next instructions can out (based on blockBackward)
107
  // notBlockedByPrevious: previous instructions can enqueue
Y
Yinan Xu 已提交
108 109 110 111 112
  val thisIsBlocked = VecInit((0 until RenameWidth).map(i => {
    // for i > 0, when Roq is empty but dispatch1 have valid instructions to enqueue, it's blocked
    if (i > 0) isNoSpecExec(i) && (!io.enqRoq.isEmpty || Cat(io.fromRename.take(i).map(_.valid)).orR)
    else isNoSpecExec(i) && !io.enqRoq.isEmpty
  }))
113
  val nextCanOut = VecInit((0 until RenameWidth).map(i =>
114
    (!isNoSpecExec(i) && !isBlockBackward(i)) || !io.fromRename(i).valid
115 116 117 118
  ))
  val notBlockedByPrevious = VecInit((0 until RenameWidth).map(i =>
    if (i == 0) true.B
    else Cat((0 until i).map(j => nextCanOut(j))).andR
119 120
  ))

121 122
  // for noSpecExec: (roqEmpty || !this.noSpecExec) && !previous.noSpecExec
  // For blockBackward:
123 124 125
  // this instruction can actually dequeue: 3 conditions
  // (1) resources are ready
  // (2) previous instructions are ready
Y
Yinan Xu 已提交
126
  val thisCanActualOut = (0 until RenameWidth).map(i => !thisIsBlocked(i) && notBlockedByPrevious(i))
Y
Yinan Xu 已提交
127

128
  // input for ROQ and LSQ
Y
Yinan Xu 已提交
129 130
  // (1) LSQ needs roqIdx; (2) DPQ needs roqIdx and lsIdx
  val updateUopWithIndex = Wire(Vec(RenameWidth, new MicroOp))
131
  for (i <- 0 until RenameWidth) {
Y
Yinan Xu 已提交
132 133
    io.enqRoq.needAlloc(i) := io.fromRename(i).valid
    io.enqRoq.req(i).valid := io.fromRename(i).valid && thisCanActualOut(i) && io.enqLsq.canAccept && io.toIntDq.canAccept && io.toFpDq.canAccept && io.toLsDq.canAccept
134
    io.enqRoq.req(i).bits := updatedUop(i)
Y
Yinan Xu 已提交
135
    XSDebug(io.enqRoq.req(i).valid, p"pc 0x${Hexadecimal(io.fromRename(i).bits.cf.pc)} receives nroq ${io.enqRoq.resp(i)}\n")
136

Y
Yinan Xu 已提交
137
    val shouldEnqLsq = isLs(i) && !isAMO(i)
Y
Yinan Xu 已提交
138
    io.enqLsq.needAlloc(i) := io.fromRename(i).valid && shouldEnqLsq
Y
Yinan Xu 已提交
139
    io.enqLsq.req(i).valid := io.fromRename(i).valid && shouldEnqLsq && thisCanActualOut(i) && io.enqRoq.canAccept && io.toIntDq.canAccept && io.toFpDq.canAccept && io.toLsDq.canAccept
140
    io.enqLsq.req(i).bits := updatedUop(i)
141
    io.enqLsq.req(i).bits.roqIdx := io.enqRoq.resp(i)
142 143
    XSDebug(io.enqLsq.req(i).valid,
      p"pc 0x${Hexadecimal(io.fromRename(i).bits.cf.pc)} receives lq ${io.enqLsq.resp(i).lqIdx} sq ${io.enqLsq.resp(i).sqIdx}\n")
144

145 146 147 148 149
    updateUopWithIndex(i)        := updatedUop(i)
    updateUopWithIndex(i).roqIdx := io.enqRoq.resp(i)
    updateUopWithIndex(i).lqIdx  := io.enqLsq.resp(i).lqIdx
    updateUopWithIndex(i).sqIdx  := io.enqLsq.resp(i).sqIdx

150 151 152 153
    // send uops to dispatch queues
    // Note that if one of their previous instructions cannot enqueue, they should not enter dispatch queue.
    // We use notBlockedByPrevious here.
    io.toIntDq.req(i).bits  := updateUopWithIndex(i)
Y
Yinan Xu 已提交
154 155
    io.toIntDq.req(i).valid := io.fromRename(i).valid && isInt(i) && thisCanActualOut(i) &&
                           io.enqLsq.canAccept && io.enqRoq.canAccept && io.toFpDq.canAccept && io.toLsDq.canAccept
156

157
    io.toFpDq.req(i).bits   := updateUopWithIndex(i)
Y
Yinan Xu 已提交
158 159
    io.toFpDq.req(i).valid  := io.fromRename(i).valid && isFp(i) && thisCanActualOut(i) &&
                           io.enqLsq.canAccept && io.enqRoq.canAccept && io.toIntDq.canAccept && io.toLsDq.canAccept
160

161
    io.toLsDq.req(i).bits   := updateUopWithIndex(i)
Y
Yinan Xu 已提交
162 163
    io.toLsDq.req(i).valid  := io.fromRename(i).valid && isLs(i) && thisCanActualOut(i) &&
                           io.enqLsq.canAccept && io.enqRoq.canAccept && io.toIntDq.canAccept && io.toFpDq.canAccept
164

165 166 167
    XSDebug(io.toIntDq.req(i).valid, p"pc 0x${Hexadecimal(io.toIntDq.req(i).bits.cf.pc)} int index $i\n")
    XSDebug(io.toFpDq.req(i).valid , p"pc 0x${Hexadecimal(io.toFpDq.req(i).bits.cf.pc )} fp  index $i\n")
    XSDebug(io.toLsDq.req(i).valid , p"pc 0x${Hexadecimal(io.toLsDq.req(i).bits.cf.pc )} ls  index $i\n")
168
  }
169

170
  /**
Y
Yinan Xu 已提交
171
    * Part 4: send response to rename when dispatch queue accepts the uop
172
    */
Y
Yinan Xu 已提交
173
  val hasSpecialInstr = Cat((0 until RenameWidth).map(i => io.fromRename(i).valid && (isBlockBackward(i) || isNoSpecExec(i)))).orR
174
  for (i <- 0 until RenameWidth) {
Y
Yinan Xu 已提交
175 176
    io.recv(i) := thisCanActualOut(i) && io.enqLsq.canAccept && io.enqRoq.canAccept && io.toIntDq.canAccept && io.toFpDq.canAccept && io.toLsDq.canAccept
    io.fromRename(i).ready := !hasSpecialInstr && io.enqLsq.canAccept && io.enqRoq.canAccept && io.toIntDq.canAccept && io.toFpDq.canAccept && io.toLsDq.canAccept
177

178
    XSInfo(io.recv(i) && io.fromRename(i).valid,
179
      p"pc 0x${Hexadecimal(io.fromRename(i).bits.cf.pc)}, type(${isInt(i)}, ${isFp(i)}, ${isLs(i)}), " +
180
      p"roq ${updateUopWithIndex(i).roqIdx}, lq ${updateUopWithIndex(i).lqIdx}, sq ${updateUopWithIndex(i).sqIdx})\n"
181
    )
182

183 184 185
    io.allocPregs(i).isInt := io.fromRename(i).valid && io.fromRename(i).bits.ctrl.rfWen && (io.fromRename(i).bits.ctrl.ldest =/= 0.U)
    io.allocPregs(i).isFp  := io.fromRename(i).valid && io.fromRename(i).bits.ctrl.fpWen
    io.allocPregs(i).preg  := io.fromRename(i).bits.pdest
186
  }
Y
Yinan Xu 已提交
187
  val renameFireCnt = PopCount(io.recv)
188 189 190
  val enqFireCnt = PopCount(io.toIntDq.req.map(_.valid && io.toIntDq.canAccept)) +
    PopCount(io.toFpDq.req.map(_.valid && io.toFpDq.canAccept)) +
    PopCount(io.toLsDq.req.map(_.valid && io.toLsDq.canAccept))
Y
Yinan Xu 已提交
191
  XSError(enqFireCnt > renameFireCnt, "enqFireCnt should not be greater than renameFireCnt\n")
192
}