scc  2024.06
SystemC components library
cci_util.h
1 /*******************************************************************************
2  * Copyright 2024 MINRES Technologies GmbH
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *******************************************************************************/
16 
17 #ifndef _SYSC_SCC_CCI_UTIL_H_
18 #define _SYSC_SCC_CCI_UTIL_H_
19 
20 #include <boost/preprocessor.hpp>
21 #include <cci_configuration>
22 
23 #define DEFINE_ENUM_DECL_VAL(r, name, val) val // BOOST_PP_CAT(name, BOOST_PP_CAT(_, val))
24 #define DEFINE_ENUM_VAL_STR(r, name, val) BOOST_PP_STRINGIZE(val)
25 #define ASSIGN_ENUM_MAP_ENTRY(r, name, val) lut[#val] = name::val;
26 #define CONCAT_OP(s, state, x) state x
27 #define CONCAT(SEQ) BOOST_PP_SEQ_FOLD_LEFT(CONCAT_OP, BOOST_PP_SEQ_HEAD(SEQ), BOOST_PP_SEQ_TAIL(SEQ)) // expands to boost
28 
40 #if CCI_VERSION_MAJOR == 1 && CCI_VERSION_MINOR == 0 && CCI_VERSION_PATCH == 0
41 #define DEFINE_ENUM4CCI(name, val_seq) \
42  enum class name { BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(DEFINE_ENUM_DECL_VAL, name, val_seq)) }; \
43  namespace cci { \
44  namespace { \
45  std::unordered_map<std::string, name> name##_lut_init() { \
46  std::unordered_map<std::string, name> lut; \
47  CONCAT(BOOST_PP_SEQ_TRANSFORM(ASSIGN_ENUM_MAP_ENTRY, name, val_seq)) \
48  return lut; \
49  } \
50  } \
51  template <> inline bool cci_value_converter<name>::pack(cci_value::reference dst, name const& src) { \
52  static const char* str_val[] = {BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(DEFINE_ENUM_VAL_STR, name, val_seq))}; \
53  dst.set_string(str_val[static_cast<unsigned>(src)]); \
54  return true; \
55  } \
56  template <> inline bool cci_value_converter<name>::unpack(name& dst, cci::cci_value::const_reference src) { \
57  static const std::unordered_map<std::string, name> lut = name##_lut_init(); \
58  if(!src.is_string()) \
59  return false; \
60  auto it = lut.find(src.get_string()); \
61  if(it != std::end(lut)) { \
62  dst = it->second; \
63  return true; \
64  } \
65  return false; \
66  } \
67  }
68 
69 #define DEFINE_NS_ENUM4CCI(ns_name, name, val_seq) \
70  namespace ns_name { \
71  enum class name { BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(DEFINE_ENUM_DECL_VAL, name, val_seq)) }; \
72  } \
73  namespace cci { \
74  namespace { \
75  std::unordered_map<std::string, ns_name::name> ns_name##_##name##_lut_init() { \
76  std::unordered_map<std::string, ns_name::name> lut; \
77  CONCAT(BOOST_PP_SEQ_TRANSFORM(ASSIGN_ENUM_MAP_ENTRY, ns_name::name, val_seq)) \
78  return lut; \
79  } \
80  } \
81  template <> inline bool cci_value_converter<ns_name::name>::pack(cci_value::reference dst, ns_name::name const& src) { \
82  static const char* str_val[] = {BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(DEFINE_ENUM_VAL_STR, name, val_seq))}; \
83  dst.set_string(str_val[static_cast<unsigned>(src)]); \
84  return true; \
85  } \
86  template <> inline bool cci_value_converter<ns_name::name>::unpack(ns_name::name& dst, cci::cci_value::const_reference src) { \
87  static const std::unordered_map<std::string, ns_name::name> lut = ns_name##_##name##_lut_init(); \
88  if(!src.is_string()) \
89  return false; \
90  auto it = lut.find(src.get_string()); \
91  if(it != std::end(lut)) { \
92  dst = it->second; \
93  return true; \
94  } \
95  return false; \
96  } \
97  }
98 #else
99 #define DEFINE_ENUM4CCI(name, val_seq) \
100  enum class name { BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(DEFINE_ENUM_DECL_VAL, name, val_seq)) }; \
101  namespace cci { \
102  namespace { \
103  std::unordered_map<std::string, name> name##_lut_init() { \
104  std::unordered_map<std::string, name> lut; \
105  CONCAT(BOOST_PP_SEQ_TRANSFORM(ASSIGN_ENUM_MAP_ENTRY, name, val_seq)) \
106  return lut; \
107  } \
108  } \
109  template <> struct cci_value_converter<name> { \
110  static inline bool pack(cci_value::reference dst, name const& src) { \
111  static const char* str_val[] = {BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(DEFINE_ENUM_VAL_STR, name, val_seq))}; \
112  dst.set_string(str_val[static_cast<unsigned>(src)]); \
113  return true; \
114  } \
115  static inline bool unpack(name& dst, cci::cci_value::const_reference src) { \
116  static const std::unordered_map<std::string, name> lut = name##_lut_init(); \
117  if(!src.is_string()) \
118  return false; \
119  auto it = lut.find(src.get_string()); \
120  if(it != std::end(lut)) { \
121  dst = it->second; \
122  return true; \
123  } \
124  return false; \
125  } \
126  }; \
127  }
128 
129 #define DEFINE_NS_ENUM4CCI(ns_name, name, val_seq) \
130  namespace ns_name { \
131  enum class name { BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(DEFINE_ENUM_DECL_VAL, name, val_seq)) }; \
132  } \
133  namespace cci { \
134  namespace { \
135  std::unordered_map<std::string, ns_name::name> ns_name##_##name##_lut_init() { \
136  std::unordered_map<std::string, ns_name::name> lut; \
137  CONCAT(BOOST_PP_SEQ_TRANSFORM(ASSIGN_ENUM_MAP_ENTRY, ns_name::name, val_seq)) \
138  return lut; \
139  } \
140  } \
141  template <> struct cci_value_converter<ns_name ::name> { \
142  static inline bool pack(cci_value::reference dst, ns_name::name const& src) { \
143  static const char* str_val[] = {BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(DEFINE_ENUM_VAL_STR, name, val_seq))}; \
144  dst.set_string(str_val[static_cast<unsigned>(src)]); \
145  return true; \
146  } \
147  static inline bool unpack(ns_name::name& dst, cci::cci_value::const_reference src) { \
148  static const std::unordered_map<std::string, ns_name::name> lut = ns_name##_##name##_lut_init(); \
149  if(!src.is_string()) \
150  return false; \
151  auto it = lut.find(src.get_string()); \
152  if(it != std::end(lut)) { \
153  dst = it->second; \
154  return true; \
155  } \
156  return false; \
157  } \
158  }; \
159  }
160 #endif
161 #endif /* _SYSC_SCC_CCI_UTIL_H_ */