ETISS 0.11.2
ExtendableTranslatingInstructionSetSimulator(version0.11.2)
Loading...
Searching...
No Matches
VirtualStruct.h
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-3-Clause
2//
3// This file is part of ETISS. It is licensed under the BSD 3-Clause License; you may not use this file except in
4// compliance with the License. You should have received a copy of the license along with this project. If not, see the
5// LICENSE file.
13#ifndef ETISS_PLUGIN_VIRTUALSTRUCT_H_
14#define ETISS_PLUGIN_VIRTUALSTRUCT_H_
15#include "etiss/CVirtualStruct.h"
16#include "etiss/Misc.h"
18
19#include <cstddef>
20#include <cassert>
21
22#include <memory>
23
24namespace etiss
25{
26
27class VSSync;
28
101class VirtualStruct : public std::enable_shared_from_this<VirtualStruct>, public etiss::fault::Injector
102{
103 friend class VSSync;
104
105 public:
110 class Field
111 {
112 public:
120 {
121 public:
122 virtual ~Listener();
123 virtual void write(etiss::VirtualStruct::Field &field, uint64_t val) = 0;
124 };
125
126 private:
128 {
129 bool operator()(const std::pair<Listener *, std::shared_ptr<Listener>> &lhs,
130 const std::pair<Listener *, std::shared_ptr<Listener>> &rhs) const
131 {
132 return lhs.first < rhs.first;
133 }
134 };
135
136 public:
150
151 public: // flags
152 static const int R = 1;
153 static const int W = 2;
154 static const int RW = R | W;
155 static const int L = 4;
157 static const int F = 8;
158 static const int A = 16;
159 static const int P = 32;
161
162 public: // constructor
169 Field(VirtualStruct &parent, const std::string &name, const std::string &prettyname, int flags, size_t width,
170 size_t bitwidth = 0);
171 Field(VirtualStruct &parent, const std::string &name, const std::string &prettyname, int flags, size_t width,
172 bool virtual_enabled, std::function<uint64_t()> lread, std::function<void(uint64_t)> lwrite,
173 size_t bitwidth = 0);
174 virtual ~Field();
175
176 public: // fields
178 const std::string name_;
180 const std::string prettyname_;
182 int flags_;
183 const size_t width_;
184 const size_t bitwidth_;
186
187 public: // read write
188 uint64_t read(size_t offset = 0)
189 const;
192 void write(uint64_t,
193 size_t offset = 0);
196 bool applyBitflip(unsigned position, uint64_t fault_id);
198 std::string &errormsg);
199 void signalWrite();
202 protected: // read write implementation
204 virtual uint64_t _read(size_t offset = 0) const;
207 virtual void _write(uint64_t, size_t offset = 0);
209 virtual bool _applyBitflip(unsigned position, uint64_t fault_id);
211 virtual bool _applyAction(const etiss::fault::Fault &f, const etiss::fault::Action &a, std::string &errormsg);
213 std::function<uint64_t()> lread;
216 std::function<void(uint64_t)> lwrite;
217
218 public:
220 std::function<bool(unsigned position, uint64_t fault_id)> lapplyBitflip;
221
222 public:
223 std::function<void(Field *)> delete_;
224 inline Field *setDeleteP(std::function<void(Field *)> del)
225 {
226 delete_ = del;
227 return this;
228 }
229 inline Field &setDelete(std::function<void(Field *)> del)
230 {
231 delete_ = del;
232 return *this;
233 }
234
235 public:
239 bool addListener(Listener *listener, std::shared_ptr<Listener> ref = nullptr);
244 void removeListener(Listener *listener, std::shared_ptr<Listener> ref = nullptr);
245
246 private:
247 std::set<std::pair<Listener *, std::shared_ptr<Listener>>, listener_pair_compare> listeners;
248 };
249
250 private:
251 template <typename structT, typename retT, retT structT::*field>
253 {
254 static_assert(sizeof(retT) <= sizeof(uint64_t),
255 "Cannot use etiss::VirtualStruct::FieldT for a field larger than uint64_t");
256
257 protected:
258 FieldT(VirtualStruct &parent, const std::string &name, const std::string &prettyname)
259 : Field(parent, name, prettyname, 0, sizeof(retT))
260 {
261 }
262 virtual uint64_t _read(size_t offset = 0) const
263 {
264 // Virtualstruct only provides uint64_t interface. Use offset >1 to fetch upper bits.
265 assert((offset == 0 || (offset < (bitwidth_ / sizeof(uint64_t)))) &&
266 "Virtualstruct field offset out of range");
267 return (uint64_t)((const structT *)parent_.structure_)->*field;
268 }
269 virtual void _write(uint64_t val, size_t offset = 0)
270 {
271 // Virtualstruct only provides uint64_t interface. Use offset >1 to fetch upper bits.
272 assert((offset == 0 || (offset < (bitwidth_ / sizeof(uint64_t)))) &&
273 "Virtualstruct field offset out of range");
274 ((structT *)parent_.structure_)->*field = (retT)val;
275 }
276 };
277
278 protected:
279 VirtualStruct(void *structure, std::function<void(Field *)> dtor = [](Field *f) { delete f; });
280
281 public:
282 virtual ~VirtualStruct();
283
284 bool addField(Field *f, bool noerrorprint = false);
285
286 template <typename structT, typename retT, retT structT::*field>
288 bool addField(const std::string &name, const std::string &prettyname = "", bool noerrorprint = false)
289 {
290
291 Field *ret = new FieldT<structT, retT, field>(*this, name, prettyname);
292
293 if (!addField(ret, noerrorprint))
294 {
295 delete ret;
296 return false;
297 }
298
299 return true;
300 }
301
302 template <typename T>
303 bool addField(const std::string &name, const std::string &prettyname, std::function<T()> read,
304 std::function<void(T)> write, bool supportsListener = false, bool noerrorprint = false)
305 {
306 int flags = 0;
307 if (read)
308 flags |= Field::R;
309 if (write)
310 flags |= Field::W;
311 if (supportsListener)
312 flags |= Field::L;
313 Field *f = new Field(
314 *this, name, prettyname, flags, sizeof(T), false, [read]() { return (uint64_t)read(); },
315 [write](uint64_t v) { write((T)v); });
316 if (addField(f, noerrorprint))
317 return true;
318 delete f;
319 return false;
320 }
321
322 std::shared_ptr<Field> findName(const std::string &name) const;
323 std::shared_ptr<Field> findPrettyName(const std::string &name) const;
324 void foreachField(const std::function<void(std::shared_ptr<Field>)> &func);
325
326 bool mountStruct(const std::string &name, const std::shared_ptr<VirtualStruct> vs);
327 std::shared_ptr<VirtualStruct> findStruct(const std::string &name);
328 void foreachStruct(const std::function<void(const std::string &name, VirtualStruct &vs)> &func);
329
330 void close();
331 bool isClosed();
332
333 public: // inherited from etiss::fault::Injector
334 virtual std::list<std::string> listFields();
335 virtual std::list<std::string> listSubInjectors();
336
337 virtual std::shared_ptr<etiss::fault::Injector> getSubInjector(const std::string &name);
338 virtual std::shared_ptr<etiss::fault::Injector> getParentInjector();
339
340 virtual bool acceleratedTrigger(const etiss::fault::Trigger &, int32_t fault_id);
341
342 protected: // inherited from etiss::fault::Injector
343 virtual void *fastFieldAccessPtr(const std::string &name, std::string &errormsg);
344 virtual bool readField(void *fastfieldaccessptr, uint64_t &val, std::string &errormsg);
345 virtual bool applyAction(const etiss::fault::Fault &fault, const etiss::fault::Action &action,
346 std::string &errormsg);
347 virtual bool update_field_access_rights(const etiss::fault::Action &action, std::string &errormsg);
348
349 public:
352 std::function<bool(const etiss::fault::Fault &, const etiss::fault::Action &, std::string & /*errormsg*/)>
354
355 public:
356 void *const structure_;
358
359 private:
360 std::list<Field *> fields_;
361 std::map<std::string, Field *> fieldNames_;
362 std::map<std::string, Field *> fieldPrettyNames_;
363 std::map<std::string, std::weak_ptr<VirtualStruct>> subStructs_;
364 std::function<void(Field *)> dtor_;
365 bool closed;
366
367 private:
368 std::shared_ptr<VirtualStruct> parent_;
369
370 public:
371 static std::shared_ptr<VirtualStruct> allocate(void *structure, std::function<void(Field *)> delete_);
372
373 public: // name resolving an root VirtualStruct
374 static std::shared_ptr<VirtualStruct> root();
375
376 std::shared_ptr<VirtualStruct> getVirtualStruct(const std::string &path);
377
378 std::shared_ptr<VirtualStruct::Field> getResolvedField(const std::string &path);
379
380 public: // C interface
384 static std::shared_ptr<VirtualStruct> allocateFromC(void *handle, VirtualStruct_names names,
385 VirtualStruct_prettyNames prettyNames_optional,
386 VirtualStruct_read read_recommended,
387 VirtualStruct_write write_optional,
388 VirtualStruct_setListenerCallback setListenerCallback_optional,
389 std::function<void(void *handle)> cleanup);
390};
391
397{
398 public:
399 VSSync();
400 ~VSSync();
401
402 private:
403 static std::recursive_mutex &mutex();
404};
405
415void copy(VirtualStruct &dst, VirtualStruct &src, std::list<std::shared_ptr<VirtualStruct::Field>> &dst_notPresent,
416 std::list<std::shared_ptr<VirtualStruct::Field>> &dst_notWriteable,
417 std::list<std::shared_ptr<VirtualStruct::Field>> dst_unknown, bool pretend = false,
418 std::list<std::shared_ptr<VirtualStruct::Field>> *src_private = 0,
419 std::list<std::shared_ptr<VirtualStruct::Field>> *dst_private = 0);
420
422{
423 public:
424 virtual inline ~VirtualStructSupport() {}
428 virtual std::shared_ptr<VirtualStruct> getStruct() = 0;
429 virtual const std::string &getName() = 0;
430};
431
432#define ETISS_VIRTUALSTRUCT_ADDFIELD(VIRTUALSTRUCT, STRUCT, FIELD, NAME, PRETTYNAME) \
433 (VIRTUALSTRUCT).addField<STRUCT, decltype(((STRUCT *)0)->FIELD), &STRUCT::FIELD>(NAME, PRETTYNAME);
434
435} // namespace etiss
436
437#endif
contains the fault injector interface class.
general configuration and logging
do v
Definition arm_acle.h:76
static __inline__ uint64_t
Definition arm_cde.h:31
static __inline__ int32_t
Definition arm_mve.h:51
uint64_t(* VirtualStruct_read)(void *handle, uint32_t index)
read the value of the field at the given index
void(* VirtualStruct_setListenerCallback)(void *handle, void *callbackHandle, void(*callback)(void *handle, void *callbackHandle, uint32_t index))
setter function to register the callback handle for listener supported fields.
void(* VirtualStruct_write)(void *handle, uint32_t index)
write the value of the field at the given index
const char *const *(* VirtualStruct_names)(void *handle)
must return an array of zero terminated strings.
const char *const *(* VirtualStruct_prettyNames)(void *handle)
similar to above array but with human readable/alternative field names (see etiss::VirtualStruct)
used for synchronization of the tree of virtual structs.
static std::recursive_mutex & mutex()
virtual std::shared_ptr< VirtualStruct > getStruct()=0
virtual const std::string & getName()=0
virtual void _write(uint64_t val, size_t offset=0)
override this function to implement writes in case of AccessMode::VIRTUAL / AccessMode::PREFER_LAMBDA
virtual uint64_t _read(size_t offset=0) const
override this function to implement reads in case of AccessMode::VIRTUAL / AccessMode::PREFER_LAMBDA
FieldT(VirtualStruct &parent, const std::string &name, const std::string &prettyname)
NOTE: etiss::CPUArch should implement support for Listeners by either using the etiss::VirtualStruct:...
virtual void write(etiss::VirtualStruct::Field &field, uint64_t val)=0
a Field instance represents e.g.
Field & setDelete(std::function< void(Field *)> del)
std::function< uint64_t()> lread
set this function for reads in case of AccessMode::LAMBDA / AccessMode::PREFER_LAMBDA
static const int W
write flag
Field * setDeleteP(std::function< void(Field *)> del)
AccessMode
defines how a field should perform reads/writes.
@ PREFER_LAMBDA
tries to use the lread,lwrite functions and falls back to virtual functions
@ LAMBDA
uses the lread,lwrite functions
@ VIRTUAL
uses the virtual _read() / _write functions
uint64_t read(size_t offset=0) const
function to read bits/a value from the Field.
bool applyAction(const etiss::fault::Fault &f, const etiss::fault::Action &a, std::string &errormsg)
advanced fault injection. Field must have the A flag to use this.
static const int A
supports advanced fault injection/tracing with the applyAction function
const std::string name_
name of the field.
virtual bool _applyBitflip(unsigned position, uint64_t fault_id)
override this function to implement bitflip applying to a field
static const int RW
flags to signal that a field supports read and write operations
virtual void _write(uint64_t, size_t offset=0)
override this function to implement writes in case of AccessMode::VIRTUAL / AccessMode::PREFER_LAMBDA
const size_t width_
width in bytes (rounded up if neccessary)
virtual uint64_t _read(size_t offset=0) const
override this function to implement reads in case of AccessMode::VIRTUAL / AccessMode::PREFER_LAMBDA
void signalWrite()
this function should be called if the listener flag is set and the field changed without using the wr...
void removeListener(Listener *listener, std::shared_ptr< Listener > ref=nullptr)
static const int L
supports listener plugins; used for etiss::RegisterDevicePlugins to determine access to a variable/fi...
VirtualStruct & parent_
reference to parent virtual struct
int flags_
read write flags as specified by the static const int parameters of Field: R,W,L
bool addListener(Listener *listener, std::shared_ptr< Listener > ref=nullptr)
static const int P
private field: this flag indicates that this field is an implementation specific field that e....
bool applyBitflip(unsigned position, uint64_t fault_id)
function to write a bitflip to a field
std::function< bool(unsigned position, uint64_t fault_id)> lapplyBitflip
if this function is set the the default implementation of applyBitflip will use it
static const int R
read flag
static const int F
supports fault injection/tracing
const std::string prettyname_
alternative/human readable name of the field.
std::function< void(uint64_t)> lwrite
set this function for writes in case of AccessMode::LAMBDA / AccessMode::PREFER_LAMBDA
virtual bool _applyAction(const etiss::fault::Fault &f, const etiss::fault::Action &a, std::string &errormsg)
override this function to implement advanced action handling
std::set< std::pair< Listener *, std::shared_ptr< Listener > >, listener_pair_compare > listeners
const size_t bitwidth_
width in bits
std::function< void(Field *)> delete_
void write(uint64_t, size_t offset=0)
function to write bits/a value to the Field.
abstract representation of an module of a simulation which could be a embedded device of the cpu of a...
virtual bool readField(void *fastfieldaccessptr, uint64_t &val, std::string &errormsg)
read the value of a field
std::map< std::string, Field * > fieldNames_
std::map< std::string, Field * > fieldPrettyNames_
void foreachStruct(const std::function< void(const std::string &name, VirtualStruct &vs)> &func)
bool mountStruct(const std::string &name, const std::shared_ptr< VirtualStruct > vs)
std::shared_ptr< VirtualStruct > getVirtualStruct(const std::string &path)
bool addField(const std::string &name, const std::string &prettyname, std::function< T()> read, std::function< void(T)> write, bool supportsListener=false, bool noerrorprint=false)
virtual bool acceleratedTrigger(const etiss::fault::Trigger &, int32_t fault_id)
std::list< Field * > fields_
std::shared_ptr< Field > findName(const std::string &name) const
static std::shared_ptr< VirtualStruct > allocateFromC(void *handle, VirtualStruct_names names, VirtualStruct_prettyNames prettyNames_optional, VirtualStruct_read read_recommended, VirtualStruct_write write_optional, VirtualStruct_setListenerCallback setListenerCallback_optional, std::function< void(void *handle)> cleanup)
implemented in CVirtualStruct.cpp
virtual bool applyAction(const etiss::fault::Fault &fault, const etiss::fault::Action &action, std::string &errormsg)
bool addField(const std::string &name, const std::string &prettyname="", bool noerrorprint=false)
add a structure field to this VirtualStructure
static std::shared_ptr< VirtualStruct > root()
std::map< std::string, std::weak_ptr< VirtualStruct > > subStructs_
bool addField(Field *f, bool noerrorprint=false)
static std::shared_ptr< VirtualStruct > allocate(void *structure, std::function< void(Field *)> delete_)
virtual std::list< std::string > listSubInjectors()
list all sub injectors.
virtual std::list< std::string > listFields()
list all fields directly reachable by this injector
std::function< void(Field *)> dtor_
virtual void * fastFieldAccessPtr(const std::string &name, std::string &errormsg)
void foreachField(const std::function< void(std::shared_ptr< Field >)> &func)
std::shared_ptr< VirtualStruct > parent_
std::shared_ptr< VirtualStruct::Field > getResolvedField(const std::string &path)
std::function< bool(const etiss::fault::Trigger &, int32_t)> acceleratedTrigger_
virtual std::shared_ptr< etiss::fault::Injector > getParentInjector()
get a the parent injector (root returns 0).
virtual bool update_field_access_rights(const etiss::fault::Action &action, std::string &errormsg)
Update the field of injector with access rights to allow action (used to get type of action).
std::shared_ptr< Field > findPrettyName(const std::string &name) const
std::function< bool(const etiss::fault::Fault &, const etiss::fault::Action &, std::string &)> applyCustomAction
set this function to handle custom commands passed by etiss::fault::Action of the type etiss::fault::...
std::shared_ptr< VirtualStruct > findStruct(const std::string &name)
virtual std::shared_ptr< etiss::fault::Injector > getSubInjector(const std::string &name)
get a sub injector.
forwards: include/jit/*
Definition Benchmark.h:17
void copy(VirtualStruct &dst, VirtualStruct &src, std::list< std::shared_ptr< VirtualStruct::Field > > &dst_notPresent, std::list< std::shared_ptr< VirtualStruct::Field > > &dst_notWriteable, std::list< std::shared_ptr< VirtualStruct::Field > > dst_unknown, bool pretend=false, std::list< std::shared_ptr< VirtualStruct::Field > > *src_private=0, std::list< std::shared_ptr< VirtualStruct::Field > > *dst_private=0)
copies all fields with the same name from the source to the destination structure.
#define bool
Definition stdbool.h:15
bool operator()(const std::pair< Listener *, std::shared_ptr< Listener > > &lhs, const std::pair< Listener *, std::shared_ptr< Listener > > &rhs) const