Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / fnx / vlib / report / src / cReport.vr
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: cReport.vr
4// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
5// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
6//
7// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8//
9// This program is free software; you can redistribute it and/or modify
10// it under the terms of the GNU General Public License as published by
11// the Free Software Foundation; version 2 of the License.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// You should have received a copy of the GNU General Public License
19// along with this program; if not, write to the Free Software
20// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21//
22// For the avoidance of doubt, and except that if any non-GPL license
23// choice is available it will apply instead, Sun elects to use only
24// the General Public License version 2 (GPLv2) at this time for any
25// software where a choice of GPL license versions is made
26// available with the language indicating that GPLv2 or any later version
27// may be used, or where a choice of which version of the GPL is applied is
28// otherwise unspecified.
29//
30// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
31// CA 95054 USA or visit www.sun.com if you need additional information or
32// have any questions.
33//
34// ========== Copyright Header End ============================================
35#include <vera_defines.vrh>
36#include "report_info.vrh"
37#include "report_msg_format.vrh"
38
39// Definitions, constants, etc.
40#define REPORT_DEFAULT_PRINT_THRESHOLD RPRT_INFO
41#define REPORT_DEFAULT_PRINT_LEVEL RPRT_INFO
42#define REPORT_DEFAULT_MAX_ERROR_COUNT 1
43#define REPORT_VERA_LOCATION_STRING "VERA"
44#define REPORT_NO_PLUS_ARG_SPECIFIED_STR "NONE"
45#define DEATH_CYCLE_DELAY 10
46
47// verilog_tasks for communicating w/ the Report PLI
48extern verilog_task ReportPLI_set_global_print_threshold(integer new_print_threshold, integer locked_by);
49extern verilog_task ReportPLI_set_max_error_count(integer max_error_count);
50extern verilog_task ReportPLI_inc_global_error_count();
51extern verilog_task ReportPLI_get_global_error_count(var integer ec);
52extern verilog_task ReportPLI_inc_global_warning_count();
53extern verilog_task ReportPLI_get_global_warning_count(var integer wc);
54extern verilog_task ReportPLI_set_short_pathnames(integer short_names);
55extern verilog_task ReportPLI_set_path_prefix(bit [(256*8)-1:0] path_prefix);
56extern verilog_task ReportPLI_disable_fatal_errors(integer num_cycles);
57extern verilog_task ReportPLI_set_show_simulation_time(integer show_sim_time);
58extern verilog_task ReportPLI_set_print_level(bit [(256*8)-1:0] regexp, integer report_type, integer print_level);
59extern verilog_task ReportPLI_set_error_level(bit [(256*8)-1:0] regexp, integer report_type, integer error_level);
60extern verilog_task ReportPLI_set_table_mode(bit [(256*8)-1:0] regexp, integer report_type, integer table_mode);
61extern verilog_task ReportPLI_set_exit_on_error(integer exit_on_error);
62extern verilog_task ReportPLI_get_exit_on_error(var integer exit_on_error);
63extern verilog_task ReportPLI_print_cycles_per_second();
64
65////////////////////////////////////////////////////////////////////////////////
66// The Vera ReportClass header
67//
68class ReportClass
69{
70 ///////////////
71 // Private data
72
73 // Class Variables (for all reports)
74 //
75 // NOTE: The Vera ReportClass only tracks the error count for Vera errors.
76 // * To obtain the total global error count (Verilog + Vera),
77 // use the method get_total_error_count().
78 //
79 static protected PrintLevel global_print_threshold = REPORT_DEFAULT_PRINT_THRESHOLD;
80 static protected integer max_error_count = REPORT_DEFAULT_MAX_ERROR_COUNT;
81 static protected integer vera_error_count = 0;
82 static protected integer vera_warning_count = 0;
83 static protected integer use_short_pathnames = 0;
84 static protected string path_prefix = "";
85 static protected integer num_remaining_nonfatal_cycles = 0;
86 static protected integer show_simulation_time = 0;
87 static protected integer in_death_spiral = 0;
88
89 // Information about report types from the report_info class
90 static protected integer report_has_been_initialized = 0;
91 static protected ReportTypeInfo report_info;
92 static protected PrintLevel print_level_per_type[];
93 static protected ErrorLevel error_level_per_type[];
94
95 // For command line overriding
96 static protected integer cmd_line_args_parsed = 0;
97 static protected integer global_print_threshold_locked_by;
98 static protected integer print_level_locked_by[];
99
100 // This semaphore prevents multiple threads from making PLI calls simultaneously.
101 // Vera can't do this since "HDL tasks aren't reentrant".
102 static protected integer pli_semaphore = alloc(SEMAPHORE, 0, 1, 1);
103
104 // Instance variables
105 protected integer table_mode;
106 static protected event deadly_event;
107
108 ///////////////
109 // Public methods
110
111 virtual task report(ReportType report_type, string msg_string,
112 (bit [511:0] arg1 = "", bit [511:0] arg2 = "", bit [511:0] arg3 = "",
113 bit [511:0] arg4 = "", bit [511:0] arg5 = "", bit [511:0] arg6 = "",
114 bit [511:0] arg7 = "", bit [511:0] arg8 = "", bit [511:0] arg9 = "",
115 bit [511:0] arg10 = "", bit [511:0] arg11 = "", bit [511:0] arg12 = ""));
116 // Just like report() but always error.
117 virtual task report_error(string msg_string,
118 bit [511:0] arg1 = "", bit [511:0] arg2 = "", bit [511:0] arg3 = "",
119 bit [511:0] arg4 = "", bit [511:0] arg5 = "", bit [511:0] arg6 = "",
120 bit [511:0] arg7 = "", bit [511:0] arg8 = "", bit [511:0] arg9 = "",
121 bit [511:0] arg10 = "", bit [511:0] arg11 = "", bit [511:0] arg12 = "");
122 // Just like report() but expects only one argument (a string)
123 virtual task report_string(ReportType report_type, string msg_string);
124 virtual task report_test_complete();
125
126 // Accessors for class variables
127 virtual task set_global_print_threshold(PrintLevel new_print_threshold, (integer locked_by = REPORT_LOCKED_BY_NO_ONE));
128 virtual function PrintLevel get_global_print_threshold();
129 virtual task set_max_error_count(integer error_count);
130 virtual function integer get_max_error_count();
131 virtual function integer get_vera_error_count();
132 virtual function integer get_vera_warning_count();
133 virtual task set_short_pathnames(integer use_short);
134 virtual function integer get_short_pathnames();
135 virtual task set_path_prefix(string prefix);
136 virtual function string get_path_prefix();
137 virtual task disable_fatal_errors(integer num_cycles);
138 virtual function integer get_num_remaining_nonfatal_cycles();
139 virtual task set_show_simulation_time(integer show_sim_time);
140 virtual function integer get_show_simulation_time();
141 virtual task set_exit_on_error(integer exit_on_error);
142 virtual function integer get_exit_on_error();
143
144 // Accessors for instance variables
145 virtual task set_print_level(ReportType report_type, PrintLevel new_print_level, (integer locked_by = REPORT_LOCKED_BY_NO_ONE));
146 virtual function PrintLevel get_print_level(ReportType report_type);
147 virtual task set_error_level(ReportType report_type, ErrorLevel new_error_level);
148 virtual function ErrorLevel get_error_level(ReportType report_type);
149 virtual task set_table_mode(integer table_mode);
150 virtual function integer get_table_mode();
151 virtual function bit will_this_print(ReportType report_type);
152
153 // Accessors for Report PLI class variables
154 virtual function integer get_total_error_count();
155 virtual function integer get_total_warning_count();
156
157 // Accessors for Report PLI instance variables
158 virtual task set_verilog_print_level(string regexp, ReportType report_type, PrintLevel print_level);
159 virtual task set_verilog_error_level(string regexp, ReportType report_type, ErrorLevel error_level);
160 virtual task set_verilog_table_mode(string regexp, ReportType report_type, integer table_mode);
161
162 //////////////
163 // Protected methods
164
165 protected virtual task handle_error();
166 protected virtual function string get_location();
167 protected virtual task launch_death_spiral();
168
169 protected task parse_cmd_line_print_threshold();
170 protected task parse_cmd_line_print_mask();
171
172 task new()
173 {
174 integer tmp_var;
175 integer index;
176
177 // Turn table mode (a per-instance variable) off by default.
178 this.table_mode = 0;
179
180 // Do a bunch of things that need to be done only once per test.
181 if (this.report_has_been_initialized == 0)
182 {
183 ReportType type;
184 // Initialize all instance properties.
185 // Populate the print/error level arrays with the correct default values.
186 //
187 // *PERFORMANCE: Only do this once, since the array is populated with
188 // values determined at compile time.
189 //
190 this.report_info = new;
191 for(type = __RTYP_FIRST_TYPE; type < __RTYP_LAST_TYPE; type++)
192 {
193 //ReportType type = index; //report_info.get_type_by_index(index);
194 this.print_level_per_type[type] = report_info.get_default_print_level(type);
195 this.error_level_per_type[type] = report_info.get_default_error_level(type);
196 }
197
198 // Parse command line print threshold
199 this.global_print_threshold_locked_by = REPORT_LOCKED_BY_NO_ONE;
200 this.parse_cmd_line_print_threshold();
201
202 // Parse command line print mask
203 for (index = 0; index < report_info.num_report_types; index++)
204 this.print_level_locked_by[index] = REPORT_LOCKED_BY_NO_ONE;
205 this.parse_cmd_line_print_mask();
206
207 // Launch a thread to wait for the "deadly event" triggered by a fatal error.
208 launch_death_spiral();
209
210 // No need to do all this again.
211 this.report_has_been_initialized = 1;
212 }
213 }
214}
215//
216////////////////////////////////////////////////////////////////////////////////
217
218////////////////////////////////////////////////////////////////////////////////
219// ReportClass method definitions
220//
221
222////////////////////////////////////////////////////////////////////////////////
223// Message display
224
225/*
226 report
227
228 Outputs a message with the given report type in a standard format.
229*/
230task ReportClass::report(ReportType report_type, string msg_str,
231 (bit [511:0] arg1 = "", bit [511:0] arg2 = "", bit [511:0] arg3 = "",
232 bit [511:0] arg4 = "", bit [511:0] arg5 = "", bit [511:0] arg6 = "",
233 bit [511:0] arg7 = "", bit [511:0] arg8 = "", bit [511:0] arg9 = "",
234 bit [511:0] arg10 = "", bit [511:0] arg11 = "", bit [511:0] arg12 = ""))
235{
236 string prefix_str, time_str, location_str;
237 PrintLevel my_print_level = this.print_level_per_type[report_type];
238 ErrorLevel my_error_level = this.error_level_per_type[report_type];
239
240 // *PERFORMANCE: Return -immediately- if this report will be a NOP.
241 if (my_print_level < this.global_print_threshold)
242 return;
243
244
245 // - if fatal errors are disabled, make errors into warnings.
246 if (this.num_remaining_nonfatal_cycles > 0 && my_error_level == RERR_ERROR)
247 prefix_str = report_info.get_prefix(report_type, RERR_MESSAGE);
248 else
249 prefix_str = report_info.get_prefix(report_type, my_error_level);
250
251 // Generate the time string.
252 // - tack on simulation time if so desired.
253 if (show_simulation_time)
254 {
255 string cycle_str, tick_hi_str, tick_lo_str;
256 sprintf(cycle_str, "%0d", get_cycle());
257 sprintf(tick_hi_str, "%0d", get_time(HI));
258 sprintf(tick_lo_str, "%0d", get_time(LO));
259 time_str = {cycle_str, ",", tick_hi_str, tick_lo_str}; // e.g. "350,768990"
260 }
261 else
262 {
263 sprintf(time_str, "%0d", get_cycle());
264 }
265
266 // Get the location string.
267 location_str = this.get_location();
268
269 // Actually do the output, if the print level is appropriate.
270 if (my_print_level >= this.global_print_threshold)
271 {
272 string regexp_pattern, match_str;
273
274 // review: Support output redirection here!!!
275
276 // Check for bitfield width specifiers in the message format string.
277 // For example, "%32h" will print only the rightmost 32 bits of a hex number.
278 /*
279 TODO: Figure out how to implement this cleanly.
280
281 regexp_pattern = "[^%]%([0-9]+)[hHxXoObB]";
282 match_str = msg_str;
283 while (match_str.match(regexp_pattern) == 1)
284 {
285 string width_str = match_str.backref(0);
286 integer width = width_str.atoi();
287 printf("*** msg_str contains bitfield width specifier %s, giving width of %0d ***\n", match_str.thismatch(), width);
288 match_str = match_str.postmatch();
289 }
290 */
291
292
293 if (!this.table_mode)
294 printf(REPORT_MSG_FORMAT_STRING, prefix_str, time_str, location_str);
295
296 // If fatal error, output the error type.
297 if (my_error_level == RERR_ERROR)
298 printf("%s: ", report_info.report_type_to_str(report_type));
299
300 // Print message string
301 printf(msg_str, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12);
302
303 // Print newline (if not in table mode)
304 if (!this.table_mode) printf("\n");
305 }
306
307 // If this message was an error/warning, increment the global error/warning count.
308 // Then increment the Vera-specific error/warning count.
309 if (my_error_level == RERR_ERROR)
310 {
311 integer total_errors, exit_on_error;
312
313 semaphore_get(WAIT, this.pli_semaphore, 1);
314
315 if (num_remaining_nonfatal_cycles == 0)
316 {
317 // Only do this if fatal errors are not currently disabled!
318 ReportPLI_inc_global_error_count();
319 vera_error_count++;
320 }
321
322 ReportPLI_get_global_error_count(total_errors);
323
324 semaphore_put(this.pli_semaphore, 1);
325
326 // If this error pushed us over the maximum error count (as recorded by Verilog)
327 // handle the error and kill the simulation if we're supposed to.
328
329 if (total_errors >= this.max_error_count)
330 {
331 this.handle_error();
332
333 trigger(ONE_BLAST, deadly_event); // unblocks launch_death_spiral()
334 }
335 }
336 else if (my_error_level == RERR_WARNING)
337 {
338 semaphore_get(WAIT, this.pli_semaphore, 1);
339 ReportPLI_inc_global_warning_count();
340 vera_warning_count++;
341 semaphore_put(this.pli_semaphore, 1);
342 }
343}
344
345 // Just like report() but always error.
346task ReportClass::report_error(string msg_string,
347 bit [511:0] arg1 = "", bit [511:0] arg2 = "", bit [511:0] arg3 = "",
348 bit [511:0] arg4 = "", bit [511:0] arg5 = "", bit [511:0] arg6 = "",
349 bit [511:0] arg7 = "", bit [511:0] arg8 = "", bit [511:0] arg9 = "",
350 bit [511:0] arg10 = "", bit [511:0] arg11 = "", bit [511:0] arg12 = "") {
351 this.report(RTYP_VERA_ERROR, msg_string, arg1, arg2, arg3,
352 arg4, arg5, arg6,
353 arg7, arg8, arg9,
354 arg10, arg11, arg12);
355} // ReportClass.error()
356
357
358/*
359 * report_string
360 */
361task ReportClass::report_string(ReportType report_type, string msg_string)
362{
363 string prefix_str, time_str, location_str;
364 PrintLevel my_print_level = this.print_level_per_type[report_type];
365 ErrorLevel my_error_level = this.error_level_per_type[report_type];
366
367 // *PERFORMANCE: Return -immediately- if this report will be a NOP.
368 if (my_print_level < this.global_print_threshold)
369 return;
370
371
372 // - if fatal errors are disabled, make errors into warnings.
373 if (this.num_remaining_nonfatal_cycles > 0 && my_error_level == RERR_ERROR)
374 prefix_str = report_info.get_prefix(report_type, RERR_MESSAGE);
375 else
376 prefix_str = report_info.get_prefix(report_type, my_error_level);
377
378 // Generate the time string.
379 // - tack on simulation time if so desired.
380 if (show_simulation_time)
381 {
382 string cycle_str, tick_hi_str, tick_lo_str;
383 sprintf(cycle_str, "%0d", get_cycle());
384 sprintf(tick_hi_str, "%0d", get_time(HI));
385 sprintf(tick_lo_str, "%0d", get_time(LO));
386 time_str = {cycle_str, ",", tick_hi_str, tick_lo_str}; // e.g. "350,768990"
387 }
388 else
389 {
390 sprintf(time_str, "%0d", get_cycle());
391 }
392
393 // Get the location string.
394 location_str = this.get_location();
395
396 // Actually do the output, if the print level is appropriate.
397 if (my_print_level >= this.global_print_threshold)
398 {
399 string regexp_pattern, match_str;
400
401
402 if (!this.table_mode)
403 printf(REPORT_MSG_FORMAT_STRING, prefix_str, time_str, location_str);
404
405 // If fatal error, output the error type.
406 if (my_error_level == RERR_ERROR)
407 printf("%s: ", report_info.report_type_to_str(report_type));
408
409 // Print message string
410 printf(msg_string);
411
412 // Print newline (if not in table mode)
413 if (!this.table_mode) printf("\n");
414 }
415
416 // If this message was an error/warning, increment the global error/warning count.
417 // Then increment the Vera-specific error/warning count.
418 if (my_error_level == RERR_ERROR)
419 {
420 integer total_errors, exit_on_error;
421
422 semaphore_get(WAIT, this.pli_semaphore, 1);
423
424 if (num_remaining_nonfatal_cycles == 0)
425 {
426 // Only do this if fatal errors are not currently disabled!
427 ReportPLI_inc_global_error_count();
428 vera_error_count++;
429 }
430
431 ReportPLI_get_global_error_count(total_errors);
432
433 semaphore_put(this.pli_semaphore, 1);
434
435 // If this error pushed us over the maximum error count (as recorded by Verilog)
436 // handle the error and kill the simulation if we're supposed to.
437
438 if (total_errors >= this.max_error_count)
439 {
440 this.handle_error();
441
442 trigger(ONE_BLAST, deadly_event); // unblocks launch_death_spiral()
443 }
444 }
445 else if (my_error_level == RERR_WARNING)
446 {
447 semaphore_get(WAIT, this.pli_semaphore, 1);
448 ReportPLI_inc_global_warning_count();
449 vera_warning_count++;
450 semaphore_put(this.pli_semaphore, 1);
451 }
452}
453
454
455/*
456 report_test_complete
457 */
458task ReportClass::report_test_complete()
459{
460 integer total_errors, total_warnings;
461
462 semaphore_get(WAIT, this.pli_semaphore, 1);
463 ReportPLI_get_global_error_count(total_errors);
464 ReportPLI_get_global_warning_count(total_warnings);
465 semaphore_put(this.pli_semaphore, 1);
466 if (in_death_spiral) {
467 error("Report(%0d) [VERA] Test finished in death spiral!\n", get_cycle());
468 }
469 printf(REPORT_TEST_DONE_FORMAT_STRING, get_cycle(), total_errors, total_warnings);
470 ReportPLI_print_cycles_per_second();
471}
472
473/*
474 handle_error
475 */
476task ReportClass::handle_error()
477{
478 // NOTE: By default, the base ReportClass does nothing to handle errors.
479 this.report(RTYP_REPORT_MSG, "Fatal error encountered!!!");
480}
481
482/*
483 protected virtual function string get_location()
484
485 Returns the location from which this report is being made.
486 NOTE: This may one day actually be the object+method we're in,
487 but Vera doesn't currently support this.
488 */
489function string ReportClass::get_location()
490{
491 get_location = REPORT_VERA_LOCATION_STRING;
492}
493
494//
495////////////////////////////////////////////////////////////////////////////////
496
497////////////////////////////////////////////////////////////////////////////////
498// Accessors for class variables
499//
500// NOTE: Since control changes in Vera override those in Verilog,
501// these accessors also call the UDF functions to reconfigure the C+ ReportClass.
502
503/*
504 set_global_print_threshold
505
506 This accessor may be called with a "lock" variable to prevent further changes.
507 This can be used to lock in changes from the command line, for example.
508 NOTE! The lock variable can only be set once; further changes are ignored.
509 */
510task ReportClass::set_global_print_threshold(PrintLevel new_print_threshold, (integer locked_by = REPORT_LOCKED_BY_NO_ONE))
511{
512 integer int_pl = new_print_threshold;
513 if (this.global_print_threshold_locked_by == REPORT_LOCKED_BY_NO_ONE)
514 {
515 if (locked_by != REPORT_LOCKED_BY_NO_ONE)
516 {
517 this.report(RTYP_REPORT_MSG, "Locked global print threshold to %s -- further changes will be ignored",
518 report_info.print_level_to_str(new_print_threshold));
519 this.global_print_threshold_locked_by = locked_by;
520 }
521 else
522 {
523 // The usual case -- no locks specified or set.
524 // When we call C++, though, lock their print threshold so only we can change it.
525 this.report(RTYP_REPORT_MSG, "Changing global print threshold from %s to %s",
526 report_info.print_level_to_str(this.global_print_threshold),
527 report_info.print_level_to_str(new_print_threshold));
528 locked_by = REPORT_LOCKED_BY_VERA;
529 }
530 this.global_print_threshold = new_print_threshold;
531
532 // Pass the good news along to C++.
533
534// semaphore_get(WAIT, pli_semaphore, 1);
535 ReportPLI_set_global_print_threshold(int_pl, locked_by);
536// semaphore_put(pli_semaphore, 1);
537 }
538 else
539 {
540 this.report(RTYP_REPORT_MSG, "Can't change global print threshold to %s -- it's locked!",
541 report_info.print_level_to_str(new_print_threshold));
542 }
543}
544
545/*
546 get_global_print_threshold
547 */
548function PrintLevel ReportClass::get_global_print_threshold()
549{
550 get_global_print_threshold = this.global_print_threshold;
551}
552
553/*
554 set_max_error_count
555 */
556task ReportClass::set_max_error_count(integer error_count)
557{
558 semaphore_get(WAIT, pli_semaphore, 1);
559 ReportPLI_set_max_error_count(error_count);
560 semaphore_put(pli_semaphore, 1);
561 this.report(RTYP_REPORT_MSG, "Changing maximum error count from %0d to %0d",
562 this.max_error_count, error_count);
563 this.max_error_count = error_count;
564}
565
566/*
567 get_max_error_count
568 */
569function integer ReportClass::get_max_error_count()
570{
571 get_max_error_count = this.max_error_count;
572}
573
574/*
575 get_vera_error_count
576 */
577function integer ReportClass::get_vera_error_count()
578{
579 get_vera_error_count = this.vera_error_count;
580}
581
582/*
583 get_vera_warning_count
584 */
585function integer ReportClass::get_vera_warning_count()
586{
587 get_vera_warning_count = this.vera_warning_count;
588}
589
590/*
591 set_short_pathnames
592 */
593task ReportClass::set_short_pathnames(integer use_short)
594{
595 semaphore_get(WAIT, pli_semaphore, 1);
596 ReportPLI_set_short_pathnames(use_short);
597 semaphore_put(pli_semaphore, 1);
598 if (use_short)
599 this.report(RTYP_REPORT_MSG, "Using short pathnames.");
600 else
601 this.report(RTYP_REPORT_MSG, "Using long pathnames.");
602
603 this.use_short_pathnames = use_short;
604}
605
606/*
607 get_short_pathnames
608 */
609function integer ReportClass::get_short_pathnames()
610{
611 get_short_pathnames = this.use_short_pathnames;
612}
613
614/*
615 set_path_prefix
616 */
617task ReportClass::set_path_prefix(string prefix)
618{
619 semaphore_get(WAIT, pli_semaphore, 1);
620 ReportPLI_set_path_prefix(prefix);
621 semaphore_put(pli_semaphore, 1);
622 this.report(RTYP_REPORT_MSG, "Setting path prefix to %s", prefix);
623 this.path_prefix = prefix;
624}
625
626/*
627 get_path_prefix
628 */
629function string ReportClass::get_path_prefix()
630{
631 get_path_prefix = this.path_prefix;
632}
633
634/*
635 set_exit_on_error
636 */
637task ReportClass::set_exit_on_error(integer exit)
638{
639 semaphore_get(WAIT, pli_semaphore, 1);
640 ReportPLI_set_exit_on_error(exit);
641 semaphore_put(pli_semaphore, 1);
642}
643
644/*
645 get_exit_on_error
646 */
647function integer ReportClass::get_exit_on_error()
648{
649 integer exit_on_error;
650 semaphore_get(WAIT, pli_semaphore, 1);
651 ReportPLI_get_exit_on_error(exit_on_error);
652 semaphore_put(pli_semaphore, 1);
653 get_exit_on_error = exit_on_error;
654}
655
656/*
657 disable_fatal_errors
658 */
659task ReportClass::disable_fatal_errors(integer num_cycles)
660{
661 semaphore_get(WAIT, pli_semaphore, 1);
662 ReportPLI_disable_fatal_errors(num_cycles);
663 semaphore_put(pli_semaphore, 1);
664 if (num_cycles > 0)
665 {
666 this.report(RTYP_REPORT_MSG, "Disabling fatal errors for %0d cycles.", num_cycles);
667 this.num_remaining_nonfatal_cycles = num_cycles;
668
669 // Spawn a thread to count down the number of remaining nonfatal cycles.
670 // NOTE: The nonfatal cycle count for C++ is decremented by the PLI code.
671 fork
672 repeat (num_cycles)
673 {
674 this.report(RTYP_REPORT_MSG, "Fatal errors are disabled on this cycle!!!");
675 this.num_remaining_nonfatal_cycles--;
676 @(posedge CLOCK); // review: Which clock? What if there is more than one?
677 }
678 join none
679 }
680}
681
682/*
683 get_num_remaining_nonfatal_cycles
684 */
685function integer ReportClass::get_num_remaining_nonfatal_cycles()
686{
687 get_num_remaining_nonfatal_cycles = this.num_remaining_nonfatal_cycles;
688}
689
690/*
691 set_show_simulation_time
692 */
693task ReportClass::set_show_simulation_time(integer sim_time)
694{
695 semaphore_get(WAIT, pli_semaphore, 1);
696 ReportPLI_set_show_simulation_time(sim_time);
697 semaphore_put(pli_semaphore, 1);
698 if (!sim_time)
699 report(RTYP_REPORT_MSG, "ReportClass: Not displaying simulation time.");
700 else
701 report(RTYP_REPORT_MSG, "ReportClass: Displaying simulation time.");
702 this.show_simulation_time = sim_time;
703}
704
705/*
706 get_show_simulation_time
707 */
708function integer ReportClass::get_show_simulation_time()
709{
710 get_show_simulation_time = this.show_simulation_time;
711}
712
713////////////////////////////////////////////////////////////////////////////////
714// Accessors for instance variables
715
716/*
717 set_print_level
718 Changes the print level of this message type only
719*/
720task ReportClass::set_print_level(ReportType report_type, PrintLevel new_print_level, (integer locked_by = REPORT_LOCKED_BY_NO_ONE))
721{
722 if (this.print_level_locked_by[report_type] == REPORT_LOCKED_BY_NO_ONE)
723 {
724 if (locked_by != REPORT_LOCKED_BY_NO_ONE)
725 {
726 report(RTYP_REPORT_MSG, "ReportClass: Locking print level for report type %s to %s -- further changes will be ignored",
727 report_info.report_type_to_str(report_type), report_info.print_level_to_str(new_print_level));
728 this.print_level_locked_by[report_type] = locked_by;
729 }
730 else
731 {
732 report(RTYP_REPORT_MSG, "ReportClass: Setting print level for report type %s to %s",
733 report_info.report_type_to_str(report_type), report_info.print_level_to_str(new_print_level));
734 }
735
736 // If the type is "ALL_REPORTS", set everything.
737 // Otherwise, just set the desired type.
738 if (report_type == RTYP_ALL_REPORTS)
739 {
740 ReportType type;
741 for (type = __RTYP_FIRST_TYPE; type <= __RTYP_LAST_TYPE; type++)
742 {
743 print_level_per_type[type] = new_print_level;
744 }
745 }
746 else
747 {
748 print_level_per_type[report_type] = new_print_level;
749 }
750 }
751 else
752 {
753 report(RTYP_REPORT_MSG, "Can't change print level for %s to %s -- it's locked!",
754 report_info.report_type_to_str(report_type), report_info.print_level_to_str(new_print_level));
755 }
756}
757
758/*
759 get_print_level
760 Returns this message type's print level
761*/
762
763function PrintLevel ReportClass::get_print_level(ReportType report_type)
764{
765 get_print_level = print_level_per_type[report_type];
766}
767
768/*
769 set_error_level
770 Changes the error level of this message type only
771*/
772task ReportClass::set_error_level(ReportType report_type, ErrorLevel new_error_level)
773{
774 report(RTYP_REPORT_MSG, "ReportClass: Setting error level for report type %s to %s",
775 report_info.report_type_to_str(report_type), report_info.error_level_to_str(new_error_level));
776
777 // If the type is "ALL_REPORTS", set everything.
778 // Otherwise, just set the desired type.
779 if (report_type == RTYP_ALL_REPORTS)
780 {
781 ReportType type;
782 for (type = __RTYP_FIRST_TYPE; type <= __RTYP_LAST_TYPE; type++)
783 {
784 error_level_per_type[type] = new_error_level;
785 }
786 }
787 else
788 {
789 error_level_per_type[report_type] = new_error_level;
790 }
791}
792
793/*
794 get_error_level
795 Returns this message type's error level
796*/
797
798function ErrorLevel ReportClass::get_error_level(ReportType report_type)
799{
800 get_error_level = error_level_per_type[report_type];
801}
802
803/*
804 set_table_mode
805 */
806task ReportClass::set_table_mode(integer table_mode)
807{
808 /*
809 if (!table_mode)
810 report(RTYP_DEBUG_1, "ReportClass: Disabling table mode.");
811 else
812 report(RTYP_DEBUG_1, "ReportClass: Enabling table mode.");
813 */
814
815 this.table_mode = table_mode;
816}
817
818/*
819 get_table_mode
820 */
821function integer ReportClass::get_table_mode()
822{
823 get_table_mode = this.table_mode;
824}
825
826/*
827 * will_this_print
828 *
829 * Returns 1 if report_type's print_level is above the global print threshold,
830 * and 0 if it is not.
831 *
832 */
833function bit ReportClass::will_this_print(ReportType report_type)
834{
835 will_this_print = (print_level_per_type[report_type] >= this.global_print_threshold);
836}
837
838////////////////////////////////////////////////////////////////////////////////
839// Accessors for Report PLI class variables
840function integer ReportClass::get_total_error_count()
841{
842 integer ec;
843 semaphore_get(WAIT, pli_semaphore, 1);
844 ReportPLI_get_global_error_count(ec);
845 semaphore_put(pli_semaphore, 1);
846 get_total_error_count = ec;
847}
848
849function integer ReportClass::get_total_warning_count()
850{
851 integer wc;
852 semaphore_get(WAIT, pli_semaphore, 1);
853 ReportPLI_get_global_warning_count(wc);
854 semaphore_put(pli_semaphore, 1);
855 get_total_warning_count = wc;
856}
857
858////////////////////////////////////////////////////////////////////////////////
859// Accessors for Report PLI instance variables
860//
861task ReportClass::set_verilog_print_level(string regexp, ReportType report_type, PrintLevel print_level)
862{
863 integer int_type = report_type;
864 integer int_lvl = print_level;
865 semaphore_get(WAIT, pli_semaphore, 1);
866 ReportPLI_set_print_level(regexp, int_type, int_lvl);
867 semaphore_put(pli_semaphore, 1);
868}
869
870task ReportClass::set_verilog_error_level(string regexp, ReportType report_type, ErrorLevel error_level)
871{
872 integer int_type = report_type;
873 integer int_lvl = error_level;
874 semaphore_get(WAIT, pli_semaphore, 1);
875 ReportPLI_set_error_level(regexp, int_type, int_lvl);
876 semaphore_put(pli_semaphore, 1);
877}
878
879task ReportClass::set_verilog_table_mode(string regexp, ReportType report_type, integer table_mode)
880{
881 integer int_type = report_type;
882 semaphore_get(WAIT, pli_semaphore, 1);
883 ReportPLI_set_table_mode(regexp, int_type, table_mode);
884 semaphore_put(pli_semaphore, 1);
885}
886
887////////////////////////////////////////////////////////////////////////////////
888// Protected methods
889
890/*
891 * parse_cmd_line_print_threshold
892 *
893 */
894task ReportClass::parse_cmd_line_print_threshold()
895{
896 // Get print thresholds specified on the command line.
897 bit [511:0] global_print_threshold_bits, vera_print_threshold_bits, verilog_print_threshold_bits;
898 PrintLevel global_print_threshold, vera_print_threshold, verilog_print_threshold;
899
900 global_print_threshold_bits = get_plus_arg(STR, "report_global_print_threshold=");
901 vera_print_threshold_bits = get_plus_arg(STR, "report_vera_print_threshold=");
902 verilog_print_threshold_bits = get_plus_arg(STR, "report_verilog_print_threshold=");
903
904 if (!report_info.bit_string_to_print_level(global_print_threshold_bits, global_print_threshold))
905 {
906 // No global specified -- check for individual Verilog or Vera thresholds.
907 // Set the Verilog threshold, if any...
908 if (report_info.bit_string_to_print_level(verilog_print_threshold_bits, verilog_print_threshold))
909 {
910 integer int_pl = verilog_print_threshold;
911 if (verilog_print_threshold != this.get_global_print_threshold())
912 {
913
914// semaphore_get(WAIT, pli_semaphore, 1);
915 ReportPLI_set_global_print_threshold(int_pl, REPORT_LOCKED_BY_CMD_LINE);
916// semaphore_put(pli_semaphore, 1);
917 }
918 }
919
920 // ...then set the Vera threshold, if any.
921 if (report_info.bit_string_to_print_level(vera_print_threshold_bits, vera_print_threshold))
922 {
923 if (vera_print_threshold != this.get_global_print_threshold())
924 this.set_global_print_threshold(vera_print_threshold, REPORT_LOCKED_BY_VERA); // HACK: leave Verilog threshold unchanged by specifying 'Vera' lock
925 }
926 }
927 else
928 {
929 // "global" overrides both of the "vera" and "verilog" individual settings.
930 if (global_print_threshold != this.get_global_print_threshold())
931 this.set_global_print_threshold(global_print_threshold, REPORT_LOCKED_BY_CMD_LINE);
932 }
933}
934
935/*
936 * parse_cmd_line_print_mask
937 *
938 */
939task ReportClass::parse_cmd_line_print_mask()
940{
941 // Get the Vera print mask specified on the command line, if any.
942 // Pull out individual message types from it by using a regular expression.
943 bit [511:0] vera_print_mask_bits;
944 string vera_print_mask_str;
945
946 vera_print_mask_bits = get_plus_arg(STR, "report_vera_print_mask=");
947 vera_print_mask_str.bittostr(vera_print_mask_bits);
948
949 // Get each message type name and lock its print level to NONMASKABLE.
950 while (vera_print_mask_str.match("[a-zA-Z0-9_]+") > 0)
951 {
952 ReportType type;
953 if (report_info.string_to_report_type(vera_print_mask_str.thismatch(), type))
954 {
955 this.set_print_level(type, RPRT_NONMASKABLE, REPORT_LOCKED_BY_CMD_LINE);
956 }
957 else
958 {
959 this.report(RTYP_REPORT_MSG, "Encountered bad report type %s in command line argument REPORT_VERA_PRINT_MASK",
960 vera_print_mask_str.thismatch());
961 }
962 vera_print_mask_str = vera_print_mask_str.postmatch();
963 }
964}
965
966//
967////////////////////////////////////////////////////////////////////////////////
968
969// task launch_death_spiral
970//
971// Description: This class launches the thread which will actually kill the
972// test on a fatal error. The test is killed by an error()
973// call triggered DEATH_CYCLE_DELAY cycles after receiving
974// the 'deadly_event' signal.
975//
976
977task ReportClass::launch_death_spiral()
978{
979 fork
980 {
981 integer exit_on_error;
982
983 // Block until the deadly event happens.
984 // NOTE: Only need to do this once, since it will kill the test!
985 sync(ALL, deadly_event);
986
987 ReportPLI_get_exit_on_error(exit_on_error);
988
989 if (exit_on_error)
990 {
991 if (!in_death_spiral)
992 {
993 integer death_spiral_count = DEATH_CYCLE_DELAY;
994
995 in_death_spiral = 1;
996 printf("Report:(%0d) [VERA] Scheduling termination for cycle %0d\n", get_cycle(), get_cycle() + DEATH_CYCLE_DELAY);
997
998 while(death_spiral_count--) {
999
1000 printf("Report:(%0d) [VERA] In death spiral. %0d cycles left till termination.\n",
1001 get_cycle(), death_spiral_count);
1002
1003 @(posedge CLOCK);
1004 }
1005
1006 printf("Report:(%0d) [VERA] Calling error() for error which occurred on cycle %0d\n",
1007 get_cycle(), get_cycle() - DEATH_CYCLE_DELAY);
1008 error(""); // actually kill the test!
1009
1010 }
1011 else
1012 {
1013 printf("Report:(%0d) [VERA] termination already scheduled\n");
1014 }
1015 }
1016 }
1017 join none
1018}