C++ Device API Reference Manual
Reference documentation for the Simics C++ Device API.
 
Loading...
Searching...
No Matches
attribute-setter.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_DETAIL_ATTRIBUTE_SETTER_H
17#define SIMICS_DETAIL_ATTRIBUTE_SETTER_H
18
19#include <simics/base/log.h>
20
21#include <utility> // move
22
23#include "simics/attribute-traits.h" // attr_to_std
24#include "simics/conf-object.h" // from_obj
25
26namespace simics {
27namespace detail {
28
29template <typename T> struct attr_setter_helper;
30template <typename T, typename O> struct attr_setter_helper_dual;
31
32/*
33 * Returns a functor of type set_attr_t serving as a wrapper for a given
34 * pointer to a class member/method.
35 *
36 * The macro uses simics::attr_setter_helper template, which implements
37 * wrapper functions for member.
38 *
39 * Wrapper uses simics::attr_to_std to convert attr_value_t into a standard
40 * C++ type value. If conversion fails, wrapper catches exception and returns
41 * proper value of type set_error_t.
42 */
43#define _S_SINGLE(func_ptr) \
44 simics::detail::attr_setter_helper<decltype(&func_ptr)>::\
45 template f<&func_ptr>
46#define _S_DUAL(cls, m) \
47 simics::detail::attr_setter_helper_dual<decltype(&cls::m), cls>::\
48 template f<&cls::m>
49
50inline set_error_t handle_exception(const std::exception &e) {
51 SIM_attribute_error(e.what());
52 if (dynamic_cast<const SetInterfaceNotFound *>(&e)) {
53 return Sim_Set_Interface_Not_Found;
54 } else if (dynamic_cast<const SetIllegalType *>(&e)) {
55 return Sim_Set_Illegal_Type;
56 } else if (dynamic_cast<const SetNotWritable *>(&e)) {
57 return Sim_Set_Not_Writable;
58 } else {
59 return Sim_Set_Illegal_Value;
60 }
61}
62
63// For class member function pointer
64template <typename O, typename T>
65struct attr_setter_helper<void (O::*)(T)> {
66 // Always fail. Use two arguments version instead
67 static_assert(sizeof(T) == -1,
68 "Pass class member pointer as two arguments to the MACRO:"
69 " cls and member");
70};
71
72template <typename O, typename T>
73struct attr_setter_helper<void (O::*)(T&)> {
74 // Always fail. Use two arguments version instead
75 static_assert(sizeof(T) == -1,
76 "Pass class member pointer as two arguments to the MACRO:"
77 " cls and member");
78};
79
80template <typename O, typename T, typename C>
81struct attr_setter_helper_dual<void (O::*)(T), C> {
82 static_assert(std::is_base_of<O, C>::value, "C must be derived from O");
83 template <void (O::*F)(T)>
84 static set_error_t f(conf_object_t *obj, attr_value_t *val) {
85 O *o = static_cast<O*>(from_obj<C>(obj));
86 try {
87 (o->*F)(attr_to_std<std::remove_cv_t<T>>(*val));
88 } catch (const std::exception &e) {
89 return handle_exception(e);
90 }
91 return Sim_Set_Ok;
92 }
93};
94
95template <typename O, typename T, typename C>
96struct attr_setter_helper_dual<void (O::*)(T&), C> {
97 template <void (O::*F)(T&)>
98 static set_error_t f(conf_object_t *obj, attr_value_t *val) {
99 C *o = from_obj<C>(obj);
100 try {
101 T tval = attr_to_std<T>(*val);
102 (o->*F)(tval);
103 } catch (const std::exception &e) {
104 return handle_exception(e);
105 }
106 return Sim_Set_Ok;
107 }
108};
109
110// For class member variable pointer
111template <typename O, typename T>
112struct attr_setter_helper<T O::*> {
113 // Always fail. Use two arguments version instead
114 static_assert(sizeof(T) == -1,
115 "Pass class member pointer as two arguments to the MACRO:"
116 " cls and member");
117};
118
119template <typename O, typename T, typename C>
120struct attr_setter_helper_dual<T O::*, C> {
121 // If T is derived from ConnectBase, use set instead of =
122 template <T O::*R, typename T1 = T> static
123 typename std::enable_if<std::is_base_of<ConnectBase, T1>::value,
124 set_error_t>::type
125 f(conf_object_t *obj, attr_value_t *val) {
126 C *o = from_obj<C>(obj);
127 if ((o->*R).set(attr_to_std<ConfObjectRef>(*val)) == false) {
128 return Sim_Set_Interface_Not_Found;
129 }
130 return Sim_Set_Ok;
131 }
132
133 // If T is a std::array and the value_type is derived from ConnectBase,
134 // assign the new value use set for each member
135 template <T O::*R, typename T1 = T> static
136 typename std::enable_if<is_array_of_connectbase<T1>::value,
137 set_error_t>::type
138 f(conf_object_t *obj, attr_value_t *val) {
139 C *o = from_obj<C>(obj);
140 auto it = (o->*R).begin();
141 for (unsigned i = 0; it != (o->*R).end(); ++i, ++it) {
142 if (it->set(attr_to_std<ConfObjectRef>(
143 SIM_attr_list_item(*val, i))) == false) {
144 return Sim_Set_Interface_Not_Found;
145 }
146 }
147 return Sim_Set_Ok;
148 }
149
150 // If T is a variable length container and the value_type is derived
151 // from ConnectBase, construct a new T
152 template <T O::*R, typename T1 = T> static
153 typename std::enable_if<is_container_of_connectbase<T1>::value,
154 set_error_t>::type
155 f(conf_object_t *obj, attr_value_t *val) {
156 C *o = from_obj<C>(obj);
157 T new_t(SIM_attr_list_size(*val), typename T::value_type(obj));
158 auto it = new_t.begin();
159 for (unsigned i = 0; it != new_t.end(); ++i, ++it) {
160 if (it->set(attr_to_std<ConfObjectRef>(
161 SIM_attr_list_item(*val, i))) == false) {
162 return Sim_Set_Interface_Not_Found;
163 }
164 }
165 o->*R = std::move(new_t);
166 return Sim_Set_Ok;
167 }
168
169 // For all other types
170 template <T O::*R, typename T1 = T> static
171 typename std::enable_if<!is_container_of_connectbase<T1>::value
173 && !std::is_base_of<ConnectBase, T1>::value,
174 set_error_t>::type
175 f(conf_object_t *obj, attr_value_t *val) {
176 C *o = from_obj<C>(obj);
177 try {
178 o->*R = attr_to_std<T>(*val);
179 } catch (const std::exception &e) {
180 return handle_exception(e);
181 }
182 return Sim_Set_Ok;
183 }
184};
185
186// For normal functions take an object reference
187template <typename O, typename T>
188struct attr_setter_helper<void (*)(O&, T&)> {
189 template <void (*F)(O&, T&)>
190 static set_error_t f(conf_object_t *obj, attr_value_t *val) {
191 O *o = from_obj<O>(obj);
192 try {
193 F(*o, attr_to_std<std::remove_cv_t<T>>(*val));
194 } catch (const std::exception &e) {
195 return handle_exception(e);
196 }
197 return Sim_Set_Ok;
198 }
199};
200
201// For normal functions take an object value
202template <typename O, typename T>
203struct attr_setter_helper<void (*)(O&, T)> {
204 template <void (*F)(O&, T)>
205 static set_error_t f(conf_object_t *obj, attr_value_t *val) {
206 O *o = from_obj<O>(obj);
207 try {
208 F(*o, attr_to_std<std::remove_cv_t<T>>(*val));
209 } catch (const std::exception &e) {
210 return handle_exception(e);
211 }
212 return Sim_Set_Ok;
213 }
214};
215
216template <typename O, typename T>
217struct attr_setter_helper<T& (*)(O&)> {
218 template <T& (*F)(O&)>
219 static set_error_t f(conf_object_t *obj, attr_value_t *val) {
220 O *o = from_obj<O>(obj);
221 try {
222 F(*o) = attr_to_std<T>(*val);
223 } catch (const std::exception &e) {
224 return handle_exception(e);
225 }
226 return Sim_Set_Ok;
227 }
228};
229
230} // namespace detail
231} // namespace simics
232
233#endif
Definition: attribute-exceptions.h:38
Definition: attribute-exceptions.h:25
Definition: attribute-exceptions.h:64
set_error_t handle_exception(const std::exception &e)
Definition: attribute-setter.h:50
Definition: after-bank.h:33
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:207
static set_error_t f(conf_object_t *obj, attr_value_t *val)
Definition: attribute-setter.h:219
static set_error_t f(conf_object_t *obj, attr_value_t *val)
Definition: attribute-setter.h:190
static set_error_t f(conf_object_t *obj, attr_value_t *val)
Definition: attribute-setter.h:205
static std::enable_if< is_container_of_connectbase< T1 >::value, set_error_t >::type f(conf_object_t *obj, attr_value_t *val)
Definition: attribute-setter.h:155
static std::enable_if< std::is_base_of< ConnectBase, T1 >::value, set_error_t >::type f(conf_object_t *obj, attr_value_t *val)
Definition: attribute-setter.h:125
static std::enable_if<!is_container_of_connectbase< T1 >::value &&!is_array_of_connectbase< T1 >::value &&!std::is_base_of< ConnectBase, T1 >::value, set_error_t >::type f(conf_object_t *obj, attr_value_t *val)
Definition: attribute-setter.h:175
static std::enable_if< is_array_of_connectbase< T1 >::value, set_error_t >::type f(conf_object_t *obj, attr_value_t *val)
Definition: attribute-setter.h:138
static set_error_t f(conf_object_t *obj, attr_value_t *val)
Definition: attribute-setter.h:98
static set_error_t f(conf_object_t *obj, attr_value_t *val)
Definition: attribute-setter.h:84
Definition: attribute-setter.h:30
Definition: attribute-setter.h:29
Definition: attribute-traits.h:151