The Sparta Modeling Framework
Loading...
Searching...
No Matches
ContextCounter.hpp
1// <ContextCounter> -*- C++ -*-
2
3
4#pragma once
5
6#include <boost/lexical_cast.hpp>
7#include <cstddef>
8#include <cstdint>
9#include <string>
10#include <cinttypes>
11#include <iterator>
12#include <ostream>
13#include <set>
14#include <type_traits>
15#include <utility>
16#include <vector>
17
20#include "sparta/statistics/ReadOnlyCounter.hpp"
21#include "sparta/report/Report.hpp"
23#include "sparta/trigger/ContextCounterTrigger.hpp"
28
29namespace sparta {
30class CounterBase;
31class ReadOnlyCounter;
32class StatisticSet;
33} // namespace sparta
34
35// Non-template internal counter information for JSON serialization
37 std::string name_;
38 std::string desc_;
40 double val_ = 0;
41 const void * ctx_addr_ = nullptr;
42};
43
44bool __groupedPrinting(
45 std::set<const void*> & dont_print_these,
46 void * grouped_json_, void * doc_,
47 const std::vector<ContextCounterInfo> & ctx_info,
48 const std::string & aggregate_desc,
50
51bool __groupedPrintingReduced(
52 std::set<const void*> & dont_print_these,
53 void * grouped_json_, void * doc_,
54 const std::vector<ContextCounterInfo> & ctx_info);
55
56bool __groupedPrintingDetail(
57 std::set<const void*> & dont_print_these,
58 void * grouped_json_, void * doc_,
59 const std::vector<ContextCounterInfo> & ctx_info);
60
61namespace sparta
62{
216 template<class CounterT>
218 {
219
220 StatisticDef::ExpressionArg generateExprArg_(uint32_t num_contexts, const std::string & context_name) const
221 {
222 std::stringstream expr;
223 uint32_t i = 0;
224 expr << context_name << i;
225 ++i;
226 while(i < num_contexts) {
227 expr << "+" << context_name << i;
228 ++i;
229 }
230 return expr.str();
231 }
232
233 virtual bool groupedPrinting(const std::vector<const StatisticInstance*> & sub_stats,
234 std::set<const void*> & dont_print_these,
235 void * grouped_json_,
236 void * doc_) const override
237 {
238 extractCtxInfo_(sub_stats);
239 return __groupedPrinting(dont_print_these, grouped_json_, doc_,
240 ctx_info_, getDesc(), getVisibility());
241 }
242
243 virtual bool groupedPrintingReduced(const std::vector<const StatisticInstance*> & sub_stats,
244 std::set<const void*> & dont_print_these,
245 void * grouped_json_,
246 void * doc_) const override
247 {
248 extractCtxInfo_(sub_stats);
249 return __groupedPrintingReduced(dont_print_these, grouped_json_, doc_, ctx_info_);
250 }
251
252 virtual bool groupedPrintingDetail(const std::vector<const StatisticInstance*> & sub_stats,
253 std::set<const void*> & dont_print_these,
254 void * grouped_json_,
255 void * doc_) const override
256 {
257 extractCtxInfo_(sub_stats);
258 return __groupedPrintingDetail(dont_print_these, grouped_json_, doc_, ctx_info_);
259 }
260
261 void extractCtxInfo_(const std::vector<const StatisticInstance*> & sub_stats) const
262 {
263 if (!ctx_info_.empty()) {
264 sparta_assert(sub_stats.size() == ctx_info_.size());
265 for (size_t idx = 0; idx < sub_stats.size(); ++idx) {
266 const auto & stat_si = sub_stats[idx];
267 auto & ctx_info = ctx_info_[idx];
268 ctx_info.val_ = stat_si->getValue();
269 }
270 return;
271 }
272
273 sparta_assert(sub_stats.size() == internal_counters_.size());
274
275 ctx_info_.reserve(internal_counters_.size());
276 for (size_t idx = 0; idx < sub_stats.size(); ++idx) {
277 const auto & counter = internal_counters_[idx];
278 const auto & stat_si = sub_stats[idx];
279
281 info.name_ = counter.getName();
282 info.desc_ = counter.getDesc();
283 info.vis_ = counter.getVisibility();
284 info.val_ = stat_si->getValue();
285 info.ctx_addr_ = &counter;
286 ctx_info_.push_back(info);
287
288 //There is code that needs to know our internal_counter_
289 //variables' this pointers. That code goes through the
290 //StatisticDef::getSubStatistics() method to get those
291 //pointers without asking the ContextCounter directly.
292 //This assertion is to prevent that outside logic from
293 //breaking unexpectedly.
294 sparta_assert(stat_si->getCounter() == &counter);
295 }
296 }
297
298 mutable std::vector<ContextCounterInfo> ctx_info_;
299
300 public:
301 using counter_type = CounterT;
302
306
317 template <class... CounterTArgs>
319 const std::string & name,
320 const std::string & desc,
321 const uint32_t num_contexts,
322 const std::string & context_name,
323 CounterTArgs && ...args) :
324 ContextCounter(stat_set,
325 name,
326 desc,
327 num_contexts,
328 generateExprArg_(num_contexts, context_name),
329 context_name,
330 std::forward<CounterTArgs>(args)...)
331 { }
332
344 template <class... CounterTArgs>
346 const std::string & name,
347 const std::string & desc,
348 const uint32_t num_contexts,
349 const StatisticDef::ExpressionArg & expression,
350 const std::string & context_name,
351 CounterTArgs && ...args) :
352 sparta::StatisticDef(stat_set, name, desc + " aggregate", this, expression)
353 {
354 static_assert(std::is_same<sparta::ReadOnlyCounter, CounterT>::value == false,
355 "The Counter type (CounterT) of ContextCounter cannot be a ReadOnlyCounter -- doesn't make sense!");
356 static_assert(std::is_base_of<sparta::CounterBase, CounterT>::value,
357 "The Counter type (CounterT) of ContextCounter must be a sparta::CounterBase type");
358
359 // You MUST reserve memory for the Counters in the vector
360 // otherwise, the vector will MOVE the counters internally
361 // on each growth and reorder the counters in the tree --
362 // putting them out-of-order
363 internal_counters_.reserve(num_contexts);
364 for(uint32_t i = 0; i < num_contexts; ++i) {
365 internal_counters_.emplace_back(this,
366 context_name + utils::uint32_to_str(i),
367 "A context of counter " + name, args...);
368 }
369
370 auto make_sub_stat_name = [&context_name](const std::string & name,
371 const size_t sub_stat_index) {
372 std::ostringstream oss;
373 oss << name << "_" << context_name << sub_stat_index;
374 return oss.str();
375 };
376
377 size_t sub_stat_index = 0;
378 for (const auto & counter : internal_counters_) {
379 addSubStatistic_(&counter, make_sub_stat_name(name, sub_stat_index));
380 ++sub_stat_index;
381 }
382
383 addMetadata_("context_name", context_name);
384 addMetadata_("num_contexts", std::to_string(num_contexts));
385
386 begin_counter_ = &internal_counters_.front();
387 end_counter_ = &internal_counters_.back();
388 ++end_counter_;
389 }
390
395 const counter_type & context(const uint32_t idx) const {
396 sparta_assert(idx < internal_counters_.size());
397 return internal_counters_[idx];
398 }
399
404 counter_type & context(const uint32_t idx) {
405 sparta_assert(idx < internal_counters_.size());
406 return internal_counters_[idx];
407 }
408
412 const counter_type * begin() const {
413 sparta_assert(begin_counter_);
414 return begin_counter_;
415 }
416
420 const counter_type * end() const {
421 sparta_assert(end_counter_);
422 return end_counter_;
423 }
424
428 uint32_t numContexts() const {
429 return std::distance(begin(), end());
430 }
431
432 private:
433 // Internal counters
434 std::vector<CounterT> internal_counters_;
435 counter_type * begin_counter_ = nullptr;
436 counter_type * end_counter_ = nullptr;
437 };
438
439}
440
477#define REGISTER_CONTEXT_COUNTER_AGGREGATE_FCN(ClassT, method, aggregated_value) \
478 static_assert(std::is_base_of<sparta::TreeNode, ClassT>::value, \
479 "Invalid attempt to register a context counter aggregate function " \
480 "that is not a method of a sparta::TreeNode subclass."); \
481 { \
482 auto handler = CREATE_SPARTA_HANDLER(ClassT, method); \
483 sparta::trigger::ContextCounterTrigger:: \
484 registerContextCounterAggregateFcn(handler, this, #method, aggregated_value); \
485 }
486
Virtual interface node for simulator instrumentation (e.g. counters, stats, nontifications).
Set of macros for Sparta assertions. Caught by the framework.
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
File that contains the macro used to generate the class callbacks.
Contains a statistic definition (some useful information which can be computed)
Contains a StatisticInstance which refers to a StatisticDef or Counter and some local state to comput...
File that defines the StatisticSet class.
Cool string utilities.
A container type that allows a modeler to build, store, and charge counts to a specific context.
ContextCounter(StatisticSet *stat_set, const std::string &name, const std::string &desc, const uint32_t num_contexts, const std::string &context_name, CounterTArgs &&...args)
ContextCounter constructor.
const counter_type * end() const
Return a pointer to one past the last internal counter.
uint32_t numContexts() const
Return the number of contexts in this ContextCounter.
counter_type & context(const uint32_t idx)
Return the internal counter at the given context.
const counter_type & context(const uint32_t idx) const
Return the internal counter at the given context.
ContextCounter(StatisticSet *stat_set, const std::string &name, const std::string &desc, const uint32_t num_contexts, const StatisticDef::ExpressionArg &expression, const std::string &context_name, CounterTArgs &&...args)
ContextCounter constructor.
const counter_type * begin() const
Return a pointer to the first internal counter.
uint32_t visibility_t
Continuous visibility level. Several key points along continum are indicated within Visibility.
visibility_t getVisibility() const
Gets the visibility hint of this node. This is invariant after construction.
void addMetadata_(const std::string &key, const std::string &value)
Add any arbitrary metadata as strings to this object. Used to add extra information to statistics rep...
Contains a statistic definition (some useful information which can be computed)
void addSubStatistic_(const TreeNode *stat_node, const std::string &stat_name) const
Allow subclasses to forward along substatistic information to this stat definition....
Set of StatisticDef and CounterBase-derived objects for visiblility through a sparta Tree.
const std::string & getDesc() const
Gets the description of this node.
Macros for handling exponential backoff.
Intermediate type for minimizing the number of distinct constructors that must be created for this cl...