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)
190 case etiss::fault::Action::mask_op_t::AND:
191 errval = (val & mask_value);
193 case etiss::fault::Action::mask_op_t::OR:
194 errval = (val | mask_value);
196 case etiss::fault::Action::mask_op_t::XOR:
197 errval = (val ^ mask_value);
199 case etiss::fault::Action::mask_op_t::NAND:
200 errval = ~(val & mask_value);
202 case etiss::fault::Action::mask_op_t::NOR:
203 errval = ~(val | mask_value);
205 case etiss::fault::Action::mask_op_t::NOP:
210 std::stringstream ss;
211 ss <<
"Injected mask fault in " << name_ <<
" 0x" << std::hex << val <<
" " << a.
getMaskOp() <<
" 0x"
212 << mask_value <<
"->0x" << errval << std::dec;
216 else if (a.
getType() == +etiss::fault::Action::type_t::BITFLIP)
227 listeners.insert(std::pair<
Listener *, std::shared_ptr<Listener>>(listener, ref));
232 listeners.erase(std::pair<
Listener *, std::shared_ptr<Listener>>(listener, ref));
246 if ((*iter)->delete_)
248 std::function<void(
Field *)> del_ = (*iter)->delete_;
260 "likely result in a memory leak.");
277 if (f->
name_.empty())
315 std::shared_ptr<const VirtualStruct> pref = shared_from_this();
318 return std::shared_ptr<VirtualStruct::Field>();
328 std::shared_ptr<const VirtualStruct> pref = shared_from_this();
338 std::shared_ptr<const VirtualStruct> pref = shared_from_this();
365 if (find->second.lock())
373 vs->parent_ = shared_from_this();
374 subStructs_.insert(std::pair<std::string, std::weak_ptr<VirtualStruct>>(name, vs));
382 return find->second.lock();
383 return std::shared_ptr<VirtualStruct>();
390 auto sp = e.second.lock();
413 std::list<std::string> ret;
415 [&ret](std::shared_ptr<Field> f)
418 ret.push_back(f->name_);
424 std::list<std::string> ret;
458 errormsg =
"No such field";
463 errormsg =
"No read access";
470 std::string &errormsg)
474 case +etiss::fault::Action::type_t::COMMAND:
479 ": VirtualStruct::applyCustomAction function not set. cannot handle custom actions.";
484 case +etiss::fault::Action::type_t::MASK:
485#if __cplusplus >= 201703L
488 case +etiss::fault::Action::type_t::BITFLIP:
546 case +etiss::fault::Action::type_t::MASK:
547#if __cplusplus >= 201703L
550 case +etiss::fault::Action::type_t::BITFLIP:
560 std::string(
"VirtualStruct:update_field_access_rights(): Required field not a field in VirtualStruct!");
576 static std::recursive_mutex mu;
581 std::list<std::shared_ptr<VirtualStruct::Field>> ¬Writeable,
582 std::list<std::shared_ptr<VirtualStruct::Field>> unknown,
bool pretend,
583 std::list<std::shared_ptr<VirtualStruct::Field>> *src_private,
584 std::list<std::shared_ptr<VirtualStruct::Field>> *dst_private)
589 std::set<std::shared_ptr<VirtualStruct::Field>> dst_known;
592 [&](std::shared_ptr<VirtualStruct::Field> srcf)
597 src_private->push_back(srcf);
601 auto dstf = dst.
findName(srcf->name_);
604 notPresent.push_back(srcf);
610 notPresent.push_back(srcf);
614 dst_known.insert(dstf);
618 notWriteable.push_back(dstf);
623 dstf->write(srcf->read());
627 [&](std::shared_ptr<VirtualStruct::Field> dstf)
629 if (dst_known.find(dstf) == dst_known.end())
635 dst_private->push_back(dstf);
640 unknown.push_back(dstf);
650 return std::shared_ptr<VirtualStruct>(ret, [](
VirtualStruct *vs) {
delete vs; });
655 static std::shared_ptr<VirtualStruct> r =
allocate(0, [](
Field *) {});
662 return shared_from_this();
663 std::shared_ptr<VirtualStruct> ret;
664 if (path.find_first_of(
".") != std::string::npos)
669 auto pp1 = path.find(
"::");
674 auto prev = shared_from_this();
680 return prev->getVirtualStruct(path.substr(pp1 + 2));
685 auto find =
subStructs_.find((pp1 == std::string::npos) ? path : path.substr(0, pp1));
688 ret = find->second.lock();
695 if (pp1 == std::string::npos)
701 return ret->getVirtualStruct(path.substr(pp1 + 2));
707 return std::shared_ptr<etiss::fault::Injector>(
VirtualStruct::root()->getVirtualStruct(path));
712 auto pp1 = path.find_first_of(
".");
713 if (pp1 == std::string::npos)
714 return std::shared_ptr<VirtualStruct::Field>();
718 return std::shared_ptr<VirtualStruct::Field>();
720 auto ret = m->findName(path.substr(pp1 + 1));
722 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
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
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
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)
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
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.
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
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)
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.