The Sparta Modeling Framework
Loading...
Searching...
No Matches
Utils.hpp
1// <Utils> -*- C++ -*-
2
3#pragma once
4
5#include <string>
6#include <math.h>
7#include <cxxabi.h>
8#include <vector>
9#include <algorithm>
10
13#include "sparta/utils/SpartaExpBackoff.hpp"
14
16#define NULL_TO_EMPTY_STR(s) (((s)==nullptr)?"":s)
17
22#define DEMANGLE_BUF_LENGTH 4096
23
24
25// Custom Literals
26
30constexpr inline uint64_t operator ""_u64(unsigned long long i) {
31 return i;
32}
33
37constexpr inline uint32_t operator ""_u32(unsigned long long i) {
38 return i;
39}
40
44constexpr inline uint16_t operator ""_u16(unsigned long long i) {
45 return i;
46}
47
51constexpr inline uint8_t operator ""_u8(unsigned long long i) {
52 return i;
53}
54
58constexpr inline int64_t operator ""_64(unsigned long long i) {
59 return i;
60}
61
65constexpr inline int32_t operator ""_32(unsigned long long i) {
66 return i;
67}
68
72constexpr inline int16_t operator ""_16(unsigned long long i) {
73 return i;
74}
75
79constexpr inline int8_t operator ""_8(unsigned long long i) {
80 return i;
81}
82
83namespace sparta
84{
85
92template<typename K, typename V, typename... Args, template<typename...> class MapType>
93MapType<V, K> flipMap(const MapType<K, V, Args...>& map){
94 auto inverted_map {MapType<V, K>{}};
95 for(const auto& [key, value] : map){
96 inverted_map.insert({value, key});
97 }
98 return inverted_map;
99}
100
123template <typename T,
124 typename ConstT=typename std::add_pointer<
125 typename std::add_const<
126 typename std::remove_pointer<T>::type
127 >::type
128 >::type>
130 typedef ConstT type;
131};
132
142inline bool isPowerOf2(uint64_t x) {
143 return ((x==0) || !(x & (x-1)));
144}
145
159template <typename T>
160inline T computeMask(T size, T& lsb_pos) {
161 T mask;
162 if(size >= 1){
163 double tmp = log2(size);
164 if(tmp != floor(tmp)){
165 throw SpartaException("For computeMask, size must be a power of 2, is ")
166 << size;
167 }
168 lsb_pos = (T)tmp;
169 mask = ~((1 << lsb_pos) - 1);
170
171 sparta_assert((1ul << lsb_pos) == size);
172 }else{
173 lsb_pos = sizeof(T) * 8;
174 mask = (T)0;
175 }
176 return mask;
177}
178
186template <typename T>
187inline T computeMaskShift(T size) {
188 T shift;
189 computeMask(size, shift);
190 return shift;
191}
192
193
203inline std::string demangle(const std::string& name) noexcept {
204 char buf[DEMANGLE_BUF_LENGTH];
205 size_t buf_size = DEMANGLE_BUF_LENGTH;
206 int status;
207 char* out = __cxxabiv1::__cxa_demangle(name.c_str(), buf, &buf_size, &status);
208 if(nullptr == out){
209 return name;
210 }
211 return std::string(out);
212}
213
223template <typename T>
224inline T* notNull(T* p) {
225 if(p == nullptr){
226 throw SpartaException("notNull: pointer was null: " + demangle(typeid(T).name()));
227 }
228 return p;
229}
230
236template <typename T> struct is_vector {
242 static const bool value = false;
243};
244
246template <typename T> struct is_vector<std::vector<T> > {
247 static const bool value = true;
248};
249
265inline uint32_t replaceSubstring(std::string& s, const std::string& from, const std::string& to){
266 uint32_t num_replacements = 0;
267 size_t pos = 0;
268 while((pos = s.find(from, pos)) != std::string::npos) {
269 s.replace(pos, from.size(), to);
270 pos += to.length();
271 ++num_replacements;
272 }
273 return num_replacements;
274}
275
282inline std::string copyWithReplace(const std::string& s, char from, const std::string& to){
283 std::string result;
284 result.reserve(s.size()*2); // Take an initial guess so we don't have to reallocate
285
286 const char* p = s.c_str();
287 while(1){
288 if(*p == from){
289 result += to;
290 }else if(*p == '\0'){
291 break;
292 }else{
293 result += *p;
294 }
295 ++p;
296 }
297
298 return result;
299}
300
307inline std::string convertCPPStringToPython(const std::string& s)
308{
309 std::string result = s;
310 const char * cpp_stuff = "<>:";
311 const char replacement = '_';
312
313 std::string::size_type pos;
314 while(pos = result.find_first_of(cpp_stuff), pos != std::string::npos) {
315 result[pos] = replacement;
316 }
317
318 // Strip parens
319 while(pos = result.find_first_of("()"), pos != std::string::npos) {
320 std::string newstr = result.substr(0, pos);
321 newstr += result.substr(pos + 1);
322 result = newstr;
323 }
324
325
326 return result;
327}
328
332inline void writeNChars(std::ostream& out, uint32_t num, char chr=' ') {
333 for(uint32_t i=0; i<num; ++i){
334 out << chr;
335 }
336}
337
341inline std::string toLower(const std::string& s){
342 std::string out(s.size(), ' ');
343 std::transform(s.begin(), s.end(), out.begin(), (int(*)(int))std::tolower);
344 return out;
345}
346
353template <bool Default>
355{
356 bool value_ = Default;
357
358public:
359
363 OneWayBool() = default;
364
365 /*
366 * \brief Initialize with a value. This value must be the opposite of value
367 */
368 OneWayBool(bool value)
369 : value_(value)
370 {
371 sparta_assert(value != Default,
372 "OneWayBool<" << Default << "> can only be explicitly initalized to " << !Default
373 << ". Otherwise, it must be default-constructed which will provide a value of "
374 << Default);
375 }
376
380 operator bool () const { return value_; }
381
385 bool operator==(bool b) const { return value_ == b; }
386
390 template <bool ArgDefault>
391 bool operator==(const OneWayBool<ArgDefault>& b) const { return value_ == b.value_; }
392
398 template <bool ArgDefault>
400 sparta_assert(Default != b.value_,
401 "OneWayBool<" << Default << "> can never be set to " << Default
402 << " except at initialization");
403 value_ = b.value;
404 return value_;
405 }
406
412 bool operator=(bool b) {
413 sparta_assert(Default != b,
414 "OneWayBool<" << Default << "> can never be set to " << Default
415 << " except at initialization");
416 value_ = b;
417 return value_;
418 }
419
426 void set_DEPRECATED(bool b) {
427 value_ = b;
428 }
429};
430
436template <typename T>
438{
439 OneWayBool<false> set_;
440
441 bool defaulted_ = false;
442
443 T value_;
444
445 const char * name_ = nullptr;
446
447public:
448
453 : set_(rhp.set_),
454 defaulted_(rhp.defaulted_),
455 value_(rhp.value_),
456 name_(rhp.name_)
457 {;}
458
463 : set_(rhp.set_),
464 defaulted_(rhp.defaulted_),
465 value_(rhp.value_),
466 name_(rhp.name_)
467 {
468 // No need to invalidate rhp
469 }
470
478 AssignOnceObject(const T& def_value,
479 const char* name)
480 : defaulted_(true),
481 value_(def_value),
482 name_(name)
483 {;}
484
490
494 operator const T& () const {
495 return get();
496 }
497
501 const T& get() const {
502 sparta_assert(set_ || defaulted_, getPrintableQuotedName_() << " must be set before reading");
503 return value_;
504 }
505
509 bool operator==(const AssignOnceObject<T>& b) const {
510 sparta_assert(set_ || defaulted_, getPrintableQuotedName_() << " must be set before comparing");
511 return value_ == b.get();
512 }
513
517 const T& operator=(const AssignOnceObject<T>& b) {
518 sparta_assert(set_ == false,
519 getPrintableQuotedName_() << " has already been assigned once. It cannot be re-assigned");
520 sparta_assert(b.set_ || b.defaulted_,
521 getPrintableQuotedName_() << " cannot be assigned with another AssignOnceObject which is not defaulted or set");
522
523 set_ = true; // arg 'b' must be defaulted or set
524 value_ = b.value_;
525 return value_;
526 }
527
531 const T& operator=(const T& v) {
532 sparta_assert(set_ == false,
533 getPrintableQuotedName_() << " has already been assigned once. It cannot be re-assigned");
534
535 set_ = true;
536 value_ = v;
537 return value_;
538 }
539
540 /*
541 * \brief Has this value been assigned
542 */
543 bool assigned() const {
544 return set_;
545 }
546
547private:
548
549 template <typename X>
550 friend inline std::ostream& operator<<(std::ostream& o, const AssignOnceObject<X>& v);
551
557 std::string getPrintableQuotedName_() const {
558 if(name_ != nullptr){
559 return std::string("\"") + name_ + "\"";
560 }else{
561 return std::string("\"AssignOnceObject<") + typeid(T).name() + ">";
562 }
563 }
564};
565
566template <typename T>
567inline std::ostream& operator<<(std::ostream& o, const AssignOnceObject<T>& v) {
568 if(v.set_ || v.defaulted_){
569 o << v.value_;
570 }else{
571 o << "<uninitialized>";
572 }
573 return o;
574}
575
582template <typename T, T min_bound=std::numeric_limits<T>::min(), T max_bound=std::numeric_limits<T>::max()>
584{
585 T val_;
586public:
587
588 bounded_int(const bounded_int&) = default;
589
590 explicit bounded_int(bounded_int&&) = default;
591
592 template <typename ArgT=T>
593 bounded_int(ArgT, typename std::enable_if<std::is_integral<ArgT>::value==false
594 && std::is_convertible<ArgT,T>::value==false>::type* = 0)
595 : val_(0)
596 {
597 static_assert(std::is_integral<ArgT>::value,
598 "Cannot store a non-integral value in a bounded integer type");
599 }
600
601 template <typename ArgT=T>
602 bounded_int(ArgT val, typename std::enable_if<std::is_integral<ArgT>::value==false
603 && std::is_convertible<ArgT,T>::value==true>::type* = 0)
604 : val_(static_cast<T>(val))
605 {
606 rangeCheck_(static_cast<T>(val));
607 }
608
609 // Different sign
610 template <typename ArgT=T>
611 bounded_int(ArgT val, typename std::enable_if<std::is_integral<ArgT>::value
612 && std::is_signed<ArgT>::value!=std::is_signed<T>::value>::type* = 0)
613 : val_(val)
614 {
615 rangeCheck_(val);
616 }
617
618 // Same sign, smaller (or same-sized) input value data type
619 template <typename ArgT=T>
620 bounded_int(ArgT val, typename std::enable_if<std::is_integral<ArgT>::value
621 && (sizeof(ArgT) <= sizeof(T))
622 && std::is_signed<ArgT>::value==std::is_signed<T>::value>::type* = 0)
623 : val_(val)
624 {
625 // Types have same signed-ness and argument is smaller than container.
626 // Container type T bounds guaranteed unexceeded
627
628 // Check bounds if there are user defined bounds
629
630 rangeCheck_(val);
631 }
632
633 // Same sign, larger input value data type
634 template <typename ArgT=T>
635 bounded_int(ArgT val, typename std::enable_if<std::is_integral<ArgT>::value
636 && (sizeof(ArgT) > sizeof(T))
637 && std::is_signed<ArgT>::value==std::is_signed<T>::value>::type* = 0)
638 : val_(val)
639 {
640 // Types have same signed-ness but argument is larger
641 rangeCheck_(val);
642 }
643
644 template <typename ArgT>
645 void rangeCheck_(ArgT val){
646 lowerRangeCheck_(val);
647 upperRangeCheck_(val);
648 }
649
650 template <typename ArgT=T>
651 typename std::enable_if<std::numeric_limits<ArgT>::min()!=min_bound, void>::type
652 lowerRangeCheck_(ArgT val) const {
653 sparta_assert(val >= min_bound,
654 "Tried to store a " << typeid(ArgT).name() << " into a bounded " << typeid(T).name() << ". Not safe to "
655 "cast " << val << " into a type with a minimum of " << min_bound);
656 }
657
658 template <typename ArgT=T>
659 typename std::enable_if<std::numeric_limits<ArgT>::min()==min_bound, void>::type
660 lowerRangeCheck_(ArgT val) const {
661 (void) val; // Lower bound of val is same as this bounded_int
662 }
663
664 template <typename ArgT=T>
665 typename std::enable_if<std::numeric_limits<ArgT>::max()!=max_bound, void>::type
666 upperRangeCheck_(ArgT val) const {
667 sparta_assert(val <= max_bound,
668 "Tried to store a " << typeid(ArgT).name() << " into a bounded " << typeid(T).name() << ". Not safe to "
669 "cast " << val << " into a type with a maximum of " << max_bound);
670 }
671
672 template <typename ArgT=T>
673 typename std::enable_if<std::numeric_limits<ArgT>::max()==max_bound, void>::type
674 upperRangeCheck_(ArgT val) const {
675 (void) val; // Upper bound of val is same as this bounded_int
676 }
677
682 //template <T local_min_bound, T local_max_bound, typename U=T>
683 //static T bound(U value) {
684 // bt = bounded_type<T, local_min_bound, local_max_bound>(value);
685 // return bt.val_;
686 //}
687
692 operator T() const { return val_; }
693
697 bool operator==(const bounded_int&) = delete;
698
702 bool operator=(const bounded_int&) = delete;
703
704};
705
706} // namespace sparta
707
724#define GENERATE_HAS_ATTR(name) \
725 template <typename T> \
726 struct has_attr_##name { \
727 typedef char one[1]; \
728 typedef char two[2]; \
729 \
730 template <typename C> static one& test( decltype(&C::name) ) ; \
731 template <typename C> static two& test(...); \
732 \
733 enum { value = sizeof(test<T>(nullptr)) == sizeof(one) }; \
734 };
Set of macros for Sparta assertions. Caught by the framework.
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
Exception class for all of Sparta.
Object which can only have it's value set once. Throws exception if being set more than once.
Definition Utils.hpp:438
const T & operator=(const T &v)
Assign using a given value of type T.
Definition Utils.hpp:531
AssignOnceObject()
Construct with no name.
Definition Utils.hpp:488
AssignOnceObject(const AssignOnceObject &rhp)
Copy Constructor.
Definition Utils.hpp:452
const T & operator=(const AssignOnceObject< T > &b)
Assign using another AssignOnceObject of the same contained type T.
Definition Utils.hpp:517
const T & get() const
Get contained value of type T.
Definition Utils.hpp:501
AssignOnceObject(AssignOnceObject &&rhp)
Move-Construction disabled until needed.
Definition Utils.hpp:462
AssignOnceObject(const T &def_value, const char *name)
Construct with a default and name for use during errors. This constructor starts the object in unassi...
Definition Utils.hpp:478
bool operator==(const AssignOnceObject< T > &b) const
Compare against another AssignOnceObject of the same contained type T.
Definition Utils.hpp:509
Boolean with a default capable of being changed to the opposite value only. it can never set to the d...
Definition Utils.hpp:355
OneWayBool()=default
Default construction. Defaults to template argument 'Default'.
bool operator=(bool b)
Assign value from a bool.
Definition Utils.hpp:412
bool operator=(const OneWayBool< ArgDefault > &b)
Assign value from another OneWayBool.
Definition Utils.hpp:399
bool operator==(const OneWayBool< ArgDefault > &b) const
Compare value with another OneWayBool.
Definition Utils.hpp:391
void set_DEPRECATED(bool b)
set this object arbitrarily
Definition Utils.hpp:426
bool operator==(bool b) const
Compare value with a bool.
Definition Utils.hpp:385
Used to construct and throw a standard C++ exception. Inherits from std::exception.
Bounded integer type with range-checking.
Definition Utils.hpp:584
bool operator=(const bounded_int &)=delete
Deleted comaprison with bounded in (until implemented fully)
bool operator==(const bounded_int &)=delete
Deleted comaprison with bounded in (until implemented fully)
Macros for handling exponential backoff.
std::string convertCPPStringToPython(const std::string &s)
Take all of the C++-isms out of a string (like parens, angle brackets, colons, etc) and replace them ...
Definition Utils.hpp:307
std::string copyWithReplace(const std::string &s, char from, const std::string &to)
Copies from 1 string to another with replacement of a single character with a string.
Definition Utils.hpp:282
T * notNull(T *p)
Ensures that a pointer is not null.
Definition Utils.hpp:224
void writeNChars(std::ostream &out, uint32_t num, char chr=' ')
Insert a number of some character into an ostream.
Definition Utils.hpp:332
uint32_t replaceSubstring(std::string &s, const std::string &from, const std::string &to)
Replaces within a string 's' all instances of some string 'from' with 'to'.
Definition Utils.hpp:265
std::ostream & operator<<(std::ostream &o, const SimulationInfo &info)
ostream insertion operator for SimulationInfo
std::string demangle(const std::string &name) noexcept
Demangles a C++ symbol.
Definition Utils.hpp:203
T computeMask(T size, T &lsb_pos)
Computes a maks and the lsb-position given a block size. The mask generated can be AND-ed with any nu...
Definition Utils.hpp:160
MapType< V, K > flipMap(const MapType< K, V, Args... > &map)
Function to invert a maps or an unordered_map, or any type of class that has key/value semantics....
Definition Utils.hpp:93
std::string toLower(const std::string &s)
Makes a copy of an input string s in lower-case.
Definition Utils.hpp:341
T computeMaskShift(T size)
Convenience wrapper around computeMask to get the shift value.
Definition Utils.hpp:187
bool isPowerOf2(uint64_t x)
Determines if input is 0 or a power of 2.
Definition Utils.hpp:142
Templated for determining if ValueType is std::vector for use in metaprogramming constructs....
Definition Utils.hpp:236
static const bool value
'value' field used by enable_if construct.
Definition Utils.hpp:242
Template type helper that removes a pointer, adds a const, and then re-adds the pointer....
Definition Utils.hpp:129