Browse Source

Added categories to logging

pull/6/head
Eyck Jentzsch 2 years ago
parent
commit
46d79504a8
8 changed files with 399 additions and 26 deletions
  1. 4
    3
      incl/sysc/memory.h
  2. 14
    7
      incl/sysc/report.h
  3. 52
    0
      incl/util/assert.h
  4. 72
    0
      incl/util/ities.h
  5. 50
    15
      incl/util/logging.h
  6. 87
    0
      incl/util/sparse_array.h
  7. 117
    0
      incl/util/thread_syncronizer.h
  8. 3
    1
      src/report.cpp

+ 4
- 3
incl/sysc/memory.h View File

@@ -27,6 +27,7 @@
#define SC_INCLUDE_DYNAMIC_PROCESSES

#include "utilities.h"
#include <sysc/report.h>
#include <tlm.h>
#include <tlm_utils/simple_target_socket.h>

@@ -53,7 +54,7 @@ private:
};

template<unsigned SIZE, unsigned BUSWIDTH, bool LOG_ACCESS>
memory<SIZE,BUSWIDTH,LOG_ACCESS>::memory(const sc_core::sc_module_name& nm):sc_module(nm),SOCKET(socket) {
memory<SIZE,BUSWIDTH,LOG_ACCESS>::memory(const sc_core::sc_module_name& nm):sc_module(nm),NAMED(socket) {
// Register callback for incoming b_transport interface method call
socket.register_b_transport(this, &memory::b_transport);
socket.register_transport_dbg(this, &memory::transport_dbg);
@@ -95,9 +96,9 @@ int memory<SIZE,BUSWIDTH,LOG_ACCESS>::handle_operation(tlm::tlm_generic_payload&
tlm::tlm_command cmd = trans.get_command();
if(LOG_ACCESS){
if(adr>=0x20 && adr<0x60)
LOG(logging::warning)<<(cmd==tlm::TLM_READ_COMMAND?"read":"write")<<" access to addr 0x"<<std::hex<<adr-0x20<<"(0x"<<(adr)<<")"<<std::dec;
LOG(WARNING)<<(cmd==tlm::TLM_READ_COMMAND?"read":"write")<<" access to addr 0x"<<std::hex<<adr-0x20<<"(0x"<<(adr)<<")"<<std::dec;
else
LOG(logging::warning)<<(cmd==tlm::TLM_READ_COMMAND?"read":"write")<<" access to addr 0x"<<std::hex<<adr<<std::dec;
LOG(WARNING)<<(cmd==tlm::TLM_READ_COMMAND?"read":"write")<<" access to addr 0x"<<std::hex<<adr<<std::dec;
}
if (cmd == tlm::TLM_READ_COMMAND)
memcpy(ptr, mem + adr, len);

+ 14
- 7
incl/sysc/report.h View File

@@ -30,6 +30,9 @@
#include <iomanip>


namespace logging {
struct SystemC {};
}
namespace sysc {

namespace log=logging;
@@ -46,6 +49,11 @@ class Log: public logging::Log<T>{
public:
Log(){};


Log(const Log&) = delete;

Log& operator =(const Log&) = delete;

/**
*
* @param level
@@ -63,7 +71,7 @@ public:

};

class FILELOG_DECLSPEC Logger : public Log<logging::Output2FILE> {
class FILELOG_DECLSPEC Logger : public Log<logging::Output2FILE<log::SystemC>> {
static std::once_flag once;
public:
/**
@@ -73,17 +81,16 @@ public:
*/
static logging::log_level& reporting_level(){
std::call_once(once, [](){ init_logging();});
return logging::Log<logging::Output2FILE>::reporting_level();
return logging::Log<logging::Output2FILE<log::SystemC>>::reporting_level();
}
};

}

#undef LOG
#define LOG(level) \
if (level > FILELOG_MAX_LEVEL) ;\
else if (level > logging::Logger::reporting_level() || !logging::Output2FILE::stream()) ; \
else sysc::Logger().get(level)

#define LOG(LEVEL) \
if (logging::LEVEL > FILELOG_MAX_LEVEL) ;\
else if (logging::LEVEL > LOGGER(SystemC)::reporting_level() || !LOG_OUTPUT(SystemC)::stream()) ; \
else LOGGER(SystemC)().get(logging::LEVEL)

#endif /* _SYSC_REPORT_H_ */

+ 52
- 0
incl/util/assert.h View File

@@ -0,0 +1,52 @@
/*******************************************************************************
* Copyright (C) 2017, MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* eyck@minres.com - initial API and implementation
******************************************************************************/

#ifndef _ASSERT_H_
#define _ASSERT_H_

#include <util/logging.h>

#ifndef NDEBUG
# define ASSERT(condition, message) \
do { \
if (! (condition)) { \
LOG(FATAL) << "Assertion `" #condition "` failed in " << __FILE__ << " line " << __LINE__ << ": " << message << std::endl; \
std::terminate(); \
} \
} while (false)
#else
# define ASSERT(condition, message) do { } while (false)
#endif

#endif /* _ASSERT_H_ */

+ 72
- 0
incl/util/ities.h View File

@@ -0,0 +1,72 @@
/*******************************************************************************
* Copyright (C) 2017, MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* eyck@minres.com - initial API and implementation
******************************************************************************/

#ifndef _UTIL_ITIES_H_
#define _UTIL_ITIES_H_

#include <bitset>
#include <type_traits>

//some helper functions
template<unsigned int bit, unsigned int width, typename T>
inline constexpr T bit_sub(T v) {
return (v >> bit) & ((T(1) << width) - 1);
}

template<unsigned int bit, unsigned int width, typename T>
inline constexpr typename std::make_signed<T>::type signed_bit_sub(T v) {
typename std::make_signed<T>::type r = v<<(sizeof(T)*8-bit-width);
typename std::make_signed<T>::type ret = (r >> (sizeof(T)*8-width));
return ret;
}

// according to http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup
static const int MultiplyDeBruijnBitPosition[32] =
{
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
template<size_t N>
constexpr size_t find_first(std::bitset<N>& bits){
static_assert(N<=32, "find_first only supports bitsets smaller than 33");
return MultiplyDeBruijnBitPosition[((uint32_t)((bits.to_ulong() & -bits.to_ulong()) * 0x077CB531U)) >> 27];
}

// according to https://stackoverflow.com/questions/8871204/count-number-of-1s-in-binary-representation
constexpr size_t bit_count(uint32_t u) {
size_t uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111);
return ((uCount + (uCount >> 3)) & 030707070707) % 63;
}

#endif /* _UTIL_ITIES_H_ */

+ 50
- 15
incl/util/logging.h View File

@@ -42,6 +42,7 @@
#include <cstring>
#include <mutex>
#include <stdio.h>
#include <assert.h>
#include <sys/time.h>

#define LEVELS(L) L(NONE) L(FATAL) L(ERROR) L(WARNING) L(INFO) L(DEBUG) L(TRACE)
@@ -53,32 +54,51 @@ namespace logging {
static const char * const buffer[] = { LEVELS(DO_DESCRIPTION)};
enum log_level { LEVELS(DO_ENUM) };

inline
log_level as_log_level(int l){
assert(l>=NONE && l<=TRACE);
const log_level m[]={NONE,FATAL,ERROR,WARNING,INFO,DEBUG,TRACE};
return m[l];
}

inline std::string now_time();

template <typename T>
class Log{
public:
Log(){};

Log(const Log&) = delete;

Log& operator =(const Log&) = delete;

virtual ~Log(){
os << std::endl;
T::output(os.str());
//TODO: use a more specific exception
if(get_last_log_level() == FATAL) throw std::exception();
};
std::ostringstream& get(log_level level = INFO){
os << "- " << now_time();
os << " " << to_string(level) << ": ";
}

std::ostringstream& get(log_level level = INFO, const char* category=""){
if(print_time()) os << "- " << now_time();
if(print_severity()){
os << " " << to_string(level);
if(strlen(category)) os<<"/"<<category;
os<< ": ";
}
get_last_log_level()=level;
return os;
};
public:
static log_level& reporting_level(){
static log_level reportingLevel = WARNING;
return reportingLevel;
}

static std::string to_string(log_level level){
return std::string(get_log_level_cstr()[level]);
};

static log_level from_string(const std::string& level) {
for(unsigned int i=NONE; i<=TRACE; i++)
if(!strncasecmp(level.c_str(), (const char*)(get_log_level_cstr()+i), strlen((const char*)get_log_level_cstr()+i))) return i;
@@ -86,6 +106,15 @@ public:
return INFO;
}

static bool& print_time(){
static bool flag=true;
return flag;
}

static bool& print_severity(){
static bool flag=true;
return flag;
}
protected:
log_level& get_last_log_level(){
static log_level level = TRACE;
@@ -95,12 +124,10 @@ protected:
return buffer;
};
std::ostringstream os;
private:
Log(const Log&);
Log& operator =(const Log&);
};

struct Output2FILE {
template<typename CATEGORY>
struct Output2FILE: CATEGORY {
static FILE*& stream(){
static FILE* pStream = stderr;
return pStream;
@@ -114,6 +141,7 @@ struct Output2FILE {
fflush(pStream);
}
};
class DEFAULT {};

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
# if defined (BUILDING_FILELOG_DLL)
@@ -127,17 +155,24 @@ struct Output2FILE {
# define FILELOG_DECLSPEC
#endif // _WIN32

class FILELOG_DECLSPEC Logger : public Log<Output2FILE> {};
//typedef Log<Output2FILE> Logger;

#ifndef FILELOG_MAX_LEVEL
#define FILELOG_MAX_LEVEL logging::TRACE
#endif

#define LOG(level) \
if (level > FILELOG_MAX_LEVEL) ;\
else if (level > logging::Logger::reporting_level() || !logging::Output2FILE::stream()) ; \
else logging::Logger().get(level)
#define LOGGER(CATEGORY) logging::Log<logging::Output2FILE<logging::CATEGORY>>
#define LOG_OUTPUT(CATEGORY) logging::Output2FILE<logging::CATEGORY>

#define LOG(LEVEL) \
if (logging::LEVEL > FILELOG_MAX_LEVEL) ;\
else if (logging::LEVEL > LOGGER(DEFAULT)::reporting_level() || !LOG_OUTPUT(DEFAULT)::stream()) ; \
else LOGGER(DEFAULT)().get(logging::LEVEL)

#define CLOG(LEVEL, CATEGORY) \
if (logging::LEVEL > FILELOG_MAX_LEVEL) ;\
else if (logging::LEVEL > LOGGER(CATEGORY)::reporting_level() || !LOG_OUTPUT(CATEGORY)::stream()) ; \
else LOGGER(CATEGORY)().get(logging::LEVEL,#CATEGORY)


#if defined(WIN32)


+ 87
- 0
incl/util/sparse_array.h View File

@@ -0,0 +1,87 @@
/*******************************************************************************
* Copyright (C) 2017, MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* eyck@minres.com - initial API and implementation
******************************************************************************/

#ifndef _SPARSE_ARRAY_H_
#define _SPARSE_ARRAY_H_

#include <array>
#include <cassert>

namespace util {

/**
* a simple array which allocates memory in 16MB chunks
*/
template<typename T, uint64_t SIZE, int lower_width=24>
struct sparse_array {

const uint64_t page_addr_mask = (1<<lower_width)-1;

const uint64_t page_size = (1<<lower_width);

const uint64_t page_addr_width = lower_width;

using page_type=std::array<T,1<<lower_width>;


sparse_array(){
arr.fill(nullptr);
}

~sparse_array(){
for(auto i:arr) delete i;
}

T& operator[](uint32_t addr) {
assert(addr<SIZE);
T nr = addr>>lower_width;
if(arr[nr] == nullptr) arr[nr]= new page_type();
return arr[nr]->at(addr & page_addr_mask);
}

page_type& operator()(uint32_t page_nr) {
assert(page_nr<(SIZE/(1<<lower_width)));
if(arr[page_nr] == nullptr) arr[page_nr]= new page_type();
return *(arr[page_nr]);
}

uint64_t size(){return SIZE;}

protected:
std::array<page_type*, SIZE/(1<<lower_width)+1> arr;
};

}

#endif /* _SPARSE_ARRAY_H_ */

+ 117
- 0
incl/util/thread_syncronizer.h View File

@@ -0,0 +1,117 @@
/*******************************************************************************
* Copyright (C) 2017, MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* eyck@minres.com - initial API and implementation
******************************************************************************/
#ifndef _THREAD_SYNCRONIZER_H_
#define _THREAD_SYNCRONIZER_H_


#include <queue>
#include <atomic>
#include <future>
#include <functional>
#include <stdexcept>

class thread_syncronizer {
private:
std::queue< std::function< void() > > tasks_;
std::atomic<bool> ready;
std::mutex mutex_;
std::condition_variable condition_;
public:
/// @brief Constructor.
thread_syncronizer() { }

/// @brief Destructor.
~thread_syncronizer(){
// Set running flag to false then notify all threads.
condition_.notify_all();
}

bool is_ready(){return ready.load(std::memory_order_acquire);}

template<class F, class... Args>
typename std::result_of<F(Args...)>::type enqueue_and_wait(F&& f, Args&&... args) {
auto res = enqueue(f, args...);
res.wait();
return res.get();
}


template<class F, class... Args>
auto enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type> {
using return_type = typename std::result_of<F(Args...)>::type;
auto task = std::make_shared< std::packaged_task<return_type()> >(
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
);

std::future<return_type> res = task->get_future();
{
std::unique_lock<std::mutex> lock(mutex_);
tasks_.emplace([task](){ (*task)(); });
}
condition_.notify_one();
return res;
}
/// @brief execute the next task in queue but do not wait for the next one
void execute(){
if(tasks_.empty()) return ;
{
std::unique_lock< std::mutex > lock( mutex_ );
// Copy task locally and remove from the queue. This is done within
// its own scope so that the task object is destructed immediately
// after running the task. This is useful in the event that the
// function contains shared_ptr arguments bound via bind.
std::function< void() > functor = tasks_.front();
tasks_.pop();
lock.unlock();
// Run the task.
try{
functor();
} catch ( ... ) {} // Suppress all exceptions.
}
}

/// @brief execute the next task in queue or wait for the next one
void executeNext(){
ready.store(true, std::memory_order_release);
// Wait on condition variable while the task is empty
std::unique_lock< std::mutex > lock( mutex_ );
while ( tasks_.empty() && ready.load(std::memory_order_acquire)){
condition_.wait_for(lock, std::chrono::milliseconds(10));
}
lock.unlock();
execute();
ready.store(false, std::memory_order_release);
}
};
#endif /* _THREAD_SYNCRONIZER_H_ */

+ 3
- 1
src/report.cpp View File

@@ -52,7 +52,9 @@ static const std::string compose_message(const sc_report& rep){
static void report_handler(const sc_report& rep, const sc_actions& actions){
const logging::log_level map[] = {logging::INFO, logging::WARNING, logging::ERROR, logging::FATAL};
if ( actions & SC_DISPLAY )
LOG(map[rep.get_severity()]) << compose_message(rep);
if (map[rep.get_severity()] > FILELOG_MAX_LEVEL) ;\
else if (map[rep.get_severity()] > LOGGER(SystemC)::reporting_level() || !LOG_OUTPUT(SystemC)::stream()) ; \
else LOGGER(SystemC)().get(map[rep.get_severity()])<< compose_message(rep);
// if ( (actions & SC_LOG) && log_file_name ) {
// if ( !log_stream ) log_stream = new ::std::ofstream(log_file_name); // ios::trunc
// *log_stream << rep.get_time() << ": " << my_report_compose_message(rep) << ::std::endl;

Loading…
Cancel
Save