C++ Device API Reference Manual
Reference documentation for the Simics C++ Device API.
 
Loading...
Searching...
No Matches
attribute-traits.h
Go to the documentation of this file.
1// -*- mode: C++; c-file-style: "virtutech-c++" -*-
2
3/*
4 © 2021 Intel Corporation
5
6 This software and the related documents are Intel copyrighted materials, and
7 your use of them is governed by the express license under which they were
8 provided to you ("License"). Unless the License provides otherwise, you may
9 not use, modify, copy, publish, distribute, disclose or transmit this software
10 or the related documents without Intel's prior written permission.
11
12 This software and the related documents are provided as is, with no express or
13 implied warranties, other than those that are expressly stated in the License.
14*/
15
16#ifndef SIMICS_ATTRIBUTE_TRAITS_H
17#define SIMICS_ATTRIBUTE_TRAITS_H
18
19#include <simics/base/attr-value.h> // SIM_attr_list_item
20#include <string>
21#include <array>
22#include <vector>
23#include <list>
24#include <utility> // pair
25#include <algorithm> // copy_n
26#include <deque>
27#include <map>
28#include <type_traits> // is_enum, underlying_type_t, remove_cv_t
29#include <limits> // numeric_limits
30
31#include "conf-object.h"
32#include "connect.h" // ConnectBase
33
34namespace simics {
35namespace detail {
36
37template <typename T>
39 static attr_value_t f(const T &src);
40};
41
42template <typename T>
44 static T f(const attr_value_t &src);
45};
46
47// ConfObjectRef, needed by std_to_attr<T> when T is derived from ConnectBase
48template <>
50 static attr_value_t f(const ConfObjectRef &src) {
51 if (src) {
52 if (src.port_name().empty()) {
53 return SIM_make_attr_object(src);
54 } else {
55 attr_value_t ret = SIM_alloc_attr_list(2);
56 SIM_attr_list_set_item(&ret, 0, SIM_make_attr_object(src));
57 attr_value_t string = SIM_make_attr_string(
58 src.port_name().c_str());
59 SIM_attr_list_set_item(&ret, 1, string);
60 return ret;
61 }
62 } else {
63 return SIM_make_attr_nil();
64 }
65 }
66};
67
68template <>
70 static ConfObjectRef f(const attr_value_t &src) {
71 if (SIM_attr_is_list(src)) {
72 if (SIM_attr_list_size(src) != 2) {
73 throw SetIllegalType {
74 "Expected Simics list type with exactly 2 members"
75 };
76 }
77
78 auto item = SIM_attr_list_item(src, 0);
79 if (!SIM_attr_is_object(item)) {
80 throw SetIllegalType {
81 "The first item should be Simics object type"
82 };
83 }
84 ConfObjectRef r = SIM_attr_object(item);
85
86 item = SIM_attr_list_item(src, 1);
87 if (!SIM_attr_is_string(item)) {
88 throw SetIllegalType {
89 "The second item should be Simics string type"
90 };
91 }
92 r.set_port_name(SIM_attr_string(item));
93 return r;
94 } else {
95 if (!SIM_attr_is_object(src) && !SIM_attr_is_nil(src)) {
96 throw SetIllegalType {
97 "Expected Simics object or NIL type"
98 };
99 }
100 return SIM_attr_object_or_nil(src);
101 }
102 }
103};
104} // namespace detail
105
109template <typename T> inline
110typename std::enable_if<std::is_enum<T>::value, attr_value_t>::type
111std_to_attr(const T &src) {
113 static_cast<std::underlying_type_t<T>>(src));
114}
115
119template <typename T> inline
120typename std::enable_if<std::is_base_of<ConnectBase, T>::value,
121 attr_value_t>::type
122std_to_attr(const T &src) {
124}
125
129template <typename T> inline
130typename std::enable_if<!std::is_enum<T>::value
131 && !std::is_base_of<ConnectBase, T>::value,
132 attr_value_t>::type
133std_to_attr(const T &src) {
135}
136
140template <typename T> inline
141typename std::enable_if<std::is_enum<T>::value, T>::type
142attr_to_std(attr_value_t src) {
143 return static_cast<T>(
145}
146
150template <typename T> inline
151typename std::enable_if<std::is_base_of<ConnectBase, T>::value, T>::type
152attr_to_std(attr_value_t src) {
153 T c;
155 throw std::runtime_error {
156 "Unable to set to an illegal object"
157 };
158 }
159 return c;
160}
161
165template <typename T> inline
166typename std::enable_if<!std::is_enum<T>::value
167 && !std::is_base_of<ConnectBase, T>::value,
168 T>::type
169attr_to_std(attr_value_t src) {
171}
172
173namespace detail {
174
175// Integral
176#define _STD2ATTR_INT_HELPER(type) \
177 template <> \
178 struct attr_from_std_helper<type> { \
179 static attr_value_t f(const type &src) { \
180 return SIM_make_attr_int64(src); \
181 } \
182 };
183#define _STD2ATTR_UINT_HELPER(type) \
184 template <> \
185 struct attr_from_std_helper<type> { \
186 static attr_value_t f(const type &src) { \
187 return SIM_make_attr_uint64(src); \
188 } \
189 };
191_STD2ATTR_INT_HELPER(signed char)
192_STD2ATTR_UINT_HELPER(unsigned char)
193_STD2ATTR_INT_HELPER(short) // NOLINT(runtime/int)
194_STD2ATTR_UINT_HELPER(unsigned short) // NOLINT(runtime/int)
196_STD2ATTR_UINT_HELPER(unsigned int)
197_STD2ATTR_INT_HELPER(long int) // NOLINT(runtime/int)
198_STD2ATTR_UINT_HELPER(unsigned long int) // NOLINT(runtime/int)
199_STD2ATTR_INT_HELPER(long long int) // NOLINT(runtime/int)
200_STD2ATTR_UINT_HELPER(unsigned long long int) // NOLINT(runtime/int)
201#undef _STD2ATTR_INT_HELPER
202#undef _STD2ATTR_UINT_HELPER
203
204#define _ATTR2STD_INT_HELPER(type) \
205 template <> \
206 struct attr_to_std_helper<type> { \
207 static type f(const attr_value_t &src) { \
208 if (!SIM_attr_is_integer(src)) { \
209 throw SetIllegalType { \
210 "Expected Simics integer type" \
211 }; \
212 } \
213 intmax_t i = SIM_attr_integer(src); \
214 if (i > (std::numeric_limits<type>::max)() \
215 || i < (std::numeric_limits<type>::min)()) { \
216 throw SetIllegalValue { \
217 "Value does not fit in type" \
218 }; \
219 } \
220 return (type) i; \
221 } \
222 };
223
224#define _ATTR2STD_UINT_HELPER(type) \
225 template <> \
226 struct attr_to_std_helper<type> { \
227 static type f(const attr_value_t &src) { \
228 if (!SIM_attr_is_integer(src)) { \
229 throw SetIllegalType { \
230 "Expected Simics integer type" \
231 }; \
232 } \
233 uintmax_t i = SIM_attr_integer(src); \
234 if (sizeof(type) != 8 \
235 && i > (std::numeric_limits<type>::max)()) { \
236 throw SetIllegalValue { \
237 "Value does not fit in type" \
238 }; \
239 } \
240 return (type) i; \
241 } \
242 };
244_ATTR2STD_INT_HELPER(signed char)
245_ATTR2STD_UINT_HELPER(unsigned char)
246_ATTR2STD_INT_HELPER(short) // NOLINT(runtime/int)
247_ATTR2STD_UINT_HELPER(unsigned short) // NOLINT(runtime/int)
249_ATTR2STD_UINT_HELPER(unsigned int)
250_ATTR2STD_INT_HELPER(long int) // NOLINT(runtime/int)
251_ATTR2STD_UINT_HELPER(unsigned long int) // NOLINT(runtime/int)
252_ATTR2STD_INT_HELPER(long long int) // NOLINT(runtime/int)
253_ATTR2STD_UINT_HELPER(unsigned long long int) // NOLINT(runtime/int)
254#undef _ATTR2STD_INT_HELPER
255#undef _ATTR2STD_UINT_HELPER
256
257
258// Float
259#define _STD2ATTR_FLOAT_HELPER(type) \
260 template <> \
261 struct attr_from_std_helper<type> { \
262 static attr_value_t f(const type &src) { \
263 return SIM_make_attr_floating(src); \
264 } \
265 };
268#undef _STD2ATTR_FLOAT_HELPER
269
270#define _ATTR2STD_FLOAT_HELPER(type) \
271 template <> \
272 struct attr_to_std_helper<type> { \
273 static type f(const attr_value_t &src) { \
274 if (!SIM_attr_is_floating(src)) { \
275 throw SetIllegalType { \
276 "Expected Simics floating type" \
277 }; \
278 } \
279 return (type) SIM_attr_floating(src); \
280 } \
281 };
284#undef _ATTR2STD_FLOAT_HELPER
285
286
287// std::string
288template <>
289struct attr_from_std_helper<std::string> {
290 static attr_value_t f(const std::string &src) {
291 return SIM_make_attr_string(src.c_str());
292 }
293};
294
295template <>
296struct attr_to_std_helper<std::string> {
297 static std::string f(const attr_value_t &src) {
298 if (!SIM_attr_is_string(src)) {
299 throw SetIllegalType {
300 "Expected Simics string type"
301 };
302 }
303 return SIM_attr_string(src);
304 }
305};
306
307template <>
308struct attr_from_std_helper<const char*> {
309 static attr_value_t f(const char *src) {
310 return SIM_make_attr_string(src);
311 }
312};
313
314template <>
315struct attr_to_std_helper<const char*> {
316 static const char *f(const attr_value_t &src) {
317 if (SIM_attr_is_nil(src)) {
318 return nullptr;
319 } else {
320 if (!SIM_attr_is_string(src)) {
321 throw SetIllegalType {
322 "Expected Simics string type"
323 };
324 }
325 return SIM_attr_string(src);
326 }
327 }
328};
329
330
331// bool
332template <>
334 static attr_value_t f(const bool &src) {
335 return SIM_make_attr_boolean(src);
336 }
337};
338
339template <>
340struct attr_to_std_helper<bool> {
341 static bool f(const attr_value_t &src) {
342 if (!SIM_attr_is_boolean(src)) {
343 throw SetIllegalType {
344 "Expected Simics boolean type"
345 };
346 }
347 return SIM_attr_boolean(src);
348 }
349};
350
351
352// attr_value_t
353template <>
354struct attr_from_std_helper<attr_value_t> {
355 static attr_value_t f(const attr_value_t &src) {
356 return src;
357 }
358};
359
360template <>
361struct attr_to_std_helper<attr_value_t> {
362 static attr_value_t f(const attr_value_t &src) {
363 return src;
364 }
365};
366
367
368// Container
369template <typename C, typename T = typename C::value_type>
370attr_value_t from_container(const C &src) {
371 auto it = src.cbegin();
372 const size_t size = src.size();
373 attr_value_t dst = SIM_alloc_attr_list(size);
374 for (unsigned i = 0; i < size; ++i, ++it) {
375 SIM_attr_list_set_item(&dst, i, std_to_attr(*it));
376 }
377 return dst;
378}
379
380template <typename V, std::size_t N>
381struct attr_from_std_helper<std::array<V, N>> {
382 static attr_value_t f(const std::array<V, N> &src) {
383 return from_container<std::array<V, N>>(src);
384 }
385};
386
387template <typename V>
388struct attr_from_std_helper<std::vector<V>> {
389 static attr_value_t f(const std::vector<V> &src) {
390 return from_container<std::vector<V>>(src);
391 }
392};
393
394template <typename V>
395struct attr_from_std_helper<std::list<V>> {
396 static attr_value_t f(const std::list<V> &src) {
397 return from_container<std::list<V>>(src);
398 }
399};
400
401template <typename V>
402struct attr_from_std_helper<std::deque<V>> {
403 static attr_value_t f(const std::deque<V> &src) {
404 return from_container<std::deque<V>>(src);
405 }
406};
407
408template <typename X, typename Y>
409struct attr_from_std_helper<std::pair<X, Y>> {
410 static attr_value_t f(const std::pair<X, Y>& src) {
411 attr_value_t dst = SIM_alloc_attr_list(2);
412 SIM_attr_list_set_item(&dst, 0, std_to_attr(src.first));
413 SIM_attr_list_set_item(&dst, 1, std_to_attr(src.second));
414 return dst;
415 }
416};
417
418template <typename X, typename Y>
419struct attr_from_std_helper<std::map<X, Y>> {
420 static attr_value_t f(const std::map<X, Y>& src) {
421 const unsigned size = src.size();
422 attr_value_t dst = SIM_alloc_attr_list(size);
423 auto it = src.cbegin();
424 for (unsigned i = 0; i < size; ++i, ++it) {
425 std::pair<X, Y> p {it->first, it->second};
426 SIM_attr_list_set_item(&dst, i, std_to_attr(p));
427 }
428 return dst;
429 }
430};
431
432template <typename C, typename T = typename C::value_type>
433C to_container(const attr_value_t &src) {
434 if (!SIM_attr_is_list(src)) {
435 throw SetIllegalType {
436 "Expected Simics list type"
437 };
438 }
439 const unsigned size = SIM_attr_list_size(src);
440 C dst(size);
441 // The scope of variable it should be inside the for, but for cannot
442 // initialize two different type variables
443 auto it = dst.begin();
444 for (unsigned i = 0; i < size; ++i, ++it) {
445 *it = attr_to_std<T>(SIM_attr_list_item(src, i));
446 }
447 return dst;
448}
449
450template <typename V, std::size_t N>
451struct attr_to_std_helper<std::array<V, N>> {
452 static std::array<V, N> f(const attr_value_t &src) {
453 std::array<V, N> arr;
454 arr.fill(V{});
455 auto vec = to_container<std::vector<V>>(src);
456 std::copy_n(vec.begin(), N, arr.begin());
457 return arr;
458 }
459};
460
461template <typename V>
462struct attr_to_std_helper<std::vector<V>> {
463 static std::vector<V> f(const attr_value_t &src) {
464 return to_container<std::vector<V>>(src);
465 }
466};
467
468template <typename V>
469struct attr_to_std_helper<std::list<V>> {
470 static std::list<V> f(const attr_value_t &src) {
471 return to_container<std::list<V>>(src);
472 }
473};
474
475template <typename V>
476struct attr_to_std_helper<std::deque<V>> {
477 static std::deque<V> f(const attr_value_t &src) {
478 return to_container<std::deque<V>>(src);
479 }
480};
481
482template <typename X, typename Y>
483struct attr_to_std_helper<std::pair<X, Y>> {
484 static std::pair<X, Y> f(const attr_value_t& src) {
485 if (!SIM_attr_is_list(src) || SIM_attr_list_size(src) != 2) {
486 throw SetIllegalType {
487 "Expected Simics list type with exactly two members"
488 };
489 }
490 return {attr_to_std<X>(SIM_attr_list_item(src, 0)),
491 attr_to_std<Y>(SIM_attr_list_item(src, 1))};
492 }
493};
494
495template <typename X, typename Y>
496struct attr_to_std_helper<std::map<X, Y>> {
497 static std::map<X, Y> f(const attr_value_t& src) {
498 if (!SIM_attr_is_list(src)) {
499 throw SetIllegalType {
500 "Expected Simics list type"
501 };
502 }
503 std::map<X, Y> ret;
504 for (unsigned i = 0; i < SIM_attr_list_size(src); ++i) {
505 ret.emplace(attr_to_std<std::pair<X, Y>>(
506 SIM_attr_list_item(src, i)));
507 }
508 return ret;
509 }
510};
511
512// Use this type for Simics "data" type
513using data_attribute = std::vector<uint8>;
514
515template <>
517 static attr_value_t f(const data_attribute& src) {
518 return SIM_make_attr_data(src.size(), src.data());
519 }
520};
521
522template <>
524 static data_attribute f(const attr_value_t& src) {
525 if (!SIM_attr_is_data(src)) {
526 throw SetIllegalType {
527 "Expected Simics data type"
528 };
529 }
530 size_t size = SIM_attr_data_size(src);
531 const uint8 *data = SIM_attr_data(src);
532 return data_attribute(data, data + size);
533 }
534};
535
536} // namespace detail
537} // namespace simics
538
539#endif
#define _STD2ATTR_UINT_HELPER(type)
Definition: attribute-traits.h:183
#define _ATTR2STD_UINT_HELPER(type)
Definition: attribute-traits.h:224
#define _STD2ATTR_INT_HELPER(type)
Definition: attribute-traits.h:176
#define _ATTR2STD_FLOAT_HELPER(type)
Definition: attribute-traits.h:270
#define _ATTR2STD_INT_HELPER(type)
Definition: attribute-traits.h:204
#define _STD2ATTR_FLOAT_HELPER(type)
Definition: attribute-traits.h:259
Represents Simics C type conf_object_t.
Definition: conf-object.h:37
const std::string & port_name() const
Get & set name for the port implements the interface.
Definition: conf-object.h:63
void set_port_name(const std::string &name)
Definition: conf-object.h:64
Definition: attribute-exceptions.h:38
std::vector< uint8 > data_attribute
Definition: attribute-traits.h:513
C to_container(const attr_value_t &src)
Definition: attribute-traits.h:433
attr_value_t from_container(const C &src)
Definition: attribute-traits.h:370
Definition: attr-value.h:23
std::enable_if< std::is_enum< T >::value, attr_value_t >::type std_to_attr(const T &src)
Function transforms C++ enum type T to Simics attr_value_t.
Definition: attribute-traits.h:111
std::enable_if< std::is_enum< T >::value, T >::type attr_to_std(attr_value_t src)
Function transforms Simics attr_value_t to C++ enum type.
Definition: attribute-traits.h:142
Definition: common-types.h:63
static attr_value_t f(const ConfObjectRef &src)
Definition: attribute-traits.h:50
static attr_value_t f(const attr_value_t &src)
Definition: attribute-traits.h:355
static attr_value_t f(const bool &src)
Definition: attribute-traits.h:334
static attr_value_t f(const char *src)
Definition: attribute-traits.h:309
static attr_value_t f(const data_attribute &src)
Definition: attribute-traits.h:517
static attr_value_t f(const std::array< V, N > &src)
Definition: attribute-traits.h:382
static attr_value_t f(const std::deque< V > &src)
Definition: attribute-traits.h:403
static attr_value_t f(const std::list< V > &src)
Definition: attribute-traits.h:396
static attr_value_t f(const std::map< X, Y > &src)
Definition: attribute-traits.h:420
static attr_value_t f(const std::pair< X, Y > &src)
Definition: attribute-traits.h:410
static attr_value_t f(const std::string &src)
Definition: attribute-traits.h:290
static attr_value_t f(const std::vector< V > &src)
Definition: attribute-traits.h:389
Definition: attribute-traits.h:38
static attr_value_t f(const T &src)
static ConfObjectRef f(const attr_value_t &src)
Definition: attribute-traits.h:70
static attr_value_t f(const attr_value_t &src)
Definition: attribute-traits.h:362
static bool f(const attr_value_t &src)
Definition: attribute-traits.h:341
static const char * f(const attr_value_t &src)
Definition: attribute-traits.h:316
static data_attribute f(const attr_value_t &src)
Definition: attribute-traits.h:524
static std::array< V, N > f(const attr_value_t &src)
Definition: attribute-traits.h:452
static std::deque< V > f(const attr_value_t &src)
Definition: attribute-traits.h:477
static std::list< V > f(const attr_value_t &src)
Definition: attribute-traits.h:470
static std::map< X, Y > f(const attr_value_t &src)
Definition: attribute-traits.h:497
static std::pair< X, Y > f(const attr_value_t &src)
Definition: attribute-traits.h:484
static std::string f(const attr_value_t &src)
Definition: attribute-traits.h:297
static std::vector< V > f(const attr_value_t &src)
Definition: attribute-traits.h:463
Definition: attribute-traits.h:43
static T f(const attr_value_t &src)