diff --git a/service/Makefile.am b/service/Makefile.am index 7763b09ed5..01635467e6 100644 --- a/service/Makefile.am +++ b/service/Makefile.am @@ -236,6 +236,10 @@ libgeopmd_la_SOURCES = $(include_HEADERS) \ src/TimeSignal.cpp \ src/TimeSignal.hpp \ src/TimeZero.cpp \ + src/VariorumIOGroup.cpp \ + src/VariorumIOGroup.hpp \ + src/VariorumJSONIO.cpp \ + src/VariorumJSONIO.hpp \ src/geopm_hash.c \ src/geopm_plugin.cpp \ src/geopm_sched.c \ diff --git a/service/src/IOGroup.cpp b/service/src/IOGroup.cpp index 0184136abb..dda069cc0f 100644 --- a/service/src/IOGroup.cpp +++ b/service/src/IOGroup.cpp @@ -30,6 +30,9 @@ #ifdef GEOPM_ENABLE_NVML #include "NVMLIOGroup.hpp" #endif +#ifdef GEOPM_VARIORUM_IOGROUP +#include "VariorumIOGroup.hpp" +#endif #ifdef GEOPM_ENABLE_LEVELZERO #include "LevelZeroIOGroup.hpp" #endif @@ -114,6 +117,10 @@ namespace geopm register_plugin(NVMLIOGroup::plugin_name(), NVMLIOGroup::make_plugin); #endif +#ifdef GEOPM_VARIORUM_IOGROUP + register_plugin(VariorumIOGroup::plugin_name(), + VariorumIOGroup::make_plugin); +#endif #ifdef GEOPM_ENABLE_LEVELZERO register_plugin(LevelZeroIOGroup::plugin_name(), LevelZeroIOGroup::make_plugin); diff --git a/service/src/VariorumIOGroup.cpp b/service/src/VariorumIOGroup.cpp index 88aafb21dd..8bfa7536ab 100644 --- a/service/src/VariorumIOGroup.cpp +++ b/service/src/VariorumIOGroup.cpp @@ -22,8 +22,8 @@ namespace geopm { - static const std::string FRESHNESS_FILE_NAME("freshness"); - static const std::string RAW_SCAN_HZ_FILE_NAME("raw_scan_hz"); +// static const std::string FRESHNESS_FILE_NAME("freshness"); +// static const std::string RAW_SCAN_HZ_FILE_NAME("raw_scan_hz"); static std::function get_formatted_file_reader(const std::string &path, const std::string &units) @@ -37,15 +37,13 @@ namespace geopm } VariorumIOGroup::VariorumIOGroup(const std::string &cpu_info_path) - : m_signal_available({{"Variorum::CPU_POWER", { + : m_signal_index_map({{"Variorum::CPU_POWER", { "Point in time power", - Agg::sum, - string_format_integer, - get_formatted_file_reader(cpu_info_path + "/power", "W"), - false, + variorum_get_node_power_json, + true, NAN, M_UNITS_WATTS, - IOGroup::M_SIGNAL_BEHAVIOR_VARIABLE}}, + }}, }) , m_time_zero(geopm::time_zero()) { @@ -59,20 +57,20 @@ namespace geopm m_initial_freshness = read_double_from_file(cpu_info_path + "/" + FRESHNESS_FILE_NAME, ""); - for (const auto &signal : m_signal_available) { + for (const auto &signal : m_signal_index_map) { // Attempt to call each of the read functions so we can fail // construction of this IOGroup if it isn't supported. signal.second.m_read_function(); } - register_signal_alias("BOARD_POWER", "Variorum::BOARD_POWER"); - register_signal_alias("BOARD_ENERGY", "Variorum::BOARD_ENERGY"); + register_signal_alias("CPU_POWER", "Variorum::CPU_POWER"); +// register_signal_alias("BOARD_ENERGY", "Variorum::BOARD_ENERGY"); } std::set VariorumIOGroup::signal_names(void) const { std::set names; - for (const auto &sv : m_signal_available) { + for (const auto &sv : m_signal_index_map) { names.insert(sv.first); } return names; @@ -85,7 +83,7 @@ namespace geopm bool VariorumIOGroup::is_valid_signal(const std::string &signal_name) const { - return m_signal_available.find(signal_name) != m_signal_available.end(); + return m_signal_index_map.find(signal_name) != m_signal_index_map.end(); } bool VariorumIOGroup::is_valid_control(const std::string &control_name) const @@ -95,7 +93,7 @@ namespace geopm int VariorumIOGroup::signal_domain_type(const std::string &signal_name) const { - return is_valid_signal(signal_name) ? GEOPM_DOMAIN_BOARD : GEOPM_DOMAIN_INVALID; + return is_valid_signal(signal_name) ? GEOPM_DOMAIN_PACKAGE : GEOPM_DOMAIN_INVALID; } int VariorumIOGroup::control_domain_type(const std::string &control_name) const @@ -111,14 +109,14 @@ namespace geopm "not valid for VariorumIOGroup", GEOPM_ERROR_INVALID, __FILE__, __LINE__); } - else if (domain_type != GEOPM_DOMAIN_BOARD) { + else if (domain_type != GEOPM_DOMAIN_PACKAGE) { throw Exception("VariorumIOGroup::push_signal(): domain_type " + std::to_string(domain_type) + "not valid for VariorumIOGroup", GEOPM_ERROR_INVALID, __FILE__, __LINE__); } - m_signal_available[signal_name].m_do_read = true; - return std::distance(m_signal_available.begin(), m_signal_available.find(signal_name)); + m_signal_index_map[signal_name].m_do_read = true; + return std::distance(m_signal_index_map.begin(), m_signal_index_map.find(signal_name)); } int VariorumIOGroup::push_control(const std::string &control_name, @@ -130,7 +128,8 @@ namespace geopm void VariorumIOGroup::read_batch(void) { - for (auto &signal : m_signal_available) { + m_is_batch_read = true; + for (auto &signal : m_signal_index_map) { if (signal.second.m_do_read) { signal.second.m_value = signal.second.m_read_function(); } @@ -142,8 +141,8 @@ namespace geopm double VariorumIOGroup::sample(int batch_idx) { double result = NAN; - auto res_it = m_signal_available.begin(); - if (batch_idx >= 0 && batch_idx < static_cast(m_signal_available.size())) { + auto res_it = m_signal_index_map.begin(); + if (batch_idx >= 0 && batch_idx < static_cast(m_signal_index_map.size())) { std::advance(res_it, batch_idx); if(res_it->second.m_do_read) { result = res_it->second.m_value; @@ -181,7 +180,7 @@ namespace geopm "not valid for VariorumIOGroup", GEOPM_ERROR_INVALID, __FILE__, __LINE__); } - return m_signal_available.find(signal_name)->second.m_read_function(); + return m_signal_index_map.find(signal_name)->second.m_read_function(); } void VariorumIOGroup::write_control(const std::string &control_name, @@ -200,8 +199,8 @@ namespace geopm std::function &)> VariorumIOGroup::agg_function(const std::string &signal_name) const { - auto it = m_signal_available.find(signal_name); - if (it == m_signal_available.end()) { + auto it = m_signal_index_map.find(signal_name); + if (it == m_signal_index_map.end()) { throw Exception("VariorumIOGroup::agg_function(): unknown how to aggregate \"" + signal_name + "\"", GEOPM_ERROR_INVALID, __FILE__, __LINE__); @@ -212,8 +211,8 @@ namespace geopm std::function VariorumIOGroup::format_function(const std::string &signal_name) const { - auto it = m_signal_available.find(signal_name); - if (it == m_signal_available.end()) { + auto it = m_signal_index_map.find(signal_name); + if (it == m_signal_index_map.end()) { throw Exception("VariorumIOGroup::format_function(): unknown how to format \"" + signal_name + "\"", GEOPM_ERROR_INVALID, __FILE__, __LINE__); @@ -230,8 +229,8 @@ namespace geopm } std::string result = "Invalid signal description: no description found."; - auto it = m_signal_available.find(signal_name); - if (it != m_signal_available.end()) { + auto it = m_signal_index_map.find(signal_name); + if (it != m_signal_index_map.end()) { result = " description: " + it->second.m_description + '\n'; // Includes alias_for if applicable result += " units: " + IOGroup::units_to_string(it->second.m_units) + '\n'; result += " aggregation: " + Agg::function_to_name(it->second.m_agg_function) + '\n'; @@ -263,8 +262,8 @@ namespace geopm GEOPM_ERROR_INVALID, __FILE__, __LINE__); } int result = -1; - auto it = m_signal_available.find(signal_name); - if (it != m_signal_available.end()) { + auto it = m_signal_index_map.find(signal_name); + if (it != m_signal_index_map.end()) { result = it->second.m_behavior; } #ifdef GEOPM_DEBUG @@ -300,20 +299,20 @@ namespace geopm void VariorumIOGroup::register_signal_alias(const std::string &alias_name, const std::string &signal_name) { - if (m_signal_available.find(alias_name) != m_signal_available.end()) { + if (m_signal_index_map.find(alias_name) != m_signal_index_map.end()) { throw Exception("VariorumIOGroup::register_signal_alias(): signal_name " + alias_name + " was previously registered.", GEOPM_ERROR_INVALID, __FILE__, __LINE__); } - auto it = m_signal_available.find(signal_name); - if (it == m_signal_available.end()) { + auto it = m_signal_index_map.find(signal_name); + if (it == m_signal_index_map.end()) { // skip adding an alias if underlying signal is not found return; } // copy signal info but append to description - m_signal_available[alias_name] = it->second; - m_signal_available[alias_name].m_description = - m_signal_available[signal_name].m_description + '\n' + " alias_for: " + signal_name; + m_signal_index_map[alias_name] = it->second; + m_signal_index_map[alias_name].m_description = + m_signal_index_map[signal_name].m_description + '\n' + " alias_for: " + signal_name; } void VariorumIOGroup::save_control(const std::string &save_path) diff --git a/service/src/VariorumIOGroup.hpp b/service/src/VariorumIOGroup.hpp index 559424423c..4b80243e3a 100644 --- a/service/src/VariorumIOGroup.hpp +++ b/service/src/VariorumIOGroup.hpp @@ -2,8 +2,8 @@ * Copyright (c) 2015 - 2023, Intel Corporation * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef CNLIOGROUP_HPP_INCLUDE -#define CNLIOGROUP_HPP_INCLUDE +#ifndef VARIORUMIOGROUP_HPP_INCLUDE +#define VARIORUMIOGROUP_HPP_INCLUDE #include #include @@ -15,20 +15,20 @@ namespace geopm { /// @brief IOGroup that wraps interfaces to Compute Node Linux. /// - /// @details The CNLIOGroup provides board-level energy counters from Compute Node Linux + /// @details The VariorumIOGroup provides board-level energy counters from Compute Node Linux /// as signals. These values are obtained through the proc(5) - class CNLIOGroup : public IOGroup + class VariorumIOGroup : public IOGroup { public: - CNLIOGroup(); - CNLIOGroup(const std::string &pm_counters_path); - virtual ~CNLIOGroup() = default; + VariorumIOGroup(); + VariorumIOGroup(const std::string &pm_counters_path); + virtual ~VariorumIOGroup() = default; /// @return the list of signal names provided by this IOGroup. std::set signal_names(void) const override; /// @return empty set; this IOGroup does not provide any controls. std::set control_names(void) const override; /// @return whether the given signal_name is supported by the - /// CNLIOGroup for the current platform. + /// VariorumIOGroup for the current platform. bool is_valid_signal(const std::string &signal_name) const override; /// @return false; this IOGroup does not provide any controls. bool is_valid_control(const std::string &control_name) const override; @@ -50,7 +50,7 @@ namespace geopm int domain_idx) override; /// @brief Should not be called; this IOGroup does not provide any controls. /// - /// @throws geopm::Exception there are no controls supported by the CNLIOGroup + /// @throws geopm::Exception there are no controls supported by the VariorumIOGroup int push_control(const std::string &control_name, int domain_type, int domain_idx) override; /// @brief Read all pushed signals from the platform so that the next call to @@ -69,7 +69,7 @@ namespace geopm double sample(int batch_idx) override; /// @brief Should not be called; this IOGroup does not provide any controls. /// - /// @throws geopm::Exception there are no controls supported by the CNLIOGroup + /// @throws geopm::Exception there are no controls supported by the VariorumIOGroup void adjust(int batch_idx, double setting) override; /// @param signal_name Specifies the name of the signal whose value you want to get. /// @@ -86,7 +86,7 @@ namespace geopm int domain_idx) override; /// @brief Should not be called; this IOGroup does not provide any controls. /// - /// @throws geopm::Exception there are no controls supported by the CNLIOGroup + /// @throws geopm::Exception there are no controls supported by the VariorumIOGroup void write_control(const std::string &control_name, int domain_type, int domain_idx, double setting) override; /// @brief Does nothing; this IOGroup does not provide any controls. @@ -109,7 +109,7 @@ namespace geopm std::string signal_description(const std::string &signal_name) const override; /// @brief Should not be called; this IOGroup does not provide any controls. /// - /// @throws geopm::Exception there are no controls supported by the CNLIOGroup + /// @throws geopm::Exception there are no controls supported by the VariorumIOGroup std::string control_description(const std::string &control_name) const override; /// @return one of the IOGroup::signal_behavior_e values which /// describes about how a signal will change as a function of time. @@ -132,7 +132,7 @@ namespace geopm /// /// @see geopm::PluginFactory static std::string plugin_name(void); - /// @return a pointer to a new CNLIOGroup object + /// @return a pointer to a new VariorumIOGroup object /// /// @see geopm::PluginFactory static std::unique_ptr make_plugin(void); @@ -142,13 +142,13 @@ namespace geopm struct m_signal_info_s { std::string m_description; - std::function &)> m_agg_function; - std::function m_format_function; +// std::function &)> m_agg_function; +// std::function m_format_function; std::function m_read_function; bool m_do_read; double m_value; int m_units; - int m_behavior; +// int m_behavior; }; std::map m_signal_available; diff --git a/service/src/VariorumJSONIO.cpp b/service/src/VariorumJSONIO.cpp new file mode 100644 index 0000000000..8bfa7536ab --- /dev/null +++ b/service/src/VariorumJSONIO.cpp @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2015 - 2023, Intel Corporation + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "VariorumIOGroup.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#include "geopm/Agg.hpp" +#include "geopm/Exception.hpp" +#include "geopm/Helper.hpp" +#include "geopm/PlatformTopo.hpp" + +#include "config.h" + +namespace geopm +{ +// static const std::string FRESHNESS_FILE_NAME("freshness"); +// static const std::string RAW_SCAN_HZ_FILE_NAME("raw_scan_hz"); + + static std::function get_formatted_file_reader(const std::string &path, + const std::string &units) + { + return std::bind(read_double_from_file, path, units); + } + + VariorumIOGroup::VariorumIOGroup() + : VariorumIOGroup("Variorum") + { + } + + VariorumIOGroup::VariorumIOGroup(const std::string &cpu_info_path) + : m_signal_index_map({{"Variorum::CPU_POWER", { + "Point in time power", + variorum_get_node_power_json, + true, + NAN, + M_UNITS_WATTS, + }}, + }) + , m_time_zero(geopm::time_zero()) + { + m_sample_rate = read_double_from_file( + cpu_info_path + "/" + RAW_SCAN_HZ_FILE_NAME, ""); + if (m_sample_rate <= 0) { + throw Exception("VariorumIOGroup::VariorumIOGroup(): Unexpected sample frequency " + + std::to_string(m_sample_rate), + GEOPM_ERROR_RUNTIME, __FILE__, __LINE__); + } + m_initial_freshness = + read_double_from_file(cpu_info_path + "/" + FRESHNESS_FILE_NAME, ""); + + for (const auto &signal : m_signal_index_map) { + // Attempt to call each of the read functions so we can fail + // construction of this IOGroup if it isn't supported. + signal.second.m_read_function(); + } + + register_signal_alias("CPU_POWER", "Variorum::CPU_POWER"); +// register_signal_alias("BOARD_ENERGY", "Variorum::BOARD_ENERGY"); + } + + std::set VariorumIOGroup::signal_names(void) const + { + std::set names; + for (const auto &sv : m_signal_index_map) { + names.insert(sv.first); + } + return names; + } + + std::set VariorumIOGroup::control_names(void) const + { + return {}; + } + + bool VariorumIOGroup::is_valid_signal(const std::string &signal_name) const + { + return m_signal_index_map.find(signal_name) != m_signal_index_map.end(); + } + + bool VariorumIOGroup::is_valid_control(const std::string &control_name) const + { + return false; + } + + int VariorumIOGroup::signal_domain_type(const std::string &signal_name) const + { + return is_valid_signal(signal_name) ? GEOPM_DOMAIN_PACKAGE : GEOPM_DOMAIN_INVALID; + } + + int VariorumIOGroup::control_domain_type(const std::string &control_name) const + { + return GEOPM_DOMAIN_INVALID; + } + + int VariorumIOGroup::push_signal(const std::string &signal_name, int domain_type, + int domain_idx) + { + if (!is_valid_signal(signal_name)) { + throw Exception("VariorumIOGroup::push_signal(): " + signal_name + + "not valid for VariorumIOGroup", + GEOPM_ERROR_INVALID, __FILE__, __LINE__); + } + else if (domain_type != GEOPM_DOMAIN_PACKAGE) { + throw Exception("VariorumIOGroup::push_signal(): domain_type " + std::to_string(domain_type) + + "not valid for VariorumIOGroup", + GEOPM_ERROR_INVALID, __FILE__, __LINE__); + } + + m_signal_index_map[signal_name].m_do_read = true; + return std::distance(m_signal_index_map.begin(), m_signal_index_map.find(signal_name)); + } + + int VariorumIOGroup::push_control(const std::string &control_name, + int domain_type, int domain_idx) + { + throw Exception("VariorumIOGroup::push_control(): there are no controls supported by the VariorumIOGroup", + GEOPM_ERROR_INVALID, __FILE__, __LINE__); + } + + void VariorumIOGroup::read_batch(void) + { + m_is_batch_read = true; + for (auto &signal : m_signal_index_map) { + if (signal.second.m_do_read) { + signal.second.m_value = signal.second.m_read_function(); + } + } + } + + void VariorumIOGroup::write_batch(void) {} + + double VariorumIOGroup::sample(int batch_idx) + { + double result = NAN; + auto res_it = m_signal_index_map.begin(); + if (batch_idx >= 0 && batch_idx < static_cast(m_signal_index_map.size())) { + std::advance(res_it, batch_idx); + if(res_it->second.m_do_read) { + result = res_it->second.m_value; + } + else if (!res_it->second.m_do_read) { + throw Exception("VariorumIOGroup::sample(): batch_idx " + + std::to_string(batch_idx) + " has not been pushed", + GEOPM_ERROR_INVALID, __FILE__, __LINE__); + } + } + else { + throw Exception("VariorumIOGroup::sample(): batch_idx " + std::to_string(batch_idx) + + "not valid for VariorumIOGroup", + GEOPM_ERROR_INVALID, __FILE__, __LINE__); + } + return result; + } + + void VariorumIOGroup::adjust(int batch_idx, double setting) + { + throw Exception("VariorumIOGroup::adjust(): there are no controls supported by the VariorumIOGroup", + GEOPM_ERROR_INVALID, __FILE__, __LINE__); + } + + double VariorumIOGroup::read_signal(const std::string &signal_name, + int domain_type, int domain_idx) + { + if (!is_valid_signal(signal_name)) { + throw Exception("VariorumIOGroup::read_signal(): " + signal_name + + "not valid for VariorumIOGroup", + GEOPM_ERROR_INVALID, __FILE__, __LINE__); + } + else if (domain_type != GEOPM_DOMAIN_BOARD) { + throw Exception("VariorumIOGroup:read_signal(): domain_type " + std::to_string(domain_type) + + "not valid for VariorumIOGroup", + GEOPM_ERROR_INVALID, __FILE__, __LINE__); + } + return m_signal_index_map.find(signal_name)->second.m_read_function(); + } + + void VariorumIOGroup::write_control(const std::string &control_name, + int domain_type, int domain_idx, double setting) + { + throw Exception( + "VariorumIOGroup::write_control(): there are no controls " + "supported by the VariorumIOGroup", + GEOPM_ERROR_INVALID, __FILE__, __LINE__); + } + + void VariorumIOGroup::save_control(void) {} + + void VariorumIOGroup::restore_control(void) {} + + std::function &)> + VariorumIOGroup::agg_function(const std::string &signal_name) const + { + auto it = m_signal_index_map.find(signal_name); + if (it == m_signal_index_map.end()) { + throw Exception("VariorumIOGroup::agg_function(): unknown how to aggregate \"" + + signal_name + "\"", + GEOPM_ERROR_INVALID, __FILE__, __LINE__); + } + return it->second.m_agg_function; + } + + std::function + VariorumIOGroup::format_function(const std::string &signal_name) const + { + auto it = m_signal_index_map.find(signal_name); + if (it == m_signal_index_map.end()) { + throw Exception("VariorumIOGroup::format_function(): unknown how to format \"" + + signal_name + "\"", + GEOPM_ERROR_INVALID, __FILE__, __LINE__); + } + return it->second.m_format_function; + } + + std::string VariorumIOGroup::signal_description(const std::string &signal_name) const + { + if (!is_valid_signal(signal_name)) { + throw Exception("VariorumIOGroup::signal_description(): " + signal_name + + "not valid for VariorumIOGroup", + GEOPM_ERROR_INVALID, __FILE__, __LINE__); + } + + std::string result = "Invalid signal description: no description found."; + auto it = m_signal_index_map.find(signal_name); + if (it != m_signal_index_map.end()) { + result = " description: " + it->second.m_description + '\n'; // Includes alias_for if applicable + result += " units: " + IOGroup::units_to_string(it->second.m_units) + '\n'; + result += " aggregation: " + Agg::function_to_name(it->second.m_agg_function) + '\n'; + result += " domain: " + PlatformTopo::domain_type_to_name(GEOPM_DOMAIN_BOARD) + '\n'; + result += " iogroup: VariorumIOGroup"; + } +#ifdef GEOPM_DEBUG + else { + throw Exception("VariorumIOGroup::signal_description(): signal valid but not found in map", + GEOPM_ERROR_LOGIC, __FILE__, __LINE__); + } +#endif + return result; + } + + std::string VariorumIOGroup::control_description(const std::string &control_name) const + { + throw Exception( + "VariorumIOGroup::control_description(): there are no controls " + "supported by the VariorumIOGroup", + GEOPM_ERROR_INVALID, __FILE__, __LINE__); + } + + int VariorumIOGroup::signal_behavior(const std::string &signal_name) const + { + if (!is_valid_signal(signal_name)) { + throw Exception("VariorumIOGroup::signal_behavior(): " + signal_name + + "not valid for VariorumIOGroup", + GEOPM_ERROR_INVALID, __FILE__, __LINE__); + } + int result = -1; + auto it = m_signal_index_map.find(signal_name); + if (it != m_signal_index_map.end()) { + result = it->second.m_behavior; + } +#ifdef GEOPM_DEBUG + else { + throw Exception("VariorumIOGroup::signal_description(): signal valid but not found in map", + GEOPM_ERROR_LOGIC, __FILE__, __LINE__); + } +#endif + return result; + } + + std::string VariorumIOGroup::name(void) const + { + return plugin_name(); + } + + std::string VariorumIOGroup::plugin_name(void) + { + return "Variorum"; + } + + std::unique_ptr VariorumIOGroup::make_plugin(void) + { + return geopm::make_unique(); + } + + double VariorumIOGroup::read_time(const std::string &freshness_path) const + { + auto freshness = read_double_from_file(freshness_path, ""); + return (freshness - m_initial_freshness) / m_sample_rate; + } + + void VariorumIOGroup::register_signal_alias(const std::string &alias_name, + const std::string &signal_name) + { + if (m_signal_index_map.find(alias_name) != m_signal_index_map.end()) { + throw Exception("VariorumIOGroup::register_signal_alias(): signal_name " + alias_name + + " was previously registered.", + GEOPM_ERROR_INVALID, __FILE__, __LINE__); + } + auto it = m_signal_index_map.find(signal_name); + if (it == m_signal_index_map.end()) { + // skip adding an alias if underlying signal is not found + return; + } + // copy signal info but append to description + m_signal_index_map[alias_name] = it->second; + m_signal_index_map[alias_name].m_description = + m_signal_index_map[signal_name].m_description + '\n' + " alias_for: " + signal_name; + } + + void VariorumIOGroup::save_control(const std::string &save_path) + { + + } + + void VariorumIOGroup::restore_control(const std::string &save_path) + { + + } +} diff --git a/service/src/VariorumJSONIO.hpp b/service/src/VariorumJSONIO.hpp new file mode 100644 index 0000000000..4b80243e3a --- /dev/null +++ b/service/src/VariorumJSONIO.hpp @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2015 - 2023, Intel Corporation + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef VARIORUMIOGROUP_HPP_INCLUDE +#define VARIORUMIOGROUP_HPP_INCLUDE + +#include +#include + +#include "geopm/IOGroup.hpp" +#include "geopm_time.h" + +namespace geopm +{ + /// @brief IOGroup that wraps interfaces to Compute Node Linux. + /// + /// @details The VariorumIOGroup provides board-level energy counters from Compute Node Linux + /// as signals. These values are obtained through the proc(5) + class VariorumIOGroup : public IOGroup + { + public: + VariorumIOGroup(); + VariorumIOGroup(const std::string &pm_counters_path); + virtual ~VariorumIOGroup() = default; + /// @return the list of signal names provided by this IOGroup. + std::set signal_names(void) const override; + /// @return empty set; this IOGroup does not provide any controls. + std::set control_names(void) const override; + /// @return whether the given signal_name is supported by the + /// VariorumIOGroup for the current platform. + bool is_valid_signal(const std::string &signal_name) const override; + /// @return false; this IOGroup does not provide any controls. + bool is_valid_control(const std::string &control_name) const override; + /// @return GEOPM_DOMAIN_BOARD; If the signal_name is valid for this IOGroup, + /// GEOPM_DOMAIN_INVALID otherwise if the signal_name is invalid for this IOGroup. + int signal_domain_type(const std::string &signal_name) const override; + /// @return GEOPM_DOMAIN_INVALID; this IOGroup does not provide any controls. + int control_domain_type(const std::string &control_name) const override; + /// @param signal_name Adds the signal specified to the list of signals to be read during read_batch() + /// + /// @param domain_type This must be == GEOPM_DOMAIN_BOARD + /// + /// @param domain_idx is ignored + /// + /// @throws geopm::Exception + /// if signal_name is not valid + /// if domain_type is not GEOPM_DOMAIN_BOARD + int push_signal(const std::string &signal_name, int domain_type, + int domain_idx) override; + /// @brief Should not be called; this IOGroup does not provide any controls. + /// + /// @throws geopm::Exception there are no controls supported by the VariorumIOGroup + int push_control(const std::string &control_name, int domain_type, + int domain_idx) override; + /// @brief Read all pushed signals from the platform so that the next call to + /// sample() will reflect the updated data. + /// + /// @details The intention is that read_batch() will read the all of the + /// IOGroup's signals into memory once per call. + void read_batch(void) override; + /// @brief Does nothing; this IOGroup does not provide any controls. + void write_batch(void) override; + /// @param batch_idx Specifies a signal_idx returned from push_signal() + /// + /// @return the value of the signal specified by a signal_idx returned from push_signal(). + /// + /// @details The value will have been updated by the most recent call to read_batch(). + double sample(int batch_idx) override; + /// @brief Should not be called; this IOGroup does not provide any controls. + /// + /// @throws geopm::Exception there are no controls supported by the VariorumIOGroup + void adjust(int batch_idx, double setting) override; + /// @param signal_name Specifies the name of the signal whose value you want to get. + /// + /// @param domain_type This must be == GEOPM_DOMAIN_BOARD + /// + /// @param domain_idx is ignored + /// + /// @throws geopm::Exception + /// if signal_name is not valid + /// if domain_type is not GEOPM_DOMAIN_BOARD + /// + /// @return the stored value for the given signal_name. + double read_signal(const std::string &signal_name, int domain_type, + int domain_idx) override; + /// @brief Should not be called; this IOGroup does not provide any controls. + /// + /// @throws geopm::Exception there are no controls supported by the VariorumIOGroup + void write_control(const std::string &control_name, int domain_type, + int domain_idx, double setting) override; + /// @brief Does nothing; this IOGroup does not provide any controls. + void save_control(void) override; + /// @brief Does nothing; this IOGroup does not provide any controls. + void restore_control(void) override; + /// @param signal_name Specifies the name of the signal to be used for aggregation. + /// + /// @return a function that should be used when aggregating the given signal. + /// + /// @see geopm::Agg + std::function &)> + agg_function(const std::string &signal_name) const override; + /// @return a function that should be used when formatting the given signal. + /// + /// @see geopm::Agg + std::function + format_function(const std::string &signal_name) const override; + /// @return a string description for signal_name, if defined. + std::string signal_description(const std::string &signal_name) const override; + /// @brief Should not be called; this IOGroup does not provide any controls. + /// + /// @throws geopm::Exception there are no controls supported by the VariorumIOGroup + std::string control_description(const std::string &control_name) const override; + /// @return one of the IOGroup::signal_behavior_e values which + /// describes about how a signal will change as a function of time. + /// + /// @details This can be used when generating reports to decide how to + /// summarize a signal's value for the entire application run. + int signal_behavior(const std::string &signal_name) const override; + /// @brief Does nothing; this IOGroup does not provide any controls. + /// + /// @param save_path this argument is ignored + void save_control(const std::string &save_path) override; + /// @brief Does nothing; this IOGroup does not provide any controls. + /// + /// @param save_path this argument is ignored + void restore_control(const std::string &save_path) override; + /// @return the name of the IOGroup + std::string name(void) const override; + /// @return the name of the plugin to use when this plugin is + /// registered with the IOGroup factory + /// + /// @see geopm::PluginFactory + static std::string plugin_name(void); + /// @return a pointer to a new VariorumIOGroup object + /// + /// @see geopm::PluginFactory + static std::unique_ptr make_plugin(void); + + private: + void register_signal_alias(const std::string &alias_name, const std::string &signal_name); + + struct m_signal_info_s { + std::string m_description; +// std::function &)> m_agg_function; +// std::function m_format_function; + std::function m_read_function; + bool m_do_read; + double m_value; + int m_units; +// int m_behavior; + }; + std::map m_signal_available; + + double read_time(const std::string &freshness_path) const; + + geopm_time_s m_time_zero; + double m_initial_freshness; + double m_sample_rate; + }; +} + +#endif