Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: nas_top.v | |
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 | `timescale 1 ps/ 1 ps | |
36 | ||
37 | module nas_top; | |
38 | ||
39 | `include "defines.vh" | |
40 | `include "nas.vh" | |
41 | ||
42 | integer act_queue; // Actual (DUT) queue handle | |
43 | integer exp_queue; // Expected (Ref Model) queue handle | |
44 | reg [63:0] act_status; // if 0, empty. if 1, not empty. | |
45 | reg [63:0] exp_status; | |
46 | reg [2:0] th_cwp [0:63]; // copy of CWP updated by nas_pipe.v | |
47 | reg [2:0] th_currcwp [0:63]; // copy of CWP currently checked | |
48 | integer tindex; | |
49 | integer delta_cnt; | |
50 | integer oldest_actid; // Oldest TID in exp_actual Queue | |
51 | integer err_cnt [63:0]; | |
52 | reg [63:0] sstep_sent; // Asserted if SSTEP was already sent | |
53 | // by another module (i.e. tlb_sync,ldst_sync,int_sync) | |
54 | reg [63:0] sstep_early; // Asserted if SSTEP was sent before | |
55 | // nas_pipe captured state changes | |
56 | integer last_skt_cycle;// Timer used for socket timeout | |
57 | ||
58 | // wires for asm user events | |
59 | `include "asmEventsProbes.vh" | |
60 | ||
61 | reg [63:0] good_trap_detected; // Good_trap, but wait for stb empty | |
62 | ||
63 | // wires for lsu_stb_empty, ireq_pending | |
64 | `include "nas_top_inc.vh" | |
65 | ||
66 | //---------------------------------------------------------- | |
67 | // Instantiate 1-8 cores | |
68 | `ifdef CORE_0 | |
69 | nas_core0 c0 (3'h0); | |
70 | `endif | |
71 | `ifdef CORE_1 | |
72 | nas_core1 c1 (3'h1); | |
73 | `endif | |
74 | `ifdef CORE_2 | |
75 | nas_core2 c2 (3'h2); | |
76 | `endif | |
77 | `ifdef CORE_3 | |
78 | nas_core3 c3 (3'h3); | |
79 | `endif | |
80 | `ifdef CORE_4 | |
81 | nas_core4 c4 (3'h4); | |
82 | `endif | |
83 | `ifdef CORE_5 | |
84 | nas_core5 c5 (3'h5); | |
85 | `endif | |
86 | `ifdef CORE_6 | |
87 | nas_core6 c6 (3'h6); | |
88 | `endif | |
89 | `ifdef CORE_7 | |
90 | nas_core7 c7 (3'h7); | |
91 | `endif | |
92 | ||
93 | //---------------------------------------------------------- | |
94 | // Queue and Socket Initialization | |
95 | ||
96 | initial begin: INIT_BLOCK // { | |
97 | integer i; | |
98 | ||
99 | ||
100 | @ (negedge `SYSTEMCLOCK); | |
101 | if (`PARGS.nas_check_on) begin // { | |
102 | `PR_INFO("nas", `INFO, "Init actual_queue, expect_queue"); | |
103 | act_status = 64'h0; | |
104 | exp_status = 64'h0; | |
105 | sstep_sent = 64'h0; | |
106 | sstep_early = 64'h0; | |
107 | exp_queue = $queue(`EXP_QUEUE, `INIT_Q); | |
108 | act_queue = $queue(`ACT_QUEUE, `INIT_Q); | |
109 | $socket_init(); | |
110 | for (i=0;i<=63;i=i+1) begin | |
111 | err_cnt[i] = 0; | |
112 | end | |
113 | end //} | |
114 | good_trap_detected = 64'h0; | |
115 | last_skt_cycle = 0; | |
116 | // Initialize shadow copy of CWP for each thread | |
117 | for (i=0;i<=63; i=i+1) begin | |
118 | th_cwp[i] = 3'b0; | |
119 | th_currcwp[i] = 3'b0; | |
120 | end | |
121 | ||
122 | end // } | |
123 | ||
124 | ||
125 | //---------------------------------------------------------- | |
126 | // Read & parse socket if ready | |
127 | ||
128 | always begin : NAS_CHECK // { | |
129 | integer i; | |
130 | repeat (`PARGS.nas_q_rate/2) @ (negedge `SYSTEMCLOCK); | |
131 | ||
132 | if (`PARGS.nas_check_on && (`ACT_STATUS & `PARGS.th_check_enable)) begin // { BITWISE & ! | |
133 | if (`PARGS.socket_use_flush) $sim_flush(); | |
134 | repeat (`PARGS.nas_q_rate/2) @ (negedge `SYSTEMCLOCK); | |
135 | `EXP_STATUS = $sim_recv(`EXP_QUEUE, `ACT_QUEUE, oldest_actid); | |
136 | while (`EXP_STATUS[oldest_actid]&& | |
137 | `ACT_STATUS[oldest_actid]&& | |
138 | `PARGS.th_check_enable[oldest_actid]) begin // { | |
139 | cmp_queue (oldest_actid); | |
140 | last_skt_cycle = `TOP.core_cycle_cnt; | |
141 | end // } | |
142 | if (`PARGS.socket_use_flush) $sim_flush(); | |
143 | end // } | |
144 | ||
145 | // Check for socket timeout (i.e. no socket msgs coming from NAS) | |
146 | if (`PARGS.nas_check_on && (`TOP.core_cycle_cnt - last_skt_cycle) > `PARGS.skt_timeout) | |
147 | begin // { | |
148 | ||
149 | // Note: Do not change this message because regreport parses it for certain words. | |
150 | `PR_ALWAYS ("top", `ALWAYS, "ERROR: No Socket msgs received from NAS for %0d Cycles - Socket TIMEOUT!", | |
151 | `PARGS.skt_timeout); | |
152 | bad_end; | |
153 | end //} | |
154 | ||
155 | // Wait for special conditions before stopping all messages for a thread to be sent. | |
156 | if (|good_trap_detected) begin // { | |
157 | for (i=0;i<=63;i=i+1) begin // { | |
158 | if (good_trap_detected[i] & lsu_stb_empty[i] & ireq_pending[i]) begin // { | |
159 | `PR_NORMAL("nas", `NORMAL, "T%0d reached Good Trap. Disabling checking for thread %0d", | |
160 | i, i); | |
161 | `PARGS.th_check_enable[i] = 1'b0; | |
162 | `TOP.finished_tids[i] = 1'b1; | |
163 | `EXP_STATUS = $queue(`EXP_QUEUE, `FLUSH_TH_Q, i); | |
164 | `ACT_STATUS = $queue(`ACT_QUEUE, `FLUSH_TH_Q, i); | |
165 | good_trap_detected[i] = 1'b0; | |
166 | end //} | |
167 | end // } | |
168 | end //} | |
169 | ||
170 | end // } | |
171 | ||
172 | //---------------------------------------------------------- | |
173 | // Compare actual_queue, expect_queue | |
174 | ||
175 | task cmp_queue; | |
176 | ||
177 | input [5:0] tnum; | |
178 | ||
179 | reg [63:0] exp_tstamp; | |
180 | reg [63:0] act_tstamp; | |
181 | integer exp_regnum; | |
182 | integer act_regnum; | |
183 | integer exp_level; | |
184 | integer act_level; | |
185 | integer exp_win; | |
186 | integer act_win; | |
187 | reg [63:0] exp_value; | |
188 | reg [63:0] act_value; | |
189 | reg [7:0] exp_type; | |
190 | reg [7:0] act_type; | |
191 | reg [63:0] value_mask; | |
192 | reg [(20*8)-1:0] exp_regname; | |
193 | reg [(20*8)-1:0] act_regname; | |
194 | ||
195 | integer i; | |
196 | ||
197 | begin : CMP_BLOCK // { | |
198 | ||
199 | delta_cnt = 0; | |
200 | ||
201 | //---------- | |
202 | // Pop while exp_queue is oldest and not empty | |
203 | // Or has an error pending and needs to drain act_queue to get timestamps | |
204 | while (err_cnt[tnum] || (`EXP_STATUS[tnum] && `ACT_STATUS[tnum] && | |
205 | (oldest_actid == tnum))) begin : STATUS_BLOCK // { | |
206 | // If error has occurred, find instruction boundary, | |
207 | // print instruction, then kill simulation | |
208 | if (err_cnt[tnum] != 0) begin // { | |
209 | `NASTOP.delta_cnt = 0; | |
210 | $display ("\nDumping remaining ACTUAL deltas .."); | |
211 | print_delta (tnum,act_type,act_win,act_regnum,act_value); | |
212 | act_regnum = 0; | |
213 | while (act_regnum != `END_INSTR) begin // { | |
214 | `ACT_STATUS = $queue(`ACT_QUEUE, `POP_Q, tnum, act_tstamp, act_type, | |
215 | act_level, act_win, act_regnum, act_value, | |
216 | oldest_actid); | |
217 | `PR_DEBUG("nas", `DEBUG, "Act Queue: T%0d, \"%s\", GL=%0d, CWP=%0d, Reg=%0d, %h", | |
218 | tnum, act_type, act_level, act_win, act_regnum, act_value); | |
219 | ||
220 | print_delta (tnum,act_type,act_win,act_regnum,act_value); | |
221 | end // } | |
222 | `EXP_STATUS = $queue(`EXP_QUEUE, `PR_INSTR_Q, tnum, act_value, | |
223 | act_tstamp, "", "FAILED!"); | |
224 | disable NAS_CHECK; | |
225 | end // } | |
226 | ||
227 | ||
228 | `EXP_STATUS = $queue(`EXP_QUEUE, `POP_Q, tnum, exp_tstamp, exp_type, | |
229 | exp_level, exp_win, exp_regnum, exp_value); | |
230 | ||
231 | `PR_DEBUG("nas", `DEBUG, "Exp Queue: T%0d, \"%s\", GL=%0d, CWP=%0d, reg=%0d, %h", | |
232 | tnum, exp_type, exp_level, exp_win, exp_regnum, exp_value); | |
233 | //---------- | |
234 | // Only proceed if thread checking still enabled .. | |
235 | if (`PARGS.th_check_enable[tnum]) begin // { | |
236 | if (`PARGS.show_delta_on) begin // { | |
237 | print_delta (tnum,exp_type,exp_win,exp_regnum,exp_value); | |
238 | end // } | |
239 | ||
240 | //---------- | |
241 | if (check_this_one(exp_type,exp_regnum)) begin:CHECK_THIS // { | |
242 | ||
243 | `ACT_STATUS = $queue(`ACT_QUEUE, `POP_Q, tnum, act_tstamp, act_type, | |
244 | act_level, act_win, act_regnum, act_value, | |
245 | oldest_actid); | |
246 | ||
247 | `PR_DEBUG("nas", `DEBUG, "Act Queue: T%0d, \"%s\", GL=%0d, CWP=%0d, reg=%0d, %h", | |
248 | tnum, act_type, act_level, act_win, act_regnum, act_value); | |
249 | ||
250 | if (!check_this_one(act_type,act_regnum)) begin // { | |
251 | if (exp_regnum ==`END_INSTR) begin // { | |
252 | `EXP_STATUS = $queue(`EXP_QUEUE, `PR_INSTR_Q, tnum, act_value, | |
253 | act_tstamp, "", "OK"); | |
254 | if (`PARGS.show_delta_on) | |
255 | get_regname(tnum,act_type,act_win,act_regnum,act_regname); | |
256 | while (act_regnum != `END_INSTR) begin // { | |
257 | `ACT_STATUS = $queue(`ACT_QUEUE, `POP_Q, tnum, act_tstamp, act_type, | |
258 | act_level, act_win, act_regnum, act_value, | |
259 | oldest_actid); | |
260 | `PR_DEBUG("nas", `DEBUG, "Act Queue: T%0d, \"%s\", GL=%0d, CWP=%0d, reg=%0d, %h", | |
261 | tnum, act_type, act_level, act_win, act_regnum, act_value); | |
262 | delta_cnt = 0; | |
263 | end // } | |
264 | disable STATUS_BLOCK; | |
265 | end //} | |
266 | disable CHECK_THIS; | |
267 | end // } | |
268 | ||
269 | //---------- | |
270 | if ((act_regnum ==`END_INSTR)&&(exp_regnum ==`END_INSTR)) begin // { | |
271 | // End of Instr - w/o errors | |
272 | // Print Instruction & Pop next Instruction | |
273 | if (err_cnt[tnum] == 0) begin // { | |
274 | `EXP_STATUS = $queue(`EXP_QUEUE, `PR_INSTR_Q, tnum, act_value, | |
275 | act_tstamp, "", "OK"); | |
276 | delta_cnt = 0; | |
277 | if (`PARGS.show_delta_on) | |
278 | get_regname(tnum,act_type,act_win,act_regnum,act_regname); | |
279 | disable STATUS_BLOCK; | |
280 | end // } | |
281 | // End of Instr - w/ errors | |
282 | else begin // { | |
283 | `EXP_STATUS = $queue(`EXP_QUEUE, `PR_INSTR_Q, tnum, act_value, | |
284 | act_tstamp, "", "FAILED!"); | |
285 | disable NAS_CHECK; | |
286 | end // } | |
287 | end // } | |
288 | // End of Instr - w/ errors (Act finished unexpectedly) | |
289 | else if ((act_regnum ==`END_INSTR)&&(exp_regnum !=`END_INSTR)) | |
290 | begin // { | |
291 | if (`PARGS.show_delta_on) begin $display(); end | |
292 | get_regname(tnum,exp_type,exp_win,exp_regnum,exp_regname); | |
293 | // Print failing expect register if show_delta OFF | |
294 | if (!`PARGS.show_delta_on) begin // { | |
295 | print_delta (tnum,exp_type,exp_win,exp_regnum,exp_value); | |
296 | $display(); | |
297 | end // } | |
298 | `PR_ERROR("nas", `ERROR, "@%0d T%0d - DUT Reg did not change: Exp %0s = %h. \n", | |
299 | act_tstamp, tnum,exp_regname,exp_value); | |
300 | `EXP_STATUS = $queue(`EXP_QUEUE, `PR_INSTR_Q, tnum, act_value, | |
301 | act_tstamp, "", "FAILED!"); | |
302 | show_unchecked_delta(tnum); | |
303 | disable NAS_CHECK; | |
304 | end // } | |
305 | // End of Instr - w/ errors (Act not finished) | |
306 | else if ((act_regnum !=`END_INSTR)&&(exp_regnum ==`END_INSTR)) | |
307 | begin // { | |
308 | if (`PARGS.show_delta_on) begin $display(); end | |
309 | get_regname(tnum,act_type,act_win,act_regnum,act_regname); | |
310 | `PR_ERROR ("nas", `ERROR, "@%0d T%0d - Unexpected Reg change in DUT. %0s = %h.\n", | |
311 | act_tstamp, tnum,act_regname,act_value); | |
312 | // Don't know address until DUT reaches END_INSTR .. | |
313 | err_cnt[tnum] = err_cnt[tnum] + 1; | |
314 | disable CHECK_THIS; | |
315 | end // } | |
316 | ||
317 | //---------- | |
318 | // Not End of Instr | |
319 | // So, continue checking this instruction | |
320 | ||
321 | // Exclude %g0 from this check since %g0 is used for ldst_sync/tlb_sync error indication | |
322 | // and global level may not be correct. | |
323 | if ((exp_type=="G")&&(act_type=="G") && (exp_level != act_level) && (exp_regnum != 0)) begin // { | |
324 | err_cnt[tnum] = err_cnt[tnum] + 1; | |
325 | if (`PARGS.show_delta_on) begin $display(); end | |
326 | `PR_ERROR ("nas", `ERROR, "@%0d T%0d - Wrong Global Level. Act = %0h. Exp = %0h.\n", | |
327 | act_tstamp, tnum, act_level,exp_level); | |
328 | end // } | |
329 | ||
330 | if (exp_regnum ==`PC || exp_regnum == `NPC) begin // { | |
331 | value_mask = `PC_MASK; | |
332 | end // } | |
333 | else if (exp_regnum == `TBA ||exp_regnum == `HTBA || | |
334 | exp_regnum ==`TPC1 || exp_regnum == `TNPC1 || | |
335 | exp_regnum ==`TPC2 || exp_regnum == `TNPC2 || | |
336 | exp_regnum ==`TPC3 || exp_regnum == `TNPC3 || | |
337 | exp_regnum ==`TPC4 || exp_regnum == `TNPC4 || | |
338 | exp_regnum ==`TPC5 || exp_regnum == `TNPC5 || | |
339 | exp_regnum ==`TPC6 || exp_regnum == `TNPC6 || | |
340 | exp_regnum ==`I_TAG_ACC || exp_regnum ==`D_TAG_ACC || | |
341 | exp_regnum ==`WATCHPOINT_ADDR | |
342 | ) | |
343 | begin // { | |
344 | value_mask = `MASK_48 ; | |
345 | end //} | |
346 | else begin // { | |
347 | value_mask = 64'hffff_ffff_ffff_ffff; | |
348 | end // } | |
349 | ||
350 | if ((exp_type != act_type) || | |
351 | (exp_regnum != act_regnum) || | |
352 | ((exp_type =="W") && (exp_win != act_win)))begin // { | |
353 | err_cnt[tnum] = err_cnt[tnum] + 1; | |
354 | // Print failing expect register if show_delta OFF | |
355 | if (!`PARGS.show_delta_on) begin // { | |
356 | print_delta (tnum,exp_type,exp_win,exp_regnum,exp_value); | |
357 | $display(); | |
358 | end // } | |
359 | if (exp_regnum > act_regnum) begin // { | |
360 | if (`PARGS.show_delta_on) begin $display(); end | |
361 | get_regname(tnum,act_type,act_win,act_regnum,act_regname); | |
362 | `PR_ERROR ("nas", `ERROR, "@%0d T%0d - Unexpected Reg Change: DUT %0s = %h.\n", | |
363 | act_tstamp, tnum,act_regname,act_value); | |
364 | end // } | |
365 | else if (exp_regnum < act_regnum) begin // { | |
366 | if (`PARGS.show_delta_on) begin $display(); end | |
367 | get_regname(tnum,exp_type,exp_win,exp_regnum,exp_regname); | |
368 | `PR_ERROR ("nas", `ERROR, "@%0d T%0d - DUT Reg did not change: Exp %0s = %h.\n", | |
369 | act_tstamp, tnum,exp_regname, exp_value); | |
370 | end // } | |
371 | else begin // { | |
372 | if (`PARGS.show_delta_on) begin $display(); end | |
373 | get_regname(tnum,exp_type,exp_win,exp_regnum,exp_regname); | |
374 | get_regname(tnum,act_type,act_win,act_regnum,act_regname); | |
375 | `PR_ERROR ("nas", `ERROR, "@%0d T%0d - Reg Name Mismatch: DUT = %s, Expect=%0s.\n", | |
376 | act_tstamp, tnum,act_regname,exp_regname); | |
377 | end // } | |
378 | show_unchecked_delta(tnum); | |
379 | disable CHECK_THIS; | |
380 | end // } | |
381 | ||
382 | else if ((exp_value & value_mask) != (act_value & value_mask))begin // { | |
383 | // Suppress error if `OPCODE & value==0 (special case of illtrap where miscmp will happen) | |
384 | // Suppress error if pc[0] is 1 (WMR case, we force pc[0]=1) | |
385 | if ((((exp_regnum==`OPCODE)&&(exp_value!=0)) || | |
386 | (exp_regnum!=`OPCODE)) && | |
387 | (!((act_regnum==`PC)&&(act_value[0]==1))))begin // { | |
388 | err_cnt[tnum] = err_cnt[tnum] + 1; | |
389 | if (`PARGS.show_delta_on) begin $display(); end | |
390 | get_regname(tnum,exp_type,exp_win,exp_regnum,exp_regname); | |
391 | get_regname(tnum,act_type,act_win,act_regnum,act_regname); | |
392 | // Print failing expect register if show_delta OFF | |
393 | if (!`PARGS.show_delta_on) begin // { | |
394 | print_delta (tnum,exp_type,exp_win,exp_regnum,exp_value); | |
395 | $display(); | |
396 | end // } | |
397 | // Special msg for OPCODE miscompare. | |
398 | if (exp_regnum==`OPCODE) begin // { | |
399 | `PR_ERROR ("nas", `ERROR, "@%0d T%0d - Instruction Miscompare: DUT %0s = %h, Exp %0s = %h, Mask = %h.\n", | |
400 | act_tstamp, tnum,act_regname,act_value,exp_regname,exp_value,value_mask); | |
401 | end // } | |
402 | // Generic msg for register miscompare | |
403 | else begin // { | |
404 | `PR_ERROR ("nas", `ERROR, "@%0d T%0d - Reg Value Miscompare: DUT %0s = %h, Exp %0s = %h, Mask = %h.\n", | |
405 | act_tstamp, tnum,act_regname,act_value,exp_regname,exp_value,value_mask); | |
406 | ||
407 | end // } | |
408 | // Special msg for PC/NPC miscompare | |
409 | if ((exp_regnum==`PC)|(exp_regnum==`NPC)) begin // { | |
410 | `PR_NORMAL("nas", `NORMAL, "T%0d PC/NPC are architected state AFTER instruction completes",tnum); | |
411 | `PR_NORMAL("nas", `NORMAL, "T%0d NEXT instruction will be wrong because branch/exception not/incorrectly taken",tnum); | |
412 | ||
413 | end // } | |
414 | show_unchecked_delta(tnum); | |
415 | disable CHECK_THIS; | |
416 | end // } | |
417 | end // } | |
418 | ||
419 | ||
420 | // When th_check_enable is OFF, ldst_sync msgs are disabled. | |
421 | // A Store will retire in the pipeline before the Store is acked in the LSU. | |
422 | // th_check_enable cannot be turned off until all the ldst_sync msgs for the Store are done. | |
423 | // Need to make sure Store Buffer is empty before turning off th_check_enable. | |
424 | // Set good_trap_detected, which will wait for stb_empty to turn of th_check_enable .. | |
425 | for (i=0;i<`PARGS.good_trap_count;i=i+1) | |
426 | if ((exp_regnum==`PC) && | |
427 | (`PC_MASK&exp_value)==(`PC_MASK&`PARGS.good_trap_addr[i])) begin // { | |
428 | if (`PARGS.show_delta_on) $write("\n"); | |
429 | good_trap_detected[tnum] = 1'b1; | |
430 | disable CMP_BLOCK; | |
431 | end // } | |
432 | for (i=0;i<`PARGS.bad_trap_count;i=i+1) | |
433 | if ((exp_regnum==`PC) && | |
434 | (`PC_MASK&exp_value)==(`PC_MASK&`PARGS.bad_trap_addr[i])) begin // { | |
435 | if (`PARGS.show_delta_on) $write("\n"); | |
436 | `PR_ERROR("nas", `ERROR, "T%0d reached Bad Trap.\n",tnum); | |
437 | end // } | |
438 | end // } | |
439 | `ACT_STATUS = $queue(`ACT_QUEUE, `STATUS_Q, `ACT_QUEUE, oldest_actid); | |
440 | end // } | |
441 | ||
442 | end // } | |
443 | ||
444 | end // } | |
445 | endtask | |
446 | ||
447 | ||
448 | //---------------------------------------------------------- | |
449 | // Print exp deltas after a fail is detected .. | |
450 | task show_unchecked_delta; | |
451 | input [5:0] tnum; | |
452 | ||
453 | integer oldest_expid; | |
454 | reg [7:0] exp_type; | |
455 | reg [3:0] exp_level; | |
456 | reg [31:0] exp_win; | |
457 | reg [31:0] exp_regnum; | |
458 | reg [63:0] exp_value, exp_tstamp; | |
459 | begin // { | |
460 | exp_regnum = 0; | |
461 | `NASTOP.delta_cnt = 0; | |
462 | $display ("\nDumping remaining EXPECTED deltas .."); | |
463 | while (exp_regnum != `END_INSTR) begin // { | |
464 | `ACT_STATUS = $queue(`EXP_QUEUE, `POP_Q, tnum, exp_tstamp, | |
465 | exp_type, exp_level, exp_win, | |
466 | exp_regnum, exp_value, oldest_expid); | |
467 | print_delta (tnum,exp_type,exp_win, exp_regnum,exp_value); | |
468 | ||
469 | end // } | |
470 | end //} | |
471 | endtask | |
472 | ||
473 | //---------------------------------------------------------- | |
474 | // Print a register's name and value | |
475 | task print_delta; | |
476 | input [5:0] tnum; | |
477 | input [7:0] type; | |
478 | input [31:0] win; | |
479 | input [31:0] regnum; | |
480 | input [63:0] value; | |
481 | ||
482 | reg [2:0] cid; | |
483 | reg [2:0] tid; | |
484 | reg [(20*8)-1:0] tmp_regname; | |
485 | ||
486 | integer cnt_per_line; | |
487 | ||
488 | begin // { | |
489 | ||
490 | delta_cnt = delta_cnt + 1; | |
491 | if (`TOP.debug) | |
492 | cnt_per_line =1; | |
493 | else | |
494 | cnt_per_line = 3; | |
495 | ||
496 | cid = tnum / 8; | |
497 | tid = tnum % 8; | |
498 | // Print TID at beginning of each line | |
499 | if ((cnt_per_line ==1 || (delta_cnt % cnt_per_line) == 1) && | |
500 | (regnum!=`END_INSTR)) begin // { | |
501 | $write("<T%0d>\t",tnum); | |
502 | end // } | |
503 | ||
504 | `NASTOP.get_regname(tnum,type,win,regnum,tmp_regname); | |
505 | if (regnum!=`END_INSTR) begin // { | |
506 | $write ("%0s = %h",tmp_regname,value); | |
507 | end // } | |
508 | ||
509 | // Print N registers per line | |
510 | ||
511 | // If no more deltas, Add <CR> to finish off previous line | |
512 | if ((regnum==`END_INSTR)&&((delta_cnt % cnt_per_line)!=1 || | |
513 | cnt_per_line ==1)) begin // { | |
514 | $write ("\n"); | |
515 | end // } | |
516 | else if (regnum==`END_INSTR) begin // { | |
517 | // no <cr> or <tab> | |
518 | end // } | |
519 | // Add <CR> to finish off previous line and continue with next delta | |
520 | else if ((delta_cnt % cnt_per_line)==0 || cnt_per_line ==1 ) begin // { | |
521 | $write ("\n"); | |
522 | end // } | |
523 | // Add <tab> before next delta | |
524 | else begin // { | |
525 | $write ("\t"); | |
526 | end // } | |
527 | ||
528 | end // } | |
529 | endtask | |
530 | ||
531 | //---------------------------------------------------------- | |
532 | // Convert to registers names (i.e. %o1, %g2, %i3, %l4, PC) | |
533 | task get_regname; | |
534 | ||
535 | input [5:0] tnum; | |
536 | input [7:0] type; | |
537 | input [31:0] win; | |
538 | input [31:0] regnum; | |
539 | output [(20*8)-1:0] tmp_regname; | |
540 | reg [(2*8)-1:0] tmp_regnum; | |
541 | integer tmp1,tmp2; | |
542 | ||
543 | begin // { | |
544 | case (type) | |
545 | "W": begin // { | |
546 | case (regnum) // { | |
547 | 8,9,10,11,12,13,14,15: begin // { | |
548 | if ( win == th_currcwp[tnum] ) begin // { | |
549 | tmp_regname = "%o"; | |
550 | tmp_regnum = regnum - 8; | |
551 | end // } | |
552 | else begin // { | |
553 | tmp_regname = "%i"; | |
554 | tmp_regnum = regnum - 8; | |
555 | end // } | |
556 | end // } | |
557 | 16,17,18,19,20,21,22,23: begin // { | |
558 | tmp_regname = "%l"; | |
559 | tmp_regnum = regnum - 16; | |
560 | end // } | |
561 | endcase // } | |
562 | tmp_regnum = tmp_regnum+'h30; // convert to ascii value for num | |
563 | tmp_regname = {tmp_regname,tmp_regnum}; | |
564 | end // } | |
565 | "G": begin // { | |
566 | tmp_regnum = regnum; | |
567 | tmp_regname = "%g"; | |
568 | tmp_regnum = tmp_regnum+'h30; // convert to ascii value for num | |
569 | tmp_regname = {tmp_regname,tmp_regnum}; | |
570 | end // } | |
571 | "F": begin // { | |
572 | tmp_regnum = regnum; | |
573 | tmp_regname = "%f"; | |
574 | if (tmp_regnum<=9) begin | |
575 | tmp_regnum = tmp_regnum+'h30; // convert to ascii value for num | |
576 | end | |
577 | else begin | |
578 | tmp1 = tmp_regnum%10; | |
579 | tmp2 = tmp_regnum/10; | |
580 | tmp_regnum = ((tmp2+'h30)<<8) + (tmp1+'h30); // convert to ascii value for num | |
581 | end | |
582 | tmp_regname = {tmp_regname,tmp_regnum}; | |
583 | end // } | |
584 | "C": begin :CONTROL_REG// { | |
585 | case(regnum) | |
586 | `PC: tmp_regname = "PC"; | |
587 | `NPC: tmp_regname = "NPC"; | |
588 | `Y: tmp_regname = "Y"; | |
589 | `CCR: tmp_regname = "CCR"; | |
590 | `FPRS: tmp_regname = "FPRS"; | |
591 | `FSR: tmp_regname = "FSR"; | |
592 | `ASI: tmp_regname = "ASI"; | |
593 | `TICK: tmp_regname = "TICK"; | |
594 | `GSR: tmp_regname = "GSR"; | |
595 | `TICK_CMPR: tmp_regname = "TICK_CMPR"; | |
596 | `STICK: tmp_regname = "STICK"; | |
597 | `STICK_CMPR: tmp_regname = "STICK_CMPR"; | |
598 | `PSTATE: tmp_regname = "PSTATE"; | |
599 | `TL: tmp_regname = "TL"; | |
600 | `PIL: tmp_regname = "PIL"; | |
601 | `TPC1: tmp_regname = "TPC1"; | |
602 | `TPC2: tmp_regname = "TPC2"; | |
603 | `TPC3: tmp_regname = "TPC3"; | |
604 | `TPC4: tmp_regname = "TPC4"; | |
605 | `TPC5: tmp_regname = "TPC5"; | |
606 | `TPC6: tmp_regname = "TPC6"; | |
607 | `TNPC1: tmp_regname = "TNPC1"; | |
608 | `TNPC2: tmp_regname = "TNPC2"; | |
609 | `TNPC3: tmp_regname = "TNPC3"; | |
610 | `TNPC4: tmp_regname = "TNPC4"; | |
611 | `TNPC5: tmp_regname = "TNPC5"; | |
612 | `TNPC6: tmp_regname = "TNPC6"; | |
613 | `TSTATE1: tmp_regname = "TSTATE1"; | |
614 | `TSTATE2: tmp_regname = "TSTATE2"; | |
615 | `TSTATE3: tmp_regname = "TSTATE3"; | |
616 | `TSTATE4: tmp_regname = "TSTATE4"; | |
617 | `TSTATE5: tmp_regname = "TSTATE5"; | |
618 | `TSTATE6: tmp_regname = "TSTATE6"; | |
619 | `TT1: tmp_regname = "TT1"; | |
620 | `TT2: tmp_regname = "TT2"; | |
621 | `TT3: tmp_regname = "TT3"; | |
622 | `TT4: tmp_regname = "TT4"; | |
623 | `TT5: tmp_regname = "TT5"; | |
624 | `TT6: tmp_regname = "TT6"; | |
625 | `TBA: tmp_regname = "TBA"; | |
626 | `VER: tmp_regname = "VER"; | |
627 | `CWP: tmp_regname = "CWP"; | |
628 | `CANSAVE: tmp_regname = "CANSAVE"; | |
629 | `CANRESTORE: tmp_regname = "CANRESTORE"; | |
630 | `OTHERWIN: tmp_regname = "OTHERWIN"; | |
631 | `WSTATE: tmp_regname = "WSTATE"; | |
632 | `CLEANWIN: tmp_regname = "CLEANWIN"; | |
633 | `SOFTINT: tmp_regname = "SOFTINT"; | |
634 | `INTR_RECEIVE: tmp_regname = "INTR_RECEIVE"; | |
635 | `GL: tmp_regname = "GL"; | |
636 | `HPSTATE: tmp_regname = "HPSTATE"; | |
637 | `HTSTATE1: tmp_regname = "HTSTATE1"; | |
638 | `HTSTATE2: tmp_regname = "HTSTATE2"; | |
639 | `HTSTATE3: tmp_regname = "HTSTATE3"; | |
640 | `HTSTATE4: tmp_regname = "HTSTATE4"; | |
641 | `HTSTATE5: tmp_regname = "HTSTATE5"; | |
642 | `HTSTATE6: tmp_regname = "HTSTATE6"; | |
643 | `HTBA: tmp_regname = "HTBA"; | |
644 | `HINTP: tmp_regname = "HINTP"; | |
645 | `HSTICK_CMPR: tmp_regname = "HSTICK_CMPR"; | |
646 | `MID: tmp_regname = "MID"; | |
647 | `ISFSR: tmp_regname = "ISFSR"; | |
648 | `DSFSR: tmp_regname = "DSFSR"; | |
649 | `DSFAR: tmp_regname = "DSFAR"; | |
650 | ||
651 | `CTXT_PRIM_0: tmp_regname = "CTXT_PRIM_0"; | |
652 | `CTXT_SEC_0: tmp_regname = "CTXT_SEC_0"; | |
653 | `CTXT_PRIM_1: tmp_regname = "CTXT_PRIM_1"; | |
654 | `CTXT_SEC_1: tmp_regname = "CTXT_SEC_1"; | |
655 | `LSU_CONTROL: tmp_regname = "LSU_CONTROL"; | |
656 | `I_TAG_ACC: tmp_regname = "I_TAG_ACC"; | |
657 | `CTXT_Z_TSB_CFG0: tmp_regname = "CTXT_Z_TSB_CFG0"; | |
658 | `CTXT_Z_TSB_CFG1: tmp_regname = "CTXT_Z_TSB_CFG1"; | |
659 | `CTXT_Z_TSB_CFG2: tmp_regname = "CTXT_Z_TSB_CFG2"; | |
660 | `CTXT_Z_TSB_CFG3: tmp_regname = "CTXT_Z_TSB_CFG3"; | |
661 | `CTXT_NZ_TSB_CFG0: tmp_regname = "CTXT_NZ_TSB_CFG0"; | |
662 | `CTXT_NZ_TSB_CFG1: tmp_regname = "CTXT_NZ_TSB_CFG1"; | |
663 | `CTXT_NZ_TSB_CFG2: tmp_regname = "CTXT_NZ_TSB_CFG2"; | |
664 | `CTXT_NZ_TSB_CFG3: tmp_regname = "CTXT_NZ_TSB_CFG3"; | |
665 | `I_DATA_IN: tmp_regname = "I_DATA_IN"; | |
666 | `D_TAG_ACC: tmp_regname = "D_TAG_ACC"; | |
667 | `WATCHPOINT_ADDR: tmp_regname = "WATCHPOINT_ADDR"; | |
668 | `D_DATA_IN: tmp_regname = "D_DATA_IN"; | |
669 | ||
670 | `OPCODE: tmp_regname = "OPCODE"; | |
671 | default: tmp_regname = "UNKNOWN"; | |
672 | endcase | |
673 | end // } | |
674 | "X": begin :EOF// { | |
675 | tmp_regname = "END_INSTR"; | |
676 | th_currcwp[tnum] = win ; // END_INSTR has win# of next instr | |
677 | end // } | |
678 | default: begin : DEFAULT // { | |
679 | tmp_regname= "UNKN"; | |
680 | `PR_ERROR("nas", `ERROR, "T%0d Illegal/Unexpected register type \"%s\" (%d)", | |
681 | tnum, type, type); | |
682 | end // } | |
683 | ||
684 | endcase | |
685 | ||
686 | end // } | |
687 | endtask | |
688 | ||
689 | //---------------------------------------------------------- | |
690 | // This function checks to see if the register is on the list | |
691 | // of registers currently supported by the bench. | |
692 | ||
693 | function check_this_one; | |
694 | input [7:0] exp_type; | |
695 | input [31:0] exp_regnum; | |
696 | ||
697 | begin // { | |
698 | check_this_one = 1'b0; // default value | |
699 | ||
700 | case (exp_type) | |
701 | "W", | |
702 | "F", | |
703 | "G": begin // { | |
704 | // Conditionally, remove IRF,FRF register compares | |
705 | `ifdef NAS_NO_IRFFRF | |
706 | check_this_one = 1'b0; | |
707 | `else | |
708 | check_this_one = 1'b1; | |
709 | `endif | |
710 | end // } | |
711 | "C": begin // { | |
712 | case (exp_regnum) | |
713 | ||
714 | // DON'T check these control registers | |
715 | `ifndef OPCODE_COMPARE | |
716 | `OPCODE, | |
717 | `endif | |
718 | ||
719 | // ADD_TSB_CFG | |
720 | // NOTE - ADD_TSB_CFG will never be used for Axis or Tharas (ifdef EMUL) or | |
721 | // if MMU reg slam is enabled | |
722 | `ifdef ADD_TSB_CFG | |
723 | // CHECK THESE = YES | |
724 | // `CTXT_Z_TSB_CFG0, | |
725 | // `CTXT_Z_TSB_CFG1, | |
726 | // `CTXT_Z_TSB_CFG2, | |
727 | // `CTXT_Z_TSB_CFG3, | |
728 | // `CTXT_NZ_TSB_CFG0, | |
729 | // `CTXT_NZ_TSB_CFG1, | |
730 | // `CTXT_NZ_TSB_CFG2, | |
731 | // `CTXT_NZ_TSB_CFG3, | |
732 | `else | |
733 | // CHECK THESE = NO | |
734 | `CTXT_Z_TSB_CFG0, | |
735 | `CTXT_Z_TSB_CFG1, | |
736 | `CTXT_Z_TSB_CFG2, | |
737 | `CTXT_Z_TSB_CFG3, | |
738 | `CTXT_NZ_TSB_CFG0, | |
739 | `CTXT_NZ_TSB_CFG1, | |
740 | `CTXT_NZ_TSB_CFG2, | |
741 | `CTXT_NZ_TSB_CFG3, | |
742 | `endif | |
743 | ||
744 | // CHECK THESE = YES | |
745 | //`D_TAG_ACC, | |
746 | ||
747 | `I_DATA_IN, | |
748 | `D_DATA_IN, | |
749 | ||
750 | `NPC, | |
751 | `STICK, | |
752 | `TICK, | |
753 | `ECACHE_ERROR_ENABLE, | |
754 | `ASYNCHRONOUS_FAULT_STATUS, | |
755 | `ASYNCHRONOUS_FAULT_ADDRESS, | |
756 | `OUT_INTR_DATA0, | |
757 | `OUT_INTR_DATA1, | |
758 | `OUT_INTR_DATA2, | |
759 | `INTR_DISPATCH_STATUS, | |
760 | `INTR_RECEIVE, | |
761 | `IN_INTR_DATA0, | |
762 | `IN_INTR_DATA1, | |
763 | `IN_INTR_DATA2, | |
764 | `MID, | |
765 | `ISFSR, | |
766 | `DSFSR: | |
767 | begin // { | |
768 | check_this_one = 1'b0; | |
769 | end // } | |
770 | ||
771 | // DO check all the rest of the control registers | |
772 | default: begin // { | |
773 | check_this_one = 1'b1; | |
774 | end // } | |
775 | endcase | |
776 | end // } | |
777 | endcase | |
778 | if (exp_regnum == `END_INSTR) check_this_one = 1'b1; | |
779 | end // } | |
780 | endfunction | |
781 | ||
782 | //---------------------------------------------------------- | |
783 | endmodule | |
784 | //---------------------------------------------------------- | |
785 | //---------------------------------------------------------- |