ETISS 0.8.0
Extendable Translating Instruction Set Simulator (version 0.8.0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Trigger.cpp
Go to the documentation of this file.
1/*
2
3 @copyright
4
5 <pre>
6
7 Copyright 2018 Infineon Technologies AG
8
9 This file is part of ETISS tool, see <https://github.com/tum-ei-eda/etiss>.
10
11 The initial version of this software has been created with the funding support by the German Federal
12 Ministry of Education and Research (BMBF) in the project EffektiV under grant 01IS13022.
13
14 Redistribution and use in source and binary forms, with or without modification, are permitted
15 provided that the following conditions are met:
16
17 1. Redistributions of source code must retain the above copyright notice, this list of conditions and
18 the following disclaimer.
19
20 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
21 and the following disclaimer in the documentation and/or other materials provided with the distribution.
22
23 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse
24 or promote products derived from this software without specific prior written permission.
25
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
27 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
28 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
29 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 POSSIBILITY OF SUCH DAMAGE.
34
35 </pre>
36
37 @author Chair of Electronic Design Automation, TUM
38
39 @version 0.1
40
41*/
42
43#ifndef NO_ETISS
44#include "etiss/fault/Trigger.h"
45#include "etiss/Misc.h"
47#else
48#include "fault/Injector.h"
49#include "fault/Trigger.h"
50#endif
51
52#include <iostream>
53
54namespace etiss
55{
56
57namespace fault
58{
59
60void Trigger::ensure(Type type) const
61{
62 if (type_ != type)
63 {
64 etiss::log(etiss::FATALERROR, std::string("etiss::fault::Trigger::ensure: Type mismatch type=") +
65 std::to_string(type) + " type_=" + std::to_string(type_));
66 throw "called function of different trigger type";
67 }
68}
69
70Trigger::Trigger() : type_(NOP)
71{
72 etiss::log(etiss::VERBOSE, std::string("etiss::fault::Trigger::Trigger() : type_ (NOP)"));
73}
75 : type_(META_COUNTER), sub_(new Trigger(sub)), param1_(count), param2_(0)
76{
77 etiss::log(etiss::VERBOSE, std::string("etiss::fault::Trigger::Trigger() : type_ (META_COUNTER)"));
78}
79Trigger::Trigger(const InjectorAddress &target_injector, const std::string &field, uint64_t value)
80 : type_(VARIABLEVALUE), field_(field), inj_(target_injector), fieldptr_(0), param1_(value)
81{
82 etiss::log(etiss::VERBOSE, std::string("etiss::fault::Trigger::Trigger() : type_ (VARIABLEVALUE)"));
83}
84Trigger::Trigger(const InjectorAddress &target_injector, uint64_t time_ps, bool relative)
85 : type_(relative ? TIMERELATIVE : TIME), inj_(target_injector), param1_(time_ps), param2_(0)
86{
87 relative ? etiss::log(etiss::VERBOSE, std::string("etiss::fault::Trigger::Trigger() : type_ (TIMERELATIVE)"))
88 : etiss::log(etiss::VERBOSE, std::string("etiss::fault::Trigger::Trigger() : type_ (TIME)"));
89}
90
91Trigger::Trigger(const Trigger &cpy) : type_(NOP)
92{
93 *this = cpy;
94}
96{
97 if (type_ == META_COUNTER)
98 delete sub_;
99 if (type_ == VARIABLEVALUE)
100 {
101 if (inj_.isResolved() && fieldptr_)
102 {
103 inj_.getInjector()->freeFastFieldAccessPtr(fieldptr_);
104 }
105 }
106 type_ = cpy.type_;
107 switch (type_)
108 {
109 case META_COUNTER:
110 sub_ = new Trigger(*cpy.sub_);
111 param1_ = cpy.param1_;
112 param2_ = cpy.param2_;
113 break;
114 case VARIABLEVALUE:
115 field_ = cpy.field_;
116 inj_ = cpy.inj_;
117 fieldptr_ = 0;
118 param1_ = cpy.param1_;
119 break;
120 case TIMERELATIVE: [[fallthrough]];
121 case TIME:
122 inj_ = cpy.inj_;
123 param1_ = cpy.param1_;
124 param2_ = cpy.param2_;
125 break;
126 case NOP:
127 break;
128 }
129 return *this;
130}
131
132#if CXX0X_UP_SUPPORTED
133Trigger::Trigger(Trigger &&cpy) : type_(NOP)
134{
135 operator=(cpy);
136}
137Trigger &Trigger::operator=(Trigger &&cpy)
138{
139 operator=((const Trigger &)cpy);
140 return *this;
141}
142#endif
143
145{
146 if (type_ == META_COUNTER)
147 delete sub_;
148 if (type_ == VARIABLEVALUE)
149 {
150 if (inj_.isResolved() && fieldptr_)
151 {
152 inj_.getInjector()->freeFastFieldAccessPtr(fieldptr_);
153 }
154 }
155}
156
157bool Trigger::fired(uint64_t time_ps, etiss::fault::Injector *target_injector)
158{
159 etiss::log(etiss::VERBOSE, std::string("etiss::fault::Trigger::fired(time_ps=") + std::to_string(time_ps) +
160 std::string(", Injector*)"));
161 // std::cout << "Trigger::fired called at " << time_ps << " ps" << std::endl;
162 switch (type_)
163 {
164 case META_COUNTER:
165 if (sub_->fired(time_ps, target_injector))
166 {
167 ++param2_; // increase count
168 if (param1_ == param2_)
169 {
170 return true; // count reached -> fire event
171 }
172 }
173 break;
174 case VARIABLEVALUE:
175 {
176 if (fieldptr_ == 0)
177 {
178 std::string errmsg;
179 fieldptr_ = target_injector->fastFieldAccessPtr(field_, errmsg);
180 if (fieldptr_ == 0)
181 {
182#ifdef NO_ETISS
183 std::cout << "Trigger::fired: Failed to get field" << std::endl;
184#else
185 etiss::log(etiss::ERROR, "Trigger::fired: Failed to get field", *this);
186#endif
187 return false;
188 }
189 }
190 uint64_t val = 0;
191 std::string errmsg;
192 if (inj_.getInjector())
193 {
194 if (!inj_.getInjector()->readField(fieldptr_, val, errmsg))
195 {
196#ifdef NO_ETISS
197 std::cout << "Trigger::fired: Failed to read field: " << errmsg << std::endl;
198#else
199 etiss::log(etiss::ERROR, "Trigger::fired: Failed to get field", *this, errmsg);
200#endif
201 return false;
202 }
203 }
204 else
205 {
206#ifdef NO_ETISS
207 std::cout << "Trigger::fired: Failed get injector: " << inj_.getInjectorPath() << std::endl;
208#else
209 etiss::log(etiss::ERROR, "Trigger::fired: Failed get injector", *this, inj_);
210#endif
211 }
212 return val == param1_;
213 }
214 break;
215 case TIMERELATIVE:
216 etiss::log(etiss::WARNING, "Trigger::fired: Unresolved TIMERELATIVE - resolving now", *this, inj_);
217 resolveTime(time_ps);
218 [[fallthrough]];
219 case TIME:
220 /* TODO: Why doing it like this ? this would always fire after time_ps has reached */
221 // Possibly because might be called not exaclty but later than excact trigger time, then late triggering should
222 // be done
223
224 // if (time_ps >= param1_ && param2_ <= time_ps)
225 if (param1_ <= time_ps && param2_ == 0) // testing alternative param2_ says if trigger has already fired
226 {
228
229 // param2_ = time_ps+1;
230 param2_ = 1; // testing alternative: param2_ says if trigger has already fired
231 return true;
232 }
233 // param2_ = time_ps;
234 // testing alternative param2_ says if trigger has already fired
235
236 // DO NOT DO IT LIKE THIS, MIGHT NOT BE CALLED EXACTLY WITH TIME OF TRIGGER
237 // if (time_ps == param1_)
238 // return true;
239 break;
240 case NOP:
241 break;
242 }
243
244 return false;
245}
246
248{
250 std::string("etiss::fault::Trigger::resolveTime(time=") + std::to_string(time) + std::string(")"));
251 if (type_ == TIMERELATIVE)
252 {
253 type_ = TIME;
254 param1_ = param1_ + time;
255 }
256 else if (type_ == META_COUNTER)
257 {
258 return getSubTrigger().resolveTime(time);
259 }
260}
262{
263 if (type_ == META_COUNTER)
264 {
265 return getSubTrigger().isResolved();
266 }
267 return type_ != TIMERELATIVE;
268}
269
271{
273 return param1_;
274}
276{
278 return *sub_;
279}
281{
283 return *sub_;
284}
286{
287 if (type_ == META_COUNTER)
288 {
289 return getSubTrigger().getTriggerTime();
290 }
291 try
292 {
293 ensure(TIME);
294 }
295 catch (char const *)
296 {
298 }
299 return param1_;
300}
302{
303 return inj_;
304}
306{
307 if (type_ == META_COUNTER)
308 {
309 return sub_->getInjector();
310 }
311 else
312 {
313 return inj_.getInjector();
314 }
315}
316bool Trigger::isNOP() const
317{
318 if (type_ == META_COUNTER)
319 {
320 return sub_->isNOP();
321 }
322 else
323 {
324 return type_ == NOP;
325 }
326}
327const std::string &Trigger::getTriggerField() const
328{
329 // std::cout << "Trigger::getTriggerField() called" << std::endl;
330 if (type_ == META_COUNTER)
331 {
333 }
335 return field_;
336}
338{
339 // std::cout << "Trigger::getTriggerFieldValue() called" << std::endl;
340 if (type_ == META_COUNTER)
341 {
343 }
345 return param1_;
346}
348{
349 return type_;
350}
351
352std::string Trigger::toString() const
353{
354 std::stringstream ss;
355 ss << "Trigger {";
356 switch (type_)
357 {
358 case META_COUNTER:
359 ss << " type=META_COUNTER triggerCount=" << +param1_ << " currentCount=" << +param2_;
360 break;
361 case VARIABLEVALUE:
362 ss << " type=VARIABLEVALUE field=" << field_ << " triggerValue=" << +param1_;
363 break;
364 case TIME:
365 ss << " type=TIME triggerTime=" << +param1_;
366 break;
367 case TIMERELATIVE:
368 ss << " type=TIMERELATIVE triggerTime=" << +param1_;
369 break;
370 case NOP:
371 ss << " type=NOP";
372 break;
373 }
374 ss << "}";
375 return ss.str();
376}
377
378#if ETISS_FAULT_XML
379namespace xml
380{
381template <>
382bool parse<etiss::fault::Trigger *>(pugi::xml_node node, etiss::fault::Trigger *&f, Diagnostics &diag)
383{
384 etiss::log(etiss::VERBOSE, std::string("Called etiss::fault::xml::parse<etiss::fault::Trigger*>") +
385 std::string("(node, Trigger*&, Diagnostics)"));
386 f = 0;
387 std::string type;
388 if (!parse_attr(node, "type", type, diag))
389 {
390 return false;
391 }
392
393 if (type == "META_COUNTER")
394 {
395 uint64_t count;
396 if (!parse<uint64_t>(findSingleNode(node, "count", diag), count, diag))
397 {
398 return false;
399 }
400 etiss::fault::Trigger *sub = 0;
401 if ((!parse<etiss::fault::Trigger *>(findSingleNode(node, "trigger", diag), sub, diag)) || (sub == 0))
402 {
403 diag.unexpectedNode(node, "Failed to parse sub trigger");
404 return false;
405 }
406 f = new etiss::fault::Trigger(*sub, count);
407 delete sub;
408 return true;
409 }
410
411 if (type == "VARIABLEVALUE")
412 {
413 uint64_t value;
414 if (!parse_hex(findSingleNode(node, "value", diag), value, diag))
415 {
416 return false;
417 }
418 std::string field;
419 if (!parse<std::string>(findSingleNode(node, "field", diag), field, diag))
420 {
421 return false;
422 }
423 setCoreName(field);
425 if (!parse<etiss::fault::InjectorAddress>(findSingleNode(node, "injector", diag), injector, diag))
426 {
427 return false;
428 }
429 f = new Trigger(injector, field, value);
430 return true;
431 }
432
433 if (type == "TIME")
434 {
435 uint64_t count;
436 if (!parse<uint64_t>(findSingleNode(node, "time_ps", diag), count, diag))
437 {
438 return false;
440 }
442 if (!parse<etiss::fault::InjectorAddress>(findSingleNode(node, "injector", diag), injector, diag))
443 {
444 return false;
445 }
446 f = new Trigger(injector, count);
447 return true;
448 }
449
450 if (type == "TIMERELATIVE")
451 {
452 uint64_t count;
453 if (!parse<uint64_t>(findSingleNode(node, "time_ps", diag), count, diag))
454 {
455 return false;
457 }
459 if (!parse<etiss::fault::InjectorAddress>(findSingleNode(node, "injector", diag), injector, diag))
460 {
461 return false;
462 }
463 f = new Trigger(injector, count, true);
464 std::cout << "Injector2: " << f->getInjectorAddress().getInjectorPath() << std::endl;
465 return true;
466 }
467
468 return false;
469}
470template <>
471bool write<const etiss::fault::Trigger *>(pugi::xml_node node, const etiss::fault::Trigger *const &f, Diagnostics &diag)
472{
473 etiss::log(etiss::VERBOSE, std::string("Called etiss::fault::xml::write<etiss::fault::Trigger*>") +
474 std::string("(node, Trigger*&, Diagnostics)"));
475 if (f == 0)
476 return false;
477 return write<etiss::fault::Trigger>(node, *f, diag);
478}
479
480template <>
481bool parse<etiss::fault::Trigger>(pugi::xml_node node, etiss::fault::Trigger &f, Diagnostics &diag)
482{
483 etiss::log(etiss::VERBOSE, std::string("Called etiss::fault::xml::parse<etiss::fault::Trigger>") +
484 std::string("(node, Trigger&, Diagnostics)"));
486 if (!parse<etiss::fault::Trigger *>(node, t, diag))
487 return false;
488 f = *t;
489 delete t;
490 return true;
491}
492template <>
493bool write<etiss::fault::Trigger>(pugi::xml_node node, const etiss::fault::Trigger &f, Diagnostics &diag)
494{
495 etiss::log(etiss::VERBOSE, std::string("Called etiss::fault::xml::write<etiss::fault::Trigger>") +
496 std::string("(node, Trigger&, Diagnostics)"));
497 // std::cout << "write<etiss::fault::Trigger> called " << std::endl;
498 switch (f.getType())
499 {
501 {
502 write_attr<std::string>(node, "type", "META_COUNTER", diag);
503 write<uint64_t>(node.append_child("count"), f.getTriggerCount(), diag);
504 write<etiss::fault::Trigger>(node.append_child("trigger"), f.getSubTrigger(), diag);
505 }
506 return true;
508 {
509 write_attr<std::string>(node, "type", "VARIABLEVALUE", diag);
510 write<std::string>(node.append_child("field"), f.getTriggerField(), diag);
511 write<uint64_t>(node.append_child("count"), f.getTriggerFieldValue(), diag);
512 Injector_ptr ptr = f.getInjector();
513 if (!ptr)
514 {
515 diag.errors.push_back("A fault trigger has no target_injector. failed to "
516 "get path of trigger");
517 return false;
518 }
519 write<std::string>(node.append_child("injector"), ptr->getInjectorPath(), diag);
520 }
521 return true;
524 {
525 write_attr<std::string>(node, "type",
526 (f.getType() == etiss::fault::Trigger::TIMERELATIVE) ? "TIMERELATIVE" : "TIME", diag);
527 write<uint64_t>(node.append_child("time_ps"), f.getTriggerTime(), diag);
528 Injector_ptr ptr = f.getInjector();
529 if (!ptr)
530 {
531 diag.errors.push_back("A fault trigger has no target_injector. failed to "
532 "get path of trigger");
533 return false;
534 }
535 write<std::string>(node.append_child("injector"), ptr->getInjectorPath(), diag);
536 }
537 return true;
539 {
540 write_attr<std::string>(node, "type", "NOP", diag);
541 }
542 return true;
543 }
544
545 diag.errors.push_back("etiss::fault::xml::write<etiss::fault::Trigger> "
546 "encountered an unknown type of trigger");
547
548 return false;
549}
550
551} // namespace xml
552#endif
553
554} // namespace fault
555
556} // namespace etiss
contains the fault injector interface class.
general configuration and logging
contains the Trigger class that defines conditions under which actions of a Fault need to be applied.
static __inline__ uint64_t
Definition arm_cde.h:31
const std::string & getInjectorPath() const
bool isResolved() const
> Calls Injector::get (implemented in VirtualStruct) to resolve path_ and get iptr_
const Injector_ptr & getInjector() const
virtual void * fastFieldAccessPtr(const std::string &name, std::string &errormsg)=0
std::string toString() const
operator<< can be used.
Definition Trigger.cpp:352
const std::string & getTriggerField() const
Definition Trigger.cpp:327
void ensure(Type type) const
Definition Trigger.cpp:60
Trigger & getSubTrigger()
Definition Trigger.cpp:275
const uint64_t & getTriggerFieldValue() const
Definition Trigger.cpp:337
uint64_t getTriggerCount() const
Definition Trigger.cpp:270
const Injector_ptr & getInjector() const
Definition Trigger.cpp:305
Type getType() const
Definition Trigger.cpp:347
bool fired(uint64_t time_ps, etiss::fault::Injector *target_injector)
this function checks if the Trigger has just fired.
Definition Trigger.cpp:157
InjectorAddress inj_
Definition Trigger.h:166
const InjectorAddress & getInjectorAddress() const
Definition Trigger.cpp:301
Trigger()
Type: NOP (no operation)
Definition Trigger.cpp:70
std::string field_
Definition Trigger.h:164
Trigger & operator=(const Trigger &cpy)
Definition Trigger.cpp:95
bool isNOP() const
Definition Trigger.cpp:316
uint64_t getTriggerTime() const
Definition Trigger.cpp:285
bool isResolved() const
returns if the translation from TIMERELATIVE to TIME trigger has taken place
Definition Trigger.cpp:261
void resolveTime(uint64_t time)
this function calculates in case of a TIMERELATIVE Trigger a constant TIME trigger
Definition Trigger.cpp:247
@ TIMERELATIVE
needs to be resolved.
Definition Trigger.h:94
xml_node append_child(xml_node_type type=node_element)
Definition pugixml.cpp:4983
void setCoreName(std::string &str)
Definition XML.cpp:62
std::shared_ptr< Injector > Injector_ptr
Definition Defs.h:86
Page Table Entry (PTE) defines the composition of Page Frame Number (PFN) and relavant flags.
Definition Benchmark.h:53
@ VERBOSE
Definition Misc.h:130
@ WARNING
Definition Misc.h:128
@ ERROR
Definition Misc.h:127
@ FATALERROR
Definition Misc.h:126
void log(Verbosity level, std::string msg)
write log message at the given level.
Definition Misc.cpp:125