Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: debug5.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 | module debug5; | |
36 | ||
37 | reg [7:0] parkedState; | |
38 | reg [7:0] parkTrans; | |
39 | reg [7:0] stepDone; // these tids have stepped | |
40 | reg [7:0] stepAllowed; // these tids will be stepping/active | |
41 | reg [7:0] stepActive; | |
42 | reg [7:0] virtualPark; // tid is "virtually parked" | |
43 | reg [7:0] watchStepFlush; | |
44 | reg [7:0] watchStepMMU; | |
45 | //reg [7:0] spuActive; | |
46 | reg doMode; | |
47 | reg ssMode; | |
48 | reg enabled; | |
49 | reg wasEnabled; | |
50 | reg noCmtCheck; | |
51 | integer stepWaitTime; | |
52 | integer redirectWait; | |
53 | integer parkWait; | |
54 | integer tmp; | |
55 | //integer spuTimeout; | |
56 | integer stepCount; | |
57 | //reg [63:0] threadEnable; | |
58 | integer flushCount0; | |
59 | integer flushCount1; | |
60 | integer flushCount2; | |
61 | integer flushCount3; | |
62 | integer flushCount4; | |
63 | integer flushCount5; | |
64 | integer flushCount6; | |
65 | integer flushCount7; | |
66 | integer redirectCount0; | |
67 | integer redirectCount1; | |
68 | integer redirectCount2; | |
69 | integer redirectCount3; | |
70 | integer redirectCount4; | |
71 | integer redirectCount5; | |
72 | integer redirectCount6; | |
73 | integer redirectCount7; | |
74 | integer pipelineCount0; | |
75 | integer pipelineCount1; | |
76 | integer pipelineCount2; | |
77 | integer pipelineCount3; | |
78 | integer pipelineCount4; | |
79 | integer pipelineCount5; | |
80 | integer pipelineCount6; | |
81 | integer pipelineCount7; | |
82 | integer junk; | |
83 | reg [1:0] cmtValid0; | |
84 | reg [1:0] cmtValid1; | |
85 | integer cmtCount0; | |
86 | integer cmtCount1; | |
87 | integer lastActiveVal; | |
88 | integer cmtCountT0; | |
89 | integer cmtCountT1; | |
90 | integer cmtCountT2; | |
91 | integer cmtCountT3; | |
92 | integer count0; | |
93 | integer count1; | |
94 | integer count2; | |
95 | integer count3; | |
96 | integer count4; | |
97 | integer count5; | |
98 | integer count6; | |
99 | integer count7; | |
100 | ||
101 | initial begin | |
102 | parkedState = 8'hff; | |
103 | parkTrans = 8'h0; | |
104 | doMode = 0; | |
105 | ssMode = 0; | |
106 | stepDone = 0; // when stepDone = ~parked, all threads have steped | |
107 | stepAllowed = 0; | |
108 | stepActive = 0; | |
109 | virtualPark = 0; | |
110 | watchStepFlush = 0; | |
111 | watchStepMMU = 0; | |
112 | enabled = 0; // start out 0! | |
113 | wasEnabled = 0; | |
114 | noCmtCheck = 0; | |
115 | stepCount = 0; | |
116 | // threadEnable = 0; | |
117 | flushCount0 = 0; | |
118 | flushCount1 = 0; | |
119 | flushCount2 = 0; | |
120 | flushCount3 = 0; | |
121 | flushCount4 = 0; | |
122 | flushCount5 = 0; | |
123 | flushCount6 = 0; | |
124 | flushCount7 = 0; | |
125 | redirectCount0 = 0; | |
126 | redirectCount1 = 0; | |
127 | redirectCount2 = 0; | |
128 | redirectCount3 = 0; | |
129 | redirectCount4 = 0; | |
130 | redirectCount5 = 0; | |
131 | redirectCount6 = 0; | |
132 | redirectCount7 = 0; | |
133 | cmtValid0 = 0; | |
134 | cmtValid1 = 0; | |
135 | //spuActive = 0; | |
136 | cmtCount0 = 0; | |
137 | cmtCount1 = 0; | |
138 | lastActiveVal = 0; | |
139 | cmtCountT0 = 0; | |
140 | cmtCountT1 = 0; | |
141 | cmtCountT2 = 0; | |
142 | cmtCountT3 = 0; | |
143 | // tunable paramaters | |
144 | `ifdef SPC_BENCH | |
145 | stepWaitTime = 1000; // From ss_start to ss_done, unless SPU | |
146 | redirectWait = 30; // From core_running_status to redirect | |
147 | parkWait = 600; // How long until core_running_status gets asserted/deasserted | |
148 | //spuTimeout = 10000000; // How long until we give up on waiting for possible SPU activity | |
149 | `else | |
150 | stepWaitTime = 2000; // From ss_start to ss_done, unless SPU | |
151 | redirectWait = 60; // From core_running_status to redirect | |
152 | //spuTimeout = 15000000; // How long until we give up on waiting for possible SPU activity | |
153 | // How long until core_running_status gets asserted/deasserted | |
154 | #2 | |
155 | parkWait = `PARGS.th_timeout-100; | |
156 | `endif | |
157 | end | |
158 | ||
159 | initial begin | |
160 | //while (`TOP.core_cycle_cnt !== 5) #10; | |
161 | @(negedge `TOP.in_reset); | |
162 | `ifdef FC_BENCH | |
163 | `ifdef FLUSH_RESET | |
164 | @(posedge `TOP.flush_reset_complete); | |
165 | `endif | |
166 | `endif | |
167 | @(posedge `SPC0.l2clk); | |
168 | if (! $test$plusargs("noDebugChecks")) enabled = 1; | |
169 | if (enabled) `PR_ALWAYS ("dbg_chk", `ALWAYS, "Core 5 Debug Logic Checker debug5.v is alive and enabled."); | |
170 | else `PR_ALWAYS ("dbg_chk", `ALWAYS, "!!!Core 5 Debug Logic Checker NOT enabled!!!"); | |
171 | if ($test$plusargs("noCmtCheck")) noCmtCheck = 1; | |
172 | if (noCmtCheck) `PR_ALWAYS ("dbg_chk", `ALWAYS, "!!!Core 5 Debug Logic Commit Checker NOT enabled!!!"); | |
173 | if ($value$plusargs("stepWaitTime=%d", tmp)) stepWaitTime = tmp; | |
174 | if ($value$plusargs("redirectWait=%d", tmp)) redirectWait = tmp; | |
175 | if ($value$plusargs("parkWait=%d", tmp)) parkWait = tmp; | |
176 | //if ($value$plusargs("spuTimeout=%d", tmp)) spuTimeout = tmp; | |
177 | //if (enabled) `PR_ALWAYS ("dbg_chk", `ALWAYS, "Using stepWaitTime/redirectWait/parkWait/spuTimeout = %0d/%0d/%0d/%0d",stepWaitTime,redirectWait,parkWait,spuTimeout); | |
178 | //threadEnable = `PARGS.finish_mask; | |
179 | //if (enabled) `PR_ALWAYS ("dbg_chk", `ALWAYS, "Assuming active threads are (%h)", threadEnable); | |
180 | end | |
181 | ||
182 | ||
183 | ||
184 | // look for some reset change | |
185 | always @(`TOP.flush_reset_complete) begin | |
186 | `PR_ALWAYS ("debugChecker", `ALWAYS, "flush_reset_complete changed to %0d. checker enabled=%0d",`TOP.flush_reset_complete,enabled); | |
187 | // going into some kind of reset | |
188 | if (enabled && !`TOP.flush_reset_complete) begin | |
189 | wasEnabled = 1; | |
190 | enabled = 0; | |
191 | end | |
192 | disable parkingCheck0; | |
193 | disable parkedCheck0; | |
194 | disable unparkCheck0; | |
195 | disable watchStep0; | |
196 | disable parkingCheck1; | |
197 | disable parkedCheck1; | |
198 | disable unparkCheck1; | |
199 | disable watchStep1; | |
200 | disable parkingCheck2; | |
201 | disable parkedCheck2; | |
202 | disable unparkCheck2; | |
203 | disable watchStep2; | |
204 | disable parkingCheck3; | |
205 | disable parkedCheck3; | |
206 | disable unparkCheck3; | |
207 | disable watchStep3; | |
208 | disable parkingCheck4; | |
209 | disable parkedCheck4; | |
210 | disable unparkCheck4; | |
211 | disable watchStep4; | |
212 | disable parkingCheck5; | |
213 | disable parkedCheck5; | |
214 | disable unparkCheck5; | |
215 | disable watchStep5; | |
216 | disable parkingCheck6; | |
217 | disable parkedCheck6; | |
218 | disable unparkCheck6; | |
219 | disable watchStep6; | |
220 | disable parkingCheck7; | |
221 | disable parkedCheck7; | |
222 | disable unparkCheck7; | |
223 | disable watchStep7; | |
224 | disable DOMODE; | |
225 | disable SSMODE; | |
226 | parkedState = 8'hff; | |
227 | cmtValid0 = 0; | |
228 | cmtValid1 = 0; | |
229 | // coming out of reset | |
230 | if (wasEnabled && `TOP.flush_reset_complete) begin | |
231 | parkTrans = 8'b0; | |
232 | enabled = 1; | |
233 | wasEnabled = 0; | |
234 | cmtValid0 = 0; | |
235 | cmtValid1 = 0; | |
236 | `ifdef FC_BENCH | |
237 | `ifdef FLUSH_RESET | |
238 | if (`TOP.flush_reset_complete !== 1) @(posedge `TOP.flush_reset_complete); | |
239 | `endif | |
240 | `endif | |
241 | end | |
242 | `PR_ALWAYS ("debugChecker", `ALWAYS, "flush_reset_complete/rst_wmr_protect transition complete. checker enabled=%0d",enabled); | |
243 | end | |
244 | ||
245 | ////////////////////////////////////////////////////////////////// | |
246 | // THREAD 0 | |
247 | ////////////////////////////////////////////////////////////////// | |
248 | ||
249 | ||
250 | // got park request. transition into parking. parking check. | |
251 | always @(negedge `SPC5.tlu.tcu_core_running[0]) begin: GOTPARK0 | |
252 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 0 calling parkingCheck"); | |
253 | if (enabled) parkingCheck0(); | |
254 | end | |
255 | ||
256 | // got unpark request. transition into running. unparking check. | |
257 | always @(posedge `SPC5.tlu.tcu_core_running[0]) begin: UNPARKCHECK0 | |
258 | if (enabled && !ssMode) begin | |
259 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 0 calling unparkCheck."); | |
260 | unparkCheck0(); | |
261 | end | |
262 | end | |
263 | ||
264 | // while parked check | |
265 | always @(posedge parkedState[0] or posedge virtualPark[0]) begin: PARKCHECK0 | |
266 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 0 calling parkedCheck"); | |
267 | if (enabled) parkedCheck0(); | |
268 | end | |
269 | ||
270 | // check for unexpected running transition | |
271 | always @(`SPC5.tlu.tlu_core_running_status[0]) begin: UNEXPECTED0 | |
272 | if (!parkTrans[0] && enabled && ! doMode && ! ssMode) // review? to remove ! doMode | |
273 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 0 spc_core_running_status changed w/o request to park/unpark (trans=%0d)!",parkTrans[0]); | |
274 | end | |
275 | ||
276 | ||
277 | ||
278 | ////////////// tasks for tid 0 //////////////////// | |
279 | ||
280 | // check the entering into parked state | |
281 | task parkingCheck0; | |
282 | ||
283 | begin | |
284 | ||
285 | ||
286 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 0 got park request!"); | |
287 | ||
288 | if (parkTrans[0] == 1) begin | |
289 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 0 got park request while park state is already transitioning! Possible diag conflict (multiple parkers)! (enabled=%0d)",enabled); | |
290 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +noDebugChecks to disable all debug checkes!"); | |
291 | disable parkingCheck0; | |
292 | end | |
293 | ||
294 | parkTrans[0] = 1; | |
295 | ||
296 | // wait before checking signals | |
297 | repeat (2) @(negedge `SPC5.l2clk); | |
298 | ||
299 | // need to see at least one assertion of flush | |
300 | // if (`SPC5.tlu_flush_ifu[0] !== 1) | |
301 | // @(posedge `SPC5.tlu_flush_ifu[0]); // has glitches | |
302 | if (`SPC5.ifu_ftu.ftu_agc_ctl.tlu_flush_ifu_f[0] !== 1) | |
303 | @(posedge `SPC5.ifu_ftu.ftu_agc_ctl.tlu_flush_ifu_f[0]); | |
304 | ||
305 | // need to see all of these go idle | |
306 | while (`SPC5.pku_quiesce[0] == 0 || | |
307 | `SPC5.ftu_ifu_quiesce[0] == 0 || | |
308 | `SPC5.lsu_stb_empty[0] == 0) | |
309 | @(negedge `SPC5.l2clk); | |
310 | ||
311 | // // need to see all of these go idle | |
312 | // while (`SPC5.pku_quiesce[0] == 0 || | |
313 | // `SPC5.ftu_ifu_quiesce[0] == 0 || | |
314 | // `SPC5.lsu_stb_empty[0] == 0 || | |
315 | // `SPC5.tlu.fls0.idl_request == 0) | |
316 | // @(negedge `SPC5.l2clk); | |
317 | ||
318 | parkedState[0] <= 1; | |
319 | parkTrans[0] <= 0; | |
320 | // `PR_ALWAYS("dbg_chk", `ALWAYS, "INFO: TID %0d has parked!", 0); | |
321 | `PR_DEBUG("dbg_chk", `DEBUG, "INFO: TID 0 has parked!"); | |
322 | ||
323 | end | |
324 | endtask | |
325 | ||
326 | ||
327 | // in parked state. | |
328 | // also called between single steps. | |
329 | task parkedCheck0; | |
330 | reg notified; | |
331 | begin //{ | |
332 | ||
333 | notified = 0; | |
334 | // loop while not transitioning out of park if not SS mode. | |
335 | // loop while in SS virtualPark if SS mode. | |
336 | while ((parkTrans[0] == 0 && ssMode == 0) || | |
337 | (virtualPark[0] == 1 && ssMode == 1 && | |
338 | `TOP.cpu.tcu_ss_request[5] == 0)) begin //{ | |
339 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 0 watching for activity while parked/between steps. trans=%0h, virtualPark=%0h, tcu_ss_request=%0h",parkTrans[0],virtualPark[0],`TOP.cpu.tcu_ss_request[5]); | |
340 | ||
341 | @(negedge `SPC5.l2clk); | |
342 | ||
343 | // if in SS mode and core_running goes to zero for that thread, the thread | |
344 | // will self step once and flush in order to change to a parked state | |
345 | // (core_running_status=0). This looks like an un-asked for step so it | |
346 | // has to be detected and ignored. Try stalling here during it. | |
347 | while (`SPC5.tlu.tcu_core_running[0] == 0 && | |
348 | `SPC5.tlu.tlu_core_running_status[0] == 1) | |
349 | @(negedge `SPC5.l2clk); | |
350 | ||
351 | // watch for instructions sneaking in | |
352 | // dec_inst_valid_m[1:0], one bit per group | |
353 | if (`SPC5.tlu_trap_pc_0_valid && `SPC5.tlu_trap_0_tid[1:0] == 0 && `SPC5.tlu.tlu_retry[0] == 1) | |
354 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 0 had tlu_trap_pc_0_valid activity while parked/between steps!"); | |
355 | ||
356 | if (`SPC5.dec_inst_valid_m[0] == 1 && `SPC5.dec_tid0_m[1:0] == 0) | |
357 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 0 had dec_inst_valid_m activity while parked/between steps!"); | |
358 | ||
359 | ||
360 | end //} while | |
361 | ||
362 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 0 STOP watching for activity while parked/between steps. trans=%0h, virtualPark=%0h, tcu_ss_request=%0h",parkTrans[0],virtualPark[0],`TOP.cpu.tcu_ss_request[5]); | |
363 | ||
364 | end //} | |
365 | endtask | |
366 | ||
367 | ||
368 | // leaving parked state | |
369 | task unparkCheck0; | |
370 | integer count; | |
371 | begin | |
372 | ||
373 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 0 got unpark request!"); | |
374 | ||
375 | if (parkTrans[0] == 1) begin | |
376 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 0 got unpark request while park state is already transitioning! Possible diag conflict! (trans=%0h)",parkTrans); | |
377 | disable unparkCheck0; | |
378 | end | |
379 | ||
380 | parkTrans[0] = 1; | |
381 | ||
382 | // must see `SPC5.tlu.core_running_status[0] w/in count clocks | |
383 | count0 = 0; | |
384 | ||
385 | while (`SPC5.tlu.tlu_core_running_status[0] == 0) begin | |
386 | @(negedge `SPC5.l2clk); | |
387 | if (count0 > parkWait) begin // <--- may need to adjust | |
388 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 0 did not assert spc_core_running_status as soon as it should have (%0d clocks)!", count0); | |
389 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +parkWait=n (currently %0d). +noDebugChecks disables all checks!",parkWait); | |
390 | end | |
391 | count0 = count0 + 1; | |
392 | end | |
393 | ||
394 | if (!doMode && !ssMode) begin | |
395 | // need to see re-direct w/in "redirectWait" more clocks | |
396 | count0 = 0; | |
397 | ||
398 | // if this is true, the redirect and the assertion of core_running_status | |
399 | // happened at once so while loop can be skipped. | |
400 | while (! (`SPC5.tlu_trap_pc_0_valid && | |
401 | `SPC5.tlu_trap_0_tid[1:0] == 0)) begin | |
402 | @(negedge `SPC5.l2clk); | |
403 | if (count0 > redirectWait) begin // <--- may need to adjust | |
404 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 0 did not redirect within %d clocks after core_running_status assert!", redirectWait); | |
405 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +redirectWait=n (currently %0d). +noDebugChecks disables all checks!",redirectWait); | |
406 | end | |
407 | count0 = count0 + 1; | |
408 | end | |
409 | end | |
410 | ||
411 | parkedState[0] <= 0; | |
412 | parkTrans[0] <= 0; | |
413 | count0 <= 0; | |
414 | ||
415 | end | |
416 | endtask | |
417 | ||
418 | ||
419 | // watch this tid step correctly. Should step 1 instruction | |
420 | // and then "virtual park". | |
421 | // for SS and DO modes. | |
422 | task watchStep0; | |
423 | begin | |
424 | ||
425 | watchStepFlush[0] = 0; // set if we got a flush | |
426 | watchStepMMU[0] = 0; // set if we got a mmu reload | |
427 | stepDone[0] = 0; | |
428 | stepActive[0] = 1; | |
429 | ||
430 | if (flushCount0) `PR_DEBUG("dbg_chk", `DEBUG, "watchStep0: TID 0 repeating watchStep task due to flush (flushCount=%0d, redirectCount=%0d)!",flushCount0,redirectCount0); | |
431 | ||
432 | ||
433 | fork | |
434 | // timeout fork | |
435 | begin : FORK10_0 | |
436 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
437 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep0: TID 0 did not see valid PC retry (waitTime=%0d)!", stepWaitTime); | |
438 | end | |
439 | ||
440 | // // look for SPU going active | |
441 | // begin : FORK11_0 | |
442 | // while (!(`SPC5.spu_tlu_cwq_busy || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 0))) | |
443 | // @(negedge `SPC5.l2clk); | |
444 | // `PR_DEBUG("dbg_chk", `DEBUG, "watchStep0: TID 0 see SPU active!"); | |
445 | // spuActive[0] = 1; | |
446 | // end | |
447 | ||
448 | // might get ss_complete due to not knowing if there are 1 or 2 or more flushes. | |
449 | // this task gets called w/o knowing in advance if there will be one more | |
450 | // assertion of tlu_trap_pc_0/1_valid or not. | |
451 | begin : FORK8_0 | |
452 | if (ssMode) begin | |
453 | @(posedge `SPC5.spc_ss_complete); | |
454 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep0: TID 0 see spc_ss_complete, step done, bailing (flushCount=%0d/redirectCount=%0d)!", flushCount0, redirectCount0); | |
455 | stepDone[0] = 1; | |
456 | stepActive[0] = 0; | |
457 | disable watchStep0; // return | |
458 | end | |
459 | end | |
460 | ||
461 | // valid PC / retry | |
462 | begin : FORK9_0 | |
463 | // start step. tid wakes up/redirects and does "one instruction" | |
464 | while (!(`SPC5.tlu_trap_pc_0_valid && `SPC5.tlu_trap_0_tid[1:0] == 0 && `SPC5.tlu.tlu_retry[0] == 1)) begin | |
465 | // might see `SPC5.tlu.mmu_reload_done[0] here if previous | |
466 | // redirect was due to a MMU miss. If so, decrement flush count because | |
467 | // the previous flush on prev pc_valid "does not count" and there can be | |
468 | // any number of them w/ no way to predict quantity. | |
469 | if (`SPC5.tlu.mmu_reload_done[0] && ssMode) begin | |
470 | flushCount0 = flushCount0-1; | |
471 | redirectCount0 = redirectCount0-1; | |
472 | watchStepMMU[0] = 1; | |
473 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep0: TID 0 saw mmu_reload_done (hwtw)! flushCount/redirectCount decremented to %0d/%0d", flushCount0, redirectCount0); | |
474 | end | |
475 | @(negedge `SPC5.l2clk); | |
476 | end | |
477 | ||
478 | redirectCount0 = redirectCount0+1; | |
479 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep0: TID 0 got valid retry, step waiting on negedge pku_quiesce (redirectCount=%0d)!",redirectCount0); | |
480 | disable FORK8_0; // kill sync on spc_ss_complete | |
481 | ||
482 | @(negedge `SPC5.pku_quiesce[0]); | |
483 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep0: TID 0 got negedge pku_quiesce, step waiting on dec_inst_valid_m!"); | |
484 | ||
485 | while (!(`SPC5.dec_inst_valid_m[0] == 1 && `SPC5.dec_tid0_m[1:0] == 0)) @(negedge `SPC5.l2clk); | |
486 | ||
487 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep0: TID 0 valid step starting!"); | |
488 | disable FORK10_0; // kill timeout | |
489 | //disable FORK11_0; | |
490 | // if (!`SPC5.spu_tlu_cwq_busy && | |
491 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
492 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 0)) spuActive[0] = 0; | |
493 | end | |
494 | join | |
495 | ||
496 | ||
497 | ||
498 | // finish step | |
499 | fork | |
500 | // timeout fork | |
501 | begin : FORK4_0 | |
502 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
503 | ||
504 | // may need to adjust. If a tid is doing a SPU sync ctl reg sync read, | |
505 | // it could stay "busy" for a REAL long time!!! Need delayed check of busy | |
506 | // since it can assert after the step has started. | |
507 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep0: TID 0 did not quiesce/complete after step (SS or DO) as it should have. not SPU busy (waitTime=%0d)!", stepWaitTime); | |
508 | end | |
509 | ||
510 | // look for SPU going active | |
511 | // begin : FORK12_0 | |
512 | // while (!(`SPC5.spu_tlu_cwq_busy || | |
513 | // ((`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 0 && doMode) || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && ssMode)))) | |
514 | // @(negedge `SPC5.l2clk); | |
515 | // spuActive[0] = 1; | |
516 | // end | |
517 | ||
518 | ||
519 | // look for flush_ifu (w/o lsu_trap_flush (aka ptrap_flush) if SS) | |
520 | // and end this task if seen. tlu_flush_ifu assertion always means | |
521 | // this "instruction" is done, but may repeat (tlb miss, etc) w/in the SS. | |
522 | begin : FORK6_0 | |
523 | // checking ptrap_flush to make sure that flush is not caused by lsu_trap_flush | |
524 | while (`SPC5.tlu_flush_ifu[0] == 0) | |
525 | @(negedge `SPC5.l2clk); | |
526 | ||
527 | // // debug!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
528 | // if (`SPC5.tlu.fls0.ptrap_flush[0] == 1) begin | |
529 | // `PR_ERROR ("dbg_chk", `ERROR, "watchStep0: TID 0 have tlu_flush_ifu !!!!!!!!!!!!!!!!!!!!!!!"); | |
530 | // end | |
531 | // | |
532 | ||
533 | if ((ssMode && `SPC5.tlu.fls0.ptrap_flush[0] == 0) || doMode) begin | |
534 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep0: TID 0 have tlu_flush_ifu (flushCount=%0d)!",flushCount0); | |
535 | watchStepFlush[0] = 1; | |
536 | flushCount0 = flushCount0+1; | |
537 | stepActive[0] = 0; | |
538 | disable watchStep0; // return | |
539 | end | |
540 | end | |
541 | ||
542 | ||
543 | // are we done fork, DO mode quiesce | |
544 | begin : FORK5_0 | |
545 | if (doMode) begin | |
546 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep0: TID 0 watching for quiesce (only matters fo DO mode)!"); | |
547 | while (`SPC5.pku_quiesce[0] == 0 || | |
548 | `SPC5.ftu_ifu_quiesce[0] == 0 || | |
549 | `SPC5.lsu_stb_empty[0] == 0) @(negedge `SPC5.l2clk); | |
550 | ||
551 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep0: TID 0 have quiesce (only matters for DO mode)!"); | |
552 | if (doMode) begin | |
553 | disable FORK4_0; // TO | |
554 | disable FORK6_0; // flush check | |
555 | //disable FORK12_0; | |
556 | // @(negedge `SPC5.l2clk); | |
557 | // if (!`SPC5.spu_tlu_cwq_busy && | |
558 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
559 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 0)) spuActive[0] = 0; | |
560 | end | |
561 | end | |
562 | end | |
563 | ||
564 | ||
565 | // are we done fork, SS mode only | |
566 | begin : FORK7_0 | |
567 | // wait for SS complete | |
568 | if (ssMode) begin | |
569 | @(posedge `SPC5.spc_ss_complete); | |
570 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep0: TID 0 see spc_ss_complete, step done, bailing (flushCount=%0d/redirectCount=%0d)!", flushCount0,redirectCount0); | |
571 | stepDone[0] = 1; | |
572 | ||
573 | // while (ssMode && !`SPC5.spc_ss_complete) begin | |
574 | // // detect a second inst valid w/o a flush between | |
575 | // if (`SPC5.tlu_trap_pc_0_valid && `SPC5.tlu_trap_0_tid[1:0] == 0 && `SPC5.tlu.tlu_retry[0] == 1) begin | |
576 | // // delay error so flush thread can kill this in the "got flush" case | |
577 | // @(negedge `SPC5.l2clk); | |
578 | // `PR_ERROR ("dbg_chk", `ERROR, "watchStep0: TID 0 had another inst start before SS done was asserted!"); | |
579 | // end | |
580 | // @(negedge `SPC5.l2clk); | |
581 | // end // while | |
582 | ||
583 | if (`SPC5.pku_quiesce[0] == 0 || | |
584 | `SPC5.ftu_ifu_quiesce[0] == 0 || | |
585 | `SPC5.lsu_stb_empty[0] == 0) | |
586 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep0: TID 0 was not quiesce at ss_complete assertion!"); | |
587 | ||
588 | disable FORK4_0; // TO | |
589 | disable FORK6_0; // flush check | |
590 | //disable FORK12_0; | |
591 | // @(negedge `SPC5.l2clk); | |
592 | // if (!`SPC5.spu_tlu_cwq_busy && | |
593 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
594 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 0)) spuActive[0] = 0; | |
595 | end | |
596 | end | |
597 | ||
598 | join | |
599 | ||
600 | ||
601 | if (flushCount0 == 0) `PR_DEBUG("dbg_chk", `DEBUG, "watchStep0: TID 0 watchStep end!"); | |
602 | else `PR_DEBUG("dbg_chk", `DEBUG, "watchStep0: TID 0 repeated watchStep end!"); | |
603 | ||
604 | stepActive[0] = 0; | |
605 | ||
606 | end | |
607 | endtask | |
608 | ||
609 | ||
610 | ||
611 | // check that thread does DO mode correctly | |
612 | task watchDOsteps0; | |
613 | begin | |
614 | ||
615 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps0: TID 0 watchDOsteps starting!"); | |
616 | ||
617 | if (! `TOP.cpu.tcu_do_mode[5]) disable watchDOsteps0; | |
618 | ||
619 | // now wait for a thread to start. TCU internal signal. | |
620 | if (`SPC5.tlu.tlu_core_running_status[0] == 0) | |
621 | @(posedge `SPC5.tlu.tlu_core_running_status[0]); | |
622 | ||
623 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps0 TID 0 unparked and running in DO mode!"); | |
624 | ||
625 | // loop on step checking. DO mode is self stepping | |
626 | while (doMode) begin : watchDOsteps0loop// && `SPC5.tlu.tlu_core_running_status[7:0] != 0) begin | |
627 | ||
628 | stepDone[0] = 0; | |
629 | watchStepFlush[0] = 0; | |
630 | watchStepMMU[0] = 0; | |
631 | ||
632 | // are we starting to park in middle of DO mode (or end)? | |
633 | // wait here until unparked again | |
634 | if (parkTrans[0]) begin | |
635 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps0 TID 0 getting parked, will delay"); | |
636 | @(negedge parkTrans[0]); | |
637 | if (!doMode) disable watchDOsteps0loop; // no longer in DO mode, bail | |
638 | // wait to be unparked or !doMode | |
639 | if (parkedState[0]) begin | |
640 | @(negedge doMode or negedge parkedState[0]); | |
641 | if (!doMode) disable watchDOsteps0loop; // no longer in DO mode, bail | |
642 | end | |
643 | end | |
644 | ||
645 | ||
646 | // an unparked thread does one instruction to completion before thread starts | |
647 | // the next instruction. | |
648 | fork | |
649 | // timeout fork | |
650 | begin : FORKDO10 | |
651 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
652 | `PR_ERROR ("dbg_chk", `ERROR, "watchDOsteps0: DO mode, TID 0 timeout waiting for watchStep call to return, not SPU busy (+stepWaitTime=%0d)!", stepWaitTime); | |
653 | end | |
654 | ||
655 | // look for SPU going active | |
656 | // begin : FORKDO20 | |
657 | // while (!(`SPC5.spu_tlu_cwq_busy || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 0))) | |
658 | // @(negedge `SPC5.l2clk); | |
659 | // `PR_ALWAYS("dbg_chk", `ALWAYS, "watchDOsteps0: DO mode, TID 0 sees SPU busy!"); | |
660 | // spuActive[0] = 1; | |
661 | // end | |
662 | ||
663 | // watch step | |
664 | begin | |
665 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps0: TID 0 calling watchStep0 in DO mode!"); | |
666 | watchStep0; // returns when step is done or flushed | |
667 | if (watchStepFlush[0]) | |
668 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 0 in DO mode had flush!"); | |
669 | if (watchStepMMU[0]) | |
670 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 0 in DO mode had mmu reload!"); | |
671 | // calling flush as a done in DO mode | |
672 | disable FORKDO10; // TO | |
673 | //disable FORKDO20; // SPU going active | |
674 | end | |
675 | ||
676 | join | |
677 | ||
678 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps0: TID 0 DO mode watchDOsteps step done!"); | |
679 | stepDone[0] = 1; | |
680 | flushCount0 = 0; | |
681 | // if (!`SPC5.spu_tlu_cwq_busy && | |
682 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
683 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 0)) spuActive[0] = 0; | |
684 | ||
685 | @(negedge `SPC5.l2clk); | |
686 | end // while | |
687 | ||
688 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps0: TID 0 DO mode watchDOsteps task ending!"); | |
689 | end | |
690 | endtask | |
691 | ||
692 | ||
693 | ||
694 | ||
695 | ////////////////////////// end tid 0 /////////////////////////////////////// | |
696 | ||
697 | ||
698 | ////////////////////////////////////////////////////////////////// | |
699 | // THREAD 1 | |
700 | ////////////////////////////////////////////////////////////////// | |
701 | ||
702 | ||
703 | // got park request. transition into parking. parking check. | |
704 | always @(negedge `SPC5.tlu.tcu_core_running[1]) begin: GOTPARK1 | |
705 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 1 calling parkingCheck"); | |
706 | if (enabled) parkingCheck1(); | |
707 | end | |
708 | ||
709 | // got unpark request. transition into running. unparking check. | |
710 | always @(posedge `SPC5.tlu.tcu_core_running[1]) begin: UNPARKCHECK1 | |
711 | if (enabled && !ssMode) begin | |
712 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 1 calling unparkCheck."); | |
713 | unparkCheck1(); | |
714 | end | |
715 | end | |
716 | ||
717 | // while parked check | |
718 | always @(posedge parkedState[1] or posedge virtualPark[1]) begin: PARKCHECK1 | |
719 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 1 calling parkedCheck"); | |
720 | if (enabled) parkedCheck1(); | |
721 | end | |
722 | ||
723 | // check for unexpected running transition | |
724 | always @(`SPC5.tlu.tlu_core_running_status[1]) begin: UNEXPECTED1 | |
725 | if (!parkTrans[1] && enabled && ! doMode && ! ssMode) // review? to remove ! doMode | |
726 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 1 spc_core_running_status changed w/o request to park/unpark (trans=%0d)!",parkTrans[1]); | |
727 | end | |
728 | ||
729 | ||
730 | ||
731 | ////////////// tasks for tid 1 //////////////////// | |
732 | ||
733 | // check the entering into parked state | |
734 | task parkingCheck1; | |
735 | ||
736 | begin | |
737 | ||
738 | ||
739 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 1 got park request!"); | |
740 | ||
741 | if (parkTrans[1] == 1) begin | |
742 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 1 got park request while park state is already transitioning! Possible diag conflict (multiple parkers)! (enabled=%0d)",enabled); | |
743 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +noDebugChecks to disable all debug checkes!"); | |
744 | disable parkingCheck1; | |
745 | end | |
746 | ||
747 | parkTrans[1] = 1; | |
748 | ||
749 | // wait before checking signals | |
750 | repeat (2) @(negedge `SPC5.l2clk); | |
751 | ||
752 | // need to see at least one assertion of flush | |
753 | // if (`SPC5.tlu_flush_ifu[1] !== 1) | |
754 | // @(posedge `SPC5.tlu_flush_ifu[1]); // has glitches | |
755 | if (`SPC5.ifu_ftu.ftu_agc_ctl.tlu_flush_ifu_f[1] !== 1) | |
756 | @(posedge `SPC5.ifu_ftu.ftu_agc_ctl.tlu_flush_ifu_f[1]); | |
757 | ||
758 | // need to see all of these go idle | |
759 | while (`SPC5.pku_quiesce[1] == 0 || | |
760 | `SPC5.ftu_ifu_quiesce[1] == 0 || | |
761 | `SPC5.lsu_stb_empty[1] == 0) | |
762 | @(negedge `SPC5.l2clk); | |
763 | ||
764 | // // need to see all of these go idle | |
765 | // while (`SPC5.pku_quiesce[1] == 0 || | |
766 | // `SPC5.ftu_ifu_quiesce[1] == 0 || | |
767 | // `SPC5.lsu_stb_empty[1] == 0 || | |
768 | // `SPC5.tlu.fls0.idl_request == 0) | |
769 | // @(negedge `SPC5.l2clk); | |
770 | ||
771 | parkedState[1] <= 1; | |
772 | parkTrans[1] <= 0; | |
773 | // `PR_ALWAYS("dbg_chk", `ALWAYS, "INFO: TID %0d has parked!", 1); | |
774 | `PR_DEBUG("dbg_chk", `DEBUG, "INFO: TID 1 has parked!"); | |
775 | ||
776 | end | |
777 | endtask | |
778 | ||
779 | ||
780 | // in parked state. | |
781 | // also called between single steps. | |
782 | task parkedCheck1; | |
783 | reg notified; | |
784 | begin //{ | |
785 | ||
786 | notified = 0; | |
787 | // loop while not transitioning out of park if not SS mode. | |
788 | // loop while in SS virtualPark if SS mode. | |
789 | while ((parkTrans[1] == 0 && ssMode == 0) || | |
790 | (virtualPark[1] == 1 && ssMode == 1 && | |
791 | `TOP.cpu.tcu_ss_request[5] == 0)) begin //{ | |
792 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 1 watching for activity while parked/between steps. trans=%0h, virtualPark=%0h, tcu_ss_request=%0h",parkTrans[1],virtualPark[1],`TOP.cpu.tcu_ss_request[5]); | |
793 | ||
794 | @(negedge `SPC5.l2clk); | |
795 | ||
796 | // if in SS mode and core_running goes to zero for that thread, the thread | |
797 | // will self step once and flush in order to change to a parked state | |
798 | // (core_running_status=0). This looks like an un-asked for step so it | |
799 | // has to be detected and ignored. Try stalling here during it. | |
800 | while (`SPC5.tlu.tcu_core_running[1] == 0 && | |
801 | `SPC5.tlu.tlu_core_running_status[1] == 1) | |
802 | @(negedge `SPC5.l2clk); | |
803 | ||
804 | // watch for instructions sneaking in | |
805 | // dec_inst_valid_m[1:0], one bit per group | |
806 | if (`SPC5.tlu_trap_pc_0_valid && `SPC5.tlu_trap_0_tid[1:0] == 1 && `SPC5.tlu.tlu_retry[0] == 1) | |
807 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 1 had tlu_trap_pc_0_valid activity while parked/between steps!"); | |
808 | ||
809 | if (`SPC5.dec_inst_valid_m[0] == 1 && `SPC5.dec_tid0_m[1:0] == 1) | |
810 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 1 had dec_inst_valid_m activity while parked/between steps!"); | |
811 | ||
812 | ||
813 | end //} while | |
814 | ||
815 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 1 STOP watching for activity while parked/between steps. trans=%0h, virtualPark=%0h, tcu_ss_request=%0h",parkTrans[1],virtualPark[1],`TOP.cpu.tcu_ss_request[5]); | |
816 | ||
817 | end //} | |
818 | endtask | |
819 | ||
820 | ||
821 | // leaving parked state | |
822 | task unparkCheck1; | |
823 | integer count; | |
824 | begin | |
825 | ||
826 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 1 got unpark request!"); | |
827 | ||
828 | if (parkTrans[1] == 1) begin | |
829 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 1 got unpark request while park state is already transitioning! Possible diag conflict! (trans=%0h)",parkTrans); | |
830 | disable unparkCheck1; | |
831 | end | |
832 | ||
833 | parkTrans[1] = 1; | |
834 | ||
835 | // must see `SPC5.tlu.core_running_status[1] w/in count clocks | |
836 | count1 = 0; | |
837 | ||
838 | while (`SPC5.tlu.tlu_core_running_status[1] == 0) begin | |
839 | @(negedge `SPC5.l2clk); | |
840 | if (count1 > parkWait) begin // <--- may need to adjust | |
841 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 1 did not assert spc_core_running_status as soon as it should have (%0d clocks)!", count1); | |
842 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +parkWait=n (currently %0d). +noDebugChecks disables all checks!",parkWait); | |
843 | end | |
844 | count1 = count1 + 1; | |
845 | end | |
846 | ||
847 | if (!doMode && !ssMode) begin | |
848 | // need to see re-direct w/in "redirectWait" more clocks | |
849 | count1 = 0; | |
850 | ||
851 | // if this is true, the redirect and the assertion of core_running_status | |
852 | // happened at once so while loop can be skipped. | |
853 | while (! (`SPC5.tlu_trap_pc_0_valid && | |
854 | `SPC5.tlu_trap_0_tid[1:0] == 1)) begin | |
855 | @(negedge `SPC5.l2clk); | |
856 | if (count1 > redirectWait) begin // <--- may need to adjust | |
857 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 1 did not redirect within %d clocks after core_running_status assert!", redirectWait); | |
858 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +redirectWait=n (currently %0d). +noDebugChecks disables all checks!",redirectWait); | |
859 | end | |
860 | count1 = count1 + 1; | |
861 | end | |
862 | end | |
863 | ||
864 | parkedState[1] <= 0; | |
865 | parkTrans[1] <= 0; | |
866 | count1 <= 0; | |
867 | ||
868 | end | |
869 | endtask | |
870 | ||
871 | ||
872 | // watch this tid step correctly. Should step 1 instruction | |
873 | // and then "virtual park". | |
874 | // for SS and DO modes. | |
875 | task watchStep1; | |
876 | begin | |
877 | ||
878 | watchStepFlush[1] = 0; // set if we got a flush | |
879 | watchStepMMU[1] = 0; // set if we got a mmu reload | |
880 | stepDone[1] = 0; | |
881 | stepActive[1] = 1; | |
882 | ||
883 | if (flushCount1) `PR_DEBUG("dbg_chk", `DEBUG, "watchStep1: TID 1 repeating watchStep task due to flush (flushCount=%0d, redirectCount=%0d)!",flushCount1,redirectCount1); | |
884 | ||
885 | ||
886 | fork | |
887 | // timeout fork | |
888 | begin : FORK10_1 | |
889 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
890 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep1: TID 1 did not see valid PC retry (waitTime=%0d)!", stepWaitTime); | |
891 | end | |
892 | ||
893 | // // look for SPU going active | |
894 | // begin : FORK11_1 | |
895 | // while (!(`SPC5.spu_tlu_cwq_busy || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 1))) | |
896 | // @(negedge `SPC5.l2clk); | |
897 | // `PR_DEBUG("dbg_chk", `DEBUG, "watchStep1: TID 1 see SPU active!"); | |
898 | // spuActive[1] = 1; | |
899 | // end | |
900 | ||
901 | // might get ss_complete due to not knowing if there are 1 or 2 or more flushes. | |
902 | // this task gets called w/o knowing in advance if there will be one more | |
903 | // assertion of tlu_trap_pc_0/1_valid or not. | |
904 | begin : FORK8_1 | |
905 | if (ssMode) begin | |
906 | @(posedge `SPC5.spc_ss_complete); | |
907 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep1: TID 1 see spc_ss_complete, step done, bailing (flushCount=%0d/redirectCount=%0d)!", flushCount1, redirectCount1); | |
908 | stepDone[1] = 1; | |
909 | stepActive[1] = 0; | |
910 | disable watchStep1; // return | |
911 | end | |
912 | end | |
913 | ||
914 | // valid PC / retry | |
915 | begin : FORK9_1 | |
916 | // start step. tid wakes up/redirects and does "one instruction" | |
917 | while (!(`SPC5.tlu_trap_pc_0_valid && `SPC5.tlu_trap_0_tid[1:0] == 1 && `SPC5.tlu.tlu_retry[0] == 1)) begin | |
918 | // might see `SPC5.tlu.mmu_reload_done[1] here if previous | |
919 | // redirect was due to a MMU miss. If so, decrement flush count because | |
920 | // the previous flush on prev pc_valid "does not count" and there can be | |
921 | // any number of them w/ no way to predict quantity. | |
922 | if (`SPC5.tlu.mmu_reload_done[1] && ssMode) begin | |
923 | flushCount1 = flushCount1-1; | |
924 | redirectCount1 = redirectCount1-1; | |
925 | watchStepMMU[1] = 1; | |
926 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep1: TID 1 saw mmu_reload_done (hwtw)! flushCount/redirectCount decremented to %0d/%0d", flushCount1, redirectCount1); | |
927 | end | |
928 | @(negedge `SPC5.l2clk); | |
929 | end | |
930 | ||
931 | redirectCount1 = redirectCount1+1; | |
932 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep1: TID 1 got valid retry, step waiting on negedge pku_quiesce (redirectCount=%0d)!",redirectCount1); | |
933 | disable FORK8_1; // kill sync on spc_ss_complete | |
934 | ||
935 | @(negedge `SPC5.pku_quiesce[1]); | |
936 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep1: TID 1 got negedge pku_quiesce, step waiting on dec_inst_valid_m!"); | |
937 | ||
938 | while (!(`SPC5.dec_inst_valid_m[0] == 1 && `SPC5.dec_tid0_m[1:0] == 1)) @(negedge `SPC5.l2clk); | |
939 | ||
940 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep1: TID 1 valid step starting!"); | |
941 | disable FORK10_1; // kill timeout | |
942 | //disable FORK11_1; | |
943 | // if (!`SPC5.spu_tlu_cwq_busy && | |
944 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
945 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 1)) spuActive[1] = 0; | |
946 | end | |
947 | join | |
948 | ||
949 | ||
950 | ||
951 | // finish step | |
952 | fork | |
953 | // timeout fork | |
954 | begin : FORK4_1 | |
955 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
956 | ||
957 | // may need to adjust. If a tid is doing a SPU sync ctl reg sync read, | |
958 | // it could stay "busy" for a REAL long time!!! Need delayed check of busy | |
959 | // since it can assert after the step has started. | |
960 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep1: TID 1 did not quiesce/complete after step (SS or DO) as it should have. not SPU busy (waitTime=%0d)!", stepWaitTime); | |
961 | end | |
962 | ||
963 | // look for SPU going active | |
964 | // begin : FORK12_1 | |
965 | // while (!(`SPC5.spu_tlu_cwq_busy || | |
966 | // ((`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 1 && doMode) || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && ssMode)))) | |
967 | // @(negedge `SPC5.l2clk); | |
968 | // spuActive[1] = 1; | |
969 | // end | |
970 | ||
971 | ||
972 | // look for flush_ifu (w/o lsu_trap_flush (aka ptrap_flush) if SS) | |
973 | // and end this task if seen. tlu_flush_ifu assertion always means | |
974 | // this "instruction" is done, but may repeat (tlb miss, etc) w/in the SS. | |
975 | begin : FORK6_1 | |
976 | // checking ptrap_flush to make sure that flush is not caused by lsu_trap_flush | |
977 | while (`SPC5.tlu_flush_ifu[1] == 0) | |
978 | @(negedge `SPC5.l2clk); | |
979 | ||
980 | // // debug!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
981 | // if (`SPC5.tlu.fls0.ptrap_flush[1] == 1) begin | |
982 | // `PR_ERROR ("dbg_chk", `ERROR, "watchStep1: TID 1 have tlu_flush_ifu !!!!!!!!!!!!!!!!!!!!!!!"); | |
983 | // end | |
984 | // | |
985 | ||
986 | if ((ssMode && `SPC5.tlu.fls0.ptrap_flush[1] == 0) || doMode) begin | |
987 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep1: TID 1 have tlu_flush_ifu (flushCount=%0d)!",flushCount1); | |
988 | watchStepFlush[1] = 1; | |
989 | flushCount1 = flushCount1+1; | |
990 | stepActive[1] = 0; | |
991 | disable watchStep1; // return | |
992 | end | |
993 | end | |
994 | ||
995 | ||
996 | // are we done fork, DO mode quiesce | |
997 | begin : FORK5_1 | |
998 | if (doMode) begin | |
999 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep1: TID 1 watching for quiesce (only matters fo DO mode)!"); | |
1000 | while (`SPC5.pku_quiesce[1] == 0 || | |
1001 | `SPC5.ftu_ifu_quiesce[1] == 0 || | |
1002 | `SPC5.lsu_stb_empty[1] == 0) @(negedge `SPC5.l2clk); | |
1003 | ||
1004 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep1: TID 1 have quiesce (only matters for DO mode)!"); | |
1005 | if (doMode) begin | |
1006 | disable FORK4_1; // TO | |
1007 | disable FORK6_1; // flush check | |
1008 | //disable FORK12_1; | |
1009 | // @(negedge `SPC5.l2clk); | |
1010 | // if (!`SPC5.spu_tlu_cwq_busy && | |
1011 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
1012 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 1)) spuActive[1] = 0; | |
1013 | end | |
1014 | end | |
1015 | end | |
1016 | ||
1017 | ||
1018 | // are we done fork, SS mode only | |
1019 | begin : FORK7_1 | |
1020 | // wait for SS complete | |
1021 | if (ssMode) begin | |
1022 | @(posedge `SPC5.spc_ss_complete); | |
1023 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep1: TID 1 see spc_ss_complete, step done, bailing (flushCount=%0d/redirectCount=%0d)!", flushCount1,redirectCount1); | |
1024 | stepDone[1] = 1; | |
1025 | ||
1026 | // while (ssMode && !`SPC5.spc_ss_complete) begin | |
1027 | // // detect a second inst valid w/o a flush between | |
1028 | // if (`SPC5.tlu_trap_pc_0_valid && `SPC5.tlu_trap_0_tid[1:0] == 1 && `SPC5.tlu.tlu_retry[0] == 1) begin | |
1029 | // // delay error so flush thread can kill this in the "got flush" case | |
1030 | // @(negedge `SPC5.l2clk); | |
1031 | // `PR_ERROR ("dbg_chk", `ERROR, "watchStep1: TID 1 had another inst start before SS done was asserted!"); | |
1032 | // end | |
1033 | // @(negedge `SPC5.l2clk); | |
1034 | // end // while | |
1035 | ||
1036 | if (`SPC5.pku_quiesce[1] == 0 || | |
1037 | `SPC5.ftu_ifu_quiesce[1] == 0 || | |
1038 | `SPC5.lsu_stb_empty[1] == 0) | |
1039 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep1: TID 1 was not quiesce at ss_complete assertion!"); | |
1040 | ||
1041 | disable FORK4_1; // TO | |
1042 | disable FORK6_1; // flush check | |
1043 | //disable FORK12_1; | |
1044 | // @(negedge `SPC5.l2clk); | |
1045 | // if (!`SPC5.spu_tlu_cwq_busy && | |
1046 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
1047 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 1)) spuActive[1] = 0; | |
1048 | end | |
1049 | end | |
1050 | ||
1051 | join | |
1052 | ||
1053 | ||
1054 | if (flushCount1 == 0) `PR_DEBUG("dbg_chk", `DEBUG, "watchStep1: TID 1 watchStep end!"); | |
1055 | else `PR_DEBUG("dbg_chk", `DEBUG, "watchStep1: TID 1 repeated watchStep end!"); | |
1056 | ||
1057 | stepActive[1] = 0; | |
1058 | ||
1059 | end | |
1060 | endtask | |
1061 | ||
1062 | ||
1063 | ||
1064 | // check that thread does DO mode correctly | |
1065 | task watchDOsteps1; | |
1066 | begin | |
1067 | ||
1068 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps1: TID 1 watchDOsteps starting!"); | |
1069 | ||
1070 | if (! `TOP.cpu.tcu_do_mode[5]) disable watchDOsteps1; | |
1071 | ||
1072 | // now wait for a thread to start. TCU internal signal. | |
1073 | if (`SPC5.tlu.tlu_core_running_status[1] == 0) | |
1074 | @(posedge `SPC5.tlu.tlu_core_running_status[1]); | |
1075 | ||
1076 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps1 TID 1 unparked and running in DO mode!"); | |
1077 | ||
1078 | // loop on step checking. DO mode is self stepping | |
1079 | while (doMode) begin : watchDOsteps1loop// && `SPC5.tlu.tlu_core_running_status[7:0] != 0) begin | |
1080 | ||
1081 | stepDone[1] = 0; | |
1082 | watchStepFlush[1] = 0; | |
1083 | watchStepMMU[1] = 0; | |
1084 | ||
1085 | // are we starting to park in middle of DO mode (or end)? | |
1086 | // wait here until unparked again | |
1087 | if (parkTrans[1]) begin | |
1088 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps1 TID 1 getting parked, will delay"); | |
1089 | @(negedge parkTrans[1]); | |
1090 | if (!doMode) disable watchDOsteps1loop; // no longer in DO mode, bail | |
1091 | // wait to be unparked or !doMode | |
1092 | if (parkedState[1]) begin | |
1093 | @(negedge doMode or negedge parkedState[1]); | |
1094 | if (!doMode) disable watchDOsteps1loop; // no longer in DO mode, bail | |
1095 | end | |
1096 | end | |
1097 | ||
1098 | ||
1099 | // an unparked thread does one instruction to completion before thread starts | |
1100 | // the next instruction. | |
1101 | fork | |
1102 | // timeout fork | |
1103 | begin : FORKDO11 | |
1104 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
1105 | `PR_ERROR ("dbg_chk", `ERROR, "watchDOsteps1: DO mode, TID 1 timeout waiting for watchStep call to return, not SPU busy (+stepWaitTime=%0d)!", stepWaitTime); | |
1106 | end | |
1107 | ||
1108 | // look for SPU going active | |
1109 | // begin : FORKDO21 | |
1110 | // while (!(`SPC5.spu_tlu_cwq_busy || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 1))) | |
1111 | // @(negedge `SPC5.l2clk); | |
1112 | // `PR_ALWAYS("dbg_chk", `ALWAYS, "watchDOsteps1: DO mode, TID 1 sees SPU busy!"); | |
1113 | // spuActive[1] = 1; | |
1114 | // end | |
1115 | ||
1116 | // watch step | |
1117 | begin | |
1118 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps1: TID 1 calling watchStep1 in DO mode!"); | |
1119 | watchStep1; // returns when step is done or flushed | |
1120 | if (watchStepFlush[1]) | |
1121 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 1 in DO mode had flush!"); | |
1122 | if (watchStepMMU[1]) | |
1123 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 1 in DO mode had mmu reload!"); | |
1124 | // calling flush as a done in DO mode | |
1125 | disable FORKDO11; // TO | |
1126 | //disable FORKDO21; // SPU going active | |
1127 | end | |
1128 | ||
1129 | join | |
1130 | ||
1131 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps1: TID 1 DO mode watchDOsteps step done!"); | |
1132 | stepDone[1] = 1; | |
1133 | flushCount1 = 0; | |
1134 | // if (!`SPC5.spu_tlu_cwq_busy && | |
1135 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
1136 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 1)) spuActive[1] = 0; | |
1137 | ||
1138 | @(negedge `SPC5.l2clk); | |
1139 | end // while | |
1140 | ||
1141 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps1: TID 1 DO mode watchDOsteps task ending!"); | |
1142 | end | |
1143 | endtask | |
1144 | ||
1145 | ||
1146 | ||
1147 | ||
1148 | ////////////////////////// end tid 1 /////////////////////////////////////// | |
1149 | ||
1150 | ||
1151 | ////////////////////////////////////////////////////////////////// | |
1152 | // THREAD 2 | |
1153 | ////////////////////////////////////////////////////////////////// | |
1154 | ||
1155 | ||
1156 | // got park request. transition into parking. parking check. | |
1157 | always @(negedge `SPC5.tlu.tcu_core_running[2]) begin: GOTPARK2 | |
1158 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 2 calling parkingCheck"); | |
1159 | if (enabled) parkingCheck2(); | |
1160 | end | |
1161 | ||
1162 | // got unpark request. transition into running. unparking check. | |
1163 | always @(posedge `SPC5.tlu.tcu_core_running[2]) begin: UNPARKCHECK2 | |
1164 | if (enabled && !ssMode) begin | |
1165 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 2 calling unparkCheck."); | |
1166 | unparkCheck2(); | |
1167 | end | |
1168 | end | |
1169 | ||
1170 | // while parked check | |
1171 | always @(posedge parkedState[2] or posedge virtualPark[2]) begin: PARKCHECK2 | |
1172 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 2 calling parkedCheck"); | |
1173 | if (enabled) parkedCheck2(); | |
1174 | end | |
1175 | ||
1176 | // check for unexpected running transition | |
1177 | always @(`SPC5.tlu.tlu_core_running_status[2]) begin: UNEXPECTED2 | |
1178 | if (!parkTrans[2] && enabled && ! doMode && ! ssMode) // review? to remove ! doMode | |
1179 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 2 spc_core_running_status changed w/o request to park/unpark (trans=%0d)!",parkTrans[2]); | |
1180 | end | |
1181 | ||
1182 | ||
1183 | ||
1184 | ////////////// tasks for tid 2 //////////////////// | |
1185 | ||
1186 | // check the entering into parked state | |
1187 | task parkingCheck2; | |
1188 | ||
1189 | begin | |
1190 | ||
1191 | ||
1192 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 2 got park request!"); | |
1193 | ||
1194 | if (parkTrans[2] == 1) begin | |
1195 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 2 got park request while park state is already transitioning! Possible diag conflict (multiple parkers)! (enabled=%0d)",enabled); | |
1196 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +noDebugChecks to disable all debug checkes!"); | |
1197 | disable parkingCheck2; | |
1198 | end | |
1199 | ||
1200 | parkTrans[2] = 1; | |
1201 | ||
1202 | // wait before checking signals | |
1203 | repeat (2) @(negedge `SPC5.l2clk); | |
1204 | ||
1205 | // need to see at least one assertion of flush | |
1206 | // if (`SPC5.tlu_flush_ifu[2] !== 1) | |
1207 | // @(posedge `SPC5.tlu_flush_ifu[2]); // has glitches | |
1208 | if (`SPC5.ifu_ftu.ftu_agc_ctl.tlu_flush_ifu_f[2] !== 1) | |
1209 | @(posedge `SPC5.ifu_ftu.ftu_agc_ctl.tlu_flush_ifu_f[2]); | |
1210 | ||
1211 | // need to see all of these go idle | |
1212 | while (`SPC5.pku_quiesce[2] == 0 || | |
1213 | `SPC5.ftu_ifu_quiesce[2] == 0 || | |
1214 | `SPC5.lsu_stb_empty[2] == 0) | |
1215 | @(negedge `SPC5.l2clk); | |
1216 | ||
1217 | // // need to see all of these go idle | |
1218 | // while (`SPC5.pku_quiesce[2] == 0 || | |
1219 | // `SPC5.ftu_ifu_quiesce[2] == 0 || | |
1220 | // `SPC5.lsu_stb_empty[2] == 0 || | |
1221 | // `SPC5.tlu.fls0.idl_request == 0) | |
1222 | // @(negedge `SPC5.l2clk); | |
1223 | ||
1224 | parkedState[2] <= 1; | |
1225 | parkTrans[2] <= 0; | |
1226 | // `PR_ALWAYS("dbg_chk", `ALWAYS, "INFO: TID %0d has parked!", 2); | |
1227 | `PR_DEBUG("dbg_chk", `DEBUG, "INFO: TID 2 has parked!"); | |
1228 | ||
1229 | end | |
1230 | endtask | |
1231 | ||
1232 | ||
1233 | // in parked state. | |
1234 | // also called between single steps. | |
1235 | task parkedCheck2; | |
1236 | reg notified; | |
1237 | begin //{ | |
1238 | ||
1239 | notified = 0; | |
1240 | // loop while not transitioning out of park if not SS mode. | |
1241 | // loop while in SS virtualPark if SS mode. | |
1242 | while ((parkTrans[2] == 0 && ssMode == 0) || | |
1243 | (virtualPark[2] == 1 && ssMode == 1 && | |
1244 | `TOP.cpu.tcu_ss_request[5] == 0)) begin //{ | |
1245 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 2 watching for activity while parked/between steps. trans=%0h, virtualPark=%0h, tcu_ss_request=%0h",parkTrans[2],virtualPark[2],`TOP.cpu.tcu_ss_request[5]); | |
1246 | ||
1247 | @(negedge `SPC5.l2clk); | |
1248 | ||
1249 | // if in SS mode and core_running goes to zero for that thread, the thread | |
1250 | // will self step once and flush in order to change to a parked state | |
1251 | // (core_running_status=0). This looks like an un-asked for step so it | |
1252 | // has to be detected and ignored. Try stalling here during it. | |
1253 | while (`SPC5.tlu.tcu_core_running[2] == 0 && | |
1254 | `SPC5.tlu.tlu_core_running_status[2] == 1) | |
1255 | @(negedge `SPC5.l2clk); | |
1256 | ||
1257 | // watch for instructions sneaking in | |
1258 | // dec_inst_valid_m[1:0], one bit per group | |
1259 | if (`SPC5.tlu_trap_pc_0_valid && `SPC5.tlu_trap_0_tid[1:0] == 2 && `SPC5.tlu.tlu_retry[0] == 1) | |
1260 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 2 had tlu_trap_pc_0_valid activity while parked/between steps!"); | |
1261 | ||
1262 | if (`SPC5.dec_inst_valid_m[0] == 1 && `SPC5.dec_tid0_m[1:0] == 2) | |
1263 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 2 had dec_inst_valid_m activity while parked/between steps!"); | |
1264 | ||
1265 | ||
1266 | end //} while | |
1267 | ||
1268 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 2 STOP watching for activity while parked/between steps. trans=%0h, virtualPark=%0h, tcu_ss_request=%0h",parkTrans[2],virtualPark[2],`TOP.cpu.tcu_ss_request[5]); | |
1269 | ||
1270 | end //} | |
1271 | endtask | |
1272 | ||
1273 | ||
1274 | // leaving parked state | |
1275 | task unparkCheck2; | |
1276 | integer count; | |
1277 | begin | |
1278 | ||
1279 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 2 got unpark request!"); | |
1280 | ||
1281 | if (parkTrans[2] == 1) begin | |
1282 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 2 got unpark request while park state is already transitioning! Possible diag conflict! (trans=%0h)",parkTrans); | |
1283 | disable unparkCheck2; | |
1284 | end | |
1285 | ||
1286 | parkTrans[2] = 1; | |
1287 | ||
1288 | // must see `SPC5.tlu.core_running_status[2] w/in count clocks | |
1289 | count2 = 0; | |
1290 | ||
1291 | while (`SPC5.tlu.tlu_core_running_status[2] == 0) begin | |
1292 | @(negedge `SPC5.l2clk); | |
1293 | if (count2 > parkWait) begin // <--- may need to adjust | |
1294 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 2 did not assert spc_core_running_status as soon as it should have (%0d clocks)!", count2); | |
1295 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +parkWait=n (currently %0d). +noDebugChecks disables all checks!",parkWait); | |
1296 | end | |
1297 | count2 = count2 + 1; | |
1298 | end | |
1299 | ||
1300 | if (!doMode && !ssMode) begin | |
1301 | // need to see re-direct w/in "redirectWait" more clocks | |
1302 | count2 = 0; | |
1303 | ||
1304 | // if this is true, the redirect and the assertion of core_running_status | |
1305 | // happened at once so while loop can be skipped. | |
1306 | while (! (`SPC5.tlu_trap_pc_0_valid && | |
1307 | `SPC5.tlu_trap_0_tid[1:0] == 2)) begin | |
1308 | @(negedge `SPC5.l2clk); | |
1309 | if (count2 > redirectWait) begin // <--- may need to adjust | |
1310 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 2 did not redirect within %d clocks after core_running_status assert!", redirectWait); | |
1311 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +redirectWait=n (currently %0d). +noDebugChecks disables all checks!",redirectWait); | |
1312 | end | |
1313 | count2 = count2 + 1; | |
1314 | end | |
1315 | end | |
1316 | ||
1317 | parkedState[2] <= 0; | |
1318 | parkTrans[2] <= 0; | |
1319 | count2 <= 0; | |
1320 | ||
1321 | end | |
1322 | endtask | |
1323 | ||
1324 | ||
1325 | // watch this tid step correctly. Should step 1 instruction | |
1326 | // and then "virtual park". | |
1327 | // for SS and DO modes. | |
1328 | task watchStep2; | |
1329 | begin | |
1330 | ||
1331 | watchStepFlush[2] = 0; // set if we got a flush | |
1332 | watchStepMMU[2] = 0; // set if we got a mmu reload | |
1333 | stepDone[2] = 0; | |
1334 | stepActive[2] = 1; | |
1335 | ||
1336 | if (flushCount2) `PR_DEBUG("dbg_chk", `DEBUG, "watchStep2: TID 2 repeating watchStep task due to flush (flushCount=%0d, redirectCount=%0d)!",flushCount2,redirectCount2); | |
1337 | ||
1338 | ||
1339 | fork | |
1340 | // timeout fork | |
1341 | begin : FORK10_2 | |
1342 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
1343 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep2: TID 2 did not see valid PC retry (waitTime=%0d)!", stepWaitTime); | |
1344 | end | |
1345 | ||
1346 | // // look for SPU going active | |
1347 | // begin : FORK11_2 | |
1348 | // while (!(`SPC5.spu_tlu_cwq_busy || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 2))) | |
1349 | // @(negedge `SPC5.l2clk); | |
1350 | // `PR_DEBUG("dbg_chk", `DEBUG, "watchStep2: TID 2 see SPU active!"); | |
1351 | // spuActive[2] = 1; | |
1352 | // end | |
1353 | ||
1354 | // might get ss_complete due to not knowing if there are 1 or 2 or more flushes. | |
1355 | // this task gets called w/o knowing in advance if there will be one more | |
1356 | // assertion of tlu_trap_pc_0/1_valid or not. | |
1357 | begin : FORK8_2 | |
1358 | if (ssMode) begin | |
1359 | @(posedge `SPC5.spc_ss_complete); | |
1360 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep2: TID 2 see spc_ss_complete, step done, bailing (flushCount=%0d/redirectCount=%0d)!", flushCount2, redirectCount2); | |
1361 | stepDone[2] = 1; | |
1362 | stepActive[2] = 0; | |
1363 | disable watchStep2; // return | |
1364 | end | |
1365 | end | |
1366 | ||
1367 | // valid PC / retry | |
1368 | begin : FORK9_2 | |
1369 | // start step. tid wakes up/redirects and does "one instruction" | |
1370 | while (!(`SPC5.tlu_trap_pc_0_valid && `SPC5.tlu_trap_0_tid[1:0] == 2 && `SPC5.tlu.tlu_retry[0] == 1)) begin | |
1371 | // might see `SPC5.tlu.mmu_reload_done[2] here if previous | |
1372 | // redirect was due to a MMU miss. If so, decrement flush count because | |
1373 | // the previous flush on prev pc_valid "does not count" and there can be | |
1374 | // any number of them w/ no way to predict quantity. | |
1375 | if (`SPC5.tlu.mmu_reload_done[2] && ssMode) begin | |
1376 | flushCount2 = flushCount2-1; | |
1377 | redirectCount2 = redirectCount2-1; | |
1378 | watchStepMMU[2] = 1; | |
1379 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep2: TID 2 saw mmu_reload_done (hwtw)! flushCount/redirectCount decremented to %0d/%0d", flushCount2, redirectCount2); | |
1380 | end | |
1381 | @(negedge `SPC5.l2clk); | |
1382 | end | |
1383 | ||
1384 | redirectCount2 = redirectCount2+1; | |
1385 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep2: TID 2 got valid retry, step waiting on negedge pku_quiesce (redirectCount=%0d)!",redirectCount2); | |
1386 | disable FORK8_2; // kill sync on spc_ss_complete | |
1387 | ||
1388 | @(negedge `SPC5.pku_quiesce[2]); | |
1389 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep2: TID 2 got negedge pku_quiesce, step waiting on dec_inst_valid_m!"); | |
1390 | ||
1391 | while (!(`SPC5.dec_inst_valid_m[0] == 1 && `SPC5.dec_tid0_m[1:0] == 2)) @(negedge `SPC5.l2clk); | |
1392 | ||
1393 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep2: TID 2 valid step starting!"); | |
1394 | disable FORK10_2; // kill timeout | |
1395 | //disable FORK11_2; | |
1396 | // if (!`SPC5.spu_tlu_cwq_busy && | |
1397 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
1398 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 2)) spuActive[2] = 0; | |
1399 | end | |
1400 | join | |
1401 | ||
1402 | ||
1403 | ||
1404 | // finish step | |
1405 | fork | |
1406 | // timeout fork | |
1407 | begin : FORK4_2 | |
1408 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
1409 | ||
1410 | // may need to adjust. If a tid is doing a SPU sync ctl reg sync read, | |
1411 | // it could stay "busy" for a REAL long time!!! Need delayed check of busy | |
1412 | // since it can assert after the step has started. | |
1413 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep2: TID 2 did not quiesce/complete after step (SS or DO) as it should have. not SPU busy (waitTime=%0d)!", stepWaitTime); | |
1414 | end | |
1415 | ||
1416 | // look for SPU going active | |
1417 | // begin : FORK12_2 | |
1418 | // while (!(`SPC5.spu_tlu_cwq_busy || | |
1419 | // ((`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 2 && doMode) || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && ssMode)))) | |
1420 | // @(negedge `SPC5.l2clk); | |
1421 | // spuActive[2] = 1; | |
1422 | // end | |
1423 | ||
1424 | ||
1425 | // look for flush_ifu (w/o lsu_trap_flush (aka ptrap_flush) if SS) | |
1426 | // and end this task if seen. tlu_flush_ifu assertion always means | |
1427 | // this "instruction" is done, but may repeat (tlb miss, etc) w/in the SS. | |
1428 | begin : FORK6_2 | |
1429 | // checking ptrap_flush to make sure that flush is not caused by lsu_trap_flush | |
1430 | while (`SPC5.tlu_flush_ifu[2] == 0) | |
1431 | @(negedge `SPC5.l2clk); | |
1432 | ||
1433 | // // debug!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
1434 | // if (`SPC5.tlu.fls0.ptrap_flush[2] == 1) begin | |
1435 | // `PR_ERROR ("dbg_chk", `ERROR, "watchStep2: TID 2 have tlu_flush_ifu !!!!!!!!!!!!!!!!!!!!!!!"); | |
1436 | // end | |
1437 | // | |
1438 | ||
1439 | if ((ssMode && `SPC5.tlu.fls0.ptrap_flush[2] == 0) || doMode) begin | |
1440 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep2: TID 2 have tlu_flush_ifu (flushCount=%0d)!",flushCount2); | |
1441 | watchStepFlush[2] = 1; | |
1442 | flushCount2 = flushCount2+1; | |
1443 | stepActive[2] = 0; | |
1444 | disable watchStep2; // return | |
1445 | end | |
1446 | end | |
1447 | ||
1448 | ||
1449 | // are we done fork, DO mode quiesce | |
1450 | begin : FORK5_2 | |
1451 | if (doMode) begin | |
1452 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep2: TID 2 watching for quiesce (only matters fo DO mode)!"); | |
1453 | while (`SPC5.pku_quiesce[2] == 0 || | |
1454 | `SPC5.ftu_ifu_quiesce[2] == 0 || | |
1455 | `SPC5.lsu_stb_empty[2] == 0) @(negedge `SPC5.l2clk); | |
1456 | ||
1457 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep2: TID 2 have quiesce (only matters for DO mode)!"); | |
1458 | if (doMode) begin | |
1459 | disable FORK4_2; // TO | |
1460 | disable FORK6_2; // flush check | |
1461 | //disable FORK12_2; | |
1462 | // @(negedge `SPC5.l2clk); | |
1463 | // if (!`SPC5.spu_tlu_cwq_busy && | |
1464 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
1465 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 2)) spuActive[2] = 0; | |
1466 | end | |
1467 | end | |
1468 | end | |
1469 | ||
1470 | ||
1471 | // are we done fork, SS mode only | |
1472 | begin : FORK7_2 | |
1473 | // wait for SS complete | |
1474 | if (ssMode) begin | |
1475 | @(posedge `SPC5.spc_ss_complete); | |
1476 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep2: TID 2 see spc_ss_complete, step done, bailing (flushCount=%0d/redirectCount=%0d)!", flushCount2,redirectCount2); | |
1477 | stepDone[2] = 1; | |
1478 | ||
1479 | // while (ssMode && !`SPC5.spc_ss_complete) begin | |
1480 | // // detect a second inst valid w/o a flush between | |
1481 | // if (`SPC5.tlu_trap_pc_0_valid && `SPC5.tlu_trap_0_tid[1:0] == 2 && `SPC5.tlu.tlu_retry[0] == 1) begin | |
1482 | // // delay error so flush thread can kill this in the "got flush" case | |
1483 | // @(negedge `SPC5.l2clk); | |
1484 | // `PR_ERROR ("dbg_chk", `ERROR, "watchStep2: TID 2 had another inst start before SS done was asserted!"); | |
1485 | // end | |
1486 | // @(negedge `SPC5.l2clk); | |
1487 | // end // while | |
1488 | ||
1489 | if (`SPC5.pku_quiesce[2] == 0 || | |
1490 | `SPC5.ftu_ifu_quiesce[2] == 0 || | |
1491 | `SPC5.lsu_stb_empty[2] == 0) | |
1492 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep2: TID 2 was not quiesce at ss_complete assertion!"); | |
1493 | ||
1494 | disable FORK4_2; // TO | |
1495 | disable FORK6_2; // flush check | |
1496 | //disable FORK12_2; | |
1497 | // @(negedge `SPC5.l2clk); | |
1498 | // if (!`SPC5.spu_tlu_cwq_busy && | |
1499 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
1500 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 2)) spuActive[2] = 0; | |
1501 | end | |
1502 | end | |
1503 | ||
1504 | join | |
1505 | ||
1506 | ||
1507 | if (flushCount2 == 0) `PR_DEBUG("dbg_chk", `DEBUG, "watchStep2: TID 2 watchStep end!"); | |
1508 | else `PR_DEBUG("dbg_chk", `DEBUG, "watchStep2: TID 2 repeated watchStep end!"); | |
1509 | ||
1510 | stepActive[2] = 0; | |
1511 | ||
1512 | end | |
1513 | endtask | |
1514 | ||
1515 | ||
1516 | ||
1517 | // check that thread does DO mode correctly | |
1518 | task watchDOsteps2; | |
1519 | begin | |
1520 | ||
1521 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps2: TID 2 watchDOsteps starting!"); | |
1522 | ||
1523 | if (! `TOP.cpu.tcu_do_mode[5]) disable watchDOsteps2; | |
1524 | ||
1525 | // now wait for a thread to start. TCU internal signal. | |
1526 | if (`SPC5.tlu.tlu_core_running_status[2] == 0) | |
1527 | @(posedge `SPC5.tlu.tlu_core_running_status[2]); | |
1528 | ||
1529 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps2 TID 2 unparked and running in DO mode!"); | |
1530 | ||
1531 | // loop on step checking. DO mode is self stepping | |
1532 | while (doMode) begin : watchDOsteps2loop// && `SPC5.tlu.tlu_core_running_status[7:0] != 0) begin | |
1533 | ||
1534 | stepDone[2] = 0; | |
1535 | watchStepFlush[2] = 0; | |
1536 | watchStepMMU[2] = 0; | |
1537 | ||
1538 | // are we starting to park in middle of DO mode (or end)? | |
1539 | // wait here until unparked again | |
1540 | if (parkTrans[2]) begin | |
1541 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps2 TID 2 getting parked, will delay"); | |
1542 | @(negedge parkTrans[2]); | |
1543 | if (!doMode) disable watchDOsteps2loop; // no longer in DO mode, bail | |
1544 | // wait to be unparked or !doMode | |
1545 | if (parkedState[2]) begin | |
1546 | @(negedge doMode or negedge parkedState[2]); | |
1547 | if (!doMode) disable watchDOsteps2loop; // no longer in DO mode, bail | |
1548 | end | |
1549 | end | |
1550 | ||
1551 | ||
1552 | // an unparked thread does one instruction to completion before thread starts | |
1553 | // the next instruction. | |
1554 | fork | |
1555 | // timeout fork | |
1556 | begin : FORKDO12 | |
1557 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
1558 | `PR_ERROR ("dbg_chk", `ERROR, "watchDOsteps2: DO mode, TID 2 timeout waiting for watchStep call to return, not SPU busy (+stepWaitTime=%0d)!", stepWaitTime); | |
1559 | end | |
1560 | ||
1561 | // look for SPU going active | |
1562 | // begin : FORKDO22 | |
1563 | // while (!(`SPC5.spu_tlu_cwq_busy || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 2))) | |
1564 | // @(negedge `SPC5.l2clk); | |
1565 | // `PR_ALWAYS("dbg_chk", `ALWAYS, "watchDOsteps2: DO mode, TID 2 sees SPU busy!"); | |
1566 | // spuActive[2] = 1; | |
1567 | // end | |
1568 | ||
1569 | // watch step | |
1570 | begin | |
1571 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps2: TID 2 calling watchStep2 in DO mode!"); | |
1572 | watchStep2; // returns when step is done or flushed | |
1573 | if (watchStepFlush[2]) | |
1574 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 2 in DO mode had flush!"); | |
1575 | if (watchStepMMU[2]) | |
1576 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 2 in DO mode had mmu reload!"); | |
1577 | // calling flush as a done in DO mode | |
1578 | disable FORKDO12; // TO | |
1579 | //disable FORKDO22; // SPU going active | |
1580 | end | |
1581 | ||
1582 | join | |
1583 | ||
1584 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps2: TID 2 DO mode watchDOsteps step done!"); | |
1585 | stepDone[2] = 1; | |
1586 | flushCount2 = 0; | |
1587 | // if (!`SPC5.spu_tlu_cwq_busy && | |
1588 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
1589 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 2)) spuActive[2] = 0; | |
1590 | ||
1591 | @(negedge `SPC5.l2clk); | |
1592 | end // while | |
1593 | ||
1594 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps2: TID 2 DO mode watchDOsteps task ending!"); | |
1595 | end | |
1596 | endtask | |
1597 | ||
1598 | ||
1599 | ||
1600 | ||
1601 | ////////////////////////// end tid 2 /////////////////////////////////////// | |
1602 | ||
1603 | ||
1604 | ////////////////////////////////////////////////////////////////// | |
1605 | // THREAD 3 | |
1606 | ////////////////////////////////////////////////////////////////// | |
1607 | ||
1608 | ||
1609 | // got park request. transition into parking. parking check. | |
1610 | always @(negedge `SPC5.tlu.tcu_core_running[3]) begin: GOTPARK3 | |
1611 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 3 calling parkingCheck"); | |
1612 | if (enabled) parkingCheck3(); | |
1613 | end | |
1614 | ||
1615 | // got unpark request. transition into running. unparking check. | |
1616 | always @(posedge `SPC5.tlu.tcu_core_running[3]) begin: UNPARKCHECK3 | |
1617 | if (enabled && !ssMode) begin | |
1618 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 3 calling unparkCheck."); | |
1619 | unparkCheck3(); | |
1620 | end | |
1621 | end | |
1622 | ||
1623 | // while parked check | |
1624 | always @(posedge parkedState[3] or posedge virtualPark[3]) begin: PARKCHECK3 | |
1625 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 3 calling parkedCheck"); | |
1626 | if (enabled) parkedCheck3(); | |
1627 | end | |
1628 | ||
1629 | // check for unexpected running transition | |
1630 | always @(`SPC5.tlu.tlu_core_running_status[3]) begin: UNEXPECTED3 | |
1631 | if (!parkTrans[3] && enabled && ! doMode && ! ssMode) // review? to remove ! doMode | |
1632 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 3 spc_core_running_status changed w/o request to park/unpark (trans=%0d)!",parkTrans[3]); | |
1633 | end | |
1634 | ||
1635 | ||
1636 | ||
1637 | ////////////// tasks for tid 3 //////////////////// | |
1638 | ||
1639 | // check the entering into parked state | |
1640 | task parkingCheck3; | |
1641 | ||
1642 | begin | |
1643 | ||
1644 | ||
1645 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 3 got park request!"); | |
1646 | ||
1647 | if (parkTrans[3] == 1) begin | |
1648 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 3 got park request while park state is already transitioning! Possible diag conflict (multiple parkers)! (enabled=%0d)",enabled); | |
1649 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +noDebugChecks to disable all debug checkes!"); | |
1650 | disable parkingCheck3; | |
1651 | end | |
1652 | ||
1653 | parkTrans[3] = 1; | |
1654 | ||
1655 | // wait before checking signals | |
1656 | repeat (2) @(negedge `SPC5.l2clk); | |
1657 | ||
1658 | // need to see at least one assertion of flush | |
1659 | // if (`SPC5.tlu_flush_ifu[3] !== 1) | |
1660 | // @(posedge `SPC5.tlu_flush_ifu[3]); // has glitches | |
1661 | if (`SPC5.ifu_ftu.ftu_agc_ctl.tlu_flush_ifu_f[3] !== 1) | |
1662 | @(posedge `SPC5.ifu_ftu.ftu_agc_ctl.tlu_flush_ifu_f[3]); | |
1663 | ||
1664 | // need to see all of these go idle | |
1665 | while (`SPC5.pku_quiesce[3] == 0 || | |
1666 | `SPC5.ftu_ifu_quiesce[3] == 0 || | |
1667 | `SPC5.lsu_stb_empty[3] == 0) | |
1668 | @(negedge `SPC5.l2clk); | |
1669 | ||
1670 | // // need to see all of these go idle | |
1671 | // while (`SPC5.pku_quiesce[3] == 0 || | |
1672 | // `SPC5.ftu_ifu_quiesce[3] == 0 || | |
1673 | // `SPC5.lsu_stb_empty[3] == 0 || | |
1674 | // `SPC5.tlu.fls0.idl_request == 0) | |
1675 | // @(negedge `SPC5.l2clk); | |
1676 | ||
1677 | parkedState[3] <= 1; | |
1678 | parkTrans[3] <= 0; | |
1679 | // `PR_ALWAYS("dbg_chk", `ALWAYS, "INFO: TID %0d has parked!", 3); | |
1680 | `PR_DEBUG("dbg_chk", `DEBUG, "INFO: TID 3 has parked!"); | |
1681 | ||
1682 | end | |
1683 | endtask | |
1684 | ||
1685 | ||
1686 | // in parked state. | |
1687 | // also called between single steps. | |
1688 | task parkedCheck3; | |
1689 | reg notified; | |
1690 | begin //{ | |
1691 | ||
1692 | notified = 0; | |
1693 | // loop while not transitioning out of park if not SS mode. | |
1694 | // loop while in SS virtualPark if SS mode. | |
1695 | while ((parkTrans[3] == 0 && ssMode == 0) || | |
1696 | (virtualPark[3] == 1 && ssMode == 1 && | |
1697 | `TOP.cpu.tcu_ss_request[5] == 0)) begin //{ | |
1698 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 3 watching for activity while parked/between steps. trans=%0h, virtualPark=%0h, tcu_ss_request=%0h",parkTrans[3],virtualPark[3],`TOP.cpu.tcu_ss_request[5]); | |
1699 | ||
1700 | @(negedge `SPC5.l2clk); | |
1701 | ||
1702 | // if in SS mode and core_running goes to zero for that thread, the thread | |
1703 | // will self step once and flush in order to change to a parked state | |
1704 | // (core_running_status=0). This looks like an un-asked for step so it | |
1705 | // has to be detected and ignored. Try stalling here during it. | |
1706 | while (`SPC5.tlu.tcu_core_running[3] == 0 && | |
1707 | `SPC5.tlu.tlu_core_running_status[3] == 1) | |
1708 | @(negedge `SPC5.l2clk); | |
1709 | ||
1710 | // watch for instructions sneaking in | |
1711 | // dec_inst_valid_m[1:0], one bit per group | |
1712 | if (`SPC5.tlu_trap_pc_0_valid && `SPC5.tlu_trap_0_tid[1:0] == 3 && `SPC5.tlu.tlu_retry[0] == 1) | |
1713 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 3 had tlu_trap_pc_0_valid activity while parked/between steps!"); | |
1714 | ||
1715 | if (`SPC5.dec_inst_valid_m[0] == 1 && `SPC5.dec_tid0_m[1:0] == 3) | |
1716 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 3 had dec_inst_valid_m activity while parked/between steps!"); | |
1717 | ||
1718 | ||
1719 | end //} while | |
1720 | ||
1721 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 3 STOP watching for activity while parked/between steps. trans=%0h, virtualPark=%0h, tcu_ss_request=%0h",parkTrans[3],virtualPark[3],`TOP.cpu.tcu_ss_request[5]); | |
1722 | ||
1723 | end //} | |
1724 | endtask | |
1725 | ||
1726 | ||
1727 | // leaving parked state | |
1728 | task unparkCheck3; | |
1729 | integer count; | |
1730 | begin | |
1731 | ||
1732 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 3 got unpark request!"); | |
1733 | ||
1734 | if (parkTrans[3] == 1) begin | |
1735 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 3 got unpark request while park state is already transitioning! Possible diag conflict! (trans=%0h)",parkTrans); | |
1736 | disable unparkCheck3; | |
1737 | end | |
1738 | ||
1739 | parkTrans[3] = 1; | |
1740 | ||
1741 | // must see `SPC5.tlu.core_running_status[3] w/in count clocks | |
1742 | count3 = 0; | |
1743 | ||
1744 | while (`SPC5.tlu.tlu_core_running_status[3] == 0) begin | |
1745 | @(negedge `SPC5.l2clk); | |
1746 | if (count3 > parkWait) begin // <--- may need to adjust | |
1747 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 3 did not assert spc_core_running_status as soon as it should have (%0d clocks)!", count3); | |
1748 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +parkWait=n (currently %0d). +noDebugChecks disables all checks!",parkWait); | |
1749 | end | |
1750 | count3 = count3 + 1; | |
1751 | end | |
1752 | ||
1753 | if (!doMode && !ssMode) begin | |
1754 | // need to see re-direct w/in "redirectWait" more clocks | |
1755 | count3 = 0; | |
1756 | ||
1757 | // if this is true, the redirect and the assertion of core_running_status | |
1758 | // happened at once so while loop can be skipped. | |
1759 | while (! (`SPC5.tlu_trap_pc_0_valid && | |
1760 | `SPC5.tlu_trap_0_tid[1:0] == 3)) begin | |
1761 | @(negedge `SPC5.l2clk); | |
1762 | if (count3 > redirectWait) begin // <--- may need to adjust | |
1763 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 3 did not redirect within %d clocks after core_running_status assert!", redirectWait); | |
1764 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +redirectWait=n (currently %0d). +noDebugChecks disables all checks!",redirectWait); | |
1765 | end | |
1766 | count3 = count3 + 1; | |
1767 | end | |
1768 | end | |
1769 | ||
1770 | parkedState[3] <= 0; | |
1771 | parkTrans[3] <= 0; | |
1772 | count3 <= 0; | |
1773 | ||
1774 | end | |
1775 | endtask | |
1776 | ||
1777 | ||
1778 | // watch this tid step correctly. Should step 1 instruction | |
1779 | // and then "virtual park". | |
1780 | // for SS and DO modes. | |
1781 | task watchStep3; | |
1782 | begin | |
1783 | ||
1784 | watchStepFlush[3] = 0; // set if we got a flush | |
1785 | watchStepMMU[3] = 0; // set if we got a mmu reload | |
1786 | stepDone[3] = 0; | |
1787 | stepActive[3] = 1; | |
1788 | ||
1789 | if (flushCount3) `PR_DEBUG("dbg_chk", `DEBUG, "watchStep3: TID 3 repeating watchStep task due to flush (flushCount=%0d, redirectCount=%0d)!",flushCount3,redirectCount3); | |
1790 | ||
1791 | ||
1792 | fork | |
1793 | // timeout fork | |
1794 | begin : FORK10_3 | |
1795 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
1796 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep3: TID 3 did not see valid PC retry (waitTime=%0d)!", stepWaitTime); | |
1797 | end | |
1798 | ||
1799 | // // look for SPU going active | |
1800 | // begin : FORK11_3 | |
1801 | // while (!(`SPC5.spu_tlu_cwq_busy || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 3))) | |
1802 | // @(negedge `SPC5.l2clk); | |
1803 | // `PR_DEBUG("dbg_chk", `DEBUG, "watchStep3: TID 3 see SPU active!"); | |
1804 | // spuActive[3] = 1; | |
1805 | // end | |
1806 | ||
1807 | // might get ss_complete due to not knowing if there are 1 or 2 or more flushes. | |
1808 | // this task gets called w/o knowing in advance if there will be one more | |
1809 | // assertion of tlu_trap_pc_0/1_valid or not. | |
1810 | begin : FORK8_3 | |
1811 | if (ssMode) begin | |
1812 | @(posedge `SPC5.spc_ss_complete); | |
1813 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep3: TID 3 see spc_ss_complete, step done, bailing (flushCount=%0d/redirectCount=%0d)!", flushCount3, redirectCount3); | |
1814 | stepDone[3] = 1; | |
1815 | stepActive[3] = 0; | |
1816 | disable watchStep3; // return | |
1817 | end | |
1818 | end | |
1819 | ||
1820 | // valid PC / retry | |
1821 | begin : FORK9_3 | |
1822 | // start step. tid wakes up/redirects and does "one instruction" | |
1823 | while (!(`SPC5.tlu_trap_pc_0_valid && `SPC5.tlu_trap_0_tid[1:0] == 3 && `SPC5.tlu.tlu_retry[0] == 1)) begin | |
1824 | // might see `SPC5.tlu.mmu_reload_done[3] here if previous | |
1825 | // redirect was due to a MMU miss. If so, decrement flush count because | |
1826 | // the previous flush on prev pc_valid "does not count" and there can be | |
1827 | // any number of them w/ no way to predict quantity. | |
1828 | if (`SPC5.tlu.mmu_reload_done[3] && ssMode) begin | |
1829 | flushCount3 = flushCount3-1; | |
1830 | redirectCount3 = redirectCount3-1; | |
1831 | watchStepMMU[3] = 1; | |
1832 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep3: TID 3 saw mmu_reload_done (hwtw)! flushCount/redirectCount decremented to %0d/%0d", flushCount3, redirectCount3); | |
1833 | end | |
1834 | @(negedge `SPC5.l2clk); | |
1835 | end | |
1836 | ||
1837 | redirectCount3 = redirectCount3+1; | |
1838 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep3: TID 3 got valid retry, step waiting on negedge pku_quiesce (redirectCount=%0d)!",redirectCount3); | |
1839 | disable FORK8_3; // kill sync on spc_ss_complete | |
1840 | ||
1841 | @(negedge `SPC5.pku_quiesce[3]); | |
1842 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep3: TID 3 got negedge pku_quiesce, step waiting on dec_inst_valid_m!"); | |
1843 | ||
1844 | while (!(`SPC5.dec_inst_valid_m[0] == 1 && `SPC5.dec_tid0_m[1:0] == 3)) @(negedge `SPC5.l2clk); | |
1845 | ||
1846 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep3: TID 3 valid step starting!"); | |
1847 | disable FORK10_3; // kill timeout | |
1848 | //disable FORK11_3; | |
1849 | // if (!`SPC5.spu_tlu_cwq_busy && | |
1850 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
1851 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 3)) spuActive[3] = 0; | |
1852 | end | |
1853 | join | |
1854 | ||
1855 | ||
1856 | ||
1857 | // finish step | |
1858 | fork | |
1859 | // timeout fork | |
1860 | begin : FORK4_3 | |
1861 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
1862 | ||
1863 | // may need to adjust. If a tid is doing a SPU sync ctl reg sync read, | |
1864 | // it could stay "busy" for a REAL long time!!! Need delayed check of busy | |
1865 | // since it can assert after the step has started. | |
1866 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep3: TID 3 did not quiesce/complete after step (SS or DO) as it should have. not SPU busy (waitTime=%0d)!", stepWaitTime); | |
1867 | end | |
1868 | ||
1869 | // look for SPU going active | |
1870 | // begin : FORK12_3 | |
1871 | // while (!(`SPC5.spu_tlu_cwq_busy || | |
1872 | // ((`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 3 && doMode) || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && ssMode)))) | |
1873 | // @(negedge `SPC5.l2clk); | |
1874 | // spuActive[3] = 1; | |
1875 | // end | |
1876 | ||
1877 | ||
1878 | // look for flush_ifu (w/o lsu_trap_flush (aka ptrap_flush) if SS) | |
1879 | // and end this task if seen. tlu_flush_ifu assertion always means | |
1880 | // this "instruction" is done, but may repeat (tlb miss, etc) w/in the SS. | |
1881 | begin : FORK6_3 | |
1882 | // checking ptrap_flush to make sure that flush is not caused by lsu_trap_flush | |
1883 | while (`SPC5.tlu_flush_ifu[3] == 0) | |
1884 | @(negedge `SPC5.l2clk); | |
1885 | ||
1886 | // // debug!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
1887 | // if (`SPC5.tlu.fls0.ptrap_flush[3] == 1) begin | |
1888 | // `PR_ERROR ("dbg_chk", `ERROR, "watchStep3: TID 3 have tlu_flush_ifu !!!!!!!!!!!!!!!!!!!!!!!"); | |
1889 | // end | |
1890 | // | |
1891 | ||
1892 | if ((ssMode && `SPC5.tlu.fls0.ptrap_flush[3] == 0) || doMode) begin | |
1893 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep3: TID 3 have tlu_flush_ifu (flushCount=%0d)!",flushCount3); | |
1894 | watchStepFlush[3] = 1; | |
1895 | flushCount3 = flushCount3+1; | |
1896 | stepActive[3] = 0; | |
1897 | disable watchStep3; // return | |
1898 | end | |
1899 | end | |
1900 | ||
1901 | ||
1902 | // are we done fork, DO mode quiesce | |
1903 | begin : FORK5_3 | |
1904 | if (doMode) begin | |
1905 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep3: TID 3 watching for quiesce (only matters fo DO mode)!"); | |
1906 | while (`SPC5.pku_quiesce[3] == 0 || | |
1907 | `SPC5.ftu_ifu_quiesce[3] == 0 || | |
1908 | `SPC5.lsu_stb_empty[3] == 0) @(negedge `SPC5.l2clk); | |
1909 | ||
1910 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep3: TID 3 have quiesce (only matters for DO mode)!"); | |
1911 | if (doMode) begin | |
1912 | disable FORK4_3; // TO | |
1913 | disable FORK6_3; // flush check | |
1914 | //disable FORK12_3; | |
1915 | // @(negedge `SPC5.l2clk); | |
1916 | // if (!`SPC5.spu_tlu_cwq_busy && | |
1917 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
1918 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 3)) spuActive[3] = 0; | |
1919 | end | |
1920 | end | |
1921 | end | |
1922 | ||
1923 | ||
1924 | // are we done fork, SS mode only | |
1925 | begin : FORK7_3 | |
1926 | // wait for SS complete | |
1927 | if (ssMode) begin | |
1928 | @(posedge `SPC5.spc_ss_complete); | |
1929 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep3: TID 3 see spc_ss_complete, step done, bailing (flushCount=%0d/redirectCount=%0d)!", flushCount3,redirectCount3); | |
1930 | stepDone[3] = 1; | |
1931 | ||
1932 | // while (ssMode && !`SPC5.spc_ss_complete) begin | |
1933 | // // detect a second inst valid w/o a flush between | |
1934 | // if (`SPC5.tlu_trap_pc_0_valid && `SPC5.tlu_trap_0_tid[1:0] == 3 && `SPC5.tlu.tlu_retry[0] == 1) begin | |
1935 | // // delay error so flush thread can kill this in the "got flush" case | |
1936 | // @(negedge `SPC5.l2clk); | |
1937 | // `PR_ERROR ("dbg_chk", `ERROR, "watchStep3: TID 3 had another inst start before SS done was asserted!"); | |
1938 | // end | |
1939 | // @(negedge `SPC5.l2clk); | |
1940 | // end // while | |
1941 | ||
1942 | if (`SPC5.pku_quiesce[3] == 0 || | |
1943 | `SPC5.ftu_ifu_quiesce[3] == 0 || | |
1944 | `SPC5.lsu_stb_empty[3] == 0) | |
1945 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep3: TID 3 was not quiesce at ss_complete assertion!"); | |
1946 | ||
1947 | disable FORK4_3; // TO | |
1948 | disable FORK6_3; // flush check | |
1949 | //disable FORK12_3; | |
1950 | // @(negedge `SPC5.l2clk); | |
1951 | // if (!`SPC5.spu_tlu_cwq_busy && | |
1952 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
1953 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 3)) spuActive[3] = 0; | |
1954 | end | |
1955 | end | |
1956 | ||
1957 | join | |
1958 | ||
1959 | ||
1960 | if (flushCount3 == 0) `PR_DEBUG("dbg_chk", `DEBUG, "watchStep3: TID 3 watchStep end!"); | |
1961 | else `PR_DEBUG("dbg_chk", `DEBUG, "watchStep3: TID 3 repeated watchStep end!"); | |
1962 | ||
1963 | stepActive[3] = 0; | |
1964 | ||
1965 | end | |
1966 | endtask | |
1967 | ||
1968 | ||
1969 | ||
1970 | // check that thread does DO mode correctly | |
1971 | task watchDOsteps3; | |
1972 | begin | |
1973 | ||
1974 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps3: TID 3 watchDOsteps starting!"); | |
1975 | ||
1976 | if (! `TOP.cpu.tcu_do_mode[5]) disable watchDOsteps3; | |
1977 | ||
1978 | // now wait for a thread to start. TCU internal signal. | |
1979 | if (`SPC5.tlu.tlu_core_running_status[3] == 0) | |
1980 | @(posedge `SPC5.tlu.tlu_core_running_status[3]); | |
1981 | ||
1982 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps3 TID 3 unparked and running in DO mode!"); | |
1983 | ||
1984 | // loop on step checking. DO mode is self stepping | |
1985 | while (doMode) begin : watchDOsteps3loop// && `SPC5.tlu.tlu_core_running_status[7:0] != 0) begin | |
1986 | ||
1987 | stepDone[3] = 0; | |
1988 | watchStepFlush[3] = 0; | |
1989 | watchStepMMU[3] = 0; | |
1990 | ||
1991 | // are we starting to park in middle of DO mode (or end)? | |
1992 | // wait here until unparked again | |
1993 | if (parkTrans[3]) begin | |
1994 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps3 TID 3 getting parked, will delay"); | |
1995 | @(negedge parkTrans[3]); | |
1996 | if (!doMode) disable watchDOsteps3loop; // no longer in DO mode, bail | |
1997 | // wait to be unparked or !doMode | |
1998 | if (parkedState[3]) begin | |
1999 | @(negedge doMode or negedge parkedState[3]); | |
2000 | if (!doMode) disable watchDOsteps3loop; // no longer in DO mode, bail | |
2001 | end | |
2002 | end | |
2003 | ||
2004 | ||
2005 | // an unparked thread does one instruction to completion before thread starts | |
2006 | // the next instruction. | |
2007 | fork | |
2008 | // timeout fork | |
2009 | begin : FORKDO13 | |
2010 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
2011 | `PR_ERROR ("dbg_chk", `ERROR, "watchDOsteps3: DO mode, TID 3 timeout waiting for watchStep call to return, not SPU busy (+stepWaitTime=%0d)!", stepWaitTime); | |
2012 | end | |
2013 | ||
2014 | // look for SPU going active | |
2015 | // begin : FORKDO23 | |
2016 | // while (!(`SPC5.spu_tlu_cwq_busy || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 3))) | |
2017 | // @(negedge `SPC5.l2clk); | |
2018 | // `PR_ALWAYS("dbg_chk", `ALWAYS, "watchDOsteps3: DO mode, TID 3 sees SPU busy!"); | |
2019 | // spuActive[3] = 1; | |
2020 | // end | |
2021 | ||
2022 | // watch step | |
2023 | begin | |
2024 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps3: TID 3 calling watchStep3 in DO mode!"); | |
2025 | watchStep3; // returns when step is done or flushed | |
2026 | if (watchStepFlush[3]) | |
2027 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 3 in DO mode had flush!"); | |
2028 | if (watchStepMMU[3]) | |
2029 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 3 in DO mode had mmu reload!"); | |
2030 | // calling flush as a done in DO mode | |
2031 | disable FORKDO13; // TO | |
2032 | //disable FORKDO23; // SPU going active | |
2033 | end | |
2034 | ||
2035 | join | |
2036 | ||
2037 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps3: TID 3 DO mode watchDOsteps step done!"); | |
2038 | stepDone[3] = 1; | |
2039 | flushCount3 = 0; | |
2040 | // if (!`SPC5.spu_tlu_cwq_busy && | |
2041 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
2042 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 3)) spuActive[3] = 0; | |
2043 | ||
2044 | @(negedge `SPC5.l2clk); | |
2045 | end // while | |
2046 | ||
2047 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps3: TID 3 DO mode watchDOsteps task ending!"); | |
2048 | end | |
2049 | endtask | |
2050 | ||
2051 | ||
2052 | ||
2053 | ||
2054 | ////////////////////////// end tid 3 /////////////////////////////////////// | |
2055 | ||
2056 | ||
2057 | ////////////////////////////////////////////////////////////////// | |
2058 | // THREAD 4 | |
2059 | ////////////////////////////////////////////////////////////////// | |
2060 | ||
2061 | ||
2062 | // got park request. transition into parking. parking check. | |
2063 | always @(negedge `SPC5.tlu.tcu_core_running[4]) begin: GOTPARK4 | |
2064 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 4 calling parkingCheck"); | |
2065 | if (enabled) parkingCheck4(); | |
2066 | end | |
2067 | ||
2068 | // got unpark request. transition into running. unparking check. | |
2069 | always @(posedge `SPC5.tlu.tcu_core_running[4]) begin: UNPARKCHECK4 | |
2070 | if (enabled && !ssMode) begin | |
2071 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 4 calling unparkCheck."); | |
2072 | unparkCheck4(); | |
2073 | end | |
2074 | end | |
2075 | ||
2076 | // while parked check | |
2077 | always @(posedge parkedState[4] or posedge virtualPark[4]) begin: PARKCHECK4 | |
2078 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 4 calling parkedCheck"); | |
2079 | if (enabled) parkedCheck4(); | |
2080 | end | |
2081 | ||
2082 | // check for unexpected running transition | |
2083 | always @(`SPC5.tlu.tlu_core_running_status[4]) begin: UNEXPECTED4 | |
2084 | if (!parkTrans[4] && enabled && ! doMode && ! ssMode) // review? to remove ! doMode | |
2085 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 4 spc_core_running_status changed w/o request to park/unpark (trans=%0d)!",parkTrans[4]); | |
2086 | end | |
2087 | ||
2088 | ||
2089 | ||
2090 | ////////////// tasks for tid 4 //////////////////// | |
2091 | ||
2092 | // check the entering into parked state | |
2093 | task parkingCheck4; | |
2094 | ||
2095 | begin | |
2096 | ||
2097 | ||
2098 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 4 got park request!"); | |
2099 | ||
2100 | if (parkTrans[4] == 1) begin | |
2101 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 4 got park request while park state is already transitioning! Possible diag conflict (multiple parkers)! (enabled=%0d)",enabled); | |
2102 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +noDebugChecks to disable all debug checkes!"); | |
2103 | disable parkingCheck4; | |
2104 | end | |
2105 | ||
2106 | parkTrans[4] = 1; | |
2107 | ||
2108 | // wait before checking signals | |
2109 | repeat (2) @(negedge `SPC5.l2clk); | |
2110 | ||
2111 | // need to see at least one assertion of flush | |
2112 | // if (`SPC5.tlu_flush_ifu[4] !== 1) | |
2113 | // @(posedge `SPC5.tlu_flush_ifu[4]); // has glitches | |
2114 | if (`SPC5.ifu_ftu.ftu_agc_ctl.tlu_flush_ifu_f[4] !== 1) | |
2115 | @(posedge `SPC5.ifu_ftu.ftu_agc_ctl.tlu_flush_ifu_f[4]); | |
2116 | ||
2117 | // need to see all of these go idle | |
2118 | while (`SPC5.pku_quiesce[4] == 0 || | |
2119 | `SPC5.ftu_ifu_quiesce[4] == 0 || | |
2120 | `SPC5.lsu_stb_empty[4] == 0) | |
2121 | @(negedge `SPC5.l2clk); | |
2122 | ||
2123 | // // need to see all of these go idle | |
2124 | // while (`SPC5.pku_quiesce[4] == 0 || | |
2125 | // `SPC5.ftu_ifu_quiesce[4] == 0 || | |
2126 | // `SPC5.lsu_stb_empty[4] == 0 || | |
2127 | // `SPC5.tlu.fls1.idl_request == 0) | |
2128 | // @(negedge `SPC5.l2clk); | |
2129 | ||
2130 | parkedState[4] <= 1; | |
2131 | parkTrans[4] <= 0; | |
2132 | // `PR_ALWAYS("dbg_chk", `ALWAYS, "INFO: TID %0d has parked!", 4); | |
2133 | `PR_DEBUG("dbg_chk", `DEBUG, "INFO: TID 4 has parked!"); | |
2134 | ||
2135 | end | |
2136 | endtask | |
2137 | ||
2138 | ||
2139 | // in parked state. | |
2140 | // also called between single steps. | |
2141 | task parkedCheck4; | |
2142 | reg notified; | |
2143 | begin //{ | |
2144 | ||
2145 | notified = 0; | |
2146 | // loop while not transitioning out of park if not SS mode. | |
2147 | // loop while in SS virtualPark if SS mode. | |
2148 | while ((parkTrans[4] == 0 && ssMode == 0) || | |
2149 | (virtualPark[4] == 1 && ssMode == 1 && | |
2150 | `TOP.cpu.tcu_ss_request[5] == 0)) begin //{ | |
2151 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 4 watching for activity while parked/between steps. trans=%0h, virtualPark=%0h, tcu_ss_request=%0h",parkTrans[4],virtualPark[4],`TOP.cpu.tcu_ss_request[5]); | |
2152 | ||
2153 | @(negedge `SPC5.l2clk); | |
2154 | ||
2155 | // if in SS mode and core_running goes to zero for that thread, the thread | |
2156 | // will self step once and flush in order to change to a parked state | |
2157 | // (core_running_status=0). This looks like an un-asked for step so it | |
2158 | // has to be detected and ignored. Try stalling here during it. | |
2159 | while (`SPC5.tlu.tcu_core_running[4] == 0 && | |
2160 | `SPC5.tlu.tlu_core_running_status[4] == 1) | |
2161 | @(negedge `SPC5.l2clk); | |
2162 | ||
2163 | // watch for instructions sneaking in | |
2164 | // dec_inst_valid_m[1:0], one bit per group | |
2165 | if (`SPC5.tlu_trap_pc_1_valid && `SPC5.tlu_trap_1_tid[1:0] == 4 && `SPC5.tlu.tlu_retry[1] == 1) | |
2166 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 4 had tlu_trap_pc_1_valid activity while parked/between steps!"); | |
2167 | ||
2168 | if (`SPC5.dec_inst_valid_m[1] == 1 && `SPC5.dec_tid1_m[1:0] == 0) | |
2169 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 4 had dec_inst_valid_m activity while parked/between steps!"); | |
2170 | ||
2171 | ||
2172 | end //} while | |
2173 | ||
2174 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 4 STOP watching for activity while parked/between steps. trans=%0h, virtualPark=%0h, tcu_ss_request=%0h",parkTrans[4],virtualPark[4],`TOP.cpu.tcu_ss_request[5]); | |
2175 | ||
2176 | end //} | |
2177 | endtask | |
2178 | ||
2179 | ||
2180 | // leaving parked state | |
2181 | task unparkCheck4; | |
2182 | integer count; | |
2183 | begin | |
2184 | ||
2185 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 4 got unpark request!"); | |
2186 | ||
2187 | if (parkTrans[4] == 1) begin | |
2188 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 4 got unpark request while park state is already transitioning! Possible diag conflict! (trans=%0h)",parkTrans); | |
2189 | disable unparkCheck4; | |
2190 | end | |
2191 | ||
2192 | parkTrans[4] = 1; | |
2193 | ||
2194 | // must see `SPC5.tlu.core_running_status[4] w/in count clocks | |
2195 | count4 = 0; | |
2196 | ||
2197 | while (`SPC5.tlu.tlu_core_running_status[4] == 0) begin | |
2198 | @(negedge `SPC5.l2clk); | |
2199 | if (count4 > parkWait) begin // <--- may need to adjust | |
2200 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 4 did not assert spc_core_running_status as soon as it should have (%0d clocks)!", count4); | |
2201 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +parkWait=n (currently %0d). +noDebugChecks disables all checks!",parkWait); | |
2202 | end | |
2203 | count4 = count4 + 1; | |
2204 | end | |
2205 | ||
2206 | if (!doMode && !ssMode) begin | |
2207 | // need to see re-direct w/in "redirectWait" more clocks | |
2208 | count4 = 0; | |
2209 | ||
2210 | // if this is true, the redirect and the assertion of core_running_status | |
2211 | // happened at once so while loop can be skipped. | |
2212 | while (! (`SPC5.tlu_trap_pc_1_valid && | |
2213 | `SPC5.tlu_trap_1_tid[1:0] == 0)) begin | |
2214 | @(negedge `SPC5.l2clk); | |
2215 | if (count4 > redirectWait) begin // <--- may need to adjust | |
2216 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 4 did not redirect within %d clocks after core_running_status assert!", redirectWait); | |
2217 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +redirectWait=n (currently %0d). +noDebugChecks disables all checks!",redirectWait); | |
2218 | end | |
2219 | count4 = count4 + 1; | |
2220 | end | |
2221 | end | |
2222 | ||
2223 | parkedState[4] <= 0; | |
2224 | parkTrans[4] <= 0; | |
2225 | count4 <= 0; | |
2226 | ||
2227 | end | |
2228 | endtask | |
2229 | ||
2230 | ||
2231 | // watch this tid step correctly. Should step 1 instruction | |
2232 | // and then "virtual park". | |
2233 | // for SS and DO modes. | |
2234 | task watchStep4; | |
2235 | begin | |
2236 | ||
2237 | watchStepFlush[4] = 0; // set if we got a flush | |
2238 | watchStepMMU[4] = 0; // set if we got a mmu reload | |
2239 | stepDone[4] = 0; | |
2240 | stepActive[4] = 1; | |
2241 | ||
2242 | if (flushCount4) `PR_DEBUG("dbg_chk", `DEBUG, "watchStep4: TID 4 repeating watchStep task due to flush (flushCount=%0d, redirectCount=%0d)!",flushCount4,redirectCount4); | |
2243 | ||
2244 | ||
2245 | fork | |
2246 | // timeout fork | |
2247 | begin : FORK10_4 | |
2248 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
2249 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep4: TID 4 did not see valid PC retry (waitTime=%0d)!", stepWaitTime); | |
2250 | end | |
2251 | ||
2252 | // // look for SPU going active | |
2253 | // begin : FORK11_4 | |
2254 | // while (!(`SPC5.spu_tlu_cwq_busy || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 4))) | |
2255 | // @(negedge `SPC5.l2clk); | |
2256 | // `PR_DEBUG("dbg_chk", `DEBUG, "watchStep4: TID 4 see SPU active!"); | |
2257 | // spuActive[4] = 1; | |
2258 | // end | |
2259 | ||
2260 | // might get ss_complete due to not knowing if there are 1 or 2 or more flushes. | |
2261 | // this task gets called w/o knowing in advance if there will be one more | |
2262 | // assertion of tlu_trap_pc_0/1_valid or not. | |
2263 | begin : FORK8_4 | |
2264 | if (ssMode) begin | |
2265 | @(posedge `SPC5.spc_ss_complete); | |
2266 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep4: TID 4 see spc_ss_complete, step done, bailing (flushCount=%0d/redirectCount=%0d)!", flushCount4, redirectCount4); | |
2267 | stepDone[4] = 1; | |
2268 | stepActive[4] = 0; | |
2269 | disable watchStep4; // return | |
2270 | end | |
2271 | end | |
2272 | ||
2273 | // valid PC / retry | |
2274 | begin : FORK9_4 | |
2275 | // start step. tid wakes up/redirects and does "one instruction" | |
2276 | while (!(`SPC5.tlu_trap_pc_1_valid && `SPC5.tlu_trap_1_tid[1:0] == 0 && `SPC5.tlu.tlu_retry[1] == 1)) begin | |
2277 | // might see `SPC5.tlu.mmu_reload_done[4] here if previous | |
2278 | // redirect was due to a MMU miss. If so, decrement flush count because | |
2279 | // the previous flush on prev pc_valid "does not count" and there can be | |
2280 | // any number of them w/ no way to predict quantity. | |
2281 | if (`SPC5.tlu.mmu_reload_done[4] && ssMode) begin | |
2282 | flushCount4 = flushCount4-1; | |
2283 | redirectCount4 = redirectCount4-1; | |
2284 | watchStepMMU[4] = 1; | |
2285 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep4: TID 4 saw mmu_reload_done (hwtw)! flushCount/redirectCount decremented to %0d/%0d", flushCount4, redirectCount4); | |
2286 | end | |
2287 | @(negedge `SPC5.l2clk); | |
2288 | end | |
2289 | ||
2290 | redirectCount4 = redirectCount4+1; | |
2291 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep4: TID 4 got valid retry, step waiting on negedge pku_quiesce (redirectCount=%0d)!",redirectCount4); | |
2292 | disable FORK8_4; // kill sync on spc_ss_complete | |
2293 | ||
2294 | @(negedge `SPC5.pku_quiesce[4]); | |
2295 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep4: TID 4 got negedge pku_quiesce, step waiting on dec_inst_valid_m!"); | |
2296 | ||
2297 | while (!(`SPC5.dec_inst_valid_m[1] == 1 && `SPC5.dec_tid1_m[1:0] == 0)) @(negedge `SPC5.l2clk); | |
2298 | ||
2299 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep4: TID 4 valid step starting!"); | |
2300 | disable FORK10_4; // kill timeout | |
2301 | //disable FORK11_4; | |
2302 | // if (!`SPC5.spu_tlu_cwq_busy && | |
2303 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
2304 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 4)) spuActive[4] = 0; | |
2305 | end | |
2306 | join | |
2307 | ||
2308 | ||
2309 | ||
2310 | // finish step | |
2311 | fork | |
2312 | // timeout fork | |
2313 | begin : FORK4_4 | |
2314 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
2315 | ||
2316 | // may need to adjust. If a tid is doing a SPU sync ctl reg sync read, | |
2317 | // it could stay "busy" for a REAL long time!!! Need delayed check of busy | |
2318 | // since it can assert after the step has started. | |
2319 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep4: TID 4 did not quiesce/complete after step (SS or DO) as it should have. not SPU busy (waitTime=%0d)!", stepWaitTime); | |
2320 | end | |
2321 | ||
2322 | // look for SPU going active | |
2323 | // begin : FORK12_4 | |
2324 | // while (!(`SPC5.spu_tlu_cwq_busy || | |
2325 | // ((`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 4 && doMode) || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && ssMode)))) | |
2326 | // @(negedge `SPC5.l2clk); | |
2327 | // spuActive[4] = 1; | |
2328 | // end | |
2329 | ||
2330 | ||
2331 | // look for flush_ifu (w/o lsu_trap_flush (aka ptrap_flush) if SS) | |
2332 | // and end this task if seen. tlu_flush_ifu assertion always means | |
2333 | // this "instruction" is done, but may repeat (tlb miss, etc) w/in the SS. | |
2334 | begin : FORK6_4 | |
2335 | // checking ptrap_flush to make sure that flush is not caused by lsu_trap_flush | |
2336 | while (`SPC5.tlu_flush_ifu[4] == 0) | |
2337 | @(negedge `SPC5.l2clk); | |
2338 | ||
2339 | // // debug!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
2340 | // if (`SPC5.tlu.fls1.ptrap_flush[0] == 1) begin | |
2341 | // `PR_ERROR ("dbg_chk", `ERROR, "watchStep4: TID 4 have tlu_flush_ifu !!!!!!!!!!!!!!!!!!!!!!!"); | |
2342 | // end | |
2343 | // | |
2344 | ||
2345 | if ((ssMode && `SPC5.tlu.fls1.ptrap_flush[0] == 0) || doMode) begin | |
2346 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep4: TID 4 have tlu_flush_ifu (flushCount=%0d)!",flushCount4); | |
2347 | watchStepFlush[4] = 1; | |
2348 | flushCount4 = flushCount4+1; | |
2349 | stepActive[4] = 0; | |
2350 | disable watchStep4; // return | |
2351 | end | |
2352 | end | |
2353 | ||
2354 | ||
2355 | // are we done fork, DO mode quiesce | |
2356 | begin : FORK5_4 | |
2357 | if (doMode) begin | |
2358 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep4: TID 4 watching for quiesce (only matters fo DO mode)!"); | |
2359 | while (`SPC5.pku_quiesce[4] == 0 || | |
2360 | `SPC5.ftu_ifu_quiesce[4] == 0 || | |
2361 | `SPC5.lsu_stb_empty[4] == 0) @(negedge `SPC5.l2clk); | |
2362 | ||
2363 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep4: TID 4 have quiesce (only matters for DO mode)!"); | |
2364 | if (doMode) begin | |
2365 | disable FORK4_4; // TO | |
2366 | disable FORK6_4; // flush check | |
2367 | //disable FORK12_4; | |
2368 | // @(negedge `SPC5.l2clk); | |
2369 | // if (!`SPC5.spu_tlu_cwq_busy && | |
2370 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
2371 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 4)) spuActive[4] = 0; | |
2372 | end | |
2373 | end | |
2374 | end | |
2375 | ||
2376 | ||
2377 | // are we done fork, SS mode only | |
2378 | begin : FORK7_4 | |
2379 | // wait for SS complete | |
2380 | if (ssMode) begin | |
2381 | @(posedge `SPC5.spc_ss_complete); | |
2382 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep4: TID 4 see spc_ss_complete, step done, bailing (flushCount=%0d/redirectCount=%0d)!", flushCount4,redirectCount4); | |
2383 | stepDone[4] = 1; | |
2384 | ||
2385 | // while (ssMode && !`SPC5.spc_ss_complete) begin | |
2386 | // // detect a second inst valid w/o a flush between | |
2387 | // if (`SPC5.tlu_trap_pc_1_valid && `SPC5.tlu_trap_1_tid[1:0] == 0 && `SPC5.tlu.tlu_retry[1] == 1) begin | |
2388 | // // delay error so flush thread can kill this in the "got flush" case | |
2389 | // @(negedge `SPC5.l2clk); | |
2390 | // `PR_ERROR ("dbg_chk", `ERROR, "watchStep4: TID 4 had another inst start before SS done was asserted!"); | |
2391 | // end | |
2392 | // @(negedge `SPC5.l2clk); | |
2393 | // end // while | |
2394 | ||
2395 | if (`SPC5.pku_quiesce[4] == 0 || | |
2396 | `SPC5.ftu_ifu_quiesce[4] == 0 || | |
2397 | `SPC5.lsu_stb_empty[4] == 0) | |
2398 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep4: TID 4 was not quiesce at ss_complete assertion!"); | |
2399 | ||
2400 | disable FORK4_4; // TO | |
2401 | disable FORK6_4; // flush check | |
2402 | //disable FORK12_4; | |
2403 | // @(negedge `SPC5.l2clk); | |
2404 | // if (!`SPC5.spu_tlu_cwq_busy && | |
2405 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
2406 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 4)) spuActive[4] = 0; | |
2407 | end | |
2408 | end | |
2409 | ||
2410 | join | |
2411 | ||
2412 | ||
2413 | if (flushCount4 == 0) `PR_DEBUG("dbg_chk", `DEBUG, "watchStep4: TID 4 watchStep end!"); | |
2414 | else `PR_DEBUG("dbg_chk", `DEBUG, "watchStep4: TID 4 repeated watchStep end!"); | |
2415 | ||
2416 | stepActive[4] = 0; | |
2417 | ||
2418 | end | |
2419 | endtask | |
2420 | ||
2421 | ||
2422 | ||
2423 | // check that thread does DO mode correctly | |
2424 | task watchDOsteps4; | |
2425 | begin | |
2426 | ||
2427 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps4: TID 4 watchDOsteps starting!"); | |
2428 | ||
2429 | if (! `TOP.cpu.tcu_do_mode[5]) disable watchDOsteps4; | |
2430 | ||
2431 | // now wait for a thread to start. TCU internal signal. | |
2432 | if (`SPC5.tlu.tlu_core_running_status[4] == 0) | |
2433 | @(posedge `SPC5.tlu.tlu_core_running_status[4]); | |
2434 | ||
2435 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps4 TID 4 unparked and running in DO mode!"); | |
2436 | ||
2437 | // loop on step checking. DO mode is self stepping | |
2438 | while (doMode) begin : watchDOsteps4loop// && `SPC5.tlu.tlu_core_running_status[7:0] != 0) begin | |
2439 | ||
2440 | stepDone[4] = 0; | |
2441 | watchStepFlush[4] = 0; | |
2442 | watchStepMMU[4] = 0; | |
2443 | ||
2444 | // are we starting to park in middle of DO mode (or end)? | |
2445 | // wait here until unparked again | |
2446 | if (parkTrans[4]) begin | |
2447 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps4 TID 4 getting parked, will delay"); | |
2448 | @(negedge parkTrans[4]); | |
2449 | if (!doMode) disable watchDOsteps4loop; // no longer in DO mode, bail | |
2450 | // wait to be unparked or !doMode | |
2451 | if (parkedState[4]) begin | |
2452 | @(negedge doMode or negedge parkedState[4]); | |
2453 | if (!doMode) disable watchDOsteps4loop; // no longer in DO mode, bail | |
2454 | end | |
2455 | end | |
2456 | ||
2457 | ||
2458 | // an unparked thread does one instruction to completion before thread starts | |
2459 | // the next instruction. | |
2460 | fork | |
2461 | // timeout fork | |
2462 | begin : FORKDO14 | |
2463 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
2464 | `PR_ERROR ("dbg_chk", `ERROR, "watchDOsteps4: DO mode, TID 4 timeout waiting for watchStep call to return, not SPU busy (+stepWaitTime=%0d)!", stepWaitTime); | |
2465 | end | |
2466 | ||
2467 | // look for SPU going active | |
2468 | // begin : FORKDO24 | |
2469 | // while (!(`SPC5.spu_tlu_cwq_busy || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 4))) | |
2470 | // @(negedge `SPC5.l2clk); | |
2471 | // `PR_ALWAYS("dbg_chk", `ALWAYS, "watchDOsteps4: DO mode, TID 4 sees SPU busy!"); | |
2472 | // spuActive[4] = 1; | |
2473 | // end | |
2474 | ||
2475 | // watch step | |
2476 | begin | |
2477 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps4: TID 4 calling watchStep4 in DO mode!"); | |
2478 | watchStep4; // returns when step is done or flushed | |
2479 | if (watchStepFlush[4]) | |
2480 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 4 in DO mode had flush!"); | |
2481 | if (watchStepMMU[4]) | |
2482 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 4 in DO mode had mmu reload!"); | |
2483 | // calling flush as a done in DO mode | |
2484 | disable FORKDO14; // TO | |
2485 | //disable FORKDO24; // SPU going active | |
2486 | end | |
2487 | ||
2488 | join | |
2489 | ||
2490 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps4: TID 4 DO mode watchDOsteps step done!"); | |
2491 | stepDone[4] = 1; | |
2492 | flushCount4 = 0; | |
2493 | // if (!`SPC5.spu_tlu_cwq_busy && | |
2494 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
2495 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 4)) spuActive[4] = 0; | |
2496 | ||
2497 | @(negedge `SPC5.l2clk); | |
2498 | end // while | |
2499 | ||
2500 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps4: TID 4 DO mode watchDOsteps task ending!"); | |
2501 | end | |
2502 | endtask | |
2503 | ||
2504 | ||
2505 | ||
2506 | ||
2507 | ////////////////////////// end tid 4 /////////////////////////////////////// | |
2508 | ||
2509 | ||
2510 | ////////////////////////////////////////////////////////////////// | |
2511 | // THREAD 5 | |
2512 | ////////////////////////////////////////////////////////////////// | |
2513 | ||
2514 | ||
2515 | // got park request. transition into parking. parking check. | |
2516 | always @(negedge `SPC5.tlu.tcu_core_running[5]) begin: GOTPARK5 | |
2517 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 5 calling parkingCheck"); | |
2518 | if (enabled) parkingCheck5(); | |
2519 | end | |
2520 | ||
2521 | // got unpark request. transition into running. unparking check. | |
2522 | always @(posedge `SPC5.tlu.tcu_core_running[5]) begin: UNPARKCHECK5 | |
2523 | if (enabled && !ssMode) begin | |
2524 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 5 calling unparkCheck."); | |
2525 | unparkCheck5(); | |
2526 | end | |
2527 | end | |
2528 | ||
2529 | // while parked check | |
2530 | always @(posedge parkedState[5] or posedge virtualPark[5]) begin: PARKCHECK5 | |
2531 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 5 calling parkedCheck"); | |
2532 | if (enabled) parkedCheck5(); | |
2533 | end | |
2534 | ||
2535 | // check for unexpected running transition | |
2536 | always @(`SPC5.tlu.tlu_core_running_status[5]) begin: UNEXPECTED5 | |
2537 | if (!parkTrans[5] && enabled && ! doMode && ! ssMode) // review? to remove ! doMode | |
2538 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 5 spc_core_running_status changed w/o request to park/unpark (trans=%0d)!",parkTrans[5]); | |
2539 | end | |
2540 | ||
2541 | ||
2542 | ||
2543 | ////////////// tasks for tid 5 //////////////////// | |
2544 | ||
2545 | // check the entering into parked state | |
2546 | task parkingCheck5; | |
2547 | ||
2548 | begin | |
2549 | ||
2550 | ||
2551 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 5 got park request!"); | |
2552 | ||
2553 | if (parkTrans[5] == 1) begin | |
2554 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 5 got park request while park state is already transitioning! Possible diag conflict (multiple parkers)! (enabled=%0d)",enabled); | |
2555 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +noDebugChecks to disable all debug checkes!"); | |
2556 | disable parkingCheck5; | |
2557 | end | |
2558 | ||
2559 | parkTrans[5] = 1; | |
2560 | ||
2561 | // wait before checking signals | |
2562 | repeat (2) @(negedge `SPC5.l2clk); | |
2563 | ||
2564 | // need to see at least one assertion of flush | |
2565 | // if (`SPC5.tlu_flush_ifu[5] !== 1) | |
2566 | // @(posedge `SPC5.tlu_flush_ifu[5]); // has glitches | |
2567 | if (`SPC5.ifu_ftu.ftu_agc_ctl.tlu_flush_ifu_f[5] !== 1) | |
2568 | @(posedge `SPC5.ifu_ftu.ftu_agc_ctl.tlu_flush_ifu_f[5]); | |
2569 | ||
2570 | // need to see all of these go idle | |
2571 | while (`SPC5.pku_quiesce[5] == 0 || | |
2572 | `SPC5.ftu_ifu_quiesce[5] == 0 || | |
2573 | `SPC5.lsu_stb_empty[5] == 0) | |
2574 | @(negedge `SPC5.l2clk); | |
2575 | ||
2576 | // // need to see all of these go idle | |
2577 | // while (`SPC5.pku_quiesce[5] == 0 || | |
2578 | // `SPC5.ftu_ifu_quiesce[5] == 0 || | |
2579 | // `SPC5.lsu_stb_empty[5] == 0 || | |
2580 | // `SPC5.tlu.fls1.idl_request == 0) | |
2581 | // @(negedge `SPC5.l2clk); | |
2582 | ||
2583 | parkedState[5] <= 1; | |
2584 | parkTrans[5] <= 0; | |
2585 | // `PR_ALWAYS("dbg_chk", `ALWAYS, "INFO: TID %0d has parked!", 5); | |
2586 | `PR_DEBUG("dbg_chk", `DEBUG, "INFO: TID 5 has parked!"); | |
2587 | ||
2588 | end | |
2589 | endtask | |
2590 | ||
2591 | ||
2592 | // in parked state. | |
2593 | // also called between single steps. | |
2594 | task parkedCheck5; | |
2595 | reg notified; | |
2596 | begin //{ | |
2597 | ||
2598 | notified = 0; | |
2599 | // loop while not transitioning out of park if not SS mode. | |
2600 | // loop while in SS virtualPark if SS mode. | |
2601 | while ((parkTrans[5] == 0 && ssMode == 0) || | |
2602 | (virtualPark[5] == 1 && ssMode == 1 && | |
2603 | `TOP.cpu.tcu_ss_request[5] == 0)) begin //{ | |
2604 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 5 watching for activity while parked/between steps. trans=%0h, virtualPark=%0h, tcu_ss_request=%0h",parkTrans[5],virtualPark[5],`TOP.cpu.tcu_ss_request[5]); | |
2605 | ||
2606 | @(negedge `SPC5.l2clk); | |
2607 | ||
2608 | // if in SS mode and core_running goes to zero for that thread, the thread | |
2609 | // will self step once and flush in order to change to a parked state | |
2610 | // (core_running_status=0). This looks like an un-asked for step so it | |
2611 | // has to be detected and ignored. Try stalling here during it. | |
2612 | while (`SPC5.tlu.tcu_core_running[5] == 0 && | |
2613 | `SPC5.tlu.tlu_core_running_status[5] == 1) | |
2614 | @(negedge `SPC5.l2clk); | |
2615 | ||
2616 | // watch for instructions sneaking in | |
2617 | // dec_inst_valid_m[1:0], one bit per group | |
2618 | if (`SPC5.tlu_trap_pc_1_valid && `SPC5.tlu_trap_1_tid[1:0] == 5 && `SPC5.tlu.tlu_retry[1] == 1) | |
2619 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 5 had tlu_trap_pc_1_valid activity while parked/between steps!"); | |
2620 | ||
2621 | if (`SPC5.dec_inst_valid_m[1] == 1 && `SPC5.dec_tid1_m[1:0] == 1) | |
2622 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 5 had dec_inst_valid_m activity while parked/between steps!"); | |
2623 | ||
2624 | ||
2625 | end //} while | |
2626 | ||
2627 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 5 STOP watching for activity while parked/between steps. trans=%0h, virtualPark=%0h, tcu_ss_request=%0h",parkTrans[5],virtualPark[5],`TOP.cpu.tcu_ss_request[5]); | |
2628 | ||
2629 | end //} | |
2630 | endtask | |
2631 | ||
2632 | ||
2633 | // leaving parked state | |
2634 | task unparkCheck5; | |
2635 | integer count; | |
2636 | begin | |
2637 | ||
2638 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 5 got unpark request!"); | |
2639 | ||
2640 | if (parkTrans[5] == 1) begin | |
2641 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 5 got unpark request while park state is already transitioning! Possible diag conflict! (trans=%0h)",parkTrans); | |
2642 | disable unparkCheck5; | |
2643 | end | |
2644 | ||
2645 | parkTrans[5] = 1; | |
2646 | ||
2647 | // must see `SPC5.tlu.core_running_status[5] w/in count clocks | |
2648 | count5 = 0; | |
2649 | ||
2650 | while (`SPC5.tlu.tlu_core_running_status[5] == 0) begin | |
2651 | @(negedge `SPC5.l2clk); | |
2652 | if (count5 > parkWait) begin // <--- may need to adjust | |
2653 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 5 did not assert spc_core_running_status as soon as it should have (%0d clocks)!", count5); | |
2654 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +parkWait=n (currently %0d). +noDebugChecks disables all checks!",parkWait); | |
2655 | end | |
2656 | count5 = count5 + 1; | |
2657 | end | |
2658 | ||
2659 | if (!doMode && !ssMode) begin | |
2660 | // need to see re-direct w/in "redirectWait" more clocks | |
2661 | count5 = 0; | |
2662 | ||
2663 | // if this is true, the redirect and the assertion of core_running_status | |
2664 | // happened at once so while loop can be skipped. | |
2665 | while (! (`SPC5.tlu_trap_pc_1_valid && | |
2666 | `SPC5.tlu_trap_1_tid[1:0] == 1)) begin | |
2667 | @(negedge `SPC5.l2clk); | |
2668 | if (count5 > redirectWait) begin // <--- may need to adjust | |
2669 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 5 did not redirect within %d clocks after core_running_status assert!", redirectWait); | |
2670 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +redirectWait=n (currently %0d). +noDebugChecks disables all checks!",redirectWait); | |
2671 | end | |
2672 | count5 = count5 + 1; | |
2673 | end | |
2674 | end | |
2675 | ||
2676 | parkedState[5] <= 0; | |
2677 | parkTrans[5] <= 0; | |
2678 | count5 <= 0; | |
2679 | ||
2680 | end | |
2681 | endtask | |
2682 | ||
2683 | ||
2684 | // watch this tid step correctly. Should step 1 instruction | |
2685 | // and then "virtual park". | |
2686 | // for SS and DO modes. | |
2687 | task watchStep5; | |
2688 | begin | |
2689 | ||
2690 | watchStepFlush[5] = 0; // set if we got a flush | |
2691 | watchStepMMU[5] = 0; // set if we got a mmu reload | |
2692 | stepDone[5] = 0; | |
2693 | stepActive[5] = 1; | |
2694 | ||
2695 | if (flushCount5) `PR_DEBUG("dbg_chk", `DEBUG, "watchStep5: TID 5 repeating watchStep task due to flush (flushCount=%0d, redirectCount=%0d)!",flushCount5,redirectCount5); | |
2696 | ||
2697 | ||
2698 | fork | |
2699 | // timeout fork | |
2700 | begin : FORK10_5 | |
2701 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
2702 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep5: TID 5 did not see valid PC retry (waitTime=%0d)!", stepWaitTime); | |
2703 | end | |
2704 | ||
2705 | // // look for SPU going active | |
2706 | // begin : FORK11_5 | |
2707 | // while (!(`SPC5.spu_tlu_cwq_busy || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 5))) | |
2708 | // @(negedge `SPC5.l2clk); | |
2709 | // `PR_DEBUG("dbg_chk", `DEBUG, "watchStep5: TID 5 see SPU active!"); | |
2710 | // spuActive[5] = 1; | |
2711 | // end | |
2712 | ||
2713 | // might get ss_complete due to not knowing if there are 1 or 2 or more flushes. | |
2714 | // this task gets called w/o knowing in advance if there will be one more | |
2715 | // assertion of tlu_trap_pc_0/1_valid or not. | |
2716 | begin : FORK8_5 | |
2717 | if (ssMode) begin | |
2718 | @(posedge `SPC5.spc_ss_complete); | |
2719 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep5: TID 5 see spc_ss_complete, step done, bailing (flushCount=%0d/redirectCount=%0d)!", flushCount5, redirectCount5); | |
2720 | stepDone[5] = 1; | |
2721 | stepActive[5] = 0; | |
2722 | disable watchStep5; // return | |
2723 | end | |
2724 | end | |
2725 | ||
2726 | // valid PC / retry | |
2727 | begin : FORK9_5 | |
2728 | // start step. tid wakes up/redirects and does "one instruction" | |
2729 | while (!(`SPC5.tlu_trap_pc_1_valid && `SPC5.tlu_trap_1_tid[1:0] == 1 && `SPC5.tlu.tlu_retry[1] == 1)) begin | |
2730 | // might see `SPC5.tlu.mmu_reload_done[5] here if previous | |
2731 | // redirect was due to a MMU miss. If so, decrement flush count because | |
2732 | // the previous flush on prev pc_valid "does not count" and there can be | |
2733 | // any number of them w/ no way to predict quantity. | |
2734 | if (`SPC5.tlu.mmu_reload_done[5] && ssMode) begin | |
2735 | flushCount5 = flushCount5-1; | |
2736 | redirectCount5 = redirectCount5-1; | |
2737 | watchStepMMU[5] = 1; | |
2738 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep5: TID 5 saw mmu_reload_done (hwtw)! flushCount/redirectCount decremented to %0d/%0d", flushCount5, redirectCount5); | |
2739 | end | |
2740 | @(negedge `SPC5.l2clk); | |
2741 | end | |
2742 | ||
2743 | redirectCount5 = redirectCount5+1; | |
2744 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep5: TID 5 got valid retry, step waiting on negedge pku_quiesce (redirectCount=%0d)!",redirectCount5); | |
2745 | disable FORK8_5; // kill sync on spc_ss_complete | |
2746 | ||
2747 | @(negedge `SPC5.pku_quiesce[5]); | |
2748 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep5: TID 5 got negedge pku_quiesce, step waiting on dec_inst_valid_m!"); | |
2749 | ||
2750 | while (!(`SPC5.dec_inst_valid_m[1] == 1 && `SPC5.dec_tid1_m[1:0] == 1)) @(negedge `SPC5.l2clk); | |
2751 | ||
2752 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep5: TID 5 valid step starting!"); | |
2753 | disable FORK10_5; // kill timeout | |
2754 | //disable FORK11_5; | |
2755 | // if (!`SPC5.spu_tlu_cwq_busy && | |
2756 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
2757 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 5)) spuActive[5] = 0; | |
2758 | end | |
2759 | join | |
2760 | ||
2761 | ||
2762 | ||
2763 | // finish step | |
2764 | fork | |
2765 | // timeout fork | |
2766 | begin : FORK4_5 | |
2767 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
2768 | ||
2769 | // may need to adjust. If a tid is doing a SPU sync ctl reg sync read, | |
2770 | // it could stay "busy" for a REAL long time!!! Need delayed check of busy | |
2771 | // since it can assert after the step has started. | |
2772 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep5: TID 5 did not quiesce/complete after step (SS or DO) as it should have. not SPU busy (waitTime=%0d)!", stepWaitTime); | |
2773 | end | |
2774 | ||
2775 | // look for SPU going active | |
2776 | // begin : FORK12_5 | |
2777 | // while (!(`SPC5.spu_tlu_cwq_busy || | |
2778 | // ((`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 5 && doMode) || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && ssMode)))) | |
2779 | // @(negedge `SPC5.l2clk); | |
2780 | // spuActive[5] = 1; | |
2781 | // end | |
2782 | ||
2783 | ||
2784 | // look for flush_ifu (w/o lsu_trap_flush (aka ptrap_flush) if SS) | |
2785 | // and end this task if seen. tlu_flush_ifu assertion always means | |
2786 | // this "instruction" is done, but may repeat (tlb miss, etc) w/in the SS. | |
2787 | begin : FORK6_5 | |
2788 | // checking ptrap_flush to make sure that flush is not caused by lsu_trap_flush | |
2789 | while (`SPC5.tlu_flush_ifu[5] == 0) | |
2790 | @(negedge `SPC5.l2clk); | |
2791 | ||
2792 | // // debug!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
2793 | // if (`SPC5.tlu.fls1.ptrap_flush[1] == 1) begin | |
2794 | // `PR_ERROR ("dbg_chk", `ERROR, "watchStep5: TID 5 have tlu_flush_ifu !!!!!!!!!!!!!!!!!!!!!!!"); | |
2795 | // end | |
2796 | // | |
2797 | ||
2798 | if ((ssMode && `SPC5.tlu.fls1.ptrap_flush[1] == 0) || doMode) begin | |
2799 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep5: TID 5 have tlu_flush_ifu (flushCount=%0d)!",flushCount5); | |
2800 | watchStepFlush[5] = 1; | |
2801 | flushCount5 = flushCount5+1; | |
2802 | stepActive[5] = 0; | |
2803 | disable watchStep5; // return | |
2804 | end | |
2805 | end | |
2806 | ||
2807 | ||
2808 | // are we done fork, DO mode quiesce | |
2809 | begin : FORK5_5 | |
2810 | if (doMode) begin | |
2811 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep5: TID 5 watching for quiesce (only matters fo DO mode)!"); | |
2812 | while (`SPC5.pku_quiesce[5] == 0 || | |
2813 | `SPC5.ftu_ifu_quiesce[5] == 0 || | |
2814 | `SPC5.lsu_stb_empty[5] == 0) @(negedge `SPC5.l2clk); | |
2815 | ||
2816 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep5: TID 5 have quiesce (only matters for DO mode)!"); | |
2817 | if (doMode) begin | |
2818 | disable FORK4_5; // TO | |
2819 | disable FORK6_5; // flush check | |
2820 | //disable FORK12_5; | |
2821 | // @(negedge `SPC5.l2clk); | |
2822 | // if (!`SPC5.spu_tlu_cwq_busy && | |
2823 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
2824 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 5)) spuActive[5] = 0; | |
2825 | end | |
2826 | end | |
2827 | end | |
2828 | ||
2829 | ||
2830 | // are we done fork, SS mode only | |
2831 | begin : FORK7_5 | |
2832 | // wait for SS complete | |
2833 | if (ssMode) begin | |
2834 | @(posedge `SPC5.spc_ss_complete); | |
2835 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep5: TID 5 see spc_ss_complete, step done, bailing (flushCount=%0d/redirectCount=%0d)!", flushCount5,redirectCount5); | |
2836 | stepDone[5] = 1; | |
2837 | ||
2838 | // while (ssMode && !`SPC5.spc_ss_complete) begin | |
2839 | // // detect a second inst valid w/o a flush between | |
2840 | // if (`SPC5.tlu_trap_pc_1_valid && `SPC5.tlu_trap_1_tid[1:0] == 1 && `SPC5.tlu.tlu_retry[1] == 1) begin | |
2841 | // // delay error so flush thread can kill this in the "got flush" case | |
2842 | // @(negedge `SPC5.l2clk); | |
2843 | // `PR_ERROR ("dbg_chk", `ERROR, "watchStep5: TID 5 had another inst start before SS done was asserted!"); | |
2844 | // end | |
2845 | // @(negedge `SPC5.l2clk); | |
2846 | // end // while | |
2847 | ||
2848 | if (`SPC5.pku_quiesce[5] == 0 || | |
2849 | `SPC5.ftu_ifu_quiesce[5] == 0 || | |
2850 | `SPC5.lsu_stb_empty[5] == 0) | |
2851 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep5: TID 5 was not quiesce at ss_complete assertion!"); | |
2852 | ||
2853 | disable FORK4_5; // TO | |
2854 | disable FORK6_5; // flush check | |
2855 | //disable FORK12_5; | |
2856 | // @(negedge `SPC5.l2clk); | |
2857 | // if (!`SPC5.spu_tlu_cwq_busy && | |
2858 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
2859 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 5)) spuActive[5] = 0; | |
2860 | end | |
2861 | end | |
2862 | ||
2863 | join | |
2864 | ||
2865 | ||
2866 | if (flushCount5 == 0) `PR_DEBUG("dbg_chk", `DEBUG, "watchStep5: TID 5 watchStep end!"); | |
2867 | else `PR_DEBUG("dbg_chk", `DEBUG, "watchStep5: TID 5 repeated watchStep end!"); | |
2868 | ||
2869 | stepActive[5] = 0; | |
2870 | ||
2871 | end | |
2872 | endtask | |
2873 | ||
2874 | ||
2875 | ||
2876 | // check that thread does DO mode correctly | |
2877 | task watchDOsteps5; | |
2878 | begin | |
2879 | ||
2880 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps5: TID 5 watchDOsteps starting!"); | |
2881 | ||
2882 | if (! `TOP.cpu.tcu_do_mode[5]) disable watchDOsteps5; | |
2883 | ||
2884 | // now wait for a thread to start. TCU internal signal. | |
2885 | if (`SPC5.tlu.tlu_core_running_status[5] == 0) | |
2886 | @(posedge `SPC5.tlu.tlu_core_running_status[5]); | |
2887 | ||
2888 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps5 TID 5 unparked and running in DO mode!"); | |
2889 | ||
2890 | // loop on step checking. DO mode is self stepping | |
2891 | while (doMode) begin : watchDOsteps5loop// && `SPC5.tlu.tlu_core_running_status[7:0] != 0) begin | |
2892 | ||
2893 | stepDone[5] = 0; | |
2894 | watchStepFlush[5] = 0; | |
2895 | watchStepMMU[5] = 0; | |
2896 | ||
2897 | // are we starting to park in middle of DO mode (or end)? | |
2898 | // wait here until unparked again | |
2899 | if (parkTrans[5]) begin | |
2900 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps5 TID 5 getting parked, will delay"); | |
2901 | @(negedge parkTrans[5]); | |
2902 | if (!doMode) disable watchDOsteps5loop; // no longer in DO mode, bail | |
2903 | // wait to be unparked or !doMode | |
2904 | if (parkedState[5]) begin | |
2905 | @(negedge doMode or negedge parkedState[5]); | |
2906 | if (!doMode) disable watchDOsteps5loop; // no longer in DO mode, bail | |
2907 | end | |
2908 | end | |
2909 | ||
2910 | ||
2911 | // an unparked thread does one instruction to completion before thread starts | |
2912 | // the next instruction. | |
2913 | fork | |
2914 | // timeout fork | |
2915 | begin : FORKDO15 | |
2916 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
2917 | `PR_ERROR ("dbg_chk", `ERROR, "watchDOsteps5: DO mode, TID 5 timeout waiting for watchStep call to return, not SPU busy (+stepWaitTime=%0d)!", stepWaitTime); | |
2918 | end | |
2919 | ||
2920 | // look for SPU going active | |
2921 | // begin : FORKDO25 | |
2922 | // while (!(`SPC5.spu_tlu_cwq_busy || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 5))) | |
2923 | // @(negedge `SPC5.l2clk); | |
2924 | // `PR_ALWAYS("dbg_chk", `ALWAYS, "watchDOsteps5: DO mode, TID 5 sees SPU busy!"); | |
2925 | // spuActive[5] = 1; | |
2926 | // end | |
2927 | ||
2928 | // watch step | |
2929 | begin | |
2930 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps5: TID 5 calling watchStep5 in DO mode!"); | |
2931 | watchStep5; // returns when step is done or flushed | |
2932 | if (watchStepFlush[5]) | |
2933 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 5 in DO mode had flush!"); | |
2934 | if (watchStepMMU[5]) | |
2935 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 5 in DO mode had mmu reload!"); | |
2936 | // calling flush as a done in DO mode | |
2937 | disable FORKDO15; // TO | |
2938 | //disable FORKDO25; // SPU going active | |
2939 | end | |
2940 | ||
2941 | join | |
2942 | ||
2943 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps5: TID 5 DO mode watchDOsteps step done!"); | |
2944 | stepDone[5] = 1; | |
2945 | flushCount5 = 0; | |
2946 | // if (!`SPC5.spu_tlu_cwq_busy && | |
2947 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
2948 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 5)) spuActive[5] = 0; | |
2949 | ||
2950 | @(negedge `SPC5.l2clk); | |
2951 | end // while | |
2952 | ||
2953 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps5: TID 5 DO mode watchDOsteps task ending!"); | |
2954 | end | |
2955 | endtask | |
2956 | ||
2957 | ||
2958 | ||
2959 | ||
2960 | ////////////////////////// end tid 5 /////////////////////////////////////// | |
2961 | ||
2962 | ||
2963 | ////////////////////////////////////////////////////////////////// | |
2964 | // THREAD 6 | |
2965 | ////////////////////////////////////////////////////////////////// | |
2966 | ||
2967 | ||
2968 | // got park request. transition into parking. parking check. | |
2969 | always @(negedge `SPC5.tlu.tcu_core_running[6]) begin: GOTPARK6 | |
2970 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 6 calling parkingCheck"); | |
2971 | if (enabled) parkingCheck6(); | |
2972 | end | |
2973 | ||
2974 | // got unpark request. transition into running. unparking check. | |
2975 | always @(posedge `SPC5.tlu.tcu_core_running[6]) begin: UNPARKCHECK6 | |
2976 | if (enabled && !ssMode) begin | |
2977 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 6 calling unparkCheck."); | |
2978 | unparkCheck6(); | |
2979 | end | |
2980 | end | |
2981 | ||
2982 | // while parked check | |
2983 | always @(posedge parkedState[6] or posedge virtualPark[6]) begin: PARKCHECK6 | |
2984 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 6 calling parkedCheck"); | |
2985 | if (enabled) parkedCheck6(); | |
2986 | end | |
2987 | ||
2988 | // check for unexpected running transition | |
2989 | always @(`SPC5.tlu.tlu_core_running_status[6]) begin: UNEXPECTED6 | |
2990 | if (!parkTrans[6] && enabled && ! doMode && ! ssMode) // review? to remove ! doMode | |
2991 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 6 spc_core_running_status changed w/o request to park/unpark (trans=%0d)!",parkTrans[6]); | |
2992 | end | |
2993 | ||
2994 | ||
2995 | ||
2996 | ////////////// tasks for tid 6 //////////////////// | |
2997 | ||
2998 | // check the entering into parked state | |
2999 | task parkingCheck6; | |
3000 | ||
3001 | begin | |
3002 | ||
3003 | ||
3004 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 6 got park request!"); | |
3005 | ||
3006 | if (parkTrans[6] == 1) begin | |
3007 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 6 got park request while park state is already transitioning! Possible diag conflict (multiple parkers)! (enabled=%0d)",enabled); | |
3008 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +noDebugChecks to disable all debug checkes!"); | |
3009 | disable parkingCheck6; | |
3010 | end | |
3011 | ||
3012 | parkTrans[6] = 1; | |
3013 | ||
3014 | // wait before checking signals | |
3015 | repeat (2) @(negedge `SPC5.l2clk); | |
3016 | ||
3017 | // need to see at least one assertion of flush | |
3018 | // if (`SPC5.tlu_flush_ifu[6] !== 1) | |
3019 | // @(posedge `SPC5.tlu_flush_ifu[6]); // has glitches | |
3020 | if (`SPC5.ifu_ftu.ftu_agc_ctl.tlu_flush_ifu_f[6] !== 1) | |
3021 | @(posedge `SPC5.ifu_ftu.ftu_agc_ctl.tlu_flush_ifu_f[6]); | |
3022 | ||
3023 | // need to see all of these go idle | |
3024 | while (`SPC5.pku_quiesce[6] == 0 || | |
3025 | `SPC5.ftu_ifu_quiesce[6] == 0 || | |
3026 | `SPC5.lsu_stb_empty[6] == 0) | |
3027 | @(negedge `SPC5.l2clk); | |
3028 | ||
3029 | // // need to see all of these go idle | |
3030 | // while (`SPC5.pku_quiesce[6] == 0 || | |
3031 | // `SPC5.ftu_ifu_quiesce[6] == 0 || | |
3032 | // `SPC5.lsu_stb_empty[6] == 0 || | |
3033 | // `SPC5.tlu.fls1.idl_request == 0) | |
3034 | // @(negedge `SPC5.l2clk); | |
3035 | ||
3036 | parkedState[6] <= 1; | |
3037 | parkTrans[6] <= 0; | |
3038 | // `PR_ALWAYS("dbg_chk", `ALWAYS, "INFO: TID %0d has parked!", 6); | |
3039 | `PR_DEBUG("dbg_chk", `DEBUG, "INFO: TID 6 has parked!"); | |
3040 | ||
3041 | end | |
3042 | endtask | |
3043 | ||
3044 | ||
3045 | // in parked state. | |
3046 | // also called between single steps. | |
3047 | task parkedCheck6; | |
3048 | reg notified; | |
3049 | begin //{ | |
3050 | ||
3051 | notified = 0; | |
3052 | // loop while not transitioning out of park if not SS mode. | |
3053 | // loop while in SS virtualPark if SS mode. | |
3054 | while ((parkTrans[6] == 0 && ssMode == 0) || | |
3055 | (virtualPark[6] == 1 && ssMode == 1 && | |
3056 | `TOP.cpu.tcu_ss_request[5] == 0)) begin //{ | |
3057 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 6 watching for activity while parked/between steps. trans=%0h, virtualPark=%0h, tcu_ss_request=%0h",parkTrans[6],virtualPark[6],`TOP.cpu.tcu_ss_request[5]); | |
3058 | ||
3059 | @(negedge `SPC5.l2clk); | |
3060 | ||
3061 | // if in SS mode and core_running goes to zero for that thread, the thread | |
3062 | // will self step once and flush in order to change to a parked state | |
3063 | // (core_running_status=0). This looks like an un-asked for step so it | |
3064 | // has to be detected and ignored. Try stalling here during it. | |
3065 | while (`SPC5.tlu.tcu_core_running[6] == 0 && | |
3066 | `SPC5.tlu.tlu_core_running_status[6] == 1) | |
3067 | @(negedge `SPC5.l2clk); | |
3068 | ||
3069 | // watch for instructions sneaking in | |
3070 | // dec_inst_valid_m[1:0], one bit per group | |
3071 | if (`SPC5.tlu_trap_pc_1_valid && `SPC5.tlu_trap_1_tid[1:0] == 6 && `SPC5.tlu.tlu_retry[1] == 1) | |
3072 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 6 had tlu_trap_pc_1_valid activity while parked/between steps!"); | |
3073 | ||
3074 | if (`SPC5.dec_inst_valid_m[1] == 1 && `SPC5.dec_tid1_m[1:0] == 2) | |
3075 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 6 had dec_inst_valid_m activity while parked/between steps!"); | |
3076 | ||
3077 | ||
3078 | end //} while | |
3079 | ||
3080 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 6 STOP watching for activity while parked/between steps. trans=%0h, virtualPark=%0h, tcu_ss_request=%0h",parkTrans[6],virtualPark[6],`TOP.cpu.tcu_ss_request[5]); | |
3081 | ||
3082 | end //} | |
3083 | endtask | |
3084 | ||
3085 | ||
3086 | // leaving parked state | |
3087 | task unparkCheck6; | |
3088 | integer count; | |
3089 | begin | |
3090 | ||
3091 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 6 got unpark request!"); | |
3092 | ||
3093 | if (parkTrans[6] == 1) begin | |
3094 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 6 got unpark request while park state is already transitioning! Possible diag conflict! (trans=%0h)",parkTrans); | |
3095 | disable unparkCheck6; | |
3096 | end | |
3097 | ||
3098 | parkTrans[6] = 1; | |
3099 | ||
3100 | // must see `SPC5.tlu.core_running_status[6] w/in count clocks | |
3101 | count6 = 0; | |
3102 | ||
3103 | while (`SPC5.tlu.tlu_core_running_status[6] == 0) begin | |
3104 | @(negedge `SPC5.l2clk); | |
3105 | if (count6 > parkWait) begin // <--- may need to adjust | |
3106 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 6 did not assert spc_core_running_status as soon as it should have (%0d clocks)!", count6); | |
3107 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +parkWait=n (currently %0d). +noDebugChecks disables all checks!",parkWait); | |
3108 | end | |
3109 | count6 = count6 + 1; | |
3110 | end | |
3111 | ||
3112 | if (!doMode && !ssMode) begin | |
3113 | // need to see re-direct w/in "redirectWait" more clocks | |
3114 | count6 = 0; | |
3115 | ||
3116 | // if this is true, the redirect and the assertion of core_running_status | |
3117 | // happened at once so while loop can be skipped. | |
3118 | while (! (`SPC5.tlu_trap_pc_1_valid && | |
3119 | `SPC5.tlu_trap_1_tid[1:0] == 2)) begin | |
3120 | @(negedge `SPC5.l2clk); | |
3121 | if (count6 > redirectWait) begin // <--- may need to adjust | |
3122 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 6 did not redirect within %d clocks after core_running_status assert!", redirectWait); | |
3123 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +redirectWait=n (currently %0d). +noDebugChecks disables all checks!",redirectWait); | |
3124 | end | |
3125 | count6 = count6 + 1; | |
3126 | end | |
3127 | end | |
3128 | ||
3129 | parkedState[6] <= 0; | |
3130 | parkTrans[6] <= 0; | |
3131 | count6 <= 0; | |
3132 | ||
3133 | end | |
3134 | endtask | |
3135 | ||
3136 | ||
3137 | // watch this tid step correctly. Should step 1 instruction | |
3138 | // and then "virtual park". | |
3139 | // for SS and DO modes. | |
3140 | task watchStep6; | |
3141 | begin | |
3142 | ||
3143 | watchStepFlush[6] = 0; // set if we got a flush | |
3144 | watchStepMMU[6] = 0; // set if we got a mmu reload | |
3145 | stepDone[6] = 0; | |
3146 | stepActive[6] = 1; | |
3147 | ||
3148 | if (flushCount6) `PR_DEBUG("dbg_chk", `DEBUG, "watchStep6: TID 6 repeating watchStep task due to flush (flushCount=%0d, redirectCount=%0d)!",flushCount6,redirectCount6); | |
3149 | ||
3150 | ||
3151 | fork | |
3152 | // timeout fork | |
3153 | begin : FORK10_6 | |
3154 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
3155 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep6: TID 6 did not see valid PC retry (waitTime=%0d)!", stepWaitTime); | |
3156 | end | |
3157 | ||
3158 | // // look for SPU going active | |
3159 | // begin : FORK11_6 | |
3160 | // while (!(`SPC5.spu_tlu_cwq_busy || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 6))) | |
3161 | // @(negedge `SPC5.l2clk); | |
3162 | // `PR_DEBUG("dbg_chk", `DEBUG, "watchStep6: TID 6 see SPU active!"); | |
3163 | // spuActive[6] = 1; | |
3164 | // end | |
3165 | ||
3166 | // might get ss_complete due to not knowing if there are 1 or 2 or more flushes. | |
3167 | // this task gets called w/o knowing in advance if there will be one more | |
3168 | // assertion of tlu_trap_pc_0/1_valid or not. | |
3169 | begin : FORK8_6 | |
3170 | if (ssMode) begin | |
3171 | @(posedge `SPC5.spc_ss_complete); | |
3172 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep6: TID 6 see spc_ss_complete, step done, bailing (flushCount=%0d/redirectCount=%0d)!", flushCount6, redirectCount6); | |
3173 | stepDone[6] = 1; | |
3174 | stepActive[6] = 0; | |
3175 | disable watchStep6; // return | |
3176 | end | |
3177 | end | |
3178 | ||
3179 | // valid PC / retry | |
3180 | begin : FORK9_6 | |
3181 | // start step. tid wakes up/redirects and does "one instruction" | |
3182 | while (!(`SPC5.tlu_trap_pc_1_valid && `SPC5.tlu_trap_1_tid[1:0] == 2 && `SPC5.tlu.tlu_retry[1] == 1)) begin | |
3183 | // might see `SPC5.tlu.mmu_reload_done[6] here if previous | |
3184 | // redirect was due to a MMU miss. If so, decrement flush count because | |
3185 | // the previous flush on prev pc_valid "does not count" and there can be | |
3186 | // any number of them w/ no way to predict quantity. | |
3187 | if (`SPC5.tlu.mmu_reload_done[6] && ssMode) begin | |
3188 | flushCount6 = flushCount6-1; | |
3189 | redirectCount6 = redirectCount6-1; | |
3190 | watchStepMMU[6] = 1; | |
3191 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep6: TID 6 saw mmu_reload_done (hwtw)! flushCount/redirectCount decremented to %0d/%0d", flushCount6, redirectCount6); | |
3192 | end | |
3193 | @(negedge `SPC5.l2clk); | |
3194 | end | |
3195 | ||
3196 | redirectCount6 = redirectCount6+1; | |
3197 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep6: TID 6 got valid retry, step waiting on negedge pku_quiesce (redirectCount=%0d)!",redirectCount6); | |
3198 | disable FORK8_6; // kill sync on spc_ss_complete | |
3199 | ||
3200 | @(negedge `SPC5.pku_quiesce[6]); | |
3201 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep6: TID 6 got negedge pku_quiesce, step waiting on dec_inst_valid_m!"); | |
3202 | ||
3203 | while (!(`SPC5.dec_inst_valid_m[1] == 1 && `SPC5.dec_tid1_m[1:0] == 2)) @(negedge `SPC5.l2clk); | |
3204 | ||
3205 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep6: TID 6 valid step starting!"); | |
3206 | disable FORK10_6; // kill timeout | |
3207 | //disable FORK11_6; | |
3208 | // if (!`SPC5.spu_tlu_cwq_busy && | |
3209 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
3210 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 6)) spuActive[6] = 0; | |
3211 | end | |
3212 | join | |
3213 | ||
3214 | ||
3215 | ||
3216 | // finish step | |
3217 | fork | |
3218 | // timeout fork | |
3219 | begin : FORK4_6 | |
3220 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
3221 | ||
3222 | // may need to adjust. If a tid is doing a SPU sync ctl reg sync read, | |
3223 | // it could stay "busy" for a REAL long time!!! Need delayed check of busy | |
3224 | // since it can assert after the step has started. | |
3225 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep6: TID 6 did not quiesce/complete after step (SS or DO) as it should have. not SPU busy (waitTime=%0d)!", stepWaitTime); | |
3226 | end | |
3227 | ||
3228 | // look for SPU going active | |
3229 | // begin : FORK12_6 | |
3230 | // while (!(`SPC5.spu_tlu_cwq_busy || | |
3231 | // ((`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 6 && doMode) || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && ssMode)))) | |
3232 | // @(negedge `SPC5.l2clk); | |
3233 | // spuActive[6] = 1; | |
3234 | // end | |
3235 | ||
3236 | ||
3237 | // look for flush_ifu (w/o lsu_trap_flush (aka ptrap_flush) if SS) | |
3238 | // and end this task if seen. tlu_flush_ifu assertion always means | |
3239 | // this "instruction" is done, but may repeat (tlb miss, etc) w/in the SS. | |
3240 | begin : FORK6_6 | |
3241 | // checking ptrap_flush to make sure that flush is not caused by lsu_trap_flush | |
3242 | while (`SPC5.tlu_flush_ifu[6] == 0) | |
3243 | @(negedge `SPC5.l2clk); | |
3244 | ||
3245 | // // debug!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
3246 | // if (`SPC5.tlu.fls1.ptrap_flush[2] == 1) begin | |
3247 | // `PR_ERROR ("dbg_chk", `ERROR, "watchStep6: TID 6 have tlu_flush_ifu !!!!!!!!!!!!!!!!!!!!!!!"); | |
3248 | // end | |
3249 | // | |
3250 | ||
3251 | if ((ssMode && `SPC5.tlu.fls1.ptrap_flush[2] == 0) || doMode) begin | |
3252 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep6: TID 6 have tlu_flush_ifu (flushCount=%0d)!",flushCount6); | |
3253 | watchStepFlush[6] = 1; | |
3254 | flushCount6 = flushCount6+1; | |
3255 | stepActive[6] = 0; | |
3256 | disable watchStep6; // return | |
3257 | end | |
3258 | end | |
3259 | ||
3260 | ||
3261 | // are we done fork, DO mode quiesce | |
3262 | begin : FORK5_6 | |
3263 | if (doMode) begin | |
3264 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep6: TID 6 watching for quiesce (only matters fo DO mode)!"); | |
3265 | while (`SPC5.pku_quiesce[6] == 0 || | |
3266 | `SPC5.ftu_ifu_quiesce[6] == 0 || | |
3267 | `SPC5.lsu_stb_empty[6] == 0) @(negedge `SPC5.l2clk); | |
3268 | ||
3269 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep6: TID 6 have quiesce (only matters for DO mode)!"); | |
3270 | if (doMode) begin | |
3271 | disable FORK4_6; // TO | |
3272 | disable FORK6_6; // flush check | |
3273 | //disable FORK12_6; | |
3274 | // @(negedge `SPC5.l2clk); | |
3275 | // if (!`SPC5.spu_tlu_cwq_busy && | |
3276 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
3277 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 6)) spuActive[6] = 0; | |
3278 | end | |
3279 | end | |
3280 | end | |
3281 | ||
3282 | ||
3283 | // are we done fork, SS mode only | |
3284 | begin : FORK7_6 | |
3285 | // wait for SS complete | |
3286 | if (ssMode) begin | |
3287 | @(posedge `SPC5.spc_ss_complete); | |
3288 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep6: TID 6 see spc_ss_complete, step done, bailing (flushCount=%0d/redirectCount=%0d)!", flushCount6,redirectCount6); | |
3289 | stepDone[6] = 1; | |
3290 | ||
3291 | // while (ssMode && !`SPC5.spc_ss_complete) begin | |
3292 | // // detect a second inst valid w/o a flush between | |
3293 | // if (`SPC5.tlu_trap_pc_1_valid && `SPC5.tlu_trap_1_tid[1:0] == 2 && `SPC5.tlu.tlu_retry[1] == 1) begin | |
3294 | // // delay error so flush thread can kill this in the "got flush" case | |
3295 | // @(negedge `SPC5.l2clk); | |
3296 | // `PR_ERROR ("dbg_chk", `ERROR, "watchStep6: TID 6 had another inst start before SS done was asserted!"); | |
3297 | // end | |
3298 | // @(negedge `SPC5.l2clk); | |
3299 | // end // while | |
3300 | ||
3301 | if (`SPC5.pku_quiesce[6] == 0 || | |
3302 | `SPC5.ftu_ifu_quiesce[6] == 0 || | |
3303 | `SPC5.lsu_stb_empty[6] == 0) | |
3304 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep6: TID 6 was not quiesce at ss_complete assertion!"); | |
3305 | ||
3306 | disable FORK4_6; // TO | |
3307 | disable FORK6_6; // flush check | |
3308 | //disable FORK12_6; | |
3309 | // @(negedge `SPC5.l2clk); | |
3310 | // if (!`SPC5.spu_tlu_cwq_busy && | |
3311 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
3312 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 6)) spuActive[6] = 0; | |
3313 | end | |
3314 | end | |
3315 | ||
3316 | join | |
3317 | ||
3318 | ||
3319 | if (flushCount6 == 0) `PR_DEBUG("dbg_chk", `DEBUG, "watchStep6: TID 6 watchStep end!"); | |
3320 | else `PR_DEBUG("dbg_chk", `DEBUG, "watchStep6: TID 6 repeated watchStep end!"); | |
3321 | ||
3322 | stepActive[6] = 0; | |
3323 | ||
3324 | end | |
3325 | endtask | |
3326 | ||
3327 | ||
3328 | ||
3329 | // check that thread does DO mode correctly | |
3330 | task watchDOsteps6; | |
3331 | begin | |
3332 | ||
3333 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps6: TID 6 watchDOsteps starting!"); | |
3334 | ||
3335 | if (! `TOP.cpu.tcu_do_mode[5]) disable watchDOsteps6; | |
3336 | ||
3337 | // now wait for a thread to start. TCU internal signal. | |
3338 | if (`SPC5.tlu.tlu_core_running_status[6] == 0) | |
3339 | @(posedge `SPC5.tlu.tlu_core_running_status[6]); | |
3340 | ||
3341 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps6 TID 6 unparked and running in DO mode!"); | |
3342 | ||
3343 | // loop on step checking. DO mode is self stepping | |
3344 | while (doMode) begin : watchDOsteps6loop// && `SPC5.tlu.tlu_core_running_status[7:0] != 0) begin | |
3345 | ||
3346 | stepDone[6] = 0; | |
3347 | watchStepFlush[6] = 0; | |
3348 | watchStepMMU[6] = 0; | |
3349 | ||
3350 | // are we starting to park in middle of DO mode (or end)? | |
3351 | // wait here until unparked again | |
3352 | if (parkTrans[6]) begin | |
3353 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps6 TID 6 getting parked, will delay"); | |
3354 | @(negedge parkTrans[6]); | |
3355 | if (!doMode) disable watchDOsteps6loop; // no longer in DO mode, bail | |
3356 | // wait to be unparked or !doMode | |
3357 | if (parkedState[6]) begin | |
3358 | @(negedge doMode or negedge parkedState[6]); | |
3359 | if (!doMode) disable watchDOsteps6loop; // no longer in DO mode, bail | |
3360 | end | |
3361 | end | |
3362 | ||
3363 | ||
3364 | // an unparked thread does one instruction to completion before thread starts | |
3365 | // the next instruction. | |
3366 | fork | |
3367 | // timeout fork | |
3368 | begin : FORKDO16 | |
3369 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
3370 | `PR_ERROR ("dbg_chk", `ERROR, "watchDOsteps6: DO mode, TID 6 timeout waiting for watchStep call to return, not SPU busy (+stepWaitTime=%0d)!", stepWaitTime); | |
3371 | end | |
3372 | ||
3373 | // look for SPU going active | |
3374 | // begin : FORKDO26 | |
3375 | // while (!(`SPC5.spu_tlu_cwq_busy || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 6))) | |
3376 | // @(negedge `SPC5.l2clk); | |
3377 | // `PR_ALWAYS("dbg_chk", `ALWAYS, "watchDOsteps6: DO mode, TID 6 sees SPU busy!"); | |
3378 | // spuActive[6] = 1; | |
3379 | // end | |
3380 | ||
3381 | // watch step | |
3382 | begin | |
3383 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps6: TID 6 calling watchStep6 in DO mode!"); | |
3384 | watchStep6; // returns when step is done or flushed | |
3385 | if (watchStepFlush[6]) | |
3386 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 6 in DO mode had flush!"); | |
3387 | if (watchStepMMU[6]) | |
3388 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 6 in DO mode had mmu reload!"); | |
3389 | // calling flush as a done in DO mode | |
3390 | disable FORKDO16; // TO | |
3391 | //disable FORKDO26; // SPU going active | |
3392 | end | |
3393 | ||
3394 | join | |
3395 | ||
3396 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps6: TID 6 DO mode watchDOsteps step done!"); | |
3397 | stepDone[6] = 1; | |
3398 | flushCount6 = 0; | |
3399 | // if (!`SPC5.spu_tlu_cwq_busy && | |
3400 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
3401 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 6)) spuActive[6] = 0; | |
3402 | ||
3403 | @(negedge `SPC5.l2clk); | |
3404 | end // while | |
3405 | ||
3406 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps6: TID 6 DO mode watchDOsteps task ending!"); | |
3407 | end | |
3408 | endtask | |
3409 | ||
3410 | ||
3411 | ||
3412 | ||
3413 | ////////////////////////// end tid 6 /////////////////////////////////////// | |
3414 | ||
3415 | ||
3416 | ////////////////////////////////////////////////////////////////// | |
3417 | // THREAD 7 | |
3418 | ////////////////////////////////////////////////////////////////// | |
3419 | ||
3420 | ||
3421 | // got park request. transition into parking. parking check. | |
3422 | always @(negedge `SPC5.tlu.tcu_core_running[7]) begin: GOTPARK7 | |
3423 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 7 calling parkingCheck"); | |
3424 | if (enabled) parkingCheck7(); | |
3425 | end | |
3426 | ||
3427 | // got unpark request. transition into running. unparking check. | |
3428 | always @(posedge `SPC5.tlu.tcu_core_running[7]) begin: UNPARKCHECK7 | |
3429 | if (enabled && !ssMode) begin | |
3430 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 7 calling unparkCheck."); | |
3431 | unparkCheck7(); | |
3432 | end | |
3433 | end | |
3434 | ||
3435 | // while parked check | |
3436 | always @(posedge parkedState[7] or posedge virtualPark[7]) begin: PARKCHECK7 | |
3437 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 7 calling parkedCheck"); | |
3438 | if (enabled) parkedCheck7(); | |
3439 | end | |
3440 | ||
3441 | // check for unexpected running transition | |
3442 | always @(`SPC5.tlu.tlu_core_running_status[7]) begin: UNEXPECTED7 | |
3443 | if (!parkTrans[7] && enabled && ! doMode && ! ssMode) // review? to remove ! doMode | |
3444 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 7 spc_core_running_status changed w/o request to park/unpark (trans=%0d)!",parkTrans[7]); | |
3445 | end | |
3446 | ||
3447 | ||
3448 | ||
3449 | ////////////// tasks for tid 7 //////////////////// | |
3450 | ||
3451 | // check the entering into parked state | |
3452 | task parkingCheck7; | |
3453 | ||
3454 | begin | |
3455 | ||
3456 | ||
3457 | `PR_DEBUG("dbg_chk", `DEBUG, "TID 7 got park request!"); | |
3458 | ||
3459 | if (parkTrans[7] == 1) begin | |
3460 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 7 got park request while park state is already transitioning! Possible diag conflict (multiple parkers)! (enabled=%0d)",enabled); | |
3461 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +noDebugChecks to disable all debug checkes!"); | |
3462 | disable parkingCheck7; | |
3463 | end | |
3464 | ||
3465 | parkTrans[7] = 1; | |
3466 | ||
3467 | // wait before checking signals | |
3468 | repeat (2) @(negedge `SPC5.l2clk); | |
3469 | ||
3470 | // need to see at least one assertion of flush | |
3471 | // if (`SPC5.tlu_flush_ifu[7] !== 1) | |
3472 | // @(posedge `SPC5.tlu_flush_ifu[7]); // has glitches | |
3473 | if (`SPC5.ifu_ftu.ftu_agc_ctl.tlu_flush_ifu_f[7] !== 1) | |
3474 | @(posedge `SPC5.ifu_ftu.ftu_agc_ctl.tlu_flush_ifu_f[7]); | |
3475 | ||
3476 | // need to see all of these go idle | |
3477 | while (`SPC5.pku_quiesce[7] == 0 || | |
3478 | `SPC5.ftu_ifu_quiesce[7] == 0 || | |
3479 | `SPC5.lsu_stb_empty[7] == 0) | |
3480 | @(negedge `SPC5.l2clk); | |
3481 | ||
3482 | // // need to see all of these go idle | |
3483 | // while (`SPC5.pku_quiesce[7] == 0 || | |
3484 | // `SPC5.ftu_ifu_quiesce[7] == 0 || | |
3485 | // `SPC5.lsu_stb_empty[7] == 0 || | |
3486 | // `SPC5.tlu.fls1.idl_request == 0) | |
3487 | // @(negedge `SPC5.l2clk); | |
3488 | ||
3489 | parkedState[7] <= 1; | |
3490 | parkTrans[7] <= 0; | |
3491 | // `PR_ALWAYS("dbg_chk", `ALWAYS, "INFO: TID %0d has parked!", 7); | |
3492 | `PR_DEBUG("dbg_chk", `DEBUG, "INFO: TID 7 has parked!"); | |
3493 | ||
3494 | end | |
3495 | endtask | |
3496 | ||
3497 | ||
3498 | // in parked state. | |
3499 | // also called between single steps. | |
3500 | task parkedCheck7; | |
3501 | reg notified; | |
3502 | begin //{ | |
3503 | ||
3504 | notified = 0; | |
3505 | // loop while not transitioning out of park if not SS mode. | |
3506 | // loop while in SS virtualPark if SS mode. | |
3507 | while ((parkTrans[7] == 0 && ssMode == 0) || | |
3508 | (virtualPark[7] == 1 && ssMode == 1 && | |
3509 | `TOP.cpu.tcu_ss_request[5] == 0)) begin //{ | |
3510 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 7 watching for activity while parked/between steps. trans=%0h, virtualPark=%0h, tcu_ss_request=%0h",parkTrans[7],virtualPark[7],`TOP.cpu.tcu_ss_request[5]); | |
3511 | ||
3512 | @(negedge `SPC5.l2clk); | |
3513 | ||
3514 | // if in SS mode and core_running goes to zero for that thread, the thread | |
3515 | // will self step once and flush in order to change to a parked state | |
3516 | // (core_running_status=0). This looks like an un-asked for step so it | |
3517 | // has to be detected and ignored. Try stalling here during it. | |
3518 | while (`SPC5.tlu.tcu_core_running[7] == 0 && | |
3519 | `SPC5.tlu.tlu_core_running_status[7] == 1) | |
3520 | @(negedge `SPC5.l2clk); | |
3521 | ||
3522 | // watch for instructions sneaking in | |
3523 | // dec_inst_valid_m[1:0], one bit per group | |
3524 | if (`SPC5.tlu_trap_pc_1_valid && `SPC5.tlu_trap_1_tid[1:0] == 7 && `SPC5.tlu.tlu_retry[1] == 1) | |
3525 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 7 had tlu_trap_pc_1_valid activity while parked/between steps!"); | |
3526 | ||
3527 | if (`SPC5.dec_inst_valid_m[1] == 1 && `SPC5.dec_tid1_m[1:0] == 3) | |
3528 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 7 had dec_inst_valid_m activity while parked/between steps!"); | |
3529 | ||
3530 | ||
3531 | end //} while | |
3532 | ||
3533 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 7 STOP watching for activity while parked/between steps. trans=%0h, virtualPark=%0h, tcu_ss_request=%0h",parkTrans[7],virtualPark[7],`TOP.cpu.tcu_ss_request[5]); | |
3534 | ||
3535 | end //} | |
3536 | endtask | |
3537 | ||
3538 | ||
3539 | // leaving parked state | |
3540 | task unparkCheck7; | |
3541 | integer count; | |
3542 | begin | |
3543 | ||
3544 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 7 got unpark request!"); | |
3545 | ||
3546 | if (parkTrans[7] == 1) begin | |
3547 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 7 got unpark request while park state is already transitioning! Possible diag conflict! (trans=%0h)",parkTrans); | |
3548 | disable unparkCheck7; | |
3549 | end | |
3550 | ||
3551 | parkTrans[7] = 1; | |
3552 | ||
3553 | // must see `SPC5.tlu.core_running_status[7] w/in count clocks | |
3554 | count7 = 0; | |
3555 | ||
3556 | while (`SPC5.tlu.tlu_core_running_status[7] == 0) begin | |
3557 | @(negedge `SPC5.l2clk); | |
3558 | if (count7 > parkWait) begin // <--- may need to adjust | |
3559 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 7 did not assert spc_core_running_status as soon as it should have (%0d clocks)!", count7); | |
3560 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +parkWait=n (currently %0d). +noDebugChecks disables all checks!",parkWait); | |
3561 | end | |
3562 | count7 = count7 + 1; | |
3563 | end | |
3564 | ||
3565 | if (!doMode && !ssMode) begin | |
3566 | // need to see re-direct w/in "redirectWait" more clocks | |
3567 | count7 = 0; | |
3568 | ||
3569 | // if this is true, the redirect and the assertion of core_running_status | |
3570 | // happened at once so while loop can be skipped. | |
3571 | while (! (`SPC5.tlu_trap_pc_1_valid && | |
3572 | `SPC5.tlu_trap_1_tid[1:0] == 3)) begin | |
3573 | @(negedge `SPC5.l2clk); | |
3574 | if (count7 > redirectWait) begin // <--- may need to adjust | |
3575 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: TID 7 did not redirect within %d clocks after core_running_status assert!", redirectWait); | |
3576 | `PR_ERROR ("dbg_chk", `ERROR, "NOTICE: For unusual circumstances, use +redirectWait=n (currently %0d). +noDebugChecks disables all checks!",redirectWait); | |
3577 | end | |
3578 | count7 = count7 + 1; | |
3579 | end | |
3580 | end | |
3581 | ||
3582 | parkedState[7] <= 0; | |
3583 | parkTrans[7] <= 0; | |
3584 | count7 <= 0; | |
3585 | ||
3586 | end | |
3587 | endtask | |
3588 | ||
3589 | ||
3590 | // watch this tid step correctly. Should step 1 instruction | |
3591 | // and then "virtual park". | |
3592 | // for SS and DO modes. | |
3593 | task watchStep7; | |
3594 | begin | |
3595 | ||
3596 | watchStepFlush[7] = 0; // set if we got a flush | |
3597 | watchStepMMU[7] = 0; // set if we got a mmu reload | |
3598 | stepDone[7] = 0; | |
3599 | stepActive[7] = 1; | |
3600 | ||
3601 | if (flushCount7) `PR_DEBUG("dbg_chk", `DEBUG, "watchStep7: TID 7 repeating watchStep task due to flush (flushCount=%0d, redirectCount=%0d)!",flushCount7,redirectCount7); | |
3602 | ||
3603 | ||
3604 | fork | |
3605 | // timeout fork | |
3606 | begin : FORK10_7 | |
3607 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
3608 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep7: TID 7 did not see valid PC retry (waitTime=%0d)!", stepWaitTime); | |
3609 | end | |
3610 | ||
3611 | // // look for SPU going active | |
3612 | // begin : FORK11_7 | |
3613 | // while (!(`SPC5.spu_tlu_cwq_busy || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 7))) | |
3614 | // @(negedge `SPC5.l2clk); | |
3615 | // `PR_DEBUG("dbg_chk", `DEBUG, "watchStep7: TID 7 see SPU active!"); | |
3616 | // spuActive[7] = 1; | |
3617 | // end | |
3618 | ||
3619 | // might get ss_complete due to not knowing if there are 1 or 2 or more flushes. | |
3620 | // this task gets called w/o knowing in advance if there will be one more | |
3621 | // assertion of tlu_trap_pc_0/1_valid or not. | |
3622 | begin : FORK8_7 | |
3623 | if (ssMode) begin | |
3624 | @(posedge `SPC5.spc_ss_complete); | |
3625 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep7: TID 7 see spc_ss_complete, step done, bailing (flushCount=%0d/redirectCount=%0d)!", flushCount7, redirectCount7); | |
3626 | stepDone[7] = 1; | |
3627 | stepActive[7] = 0; | |
3628 | disable watchStep7; // return | |
3629 | end | |
3630 | end | |
3631 | ||
3632 | // valid PC / retry | |
3633 | begin : FORK9_7 | |
3634 | // start step. tid wakes up/redirects and does "one instruction" | |
3635 | while (!(`SPC5.tlu_trap_pc_1_valid && `SPC5.tlu_trap_1_tid[1:0] == 3 && `SPC5.tlu.tlu_retry[1] == 1)) begin | |
3636 | // might see `SPC5.tlu.mmu_reload_done[7] here if previous | |
3637 | // redirect was due to a MMU miss. If so, decrement flush count because | |
3638 | // the previous flush on prev pc_valid "does not count" and there can be | |
3639 | // any number of them w/ no way to predict quantity. | |
3640 | if (`SPC5.tlu.mmu_reload_done[7] && ssMode) begin | |
3641 | flushCount7 = flushCount7-1; | |
3642 | redirectCount7 = redirectCount7-1; | |
3643 | watchStepMMU[7] = 1; | |
3644 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep7: TID 7 saw mmu_reload_done (hwtw)! flushCount/redirectCount decremented to %0d/%0d", flushCount7, redirectCount7); | |
3645 | end | |
3646 | @(negedge `SPC5.l2clk); | |
3647 | end | |
3648 | ||
3649 | redirectCount7 = redirectCount7+1; | |
3650 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep7: TID 7 got valid retry, step waiting on negedge pku_quiesce (redirectCount=%0d)!",redirectCount7); | |
3651 | disable FORK8_7; // kill sync on spc_ss_complete | |
3652 | ||
3653 | @(negedge `SPC5.pku_quiesce[7]); | |
3654 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep7: TID 7 got negedge pku_quiesce, step waiting on dec_inst_valid_m!"); | |
3655 | ||
3656 | while (!(`SPC5.dec_inst_valid_m[1] == 1 && `SPC5.dec_tid1_m[1:0] == 3)) @(negedge `SPC5.l2clk); | |
3657 | ||
3658 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep7: TID 7 valid step starting!"); | |
3659 | disable FORK10_7; // kill timeout | |
3660 | //disable FORK11_7; | |
3661 | // if (!`SPC5.spu_tlu_cwq_busy && | |
3662 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
3663 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 7)) spuActive[7] = 0; | |
3664 | end | |
3665 | join | |
3666 | ||
3667 | ||
3668 | ||
3669 | // finish step | |
3670 | fork | |
3671 | // timeout fork | |
3672 | begin : FORK4_7 | |
3673 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
3674 | ||
3675 | // may need to adjust. If a tid is doing a SPU sync ctl reg sync read, | |
3676 | // it could stay "busy" for a REAL long time!!! Need delayed check of busy | |
3677 | // since it can assert after the step has started. | |
3678 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep7: TID 7 did not quiesce/complete after step (SS or DO) as it should have. not SPU busy (waitTime=%0d)!", stepWaitTime); | |
3679 | end | |
3680 | ||
3681 | // look for SPU going active | |
3682 | // begin : FORK12_7 | |
3683 | // while (!(`SPC5.spu_tlu_cwq_busy || | |
3684 | // ((`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 7 && doMode) || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && ssMode)))) | |
3685 | // @(negedge `SPC5.l2clk); | |
3686 | // spuActive[7] = 1; | |
3687 | // end | |
3688 | ||
3689 | ||
3690 | // look for flush_ifu (w/o lsu_trap_flush (aka ptrap_flush) if SS) | |
3691 | // and end this task if seen. tlu_flush_ifu assertion always means | |
3692 | // this "instruction" is done, but may repeat (tlb miss, etc) w/in the SS. | |
3693 | begin : FORK6_7 | |
3694 | // checking ptrap_flush to make sure that flush is not caused by lsu_trap_flush | |
3695 | while (`SPC5.tlu_flush_ifu[7] == 0) | |
3696 | @(negedge `SPC5.l2clk); | |
3697 | ||
3698 | // // debug!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
3699 | // if (`SPC5.tlu.fls1.ptrap_flush[3] == 1) begin | |
3700 | // `PR_ERROR ("dbg_chk", `ERROR, "watchStep7: TID 7 have tlu_flush_ifu !!!!!!!!!!!!!!!!!!!!!!!"); | |
3701 | // end | |
3702 | // | |
3703 | ||
3704 | if ((ssMode && `SPC5.tlu.fls1.ptrap_flush[3] == 0) || doMode) begin | |
3705 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep7: TID 7 have tlu_flush_ifu (flushCount=%0d)!",flushCount7); | |
3706 | watchStepFlush[7] = 1; | |
3707 | flushCount7 = flushCount7+1; | |
3708 | stepActive[7] = 0; | |
3709 | disable watchStep7; // return | |
3710 | end | |
3711 | end | |
3712 | ||
3713 | ||
3714 | // are we done fork, DO mode quiesce | |
3715 | begin : FORK5_7 | |
3716 | if (doMode) begin | |
3717 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep7: TID 7 watching for quiesce (only matters fo DO mode)!"); | |
3718 | while (`SPC5.pku_quiesce[7] == 0 || | |
3719 | `SPC5.ftu_ifu_quiesce[7] == 0 || | |
3720 | `SPC5.lsu_stb_empty[7] == 0) @(negedge `SPC5.l2clk); | |
3721 | ||
3722 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep7: TID 7 have quiesce (only matters for DO mode)!"); | |
3723 | if (doMode) begin | |
3724 | disable FORK4_7; // TO | |
3725 | disable FORK6_7; // flush check | |
3726 | //disable FORK12_7; | |
3727 | // @(negedge `SPC5.l2clk); | |
3728 | // if (!`SPC5.spu_tlu_cwq_busy && | |
3729 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
3730 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 7)) spuActive[7] = 0; | |
3731 | end | |
3732 | end | |
3733 | end | |
3734 | ||
3735 | ||
3736 | // are we done fork, SS mode only | |
3737 | begin : FORK7_7 | |
3738 | // wait for SS complete | |
3739 | if (ssMode) begin | |
3740 | @(posedge `SPC5.spc_ss_complete); | |
3741 | `PR_DEBUG("dbg_chk", `DEBUG, "watchStep7: TID 7 see spc_ss_complete, step done, bailing (flushCount=%0d/redirectCount=%0d)!", flushCount7,redirectCount7); | |
3742 | stepDone[7] = 1; | |
3743 | ||
3744 | // while (ssMode && !`SPC5.spc_ss_complete) begin | |
3745 | // // detect a second inst valid w/o a flush between | |
3746 | // if (`SPC5.tlu_trap_pc_1_valid && `SPC5.tlu_trap_1_tid[1:0] == 3 && `SPC5.tlu.tlu_retry[1] == 1) begin | |
3747 | // // delay error so flush thread can kill this in the "got flush" case | |
3748 | // @(negedge `SPC5.l2clk); | |
3749 | // `PR_ERROR ("dbg_chk", `ERROR, "watchStep7: TID 7 had another inst start before SS done was asserted!"); | |
3750 | // end | |
3751 | // @(negedge `SPC5.l2clk); | |
3752 | // end // while | |
3753 | ||
3754 | if (`SPC5.pku_quiesce[7] == 0 || | |
3755 | `SPC5.ftu_ifu_quiesce[7] == 0 || | |
3756 | `SPC5.lsu_stb_empty[7] == 0) | |
3757 | `PR_ERROR ("dbg_chk", `ERROR, "watchStep7: TID 7 was not quiesce at ss_complete assertion!"); | |
3758 | ||
3759 | disable FORK4_7; // TO | |
3760 | disable FORK6_7; // flush check | |
3761 | //disable FORK12_7; | |
3762 | // @(negedge `SPC5.l2clk); | |
3763 | // if (!`SPC5.spu_tlu_cwq_busy && | |
3764 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
3765 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 7)) spuActive[7] = 0; | |
3766 | end | |
3767 | end | |
3768 | ||
3769 | join | |
3770 | ||
3771 | ||
3772 | if (flushCount7 == 0) `PR_DEBUG("dbg_chk", `DEBUG, "watchStep7: TID 7 watchStep end!"); | |
3773 | else `PR_DEBUG("dbg_chk", `DEBUG, "watchStep7: TID 7 repeated watchStep end!"); | |
3774 | ||
3775 | stepActive[7] = 0; | |
3776 | ||
3777 | end | |
3778 | endtask | |
3779 | ||
3780 | ||
3781 | ||
3782 | // check that thread does DO mode correctly | |
3783 | task watchDOsteps7; | |
3784 | begin | |
3785 | ||
3786 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps7: TID 7 watchDOsteps starting!"); | |
3787 | ||
3788 | if (! `TOP.cpu.tcu_do_mode[5]) disable watchDOsteps7; | |
3789 | ||
3790 | // now wait for a thread to start. TCU internal signal. | |
3791 | if (`SPC5.tlu.tlu_core_running_status[7] == 0) | |
3792 | @(posedge `SPC5.tlu.tlu_core_running_status[7]); | |
3793 | ||
3794 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps7 TID 7 unparked and running in DO mode!"); | |
3795 | ||
3796 | // loop on step checking. DO mode is self stepping | |
3797 | while (doMode) begin : watchDOsteps7loop// && `SPC5.tlu.tlu_core_running_status[7:0] != 0) begin | |
3798 | ||
3799 | stepDone[7] = 0; | |
3800 | watchStepFlush[7] = 0; | |
3801 | watchStepMMU[7] = 0; | |
3802 | ||
3803 | // are we starting to park in middle of DO mode (or end)? | |
3804 | // wait here until unparked again | |
3805 | if (parkTrans[7]) begin | |
3806 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps7 TID 7 getting parked, will delay"); | |
3807 | @(negedge parkTrans[7]); | |
3808 | if (!doMode) disable watchDOsteps7loop; // no longer in DO mode, bail | |
3809 | // wait to be unparked or !doMode | |
3810 | if (parkedState[7]) begin | |
3811 | @(negedge doMode or negedge parkedState[7]); | |
3812 | if (!doMode) disable watchDOsteps7loop; // no longer in DO mode, bail | |
3813 | end | |
3814 | end | |
3815 | ||
3816 | ||
3817 | // an unparked thread does one instruction to completion before thread starts | |
3818 | // the next instruction. | |
3819 | fork | |
3820 | // timeout fork | |
3821 | begin : FORKDO17 | |
3822 | repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
3823 | `PR_ERROR ("dbg_chk", `ERROR, "watchDOsteps7: DO mode, TID 7 timeout waiting for watchStep call to return, not SPU busy (+stepWaitTime=%0d)!", stepWaitTime); | |
3824 | end | |
3825 | ||
3826 | // look for SPU going active | |
3827 | // begin : FORKDO27 | |
3828 | // while (!(`SPC5.spu_tlu_cwq_busy || (`SPC5.spu.mct.spu_pmu_ma_busy[3] && `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 7))) | |
3829 | // @(negedge `SPC5.l2clk); | |
3830 | // `PR_ALWAYS("dbg_chk", `ALWAYS, "watchDOsteps7: DO mode, TID 7 sees SPU busy!"); | |
3831 | // spuActive[7] = 1; | |
3832 | // end | |
3833 | ||
3834 | // watch step | |
3835 | begin | |
3836 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps7: TID 7 calling watchStep7 in DO mode!"); | |
3837 | watchStep7; // returns when step is done or flushed | |
3838 | if (watchStepFlush[7]) | |
3839 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 7 in DO mode had flush!"); | |
3840 | if (watchStepMMU[7]) | |
3841 | `PR_DEBUG ("dbg_chk", `DEBUG, "TID 7 in DO mode had mmu reload!"); | |
3842 | // calling flush as a done in DO mode | |
3843 | disable FORKDO17; // TO | |
3844 | //disable FORKDO27; // SPU going active | |
3845 | end | |
3846 | ||
3847 | join | |
3848 | ||
3849 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps7: TID 7 DO mode watchDOsteps step done!"); | |
3850 | stepDone[7] = 1; | |
3851 | flushCount7 = 0; | |
3852 | // if (!`SPC5.spu_tlu_cwq_busy && | |
3853 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
3854 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 7)) spuActive[7] = 0; | |
3855 | ||
3856 | @(negedge `SPC5.l2clk); | |
3857 | end // while | |
3858 | ||
3859 | `PR_DEBUG("dbg_chk", `DEBUG, "watchDOsteps7: TID 7 DO mode watchDOsteps task ending!"); | |
3860 | end | |
3861 | endtask | |
3862 | ||
3863 | ||
3864 | ||
3865 | ||
3866 | ////////////////////////// end tid 7 /////////////////////////////////////// | |
3867 | ||
3868 | ||
3869 | ||
3870 | ////////////// DO mode checks //////////////////// | |
3871 | ||
3872 | always @(posedge `TOP.cpu.tcu_do_mode[5]) begin: DOMODE | |
3873 | if (enabled) begin | |
3874 | ||
3875 | `PR_ALWAYS ("dbg_chk", `ALWAYS, "Entering Disable Overlap mode!"); | |
3876 | if (parkedState !== 8'hff) | |
3877 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: All threads must be parked when enabling/disabling DO mode!"); | |
3878 | doMode = 1; | |
3879 | stepDone = 0; | |
3880 | ||
3881 | // wait for core_running to change (unparking) so DO steps can start | |
3882 | // Assumes (safely) a SINGLE change to this register! | |
3883 | if (`SPC5.tlu.tcu_core_running[7:0] == 0) | |
3884 | @(`SPC5.tlu.tcu_core_running[7:0]) | |
3885 | ||
3886 | stepAllowed[7:0] = `SPC5.tlu.tcu_core_running[7:0]; | |
3887 | ||
3888 | `PR_DEBUG("dbg_chk", `DEBUG, "DO mode, ready to run in DO mode!"); | |
3889 | ||
3890 | ||
3891 | // for each thread, call a task that checks DO mode. | |
3892 | // these return when DO mode ends | |
3893 | fork | |
3894 | if (stepAllowed[0]) watchDOsteps0; | |
3895 | if (stepAllowed[1]) watchDOsteps1; | |
3896 | if (stepAllowed[2]) watchDOsteps2; | |
3897 | if (stepAllowed[3]) watchDOsteps3; | |
3898 | if (stepAllowed[4]) watchDOsteps4; | |
3899 | if (stepAllowed[5]) watchDOsteps5; | |
3900 | if (stepAllowed[6]) watchDOsteps6; | |
3901 | if (stepAllowed[7]) watchDOsteps7; | |
3902 | join | |
3903 | ||
3904 | end | |
3905 | end | |
3906 | ||
3907 | ||
3908 | ||
3909 | always @(negedge `TOP.cpu.tcu_do_mode[5]) begin | |
3910 | if (enabled) begin | |
3911 | `PR_ALWAYS ("dbg_chk", `ALWAYS, "Ending Disable Overlap mode!"); | |
3912 | doMode = 0; | |
3913 | if (parkedState !== 8'hff) | |
3914 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: All threads must be parked when enabling/disabling DO mode!"); | |
3915 | if (stepAllowed[0]) disable watchStep0; | |
3916 | if (stepAllowed[1]) disable watchStep1; | |
3917 | if (stepAllowed[2]) disable watchStep2; | |
3918 | if (stepAllowed[3]) disable watchStep3; | |
3919 | if (stepAllowed[4]) disable watchStep4; | |
3920 | if (stepAllowed[5]) disable watchStep5; | |
3921 | if (stepAllowed[6]) disable watchStep6; | |
3922 | if (stepAllowed[7]) disable watchStep7; | |
3923 | stepAllowed[7:0] = 0; | |
3924 | end | |
3925 | end | |
3926 | ||
3927 | ||
3928 | ||
3929 | ////////////// SS mode checks //////////////////// | |
3930 | ////////////// SS mode checks //////////////////// | |
3931 | ////////////// SS mode checks //////////////////// | |
3932 | ||
3933 | always @(posedge `TOP.cpu.tcu_ss_mode[5]) begin: SSMODE | |
3934 | ||
3935 | if (enabled) begin | |
3936 | ||
3937 | // initial value in case ss_mode and tcu_core_running change at once | |
3938 | stepAllowed[7:0] = `SPC5.tlu.tcu_core_running[7:0]; // need? | |
3939 | ||
3940 | `PR_ALWAYS ("dbg_chk", `ALWAYS, "Entering Single Step mode!"); | |
3941 | if (parkedState !== 8'hff) | |
3942 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: All threads must be parked when enabling SS mode!"); | |
3943 | ||
3944 | stepDone = 0; | |
3945 | ssMode = 1; | |
3946 | @(negedge `SPC5.l2clk); | |
3947 | // use virtualPark for SS mode, not parkedState | |
3948 | //virtualPark = threadEnable; | |
3949 | virtualPark = `PARGS.th_check_enable; // th_check_enable is set dynamically | |
3950 | ||
3951 | // wait for core_running to change so steps can start | |
3952 | if (`SPC5.tlu.tcu_core_running[7:0] == 0) | |
3953 | @(`SPC5.tlu.tcu_core_running[7:0]) stepAllowed[7:0] = `SPC5.tlu.tcu_core_running[7:0]; | |
3954 | ||
3955 | `PR_DEBUG("dbg_chk", `DEBUG, "SS mode, ready to run in SS mode!"); | |
3956 | ||
3957 | // loop on this step checking | |
3958 | while (`TOP.cpu.tcu_ss_mode[5] === 1) begin | |
3959 | ||
3960 | // wait for TCU to request a step or for SS mode to end | |
3961 | @(posedge `TOP.cpu.tcu_ss_request or negedge `TOP.cpu.tcu_ss_mode[5]); | |
3962 | ||
3963 | if (`TOP.cpu.tcu_ss_mode[5] === 1) begin | |
3964 | ||
3965 | @(negedge `SPC5.l2clk); | |
3966 | ||
3967 | virtualPark = 0; | |
3968 | stepCount = stepCount+1; | |
3969 | stepDone = 0; | |
3970 | watchStepFlush = 0; | |
3971 | watchStepMMU = 0; | |
3972 | ||
3973 | fork | |
3974 | if (stepAllowed[0]) begin | |
3975 | flushCount0 = 0; | |
3976 | redirectCount0 = 0; | |
3977 | watchStep0; // returns when inst is done | |
3978 | // got a flush, will be more activity | |
3979 | if (flushCount0 != 0) begin | |
3980 | while (!stepDone[0]) begin | |
3981 | @(negedge `SPC5.l2clk); | |
3982 | watchStep0; // returns when inst is done | |
3983 | if (flushCount0 > 2) | |
3984 | `PR_ERROR ("dbg_chk", `ERROR, "TID 0 too many flushes in SS mode (%0d)",flushCount0); | |
3985 | if (redirectCount0 > 2) | |
3986 | `PR_ERROR ("dbg_chk", `ERROR, "TID 0 too many redirects in SS mode (%0d)",redirectCount0); | |
3987 | if (redirectCount0 > 1 && watchStepMMU[0]) | |
3988 | `PR_ERROR ("dbg_chk", `ERROR, "TID 0 too many redirects in SS mode when mmu_reload_done (%0d)",redirectCount0); | |
3989 | end | |
3990 | end | |
3991 | virtualPark[0] = 1; // should be in virtual park. starts parkedCheck0 | |
3992 | stepDone[0] = 1; | |
3993 | // if (!`SPC5.spu_tlu_cwq_busy && | |
3994 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
3995 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 0)) spuActive[0] = 0; | |
3996 | end | |
3997 | ||
3998 | if (stepAllowed[1]) begin | |
3999 | flushCount1 = 0; | |
4000 | redirectCount1 = 0; | |
4001 | watchStep1; // returns when inst is done | |
4002 | // got a flush, will be more activity | |
4003 | if (flushCount1 != 0) begin | |
4004 | while (!stepDone[1]) begin | |
4005 | @(negedge `SPC5.l2clk); | |
4006 | watchStep1; // returns when inst is done | |
4007 | if (flushCount1 > 2) | |
4008 | `PR_ERROR ("dbg_chk", `ERROR, "TID 1 too many flushes in SS mode (%0d)",flushCount1); | |
4009 | if (redirectCount1 > 2) | |
4010 | `PR_ERROR ("dbg_chk", `ERROR, "TID 1 too many redirects in SS mode (%0d)",redirectCount1); | |
4011 | if (redirectCount1 > 1 && watchStepMMU[1]) | |
4012 | `PR_ERROR ("dbg_chk", `ERROR, "TID 1 too many redirects in SS mode when mmu_reload_done (%0d)",redirectCount1); | |
4013 | end | |
4014 | end | |
4015 | virtualPark[1] = 1; // should be in virtual park. starts parkedCheck0 | |
4016 | stepDone[1] = 1; | |
4017 | // if (!`SPC5.spu_tlu_cwq_busy && | |
4018 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
4019 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 1)) spuActive[1] = 0; | |
4020 | end | |
4021 | ||
4022 | if (stepAllowed[2]) begin | |
4023 | flushCount2 = 0; | |
4024 | redirectCount2 = 0; | |
4025 | watchStep2; // returns when inst is done | |
4026 | // got a flush, will be more activity | |
4027 | if (flushCount2 != 0) begin | |
4028 | while (!stepDone[2]) begin | |
4029 | @(negedge `SPC5.l2clk); | |
4030 | watchStep2; // returns when inst is done | |
4031 | if (flushCount2 > 2) | |
4032 | `PR_ERROR ("dbg_chk", `ERROR, "TID 2 too many flushes in SS mode (%0d)",flushCount2); | |
4033 | if (redirectCount2 > 2) | |
4034 | `PR_ERROR ("dbg_chk", `ERROR, "TID 2 too many redirects in SS mode (%0d)",redirectCount2); | |
4035 | if (redirectCount2 > 1 && watchStepMMU[2]) | |
4036 | `PR_ERROR ("dbg_chk", `ERROR, "TID 2 too many redirects in SS mode when mmu_reload_done (%0d)",redirectCount2); | |
4037 | end | |
4038 | end | |
4039 | virtualPark[2] = 1; // should be in virtual park. starts parkedCheck0 | |
4040 | stepDone[2] = 1; | |
4041 | // if (!`SPC5.spu_tlu_cwq_busy && | |
4042 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
4043 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 2)) spuActive[2] = 0; | |
4044 | end | |
4045 | ||
4046 | if (stepAllowed[3]) begin | |
4047 | flushCount3 = 0; | |
4048 | redirectCount3 = 0; | |
4049 | watchStep3; // returns when inst is done | |
4050 | // got a flush, will be more activity | |
4051 | if (flushCount3 != 0) begin | |
4052 | while (!stepDone[3]) begin | |
4053 | @(negedge `SPC5.l2clk); | |
4054 | watchStep3; // returns when inst is done | |
4055 | if (flushCount3 > 2) | |
4056 | `PR_ERROR ("dbg_chk", `ERROR, "TID 3 too many flushes in SS mode (%0d)",flushCount3); | |
4057 | if (redirectCount3 > 2) | |
4058 | `PR_ERROR ("dbg_chk", `ERROR, "TID 3 too many redirects in SS mode (%0d)",redirectCount3); | |
4059 | if (redirectCount3 > 1 && watchStepMMU[3]) | |
4060 | `PR_ERROR ("dbg_chk", `ERROR, "TID 3 too many redirects in SS mode when mmu_reload_done (%0d)",redirectCount3); | |
4061 | end | |
4062 | end | |
4063 | virtualPark[3] = 1; // should be in virtual park. starts parkedCheck0 | |
4064 | stepDone[3] = 1; | |
4065 | // if (!`SPC5.spu_tlu_cwq_busy && | |
4066 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
4067 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 3)) spuActive[3] = 0; | |
4068 | end | |
4069 | ||
4070 | if (stepAllowed[4]) begin | |
4071 | flushCount4 = 0; | |
4072 | redirectCount4 = 0; | |
4073 | watchStep4; // returns when inst is done | |
4074 | // got a flush, will be more activity | |
4075 | if (flushCount4 != 0) begin | |
4076 | while (!stepDone[4]) begin | |
4077 | @(negedge `SPC5.l2clk); | |
4078 | watchStep4; // returns when inst is done | |
4079 | if (flushCount4 > 2) | |
4080 | `PR_ERROR ("dbg_chk", `ERROR, "TID 4 too many flushes in SS mode (%0d)",flushCount4); | |
4081 | if (redirectCount4 > 2) | |
4082 | `PR_ERROR ("dbg_chk", `ERROR, "TID 4 too many redirects in SS mode (%0d)",redirectCount4); | |
4083 | if (redirectCount4 > 1 && watchStepMMU[4]) | |
4084 | `PR_ERROR ("dbg_chk", `ERROR, "TID 4 too many redirects in SS mode when mmu_reload_done (%0d)",redirectCount4); | |
4085 | end | |
4086 | end | |
4087 | virtualPark[4] = 1; // should be in virtual park. starts parkedCheck0 | |
4088 | stepDone[4] = 1; | |
4089 | // if (!`SPC5.spu_tlu_cwq_busy && | |
4090 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
4091 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 4)) spuActive[4] = 0; | |
4092 | end | |
4093 | ||
4094 | if (stepAllowed[5]) begin | |
4095 | flushCount5 = 0; | |
4096 | redirectCount5 = 0; | |
4097 | watchStep5; // returns when inst is done | |
4098 | // got a flush, will be more activity | |
4099 | if (flushCount5 != 0) begin | |
4100 | while (!stepDone[5]) begin | |
4101 | @(negedge `SPC5.l2clk); | |
4102 | watchStep5; // returns when inst is done | |
4103 | if (flushCount5 > 2) | |
4104 | `PR_ERROR ("dbg_chk", `ERROR, "TID 5 too many flushes in SS mode (%0d)",flushCount5); | |
4105 | if (redirectCount5 > 2) | |
4106 | `PR_ERROR ("dbg_chk", `ERROR, "TID 5 too many redirects in SS mode (%0d)",redirectCount5); | |
4107 | if (redirectCount5 > 1 && watchStepMMU[5]) | |
4108 | `PR_ERROR ("dbg_chk", `ERROR, "TID 5 too many redirects in SS mode when mmu_reload_done (%0d)",redirectCount5); | |
4109 | end | |
4110 | end | |
4111 | virtualPark[5] = 1; // should be in virtual park. starts parkedCheck0 | |
4112 | stepDone[5] = 1; | |
4113 | // if (!`SPC5.spu_tlu_cwq_busy && | |
4114 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
4115 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 5)) spuActive[5] = 0; | |
4116 | end | |
4117 | ||
4118 | if (stepAllowed[6]) begin | |
4119 | flushCount6 = 0; | |
4120 | redirectCount6 = 0; | |
4121 | watchStep6; // returns when inst is done | |
4122 | // got a flush, will be more activity | |
4123 | if (flushCount6 != 0) begin | |
4124 | while (!stepDone[6]) begin | |
4125 | @(negedge `SPC5.l2clk); | |
4126 | watchStep6; // returns when inst is done | |
4127 | if (flushCount6 > 2) | |
4128 | `PR_ERROR ("dbg_chk", `ERROR, "TID 6 too many flushes in SS mode (%0d)",flushCount6); | |
4129 | if (redirectCount6 > 2) | |
4130 | `PR_ERROR ("dbg_chk", `ERROR, "TID 6 too many redirects in SS mode (%0d)",redirectCount6); | |
4131 | if (redirectCount6 > 1 && watchStepMMU[6]) | |
4132 | `PR_ERROR ("dbg_chk", `ERROR, "TID 6 too many redirects in SS mode when mmu_reload_done (%0d)",redirectCount6); | |
4133 | end | |
4134 | end | |
4135 | virtualPark[6] = 1; // should be in virtual park. starts parkedCheck0 | |
4136 | stepDone[6] = 1; | |
4137 | // if (!`SPC5.spu_tlu_cwq_busy && | |
4138 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
4139 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 6)) spuActive[6] = 0; | |
4140 | end | |
4141 | ||
4142 | if (stepAllowed[7]) begin | |
4143 | flushCount7 = 0; | |
4144 | redirectCount7 = 0; | |
4145 | watchStep7; // returns when inst is done | |
4146 | // got a flush, will be more activity | |
4147 | if (flushCount7 != 0) begin | |
4148 | while (!stepDone[7]) begin | |
4149 | @(negedge `SPC5.l2clk); | |
4150 | watchStep7; // returns when inst is done | |
4151 | if (flushCount7 > 2) | |
4152 | `PR_ERROR ("dbg_chk", `ERROR, "TID 7 too many flushes in SS mode (%0d)",flushCount7); | |
4153 | if (redirectCount7 > 2) | |
4154 | `PR_ERROR ("dbg_chk", `ERROR, "TID 7 too many redirects in SS mode (%0d)",redirectCount7); | |
4155 | if (redirectCount7 > 1 && watchStepMMU[7]) | |
4156 | `PR_ERROR ("dbg_chk", `ERROR, "TID 7 too many redirects in SS mode when mmu_reload_done (%0d)",redirectCount7); | |
4157 | end | |
4158 | end | |
4159 | virtualPark[7] = 1; // should be in virtual park. starts parkedCheck0 | |
4160 | stepDone[7] = 1; | |
4161 | // if (!`SPC5.spu_tlu_cwq_busy && | |
4162 | // !(`SPC5.spu.mct.spu_pmu_ma_busy[3] && | |
4163 | // `SPC5.spu.mct.spu_pmu_ma_busy[2:0] == 7)) spuActive[7] = 0; | |
4164 | end | |
4165 | ||
4166 | ||
4167 | join | |
4168 | ||
4169 | ||
4170 | // redundant sanity check | |
4171 | if (stepDone[7:0] !== `SPC5.tlu.tcu_core_running[7:0]) | |
4172 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: SS mode stepDone not correct (%b/%b/%b stepAllowed,stepDone,core_running)!",stepAllowed, stepDone, `SPC5.tlu.tcu_core_running[7:0]); | |
4173 | ||
4174 | // DUT must assert ss_complete AND stay idle. timeout for ss_complete | |
4175 | // fork | |
4176 | // begin : FORK2 | |
4177 | // repeat (stepWaitTime) @(negedge `SPC5.l2clk); | |
4178 | // `PR_ERROR ("dbg_chk", `ERROR, "ERROR: Core did not assert ss_complete when it should have! Waited %0d clocks after watchStep return.",stepWaitTime); | |
4179 | // end | |
4180 | // @(posedge `SPC5.spc_ss_complete) disable FORK2; | |
4181 | // join | |
4182 | ||
4183 | // DUT must have asserted ss_complete | |
4184 | // if (!`SPC5.spc_ss_complete) | |
4185 | // `PR_ERROR ("dbg_chk", `ERROR, "ERROR: Not seeing ss_complete after all threads stepped. Checker problem?"); | |
4186 | ||
4187 | // all threads must be in virtual park state and quiesced | |
4188 | if (virtualPark[7:0] !== `SPC5.tlu.tcu_core_running[7:0]) | |
4189 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: Core at ss_complete assertion, threads were not idle."); | |
4190 | ||
4191 | `PR_DEBUG("dbg_chk", `DEBUG, "SS mode stepDone (%0d)!", stepCount); | |
4192 | ||
4193 | end // while | |
4194 | end | |
4195 | `PR_ALWAYS ("dbg_chk", `ALWAYS, "Ending Single Step mode (running step count: %0d!",stepCount); | |
4196 | end | |
4197 | end | |
4198 | ||
4199 | ||
4200 | always @(negedge `TOP.cpu.tcu_ss_mode[5]) begin | |
4201 | if (enabled) begin | |
4202 | `PR_DEBUG("dbg_chk", `DEBUG, "Clearing out Single Step mode state!"); | |
4203 | ssMode = 0; | |
4204 | stepAllowed = 0; | |
4205 | virtualPark = 0; | |
4206 | if (!(`SPC5.tcu_core_running[7:0] == 0 && | |
4207 | `SPC5.spc_core_running_status[7:0] == 8'h0)) | |
4208 | `PR_ERROR ("dbg_chk", `ERROR, "ERROR: All threads must be parked when disabling SS mode!"); | |
4209 | disable watchStep0; | |
4210 | disable watchStep1; | |
4211 | disable watchStep2; | |
4212 | disable watchStep3; | |
4213 | disable watchStep4; | |
4214 | disable watchStep5; | |
4215 | disable watchStep6; | |
4216 | disable watchStep7; | |
4217 | end | |
4218 | end | |
4219 | ||
4220 | ||
4221 | ||
4222 | ||
4223 | // TID 0 ifetch buffer check | |
4224 | // make sure that buffer zero is the only buffer valid. | |
4225 | // | |
4226 | always @(posedge `TOP.cpu.tcu_ss_mode[5] or posedge `TOP.cpu.tcu_do_mode[5]) begin | |
4227 | if (enabled) begin | |
4228 | while (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5]) begin | |
4229 | @(negedge `SPC5.l2clk); | |
4230 | if (`TOP.cpu.spc5.ifu_ibu.ibq0.buf_valid_p[7:1] != 0 && | |
4231 | `TOP.cpu.spc5.ifu_ibu.ibq0.instr_sf_valid_except_p == 0 && | |
4232 | `SPC5.tcu_core_running[0]) | |
4233 | `PR_ERROR ("dbg_chk", `ERROR, "TID 0 had ifetch buffer(s) valid other than zero (buf_valid_p[7:1]=%0b)!",`TOP.cpu.spc5.ifu_ibu.ibq0.buf_valid_p[7:1]); | |
4234 | end | |
4235 | end | |
4236 | end | |
4237 | ||
4238 | // TID 1 ifetch buffer check | |
4239 | // make sure that buffer zero is the only buffer valid. | |
4240 | // | |
4241 | always @(posedge `TOP.cpu.tcu_ss_mode[5] or posedge `TOP.cpu.tcu_do_mode[5]) begin | |
4242 | if (enabled) begin | |
4243 | while (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5]) begin | |
4244 | @(negedge `SPC5.l2clk); | |
4245 | if (`TOP.cpu.spc5.ifu_ibu.ibq1.buf_valid_p[7:1] != 0 && | |
4246 | `TOP.cpu.spc5.ifu_ibu.ibq1.instr_sf_valid_except_p == 0 && | |
4247 | `SPC5.tcu_core_running[1]) | |
4248 | `PR_ERROR ("dbg_chk", `ERROR, "TID 1 had ifetch buffer(s) valid other than zero (buf_valid_p[7:1]=%0b)!",`TOP.cpu.spc5.ifu_ibu.ibq1.buf_valid_p[7:1]); | |
4249 | end | |
4250 | end | |
4251 | end | |
4252 | ||
4253 | // TID 2 ifetch buffer check | |
4254 | // make sure that buffer zero is the only buffer valid. | |
4255 | // | |
4256 | always @(posedge `TOP.cpu.tcu_ss_mode[5] or posedge `TOP.cpu.tcu_do_mode[5]) begin | |
4257 | if (enabled) begin | |
4258 | while (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5]) begin | |
4259 | @(negedge `SPC5.l2clk); | |
4260 | if (`TOP.cpu.spc5.ifu_ibu.ibq2.buf_valid_p[7:1] != 0 && | |
4261 | `TOP.cpu.spc5.ifu_ibu.ibq2.instr_sf_valid_except_p == 0 && | |
4262 | `SPC5.tcu_core_running[2]) | |
4263 | `PR_ERROR ("dbg_chk", `ERROR, "TID 2 had ifetch buffer(s) valid other than zero (buf_valid_p[7:1]=%0b)!",`TOP.cpu.spc5.ifu_ibu.ibq2.buf_valid_p[7:1]); | |
4264 | end | |
4265 | end | |
4266 | end | |
4267 | ||
4268 | // TID 3 ifetch buffer check | |
4269 | // make sure that buffer zero is the only buffer valid. | |
4270 | // | |
4271 | always @(posedge `TOP.cpu.tcu_ss_mode[5] or posedge `TOP.cpu.tcu_do_mode[5]) begin | |
4272 | if (enabled) begin | |
4273 | while (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5]) begin | |
4274 | @(negedge `SPC5.l2clk); | |
4275 | if (`TOP.cpu.spc5.ifu_ibu.ibq3.buf_valid_p[7:1] != 0 && | |
4276 | `TOP.cpu.spc5.ifu_ibu.ibq3.instr_sf_valid_except_p == 0 && | |
4277 | `SPC5.tcu_core_running[3]) | |
4278 | `PR_ERROR ("dbg_chk", `ERROR, "TID 3 had ifetch buffer(s) valid other than zero (buf_valid_p[7:1]=%0b)!",`TOP.cpu.spc5.ifu_ibu.ibq3.buf_valid_p[7:1]); | |
4279 | end | |
4280 | end | |
4281 | end | |
4282 | ||
4283 | // TID 4 ifetch buffer check | |
4284 | // make sure that buffer zero is the only buffer valid. | |
4285 | // | |
4286 | always @(posedge `TOP.cpu.tcu_ss_mode[5] or posedge `TOP.cpu.tcu_do_mode[5]) begin | |
4287 | if (enabled) begin | |
4288 | while (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5]) begin | |
4289 | @(negedge `SPC5.l2clk); | |
4290 | if (`TOP.cpu.spc5.ifu_ibu.ibq4.buf_valid_p[7:1] != 0 && | |
4291 | `TOP.cpu.spc5.ifu_ibu.ibq4.instr_sf_valid_except_p == 0 && | |
4292 | `SPC5.tcu_core_running[4]) | |
4293 | `PR_ERROR ("dbg_chk", `ERROR, "TID 4 had ifetch buffer(s) valid other than zero (buf_valid_p[7:1]=%0b)!",`TOP.cpu.spc5.ifu_ibu.ibq4.buf_valid_p[7:1]); | |
4294 | end | |
4295 | end | |
4296 | end | |
4297 | ||
4298 | // TID 5 ifetch buffer check | |
4299 | // make sure that buffer zero is the only buffer valid. | |
4300 | // | |
4301 | always @(posedge `TOP.cpu.tcu_ss_mode[5] or posedge `TOP.cpu.tcu_do_mode[5]) begin | |
4302 | if (enabled) begin | |
4303 | while (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5]) begin | |
4304 | @(negedge `SPC5.l2clk); | |
4305 | if (`TOP.cpu.spc5.ifu_ibu.ibq5.buf_valid_p[7:1] != 0 && | |
4306 | `TOP.cpu.spc5.ifu_ibu.ibq5.instr_sf_valid_except_p == 0 && | |
4307 | `SPC5.tcu_core_running[5]) | |
4308 | `PR_ERROR ("dbg_chk", `ERROR, "TID 5 had ifetch buffer(s) valid other than zero (buf_valid_p[7:1]=%0b)!",`TOP.cpu.spc5.ifu_ibu.ibq5.buf_valid_p[7:1]); | |
4309 | end | |
4310 | end | |
4311 | end | |
4312 | ||
4313 | // TID 6 ifetch buffer check | |
4314 | // make sure that buffer zero is the only buffer valid. | |
4315 | // | |
4316 | always @(posedge `TOP.cpu.tcu_ss_mode[5] or posedge `TOP.cpu.tcu_do_mode[5]) begin | |
4317 | if (enabled) begin | |
4318 | while (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5]) begin | |
4319 | @(negedge `SPC5.l2clk); | |
4320 | if (`TOP.cpu.spc5.ifu_ibu.ibq6.buf_valid_p[7:1] != 0 && | |
4321 | `TOP.cpu.spc5.ifu_ibu.ibq6.instr_sf_valid_except_p == 0 && | |
4322 | `SPC5.tcu_core_running[6]) | |
4323 | `PR_ERROR ("dbg_chk", `ERROR, "TID 6 had ifetch buffer(s) valid other than zero (buf_valid_p[7:1]=%0b)!",`TOP.cpu.spc5.ifu_ibu.ibq6.buf_valid_p[7:1]); | |
4324 | end | |
4325 | end | |
4326 | end | |
4327 | ||
4328 | // TID 7 ifetch buffer check | |
4329 | // make sure that buffer zero is the only buffer valid. | |
4330 | // | |
4331 | always @(posedge `TOP.cpu.tcu_ss_mode[5] or posedge `TOP.cpu.tcu_do_mode[5]) begin | |
4332 | if (enabled) begin | |
4333 | while (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5]) begin | |
4334 | @(negedge `SPC5.l2clk); | |
4335 | if (`TOP.cpu.spc5.ifu_ibu.ibq7.buf_valid_p[7:1] != 0 && | |
4336 | `TOP.cpu.spc5.ifu_ibu.ibq7.instr_sf_valid_except_p == 0 && | |
4337 | `SPC5.tcu_core_running[7]) | |
4338 | `PR_ERROR ("dbg_chk", `ERROR, "TID 7 had ifetch buffer(s) valid other than zero (buf_valid_p[7:1]=%0b)!",`TOP.cpu.spc5.ifu_ibu.ibq7.buf_valid_p[7:1]); | |
4339 | end | |
4340 | end | |
4341 | end | |
4342 | ||
4343 | // TID 0 pipelineing check | |
4344 | // watch m stage and make sure that the tid does not have a valid inst | |
4345 | // there more often than every 9 clocks. counter must get to at least 9. | |
4346 | always @(posedge `TOP.cpu.tcu_ss_mode[5] or posedge `TOP.cpu.tcu_do_mode[5]) begin | |
4347 | if (enabled) begin | |
4348 | pipelineCount0 = 9; | |
4349 | while (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5]) begin | |
4350 | @(negedge `SPC5.l2clk); | |
4351 | if (`TOP.cpu.spc5.tlu.dec_tid0_m[1:0] == 0 && `TOP.cpu.spc5.tlu.dec_inst_valid_m[0] == 1 && `SPC5.tcu_core_running[0] && (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5])) begin | |
4352 | // have inst | |
4353 | if (pipelineCount0 < 9) begin | |
4354 | `PR_ERROR ("dbg_chk", `ERROR, "TID 0 had pipelining in DO or SS mode (pipelineCount=%0d)!",pipelineCount0); | |
4355 | //stall | |
4356 | @(negedge `TOP.cpu.tcu_ss_mode[5] or negedge `TOP.cpu.tcu_do_mode[5]); | |
4357 | end | |
4358 | pipelineCount0 = 0; // reset after each inst | |
4359 | end | |
4360 | else | |
4361 | // no new inst for tid yet | |
4362 | pipelineCount0 = pipelineCount0+1; | |
4363 | ||
4364 | end // while DO/SS mode | |
4365 | end // if | |
4366 | end // always | |
4367 | ||
4368 | ||
4369 | ||
4370 | // TID 1 pipelineing check | |
4371 | // watch m stage and make sure that the tid does not have a valid inst | |
4372 | // there more often than every 9 clocks. counter must get to at least 9. | |
4373 | always @(posedge `TOP.cpu.tcu_ss_mode[5] or posedge `TOP.cpu.tcu_do_mode[5]) begin | |
4374 | if (enabled) begin | |
4375 | pipelineCount1 = 9; | |
4376 | while (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5]) begin | |
4377 | @(negedge `SPC5.l2clk); | |
4378 | if (`TOP.cpu.spc5.tlu.dec_tid0_m[1:0] == 1 && `TOP.cpu.spc5.tlu.dec_inst_valid_m[0] == 1 && `SPC5.tcu_core_running[1] && (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5])) begin | |
4379 | // have inst | |
4380 | if (pipelineCount1 < 9) begin | |
4381 | `PR_ERROR ("dbg_chk", `ERROR, "TID 1 had pipelining in DO or SS mode (pipelineCount=%0d)!",pipelineCount1); | |
4382 | //stall | |
4383 | @(negedge `TOP.cpu.tcu_ss_mode[5] or negedge `TOP.cpu.tcu_do_mode[5]); | |
4384 | end | |
4385 | pipelineCount1 = 0; // reset after each inst | |
4386 | end | |
4387 | else | |
4388 | // no new inst for tid yet | |
4389 | pipelineCount1 = pipelineCount1+1; | |
4390 | ||
4391 | end // while DO/SS mode | |
4392 | end // if | |
4393 | end // always | |
4394 | ||
4395 | ||
4396 | ||
4397 | // TID 2 pipelineing check | |
4398 | // watch m stage and make sure that the tid does not have a valid inst | |
4399 | // there more often than every 9 clocks. counter must get to at least 9. | |
4400 | always @(posedge `TOP.cpu.tcu_ss_mode[5] or posedge `TOP.cpu.tcu_do_mode[5]) begin | |
4401 | if (enabled) begin | |
4402 | pipelineCount2 = 9; | |
4403 | while (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5]) begin | |
4404 | @(negedge `SPC5.l2clk); | |
4405 | if (`TOP.cpu.spc5.tlu.dec_tid0_m[1:0] == 2 && `TOP.cpu.spc5.tlu.dec_inst_valid_m[0] == 1 && `SPC5.tcu_core_running[2] && (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5])) begin | |
4406 | // have inst | |
4407 | if (pipelineCount2 < 9) begin | |
4408 | `PR_ERROR ("dbg_chk", `ERROR, "TID 2 had pipelining in DO or SS mode (pipelineCount=%0d)!",pipelineCount2); | |
4409 | //stall | |
4410 | @(negedge `TOP.cpu.tcu_ss_mode[5] or negedge `TOP.cpu.tcu_do_mode[5]); | |
4411 | end | |
4412 | pipelineCount2 = 0; // reset after each inst | |
4413 | end | |
4414 | else | |
4415 | // no new inst for tid yet | |
4416 | pipelineCount2 = pipelineCount2+1; | |
4417 | ||
4418 | end // while DO/SS mode | |
4419 | end // if | |
4420 | end // always | |
4421 | ||
4422 | ||
4423 | ||
4424 | // TID 3 pipelineing check | |
4425 | // watch m stage and make sure that the tid does not have a valid inst | |
4426 | // there more often than every 9 clocks. counter must get to at least 9. | |
4427 | always @(posedge `TOP.cpu.tcu_ss_mode[5] or posedge `TOP.cpu.tcu_do_mode[5]) begin | |
4428 | if (enabled) begin | |
4429 | pipelineCount3 = 9; | |
4430 | while (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5]) begin | |
4431 | @(negedge `SPC5.l2clk); | |
4432 | if (`TOP.cpu.spc5.tlu.dec_tid0_m[1:0] == 3 && `TOP.cpu.spc5.tlu.dec_inst_valid_m[0] == 1 && `SPC5.tcu_core_running[3] && (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5])) begin | |
4433 | // have inst | |
4434 | if (pipelineCount3 < 9) begin | |
4435 | `PR_ERROR ("dbg_chk", `ERROR, "TID 3 had pipelining in DO or SS mode (pipelineCount=%0d)!",pipelineCount3); | |
4436 | //stall | |
4437 | @(negedge `TOP.cpu.tcu_ss_mode[5] or negedge `TOP.cpu.tcu_do_mode[5]); | |
4438 | end | |
4439 | pipelineCount3 = 0; // reset after each inst | |
4440 | end | |
4441 | else | |
4442 | // no new inst for tid yet | |
4443 | pipelineCount3 = pipelineCount3+1; | |
4444 | ||
4445 | end // while DO/SS mode | |
4446 | end // if | |
4447 | end // always | |
4448 | ||
4449 | ||
4450 | ||
4451 | // TID 4 pipelineing check | |
4452 | // watch m stage and make sure that the tid does not have a valid inst | |
4453 | // there more often than every 9 clocks. counter must get to at least 9. | |
4454 | always @(posedge `TOP.cpu.tcu_ss_mode[5] or posedge `TOP.cpu.tcu_do_mode[5]) begin | |
4455 | if (enabled) begin | |
4456 | pipelineCount4 = 9; | |
4457 | while (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5]) begin | |
4458 | @(negedge `SPC5.l2clk); | |
4459 | if (`TOP.cpu.spc5.tlu.dec_tid1_m[1:0] == 0 && `TOP.cpu.spc5.tlu.dec_inst_valid_m[1] == 1 && `SPC5.tcu_core_running[4] && (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5])) begin | |
4460 | // have inst | |
4461 | if (pipelineCount4 < 9) begin | |
4462 | `PR_ERROR ("dbg_chk", `ERROR, "TID 4 had pipelining in DO or SS mode (pipelineCount=%0d)!",pipelineCount4); | |
4463 | //stall | |
4464 | @(negedge `TOP.cpu.tcu_ss_mode[5] or negedge `TOP.cpu.tcu_do_mode[5]); | |
4465 | end | |
4466 | pipelineCount4 = 0; // reset after each inst | |
4467 | end | |
4468 | else | |
4469 | // no new inst for tid yet | |
4470 | pipelineCount4 = pipelineCount4+1; | |
4471 | ||
4472 | end // while DO/SS mode | |
4473 | end // if | |
4474 | end // always | |
4475 | ||
4476 | ||
4477 | ||
4478 | // TID 5 pipelineing check | |
4479 | // watch m stage and make sure that the tid does not have a valid inst | |
4480 | // there more often than every 9 clocks. counter must get to at least 9. | |
4481 | always @(posedge `TOP.cpu.tcu_ss_mode[5] or posedge `TOP.cpu.tcu_do_mode[5]) begin | |
4482 | if (enabled) begin | |
4483 | pipelineCount5 = 9; | |
4484 | while (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5]) begin | |
4485 | @(negedge `SPC5.l2clk); | |
4486 | if (`TOP.cpu.spc5.tlu.dec_tid1_m[1:0] == 1 && `TOP.cpu.spc5.tlu.dec_inst_valid_m[1] == 1 && `SPC5.tcu_core_running[5] && (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5])) begin | |
4487 | // have inst | |
4488 | if (pipelineCount5 < 9) begin | |
4489 | `PR_ERROR ("dbg_chk", `ERROR, "TID 5 had pipelining in DO or SS mode (pipelineCount=%0d)!",pipelineCount5); | |
4490 | //stall | |
4491 | @(negedge `TOP.cpu.tcu_ss_mode[5] or negedge `TOP.cpu.tcu_do_mode[5]); | |
4492 | end | |
4493 | pipelineCount5 = 0; // reset after each inst | |
4494 | end | |
4495 | else | |
4496 | // no new inst for tid yet | |
4497 | pipelineCount5 = pipelineCount5+1; | |
4498 | ||
4499 | end // while DO/SS mode | |
4500 | end // if | |
4501 | end // always | |
4502 | ||
4503 | ||
4504 | ||
4505 | // TID 6 pipelineing check | |
4506 | // watch m stage and make sure that the tid does not have a valid inst | |
4507 | // there more often than every 9 clocks. counter must get to at least 9. | |
4508 | always @(posedge `TOP.cpu.tcu_ss_mode[5] or posedge `TOP.cpu.tcu_do_mode[5]) begin | |
4509 | if (enabled) begin | |
4510 | pipelineCount6 = 9; | |
4511 | while (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5]) begin | |
4512 | @(negedge `SPC5.l2clk); | |
4513 | if (`TOP.cpu.spc5.tlu.dec_tid1_m[1:0] == 2 && `TOP.cpu.spc5.tlu.dec_inst_valid_m[1] == 1 && `SPC5.tcu_core_running[6] && (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5])) begin | |
4514 | // have inst | |
4515 | if (pipelineCount6 < 9) begin | |
4516 | `PR_ERROR ("dbg_chk", `ERROR, "TID 6 had pipelining in DO or SS mode (pipelineCount=%0d)!",pipelineCount6); | |
4517 | //stall | |
4518 | @(negedge `TOP.cpu.tcu_ss_mode[5] or negedge `TOP.cpu.tcu_do_mode[5]); | |
4519 | end | |
4520 | pipelineCount6 = 0; // reset after each inst | |
4521 | end | |
4522 | else | |
4523 | // no new inst for tid yet | |
4524 | pipelineCount6 = pipelineCount6+1; | |
4525 | ||
4526 | end // while DO/SS mode | |
4527 | end // if | |
4528 | end // always | |
4529 | ||
4530 | ||
4531 | ||
4532 | // TID 7 pipelineing check | |
4533 | // watch m stage and make sure that the tid does not have a valid inst | |
4534 | // there more often than every 9 clocks. counter must get to at least 9. | |
4535 | always @(posedge `TOP.cpu.tcu_ss_mode[5] or posedge `TOP.cpu.tcu_do_mode[5]) begin | |
4536 | if (enabled) begin | |
4537 | pipelineCount7 = 9; | |
4538 | while (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5]) begin | |
4539 | @(negedge `SPC5.l2clk); | |
4540 | if (`TOP.cpu.spc5.tlu.dec_tid1_m[1:0] == 3 && `TOP.cpu.spc5.tlu.dec_inst_valid_m[1] == 1 && `SPC5.tcu_core_running[7] && (`TOP.cpu.tcu_ss_mode[5] || `TOP.cpu.tcu_do_mode[5])) begin | |
4541 | // have inst | |
4542 | if (pipelineCount7 < 9) begin | |
4543 | `PR_ERROR ("dbg_chk", `ERROR, "TID 7 had pipelining in DO or SS mode (pipelineCount=%0d)!",pipelineCount7); | |
4544 | //stall | |
4545 | @(negedge `TOP.cpu.tcu_ss_mode[5] or negedge `TOP.cpu.tcu_do_mode[5]); | |
4546 | end | |
4547 | pipelineCount7 = 0; // reset after each inst | |
4548 | end | |
4549 | else | |
4550 | // no new inst for tid yet | |
4551 | pipelineCount7 = pipelineCount7+1; | |
4552 | ||
4553 | end // while DO/SS mode | |
4554 | end // if | |
4555 | end // always | |
4556 | ||
4557 | ||
4558 | // commit output for each thread group | |
4559 | always @(negedge `SPC5.l2clk) begin | |
4560 | ||
4561 | if (!noCmtCheck && enabled) begin | |
4562 | if (cmtValid0) cmtCount0 = cmtCount0 + 1; | |
4563 | ||
4564 | // should we see non zero this cycle? | |
4565 | if (cmtValid0 !== `TOP.cpu.spc5.tlu_dbg_instr_cmt_grp0[1:0]) begin | |
4566 | `PR_ERROR ("dbg_chk", `ERROR, "tlu_dbg_instr_cmt_grp0 not right, (cmtValid0=%0h, tlu_dbg_instr_cmt_grp0=%0h)",cmtValid0,`TOP.cpu.spc5.tlu_dbg_instr_cmt_grp0[1:0]); | |
4567 | `PR_ALWAYS ("dbg_chk", `ALWAYS, "tlu_dbg_instr_cmt_grp0 not right, IF THE VALUE IS X, SPC IS NOT RESET OR SOME SPC INPUT IS X!"); | |
4568 | end | |
4569 | ||
4570 | // should see non zero next cycle | |
4571 | if (`TOP.cpu.spc5.tlu.fls0.inst_valid_w && | |
4572 | !(`TOP.cpu.spc5.tlu.fls0.flush_ifu[3:0] & | |
4573 | `TOP.cpu.spc5.tlu.fls0.tid_dec_w[3:0])) begin | |
4574 | if (`TOP.cpu.spc5.tlu.fls0.cti_w) cmtValid0 = 1; | |
4575 | else if (`TOP.cpu.spc5.tlu.fls0.lsu_inst_w) cmtValid0 = 3; | |
4576 | else cmtValid0 = 2; | |
4577 | end | |
4578 | else cmtValid0 = 0; | |
4579 | end | |
4580 | end | |
4581 | ||
4582 | // commit output for each thread group | |
4583 | always @(negedge `SPC5.l2clk) begin | |
4584 | ||
4585 | if (!noCmtCheck && enabled) begin | |
4586 | if (cmtValid1) cmtCount1 = cmtCount1 + 1; | |
4587 | ||
4588 | // should we see non zero this cycle? | |
4589 | if (cmtValid1 !== `TOP.cpu.spc5.tlu_dbg_instr_cmt_grp1[1:0]) begin | |
4590 | `PR_ERROR ("dbg_chk", `ERROR, "tlu_dbg_instr_cmt_grp1 not right, (cmtValid1=%0h, tlu_dbg_instr_cmt_grp1=%0h)",cmtValid1,`TOP.cpu.spc5.tlu_dbg_instr_cmt_grp1[1:0]); | |
4591 | `PR_ALWAYS ("dbg_chk", `ALWAYS, "tlu_dbg_instr_cmt_grp1 not right, IF THE VALUE IS X, SPC IS NOT RESET OR SOME SPC INPUT IS X!"); | |
4592 | end | |
4593 | ||
4594 | // should see non zero next cycle | |
4595 | if (`TOP.cpu.spc5.tlu.fls1.inst_valid_w && | |
4596 | !(`TOP.cpu.spc5.tlu.fls1.flush_ifu[3:0] & | |
4597 | `TOP.cpu.spc5.tlu.fls1.tid_dec_w[3:0])) begin | |
4598 | if (`TOP.cpu.spc5.tlu.fls1.cti_w) cmtValid1 = 1; | |
4599 | else if (`TOP.cpu.spc5.tlu.fls1.lsu_inst_w) cmtValid1 = 3; | |
4600 | else cmtValid1 = 2; | |
4601 | end | |
4602 | else cmtValid1 = 0; | |
4603 | end | |
4604 | end | |
4605 | ||
4606 | ||
4607 | // second count tid 0 | |
4608 | always @(negedge `SPC5.l2clk) begin | |
4609 | if(`TOP.nas_top.c5.t0.complete_fw2[7:0]) cmtCountT0 = cmtCountT0+1; | |
4610 | if(`TOP.nas_top.c5.t1.complete_fw2[7:0]) cmtCountT1 = cmtCountT1+1; | |
4611 | if(`TOP.nas_top.c5.t2.complete_fw2[7:0]) cmtCountT2 = cmtCountT2+1; | |
4612 | if(`TOP.nas_top.c5.t3.complete_fw2[7:0]) cmtCountT3 = cmtCountT3+1; | |
4613 | end | |
4614 | ||
4615 | // always @(`TOP.sim_status) begin | |
4616 | // if (!noCmtCheck && enabled) begin | |
4617 | // `PR_ALWAYS ("dbg_chk", `ALWAYS, "Final commit count for group 0 is %0d!",cmtCount0); | |
4618 | // `PR_ALWAYS ("dbg_chk", `ALWAYS, "Final commit count for group 1 is %0d!",cmtCount1); | |
4619 | // `PR_ALWAYS ("dbg_chk", `ALWAYS, "Final commit count for groups is %0d!",cmtCount0+cmtCount1); | |
4620 | // `PR_ALWAYS ("dbg_chk", `ALWAYS, "Final nas pipe complete_fw2 count for T0 is %0d!",cmtCountT0); | |
4621 | // `PR_ALWAYS ("dbg_chk", `ALWAYS, "Final nas pipe complete_fw2 count for T1 is %0d!",cmtCountT1); | |
4622 | // `PR_ALWAYS ("dbg_chk", `ALWAYS, "Final nas pipe complete_fw2 count for T2 is %0d!",cmtCountT2); | |
4623 | // `PR_ALWAYS ("dbg_chk", `ALWAYS, "Final nas pipe complete_fw2 count for T3 is %0d!",cmtCountT3); | |
4624 | // end | |
4625 | // end | |
4626 | ||
4627 | ||
4628 | endmodule |