ETISS 0.8.0
Extendable Translating Instruction Set Simulator (version 0.8.0)
VirtualStruct.h
Go to the documentation of this file.
1 
52 #ifndef ETISS_PLUGIN_VIRTUALSTRUCT_H_
53 #define ETISS_PLUGIN_VIRTUALSTRUCT_H_
54 #include "etiss/CVirtualStruct.h"
55 #include "etiss/Misc.h"
56 #include "etiss/fault/Injector.h"
57 
58 #include <cstddef>
59 
60 #include <memory>
61 
62 namespace etiss
63 {
64 
65 class VSSync;
66 
139 class VirtualStruct : public std::enable_shared_from_this<VirtualStruct>, public etiss::fault::Injector
140 {
141  friend class VSSync;
142 
143  public:
148  class Field
149  {
150  public:
157  class Listener
158  {
159  public:
160  virtual ~Listener();
161  virtual void write(etiss::VirtualStruct::Field &field, uint64_t val) = 0;
162  };
163 
164  private:
166  {
167  bool operator()(const std::pair<Listener *, std::shared_ptr<Listener>> &lhs,
168  const std::pair<Listener *, std::shared_ptr<Listener>> &rhs) const
169  {
170  return lhs.first < rhs.first;
171  }
172  };
173 
174  public:
179  {
187  };
188 
189  public: // flags
190  static const int R = 1;
191  static const int W = 2;
192  static const int RW = R | W;
193  static const int L = 4;
195  static const int F = 8;
196  static const int A = 16;
197  static const int P = 32;
199 
200  public: // constructor
207  Field(VirtualStruct &parent, const std::string &name, const std::string &prettyname, int flags, size_t width,
208  size_t bitwidth = 0);
209  Field(VirtualStruct &parent, const std::string &name, const std::string &prettyname, int flags, size_t width,
210  bool virtual_enabled, std::function<uint64_t()> lread, std::function<void(uint64_t)> lwrite,
211  size_t bitwidth = 0);
212  virtual ~Field();
213 
214  public: // fields
216  const std::string name_;
218  const std::string prettyname_;
220  const int flags_;
221  const size_t width_;
222  const size_t bitwidth_;
224 
225  public: // read write
226  uint64_t read()
227  const;
230  void write(uint64_t);
233  bool applyBitflip(unsigned position, uint64_t fault_id);
234  bool applyAction(const etiss::fault::Fault &f, const etiss::fault::Action &a,
235  std::string &errormsg);
236  void signalWrite();
239  protected: // read write implementation
241  virtual uint64_t _read() const;
244  virtual void _write(uint64_t);
246  virtual bool _applyBitflip(unsigned position, uint64_t fault_id);
248  virtual bool _applyAction(const etiss::fault::Fault &f, const etiss::fault::Action &a, std::string &errormsg);
250  std::function<uint64_t()> lread;
253  std::function<void(uint64_t)> lwrite;
254 
255  public:
257  std::function<bool(unsigned position, uint64_t fault_id)> lapplyBitflip;
258 
259  public:
260  std::function<void(Field *)> delete_;
261  inline Field *setDeleteP(std::function<void(Field *)> del)
262  {
263  delete_ = del;
264  return this;
265  }
266  inline Field &setDelete(std::function<void(Field *)> del)
267  {
268  delete_ = del;
269  return *this;
270  }
271 
272  public:
276  bool addListener(Listener *listener, std::shared_ptr<Listener> ref = nullptr);
281  void removeListener(Listener *listener, std::shared_ptr<Listener> ref = nullptr);
282 
283  private:
284  std::set<std::pair<Listener *, std::shared_ptr<Listener>>, listener_pair_compare> listeners;
285  };
286 
287  private:
288  template <typename structT, typename retT, retT structT::*field>
290  {
291  static_assert(sizeof(retT) <= sizeof(uint64_t),
292  "Cannot use etiss::VirtualStruct::FieldT for a field larger than uint64_t");
293 
294  protected:
295  FieldT(VirtualStruct &parent, const std::string &name, const std::string &prettyname)
296  : Field(parent, name, prettyname, 0, sizeof(retT))
297  {
298  }
299  virtual uint64_t _read() const { return (uint64_t)((const structT *)parent_.structure_)->*field; }
300  virtual void _write(uint64_t val) { ((structT *)parent_.structure_)->*field = (retT)val; }
301  };
302 
303  private:
304  VirtualStruct(void *structure, std::function<void(Field *)> dtor = [](Field *f) { delete f; });
305 
306  public:
307  virtual ~VirtualStruct();
308 
309  bool addField(Field *f, bool noerrorprint = false);
310 
311  template <typename structT, typename retT, retT structT::*field>
313  bool addField(const std::string &name, const std::string &prettyname = "", bool noerrorprint = false)
314  {
315 
316  Field *ret = new FieldT<structT, retT, field>(*this, name, prettyname);
317 
318  if (!addField(ret, noerrorprint))
319  {
320  delete ret;
321  return false;
322  }
323 
324  return true;
325  }
326 
327  template <typename T>
328  bool addField(const std::string &name, const std::string &prettyname, std::function<T()> read,
329  std::function<void(T)> write, bool supportsListener = false, bool noerrorprint = false)
330  {
331  int flags = 0;
332  if (read)
333  flags |= Field::R;
334  if (write)
335  flags |= Field::W;
336  if (supportsListener)
337  flags |= Field::L;
338  Field *f = new Field(*this, name, prettyname, flags, sizeof(T), false, [read]() { return (uint64_t)read(); },
339  [write](uint64_t v) { write((T)v); });
340  if (addField(f, noerrorprint))
341  return true;
342  delete f;
343  return false;
344  }
345 
346  std::shared_ptr<Field> findName(const std::string &name) const;
347  std::shared_ptr<Field> findPrettyName(const std::string &name) const;
348  void foreachField(const std::function<void(std::shared_ptr<Field>)> &func);
349 
350  bool mountStruct(const std::string &name, const std::shared_ptr<VirtualStruct> vs);
351  std::shared_ptr<VirtualStruct> findStruct(const std::string &name);
352  void foreachStruct(const std::function<void(const std::string &name, VirtualStruct &vs)> &func);
353 
354  void close();
355  bool isClosed();
356 
357  public: // inherited from etiss::fault::Injector
358  virtual std::list<std::string> listFields();
359  virtual std::list<std::string> listSubInjectors();
360 
361  virtual std::shared_ptr<etiss::fault::Injector> getSubInjector(const std::string &name);
362  virtual std::shared_ptr<etiss::fault::Injector> getParentInjector();
363 
364  virtual bool acceleratedTrigger(const etiss::fault::Trigger &, int32_t fault_id);
365 
366  protected: // inherited from etiss::fault::Injector
367  virtual void *fastFieldAccessPtr(const std::string &name, std::string &errormsg);
368  virtual bool readField(void *fastfieldaccessptr, uint64_t &val, std::string &errormsg);
369  virtual bool applyAction(const etiss::fault::Fault &fault, const etiss::fault::Action &action,
370  std::string &errormsg);
371 
372  public:
375  std::function<bool(const etiss::fault::Fault &, const etiss::fault::Action &, std::string & /*errormsg*/)>
377 
378  public:
379  void *const structure_;
381 
382  private:
383  std::list<Field *> fields_;
384  std::map<std::string, Field *> fieldNames_;
385  std::map<std::string, Field *> fieldPrettyNames_;
386  std::map<std::string, std::weak_ptr<VirtualStruct>> subStructs_;
387  std::function<void(Field *)> dtor_;
388  bool closed;
389 
390  private:
391  std::shared_ptr<VirtualStruct> parent_;
392 
393  public:
394  static std::shared_ptr<VirtualStruct> allocate(void *structure, std::function<void(Field *)> delete_);
395 
396  public: // name resolving an root VirtualStruct
397  static std::shared_ptr<VirtualStruct> root();
398 
399  std::shared_ptr<VirtualStruct> getVirtualStruct(const std::string &path);
400 
401  std::shared_ptr<VirtualStruct::Field> getResolvedField(const std::string &path);
402 
403  public: // C interface
407  static std::shared_ptr<VirtualStruct> allocateFromC(void *handle, VirtualStruct_names names,
408  VirtualStruct_prettyNames prettyNames_optional,
409  VirtualStruct_read read_recommended,
410  VirtualStruct_write write_optional,
411  VirtualStruct_setListenerCallback setListenerCallback_optional,
412  std::function<void(void *handle)> cleanup);
413 };
414 
419 class VSSync
420 {
421  public:
422  VSSync();
423  ~VSSync();
424 
425  private:
426  static std::recursive_mutex &mutex();
427 };
428 
438 void copy(VirtualStruct &dst, VirtualStruct &src, std::list<std::shared_ptr<VirtualStruct::Field>> &dst_notPresent,
439  std::list<std::shared_ptr<VirtualStruct::Field>> &dst_notWriteable,
440  std::list<std::shared_ptr<VirtualStruct::Field>> dst_unknown, bool pretend = false,
441  std::list<std::shared_ptr<VirtualStruct::Field>> *src_private = 0,
442  std::list<std::shared_ptr<VirtualStruct::Field>> *dst_private = 0);
443 
445 {
446  public:
447  virtual inline ~VirtualStructSupport() {}
451  virtual std::shared_ptr<VirtualStruct> getStruct() = 0;
452 };
453 
454 #define ETISS_VIRTUALSTRUCT_ADDFIELD(VIRTUALSTRUCT, STRUCT, FIELD, NAME, PRETTYNAME) \
455  (VIRTUALSTRUCT).addField<STRUCT, decltype(((STRUCT *)0)->FIELD), &STRUCT::FIELD>(NAME, PRETTYNAME);
456 
457 } // namespace etiss
458 
459 #endif
#define static_assert(x, y)
Definition: Fault.cpp:60
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
const char *const *(* VirtualStruct_prettyNames)(void *handle)
similar to above array but with human readable/alternative field names (see etiss::VirtualStruct)
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.
used for synchronization of the tree of virtual structs.
static std::recursive_mutex & mutex()
virtual std::shared_ptr< VirtualStruct > getStruct()=0
virtual void _write(uint64_t val)
override this function to implement writes in case of AccessMode::VIRTUAL / AccessMode::PREFER_LAMBDA
FieldT(VirtualStruct &parent, const std::string &name, const std::string &prettyname)
virtual uint64_t _read() const
override this function to implement reads in case of AccessMode::VIRTUAL / AccessMode::PREFER_LAMBDA
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.
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(VirtualStruct &parent, const std::string &name, const std::string &prettyname, int flags, size_t width, size_t bitwidth=0)
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
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
Field & setDelete(std::function< void(Field *)> del)
Field * setDeleteP(std::function< void(Field *)> del)
const size_t width_
width in bytes (rounded up if neccessary)
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...
virtual uint64_t _read() const
override this function to implement reads in case of AccessMode::VIRTUAL / AccessMode::PREFER_LAMBDA
VirtualStruct & parent_
reference to parent virtual struct
bool addListener(Listener *listener, std::shared_ptr< Listener > ref=nullptr)
void write(uint64_t)
function to write bits/a value to the Field.
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
const AccessMode accessMode_
static const int R
read flag
static const int F
supports fault injection/tracing
uint64_t read() const
function to read bits/a value from the Field.
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
const int flags_
read write flags as specified by the static const int parameters of Field: R,W,L
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_
virtual void _write(uint64_t)
override this function to implement writes in case of AccessMode::VIRTUAL / AccessMode::PREFER_LAMBDA
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
void *const structure_
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)
VirtualStruct(void *structure, std::function< void(Field *)> dtor=[](Field *f) { delete f;})
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).
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.
Page Table Entry (PTE) defines the composition of Page Frame Number (PFN) and relavant flags.
Definition: Benchmark.h:53
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