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