Roq.scala 12.0 KB
Newer Older
1 2 3 4 5
package xiangshan.backend.roq

import chisel3._
import chisel3.util._
import xiangshan._
W
William Wang 已提交
6
import xiangshan.utils._
7
import chisel3.util.experimental.BoringUtils
8
import xiangshan.backend.decode.XSTrap
9

W
William Wang 已提交
10
// A "just-enough" Roq
11
class Roq(implicit val p: XSConfig) extends XSModule {
12 13
  val io = IO(new Bundle() {
    val brqRedirect = Input(Valid(new Redirect))
14
    val dp1Req = Vec(RenameWidth, Flipped(DecoupledIO(new MicroOp)))
W
William Wang 已提交
15
    val roqIdxs = Output(Vec(RenameWidth, UInt(RoqIdxWidth.W)))
16
    val redirect = Output(Valid(new Redirect))
L
LinJiawei 已提交
17
    // exu + brq
L
LinJiawei 已提交
18
    val exeWbResults = Vec(exuParameters.ExuCnt + 1, Flipped(ValidIO(new ExuOutput)))
19
    val commits = Vec(CommitWidth, Valid(new RoqCommit))
W
William Wang 已提交
20
    val scommit = Output(UInt(3.W))
21
  })
W
William Wang 已提交
22

L
LinJiawei 已提交
23 24
  val numWbPorts = io.exeWbResults.length

25
  val microOp = Mem(RoqSize, new MicroOp)
W
William Wang 已提交
26
  // val brMask = Reg(Vec(RoqSize, UInt(BrqSize.W)))
W
William Wang 已提交
27
  val valid = RegInit(VecInit(List.fill(RoqSize)(false.B)))
W
William Wang 已提交
28 29
  val writebacked = Reg(Vec(RoqSize, Bool()))
  val redirect = Reg(Vec(RoqSize, new Redirect))
30 31 32

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

W
William Wang 已提交
34 35 36 37 38 39 40 41 42
  val ringBufferHeadExtended = RegInit(0.U(RoqIdxWidth.W))
  val ringBufferTailExtended = RegInit(0.U(RoqIdxWidth.W))
  val ringBufferWalkExtended = Reg(UInt(RoqIdxWidth.W))
  val ringBufferWalkTarget = Reg(UInt(RoqIdxWidth.W))
  val ringBufferHead = ringBufferHeadExtended(InnerRoqIdxWidth-1,0)
  val ringBufferTail = ringBufferTailExtended(InnerRoqIdxWidth-1,0)
  val ringBufferWalk = ringBufferWalkExtended(InnerRoqIdxWidth-1,0)
  val ringBufferEmpty = ringBufferHead === ringBufferTail && ringBufferHeadExtended(InnerRoqIdxWidth)===ringBufferTailExtended(InnerRoqIdxWidth)
  val ringBufferFull = ringBufferHead === ringBufferTail && ringBufferHeadExtended(InnerRoqIdxWidth)=/=ringBufferTailExtended(InnerRoqIdxWidth)
W
William Wang 已提交
43 44
  val ringBufferAllowin = !ringBufferFull 

W
William Wang 已提交
45
  val s_idle :: s_walk :: s_extrawalk :: Nil = Enum(3)
W
William Wang 已提交
46 47
  val state = RegInit(s_idle)

W
William Wang 已提交
48
  // Dispatch
49
  val validDispatch = VecInit((0 until RenameWidth).map(io.dp1Req(_).valid)).asUInt
W
William Wang 已提交
50
  XSDebug("(ready, valid): ")
Y
Yinan Xu 已提交
51
  for (i <- 0 until RenameWidth) {
52
    val offset = if(i==0) 0.U else PopCount(validDispatch(i-1,0))
W
William Wang 已提交
53
    when(io.dp1Req(i).fire()){
54 55
      microOp(ringBufferHead+offset) := io.dp1Req(i).bits
      valid(ringBufferHead+offset) := true.B
W
William Wang 已提交
56
      writebacked(ringBufferHead+offset) := false.B
W
William Wang 已提交
57
    }
58 59
    io.dp1Req(i).ready := ringBufferAllowin && !valid(ringBufferHead+offset) && state === s_idle
    io.roqIdxs(i) := ringBufferHeadExtended+offset
Y
Yinan Xu 已提交
60
    XSDebug(false, true.B, "(%d, %d) ", io.dp1Req(i).ready, io.dp1Req(i).valid)
W
William Wang 已提交
61
  }
Y
Yinan Xu 已提交
62
  XSDebug(false, true.B, "\n")
W
William Wang 已提交
63

64
  val firedDispatch = VecInit((0 until CommitWidth).map(io.dp1Req(_).fire())).asUInt
W
William Wang 已提交
65 66 67
  when(firedDispatch.orR){
    ringBufferHeadExtended := ringBufferHeadExtended + PopCount(firedDispatch)
    XSInfo("dispatched %d insts\n", PopCount(firedDispatch))
W
William Wang 已提交
68 69 70
  }

