From 0fc640ad0ddaa7c4d269d78993827f9b38f69876 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89der=20Ferreira=20Zulian?= Date: Mon, 11 May 2015 12:46:21 +0200 Subject: [PATCH] Enum class <-> string macro improved. The macro generates code for two functions: EnumToString() and StringToEnum(). Notes: 1. this macro creates a scoped enumeration (enum class) which favors code readability; 2. this implementation does not support assignment of values to enumerators and also does not support multiple enumerators with the same value. The first enumerator value is 0, the next is 1, and so on. Nevertheless, it is still useful for many cases; 3. if an invalid string is passed to StringToEnum() the program will be aborted and an error message describing the error will be displayed in the standard output. --- dram/src/common/Utils.h | 72 ++++++++++--------- .../core/configuration/Configuration.cpp | 17 +---- .../core/configuration/Configuration.h | 2 +- dram/src/simulation/Dram.h | 2 +- 4 files changed, 40 insertions(+), 53 deletions(-) diff --git a/dram/src/common/Utils.h b/dram/src/common/Utils.h index af637782..f3e8394e 100644 --- a/dram/src/common/Utils.h +++ b/dram/src/common/Utils.h @@ -88,43 +88,45 @@ double queryDoubleParameter(tinyxml2::XMLElement* node, std::string name); void setUpDummy(tlm::tlm_generic_payload& payload, Bank& bank); -// -// BOOST_PP_STRINGIZE(text) -// text will be converted to a string literal. -// -// BOOST_PP_SEQ_ENUM(enumerators) -// This macro expands to a comma-separated list of the elements in -// enumerators. -// -// BOOST_PP_SEQ_FOR_EACH(macro, data, seq) -// This macro is a repetition construct. If seq is (a)(b)(c), it expands to -// the sequence: macro(r, data, a) macro(r, data, b) macro(r, data, c) -// -// Note: this implementation requires that the enumerators map to unique -// values. -// -// See also: -// http://www.boost.org/doc/libs/1_38_0/libs/preprocessor/doc/ -// http://stackoverflow.com/questions/5093460/how-to-convert-an-enum-type-variable-to-a-string -// -#define X_DEFINE_ENUM_CLASS_WITH_STRING_CONVERSIONS_TOSTRING_CASE(r, data, elem) \ +#define DEFINE_ENUM_CLASS_WITH_STRING_CONVERSIONS_TOSTRING_CASE(r, data, elem) \ case data::elem : return BOOST_PP_STRINGIZE(elem); -#define DEFINE_ENUM_CLASS_WITH_STRING_CONVERSIONS(enumName, enumerators) \ - enum class enumName { \ - BOOST_PP_SEQ_ENUM(enumerators) \ - }; \ - \ - inline const char* ToString(enumName v) \ - { \ - switch (v) { \ - BOOST_PP_SEQ_FOR_EACH( \ - X_DEFINE_ENUM_CLASS_WITH_STRING_CONVERSIONS_TOSTRING_CASE, \ - enumName, \ - enumerators \ - ) \ - default: return "[Unknown " BOOST_PP_STRINGIZE(name) "]"; \ - } \ +#define DEFINE_ENUM_CLASS_WITH_STRING_CONVERSIONS_TOENUM_IF(r, data, elem) \ + if (BOOST_PP_SEQ_TAIL(data) == BOOST_PP_STRINGIZE(elem)) \ + return BOOST_PP_SEQ_HEAD(data)::elem; else + +#define DEFINE_ENUM_CLASS_WITH_STRING_CONVERSIONS(enumName, enumerators) \ + enum class enumName { \ + BOOST_PP_SEQ_ENUM(enumerators) \ + }; \ + \ + inline const char *EnumToString(enumName v) \ + { \ + switch (v) { \ + BOOST_PP_SEQ_FOR_EACH( \ + DEFINE_ENUM_CLASS_WITH_STRING_CONVERSIONS_TOSTRING_CASE, \ + enumName, \ + enumerators \ + ) \ + default: return "[Unknown " BOOST_PP_STRINGIZE(name) "]"; \ + } \ + } \ + \ + inline enumName StringToEnum(std::string s) \ + { \ + BOOST_PP_SEQ_FOR_EACH( \ + DEFINE_ENUM_CLASS_WITH_STRING_CONVERSIONS_TOENUM_IF, \ + (enumName)(s), \ + enumerators \ + ) \ + { \ + SC_REPORT_FATAL("Configuration", \ + ("Invalid string \"" + s + "\" for conversion into enum \"" \ + + BOOST_PP_STRINGIZE(enumName) + "\"").c_str() \ + ); \ + throw; \ + } \ } #endif /* UTILS_COMMON_H_ */ + diff --git a/dram/src/controller/core/configuration/Configuration.cpp b/dram/src/controller/core/configuration/Configuration.cpp index 5d8449ff..1314c61f 100644 --- a/dram/src/controller/core/configuration/Configuration.cpp +++ b/dram/src/controller/core/configuration/Configuration.cpp @@ -57,21 +57,6 @@ EPowerDownMode string2PDNMode(string s) } } -StorageMode string2StorageMode(string s) -{ - if (s == "NoStorage") - return StorageMode::NoStorage; - else if (s == "Store") - return StorageMode::Store; - else if (s == "ErrorModel") - return StorageMode::ErrorModel; - else - { - SC_REPORT_FATAL("Configuration", ("Unknown StorageMode: " + s).c_str()); - throw; - } -} - void Configuration::setParameter(std::string name, std::string value) { if(name == "BankwiseLogic") @@ -113,7 +98,7 @@ void Configuration::setParameter(std::string name, std::string value) else if(name == "csvfile") csvfile = value; else if(name == "StorMo") - StorMode = string2StorageMode(value); + StorMode = StringToEnum(value); else { SC_REPORT_FATAL("Configuration", ("Parameter " + name + " not defined in Configuration").c_str()); diff --git a/dram/src/controller/core/configuration/Configuration.h b/dram/src/controller/core/configuration/Configuration.h index 3cab2900..85a257d8 100644 --- a/dram/src/controller/core/configuration/Configuration.h +++ b/dram/src/controller/core/configuration/Configuration.h @@ -14,7 +14,7 @@ #include "../../../common/Utils.h" enum class EPowerDownMode{NoPowerDown, Staggered, TimeoutPDN, TimeoutSREF}; -DEFINE_ENUM_CLASS_WITH_STRING_CONVERSIONS(StorageMode, (NoStorage) (Store) (ErrorModel)); +DEFINE_ENUM_CLASS_WITH_STRING_CONVERSIONS(StorageMode, (NoStorage)(Store)(ErrorModel)); struct Configuration { diff --git a/dram/src/simulation/Dram.h b/dram/src/simulation/Dram.h index c1fdfe45..a5315a4f 100644 --- a/dram/src/simulation/Dram.h +++ b/dram/src/simulation/Dram.h @@ -61,7 +61,7 @@ struct Dram: sc_module IFPOW( MemorySpecification memSpec(MemSpecParser::getMemSpecFromXML(Configuration::getInstance().memspecUri)) ); IFPOW( DRAMPower = new libDRAMPower( memSpec, 0 ) ); - cout << "StorageMode = " << ToString(StorMode) << endl; + cout << "StorageMode: " << EnumToString(StorMode) << endl; if(StorMode == StorageMode::ErrorModel) {