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