Roq.scala 9.5 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

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

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

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

  val exuData = Reg(Vec(RoqSize, UInt(XLEN.W)))//for debug
  val exuDebug = Reg(Vec(RoqSize, new DebugBundle))//for debug
W
William Wang 已提交
32
  val archRF = RegInit(VecInit(List.fill(64)(0.U(32.W))))//for debug, fp regs included
W
William Wang 已提交
33 34 35

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

W
William Wang 已提交
45 46 47
  val s_idle :: s_walk :: Nil = Enum(2)
  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): ")
W
William Wang 已提交
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
W
William Wang 已提交
60
    XSDebug(){printf("(%d, %d) ", io.dp1Req(i).ready, io.dp1Req(i).valid)}
W
William Wang 已提交
61
  }
W
William Wang 已提交
62 63
  XSDebug(){printf("\n")}

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 79 80 81 82
      XSInfo(io.exeWbResults(i).valid, "writebacked pc 0x%x wen %d data 0x%x\n", 
        microOp(io.exeWbResults(i).bits.uop.roqIdx).cf.pc,
        microOp(io.exeWbResults(i).bits.uop.roqIdx).ctrl.rfWen, 
        io.exeWbResults(i).bits.data
      )
W
William Wang 已提交
83 84 85
    }
  }

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

W
William Wang 已提交
92 93
  for(i <- 0 until CommitWidth){
    when(state === s_idle){
W
William Wang 已提交
94 95
      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
W
William Wang 已提交
96
      io.commits(i).bits.uop := microOp(ringBufferTail+i.U)
97 98 99
      when(io.commits(i).valid && microOp(ringBufferTail+i.U).ctrl.rfWen && microOp(ringBufferTail+i.U).ctrl.ldest =/= 0.U){ 
        archRF(microOp(ringBufferTail+i.U).ctrl.ldest) := exuData(ringBufferTail+i.U) 
      } // for difftest
W
William Wang 已提交
100
      when(io.commits(i).valid){valid(ringBufferTail+i.U) := false.B}
L
LinJiawei 已提交
101 102 103 104 105 106 107 108 109 110 111
      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
      )
W
William Wang 已提交
112
    }.otherwise{//state === s_walk
W
William Wang 已提交
113
      io.commits(i).valid := valid(ringBufferWalk+i.U) && shouldWalkVec(i)
W
William Wang 已提交
114
      io.commits(i).bits.uop := microOp(ringBufferWalk+i.U)
115 116 117
      when(shouldWalkVec(i)){
        valid(ringBufferWalk+i.U) := false.B
      }
W
William Wang 已提交
118
      XSInfo(io.commits(i).valid && shouldWalkVec(i), "walked 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))
W
William Wang 已提交
119 120 121
    }
    io.commits(i).bits.isWalk := state === s_walk
  }
W
William Wang 已提交
122 123 124 125 126 127 128 129

  when(state===s_walk) {
    //exit walk state when all roq entry is commited
    when(walkFinished) {
      state := s_idle
    }
    ringBufferWalkExtended := ringBufferWalkExtended + CommitWidth.U
    XSInfo("rolling back: head %d tail %d walk %d\n", ringBufferHead, ringBufferTail, ringBufferWalk)
130
  }
W
William Wang 已提交
131

W
William Wang 已提交
132
  // move tail ptr
W
William Wang 已提交
133 134 135 136
  val validCommit = VecInit((0 until CommitWidth).map(i => io.commits(i).valid)).asUInt
  when(state === s_idle){
    ringBufferTailExtended := ringBufferTailExtended + PopCount(validCommit)
  }
137
  val retireCounter = Mux(state === s_idle, PopCount(validCommit), 0.U)
W
William Wang 已提交
138

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

