18 size_t width,
size_t bitwidth)
24 ,
bitwidth_(bitwidth ? bitwidth : width * 8)
30 size_t width,
bool virtual_enabled, std::function<
uint64_t()> lread,
31 std::function<
void(
uint64_t)> lwrite,
size_t bitwidth)
34 , prettyname_(prettyname)
37 , bitwidth_(bitwidth ? bitwidth : width * 8)
50 std::runtime_error(
"VirtualStruct::Field::write called but the write flag is not set");
62 throw std::runtime_error(
63 "VirtualStruct is configured to use lambda expressions but no read function was provided.");
76 throw std::runtime_error(
"invalid enum value");
86 throw std::runtime_error(
"VirtualStruct::Field::write called but the write flag is not set");
88 if (accessMode_ == LAMBDA && !lwrite)
89 throw std::runtime_error(
90 "VirtualStruct is configured to use lambda expressions but no read function was provided.");
121 for (
auto l : listeners)
125 l.first->write(*
this, read());
140 return _applyBitflip(position, fault_id);
146 std::string &errormsg)
148 if (!(flags_ & (A | F)))
150 errormsg =
"field doesn't support action handling";
153 return _applyAction(f, a, errormsg);
158 throw std::runtime_error(
"VirtualStruct::Field::_read called but not implemented");
162 throw std::runtime_error(
"VirtualStruct::Field::_write called but not implemented");
169 return lapplyBitflip(position, fault_id);
170 if ((flags_ & RW) != RW)
174 errval = val ^ errval;
176 std::stringstream ss;
177 ss <<
"Injected bitflip in " << name_ <<
" 0x" << std::hex << val <<
"->0x" << errval << std::dec;
182 std::string &errormsg)
184 if (a.
getType() == +etiss::fault::Action::type_t::MASK)
191 case etiss::fault::Action::mask_op_t::AND:
192 errval = (val & mask_value);
194 case etiss::fault::Action::mask_op_t::OR:
195 errval = (val | mask_value);
197 case etiss::fault::Action::mask_op_t::XOR:
198 errval = (val ^ mask_value);
200 case etiss::fault::Action::mask_op_t::NAND:
201 errval = ~(val & mask_value);
203 case etiss::fault::Action::mask_op_t::NOR:
204 errval = ~(val | mask_value);
206 case etiss::fault::Action::mask_op_t::NOP:
211 std::stringstream ss;
212 ss <<
"Injected mask fault in " << name_ <<
" 0x" << std::hex << val <<
" " << a.
getMaskOp() <<
" 0x"
213 << mask_value <<
"->0x" << errval << std::dec;
217 else if (a.
getType() == +etiss::fault::Action::type_t::BITFLIP)
228 listeners.insert(std::pair<
Listener *, std::shared_ptr<Listener>>(listener, ref));
233 listeners.erase(std::pair<
Listener *, std::shared_ptr<Listener>>(listener, ref));
247 if ((*iter)->delete_)
249 std::function<void(
Field *)> del_ = (*iter)->delete_;
261 "likely result in a memory leak.");
278 if (f->
name_.empty())
316 std::shared_ptr<const VirtualStruct> pref = shared_from_this();
319 return std::shared_ptr<VirtualStruct::Field>();
329 std::shared_ptr<const VirtualStruct> pref = shared_from_this();
339 std::shared_ptr<const VirtualStruct> pref = shared_from_this();
366 if (find->second.lock())
374 vs->parent_ = shared_from_this();
375 subStructs_.insert(std::pair<std::string, std::weak_ptr<VirtualStruct>>(name, vs));
383 return find->second.lock();
384 return std::shared_ptr<VirtualStruct>();
391 auto sp = e.second.lock();
414 std::list<std::string> ret;
416 [&ret](std::shared_ptr<Field> f)
419 ret.push_back(f->name_);
425 std::list<std::string> ret;
459 errormsg =
"No such field";
464 errormsg =
"No read access";
471 std::string &errormsg)
475 case +etiss::fault::Action::type_t::COMMAND:
480 ": VirtualStruct::applyCustomAction function not set. cannot handle custom actions.";
485 case +etiss::fault::Action::type_t::MASK:
486#if __cplusplus >= 201703L
489 case +etiss::fault::Action::type_t::BITFLIP:
547 case +etiss::fault::Action::type_t::MASK:
548#if __cplusplus >= 201703L
551 case +etiss::fault::Action::type_t::BITFLIP:
561 std::string(
"VirtualStruct:update_field_access_rights(): Required field not a field in VirtualStruct!");
577 static std::recursive_mutex mu;
582 std::list<std::shared_ptr<VirtualStruct::Field>> ¬Writeable,
583 std::list<std::shared_ptr<VirtualStruct::Field>> unknown,
bool pretend,
584 std::list<std::shared_ptr<VirtualStruct::Field>> *src_private,
585 std::list<std::shared_ptr<VirtualStruct::Field>> *dst_private)
590 std::set<std::shared_ptr<VirtualStruct::Field>> dst_known;
593 [&](std::shared_ptr<VirtualStruct::Field> srcf)
598 src_private->push_back(srcf);
602 auto dstf = dst.
findName(srcf->name_);
605 notPresent.push_back(srcf);
611 notPresent.push_back(srcf);
615 dst_known.insert(dstf);
619 notWriteable.push_back(dstf);
624 dstf->write(srcf->read());
628 [&](std::shared_ptr<VirtualStruct::Field> dstf)
630 if (dst_known.find(dstf) == dst_known.end())
636 dst_private->push_back(dstf);
641 unknown.push_back(dstf);
651 return std::shared_ptr<VirtualStruct>(ret, [](
VirtualStruct *vs) {
delete vs; });
656 static std::shared_ptr<VirtualStruct> r =
allocate(0, [](
Field *) {});
663 return shared_from_this();
664 std::shared_ptr<VirtualStruct> ret;
665 if (path.find_first_of(
".") != std::string::npos)
670 auto pp1 = path.find(
"::");
675 auto prev = shared_from_this();
681 return prev->getVirtualStruct(path.substr(pp1 + 2));
686 auto find =
subStructs_.find((pp1 == std::string::npos) ? path : path.substr(0, pp1));
689 ret = find->second.lock();
696 if (pp1 == std::string::npos)
702 return ret->getVirtualStruct(path.substr(pp1 + 2));
708 return std::shared_ptr<etiss::fault::Injector>(
VirtualStruct::root()->getVirtualStruct(path));
713 auto pp1 = path.find_first_of(
".");
714 if (pp1 == std::string::npos)
715 return std::shared_ptr<VirtualStruct::Field>();
719 return std::shared_ptr<VirtualStruct::Field>();
721 auto ret = m->findName(path.substr(pp1 + 1));
723 ret = m->findPrettyName(path.substr(pp1 + 1));
contains an action class that describes actions associated with a fault
contains the fault container class that stores triggers and actions for fault injection
contains the Trigger class that defines conditions under which actions of a Fault need to be applied.
static __inline__ uint64_t
static __inline__ int32_t
used for synchronization of the tree of virtual structs.
static std::recursive_mutex & mutex()
NOTE: etiss::CPUArch should implement support for Listeners by either using the etiss::VirtualStruct:...
a Field instance represents e.g.
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)
@ 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
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
const AccessMode accessMode_
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.
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 size_t bitwidth_
width in bits
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)
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
virtual bool applyAction(const etiss::fault::Fault &fault, const etiss::fault::Action &action, std::string &errormsg)
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).
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.
const mask_op_t & getMaskOp() const
MASK only.
uint64_t getMaskValue() const
const std::string & getTargetField() const
BITFLIP only.
const type_t & getType() const
unsigned getTargetBit() const
BITFLIP only.
virtual std::string getInjectorPath()
returns the path of the current object.
static ptr get(const std::string &injectorPath)
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.
void log(Verbosity level, std::string msg)
write log message at the given level.