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