The Sparta Modeling Framework
Loading...
Searching...
No Matches
PeventCollector.hpp
1// <PeventCollector> -*- 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"
16#include <boost/algorithm/string.hpp>
17
18#define PEVENT_COLLECTOR_NOTE "_pevent"
19namespace sparta{
20namespace pevents{
21
59 template <class CollectedEntityType>
61 : public PairCollector<CollectedEntityType>, public PeventCollectorTreeNode
62 {
63 protected:
64 using PairCollector<CollectedEntityType>::getPEventLogVector;
65 using PairCollector<CollectedEntityType>::turnOn_;
66 using PairCollector<CollectedEntityType>::turnOff_;
67 using PairCollector<CollectedEntityType>::collect_;
68
69 public:
70 using PairCollector<CollectedEntityType>::isCollecting;
71 PeventCollector(const std::string& event_name, sparta::TreeNode* parent, const Clock* clk, const bool verbosity=false) :
72 PairCollector<CollectedEntityType>(),
73 PeventCollectorTreeNode(parent, event_name+PEVENT_COLLECTOR_NOTE+(verbosity ? "_verbose" : "")),
74 event_name_(event_name),
75 message_src_(this, event_name+PEVENT_COLLECTOR_NOTE, "A collector used to collect pevent data."),
76 clk_(clk),
77 f_skew_(std::plus<uint64_t>()),
78 skew_(0u),
79 verbosity_(verbosity)
80 {
81 // There should never be a null clock
82 sparta_assert (clk_ != nullptr);
83 }
84
85 virtual ~PeventCollector() {}
86
92 template<typename... Targs>
93 void collect(const typename CollectedEntityType::TypeCollected& obj,
94 const Targs&... pos_args)
95 {
96 if(isCollecting())
97 {
98 collect_(obj, pos_args...);
100 }
101 }
102
103
105 virtual const std::string& eventName() override
106 {
107 return event_name_;
108 }
109
110 void adjustSkew(const int32_t & skew_amount) {
111 skew_ = std::abs(skew_amount);
112 if(skew_amount >= 0) {
113 f_skew_ = std::plus<uint64_t>();
114 } else {
115 f_skew_ = std::minus<uint64_t>();
116 }
117 }
118
127 virtual bool addTap(const std::string& type, const std::string& file, const bool verbose) override final
128 {
129 // notice we only checkout on the lower case.
130 std::string lowertype = type;
131 boost::algorithm::to_lower(lowertype);
132 std::string lower_ev_name = event_name_;
133 boost::algorithm::to_lower(lower_ev_name);
134 if(( lowertype == lower_ev_name || lowertype == "all") && verbosity_ == verbose)
135 {
136 // Make sure they cannot add taps after the trigger has fired.
137 sparta_assert(running_ == false, "Cannot turnOn a pevent collector for which go() has already been called.");
138
139 // only create a custom tap if we don't already have this one.
140 // we could potentially end up with duplicates since the user can turn collection
141 // on at treenodes that overlap
142 bool is_unique = true;
143 for(const auto& existing_tap : taps_)
144 {
145 if(existing_tap->getDestination()->compareStrings(file) &&
146 (existing_tap->getCategoryName() == lowertype || lowertype == "all"))
147 {
148 is_unique = false;
149 break;
150 }
151 }
152
153 if(is_unique)
154 {
155 // Setup a tap to capture the output.
156 taps_.emplace_back(new log::Tap(this, event_name_+PEVENT_COLLECTOR_NOTE, file));
157 // We detatch the tap since we need to wait till the trigger
158 // fires or is manually started to start pevent collection.
159 taps_[taps_.size() - 1]->detach();
160 // We did create a tap.
161 return true;
162
163 }
164
165
166 }
167 // We never added a tap because it was not appropriate for our
168 // event type.
169 return false;
170
171 }
172
173 // Coming in a bit.
174 virtual void turnOff(const std::string& type) override final
175 {
176 sparta_assert(false, "peventTurnOff not yet supported");
177 if(type == event_name_)
178 {
179 //remove the taps, this is coming in the future.
180 if(taps_.size() == 0)
181 {
182 turnOff_();
183 }
184 }
185 }
186
192 virtual void go() override final
193 {
194
195 if(taps_.size() > 0)
196 {
197 running_ = true;
198 // Mark the pair collector running
199 turnOn_();
200 }
201 // replace the taps here so that we are officially collecting the data to file.
202 for(auto& tap : taps_)
203 {
204 tap->reset(this);
205 }
206 }
207 protected:
212 virtual void generateCollectionString_() override
213 {
214 // Write the pevent to the log.
215 std::stringstream ss;
216 // Write the event name.
217 ss << "ev=" << "\"" << event_name_ << "\" ";
218
219 // Now write the cached key values.
220 for(const auto & pair : getPEventLogVector())
221 {
222 ss << pair.first << "=" << "\"" << pair.second << "\" ";
223 }
224
225 // Write the time
226 ss << "cyc=" << f_skew_(clk_->currentCycle(), skew_);
227 // Finish the line
228 ss << ";";
229 message_src_ << ss.str();
230 }
231
232 const std::string event_name_;
233 // We are going to use sparta's logger to output our pevents for ease.
234 log::MessageSource message_src_;
235 // Log taps that this pevent is being outputted too.
236 std::vector<std::unique_ptr<log::Tap > > taps_;
237 // We do need a clock b/c each pevent records it's time.
238 const Clock* clk_;
239 std::function<uint64_t(const uint64_t &, const uint32_t &)> f_skew_;
240 uint32_t skew_;
241 bool verbosity_;
242 bool running_ = false;
243 };
244
245
246
247} // namespace pevents
248} // namespace sparta
File that defines the Clock class.
#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
Class that is capable of recording pevents as key value pairs, where a PairDefinition has been define...
virtual void generateCollectionString_() override
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 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.
void collect(const typename CollectedEntityType::TypeCollected &obj, const Targs &... pos_args)
Actually collect the object, and write out a pevent. We ovverride the collect method to ensure the th...
virtual const std::string & eventName() override
Return the ev name.
Macros for handling exponential backoff.