1/*************************************************************************************** 2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3* Copyright (c) 2020-2021 Peng Cheng Laboratory 4* 5* XiangShan is licensed under Mulan PSL v2. 6* You can use this software according to the terms and conditions of the Mulan PSL v2. 7* You may obtain a copy of Mulan PSL v2 at: 8* http://license.coscl.org.cn/MulanPSL2 9* 10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13* 14* See the Mulan PSL v2 for more details. 15***************************************************************************************/ 16 17package xiangshan.backend.rename.freelist 18 19import org.chipsalliance.cde.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import xiangshan._ 23import utils._ 24import utility._ 25 26 27class MEFreeList(size: Int)(implicit p: Parameters) extends BaseFreeList(size) with HasPerfEvents { 28 val freeList = RegInit(VecInit( 29 // originally {1, 2, ..., size - 1} are free. Register 0-31 are mapped to x0. 30 Seq.tabulate(size - 1)(i => (i + 1).U(PhyRegIdxWidth.W)) :+ 0.U(PhyRegIdxWidth.W))) 31 32 val tailPtr = RegInit(FreeListPtr(false, size - 1)) 33 34 val doWalkRename = io.walk && io.doAllocate && !io.redirect 35 val doNormalRename = io.canAllocate && io.doAllocate && !io.redirect 36 val doRename = doWalkRename || doNormalRename 37 val doCommit = io.commit.isCommit 38 39 /** 40 * Allocation: from freelist (same as StdFreelist) 41 */ 42 val phyRegCandidates = VecInit(headPtrOHVec.map(sel => Mux1H(sel, freeList))) 43 for (i <- 0 until RenameWidth) { 44 // enqueue instr, is move elimination 45 io.allocatePhyReg(i) := phyRegCandidates(PopCount(io.allocateReq.take(i))) 46 } 47 // update arch head pointer 48 val archAlloc = io.commit.commitValid zip io.commit.info map { 49 case (valid, info) => valid && info.rfWen && !info.isMove 50 } 51 val numArchAllocate = PopCount(archAlloc) 52 val archHeadPtrNew = archHeadPtr + numArchAllocate 53 val archHeadPtrNext = Mux(doCommit, archHeadPtrNew, archHeadPtr) 54 archHeadPtr := archHeadPtrNext 55 56 // update head pointer 57 val numAllocate = Mux(io.walk, PopCount(io.walkReq), PopCount(io.allocateReq)) 58 val headPtrNew = Mux(lastCycleRedirect, redirectedHeadPtr, headPtr + numAllocate) 59 val headPtrOHNew = Mux(lastCycleRedirect, redirectedHeadPtrOH, headPtrOHVec(numAllocate)) 60 val headPtrNext = Mux(doRename, headPtrNew, headPtr) 61 val headPtrOHNext = Mux(doRename, headPtrOHNew, headPtrOH) 62 headPtr := headPtrNext 63 headPtrOH := headPtrOHNext 64 65 /** 66 * Deallocation: when refCounter becomes zero, the register can be released to freelist 67 */ 68 for (i <- 0 until RabCommitWidth) { 69 when (io.freeReq(i)) { 70 val freePtr = tailPtr + PopCount(io.freeReq.take(i)) 71 freeList(freePtr.value) := io.freePhyReg(i) 72 } 73 } 74 75 // update tail pointer 76 val tailPtrNext = tailPtr + PopCount(io.freeReq) 77 tailPtr := tailPtrNext 78 79 val freeRegCnt = Mux(doWalkRename && !lastCycleRedirect, distanceBetween(tailPtrNext, headPtr) - PopCount(io.walkReq), 80 Mux(doNormalRename, distanceBetween(tailPtrNext, headPtr) - PopCount(io.allocateReq), 81 distanceBetween(tailPtrNext, headPtr))) 82 val freeRegCntReg = RegNext(freeRegCnt) 83 io.canAllocate := freeRegCntReg >= RenameWidth.U 84 85 if(backendParams.debugEn){ 86 val debugArchHeadPtr = RegNext(RegNext(archHeadPtr, FreeListPtr(false, 0)), FreeListPtr(false, 0)) // two-cycle delay from refCounter 87 val debugArchRAT = RegNext(RegNext(io.debug_rat.get, VecInit(Seq.fill(32)(0.U(PhyRegIdxWidth.W)))), VecInit(Seq.fill(32)(0.U(PhyRegIdxWidth.W)))) 88 val debugUniqPR = Seq.tabulate(32)(i => i match { 89 case 0 => true.B 90 case _ => !debugArchRAT.take(i).map(_ === debugArchRAT(i)).reduce(_ || _) 91 }) 92 XSError(distanceBetween(tailPtr, debugArchHeadPtr) +& PopCount(debugUniqPR) =/= size.U, "Integer physical register should be in either arch RAT or arch free list\n") 93 } 94 95 QueuePerf(size = size, utilization = freeRegCntReg, full = freeRegCntReg === 0.U) 96 97 XSPerfAccumulate("allocation_blocked_cycle", !io.canAllocate) 98 XSPerfAccumulate("can_alloc_wrong", !io.canAllocate && freeRegCnt >= RenameWidth.U) 99 100 val perfEvents = Seq( 101 ("me_freelist_1_4_valid", freeRegCntReg < (size / 4).U ), 102 ("me_freelist_2_4_valid", freeRegCntReg >= (size / 4).U && freeRegCntReg <= (size / 2).U ), 103 ("me_freelist_3_4_valid", freeRegCntReg >= (size / 2).U && freeRegCntReg <= (size * 3 / 4).U), 104 ("me_freelist_4_4_valid", freeRegCntReg >= (size * 3 / 4).U ), 105 ) 106 generatePerfEvent() 107} 108