Browse Source

Extended logging

Added ability to
* capture std::cout/std::cerr
* have a debug trace level
* configure the logger wrt. aborting in case of fatal error
pull/3/head
Eyck Jentzsch 1 year ago
parent
commit
5aae421a6f
3 changed files with 110 additions and 16 deletions
  1. +24
    -0
      incl/scc/report.h
  2. +17
    -10
      incl/util/logging.h
  3. +69
    -6
      src/report.cpp

+ 24
- 0
incl/scc/report.h View File

@@ -26,6 +26,7 @@

namespace logging {
class SystemC {};
class STDIO {};
}
namespace scc {

@@ -102,6 +103,16 @@ template <sc_core::sc_severity SEVERITY> struct ScLogger {
this->t = const_cast<char *>(t);
return *this;
}
/**
* set the category of the log entry
*
* @param t
* @return
*/
inline ScLogger &type(const std::string& t) {
this->t = const_cast<char *>(t.c_str());
return *this;
}
/**
* return the underlying ostringstream
*
@@ -140,6 +151,19 @@ protected:
//! macro for fatal message output
#define SCFATAL(...) \
::scc::ScLogger<::sc_core::SC_FATAL>(__FILE__, __LINE__, sc_core::SC_MEDIUM).type(__VA_ARGS__).get()

inline std::string padded(std::string str, size_t width, bool show_ellipsis=true) {
assert(width>7);
if (str.length() > width) {
if (show_ellipsis){
auto pos = str.size()-(width-6);
return str.substr(0, 3) + "..."+str.substr(pos, str.size()-pos);
} else
return str.substr(0, width);
} else {
return str+std::string(width-str.size(), ' ');
}
}
}

#endif /* _SYSC_REPORT_H_ */

+ 17
- 10
incl/util/logging.h View File

@@ -14,8 +14,7 @@
* limitations under the License.
*******************************************************************************/

#ifndef _UTIL_LOGGING_H_
#define _UTIL_LOGGING_H_
#pragma once

#include <cassert>
#include <cstdio>
@@ -29,13 +28,13 @@
#include <vector>

//! log level definitions
#define LEVELS(L) L(NONE) L(FATAL) L(ERROR) L(WARNING) L(INFO) L(DEBUG) L(TRACE)
#define LEVELS(L) L(NONE) L(FATAL) L(ERROR) L(WARNING) L(INFO) L(DEBUG) L(TRACE) L(DBGTRACE)
#define DO_DESCRIPTION(e) #e,
#define DO_ENUM(e) e,

namespace logging {
//! array holding string representations of log levels
static std::array<const char *const, 7> buffer = {{LEVELS(DO_DESCRIPTION)}};
static std::array<const char *const, 8> buffer = {{LEVELS(DO_DESCRIPTION)}};
//! enum defining the log levels
enum log_level { LEVELS(DO_ENUM) };
/**
@@ -45,7 +44,7 @@ enum log_level { LEVELS(DO_ENUM) };
*/
inline log_level as_log_level(int logLevel) {
assert(logLevel >= NONE && logLevel <= TRACE);
std::array<const log_level, 7> m = {{NONE, FATAL, ERROR, WARNING, INFO, DEBUG, TRACE}};
std::array<const log_level, 8> m = {{NONE, FATAL, ERROR, WARNING, INFO, DEBUG, TRACE, DBGTRACE}};
return m[logLevel];
}
/**
@@ -82,7 +81,7 @@ public:
os << std::endl;
T::output(os.str());
// TODO: use a more specific exception
if (get_last_log_level() == FATAL) abort();
if (get_last_log_level() == FATAL && abort_on_fatal()) throw std::runtime_error(os.str());
}
/**
* get the underlying ostringstream for a certain log level and category
@@ -96,7 +95,7 @@ public:
if (print_severity()) {
os << std::setw(7) << std::left << to_string(level);
if (strlen(category)) os << "[" << category << "]";
os << ": ";
os << ": "<<std::internal;
}
get_last_log_level() = level;
return os;
@@ -110,6 +109,15 @@ public:
static log_level reportingLevel = WARNING;
return reportingLevel;
}
/**
* get a reference to the abort on fatal flag
*
* @return the logging level
*/
static bool &abort_on_fatal() {
static bool flag = false;
return flag;
}
/**
* translate a lg level to a string
*
@@ -262,7 +270,7 @@ template <typename T> std::ostream &operator<<(std::ostream &stream, const std::

#ifndef NDEBUG
//! check only in debug mode
#define ASSERT(condition, message) \
#define SCCASSERT(condition, message) \
do { \
if (!(condition)) { \
logging::Logger().Get(logging::fatal) << "Assertion `" #condition "` failed in " << __FILE__ << " line " \
@@ -271,7 +279,7 @@ template <typename T> std::ostream &operator<<(std::ostream &stream, const std::
} \
} while (false)
#else
#define ASSERT(condition, message) \
#define SCCASSERT(condition, message) \
do { \
} while (false)
#endif
@@ -285,4 +293,3 @@ template <typename T> std::ostream &operator<<(std::ostream &stream, const std::
} \
} while (false)

#endif /* _UTIL_LOGGING_H_ */

+ 69
- 6
src/report.cpp View File

@@ -1,4 +1,3 @@
#include <array>
/*******************************************************************************
* Copyright 2017, 2018 MINRES Technologies GmbH
*
@@ -21,12 +20,35 @@
* Author: ubuntu
*/

#include "scc/report.h"
#include <scc/report.h>
#include <tuple>
#include <array>

using namespace sc_core;
using namespace logging;

namespace {
std::tuple<sc_core::sc_time::value_type, sc_core::sc_time_unit> get_tuple(const sc_core::sc_time& t){
auto val = t.value();
auto tr = (uint64_t)(sc_core::sc_time::from_value(1).to_seconds()*1E15);
auto scale = 0U;
while( ( tr % 10 ) == 0 ) {
tr /= 10;
scale++;
}
sc_assert( tr == 1 );

auto tu = scale / 3;
while( tu < SC_SEC && ( val % 10 ) == 0 ) {
val /= 10;
scale++;
tu += ( 0 == ( scale % 3 ) );
}
for( scale %= 3; scale != 0 ; scale-- )
val *= 10;
return std::make_tuple(val, static_cast<sc_time_unit>( tu ));
}

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,
@@ -36,12 +58,12 @@ std::string time2string(const sc_core::sc_time &t) {
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) {
if (!t.value()) {
oss << "0 s";
} else {
const unsigned scale = tt.unit();
const auto tt = get_tuple(t);
const auto val = std::get<0>(tt);
const auto scale = std::get<1>(tt);
const auto fs_val = val * multiplier[scale];
for (int j = multiplier.size() - 1; j >= scale; --j) {
if (fs_val > multiplier[j]) {
@@ -94,6 +116,42 @@ void report_handler(const sc_report &rep, const sc_actions &actions) {
if (actions & SC_ABORT) abort();
if (actions & SC_THROW) throw rep;
}

class log_stream_buf: public std::stringbuf {
public:
log_stream_buf(std::ostream& os, logging::log_level level):os(os), level(level){
old_buf=os.rdbuf(this); //save and redirect
}
~log_stream_buf(){
os.rdbuf(old_buf); // restore
}
void reset(){
os.rdbuf(old_buf); // restore
old_buf=nullptr;
}
protected:
std::streamsize xsputn(const char_type* s, std::streamsize n) override {
auto sz = std::stringbuf::xsputn(s, n);
if (s[n-1]=='\n'){
if(logging::INFO <= Log<Output2FILE<STDIO>>::reporting_level() && Output2FILE<STDIO>::stream()){
auto timestr = time2string(sc_core::sc_time_stamp());
std::istringstream buf(str());
std::string line;
while(getline(buf, line)) {
Log<Output2FILE<STDIO>>().get(logging::INFO, "") << "[" << std::setw(20) << timestr << "] "<<line;
}
}
str(std::string(""));
//setp(pbase(), epptr());
}
return sz;
}
std::ostream& os;
logging::log_level level;
std::streambuf* old_buf;
};
log_stream_buf cout_redirect(std::cout, logging::INFO);
log_stream_buf cerr_redirect(std::cerr, logging::ERROR);
}

void scc::init_logging(logging::log_level level, bool print_time) {
@@ -105,8 +163,13 @@ void scc::init_logging(logging::log_level level, bool print_time) {
SC_HIGH, // logging::DEBUG
SC_FULL, // logging::TRACE
SC_DEBUG}; // logging::TRACE+1
LOGGER(DEFAULT)::reporting_level() = level;
LOGGER(SystemC)::reporting_level() = level;
LOGGER(SystemC)::print_time() = print_time;
LOGGER(SystemC)::abort_on_fatal() = false;
sc_report_handler::set_verbosity_level(verbosity[level]);
sc_report_handler::set_handler(report_handler);
LOGGER(STDIO)::reporting_level() = level;
LOGGER(STDIO)::print_time() = print_time;
LOGGER(STDIO)::abort_on_fatal() = false;
}

Loading…
Cancel
Save