Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / niu / vera / niu_utils / cMesg.vr
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: cMesg.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
37enum Mesg_level =
38 e_mesg_error,
39 e_mesg_warning,
40 e_mesg_info,
41 e_mesg_debug1,
42 e_mesg_debug2,
43 e_mesg_debug3,
44 e_mesg_debug4;
45
46class Mesg {
47 local Mesg_level f_debug_level;
48
49 static local integer f_error_count;
50 static local integer f_warning_count;
51
52 function Mesg_level get_debug_level ();
53 function integer get_error_count ();
54 function integer get_warning_count ();
55
56 task new(Mesg_level level = e_mesg_info);
57 task set_debug_level (Mesg_level level);
58
59 task print(Mesg_level level,
60 string id = "",
61 string src,
62 string fmt,
63 (bit [511:0] fmt_arg0 = 0,
64 bit [511:0] fmt_arg1 = 0,
65 bit [511:0] fmt_arg2 = 0,
66 bit [511:0] fmt_arg3 = 0,
67 bit [511:0] fmt_arg4 = 0,
68 bit [511:0] fmt_arg5 = 0,
69 bit [511:0] fmt_arg6 = 0,
70 bit [511:0] fmt_arg7 = 0,
71 bit [511:0] fmt_arg8 = 0,
72 bit [511:0] fmt_arg9 = 0)
73 );
74
75 task print_test_complete();
76}
77
78task Mesg::new(Mesg_level level = e_mesg_info) {
79 f_error_count = 0;
80 f_warning_count = 0;
81 f_debug_level = e_mesg_info;
82
83 set_debug_level (level);
84}
85
86/*
87 * error count
88 */
89function integer Mesg::get_error_count () {
90 get_error_count = f_error_count;
91}
92
93/*
94 * warning count
95 */
96function integer Mesg::get_warning_count () {
97 get_warning_count = f_warning_count;
98}
99
100/*
101 * I wish we could make this callable only ONCE, no ??
102 */
103task Mesg::set_debug_level (Mesg_level level) {
104 string level_str;
105
106 if (level < e_mesg_warning)
107 print(e_mesg_error,
108 *,
109 "Mesg::set_debug_level",
110 "Can not set debug level < e_mesg_warning");
111 else {
112 sprintf(level_str, "Set debug level to %s", level);
113 print(e_mesg_info,
114 *,
115 "Mesg::set_debug_level",
116 level_str);
117 }
118
119 f_debug_level = level;
120}
121
122/*
123 * Return debug level
124 */
125function Mesg_level Mesg::get_debug_level () {
126 get_debug_level = f_debug_level;
127}
128
129/*
130 * print(level, id_string, src_string, fmt_string, [int] ...10... [int]);
131 *
132 * Input:
133 * level:
134 * e_mesg_error (increments error count)
135 * e_mesg_warning (increments warning count)
136 * e_mesg_info
137 * e_mesg_debug1
138 * e_mesg_debug2
139 * e_mesg_debug3
140 *
141 * id_string:
142 * eg, "xtr1"
143 *
144 * src_string:
145 * eg, "class::method"
146 *
147 * fmt_string:
148 * Formatted output: string (%s %S)
149 * bin (%b %B)
150 * dec (%d %D),
151 * hex (%h %H %x %X)
152 * oct (%o %O)
153 * Field width specifiers ignored (eg, %2d).
154 *
155 * Up to 10 optional arguments, int or castable to int, or string.
156 *
157 * Output:
158 * Error, warning and info messages cannot be turned off.
159 *
160 * Debug statements output only if mesg_debug_level <= set_debug_level, otherwise
161 * absolutely nothing happens.
162 *
163 * Minimum field widths used.
164 *
165 * Format type letter follows argument, except integers, eg: 20, 110001b, 32fah, 7403o
166 *
167 * Newline automaticly inserted, but additional ones are acceptable.
168 *
169 * e_mesg_error:
170 * *** ERROR [hi_time][lo_time]<id_str><src_str> formatted_message_str
171 *
172 * e_mesg_warning:
173 * WARNING [hi_time][lo_time]<id_str><src_str> formatted_message_str
174 *
175 * e_mesg_info, e_mesg_debug#:
176 * [hi_time][lo_time]<id_str><src_str> formatted_message_str
177 */
178task Mesg::print (Mesg_level level,
179 string id_str = "",
180 string src_str,
181 string fmt_str,
182 (bit [511:0] fmt_arg0 = 0,
183 bit [511:0] fmt_arg1 = 0,
184 bit [511:0] fmt_arg2 = 0,
185 bit [511:0] fmt_arg3 = 0,
186 bit [511:0] fmt_arg4 = 0,
187 bit [511:0] fmt_arg5 = 0,
188 bit [511:0] fmt_arg6 = 0,
189 bit [511:0] fmt_arg7 = 0,
190 bit [511:0] fmt_arg8 = 0,
191 bit [511:0] fmt_arg9 = 0)
192 ) {
193 integer time_lo, time_hi;
194 integer i, fmt_char, next_char, fmt_arg_idx = 0, mesg_idx = 0, j, pad_cnt, got_cnt;
195 bit is_x;
196 bit [511:0] fmt_args[10];
197 string pre_mesg_str, mesg_str, tmp_str;
198
199 /*
200 * If level is less than the specified debug level,
201 * we want to process this thing, else do absolutely nothing.
202 */
203 if (level <= f_debug_level) {
204 /*
205 * Put the args in the arg array
206 */
207 fmt_args[0] = fmt_arg0;
208 fmt_args[1] = fmt_arg1;
209 fmt_args[2] = fmt_arg2;
210 fmt_args[3] = fmt_arg3;
211 fmt_args[4] = fmt_arg4;
212 fmt_args[5] = fmt_arg5;
213 fmt_args[6] = fmt_arg6;
214 fmt_args[7] = fmt_arg7;
215 fmt_args[8] = fmt_arg8;
216 fmt_args[9] = fmt_arg9;
217
218 /*
219 * Get the verilog time
220 */
221 time_lo = get_time(LO);
222 time_hi = get_time(HI);
223
224 /*
225 * Assemble pre_mesg
226 */
227
228 // verilog time
229 if (time_hi == 0)
230 sprintf(pre_mesg_str, "%0d ", time_lo);
231 else
232 sprintf(pre_mesg_str, "%0d%0d ", time_hi, time_lo);
233
234 // message level
235 if (level == e_mesg_error) {
236 tmp_str = "ERROR ";
237 f_error_count++;
238 }
239 else if (level == e_mesg_warning) {
240 tmp_str = "WARNING ";
241 f_warning_count++;
242 }
243 else if (level == e_mesg_info)
244 tmp_str = "INFO ";
245 else if (level == e_mesg_debug1)
246 tmp_str = "DEBUG1 ";
247 else if (level == e_mesg_debug2)
248 tmp_str = "DEBUG2 ";
249 else if (level == e_mesg_debug3)
250 tmp_str = "DEBUG3 ";
251 else if (level == e_mesg_debug4)
252 tmp_str = "DEBUG4 ";
253
254 // put message level in pre-mesg
255 pre_mesg_str = { pre_mesg_str, tmp_str };
256
257 // source
258 if (id_str.len() == 0)
259 sprintf(tmp_str, "%s ", src_str);
260 else
261 sprintf(tmp_str, "%s %s ", id_str, src_str);
262
263 // put source in pre-mesg
264 pre_mesg_str = { pre_mesg_str, tmp_str };
265
266 /*
267 * Now process the format (fmt_str).
268 * Assemble the message (mesg_str).
269 */
270 for (i = 0; i < fmt_str.len(); i++, mesg_idx++) {
271 next_char = fmt_str.getc(i);
272
273 // If the char is anything but %, we want to print it to the mesg
274 if (next_char != 37)
275 sprintf(tmp_str, "%c", next_char);
276
277 // If the char is %, then print the next arg to the mesg
278 else {
279 got_cnt = 0; //tells if a pad count was received -- acts as a Boolean
280 // The next fmt_char may have the format
281 fmt_char = fmt_str.getc(++i);
282
283 // If the fmt_char is an integer, then this is a case s.a. %2d, so
284 // save the number
285
286 if ( (fmt_char >= 32'h30) && (fmt_char <= 32'h39) ){
287 // j = the number of spaces wanted
288 j = fmt_char - 32'h30;
289 // Save this number of spaces and then increment to the next character
290 // which will be the type.
291 fmt_char = fmt_str.getc(++i);
292 got_cnt = 1;
293 }
294 // If the fmt arg has any x's, we must print %b format, so override fmt_arg
295 is_x = ^fmt_args[fmt_arg_idx];
296 if (is_x === 1'bx)
297 fmt_char = 32'h42;
298
299 case (fmt_char) {
300 // %b
301 32'h42, 32'h62:{
302 sprintf(tmp_str, "%0bb", fmt_args[fmt_arg_idx++]);
303 pad_cnt = ( j + 1 - tmp_str.len() );
304 }
305 // %c
306 32'h43, 32'h63:{
307 sprintf(tmp_str, "%0c", fmt_args[fmt_arg_idx++]);
308 pad_cnt = ( j - tmp_str.len() );
309 }
310 // %d
311 32'h44, 32'h64:{
312 sprintf(tmp_str, "%0d", fmt_args[fmt_arg_idx++]);
313 pad_cnt = ( j - tmp_str.len() );
314 }
315 // %h, %x
316 32'h48, 32'h58, 32'h68, 32'h78:{
317 sprintf(tmp_str, "%0hh", fmt_args[fmt_arg_idx++]);
318 pad_cnt = ( j + 1 - tmp_str.len() );
319 }
320 // %o
321 32'h4f, 32'h6f:{
322 sprintf(tmp_str, "%0oo", fmt_args[fmt_arg_idx++]);
323 pad_cnt = ( j + 1 - tmp_str.len() );
324 }
325 // %s
326 32'h53, 32'h73:{
327 sprintf(tmp_str, "%0s", fmt_args[fmt_arg_idx++]);
328 pad_cnt = ( j - tmp_str.len() );
329 }
330 // something is wrong
331 default: {
332 sprintf(tmp_str, "NO_FMT");
333 fmt_arg_idx++;
334 }
335 }
336
337 // If user requested a field width and the argument didn't take up
338 // the whole field, pad with zeroes for nums, and spaces for strings.
339 if (( got_cnt == 1 ) && ( pad_cnt > 0 )) {
340 if ((fmt_char == 32'h53) || (fmt_char == 32'h73))
341 tmp_str = { {pad_cnt {" "} }, tmp_str };
342 else
343 tmp_str = { {pad_cnt {"0"} }, tmp_str };
344 }
345 }
346
347 // Concatenate the arg, or the next char in fmt, either way it is in
348 // tmp_str, to the message str
349 mesg_str = { mesg_str, tmp_str };
350 }
351
352 // Finally, print the freakin message!
353 printf("%s%s\n", pre_mesg_str, mesg_str);
354 }
355}
356
357/*
358 * Test complete standard format.
359 */
360task Mesg::print_test_complete() {
361 // Change the debug level to info in case it is currently < info, in whic
362 // case this TEST COMPLETE message won't be printed. Also, save the current
363 // level and restore it, just in case someone is calling this within a
364 // test for some reason, I can't necessarily assume this will only be called
365 // when the test exits.
366 Mesg_level prev = f_debug_level;
367 f_debug_level = e_mesg_info;
368 printf("\n");
369 if ( get_error_count() == 0 ) {
370 print(e_mesg_info,
371 " ",
372 " ",
373 "Simulation reach GOOD End\n");
374 os_command("banner PASS");
375 }
376 else
377 {
378 print(e_mesg_info,
379 " ",
380 " ",
381 "TEST COMPLETE. TOTAL ERRORS: %d TOTAL WARNINGS: %d\n",
382 get_error_count(), get_warning_count());
383 os_command("banner FAIL");
384 }
385
386 f_debug_level = prev;
387
388}