Roq.scala 7.7 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))
W
William Wang 已提交
16
    val exeWbResults = Vec(exuConfig.ExuCnt, Flipped(ValidIO(new ExuOutput)))
17
    val commits = Vec(CommitWidth, Valid(new RoqCommit))
W
William Wang 已提交
18
    val scommit = Output(UInt(3.W))
19
  })
W
William Wang 已提交
20

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

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

  val ringBufferHeadExtended = RegInit(0.U(ExtendedRoqIdxWidth.W))
  val ringBufferTailExtended = RegInit(0.U(ExtendedRoqIdxWidth.W))
W
William Wang 已提交
33 34 35 36 37 38 39
  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 已提交
40 41
  val ringBufferAllowin = !ringBufferFull 

W
William Wang 已提交
42 43 44
  val s_idle :: s_walk :: Nil = Enum(2)
  val state = RegInit(s_idle)

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

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

  // Writeback
  for(i <- 0 until exuConfig.ExuCnt){
W
William Wang 已提交
69
    when(io.exeWbResults(i).fire()){
W
William Wang 已提交
70
      writebacked(io.exeWbResults(i).bits.uop.roqIdx) := true.B
71 72
      exuData(io.exeWbResults(i).bits.uop.roqIdx) := io.exeWbResults(i).bits.data
      exuDebug(io.exeWbResults(i).bits.uop.roqIdx) := io.exeWbResults(i).bits.debug
W
William Wang 已提交
73 74
    }
  }
W
William Wang 已提交
75 76 77 78
  val firedWriteback = VecInit((0 until exuConfig.ExuCnt).map(io.exeWbResults(_).fire())).asUInt
  when(PopCount(firedWriteback) > 0.U){
    XSInfo("writebacked %d insts\n", PopCount(firedWriteback))
  }
79 80 81
  for(i <- 0 until exuConfig.ExuCnt){
    XSInfo("writebacked pc %x wen %d data %d\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 已提交
82

W
William Wang 已提交
83 84 85
  // Commit uop to Rename
  for(i <- 0 until CommitWidth){
    when(state === s_idle){
W
William Wang 已提交
86 87
      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 已提交
88
      io.commits(i).bits.uop := microOp(ringBufferTail+i.U)
89
      when(microOp(ringBufferTail+i.U).ctrl.rfWen){ archRF(microOp(ringBufferTail+i.U).ctrl.ldest) := exuData(ringBufferTail+i.U) }
W
William Wang 已提交
90
      when(io.commits(i).valid){valid(ringBufferTail+i.U) := false.B}
W
William Wang 已提交
91 92 93 94 95 96 97 98 99 100 101 102
    }.otherwise{//state === s_walk
      io.commits(i).valid := valid(ringBufferWalk+i.U) && writebacked(ringBufferWalk+i.U)
      io.commits(i).bits.uop := microOp(ringBufferWalk+i.U)
      valid(ringBufferWalk+i.U) := false.B
    }
    io.commits(i).bits.isWalk := state === s_walk
  }

  val validCommit = VecInit((0 until CommitWidth).map(i => io.commits(i).valid)).asUInt
  when(state === s_idle){
    ringBufferTailExtended := ringBufferTailExtended + PopCount(validCommit)
  }
103
  val retireCounter = Mux(state === s_idle, PopCount(validCommit), 0.U)
W
William Wang 已提交
104 105 106 107 108

  // commit store
  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 已提交
109
  XSInfo(retireCounter > 0.U, "retired %d insts\n", retireCounter)
W
William Wang 已提交
110 111 112 113 114 115 116 117
  XSInfo("")
  XSInfo(){
    printf("retired pcs are: ")
    for(i <- 0 until CommitWidth){
      when(io.commits(i).valid){ printf("%d:0x%x ", ringBufferTail+i.U, microOp(ringBufferTail+i.U).cf.pc) }
    }
    printf("\n")
  }
W
William Wang 已提交
118 119 120 121 122 123 124 125 126

  val walkFinished = (0 until CommitWidth).map(i => (ringBufferWalk + i.U) === ringBufferWalkTarget).reduce(_||_)

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

W
William Wang 已提交
130 131 132 133 134 135
  when(io.brqRedirect.valid){
    state := s_walk
    ringBufferWalkExtended := io.brqRedirect.bits.roqIdx
    ringBufferWalkTarget := ringBufferHeadExtended
    ringBufferHeadExtended := io.brqRedirect.bits.roqIdx
  }
W
William Wang 已提交
136

W
William Wang 已提交
137 138 139
  // roq redirect only used for exception
  io.redirect := DontCare //TODO
  io.redirect.valid := false.B //TODO
140

W
William Wang 已提交
141 142 143 144 145 146 147 148 149 150 151
  // 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 已提交
152 153 154 155 156 157 158 159 160 161 162
  
  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 已提交
163

164 165 166 167 168
  //difftest signals
  val firstValidCommit = ringBufferTail + PriorityMux(validCommit, VecInit(List.tabulate(CommitWidth)(_.U)))
  val emptyCsr = WireInit(0.U(64.W))

  if(!p.FPGAPlatform){
W
William Wang 已提交
169 170 171 172 173 174 175
    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
    BoringUtils.addSource(RegNext(false.B), "difftestSkip")//SKIP
    BoringUtils.addSource(RegNext(false.B), "difftestIsRVC")//FIXIT
    BoringUtils.addSource(RegNext(0.U), "difftestIntrNO")
176 177 178 179 180 181 182 183 184 185 186 187
    //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")
  }
188
}