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