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