diff --git a/src/main/scala/system/SoC.scala b/src/main/scala/system/SoC.scala index 003e5e7925..729c6dea55 100644 --- a/src/main/scala/system/SoC.scala +++ b/src/main/scala/system/SoC.scala @@ -98,6 +98,16 @@ trait HasSoCParameter { val NumCores = tiles.size val EnableILA = soc.EnableILA + // Parameters for trace extension + val TraceTraceGroupNum = tiles.head.traceParams.TraceGroupNum + val TraceCauseWidth = tiles.head.XLEN + val TraceTvalWidth = tiles.head.traceParams.IaddrWidth + val TracePrivWidth = tiles.head.traceParams.PrivWidth + val TraceIaddrWidth = tiles.head.traceParams.IaddrWidth + val TraceItypeWidth = tiles.head.traceParams.ItypeWidth + val TraceIretireWidthCompressed = log2Up(tiles.head.RenameWidth * tiles.head.CommitWidth * 2) + val TraceIlastsizeWidth = tiles.head.traceParams.IlastsizeWidth + // L3 configurations val L3InnerBusWidth = soc.L3InnerBusWidth val L3BlockSize = soc.L3BlockSize diff --git a/src/main/scala/top/Top.scala b/src/main/scala/top/Top.scala index 176b04e529..c8416d239b 100644 --- a/src/main/scala/top/Top.scala +++ b/src/main/scala/top/Top.scala @@ -256,6 +256,21 @@ class XSTop()(implicit p: Parameters) extends BaseXSSoc() with HasSoCParameter val riscv_halt = Output(Vec(NumCores, Bool())) val riscv_critical_error = Output(Vec(NumCores, Bool())) val riscv_rst_vec = Input(Vec(NumCores, UInt(soc.PAddrBits.W))) + val traceCoreInterface = Vec(NumCores, new Bundle { + val fromEncoder = Input(new Bundle { + val enable = Bool() + val stall = Bool() + }) + val toEncoder = Output(new Bundle { + val cause = UInt(TraceCauseWidth.W) + val tval = UInt(TraceTvalWidth.W) + val priv = UInt(TracePrivWidth.W) + val iaddr = UInt((TraceTraceGroupNum * TraceIaddrWidth).W) + val itype = UInt((TraceTraceGroupNum * TraceItypeWidth).W) + val iretire = UInt((TraceTraceGroupNum * TraceIretireWidthCompressed).W) + val ilastsize = UInt((TraceTraceGroupNum * TraceIlastsizeWidth).W) + }) + }) }) val reset_sync = withClockAndReset(io.clock.asClock, io.reset) { ResetGen() } @@ -294,6 +309,8 @@ class XSTop()(implicit p: Parameters) extends BaseXSSoc() with HasSoCParameter core.module.io.clintTime := misc.module.clintTime io.riscv_halt(i) := core.module.io.cpu_halt io.riscv_critical_error(i) := core.module.io.cpu_crtical_error + io.traceCoreInterface(i).toEncoder := core.module.io.traceCoreInterface.toEncoder + core.module.io.traceCoreInterface.fromEncoder := io.traceCoreInterface(i).fromEncoder core.module.io.reset_vector := io.riscv_rst_vec(i) } diff --git a/src/main/scala/top/XSNoCTop.scala b/src/main/scala/top/XSNoCTop.scala index 0eac365e1c..6e4a0205ed 100644 --- a/src/main/scala/top/XSNoCTop.scala +++ b/src/main/scala/top/XSNoCTop.scala @@ -116,6 +116,21 @@ class XSNoCTop()(implicit p: Parameters) extends BaseXSSoc with HasSoCParameter val chi = new PortIO val nodeID = Input(UInt(soc.NodeIDWidthList(issue).W)) val clintTime = Input(ValidIO(UInt(64.W))) + val traceCoreInterface = new Bundle { + val fromEncoder = Input(new Bundle { + val enable = Bool() + val stall = Bool() + }) + val toEncoder = Output(new Bundle { + val cause = UInt(TraceCauseWidth.W) + val tval = UInt(TraceTvalWidth.W) + val priv = UInt(TracePrivWidth.W) + val iaddr = UInt((TraceTraceGroupNum * TraceIaddrWidth).W) + val itype = UInt((TraceTraceGroupNum * TraceItypeWidth).W) + val iretire = UInt((TraceTraceGroupNum * TraceIretireWidthCompressed).W) + val ilastsize = UInt((TraceTraceGroupNum * TraceIlastsizeWidth).W) + }) + } }) // imsic axi4lite io val imsic_axi4lite = wrapper.u_imsic_bus_top.module.axi4lite.map(x => IO(chiselTypeOf(x))) @@ -150,6 +165,8 @@ class XSNoCTop()(implicit p: Parameters) extends BaseXSSoc with HasSoCParameter io.riscv_critical_error := core_with_l2.module.io.cpu_crtical_error io.hartIsInReset := core_with_l2.module.io.hartIsInReset core_with_l2.module.io.reset_vector := io.riscv_rst_vec + io.traceCoreInterface.toEncoder := core_with_l2.module.io.traceCoreInterface.toEncoder + core_with_l2.module.io.traceCoreInterface.fromEncoder := io.traceCoreInterface.fromEncoder EnableClintAsyncBridge match { case Some(param) => diff --git a/src/main/scala/xiangshan/Bundle.scala b/src/main/scala/xiangshan/Bundle.scala index 16422a482f..f7d2a25b9a 100644 --- a/src/main/scala/xiangshan/Bundle.scala +++ b/src/main/scala/xiangshan/Bundle.scala @@ -46,6 +46,7 @@ import xiangshan.frontend.AllFoldedHistories import xiangshan.frontend.AllAheadFoldedHistoryOldestBits import xiangshan.frontend.RASPtr import xiangshan.backend.rob.RobBundles.RobCommitEntryBundle +import xiangshan.backend.trace._ class ValidUndirectioned[T <: Data](gen: T) extends Bundle { val valid = Bool() diff --git a/src/main/scala/xiangshan/L2Top.scala b/src/main/scala/xiangshan/L2Top.scala index 6b037aaacf..ef38c5ca1e 100644 --- a/src/main/scala/xiangshan/L2Top.scala +++ b/src/main/scala/xiangshan/L2Top.scala @@ -24,15 +24,16 @@ import freechips.rocketchip.diplomacy._ import freechips.rocketchip.interrupts._ import freechips.rocketchip.tile.{BusErrorUnit, BusErrorUnitParams, BusErrors, MaxHartIdBits} import freechips.rocketchip.tilelink._ -import coupledL2.{L2ParamKey, EnableCHI} +import coupledL2.{EnableCHI, L2ParamKey} import coupledL2.tl2tl.TL2TLCoupledL2 -import coupledL2.tl2chi.{TL2CHICoupledL2, PortIO, CHIIssue} +import coupledL2.tl2chi.{CHIIssue, PortIO, TL2CHICoupledL2} import huancun.BankBitsKey import system.HasSoCParameter import top.BusPerfMonitor import utility._ import xiangshan.cache.mmu.TlbRequestIO import xiangshan.backend.fu.PMPRespBundle +import xiangshan.backend.trace.TraceCoreInterface class L1BusErrorUnitInfo(implicit val p: Parameters) extends Bundle with HasSoCParameter { val ecc_error = Valid(UInt(soc.PAddrBits.W)) @@ -161,6 +162,10 @@ class L2TopInlined()(implicit p: Parameters) extends LazyModule val resetInFrontend = Input(Bool()) val toTile = Output(Bool()) } + val traceCoreInterface = new Bundle{ + val fromCore = Flipped(new TraceCoreInterface) + val toTile = new TraceCoreInterface + } val debugTopDown = new Bundle() { val robTrueCommit = Input(UInt(64.W)) val robHeadPaddr = Flipped(Valid(UInt(36.W))) @@ -183,6 +188,7 @@ class L2TopInlined()(implicit p: Parameters) extends LazyModule io.hartId.toCore := io.hartId.fromTile io.cpu_halt.toTile := io.cpu_halt.fromCore io.cpu_critical_error.toTile := io.cpu_critical_error.fromCore + io.traceCoreInterface.toTile <> io.traceCoreInterface.fromCore dontTouch(io.hartId) dontTouch(io.cpu_halt) dontTouch(io.cpu_critical_error) diff --git a/src/main/scala/xiangshan/Parameters.scala b/src/main/scala/xiangshan/Parameters.scala index 47d2001fb7..0a52d076e0 100644 --- a/src/main/scala/xiangshan/Parameters.scala +++ b/src/main/scala/xiangshan/Parameters.scala @@ -29,6 +29,7 @@ import xiangshan.backend.fu.FuConfig._ import xiangshan.backend.issue.{IntScheduler, IssueBlockParams, MemScheduler, SchdBlockParams, SchedulerType, VfScheduler, FpScheduler} import xiangshan.backend.regfile._ import xiangshan.backend.BackendParams +import xiangshan.backend.trace._ import xiangshan.cache.DCacheParameters import xiangshan.cache.prefetch._ import xiangshan.frontend.{BasePredictor, BranchPredictionResp, FTB, FakePredictor, RAS, Tage, ITTage, Tage_SC, FauFTB} @@ -539,7 +540,15 @@ case class XSCoreParameters // Parameters for trace extension. // Trace parameters is useful for XSTOP. - val TraceGroupNum = 3 // Width to Encoder + val traceParams: TraceParams = new TraceParams( + HasEncoder = true, + TraceEnable = true, + TraceGroupNum = 1, + IaddrWidth = GPAddrBitsSv48x4, + PrivWidth = 3, + ItypeWidth = 4, + IlastsizeWidth = 1, + ) } case object DebugOptionsKey extends Field[DebugOptions] @@ -879,5 +888,15 @@ trait HasXSParameter { protected def TriggerChainMaxLength = 2 // Parameters for Trace extension - def TraceGroupNum = coreParams.TraceGroupNum + def TraceGroupNum = coreParams.traceParams.TraceGroupNum + def HasEncoder = coreParams.traceParams.HasEncoder + def TraceEnable = coreParams.traceParams.TraceEnable + def CauseWidth = XLEN + def TvalWidth = coreParams.traceParams.IaddrWidth + def PrivWidth = coreParams.traceParams.PrivWidth + def IaddrWidth = coreParams.traceParams.IaddrWidth + def ItypeWidth = coreParams.traceParams.ItypeWidth + def IretireWidthInPipe = log2Up(RenameWidth * 2) + def IretireWidthCompressed = log2Up(RenameWidth * CommitWidth * 2) + def IlastsizeWidth = coreParams.traceParams.IlastsizeWidth } diff --git a/src/main/scala/xiangshan/XSCore.scala b/src/main/scala/xiangshan/XSCore.scala index 9890889f69..aa5c1717e5 100644 --- a/src/main/scala/xiangshan/XSCore.scala +++ b/src/main/scala/xiangshan/XSCore.scala @@ -28,6 +28,7 @@ import utils._ import utility._ import xiangshan.backend._ import xiangshan.backend.fu.PMPRespBundle +import xiangshan.backend.trace.TraceCoreInterface import xiangshan.cache.mmu._ import xiangshan.frontend._ import xiangshan.mem.L1PrefetchFuzzer @@ -84,6 +85,7 @@ class XSCoreImp(outer: XSCoreBase) extends LazyModuleImp(outer) val cpu_halt = Output(Bool()) val cpu_critical_error = Output(Bool()) val resetInFrontend = Output(Bool()) + val traceCoreInterface = new TraceCoreInterface val l2_pf_enable = Output(Bool()) val perfEvents = Input(Vec(numPCntHc * coreParams.L2NBanks + 1, new PerfEvent)) val beu_errors = Output(new XSL1BusErrors()) @@ -238,6 +240,7 @@ class XSCoreImp(outer: XSCoreBase) extends LazyModuleImp(outer) io.cpu_halt := memBlock.io.outer_cpu_halt io.cpu_critical_error := memBlock.io.outer_cpu_critical_error + io.traceCoreInterface <> backend.io.traceCoreInterface io.beu_errors.icache <> memBlock.io.outer_beu_errors_icache io.beu_errors.dcache <> memBlock.io.error.bits.toL1BusErrorUnitInfo(memBlock.io.error.valid) io.beu_errors.l2 <> DontCare @@ -245,6 +248,9 @@ class XSCoreImp(outer: XSCoreBase) extends LazyModuleImp(outer) memBlock.io.resetInFrontendBypass.fromFrontend := frontend.io.resetInFrontend io.resetInFrontend := memBlock.io.resetInFrontendBypass.toL2Top + memBlock.io.traceCoreInterfaceBypass.fromBackend <> backend.io.traceCoreInterface + io.traceCoreInterface <> memBlock.io.traceCoreInterfaceBypass.toL2Top + if (debugOpts.ResetGen) { backend.reset := memBlock.io.reset_backend diff --git a/src/main/scala/xiangshan/XSTile.scala b/src/main/scala/xiangshan/XSTile.scala index 07776dd595..06a01cd83e 100644 --- a/src/main/scala/xiangshan/XSTile.scala +++ b/src/main/scala/xiangshan/XSTile.scala @@ -30,6 +30,7 @@ import top.{BusPerfMonitor, ArgParser, Generator} import utility.{DelayN, ResetGen, TLClientsMerger, TLEdgeBuffer, TLLogger, Constantin, ChiselDB, FileRegisters} import coupledL2.EnableCHI import coupledL2.tl2chi.PortIO +import xiangshan.backend.trace.TraceCoreInterface class XSTile()(implicit p: Parameters) extends LazyModule with HasXSParameter @@ -113,6 +114,7 @@ class XSTile()(implicit p: Parameters) extends LazyModule val cpu_halt = Output(Bool()) val cpu_crtical_error = Output(Bool()) val hartIsInReset = Output(Bool()) + val traceCoreInterface = new TraceCoreInterface val debugTopDown = new Bundle { val robHeadPaddr = Valid(UInt(PAddrBits.W)) val l3MissMatch = Input(Bool()) @@ -141,6 +143,8 @@ class XSTile()(implicit p: Parameters) extends LazyModule l2top.module.io.hartIsInReset.resetInFrontend := core.module.io.resetInFrontend io.hartIsInReset := l2top.module.io.hartIsInReset.toTile + l2top.module.io.traceCoreInterface.fromCore <> core.module.io.traceCoreInterface + io.traceCoreInterface <> l2top.module.io.traceCoreInterface.toTile l2top.module.io.beu_errors.icache <> core.module.io.beu_errors.icache l2top.module.io.beu_errors.dcache <> core.module.io.beu_errors.dcache diff --git a/src/main/scala/xiangshan/XSTileWrap.scala b/src/main/scala/xiangshan/XSTileWrap.scala index 1a2477279c..3ce65b1ad9 100644 --- a/src/main/scala/xiangshan/XSTileWrap.scala +++ b/src/main/scala/xiangshan/XSTileWrap.scala @@ -26,6 +26,7 @@ import system.HasSoCParameter import device.{IMSICAsync, MsiInfoBundle} import coupledL2.tl2chi.{PortIO, AsyncPortIO, CHIAsyncBridgeSource} import utility.{IntBuffer, ResetGen} +import xiangshan.backend.trace.TraceCoreInterface // This module is used for XSNoCTop for async time domain and divide different // voltage domain. Everything in this module should be in the core clock domain @@ -61,6 +62,7 @@ class XSTileWrap()(implicit p: Parameters) extends LazyModule val cpu_halt = Output(Bool()) val cpu_crtical_error = Output(Bool()) val hartIsInReset = Output(Bool()) + val traceCoreInterface = new TraceCoreInterface val debugTopDown = new Bundle { val robHeadPaddr = Valid(UInt(PAddrBits.W)) val l3MissMatch = Input(Bool()) @@ -93,6 +95,7 @@ class XSTileWrap()(implicit p: Parameters) extends LazyModule io.cpu_halt := tile.module.io.cpu_halt io.cpu_crtical_error := tile.module.io.cpu_crtical_error io.hartIsInReset := tile.module.io.hartIsInReset + io.traceCoreInterface <> tile.module.io.traceCoreInterface io.debugTopDown <> tile.module.io.debugTopDown tile.module.io.nodeID.foreach(_ := io.nodeID.get) diff --git a/src/main/scala/xiangshan/backend/Backend.scala b/src/main/scala/xiangshan/backend/Backend.scala index afe9389619..06f90e0dad 100644 --- a/src/main/scala/xiangshan/backend/Backend.scala +++ b/src/main/scala/xiangshan/backend/Backend.scala @@ -39,6 +39,7 @@ import xiangshan.backend.fu.{FenceIO, FenceToSbuffer, FuConfig, FuType, PFEvent, import xiangshan.backend.issue.EntryBundles._ import xiangshan.backend.issue.{CancelNetwork, Scheduler, SchedulerArithImp, SchedulerImpBase, SchedulerMemImp} import xiangshan.backend.rob.{RobCoreTopDownIO, RobDebugRollingIO, RobLsqIO, RobPtr} +import xiangshan.backend.trace.TraceCoreInterface import xiangshan.frontend.{FtqPtr, FtqRead, PreDecodeInfo} import xiangshan.mem.{LqPtr, LsqEnqIO, SqPtr} @@ -246,6 +247,7 @@ class BackendInlinedImp(override val wrapper: BackendInlined)(implicit p: Parame ctrlBlock.io.robio.csr.intrBitSet := intExuBlock.io.csrio.get.interrupt ctrlBlock.io.robio.csr.trapTarget := intExuBlock.io.csrio.get.trapTarget ctrlBlock.io.robio.csr.isXRet := intExuBlock.io.csrio.get.isXRet + ctrlBlock.io.robio.csr.traceTrapInfo := intExuBlock.io.csrio.get.trapTraceInfo ctrlBlock.io.robio.csr.wfiEvent := intExuBlock.io.csrio.get.wfi_event ctrlBlock.io.robio.lsq <> io.mem.robLsqIO ctrlBlock.io.robio.lsTopdownInfo <> io.mem.lsTopdownInfo @@ -740,6 +742,8 @@ class BackendInlinedImp(override val wrapper: BackendInlined)(implicit p: Parame io.toTop.cpuHalted := ctrlBlock.io.toTop.cpuHalt + io.traceCoreInterface <> ctrlBlock.io.traceCoreInterface + io.debugTopDown.fromRob := ctrlBlock.io.debugTopDown.fromRob ctrlBlock.io.debugTopDown.fromCore := io.debugTopDown.fromCore @@ -931,6 +935,8 @@ class BackendIO(implicit p: Parameters, params: BackendParams) extends XSBundle val toTop = new BackendToTopBundle + val traceCoreInterface = new TraceCoreInterface + val fenceio = new FenceIO // Todo: merge these bundles into BackendFrontendIO val frontend = Flipped(new FrontendToCtrlIO) diff --git a/src/main/scala/xiangshan/backend/Bundles.scala b/src/main/scala/xiangshan/backend/Bundles.scala index b64f26dfb3..61e6ca63c9 100644 --- a/src/main/scala/xiangshan/backend/Bundles.scala +++ b/src/main/scala/xiangshan/backend/Bundles.scala @@ -220,7 +220,7 @@ object Bundles { val instrSize = UInt(log2Ceil(RenameWidth + 1).W) val dirtyFs = Bool() val dirtyVs = Bool() - val traceBlockInPipe = new TracePipe(log2Up(RenameWidth * 2)) + val traceBlockInPipe = new TracePipe(IretireWidthInPipe) val eliminatedMove = Bool() // Take snapshot at this CFI inst diff --git a/src/main/scala/xiangshan/backend/CtrlBlock.scala b/src/main/scala/xiangshan/backend/CtrlBlock.scala index a1678d4ff3..3ba0dc533a 100644 --- a/src/main/scala/xiangshan/backend/CtrlBlock.scala +++ b/src/main/scala/xiangshan/backend/CtrlBlock.scala @@ -37,6 +37,7 @@ import xiangshan.backend.rob.{Rob, RobCSRIO, RobCoreTopDownIO, RobDebugRollingIO import xiangshan.frontend.{FtqPtr, FtqRead, Ftq_RF_Components} import xiangshan.mem.{LqPtr, LsqEnqIO} import xiangshan.backend.issue.{FpScheduler, IntScheduler, MemScheduler, VfScheduler} +import xiangshan.backend.trace._ class CtrlToFtqIO(implicit p: Parameters) extends XSBundle { val rob_commits = Vec(CommitWidth, Valid(new RobCommitInfo)) @@ -72,7 +73,8 @@ class CtrlBlockImp( "robFlush" -> 1, "load" -> params.LduCnt, "hybrid" -> params.HyuCnt, - "store" -> (if(EnableStorePrefetchSMS) params.StaCnt else 0) + "store" -> (if(EnableStorePrefetchSMS) params.StaCnt else 0), + "trace" -> TraceGroupNum )) private val numPcMemReadForExu = params.numPcReadPort @@ -239,6 +241,48 @@ class CtrlBlockImp( io.memStPcRead.foreach(_.data := 0.U) } + /** + * trace begin + */ + val trace = Module(new Trace) + if(HasEncoder){ + trace.io.fromEncoder.stall := io.traceCoreInterface.fromEncoder.stall + trace.io.fromEncoder.enable := io.traceCoreInterface.fromEncoder.enable + } else if(!HasEncoder && TraceEnable) { + trace.io.fromEncoder.enable := true.B + trace.io.fromEncoder.stall := false.B + } else if(!HasEncoder && !TraceEnable) { + trace.io.fromEncoder.enable := false.B + trace.io.fromEncoder.stall := false.B + } + + trace.io.fromRob := rob.io.trace.traceCommitInfo + rob.io.trace.blockCommit := trace.io.blockRobCommit + + if(backendParams.debugEn){ + dontTouch(trace.io.toEncoder) + } + + for ((pcMemIdx, i) <- pcMemRdIndexes("trace").zipWithIndex) { + val traceValid = trace.toPcMem(i).valid + pcMem.io.ren.get(pcMemIdx) := traceValid + pcMem.io.raddr(pcMemIdx) := trace.toPcMem(i).bits.ftqIdx.get.value + trace.io.fromPcMem(i) := pcMem.io.rdata(pcMemIdx).getPc(RegEnable(trace.toPcMem(i).bits.ftqOffset.get, traceValid)) + } + + io.traceCoreInterface.toEncoder.cause := trace.io.toEncoder.trap.cause.asUInt + io.traceCoreInterface.toEncoder.tval := trace.io.toEncoder.trap.tval.asUInt + io.traceCoreInterface.toEncoder.priv := trace.io.toEncoder.trap.priv.asUInt + io.traceCoreInterface.toEncoder.iaddr := VecInit(trace.io.toEncoder.blocks.map(_.bits.iaddr.get)).asUInt + io.traceCoreInterface.toEncoder.itype := VecInit(trace.io.toEncoder.blocks.map(_.bits.tracePipe.itype)).asUInt + io.traceCoreInterface.toEncoder.iretire := VecInit(trace.io.toEncoder.blocks.map(_.bits.tracePipe.iretire)).asUInt + io.traceCoreInterface.toEncoder.ilastsize := VecInit(trace.io.toEncoder.blocks.map(_.bits.tracePipe.ilastsize)).asUInt + + /** + * trace end + */ + + redirectGen.io.hartId := io.fromTop.hartId redirectGen.io.oldestExuRedirect.valid := GatedValidRegNext(oldestExuRedirect.valid) redirectGen.io.oldestExuRedirect.bits := RegEnable(oldestExuRedirect.bits, oldestExuRedirect.valid) @@ -747,6 +791,8 @@ class CtrlBlockIO()(implicit p: Parameters, params: BackendParams) extends XSBun val ratOldPest = new RatToVecExcpMod }) + val traceCoreInterface = new TraceCoreInterface + val perfInfo = Output(new Bundle{ val ctrlInfo = new Bundle { val robFull = Bool() diff --git a/src/main/scala/xiangshan/backend/MemBlock.scala b/src/main/scala/xiangshan/backend/MemBlock.scala index 68c8bd0caa..1dede16835 100644 --- a/src/main/scala/xiangshan/backend/MemBlock.scala +++ b/src/main/scala/xiangshan/backend/MemBlock.scala @@ -46,6 +46,7 @@ import xiangshan.backend.datapath.NewPipelineConnect import system.SoCParamsKey import xiangshan.backend.fu.NewCSR.TriggerUtil import xiangshan.ExceptionNO._ +import xiangshan.backend.trace.TraceCoreInterface trait HasMemBlockParameters extends HasXSParameter { // number of memory units @@ -318,6 +319,10 @@ class MemBlockInlinedImp(outer: MemBlockInlined) extends LazyModuleImp(outer) val fromFrontend = Input(Bool()) val toL2Top = Output(Bool()) } + val traceCoreInterfaceBypass = new Bundle{ + val fromBackend = Flipped(new TraceCoreInterface) + val toL2Top = new TraceCoreInterface + } }) dontTouch(io.inner_hartId) @@ -1869,6 +1874,7 @@ class MemBlockInlinedImp(outer: MemBlockInlined) extends LazyModuleImp(outer) io.reset_backend := DontCare } io.resetInFrontendBypass.toL2Top := io.resetInFrontendBypass.fromFrontend + io.traceCoreInterfaceBypass.toL2Top <> io.traceCoreInterfaceBypass.fromBackend // top-down info dcache.io.debugTopDown.robHeadVaddr := io.debugTopDown.robHeadVaddr diff --git a/src/main/scala/xiangshan/backend/fu/CSR.scala b/src/main/scala/xiangshan/backend/fu/CSR.scala index c828166f97..e96fa21a86 100644 --- a/src/main/scala/xiangshan/backend/fu/CSR.scala +++ b/src/main/scala/xiangshan/backend/fu/CSR.scala @@ -33,6 +33,7 @@ import xiangshan.backend.fu.NewCSR.CSREvents.TargetPCBundle import xiangshan.backend.fu.NewCSR.CSRNamedConstant.ContextStatus import xiangshan.backend.rob.RobPtr import utils.MathUtils.{BigIntGenMask, BigIntNot} +import xiangshan.backend.trace._ class FpuCsrIO extends Bundle { val fflags = Output(Valid(UInt(5.W))) @@ -98,6 +99,7 @@ class CSRFileIO(implicit p: Parameters) extends XSBundle { val trapTarget = Output(new TargetPCBundle) val interrupt = Output(Bool()) val wfi_event = Output(Bool()) + val trapTraceInfo = ValidIO(new TraceTrap) // from LSQ val memExceptionVAddr = Input(UInt(XLEN.W)) val memExceptionGPAddr = Input(UInt(XLEN.W)) diff --git a/src/main/scala/xiangshan/backend/fu/NewCSR/NewCSR.scala b/src/main/scala/xiangshan/backend/fu/NewCSR/NewCSR.scala index a48191c43b..48c03d2117 100644 --- a/src/main/scala/xiangshan/backend/fu/NewCSR/NewCSR.scala +++ b/src/main/scala/xiangshan/backend/fu/NewCSR/NewCSR.scala @@ -20,6 +20,7 @@ import xiangshan.backend.rob.RobPtr import xiangshan._ import xiangshan.backend.fu.PerfCounterIO import xiangshan.ExceptionNO._ +import xiangshan.backend.trace._ import scala.collection.immutable.SeqMap @@ -187,6 +188,8 @@ class NewCSR(implicit val p: Parameters) extends Module val memTrigger = new MemTdataDistributeIO() // Instruction fetch address translation type val instrAddrTransType = new AddrTransType + // trace + val trapTraceInfo = ValidIO(new TraceTrap) // custom val custom = new CSRCustomState }) @@ -1082,6 +1085,17 @@ class NewCSR(implicit val p: Parameters) extends Module * debug_end */ + // trace + val privState1HForTrace = Seq(privState.isModeM, privState.isModeHS, privState.isModeVS, privState.isModeHU, privState.isModeVU) + val privStateForTrace = Seq(Priv.M, Priv.HS, Priv.VS, Priv.HU, Priv.VU) + io.status.trapTraceInfo.valid := RegNext(io.fromRob.trap.valid) + io.status.trapTraceInfo.bits.priv := Mux(debugMode, + Priv.D, + Mux1H(privState1HForTrace, privStateForTrace) + ) + io.status.trapTraceInfo.bits.cause := Mux1H(VecInit(privState1HForTrace).asUInt.head(3), Seq(mcause.rdata, scause.rdata, vscause.rdata)) + io.status.trapTraceInfo.bits.tval := Mux1H(VecInit(privState1HForTrace).asUInt.head(3), Seq(mtval.rdata, stval.rdata, vstval.rdata)) + /** * perf_begin * perf number: 29 (frontend 8, ctrlblock 8, memblock 8, huancun 5) diff --git a/src/main/scala/xiangshan/backend/fu/wrapper/CSR.scala b/src/main/scala/xiangshan/backend/fu/wrapper/CSR.scala index 8ecac7460e..f55f28fe16 100644 --- a/src/main/scala/xiangshan/backend/fu/wrapper/CSR.scala +++ b/src/main/scala/xiangshan/backend/fu/wrapper/CSR.scala @@ -308,6 +308,8 @@ class CSR(cfg: FuConfig)(implicit p: Parameters) extends FuncUnit(cfg) csrOut.debugMode := csrMod.io.status.debugMode + csrOut.trapTraceInfo := csrMod.io.status.trapTraceInfo + csrOut.customCtrl match { case custom => custom.l1I_pf_enable := csrMod.io.status.custom.l1I_pf_enable diff --git a/src/main/scala/xiangshan/backend/rename/CompressUnit.scala b/src/main/scala/xiangshan/backend/rename/CompressUnit.scala index 5099fe0fc0..47d5b6b8cd 100644 --- a/src/main/scala/xiangshan/backend/rename/CompressUnit.scala +++ b/src/main/scala/xiangshan/backend/rename/CompressUnit.scala @@ -16,6 +16,7 @@ class CompressUnit(implicit p: Parameters) extends XSModule{ val needRobFlags = Vec(RenameWidth, Output(Bool())) val instrSizes = Vec(RenameWidth, Output(UInt(log2Ceil(RenameWidth + 1).W))) val masks = Vec(RenameWidth, Output(UInt(RenameWidth.W))) + val canCompressVec = Vec(RenameWidth, Output(Bool())) } }) @@ -63,4 +64,5 @@ class CompressUnit(implicit p: Parameters) extends XSModule{ (io.out.needRobFlags ++ io.out.instrSizes ++ io.out.masks).zip(decoder).foreach { case (sink, source) => sink := source } + io.out.canCompressVec := VecInit(canCompress) } diff --git a/src/main/scala/xiangshan/backend/rename/Rename.scala b/src/main/scala/xiangshan/backend/rename/Rename.scala index 9e99997903..842fd24040 100644 --- a/src/main/scala/xiangshan/backend/rename/Rename.scala +++ b/src/main/scala/xiangshan/backend/rename/Rename.scala @@ -430,26 +430,31 @@ class Rename(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHe /** * trace begin */ + // note: fusionInst can't robcompress val inVec = io.in.map(_.bits) - val canRobCompressVec = inVec.map(_.canRobCompress) val isRVCVec = inVec.map(_.preDecodeInfo.isRVC) - val halfWordNumVec = (0 until RenameWidth).map{ - i => compressMasksVec(i).asBools.zip(isRVCVec).map{ - case (mask, isRVC) => Mux(mask, Mux(isRVC, 1.U, 2.U), 0.U) + val isFusionVec = inVec.map(_.commitType).map(ctype => CommitType.isFused(ctype)) + + val canRobCompressVec = compressUnit.io.out.canCompressVec + val iLastSizeVec = isRVCVec.map(isRVC => Mux(isRVC, Ilastsize.HalfWord, Ilastsize.Word)) + val halfWordNumVec = isRVCVec.map(isRVC => Mux(isRVC, 1.U, 2.U)) + val halfWordNumMatrix = (0 until RenameWidth).map( + i => compressMasksVec(i).asBools.zipWithIndex.map{ case(mask, j) => + Mux(mask, halfWordNumVec(j), 0.U) } - } + ) for (i <- 0 until RenameWidth) { // iretire uops(i).traceBlockInPipe.iretire := Mux(canRobCompressVec(i), - halfWordNumVec(i).reduce(_ +& _), - Mux(isRVCVec(i), 1.U, 2.U) + halfWordNumMatrix(i).reduce(_ +& _), + (if(i < RenameWidth -1) Mux(isFusionVec(i), halfWordNumVec(i+1), 0.U) else 0.U) +& halfWordNumVec(i) ) // ilastsize - val j = i + val tmp = i val lastIsRVC = WireInit(false.B) - (j until RenameWidth).map { j => + (tmp until RenameWidth).map { j => when(compressMasksVec(i)(j)) { lastIsRVC := io.in(j).bits.preDecodeInfo.isRVC } @@ -457,7 +462,7 @@ class Rename(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHe uops(i).traceBlockInPipe.ilastsize := Mux(canRobCompressVec(i), Mux(lastIsRVC, Ilastsize.HalfWord, Ilastsize.Word), - Mux(isRVCVec(i), Ilastsize.HalfWord, Ilastsize.Word) + (if(i < RenameWidth -1) Mux(isFusionVec(i), iLastSizeVec(i+1), iLastSizeVec(i)) else iLastSizeVec(i)) ) // itype diff --git a/src/main/scala/xiangshan/backend/rob/Rob.scala b/src/main/scala/xiangshan/backend/rob/Rob.scala index 783f2e5487..9e23c6958f 100644 --- a/src/main/scala/xiangshan/backend/rob/Rob.scala +++ b/src/main/scala/xiangshan/backend/rob/Rob.scala @@ -65,6 +65,10 @@ class RobImp(override val wrapper: Rob)(implicit p: Parameters, params: BackendP val writebackNums = Flipped(Vec(writeback.size - params.StdCnt, ValidIO(UInt(writeback.size.U.getWidth.W)))) val writebackNeedFlush = Input(Vec(params.allExuParams.filter(_.needExceptionGen).length, Bool())) val commits = Output(new RobCommitIO) + val trace = new Bundle { + val blockCommit = Input(Bool()) + val traceCommitInfo = new TraceBundle(hasIaddr = false, CommitWidth, IretireWidthInPipe) + } val rabCommits = Output(new RabCommitIO) val diffCommits = if (backendParams.basicDebugEn) Some(Output(new DiffCommitIO)) else None val isVsetFlushPipe = Output(Bool()) @@ -232,7 +236,7 @@ class RobImp(override val wrapper: Rob)(implicit p: Parameters, params: BackendP // Instructions in multiple Ftq entries compressed to one RobEntry do not occur. for (i <- 0 until CommitWidth) { val lastOffset = (rawInfo(i).traceBlockInPipe.iretire - (1.U << rawInfo(i).traceBlockInPipe.ilastsize.asUInt).asUInt) + rawInfo(i).ftqOffset - commitInfo(i).ftqOffset := lastOffset + commitInfo(i).ftqOffset := Mux(CommitType.isFused(rawInfo(i).commitType), rawInfo(i).ftqOffset, lastOffset) } // data for debug @@ -724,8 +728,9 @@ class RobImp(override val wrapper: Rob)(implicit p: Parameters, params: BackendP }.elsewhen(deqNeedFlush && io.flushOut.valid && !io.flushOut.bits.flushItself()){ deqHasFlushed := true.B } + val traceBlock = io.trace.blockCommit val blockCommit = misPredBlock || lastCycleFlush || hasWFI || io.redirect.valid || - (deqNeedFlush && !deqHasFlushed) || deqFlushBlock || criticalErrorState + (deqNeedFlush && !deqHasFlushed) || deqFlushBlock || criticalErrorState || traceBlock io.commits.isWalk := state === s_walk io.commits.isCommit := state === s_idle && !blockCommit @@ -1049,11 +1054,11 @@ class RobImp(override val wrapper: Rob)(implicit p: Parameters, params: BackendP val taken = branchWBs.map(writeback => writeback.valid && writeback.bits.robIdx.value === i.U && writeback.bits.redirect.get.bits.cfiUpdate.taken).reduce(_ || _) val xret = csrWBs.map(writeback => writeback.valid && writeback.bits.robIdx.value === i.U && io.csr.isXRet).reduce(_ || _) - when(xret){ + when(robEntries(i).valid && xret){ robEntries(i).traceBlockInPipe.itype := Itype.ExpIntReturn - }.elsewhen(Itype.isBranchType(robEntries(i).traceBlockInPipe.itype)){ - // BranchType code(itype = 5) must be correctly replaced! - robEntries(i).traceBlockInPipe.itype := Mux(taken, Itype.Taken, Itype.NonTaken) + }.elsewhen(robEntries(i).valid && Itype.isBranchType(robEntries(i).traceBlockInPipe.itype) && taken){ + // BranchType code(notaken itype = 4) must be correctly replaced! + robEntries(i).traceBlockInPipe.itype := Itype.Taken } } @@ -1114,6 +1119,16 @@ class RobImp(override val wrapper: Rob)(implicit p: Parameters, params: BackendP val vxsatCanWbSeq = vxsat_wb.map(writeback => writeback.valid && writeback.bits.robIdx.value === needUpdateRobIdx(i)) val vxsatRes = vxsatCanWbSeq.zip(vxsat_wb).map { case (canWb, wb) => Mux(canWb, wb.bits.vxsat.get, 0.U) }.fold(false.B)(_ | _) needUpdate(i).vxsat := Mux(!robBanksRdata(i).valid && instCanEnqFlag, 0.U, robBanksRdata(i).vxsat | vxsatRes) + + // trace + val taken = branchWBs.map(writeback => writeback.valid && writeback.bits.robIdx.value === needUpdateRobIdx(i) && writeback.bits.redirect.get.bits.cfiUpdate.taken).reduce(_ || _) + val xret = csrWBs.map(writeback => writeback.valid && writeback.bits.robIdx.value === needUpdateRobIdx(i) && io.csr.isXRet).reduce(_ || _) + when(robBanksRdata(i).valid && xret){ + needUpdate(i).traceBlockInPipe.itype := Itype.ExpIntReturn + }.elsewhen(robBanksRdata(i).valid && Itype.isBranchType(robBanksRdata(i).traceBlockInPipe.itype) && taken){ + // BranchType code(notaken itype = 4) must be correctly replaced! + needUpdate(i).traceBlockInPipe.itype := Itype.Taken + } } robBanksRdataThisLineUpdate := VecInit(needUpdate.take(8)) robBanksRdataNextLineUpdate := VecInit(needUpdate.drop(8)) @@ -1231,6 +1246,51 @@ class RobImp(override val wrapper: Rob)(implicit p: Parameters, params: BackendP io.toVecExcpMod.logicPhyRegMap := rab.io.toVecExcpMod.logicPhyRegMap io.toVecExcpMod.excpInfo := vecExcpInfo + /** + * trace + */ + val trapTraceInfoFromCsr = io.csr.traceTrapInfo + + // trace output + val traceTrap = io.trace.traceCommitInfo.trap + val traceValids = io.trace.traceCommitInfo.blocks.map(_.valid) + val traceBlocks = io.trace.traceCommitInfo.blocks + val traceBlockInPipe = io.trace.traceCommitInfo.blocks.map(_.bits.tracePipe) + + traceTrap := trapTraceInfoFromCsr.bits + + for (i <- 0 until CommitWidth) { + traceBlocks(i).bits.ftqIdx.foreach(_ := rawInfo(i).ftqIdx) + traceBlocks(i).bits.ftqOffset.foreach(_ := rawInfo(i).ftqOffset) + traceBlockInPipe(i).itype := rawInfo(i).traceBlockInPipe.itype + traceBlockInPipe(i).iretire := Mux(io.commits.isCommit && io.commits.commitValid(i), rawInfo(i).traceBlockInPipe.iretire, 0.U) + traceBlockInPipe(i).ilastsize := rawInfo(i).traceBlockInPipe.ilastsize + } + + for (i <- 0 until CommitWidth) { + val iretire = traceBlocks(i).bits.tracePipe.iretire + val itype = traceBlocks(i).bits.tracePipe.itype + traceValids(i) := iretire =/= 0.U + } + + val t_idle :: t_waiting :: Nil = Enum(2) + val traceState = RegInit(t_idle) + when(traceState === t_idle){ + when(io.exception.valid){ + traceState := t_waiting + } + }.elsewhen(traceState === t_waiting){ + when(trapTraceInfoFromCsr.valid){ + traceState := t_idle + + traceBlocks(0).bits.tracePipe.itype := Mux(io.exception.bits.isInterrupt, + Itype.Interrupt, + Itype.Exception + ) + traceValids(0) := true.B + } + } + /** * debug info */ diff --git a/src/main/scala/xiangshan/backend/rob/RobBundles.scala b/src/main/scala/xiangshan/backend/rob/RobBundles.scala index dcdb90af62..8e7ae17434 100644 --- a/src/main/scala/xiangshan/backend/rob/RobBundles.scala +++ b/src/main/scala/xiangshan/backend/rob/RobBundles.scala @@ -66,7 +66,7 @@ object RobBundles extends HasCircularQueuePtrHelper { // data end // trace - val traceBlockInPipe = new TracePipe(log2Up(RenameWidth * 2)) + val traceBlockInPipe = new TracePipe(IretireWidthInPipe) // status begin val valid = Bool() val fflags = UInt(5.W) @@ -116,7 +116,7 @@ object RobBundles extends HasCircularQueuePtrHelper { val isMove = Bool() // for perfEvents val needFlush = Bool() // trace - val traceBlockInPipe = new TracePipe(log2Up(RenameWidth * 2)) + val traceBlockInPipe = new TracePipe(IretireWidthInPipe) // debug_begin val debug_pc = OptionWrapper(backendParams.debugEn, UInt(VAddrBits.W)) val debug_instr = OptionWrapper(backendParams.debugEn, UInt(32.W)) @@ -225,6 +225,7 @@ class RobCSRIO(implicit p: Parameters) extends XSBundle { val trapTarget = Input(new TargetPCBundle) val isXRet = Input(Bool()) val wfiEvent = Input(Bool()) + val traceTrapInfo = Flipped(ValidIO(new TraceTrap)) val fflags = Output(Valid(UInt(5.W))) val vxsat = Output(Valid(Bool())) diff --git a/src/main/scala/xiangshan/backend/trace/Interface.scala b/src/main/scala/xiangshan/backend/trace/Interface.scala index a765ed4d79..72a6ac3b52 100644 --- a/src/main/scala/xiangshan/backend/trace/Interface.scala +++ b/src/main/scala/xiangshan/backend/trace/Interface.scala @@ -8,8 +8,8 @@ import xiangshan.HasXSParameter import xiangshan.frontend.{BrType, FtqPtr, PreDecodeInfo} class TraceTrap(implicit val p: Parameters) extends Bundle with HasXSParameter { - val cause = UInt(XLEN.W) - val tval = UInt(XLEN.W) + val cause = UInt(CauseWidth.W) + val tval = UInt(TvalWidth.W) val priv = Priv() } @@ -20,9 +20,9 @@ class TracePipe(iretireWidth: Int)(implicit val p: Parameters) extends Bundle wi } class TraceBlock(hasIaddr: Boolean, iretireWidth: Int)(implicit val p: Parameters) extends Bundle with HasXSParameter { - val iaddr = if (hasIaddr) Some(UInt(XLEN.W)) else None + val iaddr = if (hasIaddr) Some(UInt(IaddrWidth.W)) else None val ftqIdx = if (!hasIaddr) Some(new FtqPtr) else None - val ftqOffset = if (!hasIaddr) Some( UInt(log2Up(PredictWidth).W)) else None + val ftqOffset = if (!hasIaddr) Some(UInt(log2Up(PredictWidth).W)) else None val tracePipe = new TracePipe(iretireWidth) } @@ -37,17 +37,6 @@ class FromEncoder extends Bundle { } class TraceCoreInterface(implicit val p: Parameters) extends Bundle with HasXSParameter { - // parameter - val CauseWidth = XLEN - val TvalWidth = XLEN - val PrivWidth = 3 - val IaddrWidth = XLEN - val ItypeWidth = 4 - val IretireWidthInPipe = log2Up(RenameWidth * 2) - val IretireWidthCompressed = log2Up(RenameWidth * CommitWidth * 2) - val IlastsizeWidth = 1 - val GroupNum = TraceGroupNum - val fromEncoder = Input(new Bundle { val enable = Bool() val stall = Bool() @@ -56,10 +45,10 @@ class TraceCoreInterface(implicit val p: Parameters) extends Bundle with HasXSPa val cause = UInt(CauseWidth.W) val tval = UInt(TvalWidth.W) val priv = UInt(PrivWidth.W) - val iaddr = UInt((GroupNum * IaddrWidth).W) - val itype = UInt((GroupNum * ItypeWidth).W) - val iretire = UInt((GroupNum * IretireWidthCompressed).W) - val ilastsize = UInt((GroupNum * IlastsizeWidth).W) + val iaddr = UInt((TraceGroupNum * IaddrWidth).W) + val itype = UInt((TraceGroupNum * ItypeWidth).W) + val iretire = UInt((TraceGroupNum * IretireWidthCompressed).W) + val ilastsize = UInt((TraceGroupNum * IlastsizeWidth).W) }) } @@ -81,8 +70,8 @@ object Itype extends NamedUInt(4) { def OtherUninferableJump = 14.U //rename def OtherInferableJump = 15.U //rename - // Assuming the branchType is taken here, it will be correctly modified after writeBack. - def Branch = 5.U + // Assuming the branchType is NonTaken here, it will be correctly modified after writeBack. + def Branch = NonTaken def jumpTypeGen(brType: UInt, rd: OpRegType, rs: OpRegType): UInt = { @@ -155,9 +144,9 @@ object Priv extends NamedUInt(3) { } class OpRegType extends Bundle { - val value = UInt(3.W) + val value = UInt(6.W) def isX0 = this.value === 0.U def isX1 = this.value === 1.U def isX5 = this.value === 5.U - def isLink = Seq(isX1, isX5).map(_ === this.value).reduce(_ || _) + def isLink = Seq(isX1, isX5).reduce(_ || _) } diff --git a/src/main/scala/xiangshan/backend/trace/Trace.scala b/src/main/scala/xiangshan/backend/trace/Trace.scala new file mode 100644 index 0000000000..02f1edf388 --- /dev/null +++ b/src/main/scala/xiangshan/backend/trace/Trace.scala @@ -0,0 +1,87 @@ +package xiangshan.backend.trace + +import chisel3._ +import chisel3.util.{RegEnable, ValidIO, log2Up} +import org.chipsalliance.cde.config.Parameters +import xiangshan.HasXSParameter + +class TraceParams( + val HasEncoder : Boolean, + val TraceEnable : Boolean, + val TraceGroupNum : Int, + val IaddrWidth : Int, + val PrivWidth : Int, + val ItypeWidth : Int, + val IlastsizeWidth : Int, +) + +class TraceIO(implicit val p: Parameters) extends Bundle with HasXSParameter { + val fromEncoder = Input(new FromEncoder) + val fromRob = Flipped(new TraceBundle(hasIaddr = false, CommitWidth, IretireWidthInPipe)) + val blockRobCommit = Output(Bool()) + val toPcMem = Vec(TraceGroupNum, ValidIO(new TraceBlock(false, IretireWidthCompressed))) + val fromPcMem = Input(Vec(TraceGroupNum, UInt(IaddrWidth.W))) + val toEncoder = new TraceBundle(hasIaddr = true, TraceGroupNum, IretireWidthCompressed) +} + +class Trace(implicit val p: Parameters) extends Module with HasXSParameter { + val io = IO(new TraceIO) + val (fromEncoder, fromRob, toPcMem, fromPcMem, toEncoder) = (io.fromEncoder, io.fromRob, io.toPcMem, io.fromPcMem, io.toEncoder) + + /** + * stage 0: CommitInfo from rob + */ + val blockCommit = Wire(Bool()) + io.blockRobCommit := blockCommit + + /** + * stage 1: regNext(robCommitInfo) + */ + val s1_in = fromRob + val s1_out = WireInit(0.U.asTypeOf(s1_in)) + + for(i <- 0 until CommitWidth) { + // Trap only occor in block(0). + s1_out.trap := RegEnable(s1_in.trap, 0.U.asTypeOf(s1_in.trap), s1_in.blocks(0).valid && Itype.isTrap(s1_in.blocks(0).bits.tracePipe.itype)) + s1_out.blocks(i).valid := RegEnable(s1_in.blocks(i).valid, 0.U.asTypeOf(s1_in.blocks(i).valid), !blockCommit) + s1_out.blocks(i).bits := RegEnable(s1_in.blocks(i).bits, 0.U.asTypeOf(s1_in.blocks(i).bits), s1_in.blocks(i).valid) + } + + /** + * stage 2: compress, s2_out(deq from traceBuffer) -> pcMem + */ + val s2_in = s1_out + val traceBuffer = Module(new TraceBuffer) + traceBuffer.io.in.fromEncoder := fromEncoder + traceBuffer.io.in.fromRob := s2_in + val s2_out_trap = traceBuffer.io.out.groups.trap + val s2_out_block = traceBuffer.io.out.groups.blocks + blockCommit := traceBuffer.io.out.blockCommit + + /** + * stage 3: groups with iaddr from pcMem(ftqidx & ftqOffset -> iaddr) -> encoder + */ + val s3_in_trap = s2_out_trap + val s3_in_block = s2_out_block + + val s3_out_trap = RegNext(s3_in_trap) + val s3_out_block = RegNext(s3_in_block) + + toPcMem := s3_in_block + + for(i <- 0 until TraceGroupNum) { + toEncoder.trap := s3_out_trap + toEncoder.blocks(i).valid := s3_out_block(i).valid + toEncoder.blocks(i).bits.iaddr.foreach(_ := Mux(s3_out_block(i).valid, fromPcMem(i), 0.U)) + toEncoder.blocks(i).bits.tracePipe := s3_out_block(i).bits.tracePipe + } + if(backendParams.debugEn){ + dontTouch(io.toEncoder) + } +} + + + + + + diff --git a/src/main/scala/xiangshan/backend/trace/TraceBuffer.scala b/src/main/scala/xiangshan/backend/trace/TraceBuffer.scala new file mode 100644 index 0000000000..21c3954c78 --- /dev/null +++ b/src/main/scala/xiangshan/backend/trace/TraceBuffer.scala @@ -0,0 +1,118 @@ +package xiangshan.backend.trace + +import chisel3._ +import chisel3.util._ +import org.chipsalliance.cde.config.Parameters +import utility.{CircularQueuePtr, HasCircularQueuePtrHelper} +import xiangshan.{HasXSParameter, XSCoreParamsKey} + +class TraceBuffer(implicit val p: Parameters) extends Module + with HasXSParameter + with HasCircularQueuePtrHelper { + + val io = IO(new Bundle { + val in = new Bundle{ + val fromEncoder = Input(new FromEncoder) + val fromRob = Flipped(new TraceBundle(hasIaddr = false, CommitWidth, IretireWidthCompressed)) + } + + val out = new Bundle { // output groups to pcMem + val blockCommit = Output(Bool()) + val groups = new TraceBundle(hasIaddr = false, TraceGroupNum, IretireWidthCompressed) + } + }) + + // buffer: compress info from robCommit + val traceTrap = Reg(new TraceTrap) + val traceEntries = Reg(Vec(CommitWidth, ValidIO(new TraceBlock(false, IretireWidthCompressed)))) + traceTrap := io.in.fromRob.trap + + val blockCommit = RegInit(false.B) // to rob + + /** + * compress, update blocks + */ + val inValidVec = VecInit(io.in.fromRob.blocks.map(_.valid)) + val inTypeIsNotNoneVec = VecInit(io.in.fromRob.blocks.map(block => Itype.isNotNone(block.bits.tracePipe.itype))) + val needPcVec = Wire(Vec(CommitWidth, Bool())) + for(i <- 0 until CommitWidth) { + val rightHasValid = if(i == CommitWidth - 1) false.B else (inValidVec.asUInt(CommitWidth-1, i+1).orR) + needPcVec(i) := inValidVec(i) & (inTypeIsNotNoneVec(i) || !rightHasValid) & !blockCommit + } + + val blocksUpdate = WireInit(io.in.fromRob.blocks) + for(i <- 1 until CommitWidth){ + when(!needPcVec(i-1)){ + blocksUpdate(i).bits.tracePipe.iretire := blocksUpdate(i - 1).bits.tracePipe.iretire + io.in.fromRob.blocks(i).bits.tracePipe.iretire + blocksUpdate(i).bits.ftqOffset.get := blocksUpdate(i - 1).bits.ftqOffset.get + blocksUpdate(i).bits.ftqIdx.get := blocksUpdate(i - 1).bits.ftqIdx.get + } + } + + /** + * enq to traceEntries + */ + val countVec = VecInit((0 until CommitWidth).map(i => PopCount(needPcVec.asUInt(i, 0)))) + val numNeedPc = countVec(CommitWidth-1) + + val enqPtr = RegInit(TracePtr(false.B, 0.U)) + val deqPtr = RegInit(TracePtr(false.B, 0.U)) + val deqPtrPre = RegNext(deqPtr) + val enqPtrNext = WireInit(enqPtr) + val deqPtrNext = WireInit(deqPtr) + enqPtr := enqPtrNext + deqPtr := deqPtrNext + val canNotTraceAll = distanceBetween(enqPtrNext, deqPtrNext) > 0.U + blockCommit := io.in.fromEncoder.enable && (canNotTraceAll || io.in.fromEncoder.stall) + + enqPtrNext := enqPtr + numNeedPc + deqPtrNext := Mux(deqPtr + TraceGroupNum.U > enqPtrNext, enqPtrNext, deqPtr + TraceGroupNum.U) + + val traceIdxVec = VecInit(countVec.map(count => (enqPtr + count - 1.U).value)) + + for(i <- 0 until CommitWidth){ + when(needPcVec(i)){ + traceEntries(traceIdxVec(i)) := blocksUpdate(i) + } + } + + /** + * deq from traceEntries + */ + val blockOut = WireInit(0.U.asTypeOf(io.out.groups)) + blockOut.trap := traceTrap + for(i <- 0 until TraceGroupNum) { + when(deqPtrPre + i.U < enqPtr) { + blockOut.blocks(i) := traceEntries((deqPtrPre + i.U).value) + } .otherwise { + blockOut.blocks(i).valid := false.B + } + } + + if(backendParams.debugEn){ + dontTouch(countVec) + dontTouch(numNeedPc) + dontTouch(traceIdxVec) + } + + io.out.blockCommit := blockCommit + io.out.groups := blockOut + +} + +class TracePtr(entries: Int) extends CircularQueuePtr[TracePtr]( + entries +) with HasCircularQueuePtrHelper { + + def this()(implicit p: Parameters) = this(p(XSCoreParamsKey).CommitWidth) + +} + +object TracePtr { + def apply(f: Bool, v: UInt)(implicit p: Parameters): TracePtr = { + val ptr = Wire(new TracePtr) + ptr.flag := f + ptr.value := v + ptr + } +} \ No newline at end of file diff --git a/src/test/scala/top/SimTop.scala b/src/test/scala/top/SimTop.scala index ed9343b40b..1e24597884 100644 --- a/src/test/scala/top/SimTop.scala +++ b/src/test/scala/top/SimTop.scala @@ -66,6 +66,8 @@ class SimTop(implicit p: Parameters) extends Module { soc.io.cacheable_check := DontCare soc.io.riscv_rst_vec.foreach(_ := 0x10000000L.U) l_soc.nmi.foreach(_.foreach(intr => { intr := false.B; dontTouch(intr) })) + soc.io.traceCoreInterface.foreach(_.fromEncoder.enable := true.B) + soc.io.traceCoreInterface.foreach(_.fromEncoder.stall := false.B) // soc.io.rtc_clock is a div100 of soc.io.clock val rtcClockDiv = 100