Roq.scala 9.8 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
      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 91
  val shouldWalkVec = Wire(Vec(CommitWidth, Bool()))
  shouldWalkVec(0) := ringBufferWalk =/= ringBufferWalkTarget
92 93
  (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 已提交
94

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

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

W
William Wang 已提交
140
  // move tail ptr
W
William Wang 已提交
141 142 143 144
  val validCommit = VecInit((0 until CommitWidth).map(i => io.commits(i).valid)).asUInt
  when(state === s_idle){
    ringBufferTailExtended := ringBufferTailExtended + PopCount(validCommit)
  }
145
  val retireCounter = Mux(state === s_idle, PopCount(validCommit), 0.U)
W
William Wang 已提交
146

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

W
William Wang 已提交
149 150 151
  // 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 已提交
152

W
William Wang 已提交
153
  // when redirect, walk back roq entries
W
William Wang 已提交
154 155
  when(io.brqRedirect.valid){
    state := s_walk
156 157 158
    ringBufferWalkExtended := ringBufferHeadExtended - 1.U
    ringBufferWalkTarget := io.brqRedirect.bits.roqIdx
    ringBufferHeadExtended := io.brqRedirect.bits.roqIdx + 1.U
W
William Wang 已提交
159
  }
W
William Wang 已提交
160

W
William Wang 已提交
161 162 163
  // roq redirect only used for exception
  io.redirect := DontCare //TODO
  io.redirect.valid := false.B //TODO
164

W
William Wang 已提交
165 166 167 168 169 170 171 172 173 174 175
  // 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 已提交
176 177 178 179 180 181 182 183 184 185 186
  
  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 已提交
187

188 189 190 191
  //difftest signals
  val firstValidCommit = ringBufferTail + PriorityMux(validCommit, VecInit(List.tabulate(CommitWidth)(_.U)))
  val emptyCsr = WireInit(0.U(64.W))

192 193 194 195 196 197 198 199 200 201 202 203 204 205
  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
  }

206
  if(!p.FPGAPlatform){
W
William Wang 已提交
207 208 209 210
    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
211
    BoringUtils.addSource(RegNext(skip.asUInt), "difftestSkip")
W
William Wang 已提交
212
    BoringUtils.addSource(RegNext(false.B), "difftestIsRVC")//FIXIT
213 214 215 216
    BoringUtils.addSource(RegNext(wen.asUInt), "difftestWen")
    BoringUtils.addSource(RegNext(wpc), "difftestWpc")
    BoringUtils.addSource(RegNext(wdata), "difftestWdata")
    BoringUtils.addSource(RegNext(wdst), "difftestWdst")
W
William Wang 已提交
217
    BoringUtils.addSource(RegNext(0.U), "difftestIntrNO")
218 219 220 221 222 223 224 225 226 227 228 229
    //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")
  }
230
}