  // Writeback
L
LinJiawei 已提交
71
  val firedWriteback = VecInit((0 until numWbPorts).map(io.exeWbResults(_).fire())).asUInt
72
  XSInfo(PopCount(firedWriteback) > 0.U, "writebacked %d insts\n", PopCount(firedWriteback))
L
LinJiawei 已提交
73
  for(i <- 0 until numWbPorts){
W
William Wang 已提交
74
    when(io.exeWbResults(i).fire()){
W
William Wang 已提交
75
      writebacked(io.exeWbResults(i).bits.uop.roqIdx) := true.B
76 77
      exuData(io.exeWbResults(i).bits.uop.roqIdx) := io.exeWbResults(i).bits.data
      exuDebug(io.exeWbResults(i).bits.uop.roqIdx) := io.exeWbResults(i).bits.debug
78
      XSInfo(io.exeWbResults(i).valid, "writebacked pc 0x%x wen %d data 0x%x ldst %d pdst %d skip %x\n", 
79
        microOp(io.exeWbResults(i).bits.uop.roqIdx).cf.pc,
Y
Yinan Xu 已提交
80 81
        microOp(io.exeWbResults(i).bits.uop.roqIdx).ctrl.rfWen,
        io.exeWbResults(i).bits.data,
82 83 84
        microOp(io.exeWbResults(i).bits.uop.roqIdx).ctrl.ldest, 
        io.exeWbResults(i).bits.uop.pdest,
        io.exeWbResults(i).bits.debug.isMMIO
85
      )
W
William Wang 已提交
86 87 88
    }
  }

W
William Wang 已提交
89
  // Commit uop to Rename
W
William Wang 已提交
90
  val shouldWalkVec = Wire(Vec(CommitWidth, Bool()))
W
William Wang 已提交
91 92 93
  shouldWalkVec(0) := ringBufferWalkExtended =/= ringBufferWalkTarget
  (1 until CommitWidth).map(i => shouldWalkVec(i) := (ringBufferWalkExtended - i.U) =/= ringBufferWalkTarget && shouldWalkVec(i - 1))
  val walkFinished = (0 until CommitWidth).map(i => (ringBufferWalkExtended - i.U) === ringBufferWalkTarget).reduce(_||_) //FIXIT!!!!!!
W
William Wang 已提交
94

W
William Wang 已提交
95 96 97 98 99
  // extra space is used weh roq has no enough space, but mispredict recovery needs such info to walk regmap
  val needExtraSpaceForMPR = WireInit(VecInit(List.tabulate(RenameWidth)(i => io.brqRedirect.valid && io.dp1Req(i).valid && !io.dp1Req(i).ready)))
  val extraSpaceForMPR = Reg(Vec(RenameWidth, new MicroOp))
  val usedSpaceForMPR = Reg(Vec(RenameWidth, Bool()))

W
William Wang 已提交
100
  for(i <- 0 until CommitWidth){
W
William Wang 已提交
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
    io.commits(i) := DontCare
    switch(state){
      is(s_idle){
        val canCommit = if(i!=0) io.commits(i-1).valid else true.B
        io.commits(i).valid := valid(ringBufferTail+i.U) && writebacked(ringBufferTail+i.U) && canCommit
        io.commits(i).bits.uop := microOp(ringBufferTail+i.U)
        when(io.commits(i).valid){valid(ringBufferTail+i.U) := false.B}
        XSInfo(io.commits(i).valid,
          "retired pc %x wen %d ldst %d data %x\n",
          microOp(ringBufferTail+i.U).cf.pc,
          microOp(ringBufferTail+i.U).ctrl.rfWen,
          microOp(ringBufferTail+i.U).ctrl.ldest,
          exuData(ringBufferTail+i.U)
        )
        XSInfo(io.commits(i).valid && exuDebug(ringBufferTail+i.U).isMMIO,
          "difftest skiped pc0x%x\n",
          microOp(ringBufferTail+i.U).cf.pc
        )
      }

      is(s_walk){
        io.commits(i).valid := valid(ringBufferWalk-i.U) && shouldWalkVec(i)
        io.commits(i).bits.uop := microOp(ringBufferWalk-i.U)
        when(shouldWalkVec(i)){
          valid(ringBufferWalk-i.U) := false.B
        }
        XSInfo(io.commits(i).valid && shouldWalkVec(i), "walked pc %x wen %d ldst %d data %x\n", 
          microOp(ringBufferWalk-i.U).cf.pc, 
          microOp(ringBufferWalk-i.U).ctrl.rfWen, 
          microOp(ringBufferWalk-i.U).ctrl.ldest, 
          exuData(ringBufferWalk-i.U)
        )
      }

      is(s_extrawalk){
W
William Wang 已提交
136
        io.commits(i).valid := usedSpaceForMPR(RenameWidth-i-1)
W
William Wang 已提交
137 138
        io.commits(i).bits.uop := extraSpaceForMPR(RenameWidth-i-1)
        state := s_walk
W
William Wang 已提交
139 140 141 142
        XSInfo(io.commits(i).valid, "use extra space walked pc %x wen %d ldst %d\n", 
          extraSpaceForMPR((RenameWidth-i-1).U).cf.pc, 
          extraSpaceForMPR((RenameWidth-i-1).U).ctrl.rfWen, 
          extraSpaceForMPR((RenameWidth-i-1).U).ctrl.ldest
W
William Wang 已提交
143
        )
144
      }
W
William Wang 已提交
145
    }
W
William Wang 已提交
146
    io.commits(i).bits.isWalk := state =/= s_idle
W
William Wang 已提交
147
  }
W
William Wang 已提交
148

W
William Wang 已提交
149
  val validCommit = VecInit((0 until CommitWidth).map(i => io.commits(i).valid)).asUInt
W
William Wang 已提交
150 151 152 153 154
  when(state===s_walk) {
    //exit walk state when all roq entry is commited
    when(walkFinished) {
      state := s_idle
    }
155
    ringBufferWalkExtended := ringBufferWalkExtended - CommitWidth.U
W
William Wang 已提交
156 157
    // ringBufferWalkExtended := ringBufferWalkExtended - validCommit
    XSInfo("rolling back: head %d tail %d walk %d:%d\n", ringBufferHead, ringBufferTail, ringBufferWalkExtended(InnerRoqIdxWidth), ringBufferWalk)
158
  }
W
William Wang 已提交
159

W
William Wang 已提交
160
  // move tail ptr
W
William Wang 已提交
161 162 163
  when(state === s_idle){
    ringBufferTailExtended := ringBufferTailExtended + PopCount(validCommit)
  }
164
  val retireCounter = Mux(state === s_idle, PopCount(validCommit), 0.U)
W
William Wang 已提交
165

W
William Wang 已提交
166
  XSInfo(retireCounter > 0.U, "retired %d insts\n", retireCounter)
W
William Wang 已提交
167

W
William Wang 已提交
168
  // commit store to lsu
W
William Wang 已提交
169
  val validScommit = WireInit(VecInit((0 until CommitWidth).map(i => state === s_idle && io.commits(i).valid && microOp(ringBufferTail+i.U).ctrl.fuType === FuType.stu && microOp(ringBufferTail+i.U).ctrl.fuOpType(3)))) //FIXIT
W
William Wang 已提交
170
  io.scommit := PopCount(validScommit.asUInt)
W
William Wang 已提交
171

W
William Wang 已提交
172
  // when redirect, walk back roq entries
W
William Wang 已提交
173 174
  when(io.brqRedirect.valid){
    state := s_walk
Y
Yinan Xu 已提交
175
    ringBufferWalkExtended := ringBufferHeadExtended - 1.U + PopCount(firedDispatch)
176 177
    ringBufferWalkTarget := io.brqRedirect.bits.roqIdx
    ringBufferHeadExtended := io.brqRedirect.bits.roqIdx + 1.U
W
William Wang 已提交
178
  }
W
William Wang 已提交
179

W
William Wang 已提交
180
  // no enough space for walk, allocate extra space
W
William Wang 已提交
181 182 183 184 185
  when(needExtraSpaceForMPR.asUInt.orR && io.brqRedirect.valid){
    usedSpaceForMPR := needExtraSpaceForMPR
    (0 until RenameWidth).map(i => extraSpaceForMPR(i) := io.dp1Req(i).bits)
    state := s_extrawalk
    XSDebug("roq full, switched to s_extrawalk. needExtraSpaceForMPR: %b\n", needExtraSpaceForMPR.asUInt)
W
William Wang 已提交
186 187
  }

W
William Wang 已提交
188 189 190
  // roq redirect only used for exception
  io.redirect := DontCare //TODO
  io.redirect.valid := false.B //TODO
191

W
William Wang 已提交
192
  // debug info
W
William Wang 已提交
193
  XSDebug("head %d:%d tail %d:%d\n", ringBufferHeadExtended(InnerRoqIdxWidth), ringBufferHead, ringBufferTailExtended(InnerRoqIdxWidth), ringBufferTail)
W
William Wang 已提交
194
  XSDebug("")
Y
Yinan Xu 已提交
195 196 197 198
  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 已提交
199
  }
