26#include <boost/program_options/options_description.hpp>
27#include <boost/program_options/parsers.hpp>
28#include <boost/program_options/variables_map.hpp>
29#include <boost/algorithm/string.hpp>
48boost::program_options::variables_map
vm;
49std::vector<std::string>
pluginOptions = {
"plugin.logger.logaddr",
"plugin.logger.logmask",
"plugin.gdbserver.port" };
53 std::set<std::string> ret;
57 if ((*iter).get() != 0)
59 if (!(*iter)->isEmpty())
61 for (
unsigned i = 0; i < (*iter)->countCPUArchs(); i++)
63 std::string jit = (*iter)->nameCPUArch(i);
64 if (ret.find(jit) != ret.end())
81 std::set<std::string> ret;
85 if ((*iter).get() != 0)
87 if (!(*iter)->isEmpty())
89 for (
unsigned i = 0; i < (*iter)->countJITs(); i++)
91 std::string jit = (*iter)->nameJIT(i);
92 if (ret.find(jit) != ret.end())
109 std::set<std::string> ret;
113 if ((*iter).get() != 0)
115 if (!(*iter)->isEmpty())
117 for (
unsigned i = 0; i < (*iter)->countPlugins(); i++)
119 std::string jit = (*iter)->namePlugin(i);
120 if (ret.find(jit) != ret.end())
137 std::shared_ptr<JIT> jit;
142 std::shared_ptr<LibraryInterface> lib = *iter;
147 for (
unsigned i = 0; i < lib->countJITs(); i++)
149 if (lib->nameJIT(i) == name)
154 "\" from library \"" + ujit +
155 "\" [also provided by library \"" + lib->getName() +
"\"]");
163 "Failed to create JIT via library interface \"" + lib->getName() +
"\"");
167 jit = std::shared_ptr<JIT>(ca, [lib](
JIT *j) { lib->deleteJIT(j); });
168 ujit = lib->getName();
181 std::shared_ptr<CPUArch> arch;
186 std::shared_ptr<LibraryInterface> lib = *iter;
191 for (
unsigned i = 0; i < lib->countCPUArchs(); i++)
193 if (lib->nameCPUArch(i) == name)
198 name +
"\" from library \"" + uarch +
199 "\" [also provided by library \"" + lib->getName() +
"\"]");
207 "Failed to create CPUArch via library interface \"" + lib->getName() +
"\"");
211 arch = std::shared_ptr<CPUArch>(ca, [lib](
CPUArch *a) { lib->deleteCPUArch(a); });
212 uarch = lib->getName();
225 std::shared_ptr<Plugin> ptrPlugin;
226 std::string strPluginName;
230 std::shared_ptr<LibraryInterface> lib = *iter;
235 for (
unsigned i = 0; i < lib->countPlugins(); i++)
237 if (lib->namePlugin(i) == name)
239 if (ptrPlugin.get() != 0)
242 "\" from library \"" + strPluginName +
243 "\" [also provided by library \"" + lib->getName() +
"\"]");
251 "Failed to create Plugin via library interface \"" + lib->getName() +
"\"");
255 ptrPlugin = std::shared_ptr<Plugin>(ca, [lib](
Plugin *p) { lib->deletePlugin(p); });
256 strPluginName = lib->getName();
258 strPluginName +
"\"\n");
299 for (
unsigned i = 0; (
etiss_defaultjit_.size() <= 0) && (i < libInterface->countJITs()); i++)
307 std::set<std::string> ret;
310 ret.insert((*iter)->getName() +
"[" + (*iter)->versionInfo() +
"]");
318 std::set<std::string> ret;
321 ret.insert((*iter)->getName());
339 std::cout << std::endl <<
"\033[0;31m" << std::endl;
341 std::cout << std::endl <<
"\033[0m" << std::endl;
345 signal(sig, SIG_DFL);
376 std::cout <<
"Initializer::loadIni(): Failed to load Ini: " << fileName << std::endl;
378 std::cout <<
"Initializer::loadIni(): Ini sucessfully loaded " << fileName << std::endl;
383 std::cout <<
" Load ini file." << std::endl;
388 std::cout <<
"Info: simpleIni already exists!" << std::endl;
391 for (
auto it_files : *files)
405 std::cout <<
" Load Configs from .ini files:" << std::endl;
426 "silent) and 5 (= verbose)");
431 CSimpleIniA::TNamesDepend sections;
433 for (
auto iter_section : sections)
436 if (std::string(iter_section.pItem) !=
"StringConfigurations" &&
437 std::string(iter_section.pItem) !=
"BoolConfigurations" &&
438 std::string(iter_section.pItem) !=
"IntConfigurations")
445 CSimpleIniA::TNamesDepend keys;
447 for (
auto iter_key : keys)
449 std::stringstream message;
450 bool warning =
false;
453 if (std::string(iter_key.pItem) ==
"etiss.loglevel")
459 message <<
" cfg already set on command line. ";
460 message <<
" " << iter_key.pItem <<
"=";
461 const ::std::type_info &type =
vm[std::string(iter_key.pItem)].value().type();
462 if (type ==
typeid(::std::string))
463 message <<
vm[std::string(iter_key.pItem)].as<std::string>() <<
",";
464 else if (type ==
typeid(
int))
465 message <<
vm[std::string(iter_key.pItem)].as<
int>() <<
",";
466 else if (type ==
typeid(
bool))
467 message << std::boolalpha <<
vm[std::string(iter_key.pItem)].as<
bool>() <<
",";
473 message <<
" " << iter_key.pItem <<
"=";
476 CSimpleIniA::TNamesDepend values;
477 po_simpleIni->GetAllValues(iter_section.pItem, iter_key.pItem, values);
478 for (
auto iter_value : values)
481 if (std::string(iter_section.pItem) ==
"StringConfigurations")
483 etiss::cfg().
set<std::string>(iter_key.pItem, iter_value.pItem);
485 else if (std::string(iter_section.pItem) ==
"BoolConfigurations")
487 std::string itemval = iter_value.pItem;
488 boost::algorithm::to_lower(itemval);
490 if ((itemval ==
"true") || (itemval ==
"yes") || (itemval ==
"1") || (itemval ==
"t"))
494 else if ((itemval ==
"false") || (itemval ==
"no") || (itemval ==
"0") || (itemval ==
"f"))
500 " could not be parsed as boolean");
502 else if (std::string(iter_section.pItem) ==
"IntConfigurations")
504 std::string itemval = iter_value.pItem;
509 val = std::stoll(itemval, &sz, 0);
512 catch (std::invalid_argument
const &)
515 " could not be parsed as integer");
527 message <<
" Section not found for Value:";
532 message << iter_value.pItem <<
",";
536 if (values.size() > 1)
539 message <<
" Multi values. Take only LAST one!";
550 std::map<std::string, std::string>
options;
555 options[*iter] = std::string(
vm[std::string(*iter)].as<std::string>());
558 "] = " + std::string(
vm[std::string(*iter)].as<std::string>()) +
"\n");
561 if (
vm.count(
"pluginToLoad"))
563 const std::vector<std::string> pluginList =
vm[
"pluginToLoad"].as<std::vector<std::string>>();
564 for (
auto pluginName = pluginList.begin(); pluginName != pluginList.end(); pluginName++)
566 std::string::size_type pos = std::string(*pluginName).length();
567 bool pluginAlreadyPresent =
false;
568 for (
auto iter : *cpu->getPlugins())
570 std::string pluginNamecpu = iter->getPluginName();
571 if (pos != std::string::npos)
573 pluginNamecpu = pluginNamecpu.substr(0, pos);
575 if (pluginNamecpu == *pluginName)
577 pluginAlreadyPresent =
true;
581 if (pluginAlreadyPresent)
590 cpu->addPlugin(plugin);
599 CSimpleIniA::TNamesDepend sections;
601 for (
auto iter_section : sections)
604 if (std::string(iter_section.pItem).substr(0, 6) != std::string(
"Plugin"))
606 std::string pluginName = std::string(iter_section.pItem).substr(7);
607 std::string::size_type pos = pluginName.length();
609 bool pluginAlreadyPresent =
false;
610 for (
auto iter : *cpu->getPlugins())
612 std::string pluginNamecpu = iter->getPluginName();
613 if (pos != std::string::npos)
615 pluginNamecpu = pluginNamecpu.substr(0, pos);
617 if (pluginNamecpu == pluginName)
619 pluginAlreadyPresent =
true;
623 if (pluginAlreadyPresent)
632 CSimpleIniA::TNamesDepend keys;
634 for (
auto iter_key : keys)
637 CSimpleIniA::TNamesDepend values;
638 po_simpleIni->GetAllValues(iter_section.pItem, iter_key.pItem, values);
641 std::stringstream ss;
642 ss << iter_key.pItem <<
" not set on the command line. Checking in .ini file.";
645 for (
auto iter_value : values)
647 options[iter_key.pItem] = iter_value.pItem;
649 "] = " + std::string(iter_value.pItem) +
"\n\n");
652 if (values.size() > 1)
659 cpu->addPlugin(plugin);
672 if (cpu->getJITName() !=
"")
675 "etiss::Initializer::loadIniJIT:" + std::string(
" JIT already present. Overwriting it."));
683 static std::mutex mu_;
684 static bool initialized_(
false);
686 std::lock_guard<std::mutex> lock(mu_);
703 "functions. Please add the line \'etiss::initialize(argc,argv);\' "
704 "at the beginning of \'int main(int argc, char**argv);\'");
711 namespace po = boost::program_options;
715 po::options_description desc(
"Allowed options");
717 (
"help",
"Produce a help message that lists all supported options.")
718 (
"ini,i", po::value<std::vector<std::string>>(),
"INI file(s)")
719 (
"arch.cpu", po::value<std::string>(),
"The CPU Architecture to simulate.")
720 (
"arch.or1k.ignore_sr_iee", po::value<bool>(),
"Ignore exception on OpenRISC.")
721 (
"arch.or1k.if_stall_cycles", po::value<int>(),
"Add instruction stall cycles on OpenRISC.")
722 (
"arch.cpu_cycle_time_ps", po::value<int>(),
"Sets CPU cycles time on OpenRISC and ARM.")
723 (
"arch.enable_semihosting", po::value<bool>(),
"Enables semihosting operations")
724 (
"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.")
725 (
"etiss.log_pc", po::value<bool>(),
"Enables logging of the program counter.")
726 (
"etiss.max_block_size", po::value<int>(),
"Sets maximum amount of instructions in a block.")
727 (
"etiss.output_path_prefix", po::value<std::string>(),
"Path prefix to use when writing output files.")
728 (
"etiss.loglevel", po::value<int>(),
"Verbosity of logging output.")
729 (
"etiss.log_to_stderr", po::value<bool>(),
"Log to stderr instead of stdout.")
730 (
"jit.gcc.cleanup", po::value<bool>(),
"Cleans up temporary files in GCCJIT. ")
731 (
"jit.gcc.opt_level", po::value<std::string>(),
"GCCJIT optimization level (0/1/2/3/s/fast=default). ")
732 (
"jit.verify", po::value<bool>(),
"Run some basic checks to verify the functionality of the JIT engine.")
733 (
"jit.debug", po::value<bool>(),
"Causes the JIT Engines to compile in debug mode.")
734 (
"jit.type", po::value<std::string>(),
"The JIT compiler to use.")
735 (
"jit.external_headers", po::value<std::string>(),
"List of semicolon-separated paths to headers for the JIT to include.")
736 (
"jit.external_libs", po::value<std::string>(),
"List of semicolon-separated library names for the JIT to link.")
737 (
"jit.external_header_paths", po::value<std::string>(),
"List of semicolon-separated headers paths for the JIT.")
738 (
"jit.external_lib_paths", po::value<std::string>(),
"List of semicolon-separated library paths for the JIT.")
739 (
"vp.sw_binary_ram", po::value<std::string>(),
"Path to binary file to be loaded into RAM.")
740 (
"vp.sw_binary_rom", po::value<std::string>(),
"Path to binary file to be loaded into ROM.")
741 (
"vp.elf_file", po::value<std::string>(),
"Load ELF file.")
742 (
"vp.stats_file_path", po::value<std::string>(),
"Path where the output json file gets stored after bare processor is run.")
743 (
"vp.quiet", po::value<std::string>(),
"Disable logging of bare_etiss_processor.")
744 (
"faults.xml", po::value<std::string>(),
"Path to faults XML file.")
745 (
"simple_mem_system.print_dbus_access", po::value<bool>(),
"Traces accesses to the data bus.")
746 (
"simple_mem_system.print_ibus_access", po::value<bool>(),
"Traces accesses to the instruction bus.")
747 (
"simple_mem_system.print_dbgbus_access", po::value<bool>(),
"Traces accesses to the debug bus.")
748 (
"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.")
749 (
"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.")
750 (
"plugin.logger.logmask", po::value<std::string>(),
"Provides the mask that is used to check for memory accesses that are redirected to the logger.")
751 (
"plugin.gdbserver.port", po::value<std::string>(),
"Option for gdbserver")
752 (
"pluginToLoad,p", po::value<std::vector<std::string>>()->multitoken(),
"List of plugins to be loaded.")
756 po::command_line_parser parser{ args };
757 po::command_line_parser iniparser{ args };
759 po::parsed_options parsed_options = parser.run();
760 po::store(parsed_options,
vm);
762 if (
vm.count(
"help"))
764 std::cout <<
"\nPlease begin all options with --\n\n";
765 std::cout << desc <<
"\n";
767 std::string(
"Please choose the right configurations from the list and re-run.\n"));
772 auto files =
vm[
"ini"].as<std::vector<std::string>>();
773 for (
auto const &f : files)
779 auto unregistered = po::collect_unrecognized(parsed_options.options, po::include_positional);
780 for (
auto iter_unreg : unregistered)
782 if (iter_unreg.find(
"-i") != 0 && iter_unreg.find(
"-p"))
785 "\n\t Please use --help to list all recognised options. \n");
789 for (po::variables_map::iterator i =
vm.begin(); i !=
vm.end(); ++i)
791 const po::variable_value &
v = i->second;
794 const ::std::type_info &type =
v.value().type();
795 if (type ==
typeid(::std::string))
797 const ::std::string &val =
v.as<::std::string>();
800 else if (type ==
typeid(
int))
802 int val =
v.as<
int>();
805 else if (type ==
typeid(
bool))
807 bool val =
v.as<
bool>();
813 catch (std::exception &e)
816 std::string(e.what()) +
"\n\t Please use --help to list all recognised options. \n");
835 "silent) and 5 (= verbose)");
851 if (
cfg().get<bool>(
"etiss.load_integrated_libraries",
true))
859 std::vector<std::string> requiredFiles;
862 requiredFiles.push_back(path +
"/include/jit/etiss/jit/CPU.h");
865 for (
auto iter = requiredFiles.begin(); iter != requiredFiles.end(); iter++)
867 std::ifstream f(iter->c_str());
871 std::string(
"Could not find file: ") + *iter +
"\n" +
"\t The installation seems broken");
884 std::vector<std::string> args{};
916 mount_successful =
true;
919 if (!mount_successful)
922 std::string(
"'s VirtualStruct, but failed: etiss::CPUCore not created!"));
927 std::string(
"'s VirtualStruct to root VirtualStruct"));
930 std::string faults =
cfg().
get<std::string>(
"faults.xml",
"");
934 for (
const auto &ff : ffs)
937 if (!stressor_successful)
940 std::string(
"\' for ") + cpu_core->getName() + std::string(
"."));
945 cpu_core->getName() + std::string(
"."));
950 std::string(
". Required for etiss::fault::Injector."));
951 cpu_core->addPlugin(std::make_shared<etiss::plugin::InstructionAccurateCallback>());
958 std::string & )>
const &fcustom_action)
961 cpu_core->getStruct()->applyCustomAction = fcustom_action;
975 std::list<std::weak_ptr<LibraryInterface>> libraries_weak;
980 libraries_weak.push_back(std::weak_ptr<LibraryInterface>(*iter));
984 for (
auto iter = libraries_weak.begin(); iter != libraries_weak.end(); iter++)
986 std::shared_ptr<LibraryInterface> li = iter->lock();
989 std::stringstream ss;
990 ss <<
"Failed to unload library \"" << li.get()->getName() <<
"\": ";
991 ss << li.use_count() - 1 <<
" references " << std::endl;
1000 if (cores.size() > 0)
1002 for (
auto iter = cores.begin(); iter != cores.end(); iter++)
1005 "etiss::shutdown() call: ") +
1023 "\"etiss::shutdown();\" at the end of main and free any "
1024 "resource acquired through ETISS.");
1045 const char *msg = etiss::RETURNCODE::getErrorMessages()[code];
1047 return std::string();
1048 return std::string(msg);
1054 std::string ret = arch->
getName() +
": ";
1060 return "Unknown CPU architecture dependent error code.";
ETISS_PLUGIN_EXPORT etiss::CPUArch std::map< std::string, std::string > options
create new instance of the CPUArch type at index
contains neccesary interfaces for instruction translation.
defines main cpu core interface
void etiss_loadIni(std::string fileName)
boost::program_options::variables_map vm
bool etiss_SIGINT_handler_enabled
static void etiss_shutdown()
void(* etiss_prev_SIGINT_handler)(int)=0
CSimpleIniA * po_simpleIni
std::string etiss_defaultjit_
static void etiss_check_shutdown()
check if etiss::shutdown() was called before exiting main.
std::recursive_mutex etiss_libraries_mu_
void etiss_SIGINT_handler(int sig)
static void etiss_remove_SIGINT()
std::list< std::shared_ptr< etiss::LibraryInterface > > etiss_libraries_
void etiss_loadIniConfigs()
std::vector< std::string > pluginOptions
void etiss_initialize(const std::vector< std::string > &args, bool forced=false)
Header file of the ETISS library.
class for simple library access.
contains the stressor class that loads and activates faults.
the interface to translate instructions of and processor architecture
std::string getName() const
returns the name of this architecture.
static std::list< std::string > list()
returns a list of currently present CPU cores
static std::pair< std::string, std::string > set_cmd_line_boost(const std::string &s)
bool isSet(std::string val)
return true if the value of an configuration key has been set
bool set(const std::string &key, T value)
template function to set the value of a configuration key.
T get(const std::string &key, T default_, bool *default_used=0)
template function to read the value of a configuration key.
void loadIni(std::list< std::string > *files)
creates a simpleIni object which holds the data of the given .ini file.
void loadIniPlugins(std::shared_ptr< etiss::CPUCore > cpu)
loads the plugins given with the previous loaded .ini files
void loadIniJIT(std::shared_ptr< etiss::CPUCore > cpu)
sets the JIT given with the previous loaded .ini files
~Initializer()
Destructor that shutdowns ETISS.
compiler interface for just in time compilation of generated C code
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
static std::shared_ptr< VirtualStruct > root()
static bool loadXML(const std::string &file, const int coreID=0)
extracts faults out of the given xml file.
static void clear()
clears the fault map.
replaces __attribute__((destructor)) in a portable way
replaces __attribute__((destructor)) in a portable way
replaces __attribute__((destructor)) in a portable way
std::shared_ptr< etiss::JIT > getDefaultJIT()
Get the default JIT implementation.
bool loadLibrary(std::string path, std::string name)
Load a library.
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.
std::string errorMessage(etiss::int32 code, CPUArch *arch=0)
Get the error message for an error code for a specific CPUArch plug-in.
std::set< std::string > listLibraryPrefixes()
Create a set with strings of the library names.
std::set< std::string > listJITs()
Create a set with all identifier names of the known JIT plug-ins.
void preloadLibraries()
Search and try to load libraries.
std::set< std::string > listPlugins()
Create a set with all identifier names of the known plug-ins.
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.
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.
void shutdown()
Shutdown ETISS.
std::set< std::string > listCPUArchs()
Create a set with all identifier names of the known CPUArch plug-ins.
void addLibrary(std::shared_ptr< etiss::LibraryInterface > libInterface)
Add a LibraryInterface to the ETISS environment.
void initialize(std::vector< std::string > &args)
Initialize and configure ETISS.
void initialize_virtualstruct(std::shared_ptr< etiss::CPUCore > cpu_core)
Initialize and configure etiss::VirtualStruct root with etiss::CPUCore cpu_core.
std::set< std::string > listLibraries()
Create a set with strings of the library names and some information appended in square brackets.
void forceInitialization()
Force the initialization of ETISS.
std::list< std::string > split(const std::string &str, std::function< size_t(const std::string &, size_t, size_t &)> findsplit)
std::string Configuration::get< std::string >(const std::string &key, std::string default_, bool *default_used)
std::string installDir()
Get ETISS installation directory.
Verbosity
Enumeration type for the log levels.
Verbosity & verbosity()
Get log level reference.
void log(Verbosity level, std::string msg)
write log message at the given level.