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 11import xiangshan.backend.rename.SnapshotGenerator 12 13class RenameBufferPtr(size: Int) extends CircularQueuePtr[RenameBufferPtr](size) { 14 def this()(implicit p: Parameters) = this(p(XSCoreParamsKey).RabSize) 15} 16 17object RenameBufferPtr { 18 def apply(flag: Boolean = false, v: Int = 0)(implicit p: Parameters): RenameBufferPtr = { 19 val ptr = Wire(new RenameBufferPtr(p(XSCoreParamsKey).RabSize)) 20 ptr.flag := flag.B 21 ptr.value := v.U 22 ptr 23 } 24} 25 26class RenameBufferEntry(implicit p: Parameters) extends RobCommitInfo { 27 val robIdx = new RobPtr 28} 29 30class RenameBuffer(size: Int)(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelper { 31 val io = IO(new Bundle { 32 val redirect = Input(ValidIO(new Bundle { 33 })) 34 35 val req = Vec(RenameWidth, Flipped(ValidIO(new DynInst))) 36 37 val walkSize = Input(UInt(log2Up(size).W)) 38 val robWalkEnd = Input(Bool()) 39 val commitSize = Input(UInt(log2Up(size).W)) 40 val snpt = Input(new SnapshotPort) 41 42 val canEnq = Output(Bool()) 43 val rabWalkEnd = Output(Bool()) 44 val enqPtrVec = Output(Vec(RenameWidth, new RenameBufferPtr)) 45 val vconfigPdest = Output(UInt(PhyRegIdxWidth.W)) 46 val commits = Output(new RobCommitIO) 47 val diffCommits = Output(new DiffCommitIO) 48 }) 49 50 // pointer 51 private val enqPtrVec = RegInit(VecInit.tabulate(RenameWidth)(idx => RenameBufferPtr(flag = false, idx))) 52 private val enqPtr = enqPtrVec.head 53 private val enqPtrOH = RegInit(1.U(size.W)) 54 private val enqPtrOHShift = CircularShift(enqPtrOH) 55 // may shift [0, RenameWidth] steps 56 private val enqPtrOHVec = VecInit.tabulate(RenameWidth + 1)(enqPtrOHShift.left) 57 private val enqPtrVecNext = Wire(enqPtrVec.cloneType) 58 59 private val deqPtrVec = RegInit(VecInit.tabulate(CommitWidth)(idx => RenameBufferPtr(flag = false, idx))) 60 private val deqPtr = deqPtrVec.head 61 private val deqPtrOH = RegInit(1.U(size.W)) 62 private val deqPtrOHShift = CircularShift(deqPtrOH) 63 private val deqPtrOHVec = VecInit.tabulate(CommitWidth + 1)(deqPtrOHShift.left) 64 private val deqPtrVecNext = Wire(deqPtrVec.cloneType) 65 XSError(deqPtr.toOH =/= deqPtrOH, p"wrong one-hot reg between $deqPtr and $deqPtrOH") 66 67 private val walkPtr = Reg(new RenameBufferPtr) 68 private val walkPtrOH = walkPtr.toOH 69 private val walkPtrOHVec = VecInit.tabulate(CommitWidth + 1)(CircularShift(walkPtrOH).left) 70 private val walkPtrNext = Wire(new RenameBufferPtr) 71 72 private val snptEnq = io.canEnq && io.req.head.valid && io.req.head.bits.snapshot 73 private val walkPtrSnapshots = SnapshotGenerator(enqPtr, snptEnq, io.snpt.snptDeq, io.redirect.valid) 74 75 // may shift [0, CommitWidth] steps 76 val headPtrOHVec2 = VecInit(Seq.tabulate(CommitWidth * MaxUopSize + 1)(_ % size).map(step => deqPtrOHShift.left(step))) 77 78 val vcfgPtrOH = RegInit(1.U(size.W)) 79 val vcfgPtrOHShift = CircularShift(vcfgPtrOH) 80 // may shift [0, 2) steps 81 val vcfgPtrOHVec = VecInit.tabulate(2)(vcfgPtrOHShift.left) 82 83 val diffPtrOH = RegInit(1.U(size.W)) 84 val diffPtrOHShift = CircularShift(diffPtrOH) 85 // may shift [0, CommitWidth * MaxUopSize] steps 86 val diffPtrOHVec = VecInit(Seq.tabulate(CommitWidth * MaxUopSize + 1)(_ % size).map(step => diffPtrOHShift.left(step))) 87 88 // Regs 89 val renameBuffer = RegInit(VecInit(Seq.fill(size){0.U.asTypeOf(new RenameBufferEntry)})) 90 91 val s_idle :: s_walk :: s_cancel :: Nil = Enum(3) 92 val state = RegInit(s_idle) 93 val stateNxt = WireInit(s_idle) 94 95 val robWalkEnd = RegInit(false.B) 96 val rabWalkEndWire = Wire(Bool()) 97 98 when(io.redirect.valid){ 99 robWalkEnd := false.B 100 }.elsewhen(io.robWalkEnd){ 101 robWalkEnd := true.B 102 } 103 104 val realNeedAlloc = io.req.map(req => req.valid && req.bits.needWriteRf) 105 val enqCount = PopCount(realNeedAlloc) 106 val commitCount = Mux(io.commits.isCommit, PopCount(io.commits.commitValid), 0.U) 107 val walkCount = Mux(io.commits.isWalk, PopCount(io.commits.walkValid), 0.U) 108 109 walkPtrNext := Mux( 110 io.redirect.valid, 111 Mux( 112 io.snpt.useSnpt, 113 walkPtrSnapshots(io.snpt.snptSelect), 114 deqPtrVecNext.head 115 ), 116 Mux( 117 state === s_walk, 118 walkPtr + walkCount, 119 walkPtr 120 ) 121 ) 122 123 walkPtr := walkPtrNext 124 125 // number of pair(ldest, pdest) ready to commit to arch_rat 126 val commitSize = RegInit(0.U(log2Up(size).W)) 127 val walkSize = RegInit(0.U(log2Up(size).W)) 128 129 val commitSizeNxt = commitSize + io.commitSize - commitCount 130 val walkSizeNxt = walkSize + io.walkSize - walkCount 131 132 commitSize := commitSizeNxt 133 walkSize := Mux(io.redirect.valid, 0.U, walkSizeNxt) 134 135 val walkCandidates = VecInit(walkPtrOHVec.map(sel => Mux1H(sel, renameBuffer))) 136 val commitCandidates = VecInit(deqPtrOHVec.map(sel => Mux1H(sel, renameBuffer))) 137 val vcfgCandidates = VecInit(vcfgPtrOHVec.map(sel => Mux1H(sel, renameBuffer))) 138 val diffCandidates = VecInit(diffPtrOHVec.map(sel => Mux1H(sel, renameBuffer))) 139 140 // update diff pointer 141 val diffPtrOHNext = Mux(state === s_idle, diffPtrOHVec(io.commitSize), diffPtrOH) 142 diffPtrOH := diffPtrOHNext 143 144 // update vcfg pointer 145 vcfgPtrOH := diffPtrOHNext 146 147 // update enq pointer 148 val enqPtrNext = Mux( 149 state === s_walk && stateNxt === s_idle, 150 walkPtrNext, 151 enqPtr + enqCount 152 ) 153 val enqPtrOHNext = Mux( 154 state === s_walk && stateNxt === s_idle, 155 walkPtrNext.toOH, 156 enqPtrOHVec(enqCount) 157 ) 158 enqPtr := enqPtrNext 159 enqPtrOH := enqPtrOHNext 160 enqPtrVecNext.zipWithIndex.map{ case(ptr, i) => ptr := enqPtrNext + i.U } 161 enqPtrVec := enqPtrVecNext 162 163 // update deq pointer 164 val deqPtrNext = deqPtr + commitCount 165 val deqPtrOHNext = deqPtrOHVec(commitCount) 166 deqPtr := deqPtrNext 167 deqPtrOH := deqPtrOHNext 168 deqPtrVecNext.zipWithIndex.map{ case(ptr, i) => ptr := deqPtrNext + i.U } 169 deqPtrVec := deqPtrVecNext 170 171 val allocatePtrVec = VecInit((0 until RenameWidth).map(i => enqPtrVec(PopCount(realNeedAlloc.take(i))).value)) 172 allocatePtrVec.zip(io.req).zip(realNeedAlloc).map{ case((allocatePtr, req), realNeedAlloc) => 173 when(realNeedAlloc){ 174 renameBuffer(allocatePtr).ldest := req.bits.ldest 175 renameBuffer(allocatePtr).pdest := req.bits.pdest 176 renameBuffer(allocatePtr).rfWen := req.bits.rfWen 177 renameBuffer(allocatePtr).fpWen := req.bits.fpWen 178 renameBuffer(allocatePtr).vecWen := req.bits.vecWen 179 renameBuffer(allocatePtr).isMove := req.bits.eliminatedMove 180 renameBuffer(allocatePtr).robIdx := req.bits.robIdx 181 } 182 } 183 184 io.commits.isCommit := state === s_idle 185 io.commits.isWalk := state === s_walk 186 187 for(i <- 0 until CommitWidth) { 188 io.commits.commitValid(i) := state === s_idle && i.U < commitSize 189 io.commits.walkValid(i) := state === s_walk && i.U < walkSize 190 io.commits.info(i) := Mux(state === s_idle, commitCandidates(i), walkCandidates(i)) 191 io.commits.robIdx(i) := Mux(state === s_idle, commitCandidates(i).robIdx, walkCandidates(i).robIdx) 192 } 193 194 stateNxt := Mux(io.redirect.valid, s_walk, 195 Mux(io.rabWalkEnd, s_idle, state)) 196 state := stateNxt 197 198 rabWalkEndWire := robWalkEnd && state === s_walk && walkSizeNxt === 0.U 199 io.rabWalkEnd := rabWalkEndWire 200 201 val allowEnqueue = RegInit(true.B) 202 val numValidEntries = distanceBetween(enqPtr, deqPtr) 203 allowEnqueue := numValidEntries + enqCount <= (size - RenameWidth).U 204 io.canEnq := allowEnqueue 205 io.enqPtrVec := enqPtrVec 206 207 io.vconfigPdest := Mux(vcfgCandidates(0).ldest === VCONFIG_IDX.U && vcfgCandidates(0).vecWen, vcfgCandidates(0).pdest, vcfgCandidates(1).pdest) 208 209 // for difftest 210 io.diffCommits := 0.U.asTypeOf(new DiffCommitIO) 211 io.diffCommits.isCommit := state === s_idle 212 for(i <- 0 until CommitWidth * MaxUopSize) { 213 io.diffCommits.commitValid(i) := state === s_idle && i.U < io.commitSize 214 io.diffCommits.info(i) := diffCandidates(i) 215 } 216 217 XSError(isBefore(enqPtr, deqPtr) && !isFull(enqPtr, deqPtr), "\ndeqPtr is older than enqPtr!\n") 218 219 QueuePerf(RabSize, numValidEntries, !allowEnqueue) 220} 221