ETISS 0.8.0
Extendable Translating Instruction Set Simulator (version 0.8.0)
ETISS.cpp
Go to the documentation of this file.
1 
36 #include "etiss/ETISS.h"
37 #include "etiss/fault/Stressor.h"
38 
39 #include <csignal>
40 #include <cstring>
41 #include <fstream>
42 #include <functional>
43 
44 #include <boost/program_options/options_description.hpp>
45 #include <boost/program_options/parsers.hpp>
46 #include <boost/program_options/variables_map.hpp>
47 #include <boost/algorithm/string.hpp>
48 
49 #include "SimpleIni.h"
50 // SimpleIni includes windows.h which defines NOERROR, clashing with our ReturnCode.
51 #ifdef NOERROR
52 #undef NOERROR
53 #endif
54 
55 #if ETISS_USE_DLSYM
56 #include <dlfcn.h>
57 #endif
58 
59 using namespace etiss;
60 
61 std::string etiss_defaultjit_;
62 
63 std::list<std::shared_ptr<etiss::LibraryInterface>> etiss_libraries_;
64 std::recursive_mutex etiss_libraries_mu_;
65 
66 boost::program_options::variables_map vm;
67 std::vector<std::string> pluginOptions = {"plugin.logger.logaddr", "plugin.logger.logmask", "plugin.gdbserver.port"};
68 
69 std::set<std::string> etiss::listCPUArchs()
70 {
71  std::set<std::string> ret;
72  std::lock_guard<std::recursive_mutex> lock(etiss_libraries_mu_);
73  for (auto iter = etiss_libraries_.begin(); iter != etiss_libraries_.end(); iter++)
74  {
75  if ((*iter).get() != 0)
76  {
77  if (!(*iter)->isEmpty())
78  {
79  for (unsigned i = 0; i < (*iter)->countCPUArchs(); i++)
80  {
81  std::string jit = (*iter)->nameCPUArch(i);
82  if (ret.find(jit) != ret.end())
83  {
84  etiss::log(etiss::ERROR, "CPUArch provided by multiple libraries: \"" + jit + "\"");
85  }
86  else
87  {
88  ret.insert(jit);
89  }
90  }
91  }
92  }
93  }
94  return ret;
95 }
96 
97 std::set<std::string> etiss::listJITs()
98 {
99  std::set<std::string> ret;
100  std::lock_guard<std::recursive_mutex> lock(etiss_libraries_mu_);
101  for (auto iter = etiss_libraries_.begin(); iter != etiss_libraries_.end(); iter++)
102  {
103  if ((*iter).get() != 0)
104  {
105  if (!(*iter)->isEmpty())
106  {
107  for (unsigned i = 0; i < (*iter)->countJITs(); i++)
108  {
109  std::string jit = (*iter)->nameJIT(i);
110  if (ret.find(jit) != ret.end())
111  {
112  etiss::log(etiss::ERROR, "JIT provided by multiple libraries: \"" + jit + "\"");
113  }
114  else
115  {
116  ret.insert(jit);
117  }
118  }
119  }
120  }
121  }
122  return ret;
123 }
124 
125 std::set<std::string> etiss::listPlugins()
126 {
127  std::set<std::string> ret;
128  std::lock_guard<std::recursive_mutex> lock(etiss_libraries_mu_);
129  for (auto iter = etiss_libraries_.begin(); iter != etiss_libraries_.end(); iter++)
130  {
131  if ((*iter).get() != 0)
132  {
133  if (!(*iter)->isEmpty())
134  {
135  for (unsigned i = 0; i < (*iter)->countPlugins(); i++)
136  {
137  std::string jit = (*iter)->namePlugin(i);
138  if (ret.find(jit) != ret.end())
139  {
140  etiss::log(etiss::ERROR, "JIT provided by multiple libraries: \"" + jit + "\"");
141  }
142  else
143  {
144  ret.insert(jit);
145  }
146  }
147  }
148  }
149  }
150  return ret;
151 }
152 
153 std::shared_ptr<JIT> etiss::getJIT(std::string name, std::map<std::string, std::string> options)
154 {
155  std::shared_ptr<JIT> jit;
156  std::string ujit;
157  std::lock_guard<std::recursive_mutex> lock(etiss_libraries_mu_);
158  for (auto iter = etiss_libraries_.begin(); iter != etiss_libraries_.end(); iter++)
159  {
160  std::shared_ptr<LibraryInterface> lib = *iter;
161  if (lib.get() != 0)
162  {
163  if (!lib->isEmpty())
164  {
165  for (unsigned i = 0; i < lib->countJITs(); i++)
166  {
167  if (lib->nameJIT(i) == name)
168  {
169  if (jit.get() != 0)
170  {
171  etiss::log(etiss::ERROR, "JIT provided by multiple libraries: using \"" + name +
172  "\" from library \"" + ujit +
173  "\" [also provided by library \"" + lib->getName() + "\"]");
174  }
175  else
176  {
177  etiss::JIT *ca = lib->createJIT(i, options);
178  if (ca == 0)
179  {
181  "Failed to create JIT via library interface \"" + lib->getName() + "\"");
182  }
183  else
184  {
185  jit = std::shared_ptr<JIT>(ca, [lib](JIT *j) { lib->deleteJIT(j); });
186  ujit = lib->getName();
187  }
188  }
189  }
190  }
191  }
192  }
193  }
194  return jit;
195 }
196 
197 std::shared_ptr<CPUArch> etiss::getCPUArch(std::string name, std::map<std::string, std::string> options)
198 {
199  std::shared_ptr<CPUArch> arch;
200  std::string uarch;
201  std::lock_guard<std::recursive_mutex> lock(etiss_libraries_mu_);
202  for (auto iter = etiss_libraries_.begin(); iter != etiss_libraries_.end(); iter++)
203  {
204  std::shared_ptr<LibraryInterface> lib = *iter;
205  if (lib.get() != 0)
206  {
207  if (!lib->isEmpty())
208  {
209  for (unsigned i = 0; i < lib->countCPUArchs(); i++)
210  {
211  if (lib->nameCPUArch(i) == name)
212  {
213  if (arch.get() != 0)
214  {
215  etiss::log(etiss::ERROR, "CPU Architecture provided by multiple libraries: using \"" +
216  name + "\" from library \"" + uarch +
217  "\" [also provided by library \"" + lib->getName() + "\"]");
218  }
219  else
220  {
221  etiss::CPUArch *ca = lib->createCPUArch(i, options);
222  if (ca == 0)
223  {
225  "Failed to create CPUArch via library interface \"" + lib->getName() + "\"");
226  }
227  else
228  {
229  arch = std::shared_ptr<CPUArch>(ca, [lib](CPUArch *a) { lib->deleteCPUArch(a); });
230  uarch = lib->getName();
231  }
232  }
233  }
234  }
235  }
236  }
237  }
238  return arch;
239 }
240 
241 std::shared_ptr<Plugin> etiss::getPlugin(std::string name, std::map<std::string, std::string> options)
242 {
243  std::shared_ptr<Plugin> ptrPlugin;
244  std::string strPluginName;
245  std::lock_guard<std::recursive_mutex> lock(etiss_libraries_mu_);
246  for (auto iter = etiss_libraries_.begin(); iter != etiss_libraries_.end(); iter++)
247  {
248  std::shared_ptr<LibraryInterface> lib = *iter;
249  if (lib.get() != 0)
250  {
251  if (!lib->isEmpty())
252  {
253  for (unsigned i = 0; i < lib->countPlugins(); i++)
254  {
255  if (lib->namePlugin(i) == name)
256  {
257  if (ptrPlugin.get() != 0)
258  {
259  etiss::log(etiss::ERROR, "Plugin provided by multiple libraries: using \"" + name +
260  "\" from library \"" + strPluginName +
261  "\" [also provided by library \"" + lib->getName() + "\"]");
262  }
263  else
264  {
265  etiss::Plugin *ca = lib->createPlugin(i, options);
266  if (ca == 0)
267  {
269  "Failed to create Plugin via library interface \"" + lib->getName() + "\"");
270  }
271  else
272  {
273  ptrPlugin = std::shared_ptr<Plugin>(ca, [lib](Plugin *p) { lib->deletePlugin(p); });
274  strPluginName = lib->getName();
275  etiss::log(etiss::INFO, "Plugin \"" + name + "\" loaded via library interface \"" +
276  strPluginName + "\"\n");
277  }
278  }
279  break;
280  }
281  }
282  }
283  }
284  }
285  return ptrPlugin;
286 }
287 
288 bool etiss::loadLibrary(std::string path, std::string name)
289 {
290  auto lib = etiss::LibraryInterface::openSharedLibrary(path, name);
291 
292  if (lib.get())
293  {
294  addLibrary(lib);
295  return true;
296  }
297 
298  return false;
299 }
300 
301 void etiss::addLibrary(std::shared_ptr<etiss::LibraryInterface> libInterface)
302 {
303  etiss::LibraryInterface *lif = libInterface.get();
304 
305  if (lif == 0)
306  {
307  return;
308  }
309 
311 
312  {
313  std::lock_guard<std::recursive_mutex> lock(etiss_libraries_mu_);
314  etiss_libraries_.push_back(libInterface);
315  }
316  // if no default jit is present, try to use one from this library
317  for (unsigned i = 0; (etiss_defaultjit_.size() <= 0) && (i < libInterface->countJITs()); i++)
318  {
319  etiss_defaultjit_ = libInterface->nameJIT(i);
320  }
321 }
322 std::set<std::string> etiss::listLibraries()
323 {
324  std::lock_guard<std::recursive_mutex> lock(etiss_libraries_mu_);
325  std::set<std::string> ret;
326  for (auto iter = etiss_libraries_.begin(); iter != etiss_libraries_.end(); iter++)
327  {
328  ret.insert((*iter)->getName() + "[" + (*iter)->versionInfo() + "]");
329  }
330  return ret;
331 }
332 
333 std::set<std::string> etiss::listLibraryPrefixes()
334 {
335  std::lock_guard<std::recursive_mutex> lock(etiss_libraries_mu_);
336  std::set<std::string> ret;
337  for (auto iter = etiss_libraries_.begin(); iter != etiss_libraries_.end(); iter++)
338  {
339  ret.insert((*iter)->getName());
340  }
341  return ret;
342 }
343 
344 std::shared_ptr<etiss::JIT> etiss::getDefaultJIT()
345 {
346  return getJIT(etiss_defaultjit_);
347 }
348 
349 // transfer controll to etiss console on SIGINT
352 
353 void etiss_SIGINT_handler(int sig)
354 {
355  if (sig == SIGINT)
356  {
357  std::cout << std::endl << "\033[0;31m" << std::endl;
359  std::cout << std::endl << "\033[0m" << std::endl;
360  }
361  else
362  { // false handler assignment
363  signal(sig, SIG_DFL);
364  raise(sig);
365  return;
366  }
367 }
368 
369 //__attribute__((destructor))
370 static void etiss_remove_SIGINT()
371 {
373  {
376  }
377 }
380 {
381  public:
384 
385 // initialize
386 CSimpleIniA *po_simpleIni;
387 void etiss_loadIni(std::string fileName)
388 {
389  if (po_simpleIni == NULL)
390  po_simpleIni = new CSimpleIniA(true, true, true);
391 
392  SI_Error rc = po_simpleIni->LoadFile(fileName.c_str());
393  if (rc < 0)
394  std::cout << "Initializer::loadIni(): Failed to load Ini: " << fileName << std::endl;
395  else
396  std::cout << "Initializer::loadIni(): Ini sucessfully loaded " << fileName << std::endl;
397 }
398 
399 void etiss::Initializer::loadIni(std::list<std::string> *files)
400 {
401  std::cout << " Load ini file." << std::endl;
402  // create ini parser
403  if (po_simpleIni == NULL)
404  po_simpleIni = new CSimpleIniA(true, true, true);
405  else
406  std::cout << "Info: simpleIni already exists!" << std::endl;
407 
408  // load file
409  for (auto it_files : *files)
410  {
411  // the check above is sufficient no need for this / checked for previous cases false and last true gives true not the case based on files structure
412  etiss_loadIni(it_files);
413  }
414 }
415 
417 {
418  if (!po_simpleIni) // no .ini files were given.
419  {
420  return;
421  }
422  std::cout << " Load Configs from .ini files:" << std::endl;
423 
424  // preload loglevel
425  if (!etiss::cfg().isSet("etiss.loglevel"))
426  {
427  etiss::cfg().set<int>("etiss.loglevel", po_simpleIni->GetLongValue("IntConfigurations", "etiss.loglevel", etiss::WARNING));
428  }
429  {
430  int ll = cfg().get<int>("etiss.loglevel", etiss::WARNING);
431  if (ll >= 0 && ll <= etiss::VERBOSE)
432  { // valid log level
433  // dnm
434  // etiss::verbosity() = etiss::VERBOSE;
435  etiss::verbosity() = (Verbosity)ll;
436  etiss::log(etiss::VERBOSE, "Log level set to VERBOSE");
437  }
438  else
439  {
441  etiss::log(etiss::ERROR, "Specified log level is not valid. must range between 0 (= "
442  "silent) and 5 (= verbose)");
443  }
444  }
445 
446  // get all sections
447  CSimpleIniA::TNamesDepend sections;
448  po_simpleIni->GetAllSections(sections);
449  for (auto iter_section : sections)
450  {
451  // only load config sections
452  if (std::string(iter_section.pItem) != "StringConfigurations" &&
453  std::string(iter_section.pItem) != "BoolConfigurations" &&
454  std::string(iter_section.pItem) != "IntConfigurations")
455  {
456  continue;
457  }
458  etiss::log(etiss::INFO, std::string(" [") + iter_section.pItem + ']');
459 
460  // get all keys in a section
461  CSimpleIniA::TNamesDepend keys;
462  po_simpleIni->GetAllKeys(iter_section.pItem, keys);
463  for (auto iter_key : keys)
464  {
465  std::stringstream message;
466  bool warning = false;
467 
468  // skip loglevel
469  if (std::string(iter_key.pItem) == "etiss.loglevel")
470  continue;
471 
472  // check if cfg is already set
473  if (etiss::cfg().isSet(iter_key.pItem))
474  {
475  message << " cfg already set on command line. ";
476  message << " " << iter_key.pItem << "=";
477  const ::std::type_info& type = vm[std::string(iter_key.pItem)].value().type() ;
478  if (type == typeid(::std::string))
479  message << vm[std::string(iter_key.pItem)].as<std::string>() << ",";
480  else if (type == typeid(int))
481  message << vm[std::string(iter_key.pItem)].as<int>() << ",";
482  else if (type == typeid(bool))
483  message << std::boolalpha << vm[std::string(iter_key.pItem)].as<bool>() << ",";
484  warning = true;
485  }
486  else
487  {
488  // write key (=option) to message.
489  message << " " << iter_key.pItem << "=";
490 
491  // get all values of a key with multiple values
492  CSimpleIniA::TNamesDepend values;
493  po_simpleIni->GetAllValues(iter_section.pItem, iter_key.pItem, values);
494  for (auto iter_value : values)
495  {
496  // Handle configurations
497  if (std::string(iter_section.pItem) == "StringConfigurations")
498  {
499  etiss::cfg().set<std::string>(iter_key.pItem, iter_value.pItem);
500  }
501  else if (std::string(iter_section.pItem) == "BoolConfigurations")
502  {
503  std::string itemval = iter_value.pItem;
504  boost::algorithm::to_lower(itemval); // converts itemval to lower case string
505  bool val;
506 
507  if ((itemval == "true") | (itemval == "yes") | (itemval == "1") | (itemval == "t")) val = true;
508  else if ((itemval == "false") | (itemval == "no") | (itemval == "0") | (itemval == "f")) val = false;
509  else etiss::log(etiss::FATALERROR, std::string("Configuration value ") + iter_key.pItem + " could not be parsed as boolean");
510 
511  etiss::cfg().set<bool>(iter_key.pItem, val);
512  }
513  else if (std::string(iter_section.pItem) == "IntConfigurations") // already load!
514  {
515  std::string itemval = iter_value.pItem;
516  std::size_t sz = 0;
517  long long val;
518  try {
519  val = std::stoll(itemval, &sz, 0);
520  }
521  // catch invalid_argument exception.
522  catch (std::invalid_argument const&){
523  etiss::log(etiss::FATALERROR, std::string("Configuration value ") + iter_key.pItem + " could not be parsed as integer");
524  }
525  etiss::cfg().set<long long>(iter_key.pItem, val);
526  // we use double, as long could have only 32 Bit (e.g. on Windows)
527  // and long long is not offered by the ini library
528  }
529  else
530  // we don't add a DoubleConfigurations section, as converting them
531  // to and from strings could provoke accuracy issues.
532  // To support double, a Configuration::get<double>() has to be
533  // added to Misc.cpp
534  {
535  message << " Section not found for Value:";
536  warning = true;
537  }
538 
539  // write item (=option value) to message.
540  message << iter_value.pItem << ",";
541  }
542 
543  // check if more than one value is set in the ini file
544  if (values.size() > 1)
545  {
546  warning = true;
547  message << " Multi values. Take only LAST one!";
548  }
549  }
550  // add message to etiss log.
551  etiss::log(warning ? etiss::WARNING : etiss::INFO, message.str());
552  }
553  }
554 }
555 
556 void etiss::Initializer::loadIniPlugins(std::shared_ptr<etiss::CPUCore> cpu)
557 {
558  std::map<std::string, std::string> options;
559  for (auto iter = pluginOptions.begin(); iter != pluginOptions.end(); iter++)
560  {
561  if (etiss::cfg().isSet(*iter))
562  {
563  options[*iter] = std::string(vm[std::string(*iter)].as<std::string>());
564  etiss::log(etiss::INFO, *iter + " written from command line\n" + " options[" +
565  std::string(*iter) +
566  "] = " + std::string(vm[std::string(*iter)].as<std::string>()) + "\n");
567  }
568  }
569  if (vm.count("pluginToLoad"))
570  {
571  const std::vector<std::string> pluginList = vm["pluginToLoad"].as<std::vector<std::string>>();
572  for (auto pluginName = pluginList.begin(); pluginName != pluginList.end(); pluginName++)
573  {
574  std::string::size_type pos = std::string(*pluginName).length();
575  bool pluginAlreadyPresent = false;
576  for (auto iter : *cpu->getPlugins())
577  {
578  std::string pluginNamecpu = iter->getPluginName();
579  if (pos != std::string::npos)
580  {
581  pluginNamecpu = pluginNamecpu.substr(0, pos);
582  }
583  if (pluginNamecpu == *pluginName)
584  {
585  pluginAlreadyPresent = true;
586  break;
587  }
588  }
589  if (pluginAlreadyPresent)
590  {
591  etiss::log(etiss::WARNING, " Warning: Plugin already present. Skipping it: " + *pluginName + "\n");
592  continue;
593  }
594  etiss::log(etiss::INFO, " Adding Plugin " + *pluginName + "\n");
595  cpu->addPlugin(etiss::getPlugin(*pluginName, options));
596  }
597  }
598  if (!po_simpleIni)
599  {
600  etiss::log(etiss::WARNING, "Ini file not loaded. Can't load plugins from simpleIni!");
601  return;
602  }
603  // get all sections
604  CSimpleIniA::TNamesDepend sections;
605  po_simpleIni->GetAllSections(sections);
606  for (auto iter_section : sections)
607  {
608  // only load Plugin sections
609  if (std::string(iter_section.pItem).substr(0, 6) != std::string("Plugin"))
610  continue;
611  std::string pluginName = std::string(iter_section.pItem).substr(7);
612  std::string::size_type pos = pluginName.length();
613  // check if Plugin is already present
614  bool pluginAlreadyPresent = false;
615  for (auto iter : *cpu->getPlugins())
616  {
617  std::string pluginNamecpu = iter->getPluginName();
618  if (pos != std::string::npos)
619  {
620  pluginNamecpu = pluginNamecpu.substr(0, pos);
621  }
622  if (pluginNamecpu == pluginName)
623  {
624  pluginAlreadyPresent = true;
625  break;
626  }
627  }
628  if (pluginAlreadyPresent)
629  {
630  etiss::log(etiss::WARNING, " Warning: Plugin already present. Skipping it: " + pluginName + "\n");
631  continue;
632  }
633 
634  etiss::log(etiss::INFO, " Adding Plugin " + pluginName + "\n");
635 
636  // get all keys in a section = plugin option
637  CSimpleIniA::TNamesDepend keys;
638  po_simpleIni->GetAllKeys(iter_section.pItem, keys);
639  for (auto iter_key : keys)
640  {
641  // get all values of a key with multiple values = value of option
642  CSimpleIniA::TNamesDepend values;
643  po_simpleIni->GetAllValues(iter_section.pItem, iter_key.pItem, values);
644  if (!etiss::cfg().isSet(iter_key.pItem))
645  {
646  std::stringstream ss;
647  ss << iter_key.pItem << " not set on the command line. Checking in .ini file.";
648  etiss::log(etiss::INFO, ss.str());
649 
650  for (auto iter_value : values)
651  {
652  options[iter_key.pItem] = iter_value.pItem;
654  " options[" + std::string(iter_key.pItem) + "] = " + std::string(iter_value.pItem) + "\n\n");
655  }
656  // check if more than one value is set in the ini file
657  if (values.size() > 1)
658  etiss::log(etiss::WARNING, "Multiple values for option. Took only last one!");
659  }
660  }
661  cpu->addPlugin(etiss::getPlugin(pluginName, options));
662  }
663 }
664 
665 void etiss::Initializer::loadIniJIT(std::shared_ptr<etiss::CPUCore> cpu)
666 {
667  // check if JIT is set
668  if (!etiss::cfg().isSet("jit.type"))
669  {
670  etiss::log(etiss::INFO, "No JIT configured. Will use default JIT. \n");
671  cpu->set(etiss::getDefaultJIT());
672  return;
673  }
674  if (cpu->getJITName() != "")
675  {
677  "etiss::Initializer::loadIniJIT:" + std::string(" JIT already present. Overwriting it."));
678  }
679  etiss::log(etiss::INFO, " Adding JIT \"" + cfg().get<std::string>("jit.type", "") + '\"');
680  cpu->set(getJIT(cfg().get<std::string>("jit.type", "")));
681 }
682 
683 std::pair<std::string, std::string> inifileload(const std::string& s)
684 {
685  if (s.find("-i") == 0)
686  {
687  std::string inifile;
688  inifile = s.substr(2);
689  etiss_loadIni(inifile);
690  }
691  return make_pair(std::string(), std::string());
692 }
693 
694 void etiss_initialize(const std::vector<std::string>& args, bool forced = false)
695 {
696  static std::mutex mu_;
697  static bool initialized_(false);
698  {
699  std::lock_guard<std::mutex> lock(mu_);
700  if (initialized_)
701  {
702  if (!forced)
703  {
704  etiss::log(etiss::WARNING, "Multiple calls to etiss::initialize");
705  }
706  else
707  {
708  return;
709  }
710  }
711  else
712  {
713  if (forced)
714  {
715  etiss::log(etiss::WARNING, "etiss::initialize has not been called before using ETISS library "
716  "functions. Please add the line \'etiss::initialize(argc,argv);\' "
717  "at the beginning of \'int main(int argc, char**argv);\'");
718  }
719  }
720  initialized_ = true;
721  }
722 
723  {
724  namespace po = boost::program_options;
725  try
726  {
727  po::options_description desc("Allowed options");
728  desc.add_options()
729  ("help", "Produce a help message that lists all supported options.")
730  ("arch.cpu", po::value<std::string>(), "The CPU Architecture to simulate.")
731  ("arch.or1k.ignore_sr_iee", po::value<bool>(), "Ignore exception on OpenRISC.")
732  ("arch.or1k.if_stall_cycles", po::value<int>(), "Add instruction stall cycles on OpenRISC.")
733  ("arch.cpu_cycle_time_ps", po::value<int>(), "Sets CPU cycles time on OpenRISC and ARM.")
734  ("arch.enable_semihosting", po::value<bool>(), "Enables semihosting operations")
735  ("etiss.enable_dmi", po::value<bool>(), "Enables the Direct Memory Interface feature of SystemC to speed up memory accesses. This needs to be disabled for memory tracing.")
736  ("etiss.log_pc", po::value<bool>(), "Enables logging of the program counter.")
737  ("etiss.max_block_size", po::value<int>(), "Sets maximum amount of instructions in a block.")
738  ("etiss.output_path_prefix", po::value<std::string>(), "Path prefix to use when writing output files.")
739  ("etiss.loglevel", po::value<int>(), "Verbosity of logging output.")
740  ("jit.gcc.cleanup", po::value<bool>(), "Cleans up temporary files in GCCJIT. ")
741  ("jit.verify", po::value<bool>(), "Run some basic checks to verify the functionality of the JIT engine.")
742  ("jit.debug", po::value<bool>(), "Causes the JIT Engines to compile in debug mode.")
743  ("jit.type", po::value<std::string>(), "The JIT compiler to use.")
744  ("jit.external_headers", po::value<std::string>(), "List of semicolon-separated paths to headers for the JIT to include.")
745  ("jit.external_libs", po::value<std::string>(), "List of semicolon-separated library names for the JIT to link.")
746  ("jit.external_header_paths", po::value<std::string>(), "List of semicolon-separated headers paths for the JIT.")
747  ("jit.external_lib_paths", po::value<std::string>(), "List of semicolon-separated library paths for the JIT.")
748  ("vp.sw_binary_ram", po::value<std::string>(), "Path to binary file to be loaded into RAM.")
749  ("vp.sw_binary_rom", po::value<std::string>(), "Path to binary file to be loaded into ROM.")
750  ("vp.elf_file", po::value<std::string>(), "Load ELF file.")
751  ("vp.stats_file_path", po::value<std::string>(), "Path where the output json file gets stored after bare processor is run.")
752  ("simple_mem_system.print_dbus_access", po::value<bool>(), "Traces accesses to the data bus.")
753  ("simple_mem_system.print_ibus_access", po::value<bool>(), "Traces accesses to the instruction bus.")
754  ("simple_mem_system.print_dbgbus_access", po::value<bool>(), "Traces accesses to the debug bus.")
755  ("simple_mem_system.print_to_file", po::value<bool>(), "Write all tracing to a file instead of the terminal. The file will be located at etiss.output_path_prefix.")
756  ("plugin.logger.logaddr", po::value<std::string>(), "Provides the compare address that is used to check for memory accesses that are redirected to the logger.")
757  ("plugin.logger.logmask", po::value<std::string>(), "Provides the mask that is used to check for memory accesses that are redirected to the logger.")
758  ("plugin.gdbserver.port", po::value<std::string>(), "Option for gdbserver")
759  ("pluginToLoad,p", po::value<std::vector<std::string>>()->multitoken(), "List of plugins to be loaded.")
760  ;
761 
762  po::command_line_parser parser{args};
763  po::command_line_parser iniparser{args};
764  iniparser.options(desc).allow_unregistered().extra_parser(inifileload).run();
765  parser.options(desc).allow_unregistered().extra_parser(etiss::Configuration::set_cmd_line_boost);
766  po::parsed_options parsed_options = parser.run();
767  po::store(parsed_options, vm);
768 
769  if (vm.count("help"))
770  {
771  std::cout << "\nPlease begin all options with --\n\n";
772  std::cout << desc << "\n";
773  etiss::log(etiss::FATALERROR, std::string("Please choose the right configurations from the list and re-run.\n"));
774  }
775 
776  auto unregistered = po::collect_unrecognized(parsed_options.options, po::include_positional);
777  for (auto iter_unreg : unregistered)
778  {
779  if (iter_unreg.find("-i") != 0 && iter_unreg.find("-p"))
780  {
781  etiss::log(etiss::FATALERROR, std::string("Unrecognised option ") + iter_unreg +
782  "\n\t Please use --help to list all recognised options. \n");
783  }
784  }
785 
786  for (po::variables_map::iterator i = vm.begin() ; i != vm.end() ; ++ i)
787  {
788  const po::variable_value& v = i->second;
789  if (!v.empty())
790  {
791  const ::std::type_info& type = v.value().type();
792  if (type == typeid(::std::string))
793  {
794  const ::std::string& val = v.as<::std::string>() ;
795  etiss::cfg().set<std::string>(std::string(i->first), val);
796  }
797  else if (type == typeid(int))
798  {
799  int val = v.as<int>();
800  etiss::cfg().set<int>(std::string(i->first), val);
801  }
802  else if (type == typeid(bool))
803  {
804  bool val = v.as<bool>();
805  etiss::cfg().set<bool>(std::string(i->first), val);
806  }
807  }
808  }
809  }
810  catch(std::exception& e)
811  {
812  etiss::log(etiss::FATALERROR, std::string(e.what()) +
813  "\n\t Please use --help to list all recognised options. \n");
814  }
815  }
817 
818  // log level
819  {
820  int ll = cfg().get<int>("etiss.loglevel", etiss::WARNING);
821  if (ll >= 0 && ll <= etiss::VERBOSE)
822  { // valid log level
823  // dnm
824  // etiss::verbosity() = etiss::VERBOSE;
825  etiss::verbosity() = (Verbosity)ll;
826  etiss::log(etiss::VERBOSE, "Log level set to VERBOSE");
827  }
828  else
829  {
831  etiss::log(etiss::ERROR, "Specified log level is not valid. must range between 0 (= "
832  "silent) and 5 (= verbose)");
833  }
834  }
835 
836  etiss::py::init(); // init python
837 
840 
841  // load integrated library
842  if (cfg().get<bool>("etiss.load_integrated_libraries", true))
843  {
845  }
846 
847  // check if some required files can be found
848  {
849  std::string path = etiss::installDir();
850  std::vector<std::string> requiredFiles;
851 
852  // required files
853  requiredFiles.push_back(path + "/include/jit/etiss/jit/CPU.h");
854 
855  // check
856  for (auto iter = requiredFiles.begin(); iter != requiredFiles.end(); iter++)
857  {
858  std::ifstream f(iter->c_str());
859  if (!f)
860  {
861  etiss::log(etiss::WARNING, std::string("Could not find file: ") + *iter + "\n" +
862  "\t The installation seems broken");
863  }
864  }
865  }
866 
867  // load fault files
868  {
869  std::string faults = cfg().get<std::string>("faults.xml", "");
870  if (!faults.empty())
871  {
872  std::list<std::string> ffs = etiss::split(faults, ';');
873  for (auto ff : ffs)
874  {
876  }
877  }
878  }
879 }
880 
881 void etiss::initialize(std::vector<std::string>& args)
882 {
883  etiss_initialize(args, false);
884 }
885 
887 {
888  std::vector<std::string> args{};
889  etiss_initialize(args, true);
890 }
891 
892 //__attribute__((destructor))
893 static void etiss_shutdown()
894 {
895  etiss::shutdown(); // TODO: verify with spec. assuming shared library close
896  // after __attribute__((destructor)) functions have been
897  // called
898 
899  // force close open libraries
900  //{
901  // std::lock_guard<std::recursive_mutex> lock(etiss_libraries_mu_);
902  // etiss_libraries_.clear();
903  //}
904 }
907 {
908  public:
911 
912 bool etiss_shutdownOk = false;
913 
915 {
916  if (etiss_shutdownOk) // only on shutdown
917  return;
918 
919  etiss_shutdownOk = true;
920 
922 
923  // unload libraries
924  {
925  std::list<std::weak_ptr<LibraryInterface>> libraries_weak;
926  {
927  std::lock_guard<std::recursive_mutex> lock(etiss_libraries_mu_);
928  for (auto iter = etiss_libraries_.begin(); iter != etiss_libraries_.end(); iter++)
929  {
930  libraries_weak.push_back(std::weak_ptr<LibraryInterface>(*iter));
931  }
932  etiss_libraries_.clear();
933  }
934  for (auto iter = libraries_weak.begin(); iter != libraries_weak.end(); iter++)
935  {
936  std::shared_ptr<LibraryInterface> li = iter->lock();
937  if (li.get() != 0)
938  {
939  std::stringstream ss;
940  ss << "Failed to unload library \"" << li.get()->getName() << "\": ";
941  ss << li.use_count() - 1 << " references " << std::endl;
942  etiss::log(etiss::ERROR, ss.str());
943  }
944  }
945  }
946 
947  // check for existing cpu core instances
948  {
949  std::list<std::string> cores = CPUCore::list();
950  if (cores.size() > 0)
951  {
952  for (auto iter = cores.begin(); iter != cores.end(); iter++)
953  {
954  etiss::log(etiss::ERROR, std::string("CPU core has not been deleted before "
955  "etiss::shutdown() call: ") +
956  *iter);
957  }
958  }
959  }
960 
962 }
963 
967 //__attribute__((destructor))
968 static void etiss_check_shutdown()
969 {
970  if (!etiss_shutdownOk)
971  {
972  etiss::log(etiss::ERROR, "To prevent segmentation faults it is neccessary to call "
973  "\"etiss::shutdown();\" at the end of main and free any "
974  "resource acquired through ETISS.");
975  }
976 }
979 {
980  public:
983 
985 {
986  if (po_simpleIni)
987  delete po_simpleIni;
988  etiss::shutdown();
989 }
990 
991 std::string etiss::errorMessage(etiss::int32 code, CPUArch *arch)
992 {
993  if (code <= 0)
994  { // global code
995  const char *msg = etiss::RETURNCODE::getErrorMessages()[code];
996  if (msg == 0)
997  return std::string();
998  return std::string(msg);
999  }
1000  else
1001  { // cpu arch dependent code
1002  if (arch != 0)
1003  {
1004  std::string ret = arch->getName() + ": ";
1006  return ret;
1007  }
1008  else
1009  {
1010  return "Unknown CPU architecture dependent error code.";
1011  }
1012  }
1013 }
1014 
etiss_int32 int32
Definition: 386-GCC.h:81
ETISS_PLUGIN_EXPORT etiss::CPUArch std::map< std::string, std::string > options
create new instance of the CPUArch type at index
void etiss_loadIni(std::string fileName)
Definition: ETISS.cpp:387
boost::program_options::variables_map vm
Definition: ETISS.cpp:66
static class helper_class_etiss_3 helper_class_etiss_3
bool etiss_SIGINT_handler_enabled
Definition: ETISS.cpp:351
static void etiss_shutdown()
Definition: ETISS.cpp:893
void(* etiss_prev_SIGINT_handler)(int)=0
Definition: ETISS.cpp:350
bool etiss_shutdownOk
Definition: ETISS.cpp:912
CSimpleIniA * po_simpleIni
Definition: ETISS.cpp:386
std::string etiss_defaultjit_
Definition: ETISS.cpp:61
static void etiss_check_shutdown()
check if etiss::shutdown() was called before exiting main.
Definition: ETISS.cpp:968
static class helper_class_etiss_2 helper_class_etiss_2
std::recursive_mutex etiss_libraries_mu_
Definition: ETISS.cpp:64
void etiss_SIGINT_handler(int sig)
Definition: ETISS.cpp:353
std::pair< std::string, std::string > inifileload(const std::string &s)
Definition: ETISS.cpp:683
static void etiss_remove_SIGINT()
Definition: ETISS.cpp:370
std::list< std::shared_ptr< etiss::LibraryInterface > > etiss_libraries_
Definition: ETISS.cpp:63
void etiss_loadIniConfigs()
Definition: ETISS.cpp:416
std::vector< std::string > pluginOptions
Definition: ETISS.cpp:67
static class helper_class_etiss_1 helper_class_etiss_1
void etiss_initialize(const std::vector< std::string > &args, bool forced=false)
Definition: ETISS.cpp:694
Header file of the ETISS library.
contains the stressor class that loads and activates faults.
__device__ int
__device__ __2f16 float bool s
do v
Definition: arm_acle.h:76
the interface to translate instructions of and processor architecture
Definition: CPUArch.h:162
std::string getName() const
returns the name of this architecture.
Definition: CPUArch.h:184
static std::list< std::string > list()
returns a list of currently present CPU cores
Definition: CPUCore.cpp:275
static std::pair< std::string, std::string > set_cmd_line_boost(const std::string &s)
Definition: Misc.cpp:388
bool set(const std::string &key, T value)
template function to set the value of a configuration key.
Definition: Misc.h:372
T get(const std::string &key, T default_, bool *default_used=0)
template function to read the value of a configuration key.
Definition: Misc.h:349
void loadIni(std::list< std::string > *files)
creates a simpleIni object which holds the data of the given .ini file.
Definition: ETISS.cpp:399
void loadIniPlugins(std::shared_ptr< etiss::CPUCore > cpu)
loads the plugins given with the previous loaded .ini files
Definition: ETISS.cpp:556
void loadIniJIT(std::shared_ptr< etiss::CPUCore > cpu)
sets the JIT given with the previous loaded .ini files
Definition: ETISS.cpp:665
~Initializer()
Destructor that shutdowns ETISS.
Definition: ETISS.cpp:984
compiler interface for just in time compilation of generated C code
Definition: JIT.h:67
interface class for libraries.
static std::shared_ptr< LibraryInterface > openIntegratedLibrary()
static std::shared_ptr< LibraryInterface > openSharedLibrary(std::string path, std::string name)
base plugin class that provides access to different plugin functions if present
Definition: Plugin.h:77
static bool loadXML(const std::string &file, const int coreID=0)
extracts faults out of the given xml file.
Definition: Stressor.cpp:80
static void clear()
clears the fault map.
Definition: Stressor.cpp:274
replaces __attribute__((destructor)) in a portable way
Definition: ETISS.cpp:907
replaces __attribute__((destructor)) in a portable way
Definition: ETISS.cpp:380
replaces __attribute__((destructor)) in a portable way
Definition: ETISS.cpp:979
std::shared_ptr< etiss::JIT > getDefaultJIT()
Get the default JIT implementation.
Definition: ETISS.cpp:344
bool loadLibrary(std::string path, std::string name)
Load a library.
Definition: ETISS.cpp:288
std::shared_ptr< Plugin > getPlugin(std::string name, std::map< std::string, std::string > options=std::map< std::string, std::string >())
Get a present Plugin plug-in by name.
Definition: ETISS.cpp:241
std::string errorMessage(etiss::int32 code, CPUArch *arch=0)
Get the error message for an error code for a specific CPUArch plug-in.
Definition: ETISS.cpp:991
std::set< std::string > listLibraryPrefixes()
Create a set with strings of the library names.
Definition: ETISS.cpp:333
std::set< std::string > listJITs()
Create a set with all identifier names of the known JIT plug-ins.
Definition: ETISS.cpp:97
void preloadLibraries()
Search and try to load libraries.
Definition: ETISSInit.cpp:192
std::set< std::string > listPlugins()
Create a set with all identifier names of the known plug-ins.
Definition: ETISS.cpp:125
std::shared_ptr< JIT > getJIT(std::string name, std::map< std::string, std::string > options=std::map< std::string, std::string >())
Get a present JIT plug-in by name.
Definition: ETISS.cpp:153
std::shared_ptr< CPUArch > getCPUArch(std::string name, std::map< std::string, std::string > options=std::map< std::string, std::string >())
Get a present CPUArch plug-in by name.
Definition: ETISS.cpp:197
void shutdown()
Shutdown ETISS.
Definition: ETISS.cpp:914
std::set< std::string > listCPUArchs()
Create a set with all identifier names of the known CPUArch plug-ins.
Definition: ETISS.cpp:69
void addLibrary(std::shared_ptr< etiss::LibraryInterface > libInterface)
Add a LibraryInterface to the ETISS environment.
Definition: ETISS.cpp:301
void initialize(std::vector< std::string > &args)
Initialize and configure ETISS.
Definition: ETISS.cpp:881
std::set< std::string > listLibraries()
Create a set with strings of the library names and some information appended in square brackets.
Definition: ETISS.cpp:322
void forceInitialization()
Force the initialization of ETISS.
Definition: ETISS.cpp:886
static std::map< int32_t, Fault > & faults()
Definition: Stressor.cpp:74
BitArray::size_type size_type
Definition: Instruction.cpp:67
void init()
void shutdown()
Page Table Entry (PTE) defines the composition of Page Frame Number (PFN) and relavant flags.
Definition: Benchmark.h:53
std::list< std::string > split(const std::string &str, std::function< size_t(const std::string &, size_t, size_t &)> findsplit)
Definition: Misc.cpp:91
std::string installDir()
Get ETISS installation directory.
Definition: Misc.cpp:583
Verbosity
Enumeration type for the log levels.
Definition: Misc.h:124
@ INFO
Definition: Misc.h:129
@ VERBOSE
Definition: Misc.h:130
@ WARNING
Definition: Misc.h:128
@ ERROR
Definition: Misc.h:127
@ FATALERROR
Definition: Misc.h:126
Configuration & cfg(const std::string &cfgName)
Get reference of the global ETISS configuration object.
Definition: Misc.cpp:560
Verbosity & verbosity()
Get log level reference.
Definition: Misc.cpp:120
void log(Verbosity level, std::string msg)
write log message at the given level.
Definition: Misc.cpp:125
#define NULL
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
Definition: opencl-c-base.h:40