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