ETISS 0.8.0
Extendable Translating Instruction Set Simulator (version 0.8.0)
Fault.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/Fault.h"
45 #include "etiss/fault/Trigger.h"
46 #include "etiss/fault/Injector.h"
48 #else
49 #include "fault/Fault.h"
50 #include "fault/Trigger.h"
51 #include "fault/Injector.h"
52 #include "fault/xml/pugixml.hpp"
53 #endif
54 
55 #if MUTEX_SUPPORTED
56 #include <mutex>
57 #endif
58 
59 #if CXX0X_UP_SUPPORTED == 0
60 #define static_assert(x, y)
61 #endif
62 
63 namespace etiss
64 {
65 namespace fault
66 {
67 
68 // Helper for XML parsing and generating
69 namespace xml
70 {
71 
110 static bool getAttribute(const pugi::xml_node &node, const std::string &attr_name, std::string &dst, Diagnostics &diag)
111 {
112  bool first = true;
113  for (pugi::xml_attribute attr = node.first_attribute(); attr; attr = attr.next_attribute())
114  {
115  if (hasName(attr, attr_name))
116  {
117  if (first)
118  {
119  dst = attr.value();
120  first = false;
121  }
122  else
123  {
124  diag.unexpectedNode(node, std::string("Duplicated attribute: ") + attr_name);
125  }
126  }
127  }
128  return !first;
129 }
130 static bool setAttribute(pugi::xml_node &node, const std::string &attr_name, const std::string &src, Diagnostics &diag)
131 {
132  node.append_attribute(attr_name.c_str()).set_value(src.c_str());
133  return true;
134 }
135 static bool getAttribute(const pugi::xml_node &node, const std::string &attr_name, int32_t &dst, Diagnostics &diag)
136 {
137  std::string val;
138  if (!getAttribute(node, attr_name, val, diag))
139  return false;
140  std::stringstream(val) >> dst;
141  return true;
142 }
143 static bool setAttribute(pugi::xml_node &node, const std::string &attr_name, const int32_t &src, Diagnostics &diag)
144 {
145  static_assert(sizeof(int32_t) <= sizeof(long long),
146  "pugixml cannot handle int32_t natively. custom string conversion required");
147  node.append_attribute(attr_name.c_str()).set_value((long long)src);
148  return true;
149 }
150 
151 template <>
152 bool parse<std::vector<etiss::fault::Fault>>(pugi::xml_node node, std::vector<etiss::fault::Fault> &dst,
153  Diagnostics &diag)
154 {
155  etiss::log(etiss::VERBOSE, std::string("etiss::fault::xml::parse<std::vector<etiss::fault::Fault") +
156  std::string("> >(node, vector<Fault>, Diagnostics) called. "));
157 
158  bool ret = true;
159  for (pugi::xml_node cnode = node.first_child(); cnode; cnode = cnode.next_sibling())
160  {
161  if (hasName(cnode, "fault"))
162  { // handle fault node
163  Fault f;
164  if (parse<etiss::fault::Fault>(cnode, f, diag))
165  {
166  dst.push_back(f);
167  }
168  else
169  {
170  ret = false;
171  }
172  }
173  else
174  {
175  diag.ignoredNode(cnode, "non \"fault\" node in fault list.");
176  }
177  }
178  return ret;
179 }
180 
181 template <>
182 bool write<std::vector<etiss::fault::Fault>>(pugi::xml_node node, const std::vector<etiss::fault::Fault> &src,
183  Diagnostics &diag)
184 {
185  etiss::log(etiss::VERBOSE, std::string("etiss::fault::xml::write<std::vector<etiss::fault::Fault") +
186  std::string("> >(node, vector<Fault>, Diagnostics) called. "));
187 
188  bool ret = true;
189  for (size_t i = 0; i < src.size(); ++i)
190  {
191  ret = ret && write(node.append_child("fault"), src[i], diag);
192  }
193  return ret;
194 }
195 
196 } // namespace xml
197 
198 // generates a unique ID for a new Fault
200 {
201 #if MUTEX_SUPPORTED
202  static std::mutex mu;
203  std::lock_guard<std::mutex> lock(mu);
204 #endif
205  static int32_t cid = -1;
206  return cid--;
207 }
209 {
210  etiss::log(etiss::VERBOSE, std::string("etiss::fault::Fault::Fault() called. "));
211  id_ = uniqueFaultId();
212 }
213 std::string Fault::toString() const
214 {
215 
216  pugi::xml_document doc;
217  doc.load("<?xml version=\"1.0\"?>");
218 
219  etiss::fault::xml::Diagnostics diag;
220 
221  etiss::fault::xml::write<etiss::fault::Fault>(doc.append_child("fault"), *this, diag);
222 
223  std::stringstream ss;
224 
225  doc.save(ss);
226 
227  return ss.str();
228 }
229 
231 {
232  etiss::log(etiss::VERBOSE, std::string("etiss::fault::Fault::resolveTime(time=") + std::to_string(time) +
233  std::string(") called. "));
234  for (std::vector<Trigger>::iterator iter = triggers.begin(); iter != triggers.end(); ++iter)
235  {
236  iter->resolveTime(time);
237  }
238 }
239 bool Fault::isResoved() const
240 {
241  for (std::vector<Trigger>::const_iterator iter = triggers.begin(); iter != triggers.end(); ++iter)
242  {
243  if (!iter->isResolved())
244  return false;
245  }
246  return true;
247 }
248 
249 #if ETISS_FAULT_XML
250 
251 bool parseXML(std::vector<Fault> &vec, std::istream &input, std::ostream &diagnostics_out)
252 {
253 
254  pugi::xml_document doc; // xml document
255 
256  pugi::xml_parse_result pr = doc.load(input); // load from stream
257 
258  if (!pr)
259  { // load failure
260  diagnostics_out << "failed to load xml from stream: " << pr.description() << std::endl;
261  return false;
262  }
263 
264  etiss::fault::xml::Diagnostics diag;
265 
266  bool ret = parse(doc.document_element(), vec, diag); // parse document
267 
268  diag.print(diagnostics_out);
269 
270  return ret;
271 }
272 
273 bool writeXML(const std::vector<Fault> &vec, std::ostream &out, std::ostream &diagnostics_out)
274 {
275  pugi::xml_document doc;
276 
277  doc.load("<?xml version=\"1.0\"?>");
278 
279  etiss::fault::xml::Diagnostics diag;
280 
281  bool ret = write(doc.append_child("faults"), vec, diag); // write document
282 
283  doc.save(out);
284 
285  diag.print(diagnostics_out);
286 
287  return ret;
288 }
289 
290 namespace xml
291 {
292 
293 template <>
294 bool parse<etiss::fault::Fault>(pugi::xml_node node, etiss::fault::Fault &f, Diagnostics &diag)
295 {
296  etiss::log(etiss::VERBOSE, std::string("etiss::fault::xml::parse<etiss::fault::Fault>") +
297  std::string("(node, Fault, Diagnostics) called. "));
298  bool ret = true;
299  /*ret = ret &*/ getAttribute(node, "name", f.name_, diag); // optional
300  /*ret = ret &*/ getAttribute(node, "id_", f.id_, diag); // optional
301  for (pugi::xml_node cnode = node.first_child(); cnode; cnode = cnode.next_sibling())
302  {
303  if (hasName(cnode, "triggers"))
304  {
305  for (pugi::xml_node ccnode = cnode.first_child(); ccnode; ccnode = ccnode.next_sibling())
306  {
307  if (hasName(ccnode, "trigger"))
308  {
310  if (parse<etiss::fault::Trigger>(ccnode, t, diag))
311  {
312  f.triggers.push_back(t);
313  }
314  else
315  {
316  ret = false;
317  }
318  }
319  else
320  {
321  diag.ignoredNode(ccnode, "\"trigger\" node expected");
322  }
323  }
324  }
325  else if (hasName(cnode, "actions"))
326  {
327  for (pugi::xml_node ccnode = cnode.first_child(); ccnode; ccnode = ccnode.next_sibling())
328  {
329  if (hasName(ccnode, "action"))
330  {
332  if (parse<etiss::fault::Action>(ccnode, t, diag))
333  {
334  f.actions.push_back(t);
335  }
336  else
337  {
338  ret = false;
339  }
340  }
341  else
342  {
343  diag.ignoredNode(ccnode, "\"trigger\" node expected");
344  }
345  }
346  }
347  else
348  {
349  diag.ignoredNode(cnode, "unknown node");
350  }
351  }
352 
353  return ret;
354 }
355 template <>
356 bool write<etiss::fault::Fault>(pugi::xml_node node, const etiss::fault::Fault &f, Diagnostics &diag)
357 {
358  etiss::log(etiss::VERBOSE, std::string("etiss::fault::xml::write<etiss::fault::Fault>") +
359  std::string("(node, Fault, Diagnostics) called. "));
360  bool ok = true;
361  ok = ok && setAttribute(node, "name", f.name_, diag);
362  ok = ok && setAttribute(node, "id", f.id_, diag);
363  pugi::xml_node triggers = node.append_child("triggers");
364  for (std::vector<etiss::fault::Trigger>::const_iterator iter = f.triggers.begin(); iter != f.triggers.end(); ++iter)
365  {
366  ok = ok && write<etiss::fault::Trigger>(triggers.append_child("trigger"), *iter, diag);
367  }
368  pugi::xml_node actions = node.append_child("actions");
369  for (std::vector<etiss::fault::Action>::const_iterator iter = f.actions.begin(); iter != f.actions.end(); ++iter)
370  {
371  ok = ok && write<etiss::fault::Action>(actions.append_child("action"), *iter, diag);
372  }
373  return ok;
374 }
375 
376 } // namespace xml
377 
378 #endif
379 
380 } // namespace fault
381 } // namespace etiss
#define static_assert(x, y)
Definition: Fault.cpp:60
contains the fault container class that stores triggers and actions for fault injection
contains the fault injector interface class.
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
static __inline__ int32_t
Definition: arm_mve.h:51
bool isResoved() const
check all Triggers if they are resolved.
Definition: Fault.cpp:239
Fault()
Constructor: Generates a new Fault with unique ID.
Definition: Fault.cpp:208
std::string toString() const
operator<< can be used.
Definition: Fault.cpp:213
int32_t id_
Definition: Fault.h:99
std::string name_
Definition: Fault.h:98
void resolveTime(uint64_t time)
Resolves time for all its Triggers.
Definition: Fault.cpp:230
std::vector< Trigger > triggers
contains the triggers for this fault
Definition: Fault.h:100
std::vector< Action > actions
contains the actions for this fault
Definition: Fault.h:101
xml_attribute next_attribute() const
Definition: pugixml.cpp:4378
bool set_value(const char_t *rhs)
Definition: pugixml.cpp:4507
xml_parse_result load(std::basic_istream< char, std::char_traits< char > > &stream, unsigned int options=parse_default, xml_encoding encoding=encoding_auto)
xml_node document_element() const
Definition: pugixml.cpp:6186
void save(xml_writer &writer, const char_t *indent=PUGIXML_TEXT("\t"), unsigned int flags=format_default, xml_encoding encoding=encoding_auto) const
Definition: pugixml.cpp:6125
xml_node append_child(xml_node_type type=node_element)
Definition: pugixml.cpp:4983
xml_node first_child() const
Definition: pugixml.cpp:4797
xml_attribute append_attribute(const char_t *name)
Definition: pugixml.cpp:4837
xml_node next_sibling() const
Definition: pugixml.cpp:4715
xml_attribute first_attribute() const
Definition: pugixml.cpp:4787
static bool setAttribute(pugi::xml_node &node, const std::string &attr_name, const std::string &src, Diagnostics &diag)
Definition: Fault.cpp:130
static bool getAttribute(const pugi::xml_node &node, const std::string &attr_name, std::string &dst, Diagnostics &diag)
Parser/writer structure:
Definition: Fault.cpp:110
static int32_t uniqueFaultId()
Definition: Fault.cpp:199
Page Table Entry (PTE) defines the composition of Page Frame Number (PFN) and relavant flags.
Definition: Benchmark.h:53
@ VERBOSE
Definition: Misc.h:130
void log(Verbosity level, std::string msg)
write log message at the given level.
Definition: Misc.cpp:125
const char * description() const
Definition: pugixml.cpp:5913