Roq.scala 13.0 KB
Newer Older
1 2
package xiangshan.backend.roq

3
import chisel3.ExcitingUtils.ConnectionType
4 5 6
import chisel3._
import chisel3.util._
import xiangshan._
L
LinJiawei 已提交
7
import utils._
8
import chisel3.util.experimental.BoringUtils
L
Opt roq  
LinJiawei 已提交
9
import xiangshan.backend.LSUOpType
10

W
William Wang 已提交
11
// A "just-enough" Roq
L
LinJiawei 已提交
12
class Roq extends XSModule {
13 14
  val io = IO(new Bundle() {
    val brqRedirect = Input(Valid(new Redirect))
W
William Wang 已提交
15
    val memRedirect = Input(Valid(new Redirect))
16
    val dp1Req = Vec(RenameWidth, Flipped(DecoupledIO(new MicroOp)))
W
William Wang 已提交
17
    val roqIdxs = Output(Vec(RenameWidth, UInt(RoqIdxWidth.W)))
18
    val redirect = Output(Valid(new Redirect))
19
    val exception = Output(new MicroOp)
L
LinJiawei 已提交
20
    // exu + brq
L
LinJiawei 已提交
21
    val exeWbResults = Vec(exuParameters.ExuCnt + 1, Flipped(ValidIO(new ExuOutput)))
22
    val commits = Vec(CommitWidth, Valid(new RoqCommit))
Y
Yinan Xu 已提交
23
    val mcommit = Vec(CommitWidth, Valid(UInt(LsroqIdxWidth.W)))
24
    val bcommit = Output(UInt(BrTagWidth.W))
25
  })
W
William Wang 已提交
26

L
LinJiawei 已提交
27 28
  val numWbPorts = io.exeWbResults.length

29
  val microOp = Mem(RoqSize, new MicroOp)
W
William Wang 已提交
30
  val valid = RegInit(VecInit(List.fill(RoqSize)(false.B)))
W
William Wang 已提交
31
  val flag = RegInit(VecInit(List.fill(RoqSize)(false.B)))
W
William Wang 已提交
32
  val writebacked = Reg(Vec(RoqSize, Bool()))
33 34 35

