diff --git a/src/base/match.hh b/src/base/match.hh index 36c5ad2b6f..8bbe2b88bc 100644 --- a/src/base/match.hh +++ b/src/base/match.hh @@ -66,6 +66,10 @@ class ObjectMatch void setExpression(const std::string &expression); void setExpression(const std::vector &expression); std::vector > getExpressions(); + bool empty() const + { + return tokens.empty(); + } bool match(const std::string &name) const { return tokens.empty() ? false : domatch(name); diff --git a/src/base/trace.cc b/src/base/trace.cc index 272b035e0f..9aa5852ac9 100644 --- a/src/base/trace.cc +++ b/src/base/trace.cc @@ -108,7 +108,7 @@ void Logger::dump(Tick when, const std::string &name, const void *d, int len, const std::string &flag) { - if (!name.empty() && ignore.match(name)) + if (!isEnabled(name)) return; const char *data = static_cast(d); @@ -148,7 +148,7 @@ void OstreamLogger::logMessage(Tick when, const std::string &name, const std::string &flag, const std::string &message) { - if (!name.empty() && ignore.match(name)) + if (!isEnabled(name)) return; if (!debug::FmtTicksOff && (when != MaxTick)) diff --git a/src/base/trace.hh b/src/base/trace.hh index a7f52ebe23..7989279025 100644 --- a/src/base/trace.hh +++ b/src/base/trace.hh @@ -39,6 +39,7 @@ #include "base/compiler.hh" #include "base/cprintf.hh" #include "base/debug.hh" +#include "base/logging.hh" #include "base/match.hh" #include "base/types.hh" #include "sim/cur_tick.hh" @@ -60,6 +61,23 @@ class Logger protected: /** Name match for objects to ignore */ ObjectMatch ignore; + /** Name match for objects to activate log */ + ObjectMatch activate; + + bool isEnabled(const std::string &name) const + { + if (name.empty()) // Enable the logger with a empty name. + return true; + bool ignore_match = ignore.match(name); + bool activate_match = activate.match(name); + if (ignore_match && activate_match) + panic("%s in both ignore and activate.\n", name); + if (ignore_match) + return false; + if (!activate.empty() && !activate_match) + return false; + return true; + } public: /** Log a single message */ @@ -76,7 +94,7 @@ class Logger const std::string &flag, const char *fmt, const Args &...args) { - if (!name.empty() && ignore.match(name)) + if (!isEnabled(name)) return; std::ostringstream line; ccprintf(line, fmt, args...); @@ -104,6 +122,12 @@ class Logger /** Add objects to ignore */ void addIgnore(const ObjectMatch &ignore_) { ignore.add(ignore_); } + /** Set objects to activate */ + void setActivate(ObjectMatch &activate_) { activate = activate_; } + + /** Add objects to activate */ + void addActivate(const ObjectMatch &activate_) { activate.add(activate_); } + virtual ~Logger() { } }; diff --git a/src/base/trace.test.cc b/src/base/trace.test.cc index c53dcd7324..a72ef54578 100644 --- a/src/base/trace.test.cc +++ b/src/base/trace.test.cc @@ -166,6 +166,61 @@ TEST(TraceTest, LogMessageFlagEnabled) trace::disable(); } +/** Test that log messages are displayed for activated objects (single). */ +TEST(TraceTest, LogMessageActivateOne) +{ + std::stringstream ss; + trace::OstreamLogger logger(ss); + + ObjectMatch activate_foo("Foo"); + ObjectMatch activate_bar("Bar"); + + // Activate foo. + logger.setActivate(activate_foo); + logger.logMessage(Tick(100), "Foo", "", "Test message"); + ASSERT_EQ(getString(&logger), " 100: Foo: Test message"); + logger.logMessage(Tick(100), "Bar", "", "Test message"); + ASSERT_EQ(getString(&logger), ""); + + // When setting a new activate, the old activates are not kept. + logger.setActivate(activate_bar); + logger.logMessage(Tick(100), "Foo", "", "Test message"); + ASSERT_EQ(getString(&logger), ""); + logger.logMessage(Tick(100), "Bar", "", "Test message"); + ASSERT_EQ(getString(&logger), " 100: Bar: Test message"); +} + +/** Test that log messages are displayed for activated objects (multiple). */ +TEST(TraceTest, LogMessageActivateMultiple) +{ + std::stringstream ss; + trace::OstreamLogger logger(ss); + + ObjectMatch activate_foo("Foo"); + ObjectMatch activate_bar("Bar"); + ObjectMatch activate_thy("Thy"); + + // Activate foo and bar + logger.setActivate(activate_foo); + logger.addActivate(activate_bar); + logger.logMessage(Tick(100), "Foo", "", "Test message"); + ASSERT_EQ(getString(&logger), " 100: Foo: Test message"); + logger.logMessage(Tick(100), "Bar", "", "Test message"); + ASSERT_EQ(getString(&logger), " 100: Bar: Test message"); + logger.logMessage(Tick(100), "Thy", "", "Test message"); + ASSERT_EQ(getString(&logger), ""); + + // Make sure that when setting a new activate, the old activates + // are not kept + logger.setActivate(activate_thy); + logger.logMessage(Tick(100), "Foo", "", "Test message"); + ASSERT_EQ(getString(&logger), ""); + logger.logMessage(Tick(100), "Bar", "", "Test message"); + ASSERT_EQ(getString(&logger), ""); + logger.logMessage(Tick(100), "Thy", "", "Test message"); + ASSERT_EQ(getString(&logger), " 100: Thy: Test message"); +} + /** Test that log messages are not displayed for ignored objects (single). */ TEST(TraceTest, LogMessageIgnoreOne) { @@ -221,6 +276,28 @@ TEST(TraceTest, LogMessageIgnoreMultiple) ASSERT_EQ(getString(&logger), ""); } +/** Test that log messages are displayed properly within ignore and activate */ +TEST(TraceTest, LogMessageActivateAndIgnore) +{ + std::stringstream ss; + trace::OstreamLogger logger(ss); + + ObjectMatch foo("Foo"); + ObjectMatch bar("Bar"); + + // Activate foo and ignore bar + logger.setActivate(foo); + logger.setIgnore(bar); + logger.logMessage(Tick(100), "Foo", "", "Test message"); + ASSERT_EQ(getString(&logger), " 100: Foo: Test message"); + logger.logMessage(Tick(100), "Bar", "", "Test message"); + ASSERT_EQ(getString(&logger), ""); + logger.logMessage(Tick(100), "Thy", "", "Test message"); + // When the Activate list is not empty and thy is not in the list, + // log of Thy will not be displayed. + ASSERT_EQ(getString(&logger), ""); +} + /** Test that dumping for an ignored name does not log anything. */ TEST(TraceTest, DumpIgnored) {