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>
49 #include "SimpleIni.h"
59 using namespace etiss;
66 boost::program_options::variables_map
vm;
67 std::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++)
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)
604 CSimpleIniA::TNamesDepend sections;
606 for (
auto iter_section : sections)
609 if (std::string(iter_section.pItem).substr(0, 6) != std::string(
"Plugin"))
611 std::string pluginName = std::string(iter_section.pItem).substr(7);
614 bool pluginAlreadyPresent =
false;
615 for (
auto iter : *cpu->getPlugins())
617 std::string pluginNamecpu = iter->getPluginName();
618 if (pos != std::string::npos)
620 pluginNamecpu = pluginNamecpu.substr(0, pos);
622 if (pluginNamecpu == pluginName)
624 pluginAlreadyPresent =
true;
628 if (pluginAlreadyPresent)
637 CSimpleIniA::TNamesDepend keys;
639 for (
auto iter_key : keys)
642 CSimpleIniA::TNamesDepend values;
643 po_simpleIni->GetAllValues(iter_section.pItem, iter_key.pItem, values);
646 std::stringstream ss;
647 ss << iter_key.pItem <<
" not set on the command line. Checking in .ini file.";
650 for (
auto iter_value : values)
652 options[iter_key.pItem] = iter_value.pItem;
654 " options[" + std::string(iter_key.pItem) +
"] = " + std::string(iter_value.pItem) +
"\n\n");
657 if (values.size() > 1)
674 if (cpu->getJITName() !=
"")
677 "etiss::Initializer::loadIniJIT:" + std::string(
" JIT already present. Overwriting it."));
680 cpu->set(
getJIT(
cfg().get<std::string>(
"jit.type",
"")));
685 if (
s.find(
"-i") == 0)
688 inifile =
s.substr(2);
691 return make_pair(std::string(), std::string());
696 static std::mutex mu_;
697 static bool initialized_(
false);
699 std::lock_guard<std::mutex> lock(mu_);
716 "functions. Please add the line \'etiss::initialize(argc,argv);\' "
717 "at the beginning of \'int main(int argc, char**argv);\'");
724 namespace po = boost::program_options;
727 po::options_description desc(
"Allowed 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.")
763 po::command_line_parser iniparser{
args};
764 iniparser.options(desc).allow_unregistered().extra_parser(
inifileload).run();
766 po::parsed_options parsed_options =
parser.run();
767 po::store(parsed_options,
vm);
769 if (
vm.count(
"help"))
771 std::cout <<
"\nPlease begin all options with --\n\n";
772 std::cout << desc <<
"\n";
776 auto unregistered = po::collect_unrecognized(parsed_options.options, po::include_positional);
777 for (
auto iter_unreg : unregistered)
779 if (iter_unreg.find(
"-i") != 0 && iter_unreg.find(
"-p"))
782 "\n\t Please use --help to list all recognised options. \n");
786 for (po::variables_map::iterator i =
vm.begin() ; i !=
vm.end() ; ++ i)
788 const po::variable_value&
v = i->second;
791 const ::std::type_info&
type =
v.value().type();
792 if (
type ==
typeid(::std::string))
794 const ::std::string& val =
v.as<::std::string>() ;
797 else if (
type ==
typeid(
int))
799 int val =
v.as<
int>();
802 else if (
type ==
typeid(
bool))
804 bool val =
v.as<
bool>();
810 catch(std::exception& e)
813 "\n\t Please use --help to list all recognised options. \n");
832 "silent) and 5 (= verbose)");
842 if (
cfg().get<bool>(
"etiss.load_integrated_libraries",
true))
850 std::vector<std::string> requiredFiles;
853 requiredFiles.push_back(path +
"/include/jit/etiss/jit/CPU.h");
856 for (
auto iter = requiredFiles.begin(); iter != requiredFiles.end(); iter++)
858 std::ifstream f(iter->c_str());
862 "\t The installation seems broken");
869 std::string
faults =
cfg().
get<std::string>(
"faults.xml",
"");
888 std::vector<std::string>
args{};
925 std::list<std::weak_ptr<LibraryInterface>> libraries_weak;
930 libraries_weak.push_back(std::weak_ptr<LibraryInterface>(*iter));
934 for (
auto iter = libraries_weak.begin(); iter != libraries_weak.end(); iter++)
936 std::shared_ptr<LibraryInterface> li = iter->lock();
939 std::stringstream ss;
940 ss <<
"Failed to unload library \"" << li.get()->getName() <<
"\": ";
941 ss << li.use_count() - 1 <<
" references " << std::endl;
950 if (cores.size() > 0)
952 for (
auto iter = cores.begin(); iter != cores.end(); iter++)
955 "etiss::shutdown() call: ") +
973 "\"etiss::shutdown();\" at the end of main and free any "
974 "resource acquired through ETISS.");
995 const char *msg = etiss::RETURNCODE::getErrorMessages()[code];
997 return std::string();
998 return std::string(msg);
1004 std::string ret = arch->
getName() +
": ";
1010 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
static class helper_class_etiss_3 helper_class_etiss_3
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.
static class helper_class_etiss_2 helper_class_etiss_2
std::recursive_mutex etiss_libraries_mu_
void etiss_SIGINT_handler(int sig)
std::pair< std::string, std::string > inifileload(const std::string &s)
static void etiss_remove_SIGINT()
std::list< std::shared_ptr< etiss::LibraryInterface > > etiss_libraries_
void etiss_loadIniConfigs()
std::vector< std::string > pluginOptions
static class helper_class_etiss_1 helper_class_etiss_1
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 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.
static std::map< int32_t, Fault > & faults()
BitArray::size_type size_type
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 installDir()
Get ETISS installation directory.
Verbosity
Enumeration type for the log levels.
Configuration & cfg(const std::string &cfgName)
Get reference of the global ETISS configuration object.
Verbosity & verbosity()
Get log level reference.
void log(Verbosity level, std::string msg)
write log message at the given level.
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.