W
William Wang 已提交
141 142 143
  // commit store to lsu
  val validScommit = WireInit(VecInit((0 until CommitWidth).map(i => io.commits(i).valid && microOp(ringBufferTail+i.U).ctrl.fuType === FuType.ldu && microOp(ringBufferTail+i.U).ctrl.fuOpType(3)))) //FIXIT
  io.scommit := PopCount(validScommit.asUInt)
W
William Wang 已提交
144

W
William Wang 已提交
145
  // when redirect, walk back roq entries
W
William Wang 已提交
146
  val newHead = io.brqRedirect.bits.roqIdx + 1.U
W
William Wang 已提交
147 148
  when(io.brqRedirect.valid){
    state := s_walk
W
William Wang 已提交
149
    ringBufferWalkExtended := newHead
W
William Wang 已提交
150
    ringBufferWalkTarget := ringBufferHeadExtended
W
William Wang 已提交
151
    ringBufferHeadExtended := newHead
W
William Wang 已提交
152
  }
W
William Wang 已提交
153

W
William Wang 已提交
154 155 156
  // roq redirect only used for exception
  io.redirect := DontCare //TODO
  io.redirect.valid := false.B //TODO
157

W
William Wang 已提交
158 159 160 161 162 163 164 165 166 167 168
  // debug info
  XSDebug("head %d tail %d\n", ringBufferHead, ringBufferTail)
  XSDebug("")
  XSDebug(){
    for(i <- 0 until RoqSize){
      when(!valid(i)){printf("-")}
      when(valid(i) && writebacked(i)){printf("w")}
      when(valid(i) && !writebacked(i)){printf("v")}
    }
    printf("\n")
  }
W
William Wang 已提交
169 170 171 172 173 174 175 176 177 178 179
  
  XSDebug(){
    for(i <- 0 until RoqSize){
      if(i % 4 == 0) XSDebug("")
      printf("%x ", microOp(i).cf.pc)
      when(!valid(i)){printf("- ")}
      when(valid(i) && writebacked(i)){printf("w ")}
      when(valid(i) && !writebacked(i)){printf("v ")}
      if(i % 4 == 3) printf("\n")
    }
  }
W
William Wang 已提交
180

181 182 183 184
  //difftest signals
  val firstValidCommit = ringBufferTail + PriorityMux(validCommit, VecInit(List.tabulate(CommitWidth)(_.U)))
  val emptyCsr = WireInit(0.U(64.W))

185 186 187 188 189 190 191 192 193 194 195 196 197 198
  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)))
  for(i <- 0 until CommitWidth){
      // io.commits(i).valid
      skip(i) := exuDebug(ringBufferTail+i.U).isMMIO && io.commits(i).valid
      wen(i) := io.commits(i).valid && microOp(ringBufferTail+i.U).ctrl.rfWen && microOp(ringBufferTail+i.U).ctrl.ldest =/= 0.U
      wdata(i) := exuData(ringBufferTail+i.U)
      wdst(i) := microOp(ringBufferTail+i.U).ctrl.ldest
      wpc(i) := microOp(ringBufferTail+i.U).cf.pc
  }

199
  if(!p.FPGAPlatform){
W
William Wang 已提交
200 201 202 203
    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
    BoringUtils.addSource(archRF, "difftestRegs")//arch RegFile
204
    BoringUtils.addSource(RegNext(skip.asUInt), "difftestSkip")
W
William Wang 已提交
205
    BoringUtils.addSource(RegNext(false.B), "difftestIsRVC")//FIXIT
206 207 208 209
    BoringUtils.addSource(RegNext(wen.asUInt), "difftestWen")
    BoringUtils.addSource(RegNext(wpc), "difftestWpc")
    BoringUtils.addSource(RegNext(wdata), "difftestWdata")
    BoringUtils.addSource(RegNext(wdst), "difftestWdst")
W
William Wang 已提交
210
    BoringUtils.addSource(RegNext(0.U), "difftestIntrNO")
211 212 213 214 215 216 217 218 219 220 221 222
    //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")
  }
223
}