  val exuData = Reg(Vec(RoqSize, UInt(XLEN.W)))//for debug
  val exuDebug = Reg(Vec(RoqSize, new DebugBundle))//for debug
W
William Wang 已提交
36

L
Opt roq  
LinJiawei 已提交
37 38 39 40 41 42 43 44 45 46
  val enqPtrExt = RegInit(0.U(RoqIdxWidth.W))
  val deqPtrExt = RegInit(0.U(RoqIdxWidth.W))
  val walkPtrExt = Reg(UInt(RoqIdxWidth.W))
  val walkTgtExt = Reg(UInt(RoqIdxWidth.W))
  val enqPtr = enqPtrExt(InnerRoqIdxWidth-1,0)
  val deqPtr = deqPtrExt(InnerRoqIdxWidth-1,0)
  val walkPtr = walkPtrExt(InnerRoqIdxWidth-1,0)
  val isEmpty = enqPtr === deqPtr && enqPtrExt.head(1)===deqPtrExt.head(1)
  val isFull = enqPtr === deqPtr && enqPtrExt.head(1)=/=deqPtrExt.head(1)
  val notFull = !isFull
W
William Wang 已提交
47

W
William Wang 已提交
48
  val s_idle :: s_walk :: s_extrawalk :: Nil = Enum(3)
W
William Wang 已提交
49 50
  val state = RegInit(s_idle)

W
William Wang 已提交
51
  // Dispatch
L
LinJiawei 已提交
52 53
  val csrEnRoq = io.dp1Req.map(i => i.bits.ctrl.fuType === FuType.csr)
  val hasCsr = RegInit(false.B)
L
Opt roq  
LinJiawei 已提交
54 55
  when(isEmpty){ hasCsr:= false.B }
  val validDispatch = io.dp1Req.map(_.valid)
W
William Wang 已提交
56
  XSDebug("(ready, valid): ")
Y
Yinan Xu 已提交
57
  for (i <- 0 until RenameWidth) {
L
Opt roq  
LinJiawei 已提交
58 59 60 61
    val offset = PopCount(validDispatch.take(i))
    val roqIdxExt = enqPtrExt + offset
    val roqIdx = roqIdxExt.tail(1)

W
William Wang 已提交
62
    when(io.dp1Req(i).fire()){
L
Opt roq  
LinJiawei 已提交
63 64
      microOp(roqIdx) := io.dp1Req(i).bits
      valid(roqIdx) := true.B
L
linjiawei 已提交
65
      flag(roqIdx) := roqIdxExt.head(1).asBool()
L
Opt roq  
LinJiawei 已提交
66
      writebacked(roqIdx) := false.B
L
LinJiawei 已提交
67
      when(csrEnRoq(i)){ hasCsr := true.B }
W
William Wang 已提交
68
    }
L
Opt roq  
LinJiawei 已提交
69 70
    io.dp1Req(i).ready := (notFull && !valid(roqIdx) && state === s_idle) &&
      (!csrEnRoq(i) || isEmpty) &&
L
LinJiawei 已提交
71
      !hasCsr
L
Opt roq  
LinJiawei 已提交
72
    io.roqIdxs(i) := roqIdxExt
Y
Yinan Xu 已提交
73
    XSDebug(false, true.B, "(%d, %d) ", io.dp1Req(i).ready, io.dp1Req(i).valid)
W
William Wang 已提交
74
  }
Y
Yinan Xu 已提交
75
  XSDebug(false, true.B, "\n")
W
William Wang 已提交
76

L
Opt roq  
LinJiawei 已提交
77 78
  val firedDispatch = Cat(io.dp1Req.map(_.fire()))
  val dispatchCnt = PopCount(firedDispatch)
W
William Wang 已提交
79
  when(firedDispatch.orR){
L
Opt roq  
LinJiawei 已提交
80 81
    enqPtrExt := enqPtrExt + dispatchCnt
    XSInfo("dispatched %d insts\n", dispatchCnt)
W
William Wang 已提交
82 83 84
  }

  // Writeback
L
Opt roq  
LinJiawei 已提交
85
  val firedWriteback = io.exeWbResults.map(_.fire())
86
  XSInfo(PopCount(firedWriteback) > 0.U, "writebacked %d insts\n", PopCount(firedWriteback))
L
LinJiawei 已提交
87
  for(i <- 0 until numWbPorts){
W
William Wang 已提交
88
    when(io.exeWbResults(i).fire()){
L
Opt roq  
LinJiawei 已提交
89 90 91 92 93 94 95 96 97 98 99
      val wbIdxExt = io.exeWbResults(i).bits.uop.roqIdx
      val wbIdx = wbIdxExt.tail(1)
      writebacked(wbIdx) := true.B
      microOp(wbIdx).cf.exceptionVec := io.exeWbResults(i).bits.uop.cf.exceptionVec
      exuData(wbIdx) := io.exeWbResults(i).bits.data
      exuDebug(wbIdx) := io.exeWbResults(i).bits.debug

      val debugUop = microOp(wbIdx)
      XSInfo(true.B, "writebacked pc 0x%x wen %d data 0x%x ldst %d pdst %d skip %x roqIdx: %x\n",
        debugUop.cf.pc,
        debugUop.ctrl.rfWen,
Y
Yinan Xu 已提交
100
        io.exeWbResults(i).bits.data,
L
Opt roq  
LinJiawei 已提交
101
        debugUop.ctrl.ldest,
102
        io.exeWbResults(i).bits.uop.pdest,
L
Opt roq  
LinJiawei 已提交
103 104
        io.exeWbResults(i).bits.debug.isMMIO,
        wbIdxExt
105
      )
W
William Wang 已提交
106 107 108
    }
  }

109
  // roq redirect only used for exception
Y
Yinan Xu 已提交
110 111
  val intrBitSet = WireInit(false.B)
  ExcitingUtils.addSink(intrBitSet, "intrBitSetIDU")
112 113
  val trapTarget = WireInit(0.U(VAddrBits.W))
  ExcitingUtils.addSink(trapTarget, "trapTarget")
L
Opt roq  
LinJiawei 已提交
114 115 116 117 118 119 120 121

