Skip to content

Commit ecb0ee7

Browse files
Split the CCI mechanism from the rest of remote.h
Signed-off-by: Mark Burton <[email protected]>
1 parent 5e537b1 commit ecb0ee7

File tree

3 files changed

+305
-150
lines changed

3 files changed

+305
-150
lines changed

report/include/scp/report.h

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,26 @@
4444
#if defined(_MSC_VER) && defined(ERROR)
4545
#undef ERROR
4646
#endif
47-
47+
static const std::array<sc_core::sc_severity, 8> severity = {
48+
sc_core::SC_FATAL, // scp::log::NONE
49+
sc_core::SC_FATAL, // scp::log::FATAL
50+
sc_core::SC_ERROR, // scp::log::ERROR
51+
sc_core::SC_WARNING, // scp::log::WARNING
52+
sc_core::SC_INFO, // scp::log::INFO
53+
sc_core::SC_INFO, // scp::log::DEBUG
54+
sc_core::SC_INFO, // scp::log::TRACE
55+
sc_core::SC_INFO // scp::log::TRACEALL
56+
};
57+
static const std::array<sc_core::sc_verbosity, 8> verbosity = {
58+
sc_core::SC_NONE, // scp::log::NONE
59+
sc_core::SC_LOW, // scp::log::FATAL
60+
sc_core::SC_LOW, // scp::log::ERROR
61+
sc_core::SC_LOW, // scp::log::WARNING
62+
sc_core::SC_MEDIUM, // scp::log::INFO
63+
sc_core::SC_HIGH, // scp::log::DEBUG
64+
sc_core::SC_FULL, // scp::log::TRACE
65+
sc_core::SC_DEBUG // scp::log::TRACEALL
66+
};
4867
namespace sc_core {
4968
const sc_core::sc_verbosity SC_UNSET = (sc_core::sc_verbosity)INT_MAX;
5069
}
@@ -168,6 +187,10 @@ struct LogConfig {
168187
bool report_only_first_error{ false };
169188
int file_info_from{ sc_core::SC_INFO };
170189

190+
std::function<sc_core::sc_verbosity(struct scp_logger_cache&, const char*,
191+
const char*)>
192+
log_level_lookup_fn;
193+
171194
//! set the logging level
172195
LogConfig& logLevel(log);
173196
//! define the width of the message field, 0 to disable,
@@ -197,6 +220,10 @@ struct LogConfig {
197220
LogConfig& fileInfoFrom(int);
198221
//! disable/enable the supression of all error messages after the first
199222
LogConfig& reportOnlyFirstError(bool = true);
223+
//! register log level function
224+
LogConfig& registerLogLevelFn(
225+
std::function<sc_core::sc_verbosity(struct scp_logger_cache&,
226+
const char*, const char*)>);
200227
};
201228

202229
/**
Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*******************************************************************************/
16+
#ifndef _SCP_REPORT_CCI_SETTER_H_
17+
#define _SCP_REPORT_CCI_SETTER_H_
18+
19+
#include <scp/report.h>
20+
#include <cci_configuration>
21+
#include <type_traits>
22+
#include <regex>
23+
24+
namespace scp {
25+
static std::set<std::string> logging_parameters;
26+
27+
class scp_logger_from_cci
28+
{
29+
std::vector<std::string> split(const std::string& s) const {
30+
std::vector<std::string> result;
31+
std::istringstream iss(s);
32+
std::string item;
33+
while (std::getline(iss, item, '.')) {
34+
result.push_back(item);
35+
}
36+
return result;
37+
}
38+
39+
std::string join(std::vector<std::string> vec) const {
40+
if (vec.empty())
41+
return "";
42+
return std::accumulate(
43+
vec.begin(), vec.end(), std::string(),
44+
[](const std::string& a, const std::string& b) -> std::string {
45+
return a + (a.length() > 0 ? "." : "") + b;
46+
});
47+
}
48+
49+
void insert(std::multimap<int, std::string, std::greater<int>>& map,
50+
std::string s, bool interesting) const {
51+
int n = std::count(s.begin(), s.end(), '.');
52+
map.insert(make_pair(n, s));
53+
54+
if (interesting) {
55+
logging_parameters.insert(s + "." SCP_LOG_LEVEL_PARAM_NAME);
56+
}
57+
}
58+
sc_core::sc_verbosity cci_lookup(cci::cci_broker_handle broker,
59+
std::string name) const {
60+
auto param_name = (name.empty()) ? SCP_LOG_LEVEL_PARAM_NAME
61+
: name + "." SCP_LOG_LEVEL_PARAM_NAME;
62+
auto h = broker.get_param_handle(param_name);
63+
if (h.is_valid()) {
64+
return verbosity.at(std::min<unsigned>(h.get_cci_value().get_int(),
65+
verbosity.size() - 1));
66+
} else {
67+
auto val = broker.get_preset_cci_value(param_name);
68+
69+
if (val.is_int()) {
70+
broker.lock_preset_value(param_name);
71+
return verbosity.at(
72+
std::min<unsigned>(val.get_int(), verbosity.size() - 1));
73+
}
74+
}
75+
return sc_core::SC_UNSET;
76+
}
77+
#ifdef __GNUG__
78+
std::string demangle(const char* name) const {
79+
int status = -4; // some arbitrary value to eliminate the compiler
80+
// warning
81+
82+
// enable c++11 by passing the flag -std=c++11 to g++
83+
std::unique_ptr<char, void (*)(void*)> res{
84+
abi::__cxa_demangle(name, NULL, NULL, &status), std::free
85+
};
86+
87+
return (status == 0) ? res.get() : name;
88+
}
89+
#else
90+
// does nothing if not GNUG
91+
std::string demangle(const char* name) { return name; }
92+
#endif
93+
public:
94+
sc_core::sc_verbosity operator()(struct scp_logger_cache& logger,
95+
const char* scname,
96+
const char* tname) const {
97+
try {
98+
// we rely on there being a broker, allow this to throw if not
99+
auto broker = sc_core::sc_get_current_object()
100+
? cci::cci_get_broker()
101+
: cci::cci_get_global_broker(cci::cci_originator(
102+
"scp_reporting_global"));
103+
104+
std::multimap<int, std::string, std::greater<int>> allfeatures;
105+
106+
/* initialize */
107+
for (auto scn = split(scname); scn.size(); scn.pop_back()) {
108+
for (int first = 0; first < scn.size(); first++) {
109+
auto f = scn.begin() + first;
110+
std::vector<std::string> p(f, scn.end());
111+
auto scn_str = ((first > 0) ? "*." : "") + join(p);
112+
113+
for (auto ft : logger.features) {
114+
for (auto ftn = split(ft); ftn.size();
115+
ftn.pop_back()) {
116+
insert(allfeatures, scn_str + "." + join(ftn),
117+
first == 0);
118+
}
119+
}
120+
insert(allfeatures, scn_str + "." + demangle(tname),
121+
first == 0);
122+
insert(allfeatures, scn_str, first == 0);
123+
}
124+
}
125+
for (auto ft : logger.features) {
126+
for (auto ftn = split(ft); ftn.size(); ftn.pop_back()) {
127+
insert(allfeatures, join(ftn), true);
128+
insert(allfeatures, "*." + join(ftn), false);
129+
}
130+
}
131+
insert(allfeatures, demangle(tname), true);
132+
insert(allfeatures, "*", false);
133+
insert(allfeatures, "", false);
134+
135+
for (std::pair<int, std::string> f : allfeatures) {
136+
sc_core::sc_verbosity v = cci_lookup(broker, f.second);
137+
if (v != sc_core::SC_UNSET) {
138+
logger.level = v;
139+
return v;
140+
}
141+
}
142+
} catch (const std::exception&) {
143+
// If there is no global broker, revert to initialized verbosity
144+
// level
145+
}
146+
return logger.level = static_cast<sc_core::sc_verbosity>(
147+
::sc_core::sc_report_handler::get_verbosity_level());
148+
}
149+
static std::vector<std::string> get_logging_parameters() {
150+
return std::vector<std::string>(logging_parameters.begin(),
151+
logging_parameters.end());
152+
}
153+
};
154+
155+
#if 0
156+
157+
/*template <typename T, typename = int>
158+
struct HasLogger : std::false_type { };
159+
160+
template <typename T>
161+
struct HasLogger <T, decltype((void) T::SCP_LOGGER_NAME(), 0)> : std::true_type
162+
{ };
163+
*/
164+
165+
class set_logger_level
166+
{
167+
template <class T>
168+
static auto test(T* p) -> decltype(p->SCP_LOGGER_NAME(), std::true_type());
169+
template <class T>
170+
static auto test(...) -> decltype(std::false_type());
171+
172+
template <class T>
173+
static constexpr bool has_logger = decltype(test<T>(nullptr))::value;
174+
175+
public:
176+
// define a function IF the method exists
177+
template <class TYPE>
178+
auto operator()(TYPE* p, sc_core::sc_verbosity level) const
179+
-> std::enable_if_t<has_logger<TYPE>> {
180+
p->SCP_LOGGER_NAME().level = level;
181+
}
182+
183+
// define a function IF NOT the method exists
184+
template <class TYPE>
185+
auto operator()(TYPE* p, sc_core::sc_verbosity level) const
186+
-> std::enable_if_t<!has_logger<TYPE>> {}
187+
};
188+
189+
int set_log_levels(std::string path, sc_core::sc_verbosity level,
190+
sc_core::sc_object* m = nullptr, bool set = false) {
191+
int found = 0;
192+
auto pathdot = path.find_first_of('.');
193+
auto lpath = (pathdot != std::string::npos) ? path.substr(pathdot) : path;
194+
195+
if (m) {
196+
std::string mname = std::string(m->name());
197+
auto namedot = mname.find_last_of('.');
198+
auto lname = (namedot != std::string::npos) ? mname.substr(namedot)
199+
: mname;
200+
201+
if (!((lpath == "*") || (lpath == lname))) {
202+
// no match here
203+
return found;
204+
}
205+
}
206+
if (path.substr(pathdot) == SCP_LOG_LEVEL_PARAM_NAME) {
207+
// Found it
208+
set = true;
209+
}
210+
211+
if (set) {
212+
found++;
213+
scp::set_logger_level()(m, level);
214+
}
215+
std::vector<sc_core::sc_object*> children;
216+
if (m) {
217+
children = m->get_child_objects();
218+
} else {
219+
children = sc_core::sc_get_top_level_objects();
220+
}
221+
222+
for (auto c : children) {
223+
if (lpath == "*") {
224+
found += set_log_levels(path, level, c, set);
225+
}
226+
if (pathdot != std::string::npos) {
227+
found += set_log_levels(path.substr(pathdot), level, c, set);
228+
}
229+
}
230+
return found;
231+
};
232+
233+
void cci_enable_logging(cci::cci_broker_handle broker) {
234+
std::string pname = std::string(".") + SCP_LOG_LEVEL_PARAM_NAME;
235+
int plen = std::string(SCP_LOG_LEVEL_PARAM_NAME).length();
236+
std::vector<cci::cci_name_value_pair> logging_paths;
237+
for (auto path : broker.get_unconsumed_preset_values(
238+
[&plen](const std::pair<std::string, cci::cci_value>& iv) {
239+
if (iv.first.length() >= plen) {
240+
return (0 == iv.first.compare(iv.first.length() - plen,
241+
plen,
242+
SCP_LOG_LEVEL_PARAM_NAME));
243+
} else {
244+
return false;
245+
}
246+
})) {
247+
logging_paths.push_back(path);
248+
}
249+
250+
std::sort(logging_paths.begin(), logging_paths.end(),
251+
[&](cci::cci_name_value_pair& s1, cci::cci_name_value_pair& s2) {
252+
return std::count(s1.first.begin(), s1.first.end(), '.') >
253+
std::count(s2.first.begin(), s2.first.end(), '.');
254+
});
255+
for (auto path : logging_paths) {
256+
int found = set_log_levels(
257+
path.first, (sc_core::sc_verbosity)(path.second.get_int()));
258+
if (found == 0) {
259+
SCP_WARN()("No logger named {} found", path.first);
260+
} else {
261+
SCP_INFO()("{} loggers enabled from name {}", found, path.first);
262+
}
263+
}
264+
}
265+
#endif
266+
267+
} // namespace scp
268+
269+
#endif

0 commit comments

Comments
 (0)