diff --git a/src/cpucounters.cpp b/src/cpucounters.cpp index 3b186164..02bb2e56 100644 --- a/src/cpucounters.cpp +++ b/src/cpucounters.cpp @@ -1749,6 +1749,12 @@ void PCM::initEnergyMonitoring() pp_energy_status.push_back(std::make_shared( new CounterWidthExtender::MsrHandleCounter(MSR[socketRefCore[0]], MSR_PP1_ENERGY_STATUS), 32, 10000)); } + + if (systemEnergyMetricAvailable() && MSR.size() && (system_energy_status.get() == nullptr)) + { + system_energy_status = std::make_shared( + new CounterWidthExtender::MsrHandleCounter(MSR[socketRefCore[0]], MSR_SYS_ENERGY_STATUS, 0x00000000FFFFFFFF), 32, 10000); + } } static const uint32 UBOX0_DEV_IDS[] = { @@ -6964,6 +6970,11 @@ void PCM::getAllCounterStates(SystemCounterState & systemState, std::vectorread(); + } } void PCM::getUncoreCounterStates(SystemCounterState & systemState, std::vector & socketStates) diff --git a/src/cpucounters.h b/src/cpucounters.h index 6dc8043f..e09be6ec 100644 --- a/src/cpucounters.h +++ b/src/cpucounters.h @@ -810,6 +810,7 @@ class PCM_API PCM std::vector > energy_status; std::vector > dram_energy_status; std::vector > pp_energy_status; + std::shared_ptr system_energy_status; std::vector>> cxlPMUs; // socket X CXL ports X UNIT {0,1} std::vector > memory_bw_local; @@ -2510,6 +2511,25 @@ class PCM_API PCM ); } + bool systemEnergyMetricAvailable() const + { + return ( + useSKLPath() + || cpu_family_model == PCM::SKX + || cpu_family_model == PCM::ICX + || cpu_family_model == PCM::ADL + || cpu_family_model == PCM::RPL + || cpu_family_model == PCM::MTL + || cpu_family_model == PCM::LNL + || cpu_family_model == PCM::ARL + || cpu_family_model == PCM::SPR + || cpu_family_model == PCM::EMR + || cpu_family_model == PCM::GNR + || cpu_family_model == PCM::SRF + || cpu_family_model == PCM::GRR + ); + } + bool packageThermalMetricsAvailable() const { return packageEnergyMetricsAvailable(); @@ -3368,6 +3388,25 @@ uint64 getConsumedEnergy(const int powerPlane, const CounterStateType& before, c return after.PPEnergyStatus[powerPlane] - before.PPEnergyStatus[powerPlane]; } +/*! \brief Returns energy consumed by system + \param before CPU counter state before the experiment + \param after CPU counter state after the experiment +*/ +template +uint64 getSystemConsumedEnergy(const CounterStateType& before, const CounterStateType& after) +{ + return after.systemEnergyStatus - before.systemEnergyStatus; +} + +/*! \brief Checks is systemEnergyStatusValid is valid in the state +* \param s CPU counter state +*/ +template +bool systemEnergyStatusValid(const CounterStateType& s) +{ + return s.systemEnergyStatus != 0; +} + /*! \brief Returns energy consumed by DRAM (measured in internal units) \param before CPU counter state before the experiment \param after CPU counter state after the experiment @@ -3435,6 +3474,31 @@ double getConsumedJoules(const int powerPlane, const CounterStateType& before, c return double(getConsumedEnergy(powerPlane, before, after)) * m->getJoulesPerEnergyUnit(); } +/*! \brief Returns Joules consumed by system + \param before CPU counter state before the experiment + \param after CPU counter state after the experiment +*/ +template +double getSystemConsumedJoules(const CounterStateType& before, const CounterStateType& after) +{ + PCM* m = PCM::getInstance(); + if (!m) return -1.; + + auto unit = m->getJoulesPerEnergyUnit(); + + switch (m->getCPUFamilyModel()) + { + case PCM::SPR: + case PCM::EMR: + case PCM::GNR: + case PCM::SRF: + unit = 1.0; + break; + } + + return double(getSystemConsumedEnergy(before, after)) * unit; +} + /*! \brief Returns Joules consumed by DRAM \param before CPU counter state before the experiment \param after CPU counter state after the experiment @@ -3860,11 +3924,14 @@ class SystemCounterState : public SocketCounterState friend std::vector getPCICFGEvent(const PCM::RawEventEncoding& eventEnc, const SystemCounterState& before, const SystemCounterState& after); friend std::vector getMMIOEvent(const PCM::RawEventEncoding& eventEnc, const SystemCounterState& before, const SystemCounterState& after); friend std::vector getPMTEvent(const PCM::RawEventEncoding& eventEnc, const SystemCounterState& before, const SystemCounterState& after); + template friend bool systemEnergyStatusValid(const CounterStateType& s); + template friend uint64 getSystemConsumedEnergy(const CounterStateType& before, const CounterStateType& after); std::vector > incomingQPIPackets; // each 64 byte std::vector > outgoingQPIFlits; // idle or data/non-data flits depending on the architecture std::vector > TxL0Cycles; uint64 uncoreTSC; + uint64 systemEnergyStatus; std::unordered_map , PCM::PCICFGRegisterEncodingHash, PCM::PCICFGRegisterEncodingCmp> PCICFGValues{}; std::unordered_map, PCM::MMIORegisterEncodingHash, PCM::MMIORegisterEncodingCmp> MMIOValues{}; std::unordered_map, PCM::PMTRegisterEncodingHash2> PMTValues{}; @@ -3890,7 +3957,8 @@ class SystemCounterState : public SocketCounterState friend uint64 getOutgoingQPILinkBytes(uint32 socketNr, uint32 linkNr, const SystemCounterState & now); SystemCounterState() : - uncoreTSC(0) + uncoreTSC(0), + systemEnergyStatus(0) { PCM * m = PCM::getInstance(); accel_counters.resize(m->getNumberofAccelCounters()); @@ -3922,6 +3990,7 @@ class SystemCounterState : public SocketCounterState return *this; } + virtual ~ SystemCounterState() {} }; diff --git a/src/pcm.cpp b/src/pcm.cpp index ddce890e..c57d9a3a 100644 --- a/src/pcm.cpp +++ b/src/pcm.cpp @@ -336,7 +336,12 @@ void print_output(PCM * m, cout << resetColor(); cout << setNextColor() << "\n Instructions retired: " << unit_format(getInstructionsRetired(sstate1, sstate2)) << " ;" << setNextColor() << " Active cycles: " << unit_format(getCycles(sstate1, sstate2)) << " ;" - << setNextColor() << " Time (TSC): " << unit_format(getInvariantTSC(cstates1[0], cstates2[0])) << "ticks;\n\n"; + << setNextColor() << " Time (TSC): " << unit_format(getInvariantTSC(cstates1[0], cstates2[0])) << "ticks;"; + if (m->systemEnergyMetricAvailable() && systemEnergyStatusValid(sstate1) && systemEnergyStatusValid(sstate2)) + { + cout << setNextColor() << " SYS energy: " << getSystemConsumedJoules(sstate1, sstate2) << " J;"; + } + cout << "\n\n"; cout << resetColor() << setNextColor() << " Core C-state residencies: "<< setNextColor() << "C0 (active,non-halted): " << (getCoreCStateResidency(0, sstate1, sstate2)*100.) << " %;"; for (int s = 1; s <= PCM::MAX_C_STATE; ++s) diff --git a/src/types.h b/src/types.h index f6f33ce2..7a986ea4 100644 --- a/src/types.h +++ b/src/types.h @@ -506,6 +506,7 @@ constexpr auto MSR_SMI_COUNT = 0x34; */ constexpr auto MSR_PKG_ENERGY_STATUS = 0x611; +constexpr auto MSR_SYS_ENERGY_STATUS = 0x64D; constexpr auto MSR_RAPL_POWER_UNIT = 0x606; constexpr auto MSR_PKG_POWER_INFO = 0x614; diff --git a/src/width_extender.h b/src/width_extender.h index 7a78f11d..1043667c 100644 --- a/src/width_extender.h +++ b/src/width_extender.h @@ -40,12 +40,20 @@ class CounterWidthExtender { std::shared_ptr msr; uint64 msr_addr; - MsrHandleCounter(std::shared_ptr msr_, uint64 msr_addr_) : msr(msr_), msr_addr(msr_addr_) { } + uint64 msr_mask; + MsrHandleCounter( std::shared_ptr msr_, + const uint64 msr_addr_, + const uint64 msr_mask_ = ~uint64(0ULL)) : + msr(msr_), + msr_addr(msr_addr_), + msr_mask(msr_mask_) + { + } uint64 operator () () { uint64 value = 0; msr->read(msr_addr, &value); - return value; + return value & msr_mask; } };