Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / common / vera / classes / baseUtilsClass.vr
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: baseUtilsClass.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 "std_display_defines.vri"
37#include "std_display_class.vrh"
38#include "plusArgMacros.vri"
39
40// if your bench does not use any common Verilog error detection,
41// define NO_VERILOG_ERRORS so that code gets excluded from here!
42
43#ifndef NO_VERILOG_ERRORS
44#include "errorCountTasks.if.vrh"
45#endif
46
47class BaseUtils {
48
49 local string className = "baseUtilsClass";
50 local StandardDisplay dbg;
51 local integer startTime = 0;
52 local integer clockPeriod;
53
54 task new(StandardDisplay dbgHndl, integer clockPeriod = 100);
55 function reg [63:0] list2vector(string thrstr);
56 task dumpFailing();
57 task startTimer();
58 task dumpStats();
59 task wait4termination(integer maxCycle=0);
60 task exitBench(string scope=null, string message="",
61 reg noPrint=0, reg externalFail=0);
62
63 function reg file_exists(string filename, string mode);
64 function reg [39:0] hashpa(reg [39:0] pa);
65 task updateClockPeriod(integer period);
66}
67
68
69
70//----------------------------------------------------------
71task BaseUtils::new(StandardDisplay dbgHndl, integer clockPeriod = 100) {
72 this.dbg = dbgHndl;
73 this.clockPeriod = clockPeriod;
74}
75
76task BaseUtils::updateClockPeriod(integer period) {
77 if (this.clockPeriod != period)
78 dbg.dispmon("baseUtils", MON_ALWAYS,
79 psprintf("clockPeriod updated to %0d",clockPeriod));
80 this.clockPeriod = period;
81}
82
83
84// Extract vector from comma seperated string
85function reg [63:0] BaseUtils::list2vector(string thrstr) {
86 string tempstr;
87 integer i;
88
89 list2vector = 0;
90
91 if (thrstr.match("^all$")) {
92 list2vector = 64'hffffffffffffffff;
93 } else if (thrstr.match("^none$")) {
94 list2vector = 0;
95 } else {
96 for (i=0;i<thrstr.len();i++) {
97 tempstr.bittostr(thrstr.getc(i));
98 if (tempstr != ",") {
99 list2vector[tempstr.atoi()] = 1;
100 }
101 }
102 }
103}
104
105//----------------------------------------------------------
106// Placeholders - expect to be extended in bench
107task BaseUtils::dumpFailing() {
108 printf ("[dumpFailing] Nothing to Dump: Need to override this method\n");
109}
110
111task BaseUtils::startTimer () {
112 startTime = 0; // review, NTB cant get_systime();
113}
114
115//----------------------------------------------------------
116// Placeholders - expect to be extended in bench
117task BaseUtils::dumpStats () {
118 integer endTime;
119 integer cycleCount;
120 integer simTime;
121
122 endTime = 2; // review, NTB cant get_systime();
123 cycleCount = get_cycle();
124 simTime = endTime - startTime;
125 if (simTime <1) simTime = 1;
126
127 printf ("\nINFO >> Simulation CPS = %0d [%0d cycles in %0d secs]\n\n",
128 cycleCount/simTime, cycleCount, simTime);
129}
130
131
132// Will wait for too many errors, too much time,
133// too many clocks, too many idle cycles etc.
134// Will NOT participate in a natural "good end".
135//
136// This is for certain benches. You may want to redefine this
137// in your class that extends this.
138task BaseUtils::wait4termination(integer maxCycle=0) {
139
140 // combine Verilog and Vera counts
141 integer myErrors[2]; // = {0,0};
142 integer myWarns[2]; // = {0,0};
143 integer previousCountE[2]; // = {0,0};
144 integer previousCountW[2]; // = {0,0};
145 integer i;
146
147 // for NTB
148 for (i=0;i<2;i++) {
149 myErrors[i] = 0;
150 myWarns[i] = 0;
151 previousCountE[i] = 0;
152 previousCountW[i] = 0;
153 }
154
155
156 fork // too many errors
157#ifndef NO_VERILOG_ERRORS
158 {
159 // watch verilog errors. you can see an inc of > 1...
160 while (1) {
161 @(errorCount_if.errorCount or errorCount_if.warnCount);
162 myErrors[0] += (errorCount_if.errorCount - previousCountE[0]);
163 previousCountE[0] = errorCount_if.errorCount;
164 myWarns[0] += (errorCount_if.warnCount - previousCountW[0]);
165 previousCountW[0] = errorCount_if.warnCount;
166 }
167 }
168#endif
169 {
170 // watch vera errors. you can see an inc of > 1...
171 while (1) {
172 wait_var(dbg.errors, dbg.warnings);
173 myErrors[1] += (dbg.errors - previousCountE[1]);
174 previousCountE[1] = dbg.errors;
175 myWarns[1] += (dbg.warnings - previousCountW[1]);
176 previousCountW[1] = dbg.warnings;
177 }
178 }
179 {
180 while ((myErrors[0] + myErrors[1]) < dbg.maxerror &&
181 (myWarns[0] + myWarns[1]) < dbg.maxwarning)
182 wait_var(myErrors[0],myWarns[0],myErrors[1],myWarns[1]);
183
184 exitBench(*, // scope
185 *, // message
186 myErrors[0] > 0 ? 1 : 0, // no vera print, verilog will
187 1); // force a fail
188 }
189
190 // too many clocks
191 // NOTE: get_cycle is based on Vera's SystemClock and may not
192 // match your particular concept of what a "cycle" is in your bench!
193 {
194 if ((maxCycle > 0) && (clockPeriod > 0)) {
195 while (1) {
196 // Please to not check every clock!
197 // delay is measurably better than repeat (x) @(posedge CLOCK).
198 // I asked Synopsys to measure it, really.
199 delay(this.clockPeriod*500);
200 if (get_cycle() >= maxCycle) {
201 dbg.dispmon("baseUtils", MON_ALWAYS,
202 psprintf("Max cycles of %0d exceeded (Vera)! Exiting with ERRORs...",maxCycle));
203 }
204 }
205 }
206 }
207
208 join none
209
210
211}
212
213
214
215//----------------------------------------------------------
216// This task may not be reached if the bench fails for some
217// other reason like a call to error(), expect error, std_display_class
218// deciding there are too many errors, etc.
219// It is suggested that this be the last thing you do when you
220// think that you are done.
221task BaseUtils::exitBench(string scope=null,
222 string message="",
223 reg noPrint=0, // set if you know Verilog will print FAIL
224 reg externalFail=0) {
225 string tmpstr;
226 reg [1024:0] testNameVera,testNameAsm,testNameAlt;
227 integer seedFileHndl, errors, warns, weFailed=0;
228
229 if (message == null) message = " ";
230
231 // check VERA error count
232 dbg.getCounts(errors,warns);
233 if (errors || (warns >= dbg.maxwarning) || externalFail) weFailed = 1;
234
235 // If you are using seeding.vri, this will update seeds.log with status.
236 seedFileHndl = fopen( "./seeds.log", "a" );
237 if ( seedFileHndl !== 0 ) {
238 if (mChkPlusarg(vera_diag_name=)) mGetPlusargStr(vera_diag_name=,testNameVera);
239 if (mChkPlusarg(asm_diag_name=)) mGetPlusargStr(asm_diag_name=,testNameAsm);
240 if (mChkPlusarg(test=)) mGetPlusargStr(test=,testNameAlt);
241 if (weFailed) {
242 fprintf(seedFileHndl, "Diag %s %s %s FAILED! Use this seed...\n", testNameVera, testNameAsm, testNameAlt, errors, warns);
243 } else {
244 fprintf(seedFileHndl, "Diag %s %s %s possibly PASSED. If you don't see PASSED, it may have hung.\n", testNameVera, testNameAsm, testNameAlt);
245 }
246 fclose(seedFileHndl);
247 }
248
249 // if we are not printing this stuff in verilog, print it here in vera!
250 // if both Vera and Verilog are checking for errors, this text may get
251 // printed by both Vera and Verilog.
252 if (noPrint == 0) {
253 if (scope == null) scope = className;
254
255 if (weFailed) {
256 printf("\n");
257 // regreport needs "ERROR". Do not alter.
258 sprintf(tmpstr, "Diag Finished/Failed with ERRORs! %s\n", message);
259 dbg.dispmon(scope, MON_ALWAYS, tmpstr);
260 // NOTE: CLOCK is based on Vera's SystemClock and may not
261 // match your particular concept of what a "clock" or "cycle" is in your bench!
262 repeat (dbg.wait_cycle_to_kill) @(posedge CLOCK);
263 } else {
264 printf("\n");
265 // regreport needs "GOOD End". Do not alter.
266 //
267 // Reaching "GOOD End" does not imply passing. The word PASS shall never
268 // be printed, ever! That is up to regreport to decide. This assumes a Sparc
269 // bench and regreport being in use although I expect regreport to be used for
270 // all simulations that are not Sparc based.
271 sprintf(tmpstr, "Diag Reached GOOD End! (pre-regreport checking) %s\n", message);
272 dbg.dispmon(scope, MON_ALWAYS,tmpstr);
273 // will remove following later after sims gets changed
274 sprintf(tmpstr, "regreport will determine if diag has really PASSED\n");
275 dbg.dispmon(scope, MON_ALWAYS,tmpstr);
276 }
277
278 sprintf(tmpstr, "regreport clock period: %0d units\n", this.clockPeriod);
279 dbg.dispmon(scope, MON_ALWAYS,tmpstr);
280
281 exit(errors);
282 }
283
284}
285
286
287//----------------------------------------------------------
288function reg BaseUtils::file_exists(string filename, string mode) {
289 integer FP;
290
291 FP = fopen(filename, mode, SILENT);
292 if (FP === 0) {
293 file_exists = 0;
294 } else {
295 file_exists = 1;
296 }
297 fclose (FP);
298}
299
300//----------------------------------------------------------
301// It is assumed that gParam.hash_on is checked before calling the routine.
302function reg [39:0] BaseUtils::hashpa(reg [39:0] pa) {
303
304 hashpa = pa;
305 hashpa [17:11] = {(pa[32:28]^pa[17:13]),(pa[19:18]^pa[12:11])};
306}