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