Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: systemTapClass.vr | |
4 | // Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved | |
5 | // 4150 Network Circle, Santa Clara, California 95054, U.S.A. | |
6 | // | |
7 | // * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
8 | // | |
9 | // This program is free software; you can redistribute it and/or modify | |
10 | // it under the terms of the GNU General Public License as published by | |
11 | // the Free Software Foundation; version 2 of the License. | |
12 | // | |
13 | // This program is distributed in the hope that it will be useful, | |
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | // GNU General Public License for more details. | |
17 | // | |
18 | // You should have received a copy of the GNU General Public License | |
19 | // along with this program; if not, write to the Free Software | |
20 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 | // | |
22 | // For the avoidance of doubt, and except that if any non-GPL license | |
23 | // choice is available it will apply instead, Sun elects to use only | |
24 | // the General Public License version 2 (GPLv2) at this time for any | |
25 | // software where a choice of GPL license versions is made | |
26 | // available with the language indicating that GPLv2 or any later version | |
27 | // may be used, or where a choice of which version of the GPL is applied is | |
28 | // otherwise unspecified. | |
29 | // | |
30 | // Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
31 | // CA 95054 USA or visit www.sun.com if you need additional information or | |
32 | // have any questions. | |
33 | // | |
34 | // ========== Copyright Header End ============================================ | |
35 | #include <vera_defines.vrh> | |
36 | #include <std_display_class.vrh> | |
37 | ||
38 | // TAP specific defines | |
39 | #include <systemTapDefines.vri> | |
40 | ||
41 | // jtag interface | |
42 | #include <systemTap.if.vri> | |
43 | ||
44 | #define CLASSNAME BaseSystemTap | |
45 | ||
46 | extern hdl_task force_tlrState(); | |
47 | extern hdl_task release_tlrState(); | |
48 | ||
49 | class CLASSNAME { | |
50 | protected bit [3:0] tap_state_reg; | |
51 | protected string dispmonScope; | |
52 | protected StandardDisplay dbg; | |
53 | public tap__port tap_port; | |
54 | protected bit genTlrGlitch; | |
55 | ||
56 | task new ( | |
57 | StandardDisplay dbgIn | |
58 | ); | |
59 | function string BinToChar ( | |
60 | bit inbit | |
61 | ); | |
62 | function string cnv2str ( | |
63 | bit [127:0] data, | |
64 | integer w | |
65 | ); | |
66 | function string cnv_instr_2_text ( | |
67 | string instr | |
68 | ); | |
69 | function string state_id_2_text ( | |
70 | bit [3:0] id | |
71 | ); | |
72 | function string cnv_domain_2_string ( | |
73 | bit [2:0] domain | |
74 | ); | |
75 | function bit [3:0] advance_tap_state_reg ( | |
76 | bit tms | |
77 | ); | |
78 | function bit [15:0] ieeeTap ( | |
79 | bit [3:0] current_state | |
80 | ); | |
81 | task TapDrive_test_mode ( | |
82 | bit test_mode | |
83 | ); | |
84 | task TapDrive_trst_n ( | |
85 | bit trst_n | |
86 | ); | |
87 | task TapDrive_tms ( | |
88 | bit tms | |
89 | ); | |
90 | task TapDrive_tdi ( | |
91 | bit tdi | |
92 | ); | |
93 | task TapDriveAdvance_tms ( | |
94 | bit tms | |
95 | ); | |
96 | task TapResetType1 ( | |
97 | ); | |
98 | task TapResetType2 ( | |
99 | ); | |
100 | task check_tck_state ( | |
101 | ); | |
102 | task TapGoto ( | |
103 | bit [3:0] next_state | |
104 | ); | |
105 | function bit TapNext ( | |
106 | bit [3:0] advance, | |
107 | bit tdi | |
108 | ); | |
109 | task TapCaptureData ( | |
110 | ); | |
111 | function string TapIRLoad ( | |
112 | string instr, | |
113 | integer len=8, | |
114 | bit check=1 | |
115 | ); | |
116 | function bit TapShiftDR_tdi_advance ( | |
117 | bit tdi | |
118 | ); | |
119 | function string TapDRLoad ( | |
120 | string TapIn | |
121 | ); | |
122 | function string TapDRGet ( | |
123 | integer w | |
124 | ); | |
125 | function integer TapWait4DataRdy ( | |
126 | integer time_out_limit | |
127 | ); | |
128 | function integer TapWait4L2DataRdy ( | |
129 | integer time_out_limit | |
130 | ); | |
131 | function integer loadUndef ( | |
132 | string aUndef | |
133 | ); | |
134 | function integer loadBypass ( | |
135 | string aBypass | |
136 | ); | |
137 | function integer loadIdcode ( | |
138 | string aIdcode | |
139 | ); | |
140 | function integer loadExtest ( | |
141 | string aExtest | |
142 | ); | |
143 | function integer checkIdcode ( | |
144 | ); | |
145 | task Delay ( | |
146 | integer count | |
147 | ); | |
148 | task toggleDutTck ( | |
149 | ); | |
150 | task posedge2Dut ( | |
151 | ); | |
152 | task negedge2Dut ( | |
153 | ); | |
154 | ||
155 | task waitVeraRefTapStateRegChange ( // wait for the variable tap_state_reg changed | |
156 | ); | |
157 | function bit [3:0] getVeraRefTapStateReg () { getVeraRefTapStateReg = tap_state_reg; } | |
158 | task enableTlrStateGlitch( | |
159 | ); | |
160 | task disableTlrStateGlitch( | |
161 | ); | |
162 | } | |
163 | ||
164 | task CLASSNAME::new(StandardDisplay dbgIn) { | |
165 | dispmonScope = "SystemTap"; | |
166 | tap_port = tap_bind; | |
167 | dbg = dbgIn; | |
168 | dbg.dispmon(dispmonScope, MON_INFO, "$Id: systemTapClass.vr,v 1.1.1.1 2007/02/13 22:21:19 drp Exp $"); | |
169 | ||
170 | tap_state_reg = 4'bx; | |
171 | tap_port.$test_mode = 1'b0 soft async; // JTAG debug mode unless told to goto manufacturing test | |
172 | tap_port.$trst_n = 1'bx soft async; | |
173 | tap_port.$tdi = 1'bx soft async; | |
174 | tap_port.$tck2dut = 1'b0 soft async; | |
175 | tap_port.$tms = 1'b1 soft async; | |
176 | dbg.dispmon(dispmonScope, MON_INFO, "WARNING: systemTapClass.vr will not reset the TAP. runRstSequence method of sys_reset.vr class needs to be called to properly reset N2 as per PRM spec"); | |
177 | if (!get_plus_arg(CHECK, "noJtagTapReset")) { | |
178 | dbg.dispmon(dispmonScope, MON_INFO, "WARNING: systemTapClass.vr : skip calling TapResetType1() to reset TAP"); | |
179 | // Drive TRST_L 0 | |
180 | // TRST_L will be de-asserted by sys_reset.vr reset sequence task | |
181 | // TapDrive_trst_n(1'b0); | |
182 | } | |
183 | if (get_plus_arg(CHECK, "disableTlrGlitch")) { | |
184 | dbg.dispmon(dispmonScope, MON_ALWAYS, psprintf("Monitoring for glitch-generating transitions on jtag tap_state") ); | |
185 | genTlrGlitch = 1'b0; | |
186 | } | |
187 | else { | |
188 | genTlrGlitch = 1'b1; | |
189 | } | |
190 | } | |
191 | ||
192 | function string CLASSNAME::BinToChar(bit inbit) { | |
193 | if(inbit === 1'b1) BinToChar = "1"; | |
194 | if(inbit === 1'b0) BinToChar = "0"; | |
195 | if(inbit === 1'bx) BinToChar = "x"; | |
196 | if(inbit === 1'bz) BinToChar = "z"; | |
197 | } | |
198 | ||
199 | // | |
200 | //// Should we improve this? This must be slow esp. on long chains -csr | |
201 | //// These should use string function... | |
202 | function string CLASSNAME::cnv2str(bit [127:0] data, integer w) { | |
203 | integer i; | |
204 | string s = ""; | |
205 | ||
206 | for ( i=0; i<w; i++ ){ | |
207 | if (data[i] == 0) | |
208 | sprintf (s, "%s%s", "0", s); | |
209 | else if (data[i] == 1) | |
210 | sprintf (s, "%s%s", "1", s); | |
211 | else | |
212 | sprintf (s, "%s%s", "x", s); | |
213 | } | |
214 | cnv2str = s; | |
215 | } | |
216 | ||
217 | function string CLASSNAME::cnv_instr_2_text(string instr) { | |
218 | case (instr) { | |
219 | ||
220 | // JTAG Public | |
221 | TAP_BYPASS_INST : cnv_instr_2_text = "TAP_BYPASS_INST"; | |
222 | TAP_EXTEST_INST : cnv_instr_2_text = "TAP_EXTEST_INST"; | |
223 | TAP_IDCODE_INST : cnv_instr_2_text = "TAP_IDCODE_INST"; | |
224 | TAP_SAMPLE_INST : cnv_instr_2_text = "TAP_SAMPLE_INST"; | |
225 | TAP_HIGHZ_INST : cnv_instr_2_text = "TAP_HIGHZ_INST"; | |
226 | TAP_CLAMP_INST : cnv_instr_2_text = "TAP_CLAMP_INST"; | |
227 | ||
228 | // JTAG Private UCB | |
229 | TAP_CREG_ADDR : cnv_instr_2_text = "TAP_CREG_ADDR"; | |
230 | TAP_CREG_WDATA : cnv_instr_2_text = "TAP_CREG_WDATA"; | |
231 | TAP_CREG_RDATA : cnv_instr_2_text = "TAP_CREG_RDATA"; | |
232 | TAP_CREG_SCRATCH : cnv_instr_2_text = "TAP_CREG_SCRATCH"; | |
233 | TAP_NCU_WRITE : cnv_instr_2_text = "TAP_NCU_WRITE"; | |
234 | TAP_NCU_READ : cnv_instr_2_text = "TAP_NCU_READ"; | |
235 | TAP_NCU_WADDR : cnv_instr_2_text = "TAP_NCU_WADDR"; | |
236 | TAP_NCU_WDATA : cnv_instr_2_text = "TAP_NCU_WDATA"; | |
237 | TAP_NCU_RADDR : cnv_instr_2_text = "TAP_NCU_RADDR"; | |
238 | ||
239 | // JTAG Private L2 access | |
240 | TAP_L2_ADDR : cnv_instr_2_text = "TAP_L2_ADDR"; | |
241 | TAP_L2_WRDATA : cnv_instr_2_text = "TAP_L2_WRDATA"; | |
242 | TAP_L2_WR : cnv_instr_2_text = "TAP_L2_WR"; | |
243 | TAP_L2_RD : cnv_instr_2_text = "TAP_L2_RD"; | |
244 | ||
245 | // JTAG Private MBIST | |
246 | TAP_MBIST_BYPASS : cnv_instr_2_text = "TAP_MBIST_BYPASS"; | |
247 | TAP_MBIST_MODE : cnv_instr_2_text = "TAP_MBIST_MODE"; | |
248 | TAP_MBIST_START : cnv_instr_2_text = "TAP_MBIST_START"; | |
249 | TAP_MBIST_RESULT : cnv_instr_2_text = "TAP_MBIST_RESULT"; | |
250 | TAP_MBIST_DIAG : cnv_instr_2_text = "TAP_MBIST_DIAG"; | |
251 | TAP_MBIST_GETDONE : cnv_instr_2_text = "TAP_MBIST_GETDONE"; | |
252 | TAP_MBIST_GETFAIL : cnv_instr_2_text = "TAP_MBIST_GETFAIL"; | |
253 | TAP_MBIST_ABORT : cnv_instr_2_text = "TAP_MBIST_ABORT"; | |
254 | ||
255 | // JTAG Private Shadow SCAN | |
256 | TAP_SPCTHR0_SHSCAN : cnv_instr_2_text = "TAP_SPCTHR0_SHSCAN"; | |
257 | TAP_SPCTHR1_SHSCAN : cnv_instr_2_text = "TAP_SPCTHR1_SHSCAN"; | |
258 | TAP_SPCTHR2_SHSCAN : cnv_instr_2_text = "TAP_SPCTHR2_SHSCAN"; | |
259 | TAP_SPCTHR3_SHSCAN : cnv_instr_2_text = "TAP_SPCTHR3_SHSCAN"; | |
260 | TAP_SPCTHR4_SHSCAN : cnv_instr_2_text = "TAP_SPCTHR4_SHSCAN"; | |
261 | TAP_SPCTHR5_SHSCAN : cnv_instr_2_text = "TAP_SPCTHR5_SHSCAN"; | |
262 | TAP_SPCTHR6_SHSCAN : cnv_instr_2_text = "TAP_SPCTHR6_SHSCAN"; | |
263 | TAP_SPCTHR7_SHSCAN : cnv_instr_2_text = "TAP_SPCTHR7_SHSCAN"; | |
264 | ||
265 | // JTAG Private Clock Stop | |
266 | TAP_CLOCK_SSTOP : cnv_instr_2_text = "TAP_CLOCK_SSTOP"; | |
267 | TAP_CLOCK_HSTOP : cnv_instr_2_text = "TAP_CLOCK_HSTOP"; | |
268 | TAP_CLOCK_START : cnv_instr_2_text = "TAP_CLOCK_START"; | |
269 | TAP_CLOCK_DOMAIN : cnv_instr_2_text = "TAP_CLOCK_DOMAIN"; | |
270 | TAP_CLOCK_STATUS : cnv_instr_2_text = "TAP_CLOCK_STATUS"; | |
271 | TAP_CLKSTP_DELAY : cnv_instr_2_text = "TAP_CLKSTP_DELAY"; | |
272 | TAP_CORE_SEL : cnv_instr_2_text = "TAP_CORE_SEL"; | |
273 | TAP_DE_COUNT : cnv_instr_2_text = "TAP_DE_COUNT"; | |
274 | TAP_CYCLE_COUNT : cnv_instr_2_text = "TAP_CYCLE_COUNT"; | |
275 | TAP_TCU_DCR : cnv_instr_2_text = "TAP_TCU_DCR"; | |
276 | TAP_CORE_RUN_STATUS : cnv_instr_2_text = "TAP_CORE_RUN_STATUS"; | |
277 | ||
278 | // JTAG Private SCAN | |
279 | TAP_SERSCAN : cnv_instr_2_text = "TAP_SERSCAN"; | |
280 | TAP_CHAINSEL : cnv_instr_2_text = "TAP_CHAINSEL"; | |
281 | TAP_SCAN_SERIAL : cnv_instr_2_text = "TAP_SCAN_SERIAL"; | |
282 | TAP_SCAN_SERIAL_SEL : cnv_instr_2_text = "TAP_SCAN_SERIAL_SEL"; | |
283 | ||
284 | // JTAG Private EFUSE | |
285 | TAP_FUSE_READ : cnv_instr_2_text = "TAP_FUSE_READ"; | |
286 | TAP_FUSE_BYPASS_DATA : cnv_instr_2_text = "TAP_FUSE_BYPASS_DATA"; | |
287 | TAP_FUSE_BYPASS : cnv_instr_2_text = "TAP_FUSE_BYPASS"; | |
288 | TAP_FUSE_ROW_ADDR : cnv_instr_2_text = "TAP_FUSE_ROW_ADDR"; | |
289 | TAP_FUSE_COL_ADDR : cnv_instr_2_text = "TAP_FUSE_COL_ADDR"; | |
290 | TAP_FUSE_READ_MODE : cnv_instr_2_text = "TAP_FUSE_READ_MODE"; | |
291 | TAP_FUSE_DEST_SAMPLE : cnv_instr_2_text = "TAP_FUSE_DEST_SAMPLE"; | |
292 | ||
293 | default : cnv_instr_2_text = "*** UNDEFINED ***"; | |
294 | } | |
295 | } | |
296 | ||
297 | function string CLASSNAME::state_id_2_text (bit [3:0] id) { | |
298 | case (id) { | |
299 | TAP_RESET : state_id_2_text = "Test-Logic-Reset"; | |
300 | TAP_CAPTURE_IR : state_id_2_text = "Capture-IR"; | |
301 | TAP_UPDATE_IR : state_id_2_text = "Update-IR"; | |
302 | TAP_IDLE : state_id_2_text = "Run-Test-Idle"; | |
303 | TAP_PAUSE_IR : state_id_2_text = "Pause-IR"; | |
304 | TAP_SHIFT_IR : state_id_2_text = "Shift-IR"; | |
305 | TAP_EXIT1_IR : state_id_2_text = "Exit1-IR"; | |
306 | TAP_EXIT2_IR : state_id_2_text = "Exit2-IR"; | |
307 | TAP_SELECT_DR : state_id_2_text = "Select-DR-Scan"; | |
308 | TAP_CAPTURE_DR : state_id_2_text = "Capture-DR"; | |
309 | TAP_UPDATE_DR : state_id_2_text = "Update-DR"; | |
310 | TAP_SELECT_IR : state_id_2_text = "Select-IR-Scan"; | |
311 | TAP_PAUSE_DR : state_id_2_text = "Pause-DR"; | |
312 | TAP_SHIFT_DR : state_id_2_text = "Shift-DR"; | |
313 | TAP_EXIT1_DR : state_id_2_text = "Exit1-DR"; | |
314 | TAP_EXIT2_DR : state_id_2_text = "Exit2-DR"; | |
315 | default : state_id_2_text = "*** Unknown ***"; | |
316 | } | |
317 | } | |
318 | ||
319 | function string CLASSNAME::cnv_domain_2_string ( bit [2:0] domain ) { | |
320 | if (domain[0]) cnv_domain_2_string = "Application"; | |
321 | else if (domain[1:0] == 2'b00) cnv_domain_2_string = "Multi-Step "; | |
322 | else if (domain == 3'b010) cnv_domain_2_string = "PLL Bypass "; | |
323 | else if (domain == 3'b110) cnv_domain_2_string = "Test/TCK "; | |
324 | } | |
325 | ||
326 | //-------- Show where we are going given next TMS ---------- | |
327 | function bit [3:0] CLASSNAME::advance_tap_state_reg (bit tms) { | |
328 | case (tap_state_reg) { | |
329 | TAP_RESET: advance_tap_state_reg = tms ? TAP_RESET : TAP_IDLE; | |
330 | TAP_CAPTURE_IR: advance_tap_state_reg = tms ? TAP_EXIT1_IR : TAP_SHIFT_IR; | |
331 | TAP_UPDATE_IR: | |
332 | { | |
333 | if (tms) { | |
334 | if (genTlrGlitch) { | |
335 | fork | |
336 | { | |
337 | dbg.dispmon(dispmonScope, MON_ALWAYS, psprintf("Glitching tlr tap_state, tap_state: %s", state_id_2_text(tap_state_reg)) ); | |
338 | force_tlrState(); | |
339 | } | |
340 | join none | |
341 | } | |
342 | advance_tap_state_reg = TAP_SELECT_DR; | |
343 | } | |
344 | else { | |
345 | advance_tap_state_reg = TAP_IDLE; | |
346 | } | |
347 | } | |
348 | TAP_IDLE: | |
349 | { | |
350 | if (tms) { | |
351 | if (genTlrGlitch) { | |
352 | fork | |
353 | { | |
354 | dbg.dispmon(dispmonScope, MON_ALWAYS, psprintf("Glitching tlr tap_state, tap_state: %s", state_id_2_text(tap_state_reg)) ); | |
355 | force_tlrState(); | |
356 | } | |
357 | join none | |
358 | } | |
359 | advance_tap_state_reg = TAP_SELECT_DR; | |
360 | } | |
361 | else { | |
362 | advance_tap_state_reg = TAP_IDLE; | |
363 | } | |
364 | } | |
365 | TAP_PAUSE_IR: advance_tap_state_reg = tms ? TAP_EXIT2_IR : TAP_PAUSE_IR; | |
366 | TAP_SHIFT_IR: advance_tap_state_reg = tms ? TAP_EXIT1_IR : TAP_SHIFT_IR; | |
367 | TAP_EXIT1_IR: advance_tap_state_reg = tms ? TAP_UPDATE_IR : TAP_PAUSE_IR; | |
368 | TAP_EXIT2_IR: advance_tap_state_reg = tms ? TAP_UPDATE_IR : TAP_SHIFT_IR; | |
369 | TAP_SELECT_DR: advance_tap_state_reg = tms ? TAP_SELECT_IR : TAP_CAPTURE_DR; | |
370 | TAP_CAPTURE_DR: advance_tap_state_reg = tms ? TAP_EXIT1_DR : TAP_SHIFT_DR; | |
371 | TAP_UPDATE_DR: advance_tap_state_reg = tms ? TAP_SELECT_DR : TAP_IDLE; | |
372 | TAP_SELECT_IR: advance_tap_state_reg = tms ? TAP_RESET : TAP_CAPTURE_IR; | |
373 | TAP_PAUSE_DR: advance_tap_state_reg = tms ? TAP_EXIT2_DR : TAP_PAUSE_DR; | |
374 | TAP_SHIFT_DR: advance_tap_state_reg = tms ? TAP_EXIT1_DR : TAP_SHIFT_DR; | |
375 | TAP_EXIT1_DR: advance_tap_state_reg = tms ? TAP_UPDATE_DR : TAP_PAUSE_DR; | |
376 | TAP_EXIT2_DR: advance_tap_state_reg = tms ? TAP_UPDATE_DR : TAP_SHIFT_DR; | |
377 | default: | |
378 | dbg.dispmon(dispmonScope, MON_ERR, psprintf("TAP register invalid/out of range: 4'b%4b", tap_state_reg)); | |
379 | } | |
380 | } | |
381 | ||
382 | //-------- Walk over the IEEE 1149.1.2001 state machine ---------- | |
383 | function bit [15:0] CLASSNAME::ieeeTap(bit [3:0] current_state) { | |
384 | case (current_state) { | |
385 | // N2: 111111 | |
386 | // N2: 5432109876543210 | |
387 | TAP_RESET: ieeeTap = 16'b1000000000000000; // 15 | |
388 | TAP_CAPTURE_IR: ieeeTap = 16'b1x11101111111111; // 14 | |
389 | TAP_UPDATE_IR: ieeeTap = 16'b11x0111111111111; // 13 | |
390 | TAP_IDLE: ieeeTap = 16'b1110111111111111; // 12 | |
391 | TAP_PAUSE_IR: ieeeTap = 16'b1111011111111111; // 11 | |
392 | TAP_SHIFT_IR: ieeeTap = 16'b1111101111111111; // 10 | |
393 | TAP_EXIT1_IR: ieeeTap = 16'b111100x011111111; // 9 | |
394 | TAP_EXIT2_IR: ieeeTap = 16'b1111000x11111111; // 8 | |
395 | TAP_SELECT_DR: ieeeTap = 16'b11111111x0010000; // 7 | |
396 | TAP_CAPTURE_DR: ieeeTap = 16'b111111111x111011; // 6 | |
397 | TAP_UPDATE_DR: ieeeTap = 16'b1110111111x11111; // 5 | |
398 | TAP_SELECT_IR: ieeeTap = 16'b10010000111x1111; // 4 | |
399 | TAP_PAUSE_DR: ieeeTap = 16'b1111111111110111; // 3 | |
400 | TAP_SHIFT_DR: ieeeTap = 16'b1111111111111011; // 2 | |
401 | TAP_EXIT1_DR: ieeeTap = 16'b11111111111100x0; // 1 | |
402 | TAP_EXIT2_DR: ieeeTap = 16'b111111111111000x; // 0 | |
403 | } | |
404 | } | |
405 | ||
406 | task CLASSNAME::TapDrive_test_mode(bit test_mode) { | |
407 | dbg.dispmon(dispmonScope, MON_INFO, psprintf("TAP test_mode=%0d", test_mode)); | |
408 | fork | |
409 | { | |
410 | tap_port.$test_mode = test_mode; | |
411 | } | |
412 | { | |
413 | toggleDutTck(); | |
414 | } | |
415 | join | |
416 | terminate; | |
417 | } | |
418 | ||
419 | //-------- The function should not do any @posedge ---------- | |
420 | task CLASSNAME::TapDrive_trst_n(bit trst_n) { | |
421 | dbg.dispmon(dispmonScope, MON_INFO, psprintf("TAP trst_n=%0d", trst_n)); | |
422 | // Make TRST_L asyncronous | |
423 | delay(32'hffff & random()); // Pick a random time unit wait | |
424 | fork | |
425 | { | |
426 | tap_port.$trst_n = trst_n async; // Drive the TRST_L | |
427 | } | |
428 | join | |
429 | terminate; | |
430 | tap_state_reg = TAP_RESET; | |
431 | } | |
432 | ||
433 | //-------- The function should not do any @posedge ---------- | |
434 | task CLASSNAME::TapDrive_tms(bit tms) { | |
435 | dbg.dispmon(dispmonScope, MON_INFO, psprintf("TAP tms=%0d", tms)); | |
436 | fork | |
437 | { | |
438 | tap_port.$tms = tms; | |
439 | } | |
440 | { | |
441 | tap_port.$tdi = 1'bx; | |
442 | } | |
443 | { | |
444 | toggleDutTck(); | |
445 | } | |
446 | join | |
447 | terminate; | |
448 | } | |
449 | ||
450 | task CLASSNAME::TapDriveAdvance_tms(bit tms) { | |
451 | TapDrive_tms(tms); | |
452 | toggleDutTck(); | |
453 | tap_state_reg = advance_tap_state_reg(tms); | |
454 | } | |
455 | ||
456 | task CLASSNAME::TapDrive_tdi(bit tdi) { | |
457 | dbg.dispmon(dispmonScope, MON_INFO, psprintf("TAP tdi=%0d", tdi)); | |
458 | fork | |
459 | { | |
460 | tap_port.$tdi = tdi; | |
461 | } | |
462 | { | |
463 | toggleDutTck(); | |
464 | } | |
465 | join | |
466 | terminate; | |
467 | } | |
468 | ||
469 | task CLASSNAME::TapResetType1() { | |
470 | dbg.dispmon(dispmonScope, MON_INFO, "TAP Resetting (default PLL values) ..."); | |
471 | TapDrive_trst_n(1'b0); | |
472 | TapDrive_tms(1'b1); // Remain in test-logic-reset after trst_n deassert | |
473 | tap_state_reg = 4'hx; | |
474 | TapDrive_trst_n(1'b1); | |
475 | tap_state_reg = TAP_RESET; | |
476 | } | |
477 | ||
478 | task CLASSNAME::TapResetType2() { | |
479 | // Potential here to randomize -csr | |
480 | // Give ourselves some arbitrary TAP state | |
481 | tap_state_reg = TAP_PAUSE_IR; | |
482 | TapDrive_trst_n(1'b1); // Disable the trst_n pin | |
483 | repeat (5) TapDriveAdvance_tms(1'b1); // IEEE 1149.1.2001; 5 cycle to reset | |
484 | } | |
485 | ||
486 | task CLASSNAME::check_tck_state() { | |
487 | if (tap_port.$tck2dut != 1'b1) { | |
488 | case (tap_state_reg) { | |
489 | TAP_RESET, TAP_IDLE : | |
490 | { | |
491 | dbg.dispmon(dispmonScope, MON_INFO, "Advancing tck"); | |
492 | toggleDutTck(); | |
493 | } | |
494 | default : | |
495 | dbg.dispmon(dispmonScope, MON_ERR, psprintf("Unable to correct tck state: 4'b%4b", tap_state_reg)); | |
496 | } | |
497 | } | |
498 | } | |
499 | ||
500 | task CLASSNAME::TapGoto (bit [3:0] next_state) { | |
501 | bit [15:0] datatemp; | |
502 | bit tms; | |
503 | ||
504 | dbg.dispmon(dispmonScope, MON_INFO, psprintf("TAP CURRENT: [%s], GOTO: [%s]" | |
505 | , state_id_2_text(tap_state_reg) | |
506 | , state_id_2_text(next_state))); | |
507 | if (tap_state_reg === 4'hx) dbg.dispmon(dispmonScope, MON_ERR, "Unknown TAP state!"); | |
508 | ||
509 | check_tck_state(); | |
510 | while (tap_state_reg != next_state) { | |
511 | datatemp = ieeeTap(tap_state_reg); | |
512 | tms = datatemp[next_state]; | |
513 | fork | |
514 | { | |
515 | tap_port.$tms = tms; | |
516 | } | |
517 | { | |
518 | toggleDutTck(); | |
519 | } | |
520 | join | |
521 | terminate; | |
522 | tap_state_reg = advance_tap_state_reg(tms); | |
523 | dbg.dispmon(dispmonScope, MON_DEBUG, psprintf("(%0d) %s", tms, state_id_2_text(tap_state_reg))); | |
524 | } | |
525 | case (next_state) { | |
526 | TAP_PAUSE_IR, TAP_PAUSE_DR : | |
527 | { | |
528 | dbg.dispmon(dispmonScope, MON_INFO, psprintf("RANDOM DELAY in TAP state: %s", state_id_2_text(next_state))); | |
529 | Delay(random()%6); // stay in pause state random intervals | |
530 | } | |
531 | TAP_SHIFT_IR, TAP_SHIFT_DR : | |
532 | tap_port.$tdi <= 1'b0 async; | |
533 | } | |
534 | } | |
535 | ||
536 | function bit CLASSNAME::TapNext(bit [3:0] advance, bit tdi) { | |
537 | bit tms; | |
538 | bit tdo_out; | |
539 | check_tck_state(); | |
540 | ||
541 | if (advance == TAP_NEXT_ADVANCE) | |
542 | case (tap_state_reg) { | |
543 | TAP_SHIFT_DR : tms = 1'b1; | |
544 | TAP_PAUSE_DR : tms = 1'b1; | |
545 | TAP_SHIFT_IR : tms = 1'b1; | |
546 | TAP_PAUSE_IR : tms = 1'b1; | |
547 | default : dbg.dispmon(dispmonScope, MON_ERR, psprintf("Doesn't know where to advance to (%s)", state_id_2_text(tap_state_reg))); | |
548 | } | |
549 | else | |
550 | // remain in current state | |
551 | case (tap_state_reg) { | |
552 | TAP_SHIFT_DR : tms = 1'b0; | |
553 | TAP_PAUSE_DR : tms = 1'b0; | |
554 | TAP_SHIFT_IR : tms = 1'b0; | |
555 | TAP_PAUSE_IR : tms = 1'b0; | |
556 | default : | |
557 | { | |
558 | dbg.dispmon(dispmonScope, MON_ERR, psprintf("Cannot remain in current state (%s)", state_id_2_text(tap_state_reg))); | |
559 | } | |
560 | } | |
561 | fork | |
562 | { | |
563 | tap_port.$tdi = tdi; | |
564 | } | |
565 | { | |
566 | tap_port.$tms = tms; | |
567 | } | |
568 | { | |
569 | tdo_out = tap_port.$tdo; | |
570 | } | |
571 | { | |
572 | toggleDutTck(); | |
573 | } | |
574 | join | |
575 | terminate; | |
576 | tap_state_reg = advance_tap_state_reg(tms); | |
577 | TapNext = tdo_out; | |
578 | } | |
579 | ||
580 | task CLASSNAME::TapCaptureData () { | |
581 | dbg.dispmon(dispmonScope, MON_INFO, "TapCaptureData"); | |
582 | TapGoto(TAP_EXIT1_DR); | |
583 | TapGoto(TAP_PAUSE_DR); | |
584 | dbg.dispmon(dispmonScope, MON_INFO, "... Done TapCaptureData"); | |
585 | } | |
586 | ||
587 | function string CLASSNAME::TapIRLoad(string instr, integer len=8, bit check=1) { | |
588 | integer i; | |
589 | integer remain; | |
590 | string TapOut = ""; | |
591 | bit [1:0] lsbMandatory = 2'b01; | |
592 | bit [127:0] b; | |
593 | bit tdo_out; | |
594 | ||
595 | if (len != 8) { | |
596 | len = instr.len(); | |
597 | } | |
598 | b = instr.atobin(); | |
599 | dbg.dispmon(dispmonScope, MON_INFO, psprintf("8'b%8b (%s) ==> IR", b, cnv_instr_2_text(instr))); | |
600 | ||
601 | remain = random()%len; | |
602 | ||
603 | if (! get_plus_arg(CHECK, "skip_tap_random_pause")) { | |
604 | if (remain) { | |
605 | TapGoto(TAP_PAUSE_IR); | |
606 | } | |
607 | } | |
608 | ||
609 | if (tap_state_reg != TAP_SHIFT_IR) TapGoto(TAP_SHIFT_IR); | |
610 | for (i=0; i<len; i++) { | |
611 | tdo_out = TapNext((i == len-1) ? TAP_NEXT_ADVANCE : TAP_NEXT_REMAIN, b[i]); | |
612 | sprintf(TapOut, "%s%s", BinToChar(tdo_out), TapOut); | |
613 | } | |
614 | tap_port.$tdi <= 1'bx; | |
615 | TapGoto(TAP_PAUSE_IR); | |
616 | ||
617 | if (check) { | |
618 | // Check that the LSB after the IR capture equals the mandatory 2'b01 -csr | |
619 | b = TapOut.atobin(); | |
620 | dbg.dispmon(dispmonScope, MON_INFO, psprintf("IR ==> 'b%0b", b)); | |
621 | if (b[1:0] != lsbMandatory) { | |
622 | dbg.dispmon(dispmonScope, MON_ERR, psprintf("LSB of scanned IR ('b%0b) does not match mandatory 2'b01", b)); | |
623 | } | |
624 | } | |
625 | TapIRLoad = TapOut; | |
626 | } | |
627 | ||
628 | function bit CLASSNAME::TapShiftDR_tdi_advance(bit tdi) { | |
629 | bit tdo_out; | |
630 | ||
631 | dbg.dispmon(dispmonScope, MON_INFO, psprintf("Shifting TDI: %0b", tdi)); | |
632 | if (tap_state_reg != TAP_SHIFT_DR) TapGoto(TAP_SHIFT_DR); | |
633 | tdo_out = TapNext(TAP_NEXT_ADVANCE, tdi); | |
634 | TapShiftDR_tdi_advance = tdo_out; | |
635 | } | |
636 | ||
637 | function string CLASSNAME::TapDRLoad(string TapIn) { | |
638 | integer i, len, index, from, to, numDiv, remain; | |
639 | string outbit, tmpStr; | |
640 | string tdo_data = ""; | |
641 | bit tdo_out; | |
642 | bit [127:0] b; | |
643 | ||
644 | len = TapIn.len(); | |
645 | numDiv = len/128; | |
646 | remain = len%128; | |
647 | dbg.dispmon(dispmonScope, MON_INFO, psprintf("'b%0b ==> DR", TapIn)); | |
648 | ||
649 | if (! get_plus_arg(CHECK, "skip_tap_random_pause")) { | |
650 | if (random()%len) { | |
651 | TapGoto(TAP_PAUSE_DR); | |
652 | } | |
653 | } | |
654 | ||
655 | if (tap_state_reg != TAP_SHIFT_DR) TapGoto(TAP_SHIFT_DR); | |
656 | if (numDiv != 0) { | |
657 | for(index=0; index<numDiv; index++) { | |
658 | // TDO - TDI order last bit shifted-in first (TapIn[len]) | |
659 | to = len-((index*128)+1); | |
660 | from = to-127; | |
661 | tmpStr = TapIn.substr(from, to); | |
662 | b = tmpStr.atobin(); | |
663 | if (tap_state_reg != TAP_SHIFT_DR) TapGoto(TAP_SHIFT_DR); | |
664 | for(i=0; i<128; i++) { | |
665 | tdo_out = TapNext((i == 127) ? TAP_NEXT_ADVANCE : TAP_NEXT_REMAIN, b[i]); | |
666 | sprintf(tdo_data ,"%s%s", BinToChar(tdo_out), tdo_data); | |
667 | } | |
668 | tap_port.$tdi <= 1'bx; | |
669 | TapGoto(TAP_PAUSE_DR); | |
670 | } | |
671 | } | |
672 | if (remain != 0) { | |
673 | if (tap_state_reg != TAP_SHIFT_DR) TapGoto(TAP_SHIFT_DR); | |
674 | // TDO - TDI order last bit shifted-in first (TapIn[len]) | |
675 | from = 0; | |
676 | to = remain -1; | |
677 | tmpStr = TapIn.substr(from, to); | |
678 | b = tmpStr.atobin(); | |
679 | for(i=0; i<remain; i++) { | |
680 | tdo_out = TapNext((i == remain-1) ? TAP_NEXT_ADVANCE : TAP_NEXT_REMAIN, b[i]); | |
681 | sprintf(tdo_data ,"%s%s", BinToChar(tdo_out), tdo_data); | |
682 | } | |
683 | tap_port.$tdi <= 1'bx; | |
684 | TapGoto(TAP_PAUSE_DR); | |
685 | } | |
686 | dbg.dispmon(dispmonScope, MON_INFO, psprintf("DR ==> 'b%s", tdo_data)); | |
687 | TapDRLoad = tdo_data; | |
688 | } | |
689 | ||
690 | function string CLASSNAME::TapDRGet(integer w) { | |
691 | integer i; | |
692 | string get_data = ""; | |
693 | bit tdo_out; | |
694 | ||
695 | dbg.dispmon(dispmonScope, MON_INFO, psprintf("TapDRGet (w=%0d)", w)); | |
696 | ||
697 | if (tap_state_reg != TAP_SHIFT_DR) TapGoto(TAP_SHIFT_DR); | |
698 | for (i=0; i<w; i++) { | |
699 | tdo_out = TapNext((i == w-1) ? TAP_NEXT_ADVANCE : TAP_NEXT_REMAIN, 0); | |
700 | sprintf(get_data, "%s%s", BinToChar(tdo_out), get_data); | |
701 | } | |
702 | tap_port.$tdi <= 1'bx; | |
703 | TapGoto(TAP_PAUSE_DR); | |
704 | ||
705 | TapDRGet = get_data; | |
706 | } | |
707 | ||
708 | //-------- Wait for an NCU read return -------------- | |
709 | // System controller gives read error if timeout occurs | |
710 | function integer CLASSNAME::TapWait4DataRdy(integer time_out_limit) { | |
711 | integer i; | |
712 | bit tdo_out; | |
713 | ||
714 | dbg.dispmon(dispmonScope, MON_INFO, psprintf("TAP UCB wait (TCK timeout: %0d cycles)", time_out_limit)); | |
715 | fork | |
716 | tdo_out = tap_port.$tdo; | |
717 | toggleDutTck(); | |
718 | join | |
719 | terminate; | |
720 | // Wait for the so-called 'sentinel' bit 65; TDO will remain 1'b0 until the read is available | |
721 | // at which time the TDO is set to 1'b1 | |
722 | for (i=0; i < time_out_limit && tdo_out !== 1'b1; i++) { | |
723 | fork | |
724 | tdo_out = tap_port.$tdo; | |
725 | toggleDutTck(); // Continue scanning the TDO until it goes high | |
726 | join | |
727 | terminate; | |
728 | } | |
729 | TapWait4DataRdy = (i >= time_out_limit); | |
730 | } | |
731 | ||
732 | //-------- Wait for L2 read return -------------- | |
733 | // System controller gives read error if timeout occurs | |
734 | function integer CLASSNAME::TapWait4L2DataRdy(integer time_out_limit) { | |
735 | integer i; | |
736 | bit tdo_out; | |
737 | ||
738 | dbg.dispmon(dispmonScope, MON_INFO, psprintf("TAP L2 wait (TCK timeout: %0d cycles)", time_out_limit)); | |
739 | fork | |
740 | tdo_out = tap_port.$tdo; | |
741 | toggleDutTck(); | |
742 | join | |
743 | terminate; | |
744 | // Wait for the so-called 'sentinel' bit 65; TDO will remain 1'b0 until the read is available | |
745 | // at which time the TDO is set to 1'b1 | |
746 | for (i=0; i < time_out_limit && tdo_out !== 1'b1; i++) { | |
747 | fork | |
748 | tdo_out = tap_port.$tdo; | |
749 | toggleDutTck(); // Continue scanning the TDO until it goes high | |
750 | join | |
751 | terminate; | |
752 | TapGoto(TAP_UPDATE_DR); | |
753 | TapGoto(TAP_SHIFT_DR); | |
754 | } | |
755 | TapWait4L2DataRdy = (i >= time_out_limit); | |
756 | } | |
757 | ||
758 | //-------------- JTAG Public ---------------- | |
759 | function integer CLASSNAME::loadUndef(string aUndef) { | |
760 | // MSB 5432109876543210 LSB | |
761 | string TapIn = "1100001110001100"; // Choose an asymetric pattern | |
762 | string TapOut; | |
763 | bit [127:0] TapInB = TapIn.atobin(); | |
764 | bit [127:0] TapOutB; | |
765 | loadUndef = 0; | |
766 | ||
767 | TapOut = TapIRLoad(aUndef); | |
768 | TapOut = TapDRLoad(TapIn); | |
769 | TapOutB = TapOut.atobin(); | |
770 | if (TapOutB !== { TapInB[14:0], 1'b0 }) { // Bypass should always shift 1'b0 first | |
771 | dbg.dispmon(dispmonScope, MON_ALWAYS, psprintf("ERROR: Bypass out ('b%0b) does not match expected", TapOutB) ); | |
772 | loadUndef = 1; | |
773 | } | |
774 | } | |
775 | ||
776 | function integer CLASSNAME::loadBypass(string aBypass) { | |
777 | loadBypass = loadUndef(aBypass); | |
778 | } | |
779 | ||
780 | function integer CLASSNAME::loadIdcode(string aIdcode) { | |
781 | void = TapIRLoad(aIdcode); | |
782 | loadIdcode = checkIdcode(); | |
783 | } | |
784 | ||
785 | function integer CLASSNAME::loadExtest(string aExtest) { | |
786 | void = TapIRLoad(aExtest); | |
787 | TapGoto(TAP_SHIFT_DR); | |
788 | loadExtest = 0; | |
789 | } | |
790 | ||
791 | function integer CLASSNAME::checkIdcode() { | |
792 | // MSB 5432109876543210 LSB | |
793 | string TapIn = "1100001110001100"; // Choose an asymetric pattern | |
794 | string TapOut; | |
795 | bit [127:0] TapOutB; | |
796 | checkIdcode = 0; | |
797 | ||
798 | TapOut = TapDRLoad({TapIn, TapIn}); | |
799 | TapOutB = TapOut.atobin(); | |
800 | if (TapOutB !== {TAP_VERSION, TAP_PART_NUM, TAP_ID_NUM, 1'b1}) { | |
801 | dbg.dispmon(dispmonScope, MON_ALWAYS, psprintf("IDCODE ('b%0b) does not match expected", TapOutB) ); | |
802 | checkIdcode = 1; | |
803 | } | |
804 | } | |
805 | ||
806 | task CLASSNAME::Delay(integer count) { | |
807 | repeat(count) toggleDutTck(); | |
808 | } | |
809 | ||
810 | task CLASSNAME::toggleDutTck() { | |
811 | posedge2Dut(); | |
812 | negedge2Dut(); | |
813 | } | |
814 | ||
815 | task CLASSNAME::posedge2Dut() { | |
816 | @(posedge tap_port.$tck); | |
817 | tap_port.$tck2dut = 1'b1 async; | |
818 | } | |
819 | ||
820 | task CLASSNAME::negedge2Dut() { | |
821 | @(negedge tap_port.$tck); | |
822 | tap_port.$tck2dut = 1'b0 async; | |
823 | } | |
824 | ||
825 | // | |
826 | // WHAT: wait for tap state reg of the Vera Reference model changed. | |
827 | // | |
828 | task CLASSNAME::waitVeraRefTapStateRegChange() { | |
829 | wait_var(tap_state_reg); | |
830 | } | |
831 | ||
832 | task CLASSNAME::enableTlrStateGlitch() { | |
833 | this.genTlrGlitch = 1'b1; | |
834 | } | |
835 | ||
836 | task CLASSNAME::disableTlrStateGlitch() { | |
837 | this.genTlrGlitch = 1'b0; | |
838 | } | |
839 |