origen_jtag 0.20.0 → 0.21.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/config/commands.rb +3 -0
- data/config/version.rb +1 -1
- data/lib/origen_jtag/driver.rb +182 -112
- data/lib/origen_jtag_dev/new_style.rb +5 -6
- data/lib/origen_jtag_dev/serial.rb +24 -0
- data/pattern/jtag_workout.rb +10 -7
- data/templates/web/index.md.erb +99 -74
- data/templates/web/legacy.md.erb +43 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b15086a4ad3545ea9f62a1dfd03cbd478ba289d81cbe417ccbf6f66f0abb7741
|
4
|
+
data.tar.gz: d92e037cdc87ad03eb50cb0b480b1f2c0ea3ad658b2c5a8a607feace42f2f61a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7cea430f01d68431304365ea7a47c08e76ecb12d4292828b01c9e4407570fba2ce5c4d344f6e58466258d24ae9d140441b4b3fa8e7e10db3a3436f1f19852273
|
7
|
+
data.tar.gz: fd389e11272f958e1c930ffd99a974fdad3f405ae5fb24fb8bd2da4a7d5d3f445917daca8e84e3af9f0e258cf84ec461873468faf57ff749269352071634af66
|
data/config/commands.rb
CHANGED
@@ -93,6 +93,9 @@ when "examples", "test"
|
|
93
93
|
ARGV = %w(jtag_workout -t new_P4 -e v93k -r approved)
|
94
94
|
load "#{Origen.top}/lib/origen/commands/generate.rb"
|
95
95
|
|
96
|
+
ARGV = %w(jtag_workout -t serial_P1 -e v93k -r approved)
|
97
|
+
load "#{Origen.top}/lib/origen/commands/generate.rb"
|
98
|
+
|
96
99
|
if Origen.app.stats.changed_files == 0 &&
|
97
100
|
Origen.app.stats.new_files == 0 &&
|
98
101
|
Origen.app.stats.changed_patterns == 0 &&
|
data/config/version.rb
CHANGED
data/lib/origen_jtag/driver.rb
CHANGED
@@ -6,12 +6,12 @@ module OrigenJTAG
|
|
6
6
|
# state machine via the TAPController module.
|
7
7
|
#
|
8
8
|
# To use this driver the parent model must define the following pins (an alias is fine):
|
9
|
-
# :
|
9
|
+
# :tck
|
10
10
|
# :tdi
|
11
11
|
# :tdo
|
12
12
|
# :tms
|
13
13
|
class Driver
|
14
|
-
REQUIRED_PINS = [:
|
14
|
+
REQUIRED_PINS = [:tck, :tdi, :tdo, :tms]
|
15
15
|
|
16
16
|
include Origen::Model
|
17
17
|
include TAPController
|
@@ -23,10 +23,20 @@ module OrigenJTAG
|
|
23
23
|
# Returns the current value in the instruction register
|
24
24
|
attr_reader :ir_value
|
25
25
|
|
26
|
-
#
|
27
|
-
|
26
|
+
# The number of cycles for one clock pulse, assumes 50% duty cycle. Uses tester non-return format to spread TCK across multiple cycles.
|
27
|
+
# e.g. @tck_multiple = 2, @tck_format = :rh, means one cycle with Tck low (non-return), one with Tck high (NR)
|
28
|
+
# @tck_multiple = 4, @tck_format = :rl, means 2 cycles with Tck high (NR), 2 with Tck low (NR)
|
29
|
+
attr_accessor :tck_multiple
|
30
|
+
alias_method :tclk_multiple, :tck_multiple
|
31
|
+
alias_method :tclk_multiple=, :tck_multiple=
|
32
|
+
|
33
|
+
# Wave/timing format of the JTAG clock: :rh (ReturnHigh) or :rl (ReturnLo), :rh is the default
|
34
|
+
attr_accessor :tck_format
|
35
|
+
alias_method :tclk_format, :tck_format
|
36
|
+
alias_method :tclk_format=, :tck_format=
|
37
|
+
|
38
|
+
attr_reader :tdo_strobe
|
28
39
|
|
29
|
-
attr_accessor :tclk_format
|
30
40
|
# Set true to print out debug comments about all state transitions
|
31
41
|
attr_accessor :verbose
|
32
42
|
alias_method :verbose?, :verbose
|
@@ -41,24 +51,17 @@ module OrigenJTAG
|
|
41
51
|
else
|
42
52
|
@owner = owner
|
43
53
|
end
|
44
|
-
validate_pins(options)
|
45
|
-
|
46
54
|
# The parent can configure JTAG settings by defining this constant
|
47
55
|
if defined?(owner.class::JTAG_CONFIG)
|
48
56
|
options = owner.class::JTAG_CONFIG.merge(options)
|
49
57
|
end
|
50
58
|
|
59
|
+
@cycle_callback = options[:cycle_callback]
|
60
|
+
validate_pins(options) unless @cycle_callback
|
61
|
+
|
51
62
|
# Fallback defaults
|
52
63
|
options = {
|
53
64
|
verbose: false,
|
54
|
-
tclk_format: :rh, # format of JTAG clock used: ReturnHigh (:rh), ReturnLo (:rl)
|
55
|
-
tclk_multiple: 1, # number of cycles for one clock pulse, assumes 50% duty cycle. Uses tester non-return format to spread TCK across multiple cycles.
|
56
|
-
# e.g. @tclk_multiple = 2, @tclk_format = :rh, means one cycle with Tck low (non-return), one with Tck high (NR)
|
57
|
-
# @tclk_multiple = 4, @tclk_format = :rl, means 2 cycles with Tck high (NR), 2 with Tck low (NR)
|
58
|
-
tdo_strobe: :tclk_high, # when using multiple cycles for TCK, when to strobe for TDO, options include:
|
59
|
-
# :tclk_high - strobe TDO only when TCK is high
|
60
|
-
# :tclk_low - strobe TDO only when TCK is low
|
61
|
-
# :tclk_all - strobe TDO throughout TCK cycle
|
62
65
|
tdo_store_cycle: 0, # store vector cycle within TCK (i.e. when to indicate to tester to store vector within TCK cycle. 0 is first vector, 1 is second, etc.)
|
63
66
|
# NOTE: only when user indicates to store TDO, which will mean we don't care the 1 or 0 value on TDO (overriding effectively :tdo_strobe option above)
|
64
67
|
init_state: :unknown
|
@@ -68,18 +71,46 @@ module OrigenJTAG
|
|
68
71
|
|
69
72
|
@verbose = options[:verbose]
|
70
73
|
@ir_value = :unknown
|
71
|
-
@
|
72
|
-
@
|
73
|
-
|
74
|
+
@tck_format = options[:tck_format] || options[:tclk_format] || :rh
|
75
|
+
@tck_multiple = options[:tck_multiple] || options[:tclk_multiple] || 1
|
76
|
+
self.tdo_strobe = options[:tdo_strobe] || :tck_high
|
74
77
|
@tdo_store_cycle = options[:tdo_store_cycle]
|
75
78
|
@state = options[:init_state]
|
76
79
|
@log_state_changes = options[:log_state_changes] || false
|
77
|
-
if options[:tclk_vals]
|
78
|
-
@
|
79
|
-
unless @
|
80
|
-
fail "When specifying
|
80
|
+
if options[:tck_vals] || options[:tclk_vals]
|
81
|
+
@tck_vals = options[:tck_vals] || options[:tclk_vals]
|
82
|
+
unless @tck_vals.is_a?(Hash) && @tck_vals.key?(:on) && @tck_vals.key?(:off)
|
83
|
+
fail "When specifying TCK values, you must supply a hash with both :on and :off keys, e.g. tck_vals: { on: 'P', off: 0 }"
|
81
84
|
end
|
82
85
|
end
|
86
|
+
if @cycle_callback && @tck_multiple != 1
|
87
|
+
fail 'A cycle_callback can only be used with a tck_multiple setting of 1'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# when using multiple cycles for TCK, set when to strobe for TDO, options include:
|
92
|
+
# :tck_high - strobe TDO only when TCK is high (Default)
|
93
|
+
# :tck_low - strobe TDO only when TCK is low
|
94
|
+
# :tck_all - strobe TDO throughout TCK cycle
|
95
|
+
def tdo_strobe=(val)
|
96
|
+
case val
|
97
|
+
when :tck_high, :tclk_high
|
98
|
+
@tdo_strobe = :tck_high
|
99
|
+
when :tck_low, :tclk_low
|
100
|
+
@tdo_strobe = :tck_low
|
101
|
+
when :tck_all, :tclk_all
|
102
|
+
@tdo_strobe = :tck_all
|
103
|
+
else
|
104
|
+
fail 'tdo_strobe must be set to one of: :tck_high, :tck_low or :tck_all'
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# When true it means that the application is dealing with how to handle the 4 JTAG signals for each JTAG cycle.
|
109
|
+
# In that case this driver calculates what state the 4 pins should be in each signal and then calls back to the
|
110
|
+
# application with that information and it is up to the application to decide what to do with that information
|
111
|
+
# and when/if to generate tester cycles.
|
112
|
+
def cycle_callback?
|
113
|
+
!!@cycle_callback
|
83
114
|
end
|
84
115
|
|
85
116
|
# Shift data into the TDI pin or out of the TDO pin.
|
@@ -155,32 +186,32 @@ module OrigenJTAG
|
|
155
186
|
# loop through each data bit
|
156
187
|
last_overlay_label = ''
|
157
188
|
size.times do |i|
|
158
|
-
|
189
|
+
store_tdo_this_tck = false
|
159
190
|
|
160
|
-
# Set up pin actions for bit transaction (
|
191
|
+
# Set up pin actions for bit transaction (tck cycle)
|
161
192
|
|
162
193
|
# TDI
|
163
|
-
|
194
|
+
action :tdi, :drive, tdi_reg[i]
|
164
195
|
|
165
196
|
# TDO
|
166
|
-
|
197
|
+
action :tdo, :dont_care # default setting
|
167
198
|
if tdo_reg[i]
|
168
199
|
if tdo_reg[i].is_to_be_stored? # store
|
169
|
-
|
170
|
-
|
200
|
+
store_tdo_this_tck = true
|
201
|
+
action :tdo, :dont_care if Origen.tester.j750?
|
171
202
|
elsif tdo_reg[i].is_to_be_read? # compare/assert
|
172
|
-
|
203
|
+
action :tdo, :assert, tdo_reg[i], meta: { position: i }
|
173
204
|
end
|
174
205
|
end
|
175
206
|
|
176
207
|
# TMS
|
177
|
-
|
208
|
+
action :tms, :drive, 0
|
178
209
|
|
179
210
|
# let tester handle overlay if implemented
|
180
211
|
overlay_options = {}
|
181
|
-
if tester.respond_to?(:source_memory)
|
212
|
+
if tester.respond_to?(:source_memory) && !cycle_callback?
|
182
213
|
if ovl_reg[i] && ovl_reg[i].has_overlay? && !Origen.mode.simulation?
|
183
|
-
overlay_options[:pins] = @
|
214
|
+
overlay_options[:pins] = @pins[:tdi]
|
184
215
|
if global_ovl
|
185
216
|
overlay_options[:overlay_str] = global_ovl
|
186
217
|
else
|
@@ -194,8 +225,8 @@ module OrigenJTAG
|
|
194
225
|
end
|
195
226
|
end
|
196
227
|
tester_subr_overlay = !(options[:no_subr] || global_ovl) && tester.overlay_style == :subroutine
|
197
|
-
|
198
|
-
|
228
|
+
action :tdi, :drive, 0 if tester_subr_overlay
|
229
|
+
action :tdo, :assert, tdo_reg[i], meta: { position: i } if options[:read] unless tester_subr_overlay
|
199
230
|
# Force the last bit to be shifted from this method if overlay requested on the last bit
|
200
231
|
options[:cycle_last] = true if i == size - 1
|
201
232
|
end
|
@@ -208,18 +239,18 @@ module OrigenJTAG
|
|
208
239
|
$tester.label(ovl_reg[i].overlay_str)
|
209
240
|
last_overlay_label = ovl_reg[i].overlay_str
|
210
241
|
end
|
211
|
-
|
242
|
+
action :tdo, :assert, tdo_reg[i], meta: { position: i } if options[:read]
|
212
243
|
else
|
213
|
-
|
244
|
+
action :tdi, :drive, 0
|
214
245
|
call_subroutine = ovl_reg[i].overlay_str
|
215
246
|
end
|
216
247
|
end
|
217
248
|
end # of let tester handle overlay
|
218
249
|
|
219
|
-
# With JTAG pin actions queued up, use block call to
|
220
|
-
# execute a single
|
250
|
+
# With JTAG pin actions queued up, use block call to tck_cycle to
|
251
|
+
# execute a single TCK period. Special handling of subroutines,
|
221
252
|
# case of last bit in shift, and store vector (within a multi-cycle
|
222
|
-
#
|
253
|
+
# tck config).
|
223
254
|
if call_subroutine || tester_subr_overlay
|
224
255
|
@last_data_vector_shifted = true
|
225
256
|
else
|
@@ -234,25 +265,25 @@ module OrigenJTAG
|
|
234
265
|
if i != size - 1 || options[:cycle_last]
|
235
266
|
if i == size - 1 && options[:includes_last_bit]
|
236
267
|
unless tester_subr_overlay
|
237
|
-
|
268
|
+
action :tms, :drive, 1
|
238
269
|
@last_data_vector_shifted = true
|
239
270
|
end
|
240
271
|
end
|
241
|
-
|
242
|
-
if
|
243
|
-
|
272
|
+
tck_cycle do
|
273
|
+
if store_tdo_this_tck && @next_data_vector_to_be_stored
|
274
|
+
action :store
|
244
275
|
end
|
245
|
-
if overlay_options[:pins].nil?
|
246
|
-
|
276
|
+
if overlay_options[:pins].nil? || cycle_callback?
|
277
|
+
cycle
|
247
278
|
else
|
248
|
-
|
279
|
+
cycle overlay: overlay_options
|
249
280
|
overlay_options[:change_data] = false # data change only on first cycle if overlay
|
250
281
|
end
|
251
282
|
end
|
252
|
-
@
|
283
|
+
@pins[:tdo].dont_care unless cycle_callback?
|
253
284
|
else
|
254
285
|
@deferred_compare = true
|
255
|
-
@deferred_store = true if
|
286
|
+
@deferred_store = true if store_tdo_this_tck
|
256
287
|
end
|
257
288
|
end
|
258
289
|
end
|
@@ -264,101 +295,100 @@ module OrigenJTAG
|
|
264
295
|
Origen.tester.dont_compress = false if compression_on
|
265
296
|
end
|
266
297
|
|
267
|
-
# Cycles the tester through one
|
268
|
-
# Adjusts for the
|
298
|
+
# Cycles the tester through one TCK cycle
|
299
|
+
# Adjusts for the TCK format and cycle span
|
269
300
|
# Assumes caller will drive pattern to tester
|
270
301
|
# via .drive or similar
|
271
|
-
def
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
302
|
+
def tck_cycle
|
303
|
+
if cycle_callback?
|
304
|
+
@next_data_vector_to_be_stored = @tdo_store_cycle
|
305
|
+
yield
|
306
|
+
else
|
307
|
+
case @tck_format
|
308
|
+
when :rh
|
309
|
+
tck_val = 0
|
310
|
+
when :rl
|
311
|
+
tck_val = 1
|
312
|
+
else
|
313
|
+
fail 'ERROR: Invalid Tclk timing format!'
|
314
|
+
end
|
284
315
|
|
285
|
-
|
286
|
-
|
287
|
-
|
316
|
+
# determine whether to mask TDO on first half cycle
|
317
|
+
mask_tdo_half0 = ((@tck_format == :rl) && (@tdo_strobe == :tck_low) && (@tck_multiple > 1)) ||
|
318
|
+
((@tck_format == :rh) && (@tdo_strobe == :tck_high) && (@tck_multiple > 1))
|
288
319
|
|
289
|
-
|
290
|
-
|
320
|
+
# determine whether to mask TDO on second half cycle
|
321
|
+
mask_tdo_half1 = ((@tck_format == :rl) && (@tdo_strobe == :tck_high) && (@tck_multiple > 1)) ||
|
322
|
+
((@tck_format == :rh) && (@tdo_strobe == :tck_low) && (@tck_multiple > 1))
|
291
323
|
|
292
|
-
|
293
|
-
|
294
|
-
|
324
|
+
# If TDO is already suspended (by an application) then don't do the
|
325
|
+
# suspends below since the resume will clear the application's suspend
|
326
|
+
tdo_already_suspended = !cycle_callback? && @pins[:tdo].suspended? && !@tdo_suspended_by_driver
|
295
327
|
|
296
|
-
|
297
|
-
|
328
|
+
@tck_multiple.times do |i|
|
329
|
+
# 50% duty cycle if @tck_multiple is even, otherwise slightly off
|
298
330
|
|
299
|
-
|
331
|
+
@next_data_vector_to_be_stored = @tdo_store_cycle == i ? true : false
|
300
332
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
unless tdo_to_be_captured
|
333
|
+
if i < (@tck_multiple + 1) / 2
|
334
|
+
# first half of cycle
|
335
|
+
@pins[:tck].drive(@tck_vals ? @tck_vals[:on] : tck_val)
|
336
|
+
unless tdo_already_suspended
|
306
337
|
if mask_tdo_half0
|
307
338
|
@tdo_suspended_by_driver = true
|
308
|
-
@
|
339
|
+
@pins[:tdo].suspend
|
309
340
|
else
|
310
341
|
@tdo_suspended_by_driver = false
|
311
|
-
@
|
342
|
+
@pins[:tdo].resume
|
312
343
|
end
|
313
344
|
end
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
unless tdo_already_suspended
|
319
|
-
unless tdo_to_be_captured
|
345
|
+
else
|
346
|
+
# second half of cycle
|
347
|
+
@pins[:tck].drive(@tck_vals ? @tck_vals[:off] : (1 - tck_val))
|
348
|
+
unless tdo_already_suspended
|
320
349
|
if mask_tdo_half1
|
321
350
|
@tdo_suspended_by_driver = true
|
322
|
-
@
|
351
|
+
@pins[:tdo].suspend
|
323
352
|
else
|
324
353
|
@tdo_suspended_by_driver = false
|
325
|
-
@
|
354
|
+
@pins[:tdo].resume
|
326
355
|
end
|
327
356
|
end
|
328
357
|
end
|
358
|
+
yield
|
359
|
+
end
|
360
|
+
if @tdo_suspended_by_driver
|
361
|
+
@tdo_suspended_by_driver = false
|
362
|
+
@pins[:tdo].resume
|
329
363
|
end
|
330
|
-
yield
|
331
|
-
end
|
332
|
-
if @tdo_suspended_by_driver
|
333
|
-
@tdo_pin.resume
|
334
|
-
@tdo_suspended_by_driver = false
|
335
364
|
end
|
336
365
|
end
|
337
366
|
|
338
367
|
# Applies the given value to the TMS pin and then
|
339
|
-
# cycles the tester for one
|
368
|
+
# cycles the tester for one TCK
|
340
369
|
#
|
341
370
|
# @param [Integer] val Value to drive on the TMS pin, 0 or 1
|
342
371
|
def tms!(val)
|
343
372
|
if @deferred_compare
|
344
373
|
@deferred_compare = nil
|
345
374
|
else
|
346
|
-
|
375
|
+
action :tdo, :dont_care
|
347
376
|
end
|
348
377
|
|
349
378
|
if @deferred_store
|
350
379
|
@deferred_store = nil
|
351
|
-
|
380
|
+
store_tdo_this_tck = true
|
352
381
|
else
|
353
|
-
|
382
|
+
store_tdo_this_tck = false
|
354
383
|
end
|
355
384
|
@next_data_vector_to_be_stored = false
|
356
385
|
|
357
|
-
|
358
|
-
if
|
359
|
-
|
386
|
+
tck_cycle do
|
387
|
+
if store_tdo_this_tck && @next_data_vector_to_be_stored
|
388
|
+
action :store
|
360
389
|
end
|
361
|
-
|
390
|
+
action :tms, :drive, val
|
391
|
+
cycle
|
362
392
|
end
|
363
393
|
end
|
364
394
|
|
@@ -493,8 +523,44 @@ module OrigenJTAG
|
|
493
523
|
end
|
494
524
|
end
|
495
525
|
|
526
|
+
def apply_action(pin, actions)
|
527
|
+
actions.each do |operation|
|
528
|
+
method = operation.shift
|
529
|
+
pin.send(method, *operation) if method
|
530
|
+
end
|
531
|
+
end
|
532
|
+
|
496
533
|
private
|
497
534
|
|
535
|
+
def action(pin_id, *operations)
|
536
|
+
@actions ||= clear_actions
|
537
|
+
if pin_id == :store
|
538
|
+
@actions[:store] = true
|
539
|
+
else
|
540
|
+
fail "Unkown JTAG pin ID: #{pin_id}" unless @actions[pin_id]
|
541
|
+
@actions[pin_id] << operations
|
542
|
+
end
|
543
|
+
end
|
544
|
+
|
545
|
+
def cycle(options = {})
|
546
|
+
if @actions
|
547
|
+
if cycle_callback?
|
548
|
+
@owner.send(@cycle_callback, @actions, options)
|
549
|
+
else
|
550
|
+
apply_action(@pins[:tms], @actions[:tms])
|
551
|
+
apply_action(@pins[:tdi], @actions[:tdi])
|
552
|
+
apply_action(@pins[:tdo], @actions[:tdo])
|
553
|
+
tester.store_next_cycle(@pins[:tdo]) if @actions[:store]
|
554
|
+
tester.cycle(options)
|
555
|
+
end
|
556
|
+
clear_actions
|
557
|
+
end
|
558
|
+
end
|
559
|
+
|
560
|
+
def clear_actions
|
561
|
+
@actions = { tdi: [], tms: [], tdo: [], store: false }
|
562
|
+
end
|
563
|
+
|
498
564
|
# Return size of transaction. Options[:size] has priority and need not match the
|
499
565
|
# register size. Any mismatch will be handled by the api.
|
500
566
|
def extract_size(reg_or_val, options = {})
|
@@ -601,15 +667,19 @@ module OrigenJTAG
|
|
601
667
|
# Validates that the parent object (the owner) has defined the necessary
|
602
668
|
# pins to implement the JTAG
|
603
669
|
def validate_pins(options)
|
604
|
-
@
|
605
|
-
@
|
606
|
-
@
|
607
|
-
@
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
@
|
670
|
+
@pins = {}
|
671
|
+
@pins[:tck] = options[:tck_pin]
|
672
|
+
@pins[:tdi] = options[:tdi_pin]
|
673
|
+
@pins[:tdo] = options[:tdo_pin]
|
674
|
+
@pins[:tms] = options[:tms_pin]
|
675
|
+
|
676
|
+
# Support legacy implementation where tck was incorrectly called tclk, in case of both being
|
677
|
+
# defined then :tck has priority
|
678
|
+
@pins[:tck] ||= @owner.pin(:tck) if @owner.has_pin?(:tck)
|
679
|
+
@pins[:tck] ||= @owner.pin(:tclk)
|
680
|
+
@pins[:tdi] ||= @owner.pin(:tdi)
|
681
|
+
@pins[:tdo] ||= @owner.pin(:tdo)
|
682
|
+
@pins[:tms] ||= @owner.pin(:tms)
|
613
683
|
rescue
|
614
684
|
puts 'Missing JTAG pins!'
|
615
685
|
puts "In order to use the JTAG driver your #{owner.class} class must either define"
|
@@ -617,7 +687,7 @@ module OrigenJTAG
|
|
617
687
|
puts REQUIRED_PINS
|
618
688
|
puts '-- or --'
|
619
689
|
puts 'Pass the pins in the initialization options:'
|
620
|
-
puts "sub_block :jtag, class_name: 'OrigenJTAG::Driver', tck_pin: dut.pin(:
|
690
|
+
puts "sub_block :jtag, class_name: 'OrigenJTAG::Driver', tck_pin: dut.pin(:tck), tdi_pin: dut.pin(:tdi), tdo_pin: dut.pin(:tdo), tms_pin: dut.pin(:tms)"
|
621
691
|
raise 'JTAG driver error!'
|
622
692
|
end
|
623
693
|
end
|
@@ -24,6 +24,7 @@ module OrigenJTAGDev
|
|
24
24
|
@jtag_config[:tdo_store_cycle] = options[:tdo_store_cycle] if options[:tdo_store_cycle]
|
25
25
|
@jtag_config[:init_state] = options[:init_state] if options[:init_state]
|
26
26
|
@jtag_config[:tclk_vals] = options[:tclk_vals] if options[:tclk_vals]
|
27
|
+
@jtag_config[:cycle_callback] = options[:cycle_callback] if options[:cycle_callback]
|
27
28
|
|
28
29
|
instantiate_registers(options)
|
29
30
|
instantiate_pins(options)
|
@@ -50,12 +51,10 @@ module OrigenJTAGDev
|
|
50
51
|
end
|
51
52
|
|
52
53
|
def instantiate_pins(options = {})
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
add_pin :tclk
|
54
|
+
add_pin :tclk
|
55
|
+
unless options[:invalid_pins]
|
56
|
+
add_pin :tdi
|
57
57
|
end
|
58
|
-
add_pin :tdi
|
59
58
|
add_pin :tdo
|
60
59
|
add_pin :tms
|
61
60
|
|
@@ -101,7 +100,7 @@ module OrigenJTAGDev
|
|
101
100
|
@jtag_config[:init_state]
|
102
101
|
end
|
103
102
|
|
104
|
-
# Wouldn't want to do this in reality, but allows some flexibility
|
103
|
+
# Wouldn't want to do this in reality, but allows some flexibility during gem testing
|
105
104
|
def update_jtag_config(cfg, val)
|
106
105
|
if @jtag_config.key?(cfg)
|
107
106
|
@jtag_config[cfg] = val
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module OrigenJTAGDev
|
2
|
+
# This is a dummy DUT model which is used
|
3
|
+
# to instantiate and test the JTAG locally
|
4
|
+
# during development.
|
5
|
+
#
|
6
|
+
# It is not included when this library is imported.
|
7
|
+
class Serial < NewStyle
|
8
|
+
def instantiate_pins(options = {})
|
9
|
+
add_pin :tck
|
10
|
+
add_pin :tio
|
11
|
+
end
|
12
|
+
|
13
|
+
def jtag_cycle(actions, options = {})
|
14
|
+
pin(:tck).drive(1)
|
15
|
+
jtag.apply_action(pin(:tio), actions[:tdi])
|
16
|
+
tester.cycle(options)
|
17
|
+
jtag.apply_action(pin(:tio), actions[:tms])
|
18
|
+
tester.cycle(options)
|
19
|
+
jtag.apply_action(pin(:tio), actions[:tdo])
|
20
|
+
tester.store_next_cycle(pin(:tio)) if actions[:store]
|
21
|
+
tester.cycle(options)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/pattern/jtag_workout.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
pat_name = "jtag_workout_#{$dut.tclk_format.upcase}#{$dut.tclk_multiple}"
|
2
2
|
pat_name = pat_name + "_#{dut.tdo_store_cycle}" if dut.tdo_store_cycle != 0
|
3
|
+
pat_name += "_serial" if dut.is_a?(OrigenJTAGDev::Serial)
|
3
4
|
pat_name += "_tclk_vals" if dut.try(:tclk_vals)
|
4
5
|
|
5
6
|
Pattern.create(options = { name: pat_name }) do
|
@@ -196,15 +197,17 @@ Pattern.create(options = { name: pat_name }) do
|
|
196
197
|
test 'Reset'
|
197
198
|
jtag.reset
|
198
199
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
200
|
+
if dut.has_pin?(:tdo)
|
201
|
+
test 'Suspend of compare on TDO works'
|
202
|
+
cc 'TDO should be H'
|
203
|
+
jtag.read_dr 0xFFFF, size: 16, msg: 'Read value out of DR'
|
204
|
+
tester.ignore_fails($dut.pin(:tdo)) do
|
205
|
+
cc 'TDO should be X'
|
206
|
+
jtag.read_dr 0xFFFF, size: 16, msg: 'Read value out of DR'
|
207
|
+
end
|
208
|
+
cc 'TDO should be H'
|
204
209
|
jtag.read_dr 0xFFFF, size: 16, msg: 'Read value out of DR'
|
205
210
|
end
|
206
|
-
cc 'TDO should be H'
|
207
|
-
jtag.read_dr 0xFFFF, size: 16, msg: 'Read value out of DR'
|
208
211
|
|
209
212
|
test 'Mask option for read_dr works'
|
210
213
|
cc 'TDO should be H'
|
data/templates/web/index.md.erb
CHANGED
@@ -26,24 +26,42 @@ or if your application is a plugin add this to your <code>.gemspec</code>
|
|
26
26
|
spec.add_development_dependency "origen_jtag", ">= <%= Origen.app.version %>"
|
27
27
|
~~~
|
28
28
|
|
29
|
-
__NOTE:__ You will also need to include <code>require 'origen_jtag'</code> somewhere in your environment.
|
29
|
+
__NOTE:__ You will also need to include <code>require 'origen_jtag'</code> somewhere in your environment.
|
30
|
+
This can be done in <code>config/environment.rb</code> for example.
|
30
31
|
|
31
32
|
### How To Use
|
32
33
|
|
33
|
-
####
|
34
|
+
#### Integration
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
Here is an example integration:
|
36
|
+
This plugin provides a JTAG driver that should be instantiated by the top-level DUT model as shown in this
|
37
|
+
basic integration example:
|
39
38
|
|
40
39
|
~~~ruby
|
41
|
-
class
|
40
|
+
class MyApp::MyDUT
|
41
|
+
include Origen::TopLevel
|
42
|
+
|
43
|
+
def initialize(options = {})
|
44
|
+
# The JTAG driver will use these pins by default if they are defined (or aliases)
|
45
|
+
add_pin :tck
|
46
|
+
add_pin :tdi
|
47
|
+
add_pin :tdo
|
48
|
+
add_pin :tms
|
49
|
+
|
50
|
+
sub_block :jtag, class_name: 'OrigenJTAG::Driver'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
~~~
|
54
|
+
|
55
|
+
Multiple JTAG blocks can be instantiated if the DUT has multiple JTAG ports, and each one can be individually
|
56
|
+
customized as shown in this more complex example:
|
42
57
|
|
58
|
+
~~~ruby
|
59
|
+
class MyApp::MyDUT
|
43
60
|
include Origen::TopLevel
|
44
61
|
|
45
62
|
def initialize
|
46
|
-
|
63
|
+
# The JTAG driver will use these pins by default if they are defined (or aliases)
|
64
|
+
add_pin :tck
|
47
65
|
add_pin :tdi
|
48
66
|
add_pin :tdo
|
49
67
|
add_pin :tms
|
@@ -58,92 +76,48 @@ class Pioneer
|
|
58
76
|
# 2 high then 2 low for each effective TCK pulse.
|
59
77
|
# Strobe TDO only when TCK high. Only store TDO on last cycle (3)
|
60
78
|
|
61
|
-
#
|
79
|
+
# Several plugins use dut.jtag, your default port driver should be named jtag for compatibility
|
62
80
|
sub_block :jtag, class_name: 'OrigenJTAG::Driver',
|
63
|
-
|
64
|
-
|
65
|
-
tdo_strobe: :
|
66
|
-
tdo_store_cycle: 3
|
67
|
-
|
68
|
-
|
69
|
-
tdo_pin: pin(:tdo),
|
70
|
-
tms_pin: pin(:tms)
|
71
|
-
|
72
|
-
# create a driver for a 2nd port like this
|
73
|
-
# note different configuration settings can be used
|
81
|
+
tck_format: :rl,
|
82
|
+
tck_multiple: 4,
|
83
|
+
tdo_strobe: :tck_high,
|
84
|
+
tdo_store_cycle: 3
|
85
|
+
|
86
|
+
# Create a driver for a 2nd port like this, note different configuration settings can be used
|
74
87
|
sub_block :jtag_port2, class_name: 'OrigenJTAG::Driver',
|
75
|
-
|
76
|
-
|
77
|
-
tdo_strobe: :
|
88
|
+
tck_format: :rh,
|
89
|
+
tck_multiple: 2,
|
90
|
+
tdo_strobe: :tck_high,
|
78
91
|
tdo_store_cycle: 1,
|
79
92
|
tck_pin: pin(:tck2),
|
80
93
|
tdi_pin: pin(:tdi2),
|
81
94
|
tdo_pin: pin(:tdo2),
|
82
95
|
tms_pin: pin(:tms2)
|
83
96
|
end
|
84
|
-
|
85
97
|
end
|
86
98
|
|
87
|
-
dut.jtag # => jtag driver for the first port (
|
99
|
+
dut.jtag # => jtag driver for the first port (tck, tdi, tdo, tms)
|
88
100
|
dut.jtag_port2 # => jtag driver for the second port (tck2, tdi2, tdo2, tms2)
|
89
101
|
~~~
|
90
102
|
|
103
|
+
Here are some of the most common configuration options:
|
104
|
+
|
105
|
+
* **tck_format** - TCK timing format, Return High (:rh) or Return Low (:rl). Default is :rh.
|
106
|
+
* **tck_multiple** - Number of cycles for a single TCK pulse to cover, to support cases where TCK needs to be a fraction of another clock period. Assumes 50% duty cycle, specify only even numbers if > 1. Default is :r1.
|
107
|
+
* **tdo_strobe** - When using multiple cycles for TCK, which state of TCK to strobe for TDO, :tck_high or :tck_low or :tck_all. Default :tck_high.
|
108
|
+
* **tdo_store_cycle** - When using multiple cycles for TCK, which cycle of TCK to store for TDO if store requested (0 to number of tck_multiple-1). Default 0
|
109
|
+
|
91
110
|
By default, the driver will apply the conventional '1' and '0' drive values on the TCK pin to turn
|
92
111
|
the clock on and off, however
|
93
|
-
this can be overridden by supplying the `:
|
112
|
+
this can be overridden by supplying the `:tck_vals` option as shown in the example below:
|
94
113
|
|
95
114
|
~~~ruby
|
96
115
|
# My V93K timing setup uses 'P' to enable a clock pulse instead of '1'
|
97
|
-
|
116
|
+
tck_vals: { on: 'P', off: 0 }
|
98
117
|
~~~
|
99
118
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
Include the <code>OrigenJTAG</code> module to add a JTAG driver to your class and
|
104
|
-
define the required pins.
|
105
|
-
Normally the pins would be an alias to existing DUT pins and therefore the
|
106
|
-
JTAG driver module cannot assume them.
|
107
|
-
|
108
|
-
Including the module adds a <code>jtag</code> method which will return an instance of
|
109
|
-
[<code>OrigenJTAG::Driver</code>](<%= path "api/OrigenJTAG/Driver.html" %>).
|
110
|
-
|
111
|
-
The following attributes can be customized by defining a <code>JTAG_CONFIG</code>
|
112
|
-
hash:
|
113
|
-
|
114
|
-
* **tclk_format** - TCLK timing format, Return High (:rh) or Return Low (:rl). Default is :rh.
|
115
|
-
* **tclk_multiple** - Number of cycles for a single TCLK pulse to cover, to support cases where TCLK needs to be a fraction of another clock period. Assumes 50% duty cycle, specify only even numbers if > 1. Default is :r1.
|
116
|
-
* **tdo_strobe** - When using multiple cycles for TCK, which state of TCK to strobe for TDO, :tclk_high or :tclk_low or :tclk_all. Default :tclk_high.
|
117
|
-
* **tdo_store_cycle** - When using multiple cycles for TCK, which cycle of TCK to store for TDO if store requested (0 to number of tclk_multiple-1). Default 0
|
118
|
-
|
119
|
-
Here is an example integration:
|
120
|
-
|
121
|
-
~~~ruby
|
122
|
-
class Pioneer
|
123
|
-
|
124
|
-
include OrigenJTAG
|
125
|
-
include Origen::Pins
|
126
|
-
|
127
|
-
# TCK covers 4 tester cycles, 2 high then 2 low for each effective TCK pulse
|
128
|
-
# Strobe TDO only when TCK high. Only store TDO on last cycle (3)
|
129
|
-
JTAG_CONFIG = {
|
130
|
-
:tclk_format => :rl,
|
131
|
-
:tclk_multiple => 4,
|
132
|
-
:tdo_strobe => :tclk_high,
|
133
|
-
:tdo_store_cycle => 3,
|
134
|
-
}
|
135
|
-
|
136
|
-
def initialize
|
137
|
-
add_pin :tclk
|
138
|
-
add_pin :tdi
|
139
|
-
add_pin :tdo
|
140
|
-
add_pin :tms
|
141
|
-
end
|
142
|
-
|
143
|
-
end
|
144
|
-
|
145
|
-
Pioneer.new.jtag # => An instance of OrigenJTAG::Driver
|
146
|
-
~~~
|
119
|
+
A [legacy integration is also supported](<%= path "legacy" %>), but not recommended for new projects
|
120
|
+
as it may be deprecated in future.
|
147
121
|
|
148
122
|
#### APIs
|
149
123
|
|
@@ -203,6 +177,57 @@ def on_jtag_state_change(new_state)
|
|
203
177
|
end
|
204
178
|
~~~
|
205
179
|
|
180
|
+
#### Custom JTAG Cycle Protocols
|
181
|
+
|
182
|
+
This plugin also allows applications to define how a JTAG cycle should be implemented at the
|
183
|
+
pin-level, providing the flexibility to handle hybrid JTAG protocols.
|
184
|
+
An example would be an ultra-low pincount device where the JTAG signals are multiplexed down a
|
185
|
+
single wire.
|
186
|
+
|
187
|
+
To implement a custom protocol, a `:cycle_callback` option should be supplied when instantiating the
|
188
|
+
driver to specify the name of the DUT method that will implement the cycle.
|
189
|
+
**Note that most other configuration options are meaningless in this context (and some non-default
|
190
|
+
values will raise an error) because the application
|
191
|
+
is now taking full responsibility for how a JTAG cycle is implemented.**
|
192
|
+
Similarly, there is no requirement for the conventional JTAG pins to be present or specified when this
|
193
|
+
option is given since the driver is no longer responsible for the vector generation.
|
194
|
+
|
195
|
+
The given method should accept two arguments:
|
196
|
+
|
197
|
+
* **actions** - A hash containing the actions that should be applied to the `:tdi`, `:tms` and `:tdo`,
|
198
|
+
pins and a boolean flag called `:store` which indicates if TDO should be stored/captured on this cycle
|
199
|
+
* **options** - Any options that should be passed to the tester when calling `tester.cycle`
|
200
|
+
|
201
|
+
The JTAG driver provides a method called `apply_action` which accepts a pin object and the pin-specific
|
202
|
+
actions from the actions hash, e.g.
|
203
|
+
|
204
|
+
~~~ruby
|
205
|
+
jtag.apply_action(pin(:my_pin), actions[:tms])
|
206
|
+
~~~
|
207
|
+
|
208
|
+
Here is a complete example which would serialize TDI, TMS and TDO on a single pin:
|
209
|
+
|
210
|
+
~~~ruby
|
211
|
+
class MyApp::MyDUT
|
212
|
+
def initialize(options = {})
|
213
|
+
add_pin :tck
|
214
|
+
add_pin :tio
|
215
|
+
|
216
|
+
sub_block :jtag, class_name: 'OrigenJTAG::Driver', cycle_callback: :jtag_cycle
|
217
|
+
end
|
218
|
+
|
219
|
+
def jtag_cycle(actions, options = {})
|
220
|
+
pin(:tck).drive(1)
|
221
|
+
jtag.apply_action(pin(:tio), actions[:tdi])
|
222
|
+
tester.cycle(options)
|
223
|
+
jtag.apply_action(pin(:tio), actions[:tms])
|
224
|
+
tester.cycle(options)
|
225
|
+
jtag.apply_action(pin(:tio), actions[:tdo])
|
226
|
+
tester.store_next_cycle(pin(:tio)) if actions[:store]
|
227
|
+
tester.cycle(options)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
~~~
|
206
231
|
|
207
232
|
### How To Setup a Development Environment
|
208
233
|
|
@@ -0,0 +1,43 @@
|
|
1
|
+
% render "layouts/basic.html" do
|
2
|
+
|
3
|
+
### Legacy Integration
|
4
|
+
|
5
|
+
The following approach to adding an JTAG driver is still supported, however new projects
|
6
|
+
should use the new style integration as described [on the home page](<%= path "/" %>).
|
7
|
+
|
8
|
+
Include the <code>OrigenJTAG</code> module to add a JTAG driver to your class and
|
9
|
+
define the required pins.
|
10
|
+
Normally the pins would be an alias to existing DUT pins and therefore the
|
11
|
+
JTAG driver module cannot assume them.
|
12
|
+
|
13
|
+
Including the module adds a <code>jtag</code> method which will return an instance of
|
14
|
+
[<code>OrigenJTAG::Driver</code>](<%= path "api/OrigenJTAG/Driver.html" %>).
|
15
|
+
|
16
|
+
Here is an example integration:
|
17
|
+
|
18
|
+
~~~ruby
|
19
|
+
class MyApp::MyDUT
|
20
|
+
include Origen::TopLevel
|
21
|
+
include OrigenJTAG
|
22
|
+
|
23
|
+
# TCK covers 4 tester cycles, 2 high then 2 low for each effective TCK pulse
|
24
|
+
# Strobe TDO only when TCK high. Only store TDO on last cycle (3)
|
25
|
+
JTAG_CONFIG = {
|
26
|
+
:tck_format => :rl,
|
27
|
+
:tck_multiple => 4,
|
28
|
+
:tdo_strobe => :tck_high,
|
29
|
+
:tdo_store_cycle => 3,
|
30
|
+
}
|
31
|
+
|
32
|
+
def initialize
|
33
|
+
add_pin :tck
|
34
|
+
add_pin :tdi
|
35
|
+
add_pin :tdo
|
36
|
+
add_pin :tms
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
MyApp::MyDUT.new.jtag # => An instance of OrigenJTAG::Driver
|
41
|
+
~~~
|
42
|
+
|
43
|
+
% end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: origen_jtag
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.21.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen McGinty
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-04-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: origen
|
@@ -59,6 +59,7 @@ files:
|
|
59
59
|
- lib/origen_jtag/driver.rb
|
60
60
|
- lib/origen_jtag/tap_controller.rb
|
61
61
|
- lib/origen_jtag_dev/new_style.rb
|
62
|
+
- lib/origen_jtag_dev/serial.rb
|
62
63
|
- lib/origen_jtag_dev/top_level.rb
|
63
64
|
- pattern/full_reg_ovly_cap.rb
|
64
65
|
- pattern/global_label_test.rb
|
@@ -67,6 +68,7 @@ files:
|
|
67
68
|
- pattern/two_port.rb
|
68
69
|
- templates/web/index.md.erb
|
69
70
|
- templates/web/layouts/_basic.html.erb
|
71
|
+
- templates/web/legacy.md.erb
|
70
72
|
- templates/web/partials/_navbar.html.erb
|
71
73
|
- templates/web/release_notes.md.erb
|
72
74
|
homepage: http://origen-sdk.org/jtag
|