1package xiangshan.backend.trace 2 3import chisel3._ 4import chisel3.util._ 5import org.chipsalliance.cde.config.Parameters 6import utility.{CircularQueuePtr, HasCircularQueuePtrHelper} 7import xiangshan.{HasXSParameter, XSCoreParamsKey} 8 9class TraceBuffer(implicit val p: Parameters) extends Module 10 with HasXSParameter 11 with HasCircularQueuePtrHelper { 12 13 val io = IO(new Bundle { 14 val in = new Bundle{ 15 val fromEncoder = Input(new FromEncoder) 16 val fromRob = Flipped(new TraceBundle(hasIaddr = false, CommitWidth, IretireWidthCompressed)) 17 } 18 val out = new Bundle { // output groups to pcMem 19 val blockCommit = Output(Bool()) 20 val groups = new TraceBundle(hasIaddr = false, TraceGroupNum, IretireWidthCompressed) 21 } 22 }) 23 24 // buffer: compress info from robCommit 25 val traceEntries = Reg(Vec(CommitWidth, ValidIO(new TraceBlock(false, IretireWidthCompressed)))) 26 val blockCommit = RegInit(false.B) // to rob 27 28 /** 29 * compress, update blocks 30 */ 31 val inValidVec = VecInit(io.in.fromRob.blocks.map(_.valid)) 32 val inTypeIsNotNoneVec = VecInit(io.in.fromRob.blocks.map(block => Itype.isNotNone(block.bits.tracePipe.itype))) 33 val needPcVec = Wire(Vec(CommitWidth, Bool())) 34 for(i <- 0 until CommitWidth) { 35 val rightHasValid = if(i == CommitWidth - 1) false.B else (inValidVec.asUInt(CommitWidth-1, i+1).orR) 36 needPcVec(i) := inValidVec(i) & (inTypeIsNotNoneVec(i) || !rightHasValid) & !blockCommit 37 } 38 39 val blocksUpdate = WireInit(io.in.fromRob.blocks) 40 for(i <- 1 until CommitWidth){ 41 when(!needPcVec(i-1)){ 42 blocksUpdate(i).bits.tracePipe.iretire := blocksUpdate(i - 1).bits.tracePipe.iretire + io.in.fromRob.blocks(i).bits.tracePipe.iretire 43 blocksUpdate(i).bits.ftqOffset.get := blocksUpdate(i - 1).bits.ftqOffset.get 44 blocksUpdate(i).bits.ftqIdx.get := blocksUpdate(i - 1).bits.ftqIdx.get 45 } 46 } 47 48 /** 49 * enq to traceEntries 50 */ 51 val countVec = VecInit((0 until CommitWidth).map(i => PopCount(needPcVec.asUInt(i, 0)))) 52 val numNeedPc = countVec(CommitWidth-1) 53 54 val enqPtr = RegInit(TracePtr(false.B, 0.U)) 55 val deqPtr = RegInit(TracePtr(false.B, 0.U)) 56 val deqPtrPre = RegNext(deqPtr) 57 val enqPtrNext = WireInit(enqPtr) 58 val deqPtrNext = WireInit(deqPtr) 59 enqPtr := enqPtrNext 60 deqPtr := deqPtrNext 61 val canNotTraceAll = distanceBetween(enqPtrNext, deqPtrNext) > 0.U 62 blockCommit := io.in.fromEncoder.enable && (canNotTraceAll || io.in.fromEncoder.stall) 63 64 enqPtrNext := enqPtr + numNeedPc 65 deqPtrNext := Mux(deqPtr + TraceGroupNum.U > enqPtrNext, enqPtrNext, deqPtr + TraceGroupNum.U) 66 67 val traceIdxVec = VecInit(countVec.map(count => (enqPtr + count - 1.U).value)) 68 for(i <- 0 until CommitWidth){ 69 when(needPcVec(i)){ 70 traceEntries(traceIdxVec(i)) := blocksUpdate(i) 71 } 72 } 73 74 /** 75 * deq from traceEntries 76 */ 77 val blockOut = WireInit(0.U.asTypeOf(io.out.groups)) 78 for(i <- 0 until TraceGroupNum) { 79 when(deqPtrPre + i.U < enqPtr) { 80 blockOut.blocks(i) := traceEntries((deqPtrPre + i.U).value) 81 } .otherwise { 82 blockOut.blocks(i).valid := false.B 83 } 84 } 85 86 io.out.blockCommit := blockCommit 87 io.out.groups := blockOut 88 89 if(backendParams.debugEn){ 90 dontTouch(countVec) 91 dontTouch(numNeedPc) 92 dontTouch(traceIdxVec) 93 } 94} 95 96class TracePtr(entries: Int) extends CircularQueuePtr[TracePtr]( 97 entries 98) with HasCircularQueuePtrHelper { 99 100 def this()(implicit p: Parameters) = this(p(XSCoreParamsKey).CommitWidth) 101 102} 103 104object TracePtr { 105 def apply(f: Bool, v: UInt)(implicit p: Parameters): TracePtr = { 106 val ptr = Wire(new TracePtr) 107 ptr.flag := f 108 ptr.value := v 109 ptr 110 } 111} 112