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