add formatting options to each custom attribute.
add formatting options to each custom attribute.
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 pevents{
typedef std::ios_base::fmtflags FormatFlags;
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&)
{}
template<>
inline bool CheckNoQuotes(const std::string& obj, const std::string& pre, const std::string& post)
{
{
return false;
}
{
return false;
}
{
return false;
}
{
return false;
}
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)
{
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)
{
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) << "=";
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.");
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;
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;
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.");
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);
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...}},
required_attrs_(name),
logger_(logger),
clk_(clk)
{
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; }
{
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();
}
}
{
}
bool observed()
{
return logger_.observed();
}
};
}
}
#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.