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
Eyck Jentzsch 8 months 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 @@
26 26
 
27 27
 namespace logging {
28 28
 class SystemC {};
29
+class STDIO {};
29 30
 }
30 31
 namespace scc {
31 32
 
@@ -103,6 +104,16 @@ template <sc_core::sc_severity SEVERITY> struct ScLogger {
103 104
         return *this;
104 105
     }
105 106
     /**
107
+     * set the category of the log entry
108
+     *
109
+     * @param t
110
+     * @return
111
+     */
112
+    inline ScLogger &type(const std::string& t) {
113
+        this->t = const_cast<char *>(t.c_str());
114
+        return *this;
115
+    }
116
+    /**
106 117
      * return the underlying ostringstream
107 118
      *
108 119
      * @return the output stream collecting the log message
@@ -140,6 +151,19 @@ protected:
140 151
 //! macro for fatal message output
141 152
 #define SCFATAL(...)                                                                                                   \
142 153
     ::scc::ScLogger<::sc_core::SC_FATAL>(__FILE__, __LINE__, sc_core::SC_MEDIUM).type(__VA_ARGS__).get()
154
+
155
+inline std::string padded(std::string str, size_t width, bool show_ellipsis=true) {
156
+    assert(width>7);
157
+    if (str.length() > width) {
158
+        if (show_ellipsis){
159
+            auto pos = str.size()-(width-6);
160
+            return str.substr(0, 3) + "..."+str.substr(pos, str.size()-pos);
161
+        } else
162
+            return str.substr(0, width);
163
+    } else {
164
+        return str+std::string(width-str.size(), ' ');
165
+    }
166
+}
143 167
 }
144 168
 
145 169
 #endif /* _SYSC_REPORT_H_ */

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

@@ -14,8 +14,7 @@
14 14
  * limitations under the License.
15 15
  *******************************************************************************/
16 16
 
17
-#ifndef _UTIL_LOGGING_H_
18
-#define _UTIL_LOGGING_H_
17
+#pragma once
19 18
 
20 19
 #include <cassert>
21 20
 #include <cstdio>
@@ -29,13 +28,13 @@
29 28
 #include <vector>
30 29
 
31 30
 //! log level definitions
32
-#define LEVELS(L) L(NONE) L(FATAL) L(ERROR) L(WARNING) L(INFO) L(DEBUG) L(TRACE)
31
+#define LEVELS(L) L(NONE) L(FATAL) L(ERROR) L(WARNING) L(INFO) L(DEBUG) L(TRACE) L(DBGTRACE)
33 32
 #define DO_DESCRIPTION(e) #e,
34 33
 #define DO_ENUM(e) e,
35 34
 
36 35
 namespace logging {
37 36
 //! array holding string representations of log levels
38
-static std::array<const char *const, 7> buffer = {{LEVELS(DO_DESCRIPTION)}};
37
+static std::array<const char *const, 8> buffer = {{LEVELS(DO_DESCRIPTION)}};
39 38
 //! enum defining the log levels
40 39
 enum log_level { LEVELS(DO_ENUM) };
41 40
 /**
@@ -45,7 +44,7 @@ enum log_level { LEVELS(DO_ENUM) };
45 44
  */
46 45
 inline log_level as_log_level(int logLevel) {
47 46
     assert(logLevel >= NONE && logLevel <= TRACE);
48
-    std::array<const log_level, 7> m = {{NONE, FATAL, ERROR, WARNING, INFO, DEBUG, TRACE}};
47
+    std::array<const log_level, 8> m = {{NONE, FATAL, ERROR, WARNING, INFO, DEBUG, TRACE, DBGTRACE}};
49 48
     return m[logLevel];
50 49
 }
51 50
 /**
@@ -82,7 +81,7 @@ public:
82 81
         os << std::endl;
83 82
         T::output(os.str());
84 83
         // TODO: use a more specific exception
85
-        if (get_last_log_level() == FATAL) abort();
84
+        if (get_last_log_level() == FATAL && abort_on_fatal()) throw std::runtime_error(os.str());
86 85
     }
87 86
     /**
88 87
      * get the underlying ostringstream for a certain log level and category
@@ -96,7 +95,7 @@ public:
96 95
         if (print_severity()) {
97 96
             os << std::setw(7) << std::left << to_string(level);
98 97
             if (strlen(category)) os << "[" << category << "]";
99
-            os << ": ";
98
+            os << ": "<<std::internal;
100 99
         }
101 100
         get_last_log_level() = level;
102 101
         return os;
@@ -111,6 +110,15 @@ public:
111 110
         return reportingLevel;
112 111
     }
113 112
     /**
113
+     * get a reference to the abort on fatal flag
114
+     *
115
+     * @return the logging level
116
+     */
117
+    static bool &abort_on_fatal() {
118
+        static bool flag = false;
119
+        return flag;
120
+    }
121
+    /**
114 122
      * translate a lg level to a string
115 123
      *
116 124
      * @param level the log level
@@ -262,7 +270,7 @@ template <typename T> std::ostream &operator<<(std::ostream &stream, const std::
262 270
 
263 271
 #ifndef NDEBUG
264 272
 //! check only in debug mode
265
-#define ASSERT(condition, message)                                                                                     \
273
+#define SCCASSERT(condition, message)                                                                                     \
266 274
     do {                                                                                                               \
267 275
         if (!(condition)) {                                                                                            \
268 276
             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::
271 279
         }                                                                                                              \
272 280
     } while (false)
273 281
 #else
274
-#define ASSERT(condition, message)                                                                                     \
282
+#define SCCASSERT(condition, message)                                                                                     \
275 283
     do {                                                                                                               \
276 284
     } while (false)
277 285
 #endif
@@ -285,4 +293,3 @@ template <typename T> std::ostream &operator<<(std::ostream &stream, const std::
285 293
         }                                                                                                              \
286 294
     } while (false)
287 295
 
288
-#endif /* _UTIL_LOGGING_H_ */

+ 69
- 6
src/report.cpp View File

@@ -1,4 +1,3 @@
1
-#include <array>
2 1
 /*******************************************************************************
3 2
  * Copyright 2017, 2018 MINRES Technologies GmbH
4 3
  *
@@ -21,12 +20,35 @@
21 20
  *      Author: ubuntu
22 21
  */
23 22
 
24
-#include "scc/report.h"
23
+#include <scc/report.h>
24
+#include <tuple>
25
+#include <array>
25 26
 
26 27
 using namespace sc_core;
27 28
 using namespace logging;
28 29
 
29 30
 namespace {
31
+std::tuple<sc_core::sc_time::value_type, sc_core::sc_time_unit> get_tuple(const sc_core::sc_time& t){
32
+    auto val = t.value();
33
+    auto tr  = (uint64_t)(sc_core::sc_time::from_value(1).to_seconds()*1E15);
34
+    auto scale = 0U;
35
+    while( ( tr % 10 ) == 0 ) {
36
+        tr /= 10;
37
+        scale++;
38
+    }
39
+    sc_assert( tr == 1 );
40
+
41
+    auto tu = scale / 3;
42
+    while( tu < SC_SEC && ( val % 10 ) == 0 ) {
43
+        val /= 10;
44
+        scale++;
45
+        tu += ( 0 == ( scale % 3 ) );
46
+    }
47
+    for( scale %= 3; scale != 0 ; scale-- )
48
+        val *= 10;
49
+    return std::make_tuple(val, static_cast<sc_time_unit>( tu ));
50
+}
51
+
30 52
 std::string time2string(const sc_core::sc_time &t) {
31 53
     const std::array<const char *, 6> time_units{"fs", "ps", "ns", "us", "ms", "s "};
32 54
     const std::array<uint64_t, 6> multiplier{1ULL,
@@ -36,12 +58,12 @@ std::string time2string(const sc_core::sc_time &t) {
36 58
                                              1000ULL * 1000 * 1000 * 1000,
37 59
                                              1000ULL * 1000 * 1000 * 1000 * 1000};
38 60
     std::ostringstream oss;
39
-    const sc_core::sc_time_tuple tt{t};
40
-    const auto val = tt.value();
41
-    if (!val) {
61
+    if (!t.value()) {
42 62
         oss << "0 s";
43 63
     } else {
44
-        const unsigned scale = tt.unit();
64
+        const auto tt = get_tuple(t);
65
+        const auto val = std::get<0>(tt);
66
+        const auto scale = std::get<1>(tt);
45 67
         const auto fs_val = val * multiplier[scale];
46 68
         for (int j = multiplier.size() - 1; j >= scale; --j) {
47 69
             if (fs_val > multiplier[j]) {
@@ -94,6 +116,42 @@ void report_handler(const sc_report &rep, const sc_actions &actions) {
94 116
     if (actions & SC_ABORT) abort();
95 117
     if (actions & SC_THROW) throw rep;
96 118
 }
119
+
120
+class log_stream_buf: public std::stringbuf {
121
+public:
122
+    log_stream_buf(std::ostream& os, logging::log_level level):os(os), level(level){
123
+        old_buf=os.rdbuf(this); //save and redirect
124
+    }
125
+    ~log_stream_buf(){
126
+        os.rdbuf(old_buf); // restore
127
+    }
128
+    void reset(){
129
+        os.rdbuf(old_buf); // restore
130
+        old_buf=nullptr;
131
+    }
132
+protected:
133
+    std::streamsize xsputn(const char_type* s, std::streamsize n) override {
134
+        auto sz = std::stringbuf::xsputn(s, n);
135
+        if (s[n-1]=='\n'){
136
+            if(logging::INFO <= Log<Output2FILE<STDIO>>::reporting_level() && Output2FILE<STDIO>::stream()){
137
+                auto timestr = time2string(sc_core::sc_time_stamp());
138
+                std::istringstream buf(str());
139
+                std::string line;
140
+                while(getline(buf, line)) {
141
+                    Log<Output2FILE<STDIO>>().get(logging::INFO, "") << "[" << std::setw(20) << timestr << "] "<<line;
142
+                }
143
+            }
144
+            str(std::string(""));
145
+            //setp(pbase(), epptr());
146
+        }
147
+        return sz;
148
+    }
149
+    std::ostream& os;
150
+    logging::log_level level;
151
+    std::streambuf* old_buf;
152
+};
153
+log_stream_buf cout_redirect(std::cout, logging::INFO);
154
+log_stream_buf cerr_redirect(std::cerr, logging::ERROR);
97 155
 }
98 156
 
99 157
 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) {
105 163
                                           SC_HIGH,   // logging::DEBUG
106 164
                                           SC_FULL,   // logging::TRACE
107 165
                                           SC_DEBUG}; // logging::TRACE+1
166
+    LOGGER(DEFAULT)::reporting_level() = level;
108 167
     LOGGER(SystemC)::reporting_level() = level;
109 168
     LOGGER(SystemC)::print_time() = print_time;
169
+    LOGGER(SystemC)::abort_on_fatal() = false;
110 170
     sc_report_handler::set_verbosity_level(verbosity[level]);
111 171
     sc_report_handler::set_handler(report_handler);
172
+    LOGGER(STDIO)::reporting_level() = level;
173
+    LOGGER(STDIO)::print_time() = print_time;
174
+    LOGGER(STDIO)::abort_on_fatal() = false;
112 175
 }