1package xiangshan.backend.issue 2 3import chisel3.{util, _} 4import chisel3.util._ 5import utils.{XSDebug, XSInfo} 6import xiangshan._ 7import xiangshan.backend.exu.ExuConfig 8import xiangshan.backend.regfile.RfReadPort 9 10class IssueQueue 11( 12 val exuCfg: ExuConfig, 13 val wakeupCnt: Int, 14 val bypassCnt: Int = 0 15) extends XSModule with HasIQConst with NeedImpl { 16 val io = IO(new Bundle() { 17 val redirect = Flipped(ValidIO(new Redirect)) 18 val enq = Flipped(DecoupledIO(new MicroOp)) 19 val readIntRf = Vec(exuCfg.intSrcCnt, Flipped(new RfReadPort)) 20 val readFpRf = Vec(exuCfg.fpSrcCnt, Flipped(new RfReadPort)) 21 val deq = DecoupledIO(new ExuInput) 22 val wakeUpPorts = Vec(wakeupCnt, Flipped(ValidIO(new ExuOutput))) 23 val bypassUops = Vec(bypassCnt, Flipped(ValidIO(new MicroOp))) 24 val numExist = Output(UInt(iqIdxWidth.W)) 25 // tlb hit, inst can deq 26 val tlbHit = Input(Bool()) 27 val replay = Flipped(ValidIO(UInt(RoqIdxWidth.W))) 28 }) 29 30 def qsize: Int = IssQueSize 31 def idxWidth = log2Up(qsize) 32 def replayDelay = 16 33 34 require(isPow2(qsize)) 35 36 /* 37 invalid --[enq]--> valid --[deq]--> wait --[tlbHit]--> invalid 38 wait --[replay]--> replay --[cnt]--> valid 39 */ 40 val s_invalid :: s_valid :: s_wait :: s_replay :: Nil = Enum(4) 41 42 val idxQueue = RegInit(VecInit((0 until qsize).map(_.U(idxWidth.W)))) 43 val stateQueue = RegInit(VecInit(Seq.fill(qsize)(s_invalid))) 44 45 val uopQueue = Reg(Vec(qsize, new MicroOp)) 46 val cntQueue = Reg(Vec(qsize, UInt(log2Up(replayDelay).W))) 47 48 val tailPtr = RegInit(0.U((idxWidth+1).W)) 49 50 // real deq 51 52 /* 53 example: realDeqIdx = 2 | realDeqIdx=0 54 moveMask = 11111100 | moveMask=11111111 55 */ 56 assert(!(io.tlbHit && io.replay.valid), "Error: tlbHit and replay are both true!") 57 58 val firstWait = PriorityEncoder(stateQueue.map(_ === s_wait)) 59 val firstBubble = PriorityEncoder(stateQueue.map(_ === s_invalid)) 60 val realDeqIdx = Mux(io.tlbHit, firstWait, firstBubble) 61 val realDeqValid = io.tlbHit || ((firstBubble < tailPtr.tail(1)) && !io.replay.valid) 62 val moveMask = { 63 (Fill(qsize, 1.U(1.W)) << realDeqIdx)(qsize-1, 0) 64 } & Fill(qsize, realDeqValid) 65 66 for(i <- 1 until qsize){ 67 when(moveMask(i)){ 68 idxQueue(i-1) := idxQueue(i) 69 stateQueue(i-1) := stateQueue(i) 70 } 71 } 72 when(realDeqValid){ 73 idxQueue.last := idxQueue(realDeqIdx) 74 stateQueue.last := s_invalid 75 } 76 77 78 // wake up 79 80 // select 81 val selectedIdxRegOH = Wire(UInt(qsize.W)) 82 val selectMask = WireInit(VecInit( 83 (0 until qsize).map(i => 84 stateQueue(i)===s_valid && !(selectedIdxRegOH(i) && io.deq.fire()) 85 ) 86 )) 87 val selectedIdxWire = PriorityEncoder(selectMask) 88 val selectedIdxReg = Reg(UInt(log2Up(qsize).W)) 89 selectedIdxReg := selectedIdxWire - moveMask(selectedIdxWire) 90 selectedIdxRegOH := UIntToOH(selectedIdxReg) 91 XSDebug( 92 p"selMaskWire:${Binary(selectMask.asUInt())} selected:$selectedIdxWire moveMask:${Binary(moveMask)}\n" 93 ) 94 95 // read data && (fake) deq 96 io.deq.valid := stateQueue(selectedIdxReg)===s_valid 97 io.deq.bits.uop := uopQueue(idxQueue(selectedIdxReg)) 98 when(io.deq.fire()){ 99 stateQueue(selectedIdxReg - moveMask(selectedIdxReg)) := s_wait 100 assert(stateQueue(selectedIdxReg) === s_valid, "Dequeue a invalid entry to lsu!") 101 } 102 103 assert(!(tailPtr===0.U && io.tlbHit), "Error: queue is empty but tlbHit is true!") 104 105 val tailAfterRealDeq = tailPtr - moveMask(tailPtr.tail(1)) 106 val isFull = tailAfterRealDeq.head(1).asBool() // tailPtr===qsize.U 107 108 // enq 109 io.enq.ready := !isFull && !io.replay.valid && !io.redirect.valid 110 when(io.enq.fire()){ 111 stateQueue(tailAfterRealDeq.tail(1)) := s_valid 112 uopQueue(idxQueue(tailPtr.tail(1))) := io.enq.bits 113 } 114 115 tailPtr := tailAfterRealDeq + io.enq.fire() 116 117 XSDebug( 118 realDeqValid, 119 p"firstWait:$firstWait firstBubble:$firstBubble realDeqIdx:$realDeqIdx\n" 120 ) 121 122 XSDebug("State Dump: ") 123 stateQueue.reverse.foreach(s =>{ 124 XSDebug(false, s===s_invalid, " -") 125 XSDebug(false, s===s_valid, " v") 126 XSDebug(false, s===s_wait, " w") 127 XSDebug(false, s===s_replay, " r") 128 }) 129 XSDebug(false, true.B, "\n") 130 131 XSDebug("State Dump: ") 132 idxQueue.reverse.foreach(id =>{ 133 XSDebug(false, true.B, p"$id") 134 }) 135 XSDebug(false, true.B, "\n") 136 137 assert(!(io.replay.valid && realDeqValid), "Error: realDeqValid should be false when replay valid!") 138 for(i <- 0 until qsize){ 139 val uopQIdx = idxQueue(i) 140 val cnt = cntQueue(uopQIdx) 141 val nextIdx = i.U - moveMask(i) 142 when( 143 (io.replay.valid && stateQueue(i)===s_wait) && 144 uopQueue(uopQIdx).isAfter(io.replay.bits) 145 ){ 146 // 'i' is enough because 'realDeqValid' must be false here 147 stateQueue(i) := s_replay 148 cnt := (replayDelay-1).U 149 } 150 when(stateQueue(i)===s_replay){ 151 when(cnt === 0.U) { 152 stateQueue(nextIdx) := s_valid 153 if(i == 0) { 154 assert(!moveMask(0), "Error: Attemp to delete a 's_replay' entry!") 155 } 156 }.otherwise({ 157 cnt := cnt - 1.U 158 }) 159 } 160 when(uopQueue(uopQIdx).needFlush(io.redirect)){ 161 stateQueue(nextIdx) := s_invalid 162 } 163 } 164 165 166 // Debug sigs 167 XSInfo( 168 io.enq.fire(), 169 p"enq fire: pc:${Hexadecimal(io.enq.bits.cf.pc)} roqIdx:${io.enq.bits.roqIdx}\n" 170 ) 171 XSInfo( 172 io.deq.fire(), 173 p"deq fire: pc:${Hexadecimal(io.deq.bits.uop.cf.pc)} roqIdx:${io.deq.bits.uop.roqIdx}\n" 174 ) 175 XSDebug(p"tailPtr:$tailPtr tailAfterDeq:$tailAfterRealDeq tlbHit:${io.tlbHit}\n") 176 177 XSDebug(false, true.B, "\n") 178} 179