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