The Sparta Modeling Framework
Loading...
Searching...
No Matches
NestedPeventCollector.hpp
1// <NestedPeventCollector> -*- C++ -*-
2
3
10#pragma once
11
13#include "sparta/pairs/SpartaKeyPairs.hpp"
14#include "sparta/pevents/PeventTreeNode.hpp"
15#include "sparta/log/MessageSource.hpp"
17
18#include <boost/algorithm/string.hpp>
19
20#define PEVENT_COLLECTOR_NOTE "_pevent"
21namespace sparta {
22namespace pevents {
23
31 template<typename DataT>
33 public sparta::PairCollector<
34 typename MetaStruct::remove_any_pointer<
35 DataT>::type::SpartaPairDefinitionType>, public PeventCollectorTreeNode {
36
37 // Aliasing the actual Datatype of the collectable being collected as Data_t
38 typedef typename MetaStruct::remove_any_pointer<DataT>::type Data_t;
39
40 // Aliasing the Datatype of the Pair Definition of the collectable being collected as PairDef_t
41 typedef typename Data_t::SpartaPairDefinitionType PairDef_t;
42
43 using PairCollector<PairDef_t>::getPEventLogVector;
44 using PairCollector<PairDef_t>::turnOn_;
45 using PairCollector<PairDef_t>::turnOff_;
46 using PairCollector<PairDef_t>::collect_;
47
48 public:
49 using PairCollector<PairDef_t>::isCollecting;
50 NestedPeventCollector(const std::string& event_name,
51 sparta::TreeNode* parent,
52 const Clock* clk,
53 const bool verbosity=false) :
54 sparta::PairCollector<PairDef_t>(),
56 event_name+PEVENT_COLLECTOR_NOTE+(verbosity ? "_verbose" : "")),
57 event_name_(event_name),
58 message_src_(this,
59 event_name+PEVENT_COLLECTOR_NOTE,
60 "A collector used to collect pevent data."),
61 clk_(clk),
62 f_skew_(std::plus<uint64_t>()),
63 skew_(0u),
64 verbosity_(verbosity) {
65
66 // There should never be a null clock
67 sparta_assert (clk_ != nullptr);
68 }
69
70 virtual ~NestedPeventCollector() {}
71
77 template<typename... Targs>
78 void collect(const Data_t & obj,
79 const Targs &... pos_args) {
80 if(isCollecting()) {
81 collect_(obj, pos_args...);
83 }
84 }
85
87 virtual const std::string& eventName() override {
88 return event_name_;
89 }
90
91 void adjustSkew(const int32_t & skew_amount) {
92 skew_ = std::abs(skew_amount);
93 if(skew_amount >= 0) {
94 f_skew_ = std::plus<uint64_t>();
95 }
96 else {
97 f_skew_ = std::minus<uint64_t>();
98 }
99 }
100
109 virtual bool addTap(const std::string& type, const std::string& file, const bool verbose) override final {
110
111 // notice we only checkout on the lower case.
112 std::string lowertype = type;
113 boost::algorithm::to_lower(lowertype);
114 std::string lower_ev_name = event_name_;
115 boost::algorithm::to_lower(lower_ev_name);
116 if(( lowertype == lower_ev_name || lowertype == "all") && verbosity_ == verbose) {
117 // Make sure they cannot add taps after the trigger has fired.
118 sparta_assert(running_ == false, "Cannot turnOn a pevent collector for which go() has already been called.");
119
120 // only create a custom tap if we don't already have this one.
121 // we could potentially end up with duplicates since the user can turn collection
122 // on at treenodes that overlap
123 bool is_unique = true;
124 for(const auto& existing_tap : taps_) {
125 if(existing_tap->getDestination()->compareStrings(file) &&
126 (existing_tap->getCategoryName() == lowertype
127 || lowertype == "all")) {
128 is_unique = false;
129 break;
130 }
131 }
132
133 if(is_unique) {
134 // Setup a tap to capture the output.
135 taps_.emplace_back(new log::Tap(this, event_name_+PEVENT_COLLECTOR_NOTE, file));
136 // We detatch the tap since we need to wait till the trigger
137 // fires or is manually started to start pevent collection.
138 taps_[taps_.size() - 1]->detach();
139 // We did create a tap.
140 return true;
141 }
142 }
143
144 // We never added a tap because it was not appropriate for our
145 // event type.
146 return false;
147 }
148
149 // Coming in a bit.
150 virtual void turnOff(const std::string& type) override final {
151 sparta_assert(false, "peventTurnOff not yet supported");
152 if(type == event_name_) {
153
154 //remove the taps, this is coming in the future.
155 if(taps_.empty()) {
156 turnOff_();
157 }
158 }
159 }
160
166 virtual void go() override final {
167 if(taps_.size() > 0) {
168 running_ = true;
169 // Mark the pair collector running
170 turnOn_();
171 }
172
173 // replace the taps here so that we are officially collecting the data to file.
174 for(auto& tap : taps_) {
175 tap->reset(this);
176 }
177 }
178
179 protected:
180
185 virtual void generateCollectionString_() override final {
186
187 // Write the pevent to the log.
188 std::stringstream ss;
189
190 // Write the event name.
191 ss << "ev=" << "\"" << event_name_ << "\" ";
192
193 // Now write the cached key values.
194 for(const auto & pair : getPEventLogVector())
195 {
196 ss << pair.first << "=" << "\"" << pair.second << "\" ";
197 }
198
199 // Write the time
200 ss << "cyc=" << f_skew_(clk_->currentCycle(), skew_);
201
202 // Finish the line
203 ss << ";";
204 message_src_ << ss.str();
205 }
206
207 private:
208
209 const std::string event_name_;
210
211 // We are going to use sparta's logger to output our pevents for ease.
212 log::MessageSource message_src_;
213
214 // Log taps that this pevent is being outputted too.
215 std::vector<std::unique_ptr<log::Tap > > taps_;
216
217 // We do need a clock b/c each pevent records it's time.
218 const Clock* clk_;
219 std::function<uint64_t(const uint64_t &, const uint32_t &)> f_skew_;
220 uint32_t skew_;
221 bool verbosity_;
222 bool running_ = false;
223 };
224} // namespace pevents
225} // namespace sparta
226
File that defines the Clock class.
Contains a collection implementation of various compile-time metaprogramming and Type-Detection APIs ...
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
A representation of simulated time.
Definition Clock.hpp:51
Cycle currentCycle() const
Get the current cycle (uses current tick from the Scheduler)
Definition Clock.hpp:176
Node in a composite tree representing a sparta Tree item.
Definition TreeNode.hpp:205
Message source object associated with a sparta TreeNode through which messages can be sent.
Logging Tap. Attach to a TreeNode to intercept logging messages from any NotificationSource nodes in ...
Definition Tap.hpp:28
a class that is capable of recording pevents as key value pairs, where a PairDefinition has been defi...
virtual void generateCollectionString_() override final
Override the generateCollectionString_() of the bases PairCollector, In this method,...
virtual void go() override final
This method should be called on all pevent collectors when the trigger either manually fires to start...
virtual const std::string & eventName() override
Return the ev name.
void collect(const Data_t &obj, const Targs &... pos_args)
Actually collect the object, and write out a pevent. We ovverride the collect method to ensure the th...
virtual bool addTap(const std::string &type, const std::string &file, const bool verbose) override final
Mark this pevent with a tap to output the pevent's data to a file.
Macros for handling exponential backoff.