From 09815a661ec65271dde1be66013546fa07747fd0 Mon Sep 17 00:00:00 2001 From: daniel-k Date: Wed, 6 Dec 2017 20:58:27 +0100 Subject: [PATCH] rough implementation of a C++ style logger class with many sharp edges :) --- fpga/include/villas/log.hpp | 95 +++++++++++++++++++++++++++++++++++++ fpga/lib/CMakeLists.txt | 1 + fpga/lib/card.cpp | 32 ++++++++----- fpga/lib/ip.cpp | 16 ++++--- fpga/lib/log.cpp | 26 ++++++++++ 5 files changed, 150 insertions(+), 20 deletions(-) create mode 100644 fpga/include/villas/log.hpp create mode 100644 fpga/lib/log.cpp diff --git a/fpga/include/villas/log.hpp b/fpga/include/villas/log.hpp new file mode 100644 index 000000000..ed4d65bad --- /dev/null +++ b/fpga/include/villas/log.hpp @@ -0,0 +1,95 @@ +#pragma once + +#include +#include + +class LoggerIndent; + +class Logger { + friend LoggerIndent; +public: + + class LoggerNewline { + public: + LoggerNewline(bool enabled = true) : enabled(enabled) {} + ~LoggerNewline() { + if(enabled) + std::cout << std::endl; + } + template + LoggerNewline& operator<< (T const& value) { + if(enabled) + std::cout << value; + return *this; + } + bool enabled; + }; + + class Indenter { + public: + Indenter(Logger* l) : logger(l) + { logger->increaseIndention(); } + + ~Indenter() + { logger->decreaseIndention(); } + private: + Logger* logger; + }; + + Logger(int level, std::string prefix = "") : level(level), prefix(prefix) {} + + Indenter indent() + { return Indenter(this); } + + static std::string + getPadding() + { + std::string out = ""; + for(int i = 0; i < depthCurrent; i++) out.append("\u2551 "); + return out; + } + + template + LoggerNewline operator<< (T const& value) { + if(level >= global_level) { + + if(depth > depthCurrent) { + std::cout << Logger::getPadding() << "\u255f\u2500\u2556" << std::endl; + depthCurrent++; + } + std::cout << Logger::getPadding() << "\u255f " << prefix << value; + return LoggerNewline(); + } else { + return LoggerNewline(false); + } + } + + + void + increaseIndention() + { + depth++; + } + + void + decreaseIndention() + { + if(depth == depthCurrent) + std::cout << Logger::getPadding() << std::endl; + + depthCurrent = --depth; + } + +private: + int level; + std::string prefix; + static int depth; + static int global_level; + static int depthCurrent; +}; + + +extern Logger cpp_debug; +extern Logger cpp_info; +extern Logger cpp_warn; +extern Logger cpp_error; diff --git a/fpga/lib/CMakeLists.txt b/fpga/lib/CMakeLists.txt index f80b17e8a..a4962cb49 100644 --- a/fpga/lib/CMakeLists.txt +++ b/fpga/lib/CMakeLists.txt @@ -28,6 +28,7 @@ set(SOURCES log.c log_config.c log_helper.c + log.cpp ) include(FindPkgConfig) diff --git a/fpga/lib/card.cpp b/fpga/lib/card.cpp index a2f69ab83..872275dd9 100644 --- a/fpga/lib/card.cpp +++ b/fpga/lib/card.cpp @@ -37,6 +37,8 @@ #include "fpga/ip.hpp" #include "fpga/card.hpp" +#include "log.hpp" + namespace villas { static FpgaCardPlugin @@ -50,7 +52,8 @@ FpgaCardPlugin::make(json_t *json, struct pci* pci, ::vfio_container* vc) const char *card_name; json_t *json_card; json_object_foreach(json, card_name, json_card) { - std::cout << "Found config for FPGA card " << card_name << std::endl; + cpp_info << "Found config for FPGA card " << card_name; + Logger::Indenter indent = cpp_debug.indent(); json_t* json_ips = nullptr; const char* pci_slot = nullptr; @@ -66,7 +69,7 @@ FpgaCardPlugin::make(json_t *json, struct pci* pci, ::vfio_container* vc) "id", &pci_id); if(ret != 0) { - std::cout << " Cannot parse JSON config" << std::endl; + cpp_warn << "Cannot parse JSON config"; continue; } @@ -81,18 +84,20 @@ FpgaCardPlugin::make(json_t *json, struct pci* pci, ::vfio_container* vc) const char* error; - if (pci_slot != nullptr and pci_device_parse_slot(&card->filter, pci_slot, &error) != 0) - std::cout << " Failed to parse PCI slot: " << error << std::endl - << " -> ignoring" << std::endl; + if (pci_slot != nullptr and pci_device_parse_slot(&card->filter, pci_slot, &error) != 0) { + cpp_warn << "Failed to parse PCI slot: " << error; +// cpp_info << "... ignoring"; + } - if (pci_id != nullptr and pci_device_parse_id(&card->filter, pci_id, &error) != 0) - std::cout << " Failed to parse PCI ID: " << error << std::endl - << " -> ignoring" << std::endl;; + if (pci_id != nullptr and pci_device_parse_id(&card->filter, pci_id, &error) != 0) { + cpp_warn << "Failed to parse PCI ID: " << error; +// cpp_info << "ignoring ..."; + } // TODO: currently fails, fix and remove comment // if(not card->start()) { -// std::cout << " cannot start, destroying ..." << std::endl; +// cpp_warn << " cannot start, destroying ..."; // delete card; // continue; // } @@ -100,11 +105,12 @@ FpgaCardPlugin::make(json_t *json, struct pci* pci, ::vfio_container* vc) const char *ip_name; json_t *json_ip; json_object_foreach(json_ips, ip_name, json_ip) { - std::cout << " Found IP " << ip_name << std::endl; + cpp_info << "Found IP: " << ip_name; + Logger::Indenter indent = cpp_debug.indent(); FpgaIp* ip = FpgaIpFactory::make(card, json_ip, ip_name); if(ip == nullptr) { - std::cout << " -> cannot initialize" << std::endl; + cpp_warn << "Cannot initialize, ignoring ..."; continue; } @@ -112,7 +118,7 @@ FpgaCardPlugin::make(json_t *json, struct pci* pci, ::vfio_container* vc) } if(not card->check()) { - std::cout << " checking failed, destroying ..." << std::endl; + cpp_warn << "Checking failed, destroying ..."; delete card; continue; } @@ -163,7 +169,7 @@ bool FpgaCard::start() serror("Failed to reset PCI device"); if(not reset()) { - std::cout << "Failed to reset FGPA card" << std::endl; + cpp_debug << "Failed to reset FGPA card"; return false; } } diff --git a/fpga/lib/ip.cpp b/fpga/lib/ip.cpp index 4e96228ae..bb7cb724a 100644 --- a/fpga/lib/ip.cpp +++ b/fpga/lib/ip.cpp @@ -29,6 +29,8 @@ #include #include +#include "log.hpp" + namespace villas { void FpgaIp::dump() { @@ -58,7 +60,7 @@ FpgaIp *FpgaIpFactory::make(FpgaCard* card, json_t *json, std::string name) ret = json_unpack(json, "{ s: s }", "vlnv", &vlnv_raw); if(ret != 0) { - std::cout << "IP " << name << " has no entry 'vlnv'" << std::endl; + cpp_warn << "IP " << name << " has no entry 'vlnv'"; return nullptr; } @@ -73,11 +75,11 @@ FpgaIp *FpgaIpFactory::make(FpgaCard* card, json_t *json, std::string name) FpgaIpFactory* fpgaIpFactory = lookup(vlnv); if(fpgaIpFactory == nullptr) { - std::cout << "No IP plugin registered to handle VLNV " << vlnv << std::endl; + cpp_warn << "No plugin found to handle " << vlnv; return nullptr; } - std::cout << "Using " << fpgaIpFactory->getName() << " for IP " << vlnv << std::endl; + cpp_debug << "Using " << fpgaIpFactory->getName() << " for IP " << vlnv; // Create new IP instance. Since this function is virtual, it will construct @@ -85,7 +87,7 @@ FpgaIp *FpgaIpFactory::make(FpgaCard* card, json_t *json, std::string name) // already picked the right factory. FpgaIp* ip = fpgaIpFactory->create(); if(ip == nullptr) { - std::cout << "Cannot create an instance of " << fpgaIpFactory->getName() << std::endl; + cpp_warn << "Cannot create an instance of " << fpgaIpFactory->getName(); goto fail; } @@ -100,7 +102,7 @@ FpgaIp *FpgaIpFactory::make(FpgaCard* card, json_t *json, std::string name) "irq", &ip->irq, "port", &ip->port); if(ret != 0) { - std::cout << "Problem while parsing JSON" << std::endl; + cpp_warn << "Problem while parsing JSON"; goto fail; } @@ -109,12 +111,12 @@ FpgaIp *FpgaIpFactory::make(FpgaCard* card, json_t *json, std::string name) // TODO: currently fails, fix and remove comment // if(not ip->start()) { -// std::cout << "Cannot start IP" << ip->name << std::endl; +// cpp_error << "Cannot start IP" << ip->name; // goto fail; // } if(not ip->check()) { - std::cout << "Checking IP " << ip->name << " failed" << std::endl; + cpp_error << "Checking IP " << ip->name << " failed"; goto fail; } diff --git a/fpga/lib/log.cpp b/fpga/lib/log.cpp new file mode 100644 index 000000000..ff19f30c3 --- /dev/null +++ b/fpga/lib/log.cpp @@ -0,0 +1,26 @@ +#include "log.hpp" +#include "utils.h" + +int Logger::depth; +int Logger::depthCurrent; +int Logger::global_level = 0; + +Logger cpp_debug(0, CLR_BLU("Debug: ")); +Logger cpp_info(20); +Logger cpp_warn(80, CLR_YEL("Warning: ")); +Logger cpp_error(100, CLR_RED("Error: ")); + +void test() +{ + cpp_debug << "Hello"; + { + Logger::Indenter indent = cpp_debug.indent(); + cpp_debug << "indented"; + { + Logger::Indenter indent = cpp_debug.indent(); + cpp_debug << "indented"; + } + } + + cpp_debug << "and root again"; +}