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