// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: cMesg.vr
// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// For the avoidance of doubt, and except that if any non-GPL license
// choice is available it will apply instead, Sun elects to use only
// the General Public License version 2 (GPLv2) at this time for any
// software where a choice of GPL license versions is made
// available with the language indicating that GPLv2 or any later version
// may be used, or where a choice of which version of the GPL is applied is
// otherwise unspecified.
// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
// CA 95054 USA or visit www.sun.com if you need additional information or
// ========== Copyright Header End ============================================
#include <vera_defines.vrh>
local Mesg_level f_debug_level;
static local integer f_error_count;
static local integer f_warning_count;
function Mesg_level get_debug_level ();
function integer get_error_count ();
function integer get_warning_count ();
task new(Mesg_level level = e_mesg_info);
task set_debug_level (Mesg_level level);
task print(Mesg_level level,
(bit [511:0] fmt_arg0 = 0,
bit [511:0] fmt_arg1 = 0,
bit [511:0] fmt_arg2 = 0,
bit [511:0] fmt_arg3 = 0,
bit [511:0] fmt_arg4 = 0,
bit [511:0] fmt_arg5 = 0,
bit [511:0] fmt_arg6 = 0,
bit [511:0] fmt_arg7 = 0,
bit [511:0] fmt_arg8 = 0,
bit [511:0] fmt_arg9 = 0)
task print_test_complete();
task Mesg::new(Mesg_level level = e_mesg_info) {
f_debug_level = e_mesg_info;
function integer Mesg::get_error_count () {
get_error_count = f_error_count;
function integer Mesg::get_warning_count () {
get_warning_count = f_warning_count;
* I wish we could make this callable only ONCE, no ??
task Mesg::set_debug_level (Mesg_level level) {
if (level < e_mesg_warning)
"Can not set debug level < e_mesg_warning");
sprintf(level_str, "Set debug level to %s", level);
function Mesg_level Mesg::get_debug_level () {
get_debug_level = f_debug_level;
* print(level, id_string, src_string, fmt_string, [int] ...10... [int]);
* e_mesg_error (increments error count)
* e_mesg_warning (increments warning count)
* Formatted output: string (%s %S)
* Field width specifiers ignored (eg, %2d).
* Up to 10 optional arguments, int or castable to int, or string.
* Error, warning and info messages cannot be turned off.
* Debug statements output only if mesg_debug_level <= set_debug_level, otherwise
* absolutely nothing happens.
* Minimum field widths used.
* Format type letter follows argument, except integers, eg: 20, 110001b, 32fah, 7403o
* Newline automaticly inserted, but additional ones are acceptable.
* *** ERROR [hi_time][lo_time]<id_str><src_str> formatted_message_str
* WARNING [hi_time][lo_time]<id_str><src_str> formatted_message_str
* e_mesg_info, e_mesg_debug#:
* [hi_time][lo_time]<id_str><src_str> formatted_message_str
task Mesg::print (Mesg_level level,
(bit [511:0] fmt_arg0 = 0,
bit [511:0] fmt_arg1 = 0,
bit [511:0] fmt_arg2 = 0,
bit [511:0] fmt_arg3 = 0,
bit [511:0] fmt_arg4 = 0,
bit [511:0] fmt_arg5 = 0,
bit [511:0] fmt_arg6 = 0,
bit [511:0] fmt_arg7 = 0,
bit [511:0] fmt_arg8 = 0,
bit [511:0] fmt_arg9 = 0)
integer time_lo, time_hi;
integer i, fmt_char, next_char, fmt_arg_idx = 0, mesg_idx = 0, j, pad_cnt, got_cnt;
bit [511:0] fmt_args[10];
string pre_mesg_str, mesg_str, tmp_str;
* If level is less than the specified debug level,
* we want to process this thing, else do absolutely nothing.
if (level <= f_debug_level) {
* Put the args in the arg array
sprintf(pre_mesg_str, "%0d ", time_lo);
sprintf(pre_mesg_str, "%0d%0d ", time_hi, time_lo);
if (level == e_mesg_error) {
else if (level == e_mesg_warning) {
else if (level == e_mesg_info)
else if (level == e_mesg_debug1)
else if (level == e_mesg_debug2)
else if (level == e_mesg_debug3)
else if (level == e_mesg_debug4)
// put message level in pre-mesg
pre_mesg_str = { pre_mesg_str, tmp_str };
sprintf(tmp_str, "%s ", src_str);
sprintf(tmp_str, "%s %s ", id_str, src_str);
// put source in pre-mesg
pre_mesg_str = { pre_mesg_str, tmp_str };
* Now process the format (fmt_str).
* Assemble the message (mesg_str).
for (i = 0; i < fmt_str.len(); i++, mesg_idx++) {
next_char = fmt_str.getc(i);
// If the char is anything but %, we want to print it to the mesg
sprintf(tmp_str, "%c", next_char);
// If the char is %, then print the next arg to the mesg
got_cnt = 0; //tells if a pad count was received -- acts as a Boolean
// The next fmt_char may have the format
fmt_char = fmt_str.getc(++i);
// If the fmt_char is an integer, then this is a case s.a. %2d, so
if ( (fmt_char >= 32'h30) && (fmt_char <= 32'h39) ){
// j = the number of spaces wanted
// Save this number of spaces and then increment to the next character
// which will be the type.
fmt_char = fmt_str.getc(++i);
// If the fmt arg has any x's, we must print %b format, so override fmt_arg
is_x = ^fmt_args[fmt_arg_idx];
sprintf(tmp_str, "%0bb", fmt_args[fmt_arg_idx++]);
pad_cnt = ( j + 1 - tmp_str.len() );
sprintf(tmp_str, "%0c", fmt_args[fmt_arg_idx++]);
pad_cnt = ( j - tmp_str.len() );
sprintf(tmp_str, "%0d", fmt_args[fmt_arg_idx++]);
pad_cnt = ( j - tmp_str.len() );
32'h48, 32'h58, 32'h68, 32'h78:{
sprintf(tmp_str, "%0hh", fmt_args[fmt_arg_idx++]);
pad_cnt = ( j + 1 - tmp_str.len() );
sprintf(tmp_str, "%0oo", fmt_args[fmt_arg_idx++]);
pad_cnt = ( j + 1 - tmp_str.len() );
sprintf(tmp_str, "%0s", fmt_args[fmt_arg_idx++]);
pad_cnt = ( j - tmp_str.len() );
sprintf(tmp_str, "NO_FMT");
// If user requested a field width and the argument didn't take up
// the whole field, pad with zeroes for nums, and spaces for strings.
if (( got_cnt == 1 ) && ( pad_cnt > 0 )) {
if ((fmt_char == 32'h53) || (fmt_char == 32'h73))
tmp_str = { {pad_cnt {" "} }, tmp_str };
tmp_str = { {pad_cnt {"0"} }, tmp_str };
// Concatenate the arg, or the next char in fmt, either way it is in
// tmp_str, to the message str
mesg_str = { mesg_str, tmp_str };
// Finally, print the freakin message!
printf("%s%s\n", pre_mesg_str, mesg_str);
* Test complete standard format.
task Mesg::print_test_complete() {
// Change the debug level to info in case it is currently < info, in whic
// case this TEST COMPLETE message won't be printed. Also, save the current
// level and restore it, just in case someone is calling this within a
// test for some reason, I can't necessarily assume this will only be called
Mesg_level prev = f_debug_level;
f_debug_level = e_mesg_info;
if ( get_error_count() == 0 ) {
"Simulation reach GOOD End\n");
os_command("banner PASS");
"TEST COMPLETE. TOTAL ERRORS: %d TOTAL WARNINGS: %d\n",
get_error_count(), get_warning_count());
os_command("banner FAIL");