116 lines
3.8 KiB
C++
116 lines
3.8 KiB
C++
/*
|
|
* logging.cpp
|
|
*
|
|
* Created on: 24.12.2018
|
|
* Author: eyck
|
|
*/
|
|
|
|
|
|
#include <systemc>
|
|
#include <deque>
|
|
#include <array>
|
|
#include <sstream>
|
|
#include <iomanip>
|
|
#include "logging_.h"
|
|
|
|
using namespace sc_core;
|
|
|
|
enum log_level {NONE, FATAL, ERROR, WARNING, INFO, DEBUG, TRACE};
|
|
|
|
namespace {
|
|
|
|
static std::deque<std::string> msg_buf;
|
|
|
|
inline log_level verbosity2log(int verb) {
|
|
if (verb >= sc_core::SC_FULL) return TRACE;
|
|
if (verb >= sc_core::SC_HIGH) return DEBUG;
|
|
return INFO;
|
|
}
|
|
|
|
std::string time2string(const sc_core::sc_time &t) {
|
|
const std::array<const char *, 6> time_units{"fs", "ps", "ns", "us", "ms", "s "};
|
|
const std::array<uint64_t, 6> multiplier{1ULL,
|
|
1000ULL,
|
|
1000ULL * 1000,
|
|
1000ULL * 1000 * 1000,
|
|
1000ULL * 1000 * 1000 * 1000,
|
|
1000ULL * 1000 * 1000 * 1000 * 1000};
|
|
std::ostringstream oss;
|
|
const sc_core::sc_time_tuple tt{t};
|
|
const auto val = tt.value();
|
|
if (!val) {
|
|
oss << "0 s";
|
|
} else {
|
|
const unsigned scale = tt.unit();
|
|
const auto fs_val = val * multiplier[scale];
|
|
for (int j = multiplier.size() - 1; j >= scale; --j) {
|
|
if (fs_val > multiplier[j]) {
|
|
const auto i = val / multiplier[j - scale];
|
|
const auto f = val % multiplier[j - scale];
|
|
oss << i << '.' << std::setw(3 * (j - scale)) << std::setfill('0') << std::left << f << ' '
|
|
<< time_units[j];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return oss.str();
|
|
}
|
|
|
|
const std::string compose_message(const sc_report &rep) {
|
|
std::stringstream os;
|
|
os << "[" << std::setw(20) << time2string(sc_core::sc_time_stamp()) << "] ";
|
|
if (rep.get_id() >= 0)
|
|
os << "("
|
|
<< "IWEF"[rep.get_severity()] << rep.get_id() << ") ";
|
|
os << rep.get_msg_type();
|
|
if (*rep.get_msg()) os << ": " << rep.get_msg();
|
|
if (rep.get_severity() > SC_INFO) {
|
|
std::array<char, 16> line_number_str;
|
|
os << " [FILE:" << rep.get_file_name() << ":" << rep.get_line_number() << "]";
|
|
sc_simcontext *simc = sc_get_curr_simcontext();
|
|
if (simc && sc_is_running()) {
|
|
const char *proc_name = rep.get_process_name();
|
|
if (proc_name) os << "[PROCESS:" << proc_name << "]";
|
|
}
|
|
}
|
|
return os.str();
|
|
}
|
|
|
|
void report_handler(const sc_report &rep, const sc_actions &actions) {
|
|
std::array<const log_level, 4> map = {{INFO, WARNING, ERROR, FATAL}};
|
|
if (actions & SC_DISPLAY) {
|
|
auto level = rep.get_severity() > sc_core::SC_INFO ? map[rep.get_severity()] : verbosity2log(rep.get_verbosity());
|
|
msg_buf.push_back(compose_message(rep));
|
|
}
|
|
if (actions & SC_STOP) sc_stop();
|
|
if (actions & SC_ABORT) abort();
|
|
if (actions & SC_THROW) throw rep;
|
|
}
|
|
}
|
|
|
|
bool has_output(){
|
|
return !msg_buf.empty();
|
|
}
|
|
|
|
std::string get_output(){
|
|
std::string ret = msg_buf.front();
|
|
msg_buf.pop_front();
|
|
return ret;
|
|
}
|
|
|
|
void init_logging(unsigned level) {
|
|
const std::array<int, 8> verbosity = {SC_NONE, // Logging::NONE
|
|
SC_LOW, // Logging::FATAL
|
|
SC_LOW, // Logging::ERROR
|
|
SC_LOW, // Logging::WARNING
|
|
SC_MEDIUM, // Logging::INFO
|
|
SC_HIGH, // logging::DEBUG
|
|
SC_FULL, // logging::TRACE
|
|
SC_DEBUG}; // logging::TRACE+1
|
|
sc_report_handler::set_verbosity_level(verbosity[level]);
|
|
sc_report_handler::set_handler(report_handler);
|
|
}
|
|
|
|
|
|
|