m5merge: ruby + inorder
[gem5.git] / src / mem / ruby / common / Debug.cc
1 /*
2 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <fstream>
30 #include <stdarg.h>
31
32 #include "base/misc.hh"
33 #include "mem/gems_common/util.hh"
34 #include "mem/ruby/common/Debug.hh"
35 #include "mem/ruby/common/Global.hh"
36 #include "mem/ruby/eventqueue/RubyEventQueue.hh"
37
38 using namespace std;
39
40 class Debug;
41 extern Debug* g_debug_ptr;
42 ostream *debug_cout_ptr;
43
44 bool Debug::m_protocol_trace = false;
45 struct DebugComponentData
46 {
47 const char *desc;
48 const char ch;
49 };
50
51 // component character list
52 DebugComponentData debugComponents[] =
53 {
54 {"System", 's' },
55 {"Node", 'N' },
56 {"Queue", 'q' },
57 {"Event Queue", 'e' },
58 {"Network", 'n' },
59 {"Sequencer", 'S' },
60 {"Tester", 't' },
61 {"Generated", 'g' },
62 {"SLICC", 'l' },
63 {"Network Queues", 'Q' },
64 {"Time", 'T' },
65 {"Network Internals", 'i' },
66 {"Store Buffer", 'b' },
67 {"Cache", 'c' },
68 {"Predictor", 'p' },
69 {"Allocator", 'a' },
70 {"Memory", 'M' },
71 };
72
73 extern "C" void changeDebugVerbosity(VerbosityLevel vb);
74 extern "C" void changeDebugFilter(int filter);
75
76 void
77 changeDebugVerbosity(VerbosityLevel vb)
78 {
79 g_debug_ptr->setVerbosity(vb);
80 }
81
82 void
83 changeDebugFilter(int filter)
84 {
85 g_debug_ptr->setFilter(filter);
86 }
87
88 Debug::Debug(const Params *p)
89 : SimObject(p)
90 {
91 clearFilter();
92 debug_cout_ptr = &cout;
93
94 setFilterString(p->filter_string.c_str());
95 setVerbosityString(p->verbosity_string.c_str());
96 setDebugOutputFile(p->output_filename.c_str());
97 m_starting_cycle = p->start_time;
98 m_protocol_trace = p->protocol_trace;
99 g_debug_ptr = this;
100 }
101
102 Debug::~Debug()
103 {
104 }
105
106 void
107 Debug::printVerbosity(ostream& out) const
108 {
109 switch (getVerbosity()) {
110 case No_Verb:
111 out << "verbosity = No_Verb" << endl;
112 break;
113 case Low_Verb:
114 out << "verbosity = Low_Verb" << endl;
115 break;
116 case Med_Verb:
117 out << "verbosity = Med_Verb" << endl;
118 break;
119 case High_Verb:
120 out << "verbosity = High_Verb" << endl;
121 break;
122 default:
123 out << "verbosity = unknown" << endl;
124 }
125 }
126
127 bool
128 Debug::validDebug(int module, PriorityLevel priority)
129 {
130 int local_module = (1 << module);
131 if (m_filter & local_module) {
132 if (g_eventQueue_ptr == NULL ||
133 g_eventQueue_ptr->getTime() >= m_starting_cycle) {
134 switch (m_verbosityLevel) {
135 case No_Verb:
136 return false;
137 case Low_Verb:
138 return (priority == HighPrio);
139 case Med_Verb:
140 return (priority == HighPrio || priority == MedPrio);
141 case High_Verb:
142 return true;
143 }
144 }
145 }
146 return false;
147 }
148
149 void
150 Debug::setDebugTime(Time t)
151 {
152 m_starting_cycle = t;
153 }
154
155 void
156 Debug::setVerbosity(VerbosityLevel vb)
157 {
158 m_verbosityLevel = vb;
159 }
160
161 void
162 Debug::setFilter(int filter)
163 {
164 m_filter = filter;
165 }
166
167 bool
168 Debug::setVerbosityString(const char *verb_str)
169 {
170 string verb = verb_str ? verb_str : "";
171 if (verb == "none") {
172 setVerbosity(No_Verb);
173 } else if (verb == "low") {
174 setVerbosity(Low_Verb);
175 } else if (verb == "med") {
176 setVerbosity(Med_Verb);
177 } else if (verb == "high") {
178 setVerbosity(High_Verb);
179 } else {
180 cerr << "Error: unrecognized verbosity (use none, low, med, high): "
181 << verb << endl;
182 return true; // error
183 }
184 return false; // no error
185 }
186
187 bool
188 Debug::checkFilter(char ch)
189 {
190 for (int i = 0; i < NUMBER_OF_COMPS; i++) {
191 // Look at all components to find a character match
192 if (debugComponents[i].ch == ch) {
193 // We found a match - return no error
194 return false; // no error
195 }
196 }
197 return true; // error
198 }
199
200 bool
201 Debug::checkFilterString(const char *filter_str)
202 {
203 if (filter_str == NULL) {
204 cerr << "Error: unrecognized component filter: NULL" << endl;
205 return true; // error
206 }
207
208 // check for default filter ("none") before reporting RUBY_DEBUG error
209 if (string(filter_str) == "none") {
210 return false; // no error
211 }
212
213 if (RUBY_DEBUG == false) {
214 cerr << "Error: User specified set of debug components, but the "
215 << "RUBY_DEBUG compile-time flag is false." << endl
216 << "Solution: Re-compile with RUBY_DEBUG set to true." << endl;
217 return true; // error
218 }
219
220 if (string(filter_str) == "all") {
221 return false; // no error
222 }
223
224 // scan string checking each character
225 for (unsigned int i = 0; i < strlen(filter_str); i++) {
226 bool unrecognized = checkFilter(filter_str[i]);
227 if (unrecognized == true) {
228 return true; // error
229 }
230 }
231 return false; // no error
232 }
233
234 bool
235 Debug::setFilterString(const char *filter_str)
236 {
237 if (checkFilterString(filter_str)) {
238 return true; // error
239 }
240
241 if (string(filter_str) == "all" ) {
242 allFilter();
243 } else if (string(filter_str) == "none") {
244 clearFilter();
245 } else {
246 // scan string adding to bit mask for each component which is present
247 for (unsigned int i = 0; i < strlen(filter_str); i++) {
248 bool error = addFilter( filter_str[i] );
249 if (error) {
250 return true; // error
251 }
252 }
253 }
254 return false; // no error
255 }
256
257 bool
258 Debug::addFilter(char ch)
259 {
260 for (int i = 0; i < NUMBER_OF_COMPS; i++) {
261 // Look at all components to find a character match
262 if (debugComponents[i].ch == ch) {
263 // We found a match - update the filter bit mask
264 cout << " Debug: Adding to filter: '" << ch << "' ("
265 << debugComponents[i].desc << ")" << endl;
266 m_filter |= (1 << i);
267 return false; // no error
268 }
269 }
270
271 // We didn't find the character
272 cerr << "Error: unrecognized component filter: " << ch << endl;
273 usageInstructions();
274 return true; // error
275 }
276
277 void
278 Debug::clearFilter()
279 {
280 m_filter = 0;
281 }
282
283 void Debug::allFilter()
284 {
285 m_filter = ~0;
286 }
287
288 void
289 Debug::usageInstructions(void)
290 {
291 cerr << "Debug components: " << endl;
292 for (int i = 0; i < NUMBER_OF_COMPS; i++) {
293 cerr << " " << debugComponents[i].ch << ": "
294 << debugComponents[i].desc << endl;
295 }
296 }
297
298 void
299 Debug::print(ostream& out) const
300 {
301 out << "[Debug]" << endl;
302 }
303
304 void
305 Debug::setDebugOutputFile (const char *filename)
306 {
307 if (filename == NULL || !strcmp(filename, "none")) {
308 debug_cout_ptr = &cout;
309 return;
310 }
311
312 if (m_fout.is_open()) {
313 m_fout.close();
314 }
315 m_fout.open(filename, ios::out);
316 if (!m_fout.is_open()) {
317 cerr << "setDebugOutputFile: can't open file " << filename << endl;
318 } else {
319 debug_cout_ptr = &m_fout;
320 }
321 }
322
323 void
324 Debug::closeDebugOutputFile ()
325 {
326 if (m_fout.is_open()) {
327 m_fout.close ();
328 debug_cout_ptr = &cout;
329 }
330 }
331
332 void
333 Debug::debugMsg( const char *fmt, ...)
334 {
335 va_list args;
336
337 // you could check validDebug() here before printing the message
338 va_start(args, fmt);
339 vfprintf(stdout, fmt, args);
340 va_end(args);
341 }
342
343 Debug *
344 RubyDebugParams::create()
345 {
346 return new Debug(this);
347 }