  val deqUop = microOp(deqPtr)
  val intrEnable = intrBitSet && (state === s_idle) && !isEmpty && !hasCsr
  val exceptionEnable = Cat(deqUop.cf.exceptionVec).orR() && (state === s_idle) && !isEmpty

  val isEcall = deqUop.cf.exceptionVec(ecallM) ||
    deqUop.cf.exceptionVec(ecallS) ||
    deqUop.cf.exceptionVec(ecallU)
122 123 124 125
  io.redirect := DontCare
  io.redirect.valid := intrEnable || exceptionEnable
  io.redirect.bits.isException := true.B
  io.redirect.bits.target := trapTarget
L
Opt roq  
LinJiawei 已提交
126 127
  io.exception := deqUop
  XSDebug(io.redirect.valid, "generate exception: pc 0x%x target 0x%x exceptionVec %b\n", io.exception.cf.pc, trapTarget, Cat(microOp(deqPtr).cf.exceptionVec))
128

L
Opt roq  
LinJiawei 已提交
129
  // Commit uop to Rename (walk)
W
William Wang 已提交
130
  val shouldWalkVec = Wire(Vec(CommitWidth, Bool()))
L
Opt roq  
LinJiawei 已提交
131 132 133 134 135 136 137 138 139
  val walkPtrMatchVec  = Wire(Vec(CommitWidth, Bool()))
  val walkPtrVec = Wire(Vec(CommitWidth, UInt(RoqIdxWidth.W)))
  for(i <- shouldWalkVec.indices){
    walkPtrVec(i) := walkPtrExt - i.U
    walkPtrMatchVec(i) := walkPtrVec(i) === walkTgtExt
    if(i == 0) shouldWalkVec(i) := !walkPtrMatchVec(i)
    else shouldWalkVec(i) := shouldWalkVec(i-1) && !walkPtrMatchVec(i)
  }
  val walkFinished = Cat(walkPtrMatchVec).orR()
W
William Wang 已提交
140

W
William Wang 已提交
141
  // extra space is used weh roq has no enough space, but mispredict recovery needs such info to walk regmap
L
Opt roq  
LinJiawei 已提交
142 143 144
  val needExtraSpaceForMPR = WireInit(VecInit(
    List.tabulate(RenameWidth)(i => io.brqRedirect.valid && io.dp1Req(i).valid && !io.dp1Req(i).ready)
  ))
W
William Wang 已提交
145 146 147
  val extraSpaceForMPR = Reg(Vec(RenameWidth, new MicroOp))
  val usedSpaceForMPR = Reg(Vec(RenameWidth, Bool()))

L
Opt roq  
LinJiawei 已提交
148 149
  val storeCommitVec = WireInit(VecInit(Seq.fill(CommitWidth)(false.B)))
  val cfiCommitVec = WireInit(VecInit(Seq.fill(CommitWidth)(false.B)))
W
William Wang 已提交
150
  for(i <- 0 until CommitWidth){
W
William Wang 已提交
151 152 153
    io.commits(i) := DontCare
    switch(state){
      is(s_idle){
L
Opt roq  
LinJiawei 已提交
154 155 156
        val commitIdx = deqPtr + i.U
        val commitUop = microOp(commitIdx)
        val hasException = Cat(commitUop.cf.exceptionVec).orR() || intrEnable
W
William Wang 已提交
157
        val canCommit = if(i!=0) io.commits(i-1).valid else true.B
L
Opt roq  
LinJiawei 已提交
158 159 160 161 162 163
        val v = valid(commitIdx)
        val w = writebacked(commitIdx)
        io.commits(i).valid := v && w && canCommit && !hasException
        io.commits(i).bits.uop := commitUop

        storeCommitVec(i) := io.commits(i).valid &&
L
linjiawei 已提交
164
          commitUop.ctrl.fuType===FuType.stu
L
Opt roq  
LinJiawei 已提交
165 166 167 168 169

        cfiCommitVec(i) := io.commits(i).valid &&
          !commitUop.cf.brUpdate.pd.notCFI

        when(io.commits(i).valid){v := false.B}
W
William Wang 已提交
170 171
        XSInfo(io.commits(i).valid,
          "retired pc %x wen %d ldst %d data %x\n",
L
Opt roq  
LinJiawei 已提交
172 173 174 175
          commitUop.cf.pc,
          commitUop.ctrl.rfWen,
          commitUop.ctrl.ldest,
          exuData(commitIdx)
W
William Wang 已提交
176
        )
L
Opt roq  
LinJiawei 已提交
177
        XSInfo(io.commits(i).valid && exuDebug(commitIdx).isMMIO,
W
William Wang 已提交
178
          "difftest skiped pc0x%x\n",
L
Opt roq  
LinJiawei 已提交
179
          commitUop.cf.pc
W
William Wang 已提交
180 181 182 183
        )
      }

      is(s_walk){
L
Opt roq  
LinJiawei 已提交
184 185 186 187 188
        val idx = walkPtrVec(i).tail(1)
        val v = valid(idx)
        val walkUop = microOp(idx)
        io.commits(i).valid := v && shouldWalkVec(i)
        io.commits(i).bits.uop := walkUop
W
William Wang 已提交
189
        when(shouldWalkVec(i)){
L
Opt roq  
LinJiawei 已提交
190
          v := false.B
W
William Wang 已提交
191
        }
L
Opt roq  
LinJiawei 已提交
192 193 194 195 196
        XSInfo(io.commits(i).valid && shouldWalkVec(i), "walked pc %x wen %d ldst %d data %x\n",
          walkUop.cf.pc,
          walkUop.ctrl.rfWen,
          walkUop.ctrl.ldest,
          exuData(idx)
W
William Wang 已提交
197 198 199 200
        )
      }

      is(s_extrawalk){
L
Opt roq  
LinJiawei 已提交
201 202 203 204
        val idx = RenameWidth-i-1
        val walkUop = extraSpaceForMPR(idx)
        io.commits(i).valid := usedSpaceForMPR(idx)
        io.commits(i).bits.uop := walkUop
W
William Wang 已提交
205
        state := s_walk
L
Opt roq  
LinJiawei 已提交
206 207 208 209
        XSInfo(io.commits(i).valid, "use extra space walked pc %x wen %d ldst %d\n",
          walkUop.cf.pc,
          walkUop.ctrl.rfWen,
          walkUop.ctrl.ldest
W
William Wang 已提交
210
        )
211
      }
W
William Wang 已提交
212
    }
W
William Wang 已提交
213
    io.commits(i).bits.isWalk := state =/= s_idle
W
William Wang 已提交
214
  }
W
William Wang 已提交
215

L
Opt roq  
LinJiawei 已提交
216
  val validCommit = io.commits.map(_.valid)
W
William Wang 已提交
217 218 219 220 221
  when(state===s_walk) {
    //exit walk state when all roq entry is commited
    when(walkFinished) {
      state := s_idle
    }
L
Opt roq  
LinJiawei 已提交
222
    walkPtrExt := walkPtrExt - CommitWidth.U
W
William Wang 已提交
223
    // ringBufferWalkExtended := ringBufferWalkExtended - validCommit
L
Opt roq  
LinJiawei 已提交
224
    XSInfo("rolling back: enqPtr %d deqPtr %d walk %d:%d\n", enqPtr, deqPtr, walkPtrExt.head(1), walkPtr)
225
  }
W
William Wang 已提交
226

W
William Wang 已提交
227
  // move tail ptr
L
Opt roq  
LinJiawei 已提交
228
  val commitCnt = PopCount(validCommit)
W
William Wang 已提交
229
  when(state === s_idle){
L
Opt roq  
LinJiawei 已提交
230
    deqPtrExt := deqPtrExt + commitCnt
W
William Wang 已提交
231
  }
L
Opt roq  
LinJiawei 已提交
232
  val retireCounter = Mux(state === s_idle, commitCnt, 0.U)
W
William Wang 已提交
233
  XSInfo(retireCounter > 0.U, "retired %d insts\n", retireCounter)
W
William Wang 已提交
234

L
linjiawei 已提交
235 236
  

L
Opt roq  
LinJiawei 已提交
237
  // commit store to lsu, commit branch to brq
L
linjiawei 已提交
238
  // TODO MMIO
239
  (0 until CommitWidth).map(i => {
L
linjiawei 已提交
240
    io.mcommit(i).valid := storeCommitVec(i)
Y
Yinan Xu 已提交
241
    io.mcommit(i).bits := io.commits(i).bits.uop.lsroqIdx
242
  })
W
William Wang 已提交
243

L
Opt roq  
LinJiawei 已提交
244
  io.bcommit := PopCount(cfiCommitVec)
245

W
William Wang 已提交
246
  // when redirect, walk back roq entries
W
William Wang 已提交
247 248
  when(io.brqRedirect.valid){
    state := s_walk
L
Opt roq  
LinJiawei 已提交
249 250 251
    walkPtrExt := enqPtrExt - 1.U + dispatchCnt
    walkTgtExt := io.brqRedirect.bits.roqIdx
    enqPtrExt := io.brqRedirect.bits.roqIdx + 1.U
W
William Wang 已提交
252
  }
W
William Wang 已提交
253

W
William Wang 已提交
254
  // no enough space for walk, allocate extra space
W
William Wang 已提交
255 256
  when(needExtraSpaceForMPR.asUInt.orR && io.brqRedirect.valid){
    usedSpaceForMPR := needExtraSpaceForMPR
L
Opt roq  
LinJiawei 已提交
257
    (0 until RenameWidth).foreach(i => extraSpaceForMPR(i) := io.dp1Req(i).bits)
W
William Wang 已提交
258 259
    state := s_extrawalk
    XSDebug("roq full, switched to s_extrawalk. needExtraSpaceForMPR: %b\n", needExtraSpaceForMPR.asUInt)
W
William Wang 已提交
260 261
  }

W
William Wang 已提交
262 263 264 265 266 267 268 269 270 271
  // when rollback, reset writebacked entry to valid
  when(io.brqRedirect.valid && io.brqRedirect.bits.isReplay){ // TODO: opt timing
    for (i <- 0 until RoqSize) {
      val recRoqIdx = Cat(flag(i).asUInt, i.U)
      when(valid(i) && io.memRedirect.bits.isAfter(recRoqIdx)){
        writebacked(i) := false.B
      }
    }
  }

272 273
  // when exception occurs, cancels all
  when (io.redirect.valid) {
L
Opt roq  
LinJiawei 已提交
274 275
    enqPtrExt := 0.U
    deqPtrExt := 0.U
Y
Yinan Xu 已提交
276 277 278
    for (i <- 0 until RoqSize) {
      valid(i) := false.B
    }
279
  }
280

W
William Wang 已提交
281
  // debug info
L
Opt roq  
LinJiawei 已提交
282
  XSDebug("enqPtr %d:%d deqPtr %d:%d\n", enqPtrExt.head(1), enqPtr, deqPtrExt.head(1), deqPtr)
W
William Wang 已提交
283
  XSDebug("")
Y
Yinan Xu 已提交
284 285 286 287
  for(i <- 0 until RoqSize){
    XSDebug(false, !valid(i), "-")
    XSDebug(false, valid(i) && writebacked(i), "w")
    XSDebug(false, valid(i) && !writebacked(i), "v")
W
William Wang 已提交
288
  }
Y
Yinan Xu 已提交
289 290 291 292 293 294 295 296 297
  XSDebug(false, true.B, "\n")

