ETISS 0.11.2
ExtendableTranslatingInstructionSetSimulator(version0.11.2)
Loading...
Searching...
No Matches
Stressor.cpp
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.
6
7#ifndef NO_ETISS
8#include "etiss/fault/XML.h"
12#include "etiss/fault/Trigger.h"
13#include "etiss/fault/Action.h"
14#include "etiss/fault/Fault.h"
15#include "etiss/Misc.h"
16#else
17#include "fault/XML.h"
18#include "fault/Stressor.h"
19#include "fault/Injector.h"
21#include "fault/Trigger.h"
22#include "fault/Action.h"
23#include "fault/Fault.h"
24#endif
25
26#include <fstream>
27#include <iostream>
28#include <map>
29
30#if CXX0X_UP_SUPPORTED
31#include <mutex>
32#endif
33
34namespace etiss
35{
36
37namespace fault
38{
39
40#if CXX0X_UP_SUPPORTED
41static std::mutex &faults_sync()
42{
43 static std::mutex mu;
44 return mu;
45}
46#endif
47// Map with all fault definitions found in XML file
48std::map<int32_t, Fault> &Stressor::faults()
49{
50 static std::map<int32_t, Fault> map;
51 return map;
52}
53
54#ifndef NO_ETISS
55etiss::int32 Stressor::event_code_;
56#else
58#endif
59
60bool Stressor::loadXML(const std::string &file, const int coreID)
61{
62
63#ifdef NO_ETISS
64 std::cout << std::string("Called etiss::fault::Stressor::loadXML(file=") + file + std::string(")") << std::endl;
65#else
66 etiss::log(etiss::INFO, std::string("Called etiss::fault::Stressor::loadXML(file=") + file + std::string(")"));
67#endif
68
69 coreIDActuallXML = coreID;
70
71 // Vector which gets the faults of the xml file
72 std::vector<Fault> fault_definitions;
73 std::vector<FaultRef> initial_faults;
74
75 // open and parse file
76 std::ifstream in;
77 in.open(file.c_str());
78 if (!in.is_open())
79 {
80#ifdef NO_ETISS
81 std::cout << "etiss::fault::Stressor::loadXML(): Failed open file " << file << std::endl;
82#else
83 etiss::log(etiss::ERROR, std::string("etiss::fault::Stressor::loadXML:") +
84 std::string(" Failed to open Trigger file ") + file);
85#endif
86 return false;
87 }
88 pugi::xml_document doc;
89
90 if (!etiss::fault::parseXML(doc, in, std::cout))
91 {
92#ifdef NO_ETISS
93 std::cout << "etiss::fault::Stressor::loadXML: Failed parse file " << file << std::endl;
94#else
96 std::string("etiss::fault::Stressor::loadXML:") + std::string(" Failed to parse file ") + file);
97#endif
98 return false;
99 }
100
101 xml::Diagnostics diag;
102
103 if (!etiss::fault::parseXML(fault_definitions, doc, diag))
104 {
105 std::stringstream ss;
106 diag.print(ss);
107#ifdef NO_ETISS
108 std::cout << "etiss::fault::Stressor::loadXML: Failed parse Fault definitions " << ss << std::endl;
109#else
110 etiss::log(etiss::ERROR, std::string("etiss::fault::Stressor::loadXML:") +
111 std::string(" Failed parse Fault definitions ") + ss.str());
112#endif
113 return false;
114 }
115
116 // add fault_definitions into a map -> access with static std::map<int32_t,Fault> &
117 // faults()
118 bool ok = true;
119 for (const auto &fdef : fault_definitions)
120 {
121 if (!addFaultDefinition(fdef))
122 {
123#ifdef NO_ETISS
124 std::cout << "etiss::fault::Stressor::loadXML: Failed to add Fault definitions: " << fdef.name_
125 << std::endl;
126#else
128 std::string("etiss::fault::Stressor::loadXML:") +
129 std::string(" Failed to add Fault definitions "),
130 fdef);
131#endif
132 ok = false;
133 }
134 }
135
136 if (!etiss::fault::parseXML(initial_faults, doc, diag))
137 {
138 std::stringstream ss;
139 diag.print(ss);
140#ifdef NO_ETISS
141 std::cout << "etiss::fault::Stressor::loadXML: Failed parse initial Faults " << ss << std::endl;
142#else
143 etiss::log(etiss::ERROR, std::string("etiss::fault::Stressor::loadXML:") +
144 std::string(" Failed parse initial Faults ") + ss.str());
145#endif
146 return false;
147 }
148
149 for (const auto &fref : initial_faults)
150 {
151 if (!addFault(fref.get_fault()))
152 {
153#ifdef NO_ETISS
154 std::cout << "etiss::fault::Stressor::loadXML: Failed to add initial Fault: " << fref.name_ << std::endl;
155#else
157 std::string("etiss::fault::Stressor::loadXML:") + std::string(" Failed to add initial Fault "),
158 fref);
159#endif
160 ok = false;
161 }
162 }
163
164 return ok;
165}
166
168{
169
170#ifdef NO_ETISS
171 std::cout << "etiss::fault::Stressor::addFaultDefinition called." << std::endl;
172#else
173 etiss::log(etiss::INFO, std::string("etiss::fault::Stressor::addFaultDefinition called. "));
174#endif
175
176 // check if fault already exists
177 std::map<int32_t, Fault>::iterator find = faults().find(f.id_);
178 if (find != faults().end())
179 {
180#ifdef NO_ETISS
181 std::cout << "etiss::fault::Stressor::addFaultDefinition: Fault definition already registered:" << f.toString()
182 << std::endl;
183#else
185 std::string("etiss::fault::Stressor::addFaultDefinition:") +
186 std::string(" Fault definition already registered: "),
187 f);
188#endif
189 return false;
190 }
191
192 // insert fault into the definitions map
193 faults().insert(std::pair<int32_t, Fault>(f.id_, f));
194
195 return true;
196}
197
198bool Stressor::addFault(const Fault &f, bool injected_fault)
199{
200
201#if CXX0X_UP_SUPPORTED
202 if (!injected_fault) // otherwise a deadlock from firedTrigger->addFault would occur
203 std::lock_guard<std::mutex> lock(faults_sync());
204#endif
205
206 Injector::ptr iptr = nullptr;
207
208 // check if fault is registered in fault definitions table
209 std::map<int32_t, Fault>::iterator find = faults().find(f.id_);
210 if (find == faults().end())
211 {
212#ifdef NO_ETISS
213 std::cout << "etiss::fault::Stressor::addFault: Fault not registered in Fault definitions:" << f.toString()
214 << std::endl;
215#else
217 std::string("etiss::fault::Stressor::addFault:") +
218 std::string(" Fault not registered in Fault definitions. "),
219 f);
220#endif
221 return false;
222 }
223
224 // Iterate through triggers of the fault
225 for (const auto &trigger : f.triggers)
226 {
227
228 if (trigger.getType() != +etiss::fault::Trigger_Type::NOP) // only add Trigger, if it is not a NOP
229 {
230 iptr = trigger.getInjector();
231
232 if (iptr != nullptr)
233 {
234#ifdef NO_ETISS
235 std::cout << "etiss::fault::Stressor::addFault: Added trigger: " << trigger.toString() << std::endl;
236#else
238 std::string("etiss::fault::Stressor::addFault:") + std::string(" Added trigger: "), trigger);
239#endif
240 iptr->addTrigger(trigger, f.id_);
241 }
242 else
243 {
244#ifdef NO_ETISS
245 std::cout << "etiss::fault::Stressor::addFault: Error: Injector not found for: " << trigger.toString()
246 << std::endl;
247#else
249 std::string("etiss::fault::Stressor::addFault:") + std::string(" Injector not found for "),
250 trigger);
251#endif
253 }
254 }
255 else // Trigger is of type NOP
256 {
257 etiss::log(etiss::WARNING, std::string("etiss::fault::Stressor::addFault:") +
258 std::string(" Trigger is a NOP and is not added."));
259 }
260 }
261
262 if (iptr != nullptr)
263 {
264 for (const auto &it : f.actions)
265 {
266 if (it.is_action_on_field())
267 {
268 bool ret_update = false;
269 std::string errormsg;
270 ret_update = iptr->update_field_access_rights(it, errormsg);
271 if (!ret_update)
272 {
273 etiss::log(etiss::ERROR, std::string("etiss::fault::Stressor::addFault:") + errormsg);
274 }
275 }
276 }
277 }
278
279 return true;
280}
281
282bool Stressor::removeFault(const Fault &f, bool injected_fault)
283{
284
285#if CXX0X_UP_SUPPORTED
286 if (!injected_fault) // otherwise a deadlock from firedTrigger->addFault would occur
287 std::lock_guard<std::mutex> lock(faults_sync());
288#endif
289
290 Injector::ptr iptr = nullptr;
291
292 // check if fault is registered in fault definitions table
293 std::map<int32_t, Fault>::iterator find = faults().find(f.id_);
294 if (find == faults().end())
295 {
296#ifdef NO_ETISS
297 std::cout << "etiss::fault::Stressor::removeFault: Fault not registered in Fault definitions:" << f.toString()
298 << std::endl;
299#else
301 std::string("etiss::fault::Stressor::removeFault:") +
302 std::string(" Fault not registered in Fault definitions. "),
303 f);
304#endif
305 return false;
306 }
307
308 // Iterate through triggers of the fault
309 for (const auto &trigger : f.triggers)
310 {
311
312 if (trigger.getType() != +etiss::fault::Trigger_Type::NOP) // don't care
313 {
314 iptr = trigger.getInjector();
315
316 if (iptr != nullptr)
317 {
318#ifdef NO_ETISS
319 std::cout << "etiss::fault::Stressor::removeFault: Removed trigger: " << trigger.toString()
320 << std::endl;
321#else
323 std::string("etiss::fault::Stressor::removeFault:") + std::string(" Removed trigger: "),
324 trigger);
325#endif
326 iptr->removeTrigger(trigger, f.id_);
327 }
328 else
329 {
330#ifdef NO_ETISS
331 std::cout << "etiss::fault::Stressor::removeFault: Error: Injector not found for: "
332 << trigger.toString() << std::endl;
333#else
335 std::string("etiss::fault::Stressor::removeFault:") +
336 std::string(" Injector not found for "),
337 trigger);
338#endif
340 }
341 }
342 else // Trigger is of type NOP
343 {
344 etiss::log(etiss::WARNING, std::string("etiss::fault::Stressor::removeFault:") +
345 std::string(" Trigger is a NOP and is does not need to be removed."));
346 }
347 }
348 faults().erase(find);
349
350 return true;
351}
352
353bool Stressor::firedTrigger(const Trigger &triggered, int32_t fault_id, Injector *injector, uint64_t time_ps)
354{
355 etiss::log(etiss::VERBOSE, std::string("etiss::fault::Stressor::firedTrigger() called. "));
356#if CXX0X_UP_SUPPORTED
357 std::lock_guard<std::mutex> lock(faults_sync());
358#endif
359 bool ret = true;
360 // find fault in fault-map
361 std::map<int32_t, Fault>::iterator find = faults().find(fault_id);
362 if (find != faults().end())
363 {
364 // iterate through the actions of the given fault
365 for (std::vector<etiss::fault::Action>::iterator iter = find->second.actions.begin();
366 iter != find->second.actions.end(); ++iter)
367 {
368 switch (iter->getType())
369 {
370 case +etiss::fault::Action_Type::INJECTION:
371 if (!iter->getFaultRef().is_set())
372 {
373 // try to resolve the reference again
374 if (!iter->getFaultRef().resolve_reference())
375 {
378 std::string(
379 "Stressor::firedTrigger: Injected Fault reference not found in fault definitions."),
380 iter->getFaultRef());
381 }
382 }
383 addFault(iter->getFaultRef().get_fault(), true);
384 break;
385 case +etiss::fault::Action_Type::EJECTION:
386 etiss::log(etiss::VERBOSE, std::string("Stressor::firedTrigger: Action is EJECTION"));
387 if (!iter->getFaultRef().is_set())
388 {
389 // try to resolve the reference again
390 if (!iter->getFaultRef().resolve_reference())
391 {
394 std::string(
395 "Stressor::firedTrigger: Injected Fault reference not found in fault definitions."),
396 iter->getFaultRef());
397 }
398 }
399 removeFault(iter->getFaultRef().get_fault(), true);
400 break;
401 case +etiss::fault::Action_Type::NOP:
403 std::string("Stressor::firedTrigger: Discarded - Action is NOP (do not care)."));
404 break;
405#ifndef NO_ETISS
406 case +etiss::fault::Action_Type::EVENT:
407 etiss::log(etiss::VERBOSE, std::string("Stressor::firedTrigger: Action is EVENT"));
408 set_event(iter->getEvent());
409 break;
410#endif
411 default: // on field actions
412 {
413 if (iter->getInjectorAddress().getInjector())
414 {
415#if CXX0X_UP_SUPPORTED
416 if (iter->getInjectorAddress().getInjector().get() != injector)
417#else
418 if (iter->getInjectorAddress().getInjector() != injector)
419#endif
420 {
421#ifndef NO_ETISS
423 std::string("etiss::fault::Stressor::firedTrigger: Action") +
424 std::string(" injector is not the injector that triggered this event.") +
425 std::string(" threadsafety must be ensured by user."),
426 find->second, *iter);
427#endif
428 }
429 std::string err;
430 bool ret_applyaction =
431 iter->getInjectorAddress().getInjector()->applyAction(find->second, *iter, err);
432 if (!ret_applyaction)
433 {
434#ifdef NO_ETISS
435 std::cout << "Stressor::firedTrigger: Failed to apply action. Fault: " << fault_id << " ["
436 << err << "]" << std::endl;
437#else
438 etiss::log(etiss::ERROR, std::string("Stressor::firedTrigger: Failed to apply action "),
439 find->second, *iter, err);
440#endif
441 }
442 ret = ret && ret_applyaction; // mask return value with ret_applyaction foreach(!) action, return
443 // false, if one fails
444 }
445 else
446 {
447#ifdef NO_ETISS
448 std::cout << "Stressor::firedTrigger: Failed to find action target. Fault: " << fault_id
449 << std::endl;
450#else
451 etiss::log(etiss::ERROR, std::string("Stressor::firedTrigger: Failed to find action target"),
452 find->second, *iter);
453#endif
454 }
455 }
456 }
457 }
458 }
459 else
460 {
461#ifdef NO_ETISS
462 std::cout << "Stressor::firedTrigger: Failed to find triggered Fault: " << fault_id << std::endl;
463#else
464 etiss::log(etiss::ERROR, std::string("Stressor::firedTrigger: Failed to find triggered Fault: "), fault_id);
465#endif
466 }
467
468 return ret;
469}
470
472{
473#if CXX0X_UP_SUPPORTED
474 std::lock_guard<std::mutex> lock(faults_sync());
475#endif
476 faults().clear();
477}
478
479} // namespace fault
480
481} // namespace etiss
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 a simple class that represents and resolves injector addresses as used by triggers (
contains the fault injector interface class.
general configuration and logging
contains the stressor class that loads and activates faults.
contains the Trigger class that defines conditions under which actions of a Fault need to be applied.
contains XML related functions.
static __inline__ uint64_t
Definition arm_cde.h:31
static __inline__ int32_t
Definition arm_mve.h:51
std::string toString() const
operator<< can be used.
Definition Fault.cpp:234
std::vector< Trigger > triggers
contains the triggers for this fault
Definition Fault.h:59
std::vector< Action > actions
contains the actions for this fault
Definition Fault.h:60
void removeTrigger(const Trigger &t, int32_t fault_id)
Definition Injector.cpp:205
virtual bool update_field_access_rights(const etiss::fault::Action &action, std::string &errormsg)=0
Update the field of injector with access rights to allow action (used to get type of action).
void addTrigger(const Trigger &t, int32_t fault_id)
TODO specialized lists. e.g. time triggers should be sorted and only the earliest time should be chec...
Definition Injector.cpp:184
static etiss::int32 event_code_
Definition Stressor.h:51
static bool loadXML(const std::string &file, const int coreID=0)
extracts faults out of the given xml file.
Definition Stressor.cpp:60
static bool removeFault(const Fault &f, bool injected_fault=false)
removes a fault's active triggers from their injectors, thus, deactivating the fault.
Definition Stressor.cpp:282
static bool addFault(const Fault &f, bool injected_fault=false)
activates a fault's triggers in their injectors
Definition Stressor.cpp:198
static bool addFaultDefinition(const Fault &f)
adds a fault to a static map that can be accessed by static std::map<int32_t,Fault> & faults().
Definition Stressor.cpp:167
static void clear()
clears the fault map.
Definition Stressor.cpp:471
static std::map< int32_t, Fault > & faults()
static map with all referencable faults.
Definition Stressor.cpp:48
static void set_event(etiss::int32 code)
Definition Stressor.h:55
static bool firedTrigger(const Trigger &firedTrigger, int32_t fault_id, Injector *injector, uint64_t time_ps)
Checks if the given trigger is valid and calls applyAction.
Definition Stressor.cpp:353
int coreIDActuallXML
Definition XML.cpp:25
bool parseXML(pugi::xml_document &doc, std::istream &input, std::ostream &diagnostics_out=std::cout)
parse a XML document held in input stream and return as doc
Definition XML.cpp:257
forwards: include/jit/*
Definition Benchmark.h:17
@ INFO
Definition Misc.h:87
@ VERBOSE
Definition Misc.h:88
@ WARNING
Definition Misc.h:86
@ ERROR
Definition Misc.h:85
void log(Verbosity level, std::string msg)
write log message at the given level.
Definition Misc.cpp:94