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