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