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>
66boost::program_options::variables_map
vm;
67std::vector<std::string>
pluginOptions = {
"plugin.logger.logaddr",
"plugin.logger.logmask",
"plugin.gdbserver.port"};
71 std::set<std::string> ret;
75 if ((*iter).get() != 0)
77 if (!(*iter)->isEmpty())
79 for (
unsigned i = 0; i < (*iter)->countCPUArchs(); i++)
81 std::string jit = (*iter)->nameCPUArch(i);
82 if (ret.find(jit) != ret.end())
99 std::set<std::string> ret;
103 if ((*iter).get() != 0)
105 if (!(*iter)->isEmpty())
107 for (
unsigned i = 0; i < (*iter)->countJITs(); i++)
109 std::string jit = (*iter)->nameJIT(i);
110 if (ret.find(jit) != ret.end())
127 std::set<std::string> ret;
131 if ((*iter).get() != 0)
133 if (!(*iter)->isEmpty())
135 for (
unsigned i = 0; i < (*iter)->countPlugins(); i++)
137 std::string jit = (*iter)->namePlugin(i);
138 if (ret.find(jit) != ret.end())
155 std::shared_ptr<JIT> jit;
160 std::shared_ptr<LibraryInterface> lib = *iter;
165 for (
unsigned i = 0; i < lib->countJITs(); i++)
167 if (lib->nameJIT(i) == name)
172 "\" from library \"" + ujit +
173 "\" [also provided by library \"" + lib->getName() +
"\"]");
181 "Failed to create JIT via library interface \"" + lib->getName() +
"\"");
185 jit = std::shared_ptr<JIT>(ca, [lib](
JIT *j) { lib->deleteJIT(j); });
186 ujit = lib->getName();
199 std::shared_ptr<CPUArch> arch;
204 std::shared_ptr<LibraryInterface> lib = *iter;
209 for (
unsigned i = 0; i < lib->countCPUArchs(); i++)
211 if (lib->nameCPUArch(i) == name)
216 name +
"\" from library \"" + uarch +
217 "\" [also provided by library \"" + lib->getName() +
"\"]");
225 "Failed to create CPUArch via library interface \"" + lib->getName() +
"\"");
229 arch = std::shared_ptr<CPUArch>(ca, [lib](
CPUArch *a) { lib->deleteCPUArch(a); });
230 uarch = lib->getName();
243 std::shared_ptr<Plugin> ptrPlugin;
244 std::string strPluginName;
248 std::shared_ptr<LibraryInterface> lib = *iter;
253 for (
unsigned i = 0; i < lib->countPlugins(); i++)
255 if (lib->namePlugin(i) == name)
257 if (ptrPlugin.get() != 0)
260 "\" from library \"" + strPluginName +
261 "\" [also provided by library \"" + lib->getName() +
"\"]");
269 "Failed to create Plugin via library interface \"" + lib->getName() +
"\"");
273 ptrPlugin = std::shared_ptr<Plugin>(ca, [lib](
Plugin *p) { lib->deletePlugin(p); });
274 strPluginName = lib->getName();
276 strPluginName +
"\"\n");
317 for (
unsigned i = 0; (
etiss_defaultjit_.size() <= 0) && (i < libInterface->countJITs()); i++)
325 std::set<std::string> ret;
328 ret.insert((*iter)->getName() +
"[" + (*iter)->versionInfo() +
"]");
336 std::set<std::string> ret;
339 ret.insert((*iter)->getName());
357 std::cout << std::endl <<
"\033[0;31m" << std::endl;
359 std::cout << std::endl <<
"\033[0m" << std::endl;
363 signal(sig, SIG_DFL);
394 std::cout <<
"Initializer::loadIni(): Failed to load Ini: " << fileName << std::endl;
396 std::cout <<
"Initializer::loadIni(): Ini sucessfully loaded " << fileName << std::endl;
401 std::cout <<
" Load ini file." << std::endl;
406 std::cout <<
"Info: simpleIni already exists!" << std::endl;
409 for (
auto it_files : *files)
422 std::cout <<
" Load Configs from .ini files:" << std::endl;
442 "silent) and 5 (= verbose)");
447 CSimpleIniA::TNamesDepend sections;
449 for (
auto iter_section : sections)
452 if (std::string(iter_section.pItem) !=
"StringConfigurations" &&
453 std::string(iter_section.pItem) !=
"BoolConfigurations" &&
454 std::string(iter_section.pItem) !=
"IntConfigurations")
461 CSimpleIniA::TNamesDepend keys;
463 for (
auto iter_key : keys)
465 std::stringstream message;
466 bool warning =
false;
469 if (std::string(iter_key.pItem) ==
"etiss.loglevel")
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>() <<
",";
489 message <<
" " << iter_key.pItem <<
"=";
492 CSimpleIniA::TNamesDepend values;
493 po_simpleIni->GetAllValues(iter_section.pItem, iter_key.pItem, values);
494 for (
auto iter_value : values)
497 if (std::string(iter_section.pItem) ==
"StringConfigurations")
499 etiss::cfg().
set<std::string>(iter_key.pItem, iter_value.pItem);
501 else if (std::string(iter_section.pItem) ==
"BoolConfigurations")
503 std::string itemval = iter_value.pItem;
504 boost::algorithm::to_lower(itemval);
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;
513 else if (std::string(iter_section.pItem) ==
"IntConfigurations")
515 std::string itemval = iter_value.pItem;
519 val = std::stoll(itemval, &sz, 0);
522 catch (std::invalid_argument
const&){
535 message <<
" Section not found for Value:";
540 message << iter_value.pItem <<
",";
544 if (values.size() > 1)
547 message <<
" Multi values. Take only LAST one!";
558 std::map<std::string, std::string>
options;
563 options[*iter] = std::string(
vm[std::string(*iter)].as<std::string>());
566 "] = " + std::string(
vm[std::string(*iter)].as<std::string>()) +
"\n");
569 if (
vm.count(
"pluginToLoad"))
571 const std::vector<std::string> pluginList =
vm[
"pluginToLoad"].as<std::vector<std::string>>();
572 for (
auto pluginName = pluginList.begin(); pluginName != pluginList.end(); pluginName++)
574 std::string::size_type pos = std::string(*pluginName).length();
575 bool pluginAlreadyPresent =
false;
576 for (
auto iter : *cpu->getPlugins())
578 std::string pluginNamecpu = iter->getPluginName();
579 if (pos != std::string::npos)
581 pluginNamecpu = pluginNamecpu.substr(0, pos);
583 if (pluginNamecpu == *pluginName)
585 pluginAlreadyPresent =
true;
589 if (pluginAlreadyPresent)
598 cpu->addPlugin(plugin);
607 CSimpleIniA::TNamesDepend sections;
609 for (
auto iter_section : sections)
612 if (std::string(iter_section.pItem).substr(0, 6) != std::string(
"Plugin"))
614 std::string pluginName = std::string(iter_section.pItem).substr(7);
615 std::string::size_type pos = pluginName.length();
617 bool pluginAlreadyPresent =
false;
618 for (
auto iter : *cpu->getPlugins())
620 std::string pluginNamecpu = iter->getPluginName();
621 if (pos != std::string::npos)
623 pluginNamecpu = pluginNamecpu.substr(0, pos);
625 if (pluginNamecpu == pluginName)
627 pluginAlreadyPresent =
true;
631 if (pluginAlreadyPresent)
640 CSimpleIniA::TNamesDepend keys;
642 for (
auto iter_key : keys)
645 CSimpleIniA::TNamesDepend values;
646 po_simpleIni->GetAllValues(iter_section.pItem, iter_key.pItem, values);
649 std::stringstream ss;
650 ss << iter_key.pItem <<
" not set on the command line. Checking in .ini file.";
653 for (
auto iter_value : values)
655 options[iter_key.pItem] = iter_value.pItem;
657 " options[" + std::string(iter_key.pItem) +
"] = " + std::string(iter_value.pItem) +
"\n\n");
660 if (values.size() > 1)
667 cpu->addPlugin(plugin);
680 if (cpu->getJITName() !=
"")
683 "etiss::Initializer::loadIniJIT:" + std::string(
" JIT already present. Overwriting it."));
691 if (
s.find(
"-i") == 0)
694 inifile =
s.substr(2);
697 return make_pair(std::string(), std::string());
702 static std::mutex mu_;
703 static bool initialized_(
false);
705 std::lock_guard<std::mutex> lock(mu_);
722 "functions. Please add the line \'etiss::initialize(argc,argv);\' "
723 "at the beginning of \'int main(int argc, char**argv);\'");
730 namespace po = boost::program_options;
733 po::options_description desc(
"Allowed options");
735 (
"help",
"Produce a help message that lists all supported options.")
736 (
"arch.cpu", po::value<std::string>(),
"The CPU Architecture to simulate.")
737 (
"arch.or1k.ignore_sr_iee", po::value<bool>(),
"Ignore exception on OpenRISC.")
738 (
"arch.or1k.if_stall_cycles", po::value<int>(),
"Add instruction stall cycles on OpenRISC.")
739 (
"arch.cpu_cycle_time_ps", po::value<int>(),
"Sets CPU cycles time on OpenRISC and ARM.")
740 (
"arch.enable_semihosting", po::value<bool>(),
"Enables semihosting operations")
741 (
"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.")
742 (
"etiss.log_pc", po::value<bool>(),
"Enables logging of the program counter.")
743 (
"etiss.max_block_size", po::value<int>(),
"Sets maximum amount of instructions in a block.")
744 (
"etiss.output_path_prefix", po::value<std::string>(),
"Path prefix to use when writing output files.")
745 (
"etiss.loglevel", po::value<int>(),
"Verbosity of logging output.")
746 (
"jit.gcc.cleanup", po::value<bool>(),
"Cleans up temporary files in GCCJIT. ")
747 (
"jit.verify", po::value<bool>(),
"Run some basic checks to verify the functionality of the JIT engine.")
748 (
"jit.debug", po::value<bool>(),
"Causes the JIT Engines to compile in debug mode.")
749 (
"jit.type", po::value<std::string>(),
"The JIT compiler to use.")
750 (
"jit.external_headers", po::value<std::string>(),
"List of semicolon-separated paths to headers for the JIT to include.")
751 (
"jit.external_libs", po::value<std::string>(),
"List of semicolon-separated library names for the JIT to link.")
752 (
"jit.external_header_paths", po::value<std::string>(),
"List of semicolon-separated headers paths for the JIT.")
753 (
"jit.external_lib_paths", po::value<std::string>(),
"List of semicolon-separated library paths for the JIT.")
754 (
"vp.sw_binary_ram", po::value<std::string>(),
"Path to binary file to be loaded into RAM.")
755 (
"vp.sw_binary_rom", po::value<std::string>(),
"Path to binary file to be loaded into ROM.")
756 (
"vp.elf_file", po::value<std::string>(),
"Load ELF file.")
757 (
"vp.stats_file_path", po::value<std::string>(),
"Path where the output json file gets stored after bare processor is run.")
758 (
"simple_mem_system.print_dbus_access", po::value<bool>(),
"Traces accesses to the data bus.")
759 (
"simple_mem_system.print_ibus_access", po::value<bool>(),
"Traces accesses to the instruction bus.")
760 (
"simple_mem_system.print_dbgbus_access", po::value<bool>(),
"Traces accesses to the debug bus.")
761 (
"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.")
762 (
"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.")
763 (
"plugin.logger.logmask", po::value<std::string>(),
"Provides the mask that is used to check for memory accesses that are redirected to the logger.")
764 (
"plugin.gdbserver.port", po::value<std::string>(),
"Option for gdbserver")
765 (
"pluginToLoad,p", po::value<std::vector<std::string>>()->multitoken(),
"List of plugins to be loaded.")
768 po::command_line_parser parser{args};
769 po::command_line_parser iniparser{args};
770 iniparser.options(desc).allow_unregistered().extra_parser(
inifileload).run();
772 po::parsed_options parsed_options = parser.run();
773 po::store(parsed_options,
vm);
775 if (
vm.count(
"help"))
777 std::cout <<
"\nPlease begin all options with --\n\n";
778 std::cout << desc <<
"\n";
782 auto unregistered = po::collect_unrecognized(parsed_options.options, po::include_positional);
783 for (
auto iter_unreg : unregistered)
785 if (iter_unreg.find(
"-i") != 0 && iter_unreg.find(
"-p"))
788 "\n\t Please use --help to list all recognised options. \n");
792 for (po::variables_map::iterator i =
vm.begin() ; i !=
vm.end() ; ++ i)
794 const po::variable_value&
v = i->second;
797 const ::std::type_info& type =
v.value().type();
798 if (type ==
typeid(::std::string))
800 const ::std::string& val =
v.as<::std::string>() ;
803 else if (type ==
typeid(
int))
805 int val =
v.as<
int>();
808 else if (type ==
typeid(
bool))
810 bool val =
v.as<
bool>();
816 catch(std::exception& e)
819 "\n\t Please use --help to list all recognised options. \n");
838 "silent) and 5 (= verbose)");
848 if (
cfg().get<bool>(
"etiss.load_integrated_libraries",
true))
856 std::vector<std::string> requiredFiles;
859 requiredFiles.push_back(path +
"/include/jit/etiss/jit/CPU.h");
862 for (
auto iter = requiredFiles.begin(); iter != requiredFiles.end(); iter++)
864 std::ifstream f(iter->c_str());
868 "\t The installation seems broken");
875 std::string faults =
cfg().
get<std::string>(
"faults.xml",
"");
894 std::vector<std::string> args{};
931 std::list<std::weak_ptr<LibraryInterface>> libraries_weak;
936 libraries_weak.push_back(std::weak_ptr<LibraryInterface>(*iter));
940 for (
auto iter = libraries_weak.begin(); iter != libraries_weak.end(); iter++)
942 std::shared_ptr<LibraryInterface> li = iter->lock();
945 std::stringstream ss;
946 ss <<
"Failed to unload library \"" << li.get()->getName() <<
"\": ";
947 ss << li.use_count() - 1 <<
" references " << std::endl;
956 if (cores.size() > 0)
958 for (
auto iter = cores.begin(); iter != cores.end(); iter++)
961 "etiss::shutdown() call: ") +
979 "\"etiss::shutdown();\" at the end of main and free any "
980 "resource acquired through ETISS.");
1001 const char *msg = etiss::RETURNCODE::getErrorMessages()[code];
1003 return std::string();
1004 return std::string(msg);
1010 std::string ret = arch->
getName() +
": ";
1016 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
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::pair< std::string, std::string > inifileload(const std::string &s)
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.
contains the stressor class that loads and activates faults.
__device__ __2f16 float bool s
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 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.
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.
Page Table Entry (PTE) defines the composition of Page Frame Number (PFN) and relavant flags.
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.