Commit | Line | Data |
---|---|---|
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 | ||
47 | class 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 | //---------------------------------------------------------- | |
71 | task BaseUtils::new(StandardDisplay dbgHndl, integer clockPeriod = 100) { | |
72 | this.dbg = dbgHndl; | |
73 | this.clockPeriod = clockPeriod; | |
74 | } | |
75 | ||
76 | task 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 | |
85 | function 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 | |
107 | task BaseUtils::dumpFailing() { | |
108 | printf ("[dumpFailing] Nothing to Dump: Need to override this method\n"); | |
109 | } | |
110 | ||
111 | task BaseUtils::startTimer () { | |
112 | startTime = 0; // review, NTB cant get_systime(); | |
113 | } | |
114 | ||
115 | //---------------------------------------------------------- | |
116 | // Placeholders - expect to be extended in bench | |
117 | task 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. | |
138 | task 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. | |
221 | task 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 | //---------------------------------------------------------- | |
288 | function 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. | |
302 | function 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 | } |