ETISS 0.8.0
Extendable Translating Instruction Set Simulator (version 0.8.0)
Misc.cpp
Go to the documentation of this file.
1 
52 #define _CRT_SECURE_NO_WARNINGS 1
53 
54 #include "etiss/Misc.h"
55 #include "etiss/Memory.h"
56 
57 #include <cstring>
58 #include <iterator>
59 #include <regex>
60 #include <string>
61 
62 #include <boost/algorithm/string/classification.hpp>
63 #include <boost/algorithm/string/split.hpp>
64 #include <boost/program_options/options_description.hpp>
65 #include <boost/program_options/parsers.hpp>
66 #include <boost/program_options/variables_map.hpp>
67 
68 using namespace etiss;
69 
70 std::string etiss::toString(const Verbosity &val)
71 {
72  switch (val)
73  {
74  case SILENT:
75  return "General";
76  case FATALERROR:
77  return "Fatal Error";
78  case ERROR:
79  return "Error";
80  case WARNING:
81  return "Warning";
82  case INFO:
83  return "Info";
84  case VERBOSE:
85  return "Verbose";
86  default:
87  return "INVALID_VERBOSITY_LEVEL";
88  }
89 }
90 
91 std::list<std::string> etiss::split(
92  const std::string &str,
93  std::function<size_t(const std::string & , size_t , size_t & )> findsplit)
94 {
95  std::list<std::string> ret;
96  size_t find = 0;
97  while (true)
98  {
99  size_t sepsize = std::string::npos;
100  size_t tmpfind = findsplit(str, find, sepsize);
101  if (tmpfind >= find && tmpfind != std::string::npos)
102  {
103  ret.push_back(str.substr(find, tmpfind - find));
104  find = tmpfind + sepsize;
105  }
106  else
107  {
108  if (str.size() > find)
109  {
110  ret.push_back(str.substr(find));
111  }
112  break;
113  }
114  }
115  return ret;
116 }
117 
119 
121 {
122  return etiss_verbosity;
123 }
124 
125 void etiss::log(Verbosity level, std::string msg)
126 {
127  if (level <= etiss_verbosity)
128  {
129  std::cout << "ETISS: " << etiss::toString(level) << ": " << msg << std::endl;
130  }
131  if (level == FATALERROR)
132  {
133  abort();
134  }
135 }
136 void etiss::logC(Verbosity level, std::function<std::string(void)> msgGen)
137 {
138  if (level <= etiss_verbosity)
139  {
140  etiss::log(level, msgGen());
141  }
142 }
143 
144 std::vector<std::string> etiss::parseCommands(const std::string &cmdline)
145 {
146 
147  std::vector<std::string> ret;
148 
149  std::string tmp;
150  unsigned state = 0;
151  for (unsigned pos = 0; pos < cmdline.length(); pos++)
152  {
153  while (true)
154  {
155  switch (state)
156  {
157  case 0:
158  switch (cmdline[pos])
159  {
160  case '\'':
161  case '\"':
162  state = 1;
163  case ' ':
164  case '\t':
165  break;
166  default:
167  state = 2;
168  continue;
169  }
170  break;
171  case 1:
172  switch (cmdline[pos])
173  {
174  case '\'':
175  case '\"':
176  ret.push_back(tmp);
177  tmp = "";
178  state = 0;
179  break;
180  case '\\':
181  if (pos + 1 < cmdline.length())
182  {
183  pos++;
184  tmp = tmp + cmdline[pos];
185  }
186  break;
187  default:
188  tmp = tmp + cmdline[pos];
189  break;
190  }
191  break;
192  case 2:
193  switch (cmdline[pos])
194  {
195  case ' ':
196  case '\t':
197  ret.push_back(tmp);
198  tmp = "";
199  state = 0;
200  break;
201  case '\\':
202  if (pos + 1 < cmdline.length())
203  {
204  pos++;
205  tmp = tmp + cmdline[pos];
206  }
207  break;
208  default:
209  tmp = tmp + cmdline[pos];
210  break;
211  }
212  if (pos + 1 >= cmdline.length())
213  {
214  ret.push_back(tmp);
215  tmp = "";
216  }
217  break;
218  default:
219  std::cerr << "ERROR: etiss::parseCommand(1) parser failed" << std::endl;
220  break;
221  }
222  break;
223  }
224  }
225 
226  return ret;
227 }
228 
231 {
232  std::vector<std::string> vec = etiss::parseCommands(args);
233  std::list<std::string> list;
234  list.insert(list.end(), vec.begin(), vec.end());
235  set(list);
236 }
237 static bool etiss_cfg_inConstructor = false;
238 etiss::Configuration::Configuration(const std::list<std::string> &args)
239 {
241  {
242  set(args);
243  }
244 }
245 
246 std::map<std::string, std::string> &etiss::Configuration::config()
247 {
248  return cfg_;
249 }
250 
251 namespace etiss
252 {
253 
254 template <>
255 std::string Configuration::get<std::string>(const std::string &key, std::string default_, bool *default_used)
256 {
257  {
258  std::lock_guard<std::mutex> lock(mu_);
259  auto find = cfg_.find(key);
260  if (find != cfg_.end())
261  {
262  if (default_used)
263  *default_used = false;
264  return find->second;
265  }
266  }
267 
268  if (this != &etiss::cfg())
269  { // use global config
270  etiss::log(etiss::VERBOSE, std::string("using global configuration for key: ") + key);
271  return etiss::cfg().get<std::string>(key, default_, default_used);
272  }
273  else
274  {
275  if (default_used)
276  *default_used = true;
277  return default_;
278  }
279 }
280 
281 template <>
282 bool Configuration::get<bool>(const std::string &key, bool default_, bool *default_used)
283 {
284  std::string val = get<std::string>(key, default_ ? "true" : "false", default_used);
286  /* c++11 only
287  std::regex rtrue("(\\s*[tT][rR][uU][eE]\\s*)|(\\s*[1-9][0-9]*\\s*)|(\\s*[oO][nN]\\s*)");
288  std::regex rfalse("(\\s*[fF][aA][lL][sS][eE]\\s*)|(\\s*0+\\s*)|(\\s*[oO][fF][fF]\\s*)");
289  if (std::regex_match(val.begin(),val.end(),rtrue)){
290  return true;
291  }
292  if (std::regex_match(val.begin(),val.end(),rfalse)){
293  return false;
294  }
295  */
296 
297  // c++0x
298  if (val == "true" || val == "1" || val == "on")
299  {
300  return true;
301  }
302 
303  if (val == "false" || val == "0" || val == "off")
304  {
305  return false;
306  }
307 
308  etiss::log(etiss::VERBOSE, std::string("failed to parse value (") + val + ") of configuration key (" + key + ").");
309  return default_;
310 }
311 
312 template <>
313 int Configuration::get<int>(const std::string &key, int default_, bool *default_used)
314 {
315  std::string val = get<std::string>(key, toString(default_), default_used);
316  try
317  {
318  return std::stoi(val, 0, 0); // see doc of std::stoi for last 0 parameter
319  }
320  catch (...)
321  {
322  if (default_used)
323  *default_used = true;
325  std::string("failed to parse value (") + val + ") of configuration key (" + key + ").");
326  return default_;
327  }
328 }
329 
330 template <>
331 unsigned Configuration::get<unsigned>(const std::string &key, unsigned default_, bool *default_used)
332 {
333  std::string val = get<std::string>(key, toString(default_), default_used);
334  try
335  {
336  return static_cast<unsigned>(std::stoull(val, 0, 0)); // see doc of std::stoull for last 0 parameter
337  }
338  catch (...)
339  {
340  if (default_used)
341  *default_used = true;
342 
344  std::string("failed to parse value (") + val + ") of configuration key (" + key + ").");
345  return default_;
346  }
347 }
348 template <>
349 uint64_t Configuration::get<uint64_t>(const std::string &key, uint64_t default_, bool *default_used)
350 {
351  std::string val = get<std::string>(key, toString(default_), default_used);
352  try
353  {
354  return std::stoull(val, 0, 0); // see doc of std::stoull for last 0 parameter
355  }
356  catch (...)
357  {
358  if (default_used)
359  *default_used = true;
360 
362  std::string("failed to parse value (") + val + ") of configuration key (" + key + ").");
363  return default_;
364  }
365 }
366 
367 } // end of namespace etiss
368 
370 {
371  return get<bool>("debug", false);
372 }
373 
374 void etiss::Configuration::remove(const std::string &key)
375 {
376  std::lock_guard<std::mutex> lock(mu_);
377  if (final_.find(key) != final_.end())
378  return;
379  cfg_.erase(key);
380 }
381 
382 bool etiss::Configuration::isSet(std::string key)
383 {
384  std::lock_guard<std::mutex> lock(mu_);
385  return cfg_.find(key) != cfg_.end();
386 }
387 
388 std::pair<std::string, std::string> etiss::Configuration::set_cmd_line_boost(const std::string& s)
389 {
390  namespace po = boost::program_options;
392  if (s.length() > 2)
393  {
394  if (s.find("-f") == 0)
395  {
396  size_t epos = s.find_first_of('=');
397  if (s.length() > 5 && s.substr(2, 3) == "no-")
398  {
399  if (epos == std::string::npos)
400  {
401  std::string tmp = s.substr(5);
402  if (sobj.isSet(tmp))
403  etiss::log(etiss::WARNING, "CONFIG " + tmp + " already set. Overwriting it to false.");
404  etiss::log(etiss::VERBOSE, std::string("CONFIG: set ") + tmp + " to false");
405  etiss::cfg().set<bool>(tmp, "false");
406  return make_pair(tmp, std::string("false"));
407  }
408  else
409  { // unusual case. assuming option shall be erased. value after '=' is ignored
410  std::string tmp = s.substr(5, epos - 5);
411  sobj.remove(tmp);
412  etiss::log(etiss::VERBOSE, std::string("CONFIG: removed ") + tmp);
413  return make_pair(std::string(), std::string());
414  }
415  }
416  else
417  {
418  if (epos == std::string::npos)
419  {
420  std::string tmp = s.substr(2);
421  if (sobj.isSet(tmp))
422  etiss::log(etiss::WARNING, "CONFIG " + tmp + " already set. Overwriting it to true.");
423  etiss::log(etiss::VERBOSE, std::string("CONFIG: set ") + tmp + " to true");
424  etiss::cfg().set<bool>(tmp, "true");
425  return make_pair(s.substr(2), std::string("true"));
426  }
427  else
428  {
429  std::string tmp = s.substr(2, epos - 2);
430  std::string tval = s.substr(epos + 1);
431  if (sobj.isSet(tmp))
432  etiss::log(etiss::WARNING, "CONFIG " + tmp + " already set. Overwriting it to " + tval);
433  etiss::log(etiss::VERBOSE, std::string("CONFIG: set ") + tmp + " to " + tval);
434  return make_pair(s.substr(2), tval);
435  }
436  return make_pair(std::string(), std::string());
437  }
438  }
439  }
440  return make_pair(std::string(), std::string());
441 }
442 
443 
444 std::list<std::string> etiss::Configuration::set(const std::list<std::string> &args)
445 {
446  std::list<std::string> ret;
447  for (auto iter = args.begin(); iter != args.end(); iter++)
448  {
449  const std::string &p = *iter;
450  bool used = false;
451  if (p.length() > 2)
452  {
453  if (p[0] == '-' && p[1] == 'f')
454  {
455  used = true;
456 
457  size_t epos = p.find_first_of('=');
458 
459  if (p.length() > 5 && p[2] == 'n' && p[3] == 'o' && p[4] == '-')
460  {
461  if (epos == std::string::npos)
462  {
463  std::string tmp = p.substr(5);
464  if (isSet(tmp))
465  etiss::log(etiss::WARNING, "CONFIG " + tmp + " already set. Overwriting it to false.");
466  set<std::string>(tmp, "false");
467  etiss::log(etiss::VERBOSE, std::string("CONFIG: set ") + tmp + " to false");
468  }
469  else
470  { // unusual case. assuming option shall be erased. value after '=' is ignored
471  std::string tmp = p.substr(5, epos - 5);
472  remove(tmp);
473  etiss::log(etiss::VERBOSE, std::string("CONFIG: removed ") + tmp);
474  }
475  }
476  else
477  {
478  if (epos == std::string::npos)
479  {
480  std::string tmp = p.substr(2);
481  if (isSet(tmp))
482  etiss::log(etiss::WARNING, "CONFIG " + tmp + " already set. Overwriting it to true.");
483  set<std::string>(tmp, "true");
484  etiss::log(etiss::VERBOSE, std::string("CONFIG: set ") + tmp + " to true");
485  }
486  else
487  {
488  std::string tmp = p.substr(2, epos - 2);
489  std::string tval = p.substr(epos + 1);
490  if (isSet(tmp))
491  etiss::log(etiss::WARNING, "CONFIG " + tmp + " already set. Overwriting it to " + tval);
492  set<std::string>(tmp, tval);
493  etiss::log(etiss::VERBOSE, std::string("CONFIG: set ") + tmp + " to " + tval);
494  }
495  }
496  }
497  if (p[0] == '-' && p[1] == 'o')
498  {
499  used = true;
500  std::string tmp = p.substr(2);
501  iter++;
502  if (iter != args.end())
503  {
504  if (isSet(tmp))
505  etiss::log(etiss::WARNING, "CONFIG " + tmp + " already set. Overwriting it to " + *iter);
506  set<std::string>(tmp, *iter);
507  }
508  else
509  {
510  etiss::log(etiss::WARNING, std::string("Expected option value after " + p));
511  }
512  }
513  }
514  if (!used)
515  {
516  ret.push_back(p);
517  }
518  }
519  return ret;
520 }
521 
522 std::map<std::string, std::string> etiss::Configuration::listFullConfiguration()
523 {
524  if (this != &etiss::cfg())
525  {
526  std::map<std::string, std::string> ret = etiss::cfg().cfg_; // copy global config
527 
528  // apply local config
529  for (auto iter = cfg_.begin(); iter != cfg_.end(); iter++)
530  {
531  ret[iter->first] = iter->second;
532  }
533 
534  return ret;
535  }
536  else
537  {
538  return cfg_;
539  }
540 }
541 
542 void etiss::Configuration::makeFinal(const std::string &key)
543 {
544  std::lock_guard<std::mutex> lock(mu_);
545  final_.insert(key);
546 }
547 
548 void etiss::Configuration::announce(std::string key, std::string type, std::string values, std::string description)
549 {
550  std::lock_guard<std::mutex> lock(mu_);
551  announced_[key] = std::tuple<std::string, std::string, std::string>(type, values, description);
552 }
553 
554 std::map<std::string, std::tuple<std::string, std::string, std::string>> etiss::Configuration::getAnnounced() const
555 {
556  std::lock_guard<std::mutex> lock(mu_);
557  return announced_;
558 }
559 
560 etiss::Configuration &etiss::cfg(const std::string &cfgName)
561 {
562  std::string cfgName_ = cfgName;
563  if (cfgName.empty())
564  {
565  etiss::log(etiss::WARNING, "Config name is empty take global!");
566  cfgName_ = "global";
567  }
569  static std::map<std::string, etiss::Configuration> cfg;
570  if (cfg.find(cfgName_) == cfg.end())
571  {
572  etiss::log(etiss::INFO, std::string("Created new config container: ") + cfgName_);
573  }
574  etiss_cfg_inConstructor = false;
575  return cfg[cfgName_];
576 }
578 {
579  std::string cfgName = "global";
580  return etiss::cfg(cfgName);
581 }
582 
583 std::string etiss::installDir()
584 {
585  auto etissLib = GetCurrentModulePath();
586  auto libPathLoc = etissLib.find_last_of("/\\");
587  auto libPath = etissLib.substr(0, libPathLoc);
588  auto etissPathLoc = libPath.find_last_of("/\\");
589  return libPath.substr(0, etissPathLoc);
590 }
591 
592 std::string etiss::jitFiles()
593 {
594  return installDir() + "/include/jit";
595 }
596 
597 std::vector<std::string> etiss::jitExtHeaders(){
598  std::vector<std::string> x;
599  std::string range = cfg().get<std::string>("jit.external_headers", "");
600  boost::split(x, range, boost::is_any_of(";, "));
601  return (x);
602 }
603 
604 std::vector<std::string> etiss::jitExtLibraries(){
605  std::vector<std::string> x;
606  std::string range = cfg().get<std::string>("jit.external_libs", "");
607  boost::split(x, range, boost::is_any_of(";, "));
608  return (x);
609 }
610 
611 std::vector<std::string> etiss::jitExtHeaderPaths(){
612  std::vector<std::string> x;
613  std::string range = cfg().get<std::string>("jit.external_header_paths", "");
614  boost::split(x, range, boost::is_any_of(";, "));
615  return (x);
616 }
617 
618 std::vector<std::string> etiss::jitExtLibPaths(){
619  std::vector<std::string> x;
620  std::string range = cfg().get<std::string>("jit.external_lib_paths", "");
621  boost::split(x, range, boost::is_any_of(";, "));
622  return (x);
623 }
624 
625 // IMPORTANT: check if fpu configuration matches endianness
626 #include "etiss/fpu/386-GCC.h"
627 #if ETISS_USE_CONSTEXPR
628 #ifdef LITTLEENDIAN
630  "ETISS detected an invalid endianness configuartion of the floating point library. please change in the "
631  "file etiss/fpu/386-GCC.h the line #define LITTLEENDIAN (or similar) to #define BIGENDIAN");
632 #endif
633 #ifdef BIGENDIAN
635  "ETISS detected an invalid endianness configuartion of the floating point library. please change in the "
636  "file etiss/fpu/386-GCC.h the line #define BIGENDIAN (or similar) to #define LITTLEENDIAN");
637 #endif
638 #else
639 #pragma message("ETISS cannot check if endianess is configured correctly due to missing constexpr support")
640 #endif
this file was derived from the 386-GCC.h file provided with John Hauser's Softfloat 2b library
#define static_assert(x, y)
Definition: Fault.cpp:60
Verbosity etiss_verbosity
Definition: Misc.cpp:118
static bool etiss_cfg_inConstructor
Definition: Misc.cpp:237
general configuration and logging
__device__ __2f16 float bool s
static __inline__ uint64_t
Definition: arm_cde.h:31
simple class to hold configuration options
Definition: Misc.h:333
std::map< std::string, std::string > & config()
access to the configuration key value map
Definition: Misc.cpp:246
void announce(std::string key, std::string type=std::string(), std::string values=std::string(), std::string description=std::string())
add a possible option to a list.
Definition: Misc.cpp:548
std::map< std::string, std::string > listFullConfiguration()
get a copy of the configuration as a map
Definition: Misc.cpp:522
static std::pair< std::string, std::string > set_cmd_line_boost(const std::string &s)
Definition: Misc.cpp:388
void makeFinal(const std::string &key)
makes an option final (option can no longer be changed)
Definition: Misc.cpp:542
std::map< std::string, std::tuple< std::string, std::string, std::string > > getAnnounced() const
get a map copy with announced options
Definition: Misc.cpp:554
bool isSet(std::string val)
return true if the value of an configuration key has been set
Definition: Misc.cpp:382
bool debug()
Get the value of the key "debug".
Definition: Misc.cpp:369
void remove(const std::string &key)
removes a key value mapping
Definition: Misc.cpp:374
bool set(const std::string &key, T value)
template function to set the value of a configuration key.
Definition: Misc.h:372
std::map< std::string, std::string > cfg_
Definition: Misc.h:478
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
Page Table Entry (PTE) defines the composition of Page Frame Number (PFN) and relavant flags.
Definition: Benchmark.h:53
std::vector< std::string > parseCommands(const std::string &cmdline)
Definition: Misc.cpp:144
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 jitFiles()
Get ETISS JIT files path.
Definition: Misc.cpp:592
void logC(Verbosity level, std::function< std::string(void)> msgGen)
write log message at the given level.
Definition: Misc.cpp:136
std::vector< std::string > jitExtLibPaths()
Get ETISS JIT external path.
Definition: Misc.cpp:618
std::string toString(const T &val)
conversion of type T to std::string.
Definition: Misc.h:174
std::string GetCurrentModulePath()
Returns the abolute path with filename to the own dynamic library.
Definition: Memory.cpp:117
std::string installDir()
Get ETISS installation directory.
Definition: Misc.cpp:583
@ _LITTLE_ENDIAN_
Definition: Misc.h:526
@ _BIG_ENDIAN_
Definition: Misc.h:527
std::vector< std::string > jitExtLibraries()
Get ETISS JIT external libraries.
Definition: Misc.cpp:604
std::vector< std::string > jitExtHeaders()
Get ETISS JIT external headers.
Definition: Misc.cpp:597
std::vector< std::string > jitExtHeaderPaths()
Get ETISS JIT external path.
Definition: Misc.cpp:611
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
@ SILENT
Definition: Misc.h:125
Configuration & cfg(const std::string &cfgName)
Get reference of the global ETISS configuration object.
Definition: Misc.cpp:560
endian_t getEndianness()
evaluates the endianness of the current build as a constexpr.
Definition: Misc.h:542
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