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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8857b553c5de44e4b7b8d5a36bb6dc071b8d6d3b85a7bbe270b87ead73e4c537
4
- data.tar.gz: 2d09587fee678bc00d6ba8c75e38d42811a0753c1c2791dee457706c678b2f5b
3
+ metadata.gz: b15086a4ad3545ea9f62a1dfd03cbd478ba289d81cbe417ccbf6f66f0abb7741
4
+ data.tar.gz: d92e037cdc87ad03eb50cb0b480b1f2c0ea3ad658b2c5a8a607feace42f2f61a
5
5
  SHA512:
6
- metadata.gz: 5410a3a6c9c4c250341a6840979908819ad5326baf8529fef0936d92029e4f910660ac9859b8dd010832013894ea8eeba830cbbb3cd0e8e7c9ec303fa91d572b
7
- data.tar.gz: d54393fceeeb9dc965c513300c7042bd550d1c1b14962b1f523e768dafe5c0c05c6ee26dd0c98428db33e39b046af7d75af09dad7a9f1caddfbc70d52f1a4aa8
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
@@ -1,6 +1,6 @@
1
1
  module OrigenJTAG
2
2
  MAJOR = 0
3
- MINOR = 20
3
+ MINOR = 21
4
4
  BUGFIX = 0
5
5
  DEV = nil
6
6
 
@@ -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
- # :tclk
9
+ # :tck
10
10
  # :tdi
11
11
  # :tdo
12
12
  # :tms
13
13
  class Driver
14
- REQUIRED_PINS = [:tclk, :tdi, :tdo, :tms]
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
- # Returns the tclk multiple
27
- attr_reader :tclk_multiple
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
- @tclk_format = options[:tclk_format]
72
- @tclk_multiple = options[:tclk_multiple]
73
- @tdo_strobe = options[:tdo_strobe]
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
- @tclk_vals = options[:tclk_vals]
79
- unless @tclk_vals.is_a?(Hash) && @tclk_vals.key?(:on) && @tclk_vals.key?(:off)
80
- fail "When specifying TCLK values, you must supply a hash with both :on and :off keys, e.g. tclk_vals: { on: 'P', off: 0 }"
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
- store_tdo_this_tclk = false
189
+ store_tdo_this_tck = false
159
190
 
160
- # Set up pin actions for bit transaction (tclk cycle)
191
+ # Set up pin actions for bit transaction (tck cycle)
161
192
 
162
193
  # TDI
163
- @tdi_pin.drive(tdi_reg[i])
194
+ action :tdi, :drive, tdi_reg[i]
164
195
 
165
196
  # TDO
166
- @tdo_pin.dont_care # default setting
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
- store_tdo_this_tclk = true
170
- @tdo_pin.dont_care if Origen.tester.j750?
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
- @tdo_pin.assert(tdo_reg[i], meta: { position: i })
203
+ action :tdo, :assert, tdo_reg[i], meta: { position: i }
173
204
  end
174
205
  end
175
206
 
176
207
  # TMS
177
- @tms_pin.drive(0)
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] = @tdi_pin
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
- @tdi_pin.drive(0) if tester_subr_overlay
198
- @tdo_pin.assert(tdo_reg[i], meta: { position: i }) if options[:read] unless tester_subr_overlay
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
- @tdo_pin.assert(tdo_reg[i], meta: { position: i }) if options[:read]
242
+ action :tdo, :assert, tdo_reg[i], meta: { position: i } if options[:read]
212
243
  else
213
- @tdi_pin.drive(0)
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 tclk_cycle to
220
- # execute a single TCLK period. Special handling of subroutines,
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
- # tclk config).
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
- @tms_pin.drive(1)
268
+ action :tms, :drive, 1
238
269
  @last_data_vector_shifted = true
239
270
  end
240
271
  end
241
- tclk_cycle do
242
- if store_tdo_this_tclk && @next_data_vector_to_be_stored
243
- Origen.tester.store_next_cycle(@tdo_pin)
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
- Origen.tester.cycle
276
+ if overlay_options[:pins].nil? || cycle_callback?
277
+ cycle
247
278
  else
248
- Origen.tester.cycle overlay: overlay_options
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
- @tdo_pin.dont_care
283
+ @pins[:tdo].dont_care unless cycle_callback?
253
284
  else
254
285
  @deferred_compare = true
255
- @deferred_store = true if store_tdo_this_tclk
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 TCLK cycle
268
- # Adjusts for the TCLK format and cycle span
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 tclk_cycle
272
- case @tclk_format
273
- when :rh
274
- tclk_val = 0
275
- when :rl
276
- tclk_val = 1
277
- else
278
- fail 'ERROR: Invalid Tclk timing format!'
279
- end
280
-
281
- # determine whether to mask TDO on first half cycle
282
- mask_tdo_half0 = ((@tclk_format == :rl) && (@tdo_strobe == :tclk_low) && (@tclk_multiple > 1)) ||
283
- ((@tclk_format == :rh) && (@tdo_strobe == :tclk_high) && (@tclk_multiple > 1))
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
- # determine whether to mask TDO on second half cycle
286
- mask_tdo_half1 = ((@tclk_format == :rl) && (@tdo_strobe == :tclk_high) && (@tclk_multiple > 1)) ||
287
- ((@tclk_format == :rh) && (@tdo_strobe == :tclk_low) && (@tclk_multiple > 1))
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
- # determine whether TDO is set to capture for this TCLK cycle
290
- tdo_to_be_captured = @tdo_pin.to_be_captured?
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
- # If TDO is already suspended (by an application) then don't do the
293
- # suspends below since the resume will clear the application's suspend
294
- tdo_already_suspended = @tdo_pin.suspended? && !@tdo_suspended_by_driver
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
- @tclk_multiple.times do |i|
297
- # 50% duty cycle if @tclk_multiple is even, otherwise slightly off
328
+ @tck_multiple.times do |i|
329
+ # 50% duty cycle if @tck_multiple is even, otherwise slightly off
298
330
 