Y
Yinan Xu 已提交
200 201 202 203 204 205 206 207 208
  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 已提交
209
  }
W
William Wang 已提交
210

211 212 213 214
  //difftest signals
  val firstValidCommit = ringBufferTail + PriorityMux(validCommit, VecInit(List.tabulate(CommitWidth)(_.U)))
  val emptyCsr = WireInit(0.U(64.W))

215 216 217 218 219
  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)))
220
  val trapVec = Wire(Vec(CommitWidth, Bool()))
221
  for(i <- 0 until CommitWidth){
222 223 224 225 226 227 228 229 230
    // io.commits(i).valid
    val idx = ringBufferTail+i.U
    val uop = microOp(idx)
    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
231
  }
232 233 234 235 236
  val instrCnt = RegInit(0.U(64.W))
  instrCnt := instrCnt + retireCounter
  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))
237

238
  if(!p.FPGAPlatform){
W
William Wang 已提交
239 240 241
    BoringUtils.addSource(RegNext(retireCounter), "difftestCommit")
    BoringUtils.addSource(RegNext(microOp(firstValidCommit).cf.pc), "difftestThisPC")//first valid PC
    BoringUtils.addSource(RegNext(microOp(firstValidCommit).cf.instr), "difftestThisINST")//first valid inst
242
    BoringUtils.addSource(RegNext(skip.asUInt), "difftestSkip")
W
William Wang 已提交
243
    BoringUtils.addSource(RegNext(false.B), "difftestIsRVC")//FIXIT
244 245 246 247
    BoringUtils.addSource(RegNext(wen.asUInt), "difftestWen")
    BoringUtils.addSource(RegNext(wpc), "difftestWpc")
    BoringUtils.addSource(RegNext(wdata), "difftestWdata")
    BoringUtils.addSource(RegNext(wdst), "difftestWdst")
W
William Wang 已提交
248
    BoringUtils.addSource(RegNext(0.U), "difftestIntrNO")
249 250 251 252 253 254 255 256 257 258 259
    //TODO: skip insts that commited in the same cycle ahead of exception

    //csr debug signals
    val ModeM = WireInit(0x3.U)
    BoringUtils.addSource(ModeM, "difftestMode")
    BoringUtils.addSource(emptyCsr, "difftestMstatus")
    BoringUtils.addSource(emptyCsr, "difftestSstatus") 
    BoringUtils.addSource(emptyCsr, "difftestMepc")
    BoringUtils.addSource(emptyCsr, "difftestSepc")
    BoringUtils.addSource(emptyCsr, "difftestMcause")
    BoringUtils.addSource(emptyCsr, "difftestScause")
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280

    class Monitor extends BlackBox {
      val io = IO(new Bundle {
        val clk = Input(Clock())
        val reset = Input(Reset())
        val isNoopTrap = Input(Bool())
        val trapCode = Input(UInt(32.W))
        val trapPC = Input(UInt(64.W))
        val cycleCnt = Input(UInt(64.W))
        val instrCnt = Input(UInt(64.W))
      })
    }

    val debugMonitor =  Module(new Monitor)
    debugMonitor.io.clk := this.clock
    debugMonitor.io.reset := this.reset
    debugMonitor.io.isNoopTrap := hitTrap
    debugMonitor.io.trapCode := trapCode
    debugMonitor.io.trapPC := trapPC
    debugMonitor.io.cycleCnt := GTimer()
    debugMonitor.io.instrCnt := instrCnt
Z
ZhangZifei 已提交
281 282 283

    // BPU temp Perf Cnt
    BoringUtils.addSource(hitTrap, "XSTRAP_BPU")
284
  }
285
}