10#include <boost/algorithm/string/replace.hpp>
11#include <boost/any.hpp>
12#include <boost/iterator/iterator_traits.hpp>
13#include <boost/type_index/type_index_facade.hpp>
22#include <unordered_map>
23#include <unordered_set>
28#include "sparta/report/Report.hpp"
29#include "sparta/utils/Utils.hpp"
30#include "sparta/report/format/BaseFormatter.hpp"
32#include "simdb_fwd.hpp"
43 class SimulationConfiguration;
46namespace sparta::trigger {
47 class SkippedAnnotatorBase;
55 class FormatterFactory;
64 namespace statistics {
70 class AsyncTimeseriesReport;
71 class AsyncNonTimeseriesReport;
81 typedef std::unordered_map<std::string, boost::any> NamedExtensions;
82 typedef std::unordered_map<std::string, std::string> TriggerKeyValues;
83 typedef std::unordered_map<std::string, std::string> MetaDataKeyValues;
91 typedef std::pair<Report*, report::format::BaseFormatter*> inst_t;
98 std::set<const Report*> triggered_reports_;
108 std::set<const Report*> idle_reports_;
113 std::map<std::string, std::shared_ptr<report::format::BaseFormatter>> formatters_;
119 std::shared_ptr<statistics::ReportStatisticsArchive> report_archive_;
125 std::shared_ptr<statistics::StreamNode> streaming_stats_root_;
133 bool updateReportActiveState_(
const Report * r);
139 std::vector<inst_t> instantiations_;
146 const sparta::report::format::FormatterFactory* fact_;
163 class DescUpdateTracker {
165 void enable(
const Scheduler * scheduler);
166 bool checkIfDuplicateUpdate();
177 DescUpdateTracker update_tracker_;
183 std::shared_ptr<sparta::trigger::SkippedAnnotatorBase> skipped_annotator_;
188 bool report_stopped_ =
false;
194 bool enabled_ =
true;
203 std::string orig_dest_file_;
211 std::shared_ptr<async::AsyncTimeseriesReport> db_timeseries_;
219 std::shared_ptr<async::AsyncNonTimeseriesReport> db_non_timeseries_;
329 simdb::AsyncTaskEval * task_queue,
330 simdb::ObjectManager * sim_db,
331 const Clock & root_clk);
343 simdb::AsyncTaskEval * task_queue,
344 simdb::ObjectManager * sim_db);
364 simdb::AsyncTaskEval * task_queue,
365 simdb::ObjectManager * sim_db);
372 std::map<std::string, std::shared_ptr<
411 const std::string& _def_file,
412 const std::string& _dest_file,
413 const std::string& _format=
"text");
451 return orig_dest_file_;
461 const std::string & dir);
479 report_stopped_ =
true;
486 std::stringstream ss;
488 <<
"\" -> \"" << (orig_dest_file_.empty() ?
dest_file : orig_dest_file_) <<
"\"";
490 ss <<
" (format=" <<
format <<
")";
518 std::ostream* out=
nullptr);
525 return instantiations_;
535 const std::vector<Report*> & pending_reports =
536 boost::any_cast<const std::vector<Report*>&>(iter->second);
538 return pending_reports;
552 std::unordered_set<Report*> all(pending.begin(), pending.end());
553 for (
const auto & cur : current) {
554 all.insert(cur.first);
556 return std::vector<Report*>(all.begin(), all.end());
631 const std::string& sim_name,
635 typedef std::vector<ReportDescriptor> ReportDescVec;
636 typedef std::vector<std::pair<std::string, std::string>> ReportYamlReplacements;
671 const std::string desc_name = getDescriptorName_(rd);
672 auto iter = indices_by_descriptor_name_.find(desc_name);
673 if (iter != indices_by_descriptor_name_.end()) {
676 if (rep_descs_.at(iter->second).isEnabled()) {
678 desc_name <<
"' already exists in this configuration";
681 indices_by_descriptor_name_[desc_name] = rep_descs_.size();
692 rep_descs_.push_back(rd);
693 rep_descs_.back().enabled_ =
true;
697 template <
class... Args>
705 for (
auto &rd : rep_descs_) {
713 for (
const auto & rep_desc : rep_descs_) {
714 if (rep_desc.isEnabled()) {
728 bool contains(
const std::string & desc_name)
const {
729 auto iter = indices_by_descriptor_name_.find(desc_name);
730 if (iter == indices_by_descriptor_name_.end()) {
733 const auto replaced_desc_name = replaceDotsWithUnderscores_(desc_name);
734 iter = indices_by_descriptor_name_.find(replaced_desc_name);
739 if (iter == indices_by_descriptor_name_.end()) {
745 return rep_descs_.at(iter->second).isEnabled();
750 auto idx = getDescriptorIndexByName_(desc_name);
751 return rep_descs_.at(idx);
763 std::vector<std::string> names;
764 for (
const auto & rd : indices_by_descriptor_name_) {
765 if (rep_descs_.at(rd.second).isEnabled()) {
766 names.push_back(rd.first);
773 std::deque<ReportDescriptor>::iterator
begin() {
774 return rep_descs_.begin();
778 std::deque<ReportDescriptor>::const_iterator
begin()
const {
779 return rep_descs_.cbegin();
783 std::deque<ReportDescriptor>::iterator
end() {
784 return rep_descs_.end();
788 std::deque<ReportDescriptor>::const_iterator
end()
const {
789 return rep_descs_.cend();
794 return replaceDotsWithUnderscores_(rd.
dest_file);
797 std::string replaceDotsWithUnderscores_(
const std::string & str)
const {
798 std::string replaced = str;
799 boost::replace_all(replaced,
".",
"_");
803 size_t getDescriptorIndexByName_(
const std::string & desc_name)
const {
804 auto iter = indices_by_descriptor_name_.find(desc_name);
805 if (iter == indices_by_descriptor_name_.end()) {
808 const auto replaced_desc_name = replaceDotsWithUnderscores_(desc_name);
809 iter = indices_by_descriptor_name_.find(replaced_desc_name);
812 if (iter == indices_by_descriptor_name_.end()) {
813 throw SpartaException(
814 "No descriptor named '") << desc_name <<
"' exists";
821 if (!rep_descs_.at(iter->second).isEnabled()) {
822 throw SpartaException(
"The descriptor named '") << desc_name
823 <<
"' has already been disabled";
828 std::deque<ReportDescriptor> rep_descs_;
829 std::unordered_map<std::string, size_t> indices_by_descriptor_name_;
891 void republishReportCollection_();
894 void finishPythonInteraction_();
897 void disallowChangesToDescriptors_();
910 bool allow_descriptor_changes_ =
true;
918 const std::string & replacements_yaml);
926 const std::string & def_file,
952 const std::string & def_file,
954 const ReportYamlReplacements & placeholder_key_value_pairs);
961 const std::string & def_string,
File that defines the Clock class.
Exception class for all of Sparta.
Basic Node framework in sparta device tree composite pattern.
File that defines a ValidValue.
A representation of simulated time.
TreeNode which represents the root ("top") of a device tree.
A class that lets you schedule events now and in the future.
Used to construct and throw a standard C++ exception. Inherits from std::exception.
Node in a composite tree representing a sparta Tree item.
Collection of named feature values.
Configuration applicator class that is used for configuring a simulator's reports....
void addMemoryReportsFromYaml(const std::string &yaml_file)
const ReportDescriptorCollection * getDescriptors() const
Access the underlying report descriptors.
ReportDescriptorCollection * getDescriptors()
Access the underlying report descriptors.
void showAllReportDescriptorInfo()
Pretty print information about all app::ReportDescriptor's.
void serializeAllDescriptorsToYaml()
void addReportsFromYaml(const std::string &yaml_file)
void removeReportByName(const std::string &rd_name)
void addReport(const ReportDescriptor &rd)
Add one report descriptor to this collection.
This collection of ReportDescriptors is designed to never deallocate memory once it has been allocate...
std::vector< std::string > getAllDescriptorNames() const
bool contains(const std::string &desc_name) const
void removeDescriptorByName(const std::string &desc_name)
std::deque< ReportDescriptor >::const_iterator begin() const
Iterator access.
size_t size() const
Get the number of enabled descriptors in this collection.
ReportDescriptor & getDescriptorByName(const std::string &desc_name)
Access a descriptor by the app::ReportDescriptor's "dest_file".
std::deque< ReportDescriptor >::iterator end()
Iterator access.
std::deque< ReportDescriptor >::iterator begin()
Iterator access.
void push_back(const ReportDescriptor &rd)
Add one report descriptor to this collection.
std::deque< ReportDescriptor >::const_iterator end() const
Iterator access.
void emplace_back(Args &&... args)
Add one report descriptor to this collection.
bool empty() const
See if there are any enabled descriptors in this collection.
void clear()
Remove (disable) all descriptors from this collection.
Describes one or more report to instantiate.
~ReportDescriptor()
Destructor (note that triggered reports are automatically flushed)
MetaDataKeyValues header_metadata_
Metadata to include in report headers.
uint32_t getUsageCount() const
Returns the usage count (incremented by addInstantiation)
const std::string & getDescriptorDefFile() const
Getter for this descriptor's def_file, e.g. "simple_stats.yaml".
std::string format
Optional formatting string (how to write to the file). This is converted to lower-case at constructio...
std::vector< Report * > getAllInstantiations() const
Returns all report instantiations, including those already instantiated (no report start trigger) and...
std::string computeFilename(const Report *r, const std::string &sim_name, uint32_t idx) const
Computes the filename to which this reportdescriptor will be saved using any necessary variables in t...
uint32_t writeOutput(std::ostream *out=nullptr)
Saves all of the instantiations whose formatters do not support 'update' to their respective destinat...
std::map< std::string, std::shared_ptr< report::format::BaseFormatter > > getFormattersByFilename() const
Provide access to the formatters we have been using so they can coordinate with the reporting infrast...
void capUpdatesToOncePerTick(const Scheduler *scheduler)
Instruct this descriptor to automatically ignore any "duplicate" updates that occur at the exact same...
report::format::BaseFormatter * addInstantiation(Report *r, Simulation *sim, std::ostream *out=nullptr)
Tracks a report instantiated based on this descriptor and allocates a new formatter for it....
const std::string & getDescriptorFormat() const
Getter for this descriptor's format, e.g. "json_reduced".
std::string dest_file
Destination filename to which report will be written. Later this will represent other types of destin...
void configureAsyncTimeseriesReport(simdb::AsyncTaskEval *task_queue, simdb::ObjectManager *sim_db, const Clock &root_clk)
Switch this descriptor's timeseries report generation from synchronous .csv generation to asynchronou...
uint32_t getNumWrites() const
Returns the number of writes done on this report descriptor's instantiated report formatters.
uint32_t getNumUpdates() const
Returns the number of updates done on this report descriptor's instantiated report formatters.
std::vector< Report * > getPendingInstantiations() const
Returns a vector of reports that have not been instantiated yet, but will be when this report descrip...
static const char * GLOBAL_KEYWORD
Global search scope node keyword for report locations.
ReportDescriptor & operator=(const ReportDescriptor &)=default
Allow assignment.
void doPostProcessing(simdb::AsyncTaskEval *task_queue, simdb::ObjectManager *sim_db)
Do any post-simulation post processing steps needed. This is typically used for final wrap-up this de...
std::string loc_pattern
Node location string (pattern) on which report should be generated. Typically "" or top.
ReportDescriptor(const std::string &_loc_pattern, const std::string &_def_file, const std::string &_dest_file, const std::string &_format="text")
Construct a report decsriptor.
void clearDestinationFiles(const Simulation &sim)
Clears all destination files that will be filled with instances of this report descriptor.
ReportDescriptor(const ReportDescriptor &)=default
Allow construction.
db::ReportHeader * getTimeseriesDatabaseHeader()
Give access to the database timeseries header. This will return null when this descriptor is used for...
void disable()
Calling this method causes the simulation to skip this descriptor when it is setting up its reports....
const std::string & getDescriptorDestFile() const
Getter for this descriptor's dest_file, e.g. "out.json".
void inspectSimulatorFeatureValues(const app::FeatureConfiguration *feature_config)
Give the descriptor a chance to see the –feature values that were set at the command line,...
const std::string & getDescriptorOrigDestFile() const
When SimDB has automatic report verification enabled, this descriptor may have had its dest_file chan...
bool isEnabled() const
See if this descriptor is enabled or not. Disabling a descriptor means that it will be filtered from ...
std::vector< inst_t > getInstantiations() const
Returns the vector of instantiated reports based on this descriptor.
NamedExtensions extensions_
Key-value extensions used by parsers to bind opaque report configurations to descriptors.
void configureAsyncNonTimeseriesReport(simdb::AsyncTaskEval *task_queue, simdb::ObjectManager *sim_db)
Switch this descriptor's report generation from synchronous to asynchronous database persistence....
static bool isValidFormatName(const std::string &format)
Determines if format is a valid name for formatter. This allows the command line parser to disregard ...
void skipOutput()
Let the descriptor know to skip over one update of data.
std::shared_ptr< statistics::ReportStatisticsArchive > logOutputValuesToArchive(const std::string &dir)
Tell the descriptor to send all of its writeOutput / updateOutput statistics values to a binary archi...
std::string def_file
Filename of report definition. If '@', auto generates reports with all counters and stats of loc_patt...
std::shared_ptr< statistics::StreamNode > createRootStatisticsStream()
Create and return a StreamNode object that sits at the top of a tree hierarchy that describes the Rep...
bool isSingleTimeseriesReport() const
Check if this descriptor holds only one report instantiation, and that it is a timeseries report (....
void ignoreFurtherUpdates()
Report descriptors may be triggered to stop early - ensure no further updates are written to disk.
std::string stringize() const
Represents this descriptor as a string.
const std::string & getDescriptorPattern() const
Getter for this descriptor's pattern, e.g. "_global".
bool isSingleNonTimeseriesReport() const
Check if this descriptor holds only one report instantiation, and that it is not a timeseries report....
void setSkippedAnnotator(std::shared_ptr< sparta::trigger::SkippedAnnotatorBase > annotator)
Give this descriptor a specific annotator subclass for printing skipped update information to reports...
uint32_t updateOutput(std::ostream *out=nullptr)
Updates all of the instantiations whose formatters support 'update', possibly by writing to the desti...
Configuration applicator class that is used for configuring a simulator. Works in conjunction with sp...
Simulator which builds a sparta DeviceTree.
This class coordinates live SPARTA simulations (source) with binary output archives (sink).
When a simulation is configured to stream its statistics values for asynchronous processing,...
Provides a wrapper around a value to ensure that the value is assigned.
Sparta Application framework.
ReportDescVec createDescriptorsFromFile(const std::string &def_file, TreeNode *context)
Given a multi-report definition YAML file, parse it out into individual descriptors,...
ReportYamlReplacements createReplacementsFromYaml(const std::string &replacements_yaml)
Parse a YAML file containing key-value pairs into a single ReportYamlReplacements data structure.
ReportDescVec createDescriptorsFromDefinitionString(const std::string &def_string, TreeNode *context)
Given a multi-report definition string, parse it out into individual descriptors.
ReportDescVec createDescriptorsFromFileWithPlaceholderReplacements(const std::string &def_file, TreeNode *context, const ReportYamlReplacements &placeholder_key_value_pairs)
This method is similar to "createDescriptorsFromFile()", except that it can be used for report yaml f...
Macros for handling exponential backoff.