ETISS 0.11.2
ExtendableTranslatingInstructionSetSimulator(version0.11.2)
Loading...
Searching...
No Matches
Action.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"
10#include "etiss/fault/Trigger.h"
11#include "etiss/fault/Fault.h"
13#include "etiss/jit/ReturnCode.h"
14#else
15#include "fault/XML.h"
16#include "fault/Action.h"
17#include "fault/Trigger.h"
18#include "fault/Fault.h"
20#endif
21
22#include <sstream>
23
24namespace etiss
25{
26namespace fault
27{
28
30{
31 if (type_ != t)
32 throw "wrong action type";
33}
34
36{
37 return ((type_ == +type_t::BITFLIP || type_ == +type_t::MASK) ? true : false);
38}
39
40Action::Action() : type_(type_t::NOP)
41{
42 etiss::log(etiss::VERBOSE, std::string("etiss::fault::Action::Action() called. "));
43}
44
45#ifndef NO_ETISS
46Action::Action(int32_t event) : type_(type_t::EVENT), event_(event)
47{
48 etiss::log(etiss::VERBOSE, std::string("etiss::fault::Action::Action(int32_t exception) called. "));
49}
50#endif
51
52Action::Action(const InjectorAddress &inj, const std::string &command)
53 : type_(type_t::COMMAND), inj_(std::make_unique<InjectorAddress>(inj)), command_(command)
54{
55 etiss::log(etiss::VERBOSE, std::string("etiss::fault::Action::Action(InjectorAddress &=") + inj.getInjectorPath() +
56 std::string(", command=") + command + std::string(") called. "));
57}
58
59Action::Action(const InjectorAddress &inj, const std::string &field, unsigned bit)
60 : type_(type_t::BITFLIP), inj_(std::make_unique<InjectorAddress>(inj)), field_(field), bit_(bit)
61{
62 etiss::log(etiss::VERBOSE, std::string("etiss::fault::Action::Action(InjectorAddress &=") + inj.getInjectorPath() +
63 std::string(", field=") + field + std::string(", bit=") + std::to_string(bit) +
64 std::string(") called. "));
65}
66
67Action::Action(const InjectorAddress &inj, const std::string &field, mask_op_t mask_op, uint64_t mask_value)
68 : type_(type_t::MASK)
69 , inj_(std::make_unique<InjectorAddress>(inj))
70 , field_(field)
71 , mask_op_(mask_op)
72 , mask_value_(mask_value)
73{
74 etiss::log(etiss::VERBOSE, std::string("etiss::fault::Action::Action(InjectorAddress &=") + inj.getInjectorPath() +
75 std::string(", field=") + field + std::string(", mask_op=") + mask_op_._to_string() +
76 std::string(", mask_value=") + std::to_string(mask_value) +
77 std::string(") called. "));
78}
79
80Action::Action(const FaultRef &fault_ref, type_t type) : type_(type), fault_ref_(std::make_unique<FaultRef>(fault_ref))
81{
82 etiss::log(etiss::VERBOSE, std::string("etiss::fault::Action::Action(FaultRef &=") + fault_ref.toString() +
83 std::string(") called. "));
84}
85
86Action::Action(const Action &cpy) : type_(cpy.getType())
87{
88 *this = cpy;
89}
90
92{
93 type_ = cpy.type_;
94 switch (type_)
95 {
96 case type_t::BITFLIP:
97 inj_ = std::make_unique<InjectorAddress>(cpy.getInjectorAddress());
98 field_ = cpy.getTargetField();
99 bit_ = cpy.getTargetBit();
100 break;
101 case type_t::MASK:
102 inj_ = std::make_unique<InjectorAddress>(cpy.getInjectorAddress());
103 field_ = cpy.getTargetField();
104 mask_op_ = cpy.getMaskOp();
106 break;
107 case type_t::COMMAND:
108 inj_ = std::make_unique<InjectorAddress>(cpy.getInjectorAddress());
109 command_ = cpy.getCommand();
110 break;
111 case type_t::EJECTION:
112 [[fallthrough]];
113 case type_t::INJECTION:
114 fault_ref_ = std::make_unique<FaultRef>(cpy.getFaultRef());
115 break;
116#ifndef NO_ETISS
117 case type_t::EVENT:
118 event_ = cpy.getEvent();
119 break;
120#endif
121 case type_t::NOP:
122 break;
123 }
124 return *this;
125}
126
127#if CXX0X_UP_SUPPORTED
128Action::Action(Action &&cpy) : type_(cpy.getType())
129{
130 operator=(cpy);
131}
132Action &Action::operator=(Action &&cpy)
133{
134 operator=((const Action &)cpy);
135 return *this;
136}
137#endif
138
140{
141 return type_;
142}
143
145{
146 if (!(type_ == +type_t::BITFLIP || type_ == +type_t::MASK || type_ == +type_t::COMMAND))
149 std::string(
150 "etiss::fault::Action::TypeStruct::getInjectorAddress(): Requested Action::Type is not Injector"));
151 return *inj_;
152}
153
155const std::string &Action::getCommand() const
156{
157 if (type_ != +type_t::COMMAND)
159 std::string("etiss::fault::Action::getCommand(): Requested Action::Type is not Command"));
160 return command_;
161}
162
164const std::string &Action::getTargetField() const
165{
166 if (!(type_ == +type_t::BITFLIP || type_ == +type_t::MASK))
168 std::string("etiss::fault::Action::getTargetField(): Requested Action::Type is not TargetField"));
169 return field_;
170}
171
173unsigned Action::getTargetBit() const
174{
175 if (type_ != +type_t::BITFLIP)
177 std::string("etiss::fault::Action::getTargetBit(): Requested Action::Type is not TargetBit"));
178 return bit_;
179}
180
182{
183 if (!((type_ == +type_t::INJECTION) || (type_ == +type_t::EJECTION)))
185 std::string("etiss::fault::Action::getFault(): Requested Action::Type is not injectable Fault"));
186 return *fault_ref_;
187}
188
190{
191 if (type_ != +type_t::MASK)
193 std::string("etiss::fault::Action::getMaskOp(): Requested Action::Type is not Mask"));
194 return mask_op_;
195}
196
198{
199 if (type_ != +type_t::MASK)
201 std::string("etiss::fault::Action::getMaskValue(): Requested Action::Type is not Mask"));
202 return mask_value_;
203}
204
205#ifndef NO_ETISS
207{
208 if (type_ != +type_t::EVENT)
210 std::string("etiss::fault::Action::getEvent(): Requested Action::Type is not Event"));
211 return event_;
212}
213#endif
214
215std::string Action::toString() const
216{
217 pugi::xml_document doc;
218 doc.load_string("<?xml version=\"1.0\"?>");
219
220 xml::Diagnostics diag;
221
222 xml::write<etiss::fault::Action>(doc.append_child("action"), *this, diag);
223
224 std::stringstream ss;
225
226 doc.save(ss);
227
228 return ss.str();
229}
230
231#if ETISS_FAULT_XML
232namespace xml
233{
234template <>
235bool parse<Action>(pugi::xml_node node, Action &f, Diagnostics &diag)
236{
237 etiss::log(etiss::VERBOSE, std::string("etiss::fault::parse<etiss::fault::Action>(node, Action") +
238 std::string(", Diagnostics) called. "));
239
240 std::string type_s;
241 if (!parse_attr(node, "type", type_s, diag))
242 {
243 diag.unexpectedNode(node, "Failed to parse type of action");
244 return false;
245 }
246 if (!Action::type_t::_from_string_nothrow(type_s.c_str()))
247 {
248 diag.unexpectedNode(node, std::string("There is no Action type ") + type_s);
249 return false;
250 }
251 auto type = Action::type_t::_from_string(type_s.c_str());
252
253 switch (type)
254 {
255 case Action::type_t::NOP:
256 {
257 f = Action();
258 return true;
259 break;
260 }
261 case Action::type_t::BITFLIP:
262 {
263 InjectorAddress inj;
264 if (!etiss::cfg().get<bool>("faultInjection::allowBitFlip", true))
265 return true;
266 if (!parse<InjectorAddress>(findSingleNode(node, "injector", diag), inj, diag))
267 {
268 diag.unexpectedNode(node, "Failed to parse target <injector>");
269 return false;
270 }
271 std::string field;
272 if (!parse<std::string>(findSingleNode(node, "field", diag), field, diag))
273 {
274 diag.unexpectedNode(node, "Failed to parse target <field>");
275 return false;
276 }
277 setCoreName(field);
278 unsigned bit;
279 if (!parse<unsigned>(findSingleNode(node, "bit", diag), bit, diag))
280 {
281 diag.unexpectedNode(node, "Failed to parse target <bit>");
282 return false;
283 }
284 f = Action(inj, field, bit);
285 return true;
286 break;
287 }
288 case Action::type_t::COMMAND:
289 {
290 InjectorAddress inj;
291 if (!parse<InjectorAddress>(findSingleNode(node, "injector", diag), inj, diag))
292 {
293 diag.unexpectedNode(node, "Failed to parse target <injector>");
294 return false;
295 }
296 std::string command;
297 if (!parse<std::string>(findSingleNode(node, "command", diag), command, diag))
298 {
299 diag.unexpectedNode(node, "Failed to parse target <command>");
300 return false;
301 }
302 f = Action(inj, command);
303 return true;
304 break;
305 }
306 case Action::type_t::INJECTION:
307 [[fallthrough]];
308 case Action::type_t::EJECTION:
309 {
310 FaultRef fault_ref;
311 if (!parse<FaultRef>(findSingleNode(node, "fault_ref", diag), fault_ref, diag))
312 {
313 diag.unexpectedNode(node, "Failed to parse <fault_ref> to inject");
314 return false;
315 }
316 f = Action(fault_ref, type);
317 return true;
318 break;
319 }
320 case Action::type_t::MASK:
321 {
322 InjectorAddress inj;
323 if (!parse<InjectorAddress>(findSingleNode(node, "injector", diag), inj, diag))
324 {
325 diag.unexpectedNode(node, "Failed to parse target <injector>");
326 return false;
327 }
328 std::string field;
329 if (!parse<std::string>(findSingleNode(node, "field", diag), field, diag))
330 {
331 diag.unexpectedNode(node, "Failed to parse target <field>");
332 return false;
333 }
334 setCoreName(field);
335 std::string op_str;
336 if (!parse<std::string>(findSingleNode(node, "op", diag), op_str, diag))
337 {
338 diag.unexpectedNode(node, "Failed to parse mask operation <op>");
339 return false;
340 }
341
342 if (!(etiss::fault::Action::mask_op_t::_from_string_nothrow(op_str.c_str())))
343 {
344 diag.unexpectedNode(node, "Failed to parse mask operation <op>");
345 return false;
346 }
347 uint64_t value;
348 if (!parse_hex(findSingleNode(node, "value", diag), value, diag))
349 {
350 diag.unexpectedNode(node, "Failed to parse mask operation <value>");
351 return false;
352 }
353 f = Action(inj, field, Action::mask_op_t::_from_string(op_str.c_str()), value);
354 return true;
355 break;
356 }
357#ifndef NO_ETISS
358 case Action::type_t::EVENT:
359 {
360 std::string event_str;
361 int32_t event;
362 if (!parse<std::string>(findSingleNode(node, "cause", diag), event_str, diag))
363 {
364 diag.unexpectedNode(node, "Failed to parse node of event type: <cause>");
365 return false;
366 }
367 if (!etiss::fault::returncode_fromstring(event, event_str))
368 {
369 diag.unexpectedNode(node, "Failed to parse event <cause>. Supported values: {NOERROR, RELOADBLOCKS, "
370 "RELOADCURRENTBLOCK, CPUFINISHED, EXCEPTION:[cause(hex)]}");
371 return false;
372 }
373 f = Action(event);
374 return true;
375 }
376#endif
377 default:
378 diag.unexpectedNode(node, std::string("Unknown type of action: ") + type._to_string());
379 return false;
380 break;
381 }
382 return false;
383}
384template <>
385bool write<Action>(pugi::xml_node node, const Action &f, Diagnostics &diag)
386{
387 etiss::log(etiss::VERBOSE, std::string("etiss::fault::write<etiss::fault::Action>(node, Action&=") +
388 std::string(", Diagnostics) called. "));
389 bool ok = true;
390 switch (f.getType())
391 {
392 case Action::type_t::NOP:
393 return write_attr<std::string>(node, "type", "NOP", diag);
394 break;
395 case Action::type_t::BITFLIP:
396 ok = ok & write_attr<std::string>(node, "type", "BITFLIP", diag);
397 ok = ok & write(node.append_child("injector"), f.getInjectorAddress(), diag);
398 ok = ok & write<std::string>(node.append_child("field"), f.getTargetField(), diag);
399 ok = ok & write<unsigned>(node.append_child("bit"), f.getTargetBit(), diag);
400 break;
401 case Action::type_t::COMMAND:
402 ok = ok & write_attr<std::string>(node, "type", "COMMAND", diag);
403 ok = ok & write<std::string>(node.append_child("command"), f.getCommand(), diag);
404 break;
405 case Action::type_t::INJECTION:
406 ok = ok & write_attr<std::string>(node, "type", "INJECTION", diag);
407 ok = ok & write<FaultRef>(node.append_child("fault_ref"), f.getFaultRef(), diag);
408 break;
409 case Action::type_t::EJECTION:
410 ok = ok & write_attr<std::string>(node, "type", "EJECTION", diag);
411 ok = ok & write<FaultRef>(node.append_child("fault_ref"), f.getFaultRef(), diag);
412 break;
413 case Action::type_t::MASK:
414 ok = ok & write_attr<std::string>(node, "type", "MASK", diag);
415 ok = ok & write(node.append_child("injector"), f.getInjectorAddress(), diag);
416 ok = ok & write<std::string>(node.append_child("field"), f.getTargetField(), diag);
417 ok = ok & write<std::string>(node.append_child("op"), f.getMaskOp()._to_string(), diag);
418 ok = ok & write<uint64_t>(node.append_child("value"), f.getMaskValue(), diag);
419 break;
420#ifndef NO_ETISS
421 case Action::type_t::EVENT:
422 ok = ok & write_attr<std::string>(node, "type", "EVENT", diag);
423 ok = ok & write<std::string>(node.append_child("cause"), etiss::fault::returncode_tostring(f.getEvent()), diag);
424 break;
425#endif
426 }
427 if (!ok)
428 etiss::log(etiss::ERROR, std::string("etiss::fault::write<etiss::fault::Action>(node, Action&=") +
429 std::string(", Diagnostics) failed. "));
430 return ok;
431}
432
433} // namespace xml
434#endif
435
436#ifndef NO_ETISS
437bool returncode_fromstring(int32_t &out, const std::string &in)
438{
439 if ((in == "NOERROR") || (in == "RETURNCODE::NOERROR"))
440 {
441 out = etiss::RETURNCODE::NOERROR;
442 }
443 else if ((in == "RELOADBLOCKS") || (in == "RETURNCODE::RELOADBLOCKS"))
444 {
445 out = etiss::RETURNCODE::RELOADBLOCKS;
446 }
447 else if ((in == "RELOADCURRENTBLOCK") || (in == "RETURNCODE::RELOADCURRENTBLOCK"))
448 {
449 out = etiss::RETURNCODE::RELOADCURRENTBLOCK;
450 }
451 else if ((in == "CPUFINISHED") || (in == "RETURNCODE::CPUFINISHED"))
452 {
453 out = etiss::RETURNCODE::CPUFINISHED;
454 }
455 else if ((in == "DBUS_WRITE_ERROR") || (in == "RETURNCODE::DBUS_WRITE_ERROR"))
456 {
457 out = etiss::RETURNCODE::DBUS_WRITE_ERROR;
458 }
459 else if ((in == "IBUS_READ_ERROR") || (in == "RETURNCODE::IBUS_READ_ERROR"))
460 {
461 out = etiss::RETURNCODE::IBUS_READ_ERROR;
462 }
463 else if ((in == "IBUS_WRITE_ERROR") || (in == "RETURNCODE::IBUS_WRITE_ERROR"))
464 {
465 out = etiss::RETURNCODE::IBUS_WRITE_ERROR;
466 }
467 else if ((in == "INTERRUPT") || (in == "RETURNCODE::INTERRUPT"))
468 {
469 out = etiss::RETURNCODE::INTERRUPT;
470 }
471 else if ((in == "RESET") || (in == "RETURNCODE::RESET"))
472 {
473 out = etiss::RETURNCODE::RESET;
474 }
475 else if ((in == "ILLEGALINSTRUCTION") || (in == "RETURNCODE::ILLEGALINSTRUCTION"))
476 {
477 out = etiss::RETURNCODE::ILLEGALINSTRUCTION;
478 }
479 else if ((in == "ILLEGALJUMP") || (in == "RETURNCODE::ILLEGALJUMP"))
480 {
481 out = etiss::RETURNCODE::ILLEGALJUMP;
482 }
483 else if ((in == "INSTR_PAGEFAULT") || in == ("RETURNCODE::INSTR_PAGEFAULT"))
484 {
485 out = etiss::RETURNCODE::INSTR_PAGEFAULT;
486 }
487 else if ((in == "LOAD_PAGEFAULT") || (in == "RETURNCODE::LOAD_PAGEFAULT"))
488 {
489 out = etiss::RETURNCODE::LOAD_PAGEFAULT;
490 }
491 else if ((in == "STORE_PAGEFAULT") || (in == "RETURNCODE::STORE_PAGEFAULT"))
492 {
493 out = etiss::RETURNCODE::STORE_PAGEFAULT;
494 }
495 else if ((in == "SYSCALL") || (in == "RETURNCODE::SYSCALL"))
496 {
497 out = etiss::RETURNCODE::SYSCALL;
498 }
499 else if ((in == "PAGEFAULT") || (in == "RETURNCODE::PAGEFAULT"))
500 {
501 out = etiss::RETURNCODE::PAGEFAULT;
502 }
503 else if ((in == "BREAKPOINT") || (in == "RETURNCODE::BREAKPOINT"))
504 {
505 out = etiss::RETURNCODE::BREAKPOINT;
506 }
507 else
508 {
509 return false;
510 }
511 return true;
512}
513
515{
516 switch (in)
517 {
518 case etiss::RETURNCODE::NOERROR:
519 return "NOERROR";
520 case etiss::RETURNCODE::RELOADBLOCKS:
521 return "RELOADBLOCKS";
522 case etiss::RETURNCODE::RELOADCURRENTBLOCK:
523 return "RELOADCURRENTBLOCK";
524 case etiss::RETURNCODE::INTERRUPT:
525 return "INTERRUPT";
526 case etiss::RETURNCODE::DBUS_WRITE_ERROR:
527 return "DBUS_WRITE_ERROR";
528 case etiss::RETURNCODE::IBUS_READ_ERROR:
529 return "IBUS_READ_ERROR";
530 case etiss::RETURNCODE::IBUS_WRITE_ERROR:
531 return "IBUS_WRITE_ERROR";
532 case etiss::RETURNCODE::RESET:
533 return "RESET";
534 case etiss::RETURNCODE::ILLEGALINSTRUCTION:
535 return "ILLEGALINSTRUCTION";
536 case etiss::RETURNCODE::ILLEGALJUMP:
537 return "ILLEGALJUMP";
538 case etiss::RETURNCODE::INSTR_PAGEFAULT:
539 return "INSTR_PAGEFAULT";
540 case etiss::RETURNCODE::LOAD_PAGEFAULT:
541 return "LOAD_PAGEFAULT";
542 case etiss::RETURNCODE::STORE_PAGEFAULT:
543 return "STORE_PAGEFAULT";
544 case etiss::RETURNCODE::SYSCALL:
545 return "SYSCALL";
546 case etiss::RETURNCODE::PAGEFAULT:
547 return "PAGEFAULT";
548 case etiss::RETURNCODE::BREAKPOINT:
549 return "BREAKPOINT";
550 case etiss::RETURNCODE::CPUFINISHED:
551 return "CPUFINISHED";
552 default:
553 std::stringstream ss;
554 ss << "EXCEPTION:" << std::hex << in;
555 return ss.str();
556 }
557}
558
559#endif
560
561} // namespace fault
562
563} // 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 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
const mask_op_t & getMaskOp() const
MASK only.
Definition Action.cpp:189
const InjectorAddress & getInjectorAddress() const
Definition Action.cpp:144
void ensure(type_t)
Definition Action.cpp:29
bool is_action_on_field(void) const
returns true if type_ is an action on a Field
Definition Action.cpp:35
unsigned bit_
concerning Bit (for fault injection)
Definition Action.h:131
std::string toString() const
operator<< can be used.
Definition Action.cpp:215
const FaultRef & getFaultRef() const
INJECTION and EJECTION only.
Definition Action.cpp:181
uint64_t getMaskValue() const
Definition Action.cpp:197
std::string command_
command e.g. for booting OR1KVCPU
Definition Action.h:129
std::unique_ptr< InjectorAddress > inj_
Address of Injector.
Definition Action.h:128
std::unique_ptr< FaultRef > fault_ref_
for fault injection
Definition Action.h:134
const std::string & getCommand() const
COMMAND only.
Definition Action.cpp:155
const std::string & getTargetField() const
BITFLIP only.
Definition Action.cpp:164
Action_MaskOp mask_op_t
Definition Action.h:49
std::string field_
concerning Field (for fault injection)
Definition Action.h:130
mask_op_t mask_op_
mask operation (for mask injection)
Definition Action.h:132
int32_t event_
exception, or rather etiss::RETURNCODE to to be injected into the simulation loop
Definition Action.h:136
const type_t & getType() const
Definition Action.cpp:139
int32_t getEvent() const
Definition Action.cpp:206
uint64_t mask_value_
mask value (for mask injection)
Definition Action.h:133
Action_Type type_t
Definition Action.h:48
Action & operator=(const Action &cpy)
Definition Action.cpp:91
unsigned getTargetBit() const
BITFLIP only.
Definition Action.cpp:173
type_t type_
type of the Attribute
Definition Action.h:127
std::string toString() const
operator<< can be used.
Definition Fault.cpp:269
const std::string & getInjectorPath() const
void setCoreName(std::string &str)
Definition XML.cpp:26
bool returncode_fromstring(int32_t &out, const std::string &in)
decode etiss::RETURNCODE from string
Definition Action.cpp:437
std::string returncode_tostring(int32_t in)
encode etiss::RETURNCODE to string
Definition Action.cpp:514
forwards: include/jit/*
Definition Benchmark.h:17
@ VERBOSE
Definition Misc.h:88
@ ERROR
Definition Misc.h:85
@ FATALERROR
Definition Misc.h:84
Configuration & cfg()
Definition Misc.cpp:548
void log(Verbosity level, std::string msg)
write log message at the given level.
Definition Misc.cpp:94
STL namespace.