  for(i <- 0 until RoqSize){
    if(i % 4 == 0) XSDebug("")
    XSDebug(false, true.B, "%x ", microOp(i).cf.pc)
    XSDebug(false, !valid(i), "- ")
    XSDebug(false, valid(i) && writebacked(i), "w ")
    XSDebug(false, valid(i) && !writebacked(i), "v ")
    if(i % 4 == 3) XSDebug(false, true.B, "\n")
W
William Wang 已提交
298
  }
W
William Wang 已提交
299

300
  //difftest signals
L
Opt roq  
LinJiawei 已提交
301
  val firstValidCommit = deqPtr + PriorityMux(validCommit, VecInit(List.tabulate(CommitWidth)(_.U)))
302

303 304 305 306 307
  val skip = Wire(Vec(CommitWidth, Bool()))
  val wen = Wire(Vec(CommitWidth, Bool()))
  val wdata = Wire(Vec(CommitWidth, UInt(XLEN.W)))
  val wdst = Wire(Vec(CommitWidth, UInt(32.W)))
  val wpc = Wire(Vec(CommitWidth, UInt(VAddrBits.W)))
308
  val trapVec = Wire(Vec(CommitWidth, Bool()))
309
  for(i <- 0 until CommitWidth){
310
    // io.commits(i).valid
L
Opt roq  
LinJiawei 已提交
311 312
    val idx = deqPtr+i.U
    val uop = io.commits(i).bits.uop
313 314 315 316 317 318
    skip(i) := exuDebug(idx).isMMIO && io.commits(i).valid
    wen(i) := io.commits(i).valid && uop.ctrl.rfWen && uop.ctrl.ldest =/= 0.U
    wdata(i) := exuData(idx)
    wdst(i) := uop.ctrl.ldest
    wpc(i) := uop.cf.pc
    trapVec(i) := io.commits(i).valid && (state===s_idle) && uop.ctrl.isXSTrap
319
  }
320 321
  val instrCnt = RegInit(0.U(64.W))
  instrCnt := instrCnt + retireCounter
322

323 324
  val difftestIntrNO = WireInit(0.U(XLEN.W))
  ExcitingUtils.addSink(difftestIntrNO, "difftestIntrNOfromCSR")
Y
Yinan Xu 已提交
325 326
  XSDebug(difftestIntrNO =/= 0.U, "difftest intrNO set %x\n", difftestIntrNO)
  val retireCounterFix = Mux(io.redirect.valid, 1.U, retireCounter)
L
Opt roq  
LinJiawei 已提交
327 328
  val retirePCFix = Mux(io.redirect.valid, microOp(deqPtr).cf.pc, microOp(firstValidCommit).cf.pc)
  val retireInstFix = Mux(io.redirect.valid, microOp(deqPtr).cf.instr, microOp(firstValidCommit).cf.instr)
L
LinJiawei 已提交
329
  if(!env.FPGAPlatform){
Y
Yinan Xu 已提交
330 331 332
    BoringUtils.addSource(RegNext(retireCounterFix), "difftestCommit")
    BoringUtils.addSource(RegNext(retirePCFix), "difftestThisPC")//first valid PC
    BoringUtils.addSource(RegNext(retireInstFix), "difftestThisINST")//first valid inst
333
    BoringUtils.addSource(RegNext(skip.asUInt), "difftestSkip")
W
William Wang 已提交
334
    BoringUtils.addSource(RegNext(false.B), "difftestIsRVC")//FIXIT
335 336 337 338
    BoringUtils.addSource(RegNext(wen.asUInt), "difftestWen")
    BoringUtils.addSource(RegNext(wpc), "difftestWpc")
    BoringUtils.addSource(RegNext(wdata), "difftestWdata")
    BoringUtils.addSource(RegNext(wdst), "difftestWdst")
339
    BoringUtils.addSource(RegNext(difftestIntrNO), "difftestIntrNO")
340

L
LinJiawei 已提交
341 342 343
    val hitTrap = trapVec.reduce(_||_)
    val trapCode = PriorityMux(wdata.zip(trapVec).map(x => x._2 -> x._1))
    val trapPC = PriorityMux(wpc.zip(trapVec).map(x => x._2 ->x._1))
344

345 346 347 348 349
    ExcitingUtils.addSource(RegNext(hitTrap), "trapValid")
    ExcitingUtils.addSource(RegNext(trapCode), "trapCode")
    ExcitingUtils.addSource(RegNext(trapPC), "trapPC")
    ExcitingUtils.addSource(RegNext(GTimer()), "trapCycleCnt")
    ExcitingUtils.addSource(RegNext(instrCnt), "trapInstrCnt")
Z
ZhangZifei 已提交
350

J
jinyue110 已提交
351
    if(EnableBPU){
352
      ExcitingUtils.addSource(hitTrap, "XSTRAP", ConnectionType.Debug)
J
jinyue110 已提交
353
    }
354
  }
355
}