The Sparta Modeling Framework
Loading...
Searching...
No Matches
PEventHelper.hpp
1#pragma once
2
3#include <tuple>
4#include <array>
5#include <iostream>
6#include <utility>
7#include "sparta/log/MessageSource.hpp"
8#include <type_traits>
9#include <boost/format.hpp>
10namespace sparta{
11namespace pevents{
12
14typedef std::ios_base::fmtflags FormatFlags;
15
16//we'll want a way to force that certain keys are not used else where.
17namespace PEventProtection
18{
19 enum ProtectAttrs{
20 EV,
21 CYCLE
22 };
23 extern std::array<std::string, 2> PEventProtectedAttrs;
24
25
31 template<typename T>
32 bool CheckNoQuotes(const T&, const std::string&, const std::string&)
33 {
34 return true;
35 }
36
37
42 template<typename T>
43 void AppendQuote(std::stringstream&)
44 {/*do nothing*/}
45
46
47 template<>
48 inline bool CheckNoQuotes(const std::string& obj, const std::string& pre, const std::string& post)
49 {
50 if(SPARTA_EXPECT_FALSE(std::strcmp(&obj.front(), "\"") == 0))
51 {
52 return false;
53 }
54 if(SPARTA_EXPECT_FALSE(std::strcmp(&obj.back(), "\"") == 0))
55 {
56 return false;
57 }
58 if(SPARTA_EXPECT_FALSE(std::strcmp(&pre.front(), "\"") == 0))
59 {
60 return false;
61 }
62 if(SPARTA_EXPECT_FALSE(std::strcmp(&post.back(), "\"") == 0))
63 {
64 return false;
65 }
66 //There were no problems with quotes.
67 return true;
68 }
69
70 template<>
71 inline void AppendQuote<const std::string&>(std::stringstream& ss)
72 {
73 ss << "\"";
74 }
75
76
77}
78
86template<typename ...CustomAttrs>
87class PEvent
88{
89
90 typedef PEvent<CustomAttrs...> ThisType;
92 struct RequiredAttrs{
93 RequiredAttrs(const std::string& name) :
94 event_name(name)
95 {}
96 uint64_t cycle_time = 0;
97 uint64_t unique_id = 0;
98 std::string event_name = "";
99 };
100
102 struct PrePostTags{
103 PrePostTags() :
104 pre_format(),
105 post_format()
106 {}
107 std::string prefix = "";
108 std::string postfix = "";
109 FormatFlags pre_format;
110 FormatFlags post_format;
111 int swidth = 0;
112 char fill_char = ' ';
113
114 };
115
118 std::array<std::string, sizeof...(CustomAttrs)> custom_attrs_names_;
119
121 std::array<PrePostTags, sizeof...(CustomAttrs)> custom_attrs_formats_;
123 std::tuple<CustomAttrs...> custom_attrs_;
124
125
126
128 RequiredAttrs required_attrs_;
129
131 log::MessageSource& logger_;
133 const Clock* clk_;
134
135
136 void writeRequiredData_(std::stringstream& s)
137 {
138 //Write event name
139 std::stringstream name_str;
140 name_str << "\"" << required_attrs_.event_name << "\"";
141 s.flags(FormatFlags(std::ios::left));
142 s << std::get<PEventProtection::EV>(PEventProtection::PEventProtectedAttrs) << "=" << std::setw(12) << name_str.str() << " ";
143 }
144
145 void appendCycle_(std::stringstream& s)
146 {
147 //Write cycle
148 s << std::get<PEventProtection::CYCLE>(PEventProtection::PEventProtectedAttrs) << "=" << clk_->currentCycle();
149 }
150
152 template <class Tuple, class Array, class Formats, std::size_t N>
153 struct TupleUnroller {
154 static void unroller_(const Tuple& t, const Array& a, const Formats& f, std::stringstream& s){
155 TupleUnroller<Tuple, Array, Formats, N-1>::unroller_(t, a, f, s);
156 s << std::get<N-1>(a) << "=";
157 //Assert that the first and last character are not quotes on a string, since we are going to insert
158 //our own quotes on strings.
159 sparta_assert(PEventProtection::CheckNoQuotes(std::get<N-1>(t), std::get<N-1>(f).prefix, std::get<N-1>(f).postfix), "Quotes are appended to string types for PEvent logging automatically and should not be done by the modeller in the prefix, postfix, or the string itself.");
160 //Automatically insert quotes to the beginning of the string types.
161 PEventProtection::AppendQuote<decltype(std::get<N-1>(t))>(s);
162 s.flags(std::get<N-1>(f).pre_format);
163 s << std::get<N-1>(f).prefix;
164 s << std::setfill(std::get<N-1>(f).fill_char);
165 s << std::setw(std::get<N-1>(f).swidth);
167 s << std::get<N-1>(t);
168 s << std::get<N-1>(f).postfix;
169 //Automatically insert quotes to the end of the string types.
170 PEventProtection::AppendQuote<decltype(std::get<N-1>(t))>(s);
171 s << " ";
172 s.flags(std::get<N-1>(f).post_format);
173 }
174 };
175 template <class Tuple, class Array, class Formats>
176 struct TupleUnroller<Tuple, Array, Formats, 1> {
177 static void unroller_(const Tuple& t, const Array& a, const Formats& f, std::stringstream& s){
178 s << std::get<0>(a) << "=";
179 s.flags(std::get<0>(f).pre_format);
180 s << std::get<0>(f).prefix;
181 //Assert that the first and last character are not quotes on a string, since we are going to insert
182 //our own quotes on strings, also do the assertions on pre and post fixes.
183 sparta_assert(PEventProtection::CheckNoQuotes(std::get<0>(t), std::get<0>(f).prefix, std::get<0>(f).postfix), "Quotes are appended to string types for PEvent logging automatically and should not be done by the modeller in the prefix, postfix, or the string itself.");
184 //Automatically insert quotes to the beginning of the string types.
185 PEventProtection::AppendQuote<decltype(std::get<0>(t))>(s);
186 s << std::get<0>(f).postfix;
187 s << std::setfill(std::get<0>(f).fill_char);
188 s << std::setw(std::get<0>(f).swidth);
190 s << std::get<0>(t);
191 s.flags(std::get<0>(f).post_format);
192 //Automatically insert quotes to the end of the string types.
193 PEventProtection::AppendQuote<decltype(std::get<0>(t))>(s);
194 s << " ";
195 }
196 };
197public:
198
203 template<typename ...ArgNames>
204 PEvent(const std::string& name, log::MessageSource& logger, const Clock* clk, ArgNames&&... names) :
205 custom_attrs_names_{{names...}}, //some crazyness with array initializer lists, and stuff.
206 required_attrs_(name),
207 logger_(logger),
208 clk_(clk)
209 {
210 //run time assert that checks to makes sure none of that custom attributes
211 //are using a restricted name, such as names for required attributes.
212 for(auto n : custom_attrs_names_)
213 {
214 sparta_assert(n != PEventProtection::PEventProtectedAttrs[0], "custom attribute name cannot be one of the protected attribute names");
215 sparta_assert(n != PEventProtection::PEventProtectedAttrs[1], "custom attribute name cannot be one of the protected attribute names");
216 }
217 }
218
219
220 void setName(const std::string& name)
221 {
222 required_attrs_.event_name = name;
223 }
240 void setFormatFlags(const uint32_t n, const FormatFlags& pre_flag,
241 const FormatFlags& post_flag,
242 const std::string& pre, const std::string& post)
243 {
244 sparta_assert(n < sizeof...(CustomAttrs), "Cannot set the format flags for an attribute where n >= the number of custom attributes.");
245
246 custom_attrs_formats_[n].prefix = pre;
247 custom_attrs_formats_[n].postfix = post;
248 custom_attrs_formats_[n].pre_format = pre_flag;
249 custom_attrs_formats_[n].post_format = post_flag;
250 }
251 void setFormatFlags(const uint32_t n, const std::string& pre, const std::string& post)
252 {
253 setFormatFlags(n, FormatFlags(), FormatFlags(), pre, post);
254 }
255
263 void setFormatLength(const uint32_t n, const int length, const FormatFlags& align, const char fill)
264 {
265 sparta_assert(n < sizeof...(CustomAttrs), "Cannot set the format flags for an attribute where n >= the number of custom attributes.");
266 custom_attrs_formats_.at(n).swidth = length;
267 custom_attrs_formats_.at(n).pre_format = custom_attrs_formats_.at(n).pre_format | align;
268 custom_attrs_formats_.at(n).fill_char = fill;
269 }
270
276 void setAsStrings(const std::initializer_list<uint32_t> list)
277 {
278 for(uint32_t i : list){
279 setFormatFlags(i, "\"", "\"");
280 }
281 }
282
288 void setAsHex(const std::initializer_list<uint32_t>& list)
289 {
290 static const int hex_length = 8;
291 for(uint32_t i : list){
292 setFormatFlags(i, pevents::FormatFlags(std::ios::hex), pevents::FormatFlags(std::ios::dec), "0x", "");
293 setFormatLength(i, hex_length, pevents::FormatFlags(std::ios::right), '0');
294 }
295 }
296
297
298
299
304 void setAttrs(CustomAttrs... attrs) { custom_attrs_ = std::make_tuple<CustomAttrs...>(std::forward<CustomAttrs>(attrs)...); }
305
308 template<typename AttrType, uint32_t N>
309 void setAttr(const AttrType& attr) { std::get<N>(custom_attrs_) = attr; }
310
313
317 {
318 if(logger_.observed())
319 {
320 std::stringstream s;
321 writeRequiredData_(s);
322 TupleUnroller<decltype(custom_attrs_), decltype(custom_attrs_names_), decltype(custom_attrs_formats_), sizeof...(CustomAttrs)>::unroller_(custom_attrs_, custom_attrs_names_, custom_attrs_formats_, s);
323 appendCycle_(s);
324 s << ";";
325 logger_ << s.str();
326 }
327 //if(Pevent logging).... ? We need this if?
328 //1)build a string with the required attrs.
329
330 //2)append custom attrs to the string
331
332 //3)dump the string, this may call a singleton head or something which passes information to the sparta logger?
334
335 //We are dumping in a string format for sure?
336
337 //Would I pass this to a logger now?
338 //std::cout << //required_attrs_.cycle_time << " id: " << required_attrs_.unique_id << " EventType: " << " ";
339 //std::cout << std::get<PEventProtection::EV>(PEventProtection::PEventProtectedAttrs) << "="<< required_attrs_.event_name << " ";
340 //This is gonna burn compile time, but oh well.
341 //TupleUnroller<decltype(custom_attrs_), decltype(custom_attrs_names_), sizeof...(CustomAttrs)>::unroller_(custom_attrs_, custom_attrs_names_);
342 //std::cout << std::endl;
343 }
344
346 void fireEvent(CustomAttrs... attrs)
347 {
348 setAttrs(attrs...);
349 fireEvent();
350 }
351
352 bool observed()
353 {
354 return logger_.observed();
355 }
356
357};
358
359
360}//namespace pevents
361}//namespace sparta
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
#define SPARTA_EXPECT_FALSE(x)
A macro for hinting to the compiler a particular condition should be considered most likely false.
Array is essentially a fixed size vector, maintains a concept of validity of its indexes,...
Definition Array.hpp:58
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
Message source object associated with a sparta TreeNode through which messages can be sent.
Defines the class base type for PEvents.
void fireEvent(CustomAttrs... attrs)
Maybe overload fireEvent to allow setting the attributes when firing.
void setAttrs(CustomAttrs... attrs)
PEvent(const std::string &name, log::MessageSource &logger, const Clock *clk, ArgNames &&... names)
void setAsStrings(const std::initializer_list< uint32_t > list)
set many attributes as strings, \usage setAsString({1,3,5}); //where 1, 3, and 5 are attributes to be...
void setAsHex(const std::initializer_list< uint32_t > &list)
a helper to set a custom attribute to be outputted in hex format. \usage setAsHex({1,...
void setAttr(const AttrType &attr)
Macros for handling exponential backoff.