299
- @next_data_vector_to_be_stored = @tdo_store_cycle == i ? true : false
331
+ @next_data_vector_to_be_stored = @tdo_store_cycle == i ? true : false
300
332
 
301
- if i < (@tclk_multiple + 1) / 2
302
- # first half of cycle
303
- @tck_pin.drive(@tclk_vals ? @tclk_vals[:on] : tclk_val)
304
- unless tdo_already_suspended
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
- @tdo_pin.suspend
339
+ @pins[:tdo].suspend
309
340
  else
310
341
  @tdo_suspended_by_driver = false
311
- @tdo_pin.resume
342
+ @pins[:tdo].resume
312
343
  end
313
344
  end
314
- end
315
- else
316
- # second half of cycle
317
- @tck_pin.drive(@tclk_vals ? @tclk_vals[:off] : (1 - tclk_val))
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
- @tdo_pin.suspend
351
+ @pins[:tdo].suspend
323
352
  else
324
353
  @tdo_suspended_by_driver = false
325
- @tdo_pin.resume
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 TCLK
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
- @tdo_pin.dont_care
375
+ action :tdo, :dont_care
347
376
  end
348
377
 
349
378
  if @deferred_store
350
379
  @deferred_store = nil
351
- store_tdo_this_tclk = true
380
+ store_tdo_this_tck = true
352
381
  else
353
- store_tdo_this_tclk = false
382
+ store_tdo_this_tck = false
354
383
  end
355
384
  @next_data_vector_to_be_stored = false
356
385
 
357
- tclk_cycle do
358
- if store_tdo_this_tclk && @next_data_vector_to_be_stored
359
- Origen.tester.store_next_cycle(@tdo_pin)
386
+ tck_cycle do
387
+ if store_tdo_this_tck && @next_data_vector_to_be_stored
388
+ action :store
360
389
  end
361
- @tms_pin.drive!(val)
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
- @tck_pin = options[:tck_pin] if options[:tck_pin]
605
- @tdi_pin = options[:tdi_pin] if options[:tdi_pin]
606
- @tdo_pin = options[:tdo_pin] if options[:tdo_pin]
607
- @tms_pin = options[:tms_pin] if options[:tms_pin]
608
-
609
- @tck_pin = @owner.pin(:tclk) if @tck_pin.nil?
610
- @tdi_pin = @owner.pin(:tdi) if @tdi_pin.nil?
611
- @tdo_pin = @owner.pin(:tdo) if @tdo_pin.nil?
612
- @tms_pin = @owner.pin(:tms) if @tms_pin.nil?
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(:tclk), tdi_pin: dut.pin(:tdi), tdo_pin: dut.pin(:tdo), tms_pin: dut.pin(:tms)"
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
- if options[:invalid_pins]
54
- add_pin :tck
55
- else
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 duing gem testing
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
@@ -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
- test 'Suspend of compare on TDO works'
200
- cc 'TDO should be H'
201
- jtag.read_dr 0xFFFF, size: 16, msg: 'Read value out of DR'
202
- tester.ignore_fails($dut.pin(:tdo)) do
203
- cc 'TDO should be X'
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'
@@ -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. This can be done in <code>config/environment.rb</code> for example.
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
- #### New Style Example
34
+ #### Integration
34
35
 
35
- The driver no longer requires specific pin names (or aliases), supports sub_block instantiation and DUTs with multiple JTAG ports.
36
- You are no longer required to include "OrigenJTAG" in your DUT class.
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 Pioneer
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
- add_pin :tclk
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
- # several pluggins use dut.jtag, your default port driver should be named jtag for compatibility
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
- tclk_format: :rl,
64
- tclk_multiple: 4,
65
- tdo_strobe: :tclk_high,
66
- tdo_store_cycle: 3,
67
- tck_pin: pin(:tclk),
68
- tdi_pin: pin(:tdi),
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
- tclk_format: :rh,
76
- tclk_multiple: 2,
77
- tdo_strobe: :tclk_high,
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 (tclk, tdi, tdo, tms)
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 `:tclk_vals` option as shown in the example below:
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
- tclk_vals: { on: 'P', off: 0 }
116
+ tck_vals: { on: 'P', off: 0 }
98
117
  ~~~
99
118
 
100
-
101
- #### Legacy Example
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.20.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-03-07 00:00:00.000000000 Z
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