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