ETISS 0.8.0
Extendable Translating Instruction Set Simulator (version 0.8.0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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
68using namespace etiss;
69
70std::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
91std::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
124
125void 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}
136void 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
144std::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}
237static bool etiss_cfg_inConstructor = false;
238etiss::Configuration::Configuration(const std::list<std::string> &args)
239{
241 {
242 set(args);
243 }
244}
245
246std::map<std::string, std::string> &etiss::Configuration::config()
247{
248 return cfg_;
249}
250
251namespace etiss
252{
253
254template <>
255std::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
281template <>
282bool 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
312template <>
313int 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
330template <>
331unsigned 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}
348template <>
349uint64_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
374void 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
382bool etiss::Configuration::isSet(std::string key)
383{
384 std::lock_guard<std::mutex> lock(mu_);
385 return cfg_.find(key) != cfg_.end();
386}
387
388std::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
444std::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
522std::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
542void etiss::Configuration::makeFinal(const std::string &key)
543{
544 std::lock_guard<std::mutex> lock(mu_);
545 final_.insert(key);
546}
547
548void 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
554std::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
560etiss::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 }
575 return cfg[cfgName_];
576}
578{
579 std::string cfgName = "global";
580 return etiss::cfg(cfgName);
581}
582
583std::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
592std::string etiss::jitFiles()
593{
594 return installDir() + "/include/jit";
595}
596
597std::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
604std::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
611std::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
618std::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
629static_assert(getEndianness() == etiss::_LITTLE_ENDIAN_,
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
634static_assert(getEndianness() == etiss::_BIG_ENDIAN_,
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
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 Configuration::get< std::string >(const std::string &key, std::string default_, bool *default_used)
Definition Misc.cpp:255
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
endian_t getEndianness()
evaluates the endianness of the current build as a constexpr.
Definition Misc.h:542
Configuration & cfg()
Definition Misc.cpp:577
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