xref: /XiangShan/src/main/scala/xiangshan/backend/rob/Rab.scala (revision a8db15d829fbeffc63c1e3101725a2131cedc087)
1*a8db15d8Sfdypackage xiangshan.backend.rob
2*a8db15d8Sfdy
3*a8db15d8Sfdyimport chipsalliance.rocketchip.config.Parameters
4*a8db15d8Sfdyimport chisel3._
5*a8db15d8Sfdyimport chisel3.util._
6*a8db15d8Sfdyimport xiangshan._
7*a8db15d8Sfdyimport utils._
8*a8db15d8Sfdyimport utility._
9*a8db15d8Sfdyimport xiangshan.backend.Bundles.DynInst
10*a8db15d8Sfdyimport xiangshan.backend.decode.VectorConstants
11*a8db15d8Sfdy
12*a8db15d8Sfdyclass RenameBuffer(size: Int)(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelper {
13*a8db15d8Sfdy  val io = IO(new Bundle {
14*a8db15d8Sfdy    val redirectValid = Input(Bool())
15*a8db15d8Sfdy
16*a8db15d8Sfdy    val req = Vec(RenameWidth, Flipped(ValidIO(new DynInst)))
17*a8db15d8Sfdy    val canEnq = Output(Bool())
18*a8db15d8Sfdy
19*a8db15d8Sfdy    val walkSize = Input(UInt(log2Up(size).W))
20*a8db15d8Sfdy    val robWalkEnd = Input(Bool())
21*a8db15d8Sfdy    val commitSize = Input(UInt(log2Up(size).W))
22*a8db15d8Sfdy    val rabWalkEnd = Output(Bool())
23*a8db15d8Sfdy
24*a8db15d8Sfdy    val vconfigPdest = Output(UInt(PhyRegIdxWidth.W))
25*a8db15d8Sfdy
26*a8db15d8Sfdy    val commits = Output(new RobCommitIO)
27*a8db15d8Sfdy    val diffCommits = Output(new DiffCommitIO)
28*a8db15d8Sfdy  })
29*a8db15d8Sfdy
30*a8db15d8Sfdy  val VEC_VCONFIG = VecLogicRegs - 1
31*a8db15d8Sfdy
32*a8db15d8Sfdy  class RenameBufferPtr extends CircularQueuePtr[RenameBufferPtr](size)
33*a8db15d8Sfdy
34*a8db15d8Sfdy  object RenameBufferPtr {
35*a8db15d8Sfdy    def apply(f: Boolean, v: Int): RenameBufferPtr = {
36*a8db15d8Sfdy      val ptr = Wire(new RenameBufferPtr)
37*a8db15d8Sfdy      ptr.flag := f.B
38*a8db15d8Sfdy      ptr.value := v.U
39*a8db15d8Sfdy      ptr
40*a8db15d8Sfdy    }
41*a8db15d8Sfdy  }
42*a8db15d8Sfdy
43*a8db15d8Sfdy  val s_idle :: s_walk :: s_cancel :: Nil = Enum(3)
44*a8db15d8Sfdy  val state = RegInit(s_idle)
45*a8db15d8Sfdy  val stateNxt = WireInit(s_idle)
46*a8db15d8Sfdy
47*a8db15d8Sfdy  val robWalkEnd = RegInit(false.B)
48*a8db15d8Sfdy
49*a8db15d8Sfdy  when(io.redirectValid){
50*a8db15d8Sfdy    robWalkEnd := false.B
51*a8db15d8Sfdy  }.elsewhen(io.robWalkEnd){
52*a8db15d8Sfdy    robWalkEnd := true.B
53*a8db15d8Sfdy  }
54*a8db15d8Sfdy
55*a8db15d8Sfdy  val renameBuffer = RegInit(VecInit(Seq.fill(size){0.U.asTypeOf(new RobCommitInfo)}))
56*a8db15d8Sfdy
57*a8db15d8Sfdy  // pointer
58*a8db15d8Sfdy  // tail: enq and walk
59*a8db15d8Sfdy  // head: commit to arch rat
60*a8db15d8Sfdy  // diff: commit to diff rat
61*a8db15d8Sfdy  val headPtr = RegInit(RenameBufferPtr(false, 0))
62*a8db15d8Sfdy  val headPtrOH = RegInit(1.U(size.W))
63*a8db15d8Sfdy  XSError(headPtr.toOH =/= headPtrOH, p"wrong one-hot reg between $headPtr and $headPtrOH")
64*a8db15d8Sfdy  val headPtrOHShift = CircularShift(headPtrOH)
65*a8db15d8Sfdy  // may shift [0, CommitWidth] steps
66*a8db15d8Sfdy  val headPtrOHVec = VecInit.tabulate(CommitWidth + 1)(headPtrOHShift.left)
67*a8db15d8Sfdy  val headPtrOHVec2 = VecInit.tabulate(CommitWidth * MaxUopSize + 1)(headPtrOHShift.left)
68*a8db15d8Sfdy
69*a8db15d8Sfdy  val vcfgPtrOH = RegInit(1.U(size.W))
70*a8db15d8Sfdy  val vcfgPtrOHShift = CircularShift(vcfgPtrOH)
71*a8db15d8Sfdy  // may shift [0, 2) steps
72*a8db15d8Sfdy  val vcfgPtrOHVec = VecInit.tabulate(2)(vcfgPtrOHShift.left)
73*a8db15d8Sfdy
74*a8db15d8Sfdy  val diffPtrOH = RegInit(1.U(size.W))
75*a8db15d8Sfdy  val diffPtrOHShift = CircularShift(diffPtrOH)
76*a8db15d8Sfdy  // may shift [0, CommitWidth * MaxUopSize] steps
77*a8db15d8Sfdy  val diffPtrOHVec = VecInit.tabulate(CommitWidth * MaxUopSize + 1)(diffPtrOHShift.left)
78*a8db15d8Sfdy
79*a8db15d8Sfdy  val tailPtr = RegInit(RenameBufferPtr(false, 0))
80*a8db15d8Sfdy  val tailPtrOH = RegInit(1.U(size.W))
81*a8db15d8Sfdy  val tailPtrOHShift = CircularShift(tailPtrOH)
82*a8db15d8Sfdy  // may shift [0, RenameWidth] steps
83*a8db15d8Sfdy  val tailPtrOHVec = VecInit.tabulate(RenameWidth + 1)(tailPtrOHShift.left)
84*a8db15d8Sfdy  val tailPtrVec = RegInit(VecInit.tabulate(RenameWidth)(_.U.asTypeOf(new RenameBufferPtr)))
85*a8db15d8Sfdy
86*a8db15d8Sfdy  val realNeedAlloc = io.req.map(req => req.valid && req.bits.needWriteRf)
87*a8db15d8Sfdy  val enqCount    = PopCount(realNeedAlloc)
88*a8db15d8Sfdy  val commitCount = PopCount(io.commits.commitValid)
89*a8db15d8Sfdy  val walkCount   = PopCount(io.commits.walkValid)
90*a8db15d8Sfdy
91*a8db15d8Sfdy  // number of pair(ldest, pdest) ready to commit to arch_rat
92*a8db15d8Sfdy  val commitSize = RegInit(0.U(log2Up(size).W))
93*a8db15d8Sfdy  val commitSizeNxt = Mux(state === s_idle, commitSize - Mux(io.commits.isCommit, commitCount, 0.U) + io.commitSize, commitSize)
94*a8db15d8Sfdy  commitSize := commitSizeNxt
95*a8db15d8Sfdy  val walkSize = RegInit(0.U(log2Up(size).W))
96*a8db15d8Sfdy  val walkSizeNxt = walkSize + io.walkSize - walkCount
97*a8db15d8Sfdy  walkSize := Mux(io.redirectValid, commitSizeNxt, walkSizeNxt)
98*a8db15d8Sfdy
99*a8db15d8Sfdy  val rabWalkEnd = robWalkEnd === true.B && walkSizeNxt === 0.U
100*a8db15d8Sfdy
101*a8db15d8Sfdy  val walkCandidates   = VecInit(tailPtrOHVec.map(sel => Mux1H(sel, renameBuffer)))
102*a8db15d8Sfdy  val commitCandidates = VecInit(headPtrOHVec.map(sel => Mux1H(sel, renameBuffer)))
103*a8db15d8Sfdy  val vcfgCandidates   = VecInit(vcfgPtrOHVec.map(sel => Mux1H(sel, renameBuffer)))
104*a8db15d8Sfdy  val diffCandidates   = VecInit(diffPtrOHVec.map(sel => Mux1H(sel, renameBuffer)))
105*a8db15d8Sfdy
106*a8db15d8Sfdy  // update head pointer
107*a8db15d8Sfdy  val headPtrNext =  headPtr + commitCount
108*a8db15d8Sfdy  val headPtrOHNext = headPtrOHVec(commitCount)
109*a8db15d8Sfdy  headPtr := headPtrNext
110*a8db15d8Sfdy  headPtrOH := headPtrOHNext
111*a8db15d8Sfdy  // update diff pointer
112*a8db15d8Sfdy  val diffPtrOHNext = Mux(state === s_idle, diffPtrOHVec(io.commitSize), diffPtrOH)
113*a8db15d8Sfdy  diffPtrOH := diffPtrOHNext
114*a8db15d8Sfdy  // update vcfg pointer
115*a8db15d8Sfdy  vcfgPtrOH := diffPtrOHNext
116*a8db15d8Sfdy  // update tail pointer
117*a8db15d8Sfdy  val tailPtrEnqNext = tailPtr + PopCount(realNeedAlloc)
118*a8db15d8Sfdy  val tailPtrWalkNext = tailPtr + walkCount
119*a8db15d8Sfdy  val tailPtrNext = Mux(io.redirectValid, headPtrNext,
120*a8db15d8Sfdy    Mux(io.commits.isWalk, tailPtrWalkNext, tailPtrEnqNext))
121*a8db15d8Sfdy  val tailPtrOHNext = Mux(io.redirectValid, headPtrOHVec2(commitCount),
122*a8db15d8Sfdy    Mux(io.commits.isWalk, tailPtrOHVec(walkCount), tailPtrOHVec(PopCount(realNeedAlloc))))
123*a8db15d8Sfdy  tailPtr := tailPtrNext
124*a8db15d8Sfdy  tailPtrOH := tailPtrOHNext
125*a8db15d8Sfdy  tailPtrVec.zipWithIndex.map{ case(ptr, i) => ptr := tailPtrNext + i.U}
126*a8db15d8Sfdy
127*a8db15d8Sfdy  val allocatePtrVec = VecInit((0 until RenameWidth).map(i => tailPtrVec(PopCount(realNeedAlloc.take(i))).value))
128*a8db15d8Sfdy  allocatePtrVec.zip(io.req).zip(realNeedAlloc).map{ case((allocatePtr, req), realNeedAlloc) =>
129*a8db15d8Sfdy    when(realNeedAlloc){
130*a8db15d8Sfdy      renameBuffer(allocatePtr).ldest := req.bits.ldest
131*a8db15d8Sfdy      renameBuffer(allocatePtr).pdest := req.bits.pdest
132*a8db15d8Sfdy      renameBuffer(allocatePtr).old_pdest := req.bits.oldPdest
133*a8db15d8Sfdy      renameBuffer(allocatePtr).rfWen := req.bits.rfWen
134*a8db15d8Sfdy      renameBuffer(allocatePtr).fpWen := req.bits.fpWen
135*a8db15d8Sfdy      renameBuffer(allocatePtr).vecWen := req.bits.vecWen
136*a8db15d8Sfdy      renameBuffer(allocatePtr).isMove := req.bits.eliminatedMove
137*a8db15d8Sfdy    }
138*a8db15d8Sfdy  }
139*a8db15d8Sfdy
140*a8db15d8Sfdy  io.commits.isCommit := state === s_idle
141*a8db15d8Sfdy  io.commits.isWalk := state === s_walk
142*a8db15d8Sfdy
143*a8db15d8Sfdy  for(i <- 0 until CommitWidth) {
144*a8db15d8Sfdy    io.commits.commitValid(i) := state === s_idle && i.U < commitSize
145*a8db15d8Sfdy    io.commits.walkValid(i) := state === s_walk && i.U < walkSize
146*a8db15d8Sfdy    io.commits.info(i) := Mux(state === s_idle, commitCandidates(i), walkCandidates(i))
147*a8db15d8Sfdy  }
148*a8db15d8Sfdy
149*a8db15d8Sfdy  stateNxt := Mux(io.redirectValid, s_walk,
150*a8db15d8Sfdy    Mux(state === s_walk && rabWalkEnd, s_idle, state))
151*a8db15d8Sfdy  state := stateNxt
152*a8db15d8Sfdy
153*a8db15d8Sfdy  io.rabWalkEnd := state === s_walk && rabWalkEnd
154*a8db15d8Sfdy
155*a8db15d8Sfdy  val allowEnqueue = RegInit(true.B)
156*a8db15d8Sfdy  val numValidEntries = distanceBetween(tailPtr, headPtr)
157*a8db15d8Sfdy  allowEnqueue := numValidEntries + enqCount <= (size - RenameWidth).U
158*a8db15d8Sfdy  io.canEnq := allowEnqueue
159*a8db15d8Sfdy
160*a8db15d8Sfdy  io.vconfigPdest := Mux(vcfgCandidates(0).ldest === VEC_VCONFIG.U && vcfgCandidates(0).vecWen, vcfgCandidates(0).pdest, vcfgCandidates(1).pdest)
161*a8db15d8Sfdy
162*a8db15d8Sfdy  // for difftest
163*a8db15d8Sfdy  io.diffCommits := 0.U.asTypeOf(new DiffCommitIO)
164*a8db15d8Sfdy  io.diffCommits.isCommit := state === s_idle
165*a8db15d8Sfdy  for(i <- 0 until CommitWidth * MaxUopSize) {
166*a8db15d8Sfdy    io.diffCommits.commitValid(i) := state === s_idle && i.U < io.commitSize
167*a8db15d8Sfdy    io.diffCommits.info(i) := diffCandidates(i)
168*a8db15d8Sfdy  }
169*a8db15d8Sfdy
170*a8db15d8Sfdy}
171