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