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