xref: /XiangShan/src/main/scala/xiangshan/backend/rob/Rab.scala (revision 5db4956b8ea14332169fca361912b6eefd5d475f)
1package xiangshan.backend.rob
2
3import chipsalliance.rocketchip.config.Parameters
4import chisel3._
5import chisel3.util._
6import xiangshan._
7import utils._
8import utility._
9import xiangshan.backend.Bundles.DynInst
10import xiangshan.backend.decode.VectorConstants
11import xiangshan.backend.rename.SnapshotGenerator
12
13class RenameBufferPtr(size: Int) extends CircularQueuePtr[RenameBufferPtr](size) {
14  def this()(implicit p: Parameters) = this(p(XSCoreParamsKey).RabSize)
15}
16
17object RenameBufferPtr {
18  def apply(flag: Boolean = false, v: Int = 0)(implicit p: Parameters): RenameBufferPtr = {
19    val ptr = Wire(new RenameBufferPtr(p(XSCoreParamsKey).RabSize))
20    ptr.flag := flag.B
21    ptr.value := v.U
22    ptr
23  }
24}
25
26class RenameBufferEntry(implicit p: Parameters) extends RobCommitInfo {
27  val robIdx = new RobPtr
28}
29
30class RenameBuffer(size: Int)(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelper {
31  val io = IO(new Bundle {
32    val redirect = Input(ValidIO(new Bundle {
33    }))
34
35    val req = Vec(RenameWidth, Flipped(ValidIO(new DynInst)))
36
37    val walkSize = Input(UInt(log2Up(size).W))
38    val robWalkEnd = Input(Bool())
39    val commitSize = Input(UInt(log2Up(size).W))
40    val snpt = Input(new SnapshotPort)
41
42    val canEnq = Output(Bool())
43    val rabWalkEnd = Output(Bool())
44    val enqPtrVec = Output(Vec(RenameWidth, new RenameBufferPtr))
45    val vconfigPdest = Output(UInt(PhyRegIdxWidth.W))
46    val commits = Output(new RobCommitIO)
47    val diffCommits = Output(new DiffCommitIO)
48  })
49
50  // pointer
51  private val enqPtrVec = RegInit(VecInit.tabulate(RenameWidth)(idx => RenameBufferPtr(flag = false, idx)))
52  private val enqPtr = enqPtrVec.head
53  private val enqPtrOH = RegInit(1.U(size.W))
54  private val enqPtrOHShift = CircularShift(enqPtrOH)
55  // may shift [0, RenameWidth] steps
56  private val enqPtrOHVec = VecInit.tabulate(RenameWidth + 1)(enqPtrOHShift.left)
57  private val enqPtrVecNext = Wire(enqPtrVec.cloneType)
58
59  private val deqPtrVec = RegInit(VecInit.tabulate(CommitWidth)(idx => RenameBufferPtr(flag = false, idx)))
60  private val deqPtr = deqPtrVec.head
61  private val deqPtrOH = RegInit(1.U(size.W))
62  private val deqPtrOHShift = CircularShift(deqPtrOH)
63  private val deqPtrOHVec = VecInit.tabulate(CommitWidth + 1)(deqPtrOHShift.left)
64  private val deqPtrVecNext = Wire(deqPtrVec.cloneType)
65  XSError(deqPtr.toOH =/= deqPtrOH, p"wrong one-hot reg between $deqPtr and $deqPtrOH")
66
67  private val walkPtr = Reg(new RenameBufferPtr)
68  private val walkPtrOH = walkPtr.toOH
69  private val walkPtrOHVec = VecInit.tabulate(CommitWidth + 1)(CircularShift(walkPtrOH).left)
70  private val walkPtrNext = Wire(new RenameBufferPtr)
71
72  private val snptEnq = io.canEnq && io.req.head.valid && io.req.head.bits.snapshot
73  private val walkPtrSnapshots = SnapshotGenerator(enqPtr, snptEnq, io.snpt.snptDeq, io.redirect.valid)
74
75  // may shift [0, CommitWidth] steps
76  val headPtrOHVec2 = VecInit(Seq.tabulate(CommitWidth * MaxUopSize + 1)(_ % size).map(step => deqPtrOHShift.left(step)))
77
78  val vcfgPtrOH = RegInit(1.U(size.W))
79  val vcfgPtrOHShift = CircularShift(vcfgPtrOH)
80  // may shift [0, 2) steps
81  val vcfgPtrOHVec = VecInit.tabulate(2)(vcfgPtrOHShift.left)
82
83  val diffPtrOH = RegInit(1.U(size.W))
84  val diffPtrOHShift = CircularShift(diffPtrOH)
85  // may shift [0, CommitWidth * MaxUopSize] steps
86  val diffPtrOHVec = VecInit(Seq.tabulate(CommitWidth * MaxUopSize + 1)(_ % size).map(step => diffPtrOHShift.left(step)))
87
88  // Regs
89  val renameBuffer = RegInit(VecInit(Seq.fill(size){0.U.asTypeOf(new RenameBufferEntry)}))
90
91  val s_idle :: s_walk :: s_cancel :: Nil = Enum(3)
92  val state = RegInit(s_idle)
93  val stateNxt = WireInit(s_idle)
94
95  val robWalkEnd = RegInit(false.B)
96  val rabWalkEndWire = Wire(Bool())
97
98  when(io.redirect.valid){
99    robWalkEnd := false.B
100  }.elsewhen(io.robWalkEnd){
101    robWalkEnd := true.B
102  }
103
104  val realNeedAlloc = io.req.map(req => req.valid && req.bits.needWriteRf)
105  val enqCount    = PopCount(realNeedAlloc)
106  val commitCount = Mux(io.commits.isCommit, PopCount(io.commits.commitValid), 0.U)
107  val walkCount   = Mux(io.commits.isWalk, PopCount(io.commits.walkValid), 0.U)
108
109  walkPtrNext := Mux(
110    io.redirect.valid,
111    Mux(
112      io.snpt.useSnpt,
113      walkPtrSnapshots(io.snpt.snptSelect),
114      deqPtrVecNext.head
115    ),
116    Mux(
117      state === s_walk,
118      walkPtr + walkCount,
119      walkPtr
120    )
121  )
122
123  walkPtr := walkPtrNext
124
125  // number of pair(ldest, pdest) ready to commit to arch_rat
126  val commitSize = RegInit(0.U(log2Up(size).W))
127  val walkSize = RegInit(0.U(log2Up(size).W))
128
129  val commitSizeNxt = commitSize + io.commitSize - commitCount
130  val walkSizeNxt = walkSize + io.walkSize - walkCount
131
132  commitSize := commitSizeNxt
133  walkSize := Mux(io.redirect.valid, 0.U, walkSizeNxt)
134
135  val walkCandidates   = VecInit(walkPtrOHVec.map(sel => Mux1H(sel, renameBuffer)))
136  val commitCandidates = VecInit(deqPtrOHVec.map(sel => Mux1H(sel, renameBuffer)))
137  val vcfgCandidates   = VecInit(vcfgPtrOHVec.map(sel => Mux1H(sel, renameBuffer)))
138  val diffCandidates   = VecInit(diffPtrOHVec.map(sel => Mux1H(sel, renameBuffer)))
139
140  // update diff pointer
141  val diffPtrOHNext = Mux(state === s_idle, diffPtrOHVec(io.commitSize), diffPtrOH)
142  diffPtrOH := diffPtrOHNext
143
144  // update vcfg pointer
145  vcfgPtrOH := diffPtrOHNext
146
147  // update enq pointer
148  val enqPtrNext = Mux(
149    state === s_walk && stateNxt === s_idle,
150    walkPtrNext,
151    enqPtr + enqCount
152  )
153  val enqPtrOHNext = Mux(
154    state === s_walk && stateNxt === s_idle,
155    walkPtrNext.toOH,
156    enqPtrOHVec(enqCount)
157  )
158  enqPtr := enqPtrNext
159  enqPtrOH := enqPtrOHNext
160  enqPtrVecNext.zipWithIndex.map{ case(ptr, i) => ptr := enqPtrNext + i.U }
161  enqPtrVec := enqPtrVecNext
162
163  // update deq pointer
164  val deqPtrNext = deqPtr + commitCount
165  val deqPtrOHNext = deqPtrOHVec(commitCount)
166  deqPtr := deqPtrNext
167  deqPtrOH := deqPtrOHNext
168  deqPtrVecNext.zipWithIndex.map{ case(ptr, i) => ptr := deqPtrNext + i.U }
169  deqPtrVec := deqPtrVecNext
170
171  val allocatePtrVec = VecInit((0 until RenameWidth).map(i => enqPtrVec(PopCount(realNeedAlloc.take(i))).value))
172  allocatePtrVec.zip(io.req).zip(realNeedAlloc).map{ case((allocatePtr, req), realNeedAlloc) =>
173    when(realNeedAlloc){
174      renameBuffer(allocatePtr).ldest := req.bits.ldest
175      renameBuffer(allocatePtr).pdest := req.bits.pdest
176      renameBuffer(allocatePtr).rfWen := req.bits.rfWen
177      renameBuffer(allocatePtr).fpWen := req.bits.fpWen
178      renameBuffer(allocatePtr).vecWen := req.bits.vecWen
179      renameBuffer(allocatePtr).isMove := req.bits.eliminatedMove
180      renameBuffer(allocatePtr).robIdx := req.bits.robIdx
181    }
182  }
183
184  io.commits.isCommit := state === s_idle
185  io.commits.isWalk := state === s_walk
186
187  for(i <- 0 until CommitWidth) {
188    io.commits.commitValid(i) := state === s_idle && i.U < commitSize
189    io.commits.walkValid(i) := state === s_walk && i.U < walkSize
190    io.commits.info(i) := Mux(state === s_idle, commitCandidates(i), walkCandidates(i))
191    io.commits.robIdx(i) := Mux(state === s_idle, commitCandidates(i).robIdx, walkCandidates(i).robIdx)
192  }
193
194  stateNxt := Mux(io.redirect.valid, s_walk,
195    Mux(io.rabWalkEnd, s_idle, state))
196  state := stateNxt
197
198  rabWalkEndWire := robWalkEnd && state === s_walk && walkSizeNxt === 0.U
199  io.rabWalkEnd := rabWalkEndWire
200
201  val allowEnqueue = RegInit(true.B)
202  val numValidEntries = distanceBetween(enqPtr, deqPtr)
203  allowEnqueue := numValidEntries + enqCount <= (size - RenameWidth).U
204  io.canEnq := allowEnqueue
205  io.enqPtrVec := enqPtrVec
206
207  io.vconfigPdest := Mux(vcfgCandidates(0).ldest === VCONFIG_IDX.U && vcfgCandidates(0).vecWen, vcfgCandidates(0).pdest, vcfgCandidates(1).pdest)
208
209  // for difftest
210  io.diffCommits := 0.U.asTypeOf(new DiffCommitIO)
211  io.diffCommits.isCommit := state === s_idle
212  for(i <- 0 until CommitWidth * MaxUopSize) {
213    io.diffCommits.commitValid(i) := state === s_idle && i.U < io.commitSize
214    io.diffCommits.info(i) := diffCandidates(i)
215  }
216
217  XSError(isBefore(enqPtr, deqPtr) && !isFull(enqPtr, deqPtr), "\ndeqPtr is older than enqPtr!\n")
218
219  QueuePerf(RabSize, numValidEntries, !allowEnqueue)
220}
221