The Sparta Modeling Framework
Loading...
Searching...
No Matches
/github/workspace/sparta/sparta/pevents/PEventHelper.hpp

add formatting options to each custom attribute.

add formatting options to each custom attribute.

Parameters
nthe position of the custom attribute in the parameters, with 0 being the first custom parameter.
pre_flagthe number format such as std::hex
post_flagthe number format after leaving this, most always std::dec i assume.
prea string to be appended to the front of the data, such as "0x"
postthe string to be appended to the end of the data, such as ","

setFormatFlags(1, pevents::FormatFlags(std::ios::hex), pevents::FormatFlags(std::ios::dec), "0x", ""); would output as EV="SOMETYPE", ... other attributes..., custom_param2=0x40

#pragma once
#include <tuple>
#include <array>
#include <iostream>
#include <utility>
#include "sparta/log/MessageSource.hpp"
#include <type_traits>
#include <boost/format.hpp>
namespace sparta{
namespace pevents{
typedef std::ios_base::fmtflags FormatFlags;
//we'll want a way to force that certain keys are not used else where.
namespace PEventProtection
{
enum ProtectAttrs{
EV,
CYCLE
};
extern std::array<std::string, 2> PEventProtectedAttrs;
template<typename T>
bool CheckNoQuotes(const T&, const std::string&, const std::string&)
{
return true;
}
template<typename T>
void AppendQuote(std::stringstream&)
{/*do nothing*/}
template<>
inline bool CheckNoQuotes(const std::string& obj, const std::string& pre, const std::string& post)
{
if(SPARTA_EXPECT_FALSE(std::strcmp(&obj.front(), "\"") == 0))
{
return false;
}
if(SPARTA_EXPECT_FALSE(std::strcmp(&obj.back(), "\"") == 0))
{
return false;
}
if(SPARTA_EXPECT_FALSE(std::strcmp(&pre.front(), "\"") == 0))
{
return false;
}
if(SPARTA_EXPECT_FALSE(std::strcmp(&post.back(), "\"") == 0))
{
return false;
}
//There were no problems with quotes.
return true;
}
template<>
inline void AppendQuote<const std::string&>(std::stringstream& ss)
{
ss << "\"";
}
}
template<typename ...CustomAttrs>
class PEvent
{
typedef PEvent<CustomAttrs...> ThisType;
struct RequiredAttrs{
RequiredAttrs(const std::string& name) :
event_name(name)
{}
uint64_t cycle_time = 0;
uint64_t unique_id = 0;
std::string event_name = "";
};
struct PrePostTags{
PrePostTags() :
pre_format(),
post_format()
{}
std::string prefix = "";
std::string postfix = "";
FormatFlags pre_format;
FormatFlags post_format;
int swidth = 0;
char fill_char = ' ';
};
std::array<std::string, sizeof...(CustomAttrs)> custom_attrs_names_;
std::array<PrePostTags, sizeof...(CustomAttrs)> custom_attrs_formats_;
std::tuple<CustomAttrs...> custom_attrs_;
RequiredAttrs required_attrs_;
log::MessageSource& logger_;
const Clock* clk_;
void writeRequiredData_(std::stringstream& s)
{
//Write event name
std::stringstream name_str;
name_str << "\"" << required_attrs_.event_name << "\"";
s.flags(FormatFlags(std::ios::left));
s << std::get<PEventProtection::EV>(PEventProtection::PEventProtectedAttrs) << "=" << std::setw(12) << name_str.str() << " ";
}
void appendCycle_(std::stringstream& s)
{
//Write cycle
s << std::get<PEventProtection::CYCLE>(PEventProtection::PEventProtectedAttrs) << "=" << clk_->currentCycle();
}
template <class Tuple, class Array, class Formats, std::size_t N>
struct TupleUnroller {
static void unroller_(const Tuple& t, const Array& a, const Formats& f, std::stringstream& s){
TupleUnroller<Tuple, Array, Formats, N-1>::unroller_(t, a, f, s);
s << std::get<N-1>(a) << "=";
//Assert that the first and last character are not quotes on a string, since we are going to insert
//our own quotes on strings.
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.");
//Automatically insert quotes to the beginning of the string types.
PEventProtection::AppendQuote<decltype(std::get<N-1>(t))>(s);
s.flags(std::get<N-1>(f).pre_format);
s << std::get<N-1>(f).prefix;
s << std::setfill(std::get<N-1>(f).fill_char);
s << std::setw(std::get<N-1>(f).swidth);
s << std::get<N-1>(t);
s << std::get<N-1>(f).postfix;
//Automatically insert quotes to the end of the string types.
PEventProtection::AppendQuote<decltype(std::get<N-1>(t))>(s);
s << " ";
s.flags(std::get<N-1>(f).post_format);
}
};
template <class Tuple, class Array, class Formats>
struct TupleUnroller<Tuple, Array, Formats, 1> {
static void unroller_(const Tuple& t, const Array& a, const Formats& f, std::stringstream& s){
s << std::get<0>(a) << "=";
s.flags(std::get<0>(f).pre_format);
s << std::get<0>(f).prefix;
//Assert that the first and last character are not quotes on a string, since we are going to insert
//our own quotes on strings, also do the assertions on pre and post fixes.
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.");
//Automatically insert quotes to the beginning of the string types.
PEventProtection::AppendQuote<decltype(std::get<0>(t))>(s);
s << std::get<0>(f).postfix;
s << std::setfill(std::get<0>(f).fill_char);
s << std::setw(std::get<0>(f).swidth);
s << std::get<0>(t);
s.flags(std::get<0>(f).post_format);
//Automatically insert quotes to the end of the string types.
PEventProtection::AppendQuote<decltype(std::get<0>(t))>(s);
s << " ";
}
};
public:
template<typename ...ArgNames>
PEvent(const std::string& name, log::MessageSource& logger, const Clock* clk, ArgNames&&... names) :
custom_attrs_names_{{names...}}, //some crazyness with array initializer lists, and stuff.
required_attrs_(name),
logger_(logger),
clk_(clk)
{
//run time assert that checks to makes sure none of that custom attributes
//are using a restricted name, such as names for required attributes.
for(auto n : custom_attrs_names_)
{
sparta_assert(n != PEventProtection::PEventProtectedAttrs[0], "custom attribute name cannot be one of the protected attribute names");
sparta_assert(n != PEventProtection::PEventProtectedAttrs[1], "custom attribute name cannot be one of the protected attribute names");
}
}
void setName(const std::string& name)
{
required_attrs_.event_name = name;
}
void setFormatFlags(const uint32_t n, const FormatFlags& pre_flag,
const FormatFlags& post_flag,
const std::string& pre, const std::string& post)
{
sparta_assert(n < sizeof...(CustomAttrs), "Cannot set the format flags for an attribute where n >= the number of custom attributes.");
custom_attrs_formats_[n].prefix = pre;
custom_attrs_formats_[n].postfix = post;
custom_attrs_formats_[n].pre_format = pre_flag;
custom_attrs_formats_[n].post_format = post_flag;
}
void setFormatFlags(const uint32_t n, const std::string& pre, const std::string& post)
{
setFormatFlags(n, FormatFlags(), FormatFlags(), pre, post);
}
void setFormatLength(const uint32_t n, const int length, const FormatFlags& align, const char fill)
{
sparta_assert(n < sizeof...(CustomAttrs), "Cannot set the format flags for an attribute where n >= the number of custom attributes.");
custom_attrs_formats_.at(n).swidth = length;
custom_attrs_formats_.at(n).pre_format = custom_attrs_formats_.at(n).pre_format | align;
custom_attrs_formats_.at(n).fill_char = fill;
}
void setAsStrings(const std::initializer_list<uint32_t> list)
{
for(uint32_t i : list){
setFormatFlags(i, "\"", "\"");
}
}
void setAsHex(const std::initializer_list<uint32_t>& list)
{
static const int hex_length = 8;
for(uint32_t i : list){
setFormatFlags(i, pevents::FormatFlags(std::ios::hex), pevents::FormatFlags(std::ios::dec), "0x", "");
setFormatLength(i, hex_length, pevents::FormatFlags(std::ios::right), '0');
}
}
void setAttrs(CustomAttrs... attrs) { custom_attrs_ = std::make_tuple<CustomAttrs...>(std::forward<CustomAttrs>(attrs)...); }
template<typename AttrType, uint32_t N>
void setAttr(const AttrType& attr) { std::get<N>(custom_attrs_) = attr; }
void fireEvent()
{
if(logger_.observed())
{
std::stringstream s;
writeRequiredData_(s);
TupleUnroller<decltype(custom_attrs_), decltype(custom_attrs_names_), decltype(custom_attrs_formats_), sizeof...(CustomAttrs)>::unroller_(custom_attrs_, custom_attrs_names_, custom_attrs_formats_, s);
appendCycle_(s);
s << ";";
logger_ << s.str();
}
//if(Pevent logging).... ? We need this if?
//1)build a string with the required attrs.
//2)append custom attrs to the string
//3)dump the string, this may call a singleton head or something which passes information to the sparta logger?
//We are dumping in a string format for sure?
//Would I pass this to a logger now?
//std::cout << //required_attrs_.cycle_time << " id: " << required_attrs_.unique_id << " EventType: " << " ";
//std::cout << std::get<PEventProtection::EV>(PEventProtection::PEventProtectedAttrs) << "="<< required_attrs_.event_name << " ";
//This is gonna burn compile time, but oh well.
//TupleUnroller<decltype(custom_attrs_), decltype(custom_attrs_names_), sizeof...(CustomAttrs)>::unroller_(custom_attrs_, custom_attrs_names_);
//std::cout << std::endl;
}
void fireEvent(CustomAttrs... attrs)
{
setAttrs(attrs...);
}
bool observed()
{
return logger_.observed();
}
};
}//namespace pevents
}//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.
void setAttrs(CustomAttrs... attrs)
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.