origen_jtag 0.17.1 → 0.17.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,595 +1,600 @@
1
- module OrigenJTAG
2
- # This driver provides methods to read and write from a JTAG instruction
3
- # and data registers.
4
- #
5
- # Low level methods are also provided for fine control of the TAP Controller
6
- # state machine via the TAPController module.
7
- #
8
- # To use this driver the parent model must define the following pins (an alias is fine):
9
- # :tclk
10
- # :tdi
11
- # :tdo
12
- # :tms
13
- class Driver
14
- REQUIRED_PINS = [:tclk, :tdi, :tdo, :tms]
15
-
16
- include TAPController
17
- include Origen::Registers
18
-
19
- # Returns the object that instantiated the JTAG
20
- attr_reader :owner
21
-
22
- # Returns the current value in the instruction register
23
- attr_reader :ir_value
24
-
25
- attr_accessor :tclk_format
26
- # Set true to print out debug comments about all state transitions
27
- attr_accessor :verbose
28
- alias_method :verbose?, :verbose
29
-
30
- # Log all state changes in pattern comments, false by default
31
- attr_accessor :log_state_changes
32
-
33
- def initialize(owner, options = {})
34
- @owner = owner
35
- validate_pins
36
-
37
- # The parent can configure JTAG settings by defining this constant
38
- if defined?(owner.class::JTAG_CONFIG)
39
- options = owner.class::JTAG_CONFIG.merge(options)
40
- end
41
-
42
- # Fallback defaults
43
- options = {
44
- verbose: false,
45
- tclk_format: :rh, # format of JTAG clock used: ReturnHigh (:rh), ReturnLo (:rl)
46
- 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.
47
- # e.g. @tclk_multiple = 2, @tclk_format = :rh, means one cycle with Tck low (non-return), one with Tck high (NR)
48
- # @tclk_multiple = 4, @tclk_format = :rl, means 2 cycles with Tck high (NR), 2 with Tck low (NR)
49
- tdo_strobe: :tclk_high, # when using multiple cycles for TCK, when to strobe for TDO, options include:
50
- # :tclk_high - strobe TDO only when TCK is high
51
- # :tclk_low - strobe TDO only when TCK is low
52
- # :tclk_all - strobe TDO throughout TCK cycle
53
- 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.)
54
- # 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)
55
- init_state: :unknown
56
- }.merge(options)
57
-
58
- init_tap_controller(options)
59
-
60
- @verbose = options[:verbose]
61
- @ir_value = :unknown
62
- @tclk_format = options[:tclk_format]
63
- @tclk_multiple = options[:tclk_multiple]
64
- @tdo_strobe = options[:tdo_strobe]
65
- @tdo_store_cycle = options[:tdo_store_cycle]
66
- @state = options[:init_state]
67
- @log_state_changes = options[:log_state_changes] || false
68
- end
69
-
70
- # Shift data into the TDI pin or out of the TDO pin.
71
- #
72
- # There is no TAP controller state checking or handling here, it just
73
- # shifts some data directly into the pattern, so it is assumed that some
74
- # higher level logic is co-ordinating the TAP Controller.
75
- #
76
- # Most applications should not call this method directly and should instead
77
- # use the pre-packaged read/write_dr/ir methods.
78
- # However it is provided as a public API for the corner cases like generating
79
- # an overlay subroutine pattern where it would be necessary to generate some JTAG
80
- # vectors outwith the normal state controller wrapper.
81
- #
82
- # @param [Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit] reg_or_val
83
- # Value to be shifted. If a reg/bit collection is supplied this can be pre-marked for
84
- # read, store or overlay and which will result in the requested action being applied to
85
- # the cycles corresponding to those bits only (don't care cycles will be generated for the others).
86
- # @param [Hash] options Options to customize the operation
87
- # @option options [Integer] :size The number of bits to shift. This is optional
88
- # when supplying a register or bit collection in which case the size will be derived from
89
- # the number of bits supplied. If this option is supplied then it will override
90
- # the size derived from the bits. If the size is greater than the number of bits
91
- # provided then the additional space will be padded by 0s or don't cares as appropriate.
92
- # @option options [Boolean] :read (false) When true the given value will be compared on the TDO pin
93
- # instead of being shifted into the TDI pin. In the case of a register object being provided
94
- # only those bits that are actually marked for read will be compared.
95
- # @option options [Boolean] :cycle_last (false) Normally the last data bit is applied to the
96
- # pins but not cycled, this is to integrate with the TAPController which usually
97
- # requires that the TMS value is also changed on the last data bit. To override this
98
- # default behavior and force a cycle for the last data bit set this to true.
99
- # @option options [Boolean] :includes_last_bit (true) When true the TMS pin will be driven
100
- # to 1 on the last cycle of the shift if :cycle_last has been specified. To override this
101
- # and keep TMS low on the last cycle set this to false. One reason for doing this would be
102
- # if generating some subroutine vectors which only represented a partial section of a shift
103
- # operation.
104
- def shift(reg_or_val, options = {})
105
- options = {
106
- read: false,
107
- cycle_last: false,
108
- includes_last_bit: true,
109
- no_subr: false # do not use subroutine for any overlay
110
- }.merge(options)
111
-
112
- # save compression state for restoring afterwards
113
- compression_on = !Origen.tester.dont_compress
114
-
115
- # clean incoming data
116
- size = extract_size(reg_or_val, options)
117
- tdi_reg = extract_shift_in_data(reg_or_val, size, options)
118
- tdo_reg = extract_shift_out_data(reg_or_val, size, options)
119
- global_ovl, ovl_reg = extract_overlay_data(reg_or_val, size, options)
120
-
121
- # let the tester handle overlay if possible
122
- unless tester.respond_to?(:source_memory)
123
- # tester does not support direct labels, so can't do
124
- if options[:no_subr] && !$tester.respond_to?('label')
125
- cc 'This tester does not support use of labels, cannot do no_subr option as requested'
126
- cc ' going with subroutine overlay instead'
127
- options[:no_subr] = false
128
- end
129
-
130
- # insert global label if specified
131
- if global_ovl
132
- if $tester.respond_to?('label')
133
- $tester.label(global_ovl, true)
134
- else
135
- cc "Unsupported global label: #{global_ovl}"
136
- end
137
- end
138
- end # of let tester handle overlay if possible
139
-
140
- # loop through each data bit
141
- last_overlay_label = ''
142
- size.times do |i|
143
- store_tdo_this_tclk = false
144
-
145
- # Set up pin actions for bit transaction (tclk cycle)
146
-
147
- # TDI
148
- owner.pin(:tdi).drive(tdi_reg[i])
149
-
150
- # TDO
151
- owner.pin(:tdo).dont_care # default setting
152
- if tdo_reg[i]
153
- if tdo_reg[i].is_to_be_stored? # store
154
- store_tdo_this_tclk = true
155
- owner.pin(:tdo).dont_care if Origen.tester.j750?
156
- elsif tdo_reg[i].is_to_be_read? # compare/assert
157
- owner.pin(:tdo).assert(tdo_reg[i])
158
- end
159
- end
160
-
161
- # TMS
162
- owner.pin(:tms).drive(0)
163
-
164
- # let tester handle overlay if implemented
165
- overlay_options = {}
166
- if tester.respond_to?(:source_memory)
167
- if ovl_reg[i] && ovl_reg[i].has_overlay? && !Origen.mode.simulation?
168
- overlay_options[:pins] = owner.pin(:tdi)
169
- if global_ovl
170
- overlay_options[:overlay_str] = global_ovl
171
- else
172
- overlay_options[:overlay_str] = ovl_reg[i].overlay_str
173
- end
174
- if options[:no_subr] || global_ovl
175
- if global_ovl
176
- overlay_options[:overlay_style] = :global_label
177
- else
178
- overlay_options[:overlay_style] = :label
179
- end
180
- end
181
- tester_subr_overlay = !(options[:no_subr] || global_ovl) && tester.overlay_style == :subroutine
182
- owner.pin(:tdi).drive(0) if tester_subr_overlay
183
- owner.pin(:tdo).assert(tdo_reg[i]) if options[:read] unless tester_subr_overlay
184
- end
185
- else
186
- # Overlay - reconfigure pin action for overlay if necessary
187
- if ovl_reg[i] && ovl_reg[i].has_overlay? && !Origen.mode.simulation?
188
- if options[:no_subr]
189
- Origen.tester.dont_compress = true
190
- if ovl_reg[i].overlay_str != last_overlay_label
191
- $tester.label(ovl_reg[i].overlay_str)
192
- last_overlay_label = ovl_reg[i].overlay_str
193
- end
194
- owner.pin(:tdo).assert(tdo_reg[i]) if options[:read]
195
- else
196
- owner.pin(:tdi).drive(0)
197
- call_subroutine = ovl_reg[i].overlay_str
198
- end
199
- end
200
- end # of let tester handle overlay
201
-
202
- # With JTAG pin actions queued up, use block call to tclk_cycle to
203
- # execute a single TCLK period. Special handling of subroutines,
204
- # case of last bit in shift, and store vector (within a multi-cycle
205
- # tclk config).
206
- if call_subroutine || tester_subr_overlay
207
- @last_data_vector_shifted = true
208
- else
209
- @last_data_vector_shifted = false
210
- end
211
-
212
- if call_subroutine
213
- Origen.tester.call_subroutine(call_subroutine)
214
- else
215
- @next_data_vector_to_be_stored = false
216
- # Don't latch the last bit, that will be done when leaving the state.
217
- if i != size - 1 || options[:cycle_last]
218
- if i == size - 1 && options[:includes_last_bit]
219
- owner.pin(:tms).drive(1) unless tester_subr_overlay
220
- end
221
- tclk_cycle do
222
- if store_tdo_this_tclk && @next_data_vector_to_be_stored
223
- Origen.tester.store_next_cycle(owner.pin(:tdo))
224
- end
225
- if overlay_options[:pins].nil?
226
- Origen.tester.cycle
227
- else
228
- Origen.tester.cycle overlay: overlay_options
229
- overlay_options[:change_data] = false # data change only on first cycle if overlay
230
- end
231
- end
232
- owner.pin(:tdo).dont_care
233
- else
234
- @deferred_compare = true
235
- @deferred_store = true if store_tdo_this_tclk
236
- end
237
- end
238
- end
239
-
240
- # Clear read and similar flags to reflect that the request has just been fulfilled
241
- reg_or_val.clear_flags if reg_or_val.respond_to?(:clear_flags)
242
-
243
- # put back compression if turned on above
244
- Origen.tester.dont_compress = false if compression_on
245
- end
246
-
247
- # Cycles the tester through one TCLK cycle
248
- # Adjusts for the TCLK format and cycle span
249
- # Assumes caller will drive pattern to tester
250
- # via .drive or similar
251
- def tclk_cycle
252
- case @tclk_format
253
- when :rh
254
- tclk_val = 0
255
- when :rl
256
- tclk_val = 1
257
- else
258
- fail 'ERROR: Invalid Tclk timing format!'
259
- end
260
-
261
- # determine whether to mask TDO on first half cycle
262
- mask_tdo_half0 = ((@tclk_format == :rl) && (@tdo_strobe == :tclk_low) && (@tclk_multiple > 1)) ||
263
- ((@tclk_format == :rh) && (@tdo_strobe == :tclk_high) && (@tclk_multiple > 1))
264
-
265
- # determine whether to mask TDO on second half cycle
266
- mask_tdo_half1 = ((@tclk_format == :rl) && (@tdo_strobe == :tclk_high) && (@tclk_multiple > 1)) ||
267
- ((@tclk_format == :rh) && (@tdo_strobe == :tclk_low) && (@tclk_multiple > 1))
268
-
269
- # determine whether TDO is set to capture for this TCLK cycle
270
- tdo_to_be_captured = owner.pin(:tdo).to_be_captured?
271
-
272
- # If TDO is already suspended (by an application) then don't do the
273
- # suspends below since the resume will clear the application's suspend
274
- tdo_already_suspended = owner.pin(:tdo).suspended? && !@tdo_suspended_by_driver
275
-
276
- @tclk_multiple.times do |i|
277
- # 50% duty cycle if @tclk_multiple is even, otherwise slightly off
278
-
279
- @next_data_vector_to_be_stored = @tdo_store_cycle == i ? true : false
280
-
281
- if i < (@tclk_multiple + 1) / 2
282
- # first half of cycle
283
- owner.pin(:tclk).drive(tclk_val)
284
- unless tdo_already_suspended
285
- unless tdo_to_be_captured
286
- if mask_tdo_half0
287
- @tdo_suspended_by_driver = true
288
- owner.pin(:tdo).suspend
289
- else
290
- @tdo_suspended_by_driver = false
291
- owner.pin(:tdo).resume
292
- end
293
- end
294
- end
295
- else
296
- # second half of cycle
297
- owner.pin(:tclk).drive(1 - tclk_val)
298
- unless tdo_already_suspended
299
- unless tdo_to_be_captured
300
- if mask_tdo_half1
301
- @tdo_suspended_by_driver = true
302
- owner.pin(:tdo).suspend
303
- else
304
- @tdo_suspended_by_driver = false
305
- owner.pin(:tdo).resume
306
- end
307
- end
308
- end
309
- end
310
- yield
311
- end
312
- if @tdo_suspended_by_driver
313
- owner.pin(:tdo).resume
314
- @tdo_suspended_by_driver = false
315
- end
316
- end
317
-
318
- # Applies the given value to the TMS pin and then
319
- # cycles the tester for one TCLK
320
- #
321
- # @param [Integer] val Value to drive on the TMS pin, 0 or 1
322
- def tms!(val)
323
- if @deferred_compare
324
- @deferred_compare = nil
325
- else
326
- owner.pin(:tdo).dont_care
327
- end
328
-
329
- if @deferred_store
330
- @deferred_store = nil
331
- store_tdo_this_tclk = true
332
- else
333
- store_tdo_this_tclk = false
334
- end
335
- @next_data_vector_to_be_stored = false
336
-
337
- tclk_cycle do
338
- if store_tdo_this_tclk && @next_data_vector_to_be_stored
339
- Origen.tester.store_next_cycle(owner.pin(:tdo))
340
- end
341
- owner.pin(:tms).drive!(val)
342
- end
343
- end
344
-
345
- # Write the given value, register or bit collection to the data register.
346
- # This is a self contained method that will take care of the TAP controller
347
- # state transitions, exiting with the TAP controller in Run-Test/Idle.
348
- #
349
- # @param [Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit] reg_or_val
350
- # Value to be written. If a reg/bit collection is supplied this can be pre-marked for overlay.
351
- # @param [Hash] options Options to customize the operation
352
- # @option options [Integer] :size The number of bits to write. This is optional
353
- # when supplying a register or bit collection in which case the size will be derived from
354
- # the number of bits supplied. If this option is supplied then it will override
355
- # the size derived from the bits. If the size is greater than the number of bits
356
- # provided then the additional space will be padded by 0s.
357
- # @option options [String] :msg By default will not make any comments directly here. Can pass
358
- # a msg to be written out prior to shifting data.
359
- def write_dr(reg_or_val, options = {})
360
- if Origen.tester.respond_to?(:write_dr)
361
- Origen.tester.write_dr(reg_or_val, options)
362
- else
363
- if options[:msg]
364
- cc "#{options[:msg]}\n"
365
- end
366
- val = reg_or_val.respond_to?(:data) ? reg_or_val.data : reg_or_val
367
- shift_dr(write: val.to_hex) do
368
- shift(reg_or_val, options)
369
- end
370
- end
371
- end
372
-
373
- # Read the given value, register or bit collection from the data register.
374
- # This is a self contained method that will take care of the TAP controller
375
- # state transitions, exiting with the TAP controller in Run-Test/Idle.
376
- #
377
- # @param [Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit] reg_or_val
378
- # Value to be read. If a reg/bit collection is supplied this can be pre-marked for read in which
379
- # case only the marked bits will be read and the vectors corresponding to the data from the non-read
380
- # bits will be set to don't care. Similarly the bits can be pre-marked for store (capture) or
381
- # overlay.
382
- # @param [Hash] options Options to customize the operation
383
- # @option options [Integer] :size The number of bits to read. This is optional
384
- # when supplying a register or bit collection in which case the size will be derived from
385
- # the number of bits supplied. If the size is supplied then it will override
386
- # the size derived from the bits. If the size is greater than the number of bits
387
- # provided then the additional space will be padded by don't care cycles.
388
- # @option options [String] :msg By default will not make any comments directly here. Can pass
389
- # a msg to be written out prior to shifting data.
390
- def read_dr(reg_or_val, options = {})
391
- if Origen.tester.respond_to?(:read_dr)
392
- Origen.tester.read_dr(reg_or_val, options)
393
- else
394
- options = {
395
- read: true
396
- }.merge(options)
397
- if options[:msg]
398
- cc "#{options[:msg]}\n"
399
- end
400
- shift_dr(read: Origen::Utility.read_hex(reg_or_val)) do
401
- shift(reg_or_val, options)
402
- end
403
- end
404
- end
405
-
406
- # Write the given value, register or bit collection to the instruction register.
407
- # This is a self contained method that will take care of the TAP controller
408
- # state transitions, exiting with the TAP controller in Run-Test/Idle.
409
- #
410
- # @param [Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit] reg_or_val
411
- # Value to be written. If a reg/bit collection is supplied this can be pre-marked for overlay.
412
- # @param [Hash] options Options to customize the operation
413
- # @option options [Integer] :size The number of bits to write. This is optional
414
- # when supplying a register or bit collection in which case the size will be derived from
415
- # the number of bits supplied. If this option is supplied then it will override
416
- # the size derived from the bits. If the size is greater than the number of bits
417
- # provided then the additional space will be padded by 0s.
418
- # @option options [Boolean] :force By default multiple calls to this method will not generate
419
- # multiple writes. This is to allow wrapper algorithms to remain efficient yet not have to
420
- # manually track the IR state (and in many cases this may be impossible due to multiple
421
- # protocols using the same JTAG). To force a write regardless of what the driver thinks the IR
422
- # contains set this to true.
423
- # @option options [String] :msg By default will not make any comments directly here. Can pass
424
- # a msg to be written out prior to shifting in IR data. Will not write comment only if write
425
- # occurs.
426
- def write_ir(reg_or_val, options = {})
427
- if Origen.tester.respond_to?(:write_ir)
428
- Origen.tester.write_ir(reg_or_val, options)
429
- else
430
- val = reg_or_val.respond_to?(:data) ? reg_or_val.data : reg_or_val
431
- if val != ir_value || options[:force]
432
- if options[:msg]
433
- cc "#{options[:msg]}\n"
434
- end
435
- shift_ir(write: val.to_hex) do
436
- shift(reg_or_val, options)
437
- end
438
- @ir_value = val
439
- end
440
- end
441
- end
442
-
443
- # Read the given value, register or bit collection from the instruction register.
444
- # This is a self contained method that will take care of the TAP controller
445
- # state transitions, exiting with the TAP controller in Run-Test/Idle.
446
- #
447
- # @param [Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit] reg_or_val
448
- # Value to be read. If a reg/bit collection is supplied this can be pre-marked for read in which
449
- # case only the marked bits will be read and the vectors corresponding to the data from the non-read
450
- # bits will be set to don't care. Similarly the bits can be pre-marked for store (capture) or
451
- # overlay.
452
- # @param [Hash] options Options to customize the operation
453
- # @option options [Integer] :size The number of bits to read. This is optional
454
- # when supplying a register or bit collection in which case the size will be derived from
455
- # the number of bits supplied. If the size is supplied then it will override
456
- # the size derived from the bits. If the size is greater than the number of bits
457
- # provided then the additional space will be padded by don't care cycles.
458
- # @option options [String] :msg By default will not make any comments directly here. Can pass
459
- # a msg to be written out prior to shifting data.
460
- def read_ir(reg_or_val, options = {})
461
- if Origen.tester.respond_to?(:read_ir)
462
- Origen.tester.read_ir(reg_or_val, options)
463
- else
464
- options = {
465
- read: true
466
- }.merge(options)
467
- if options[:msg]
468
- cc "#{options[:msg]}\n"
469
- end
470
- shift_ir(read: Origen::Utility.read_hex(reg_or_val)) do
471
- shift(reg_or_val, options)
472
- end
473
- end
474
- end
475
-
476
- private
477
-
478
- # Return size of transaction. Options[:size] has priority and need not match the
479
- # register size. Any mismatch will be handled by the api.
480
- def extract_size(reg_or_val, options = {})
481
- size = options[:size]
482
- unless size
483
- if reg_or_val.is_a?(Fixnum) || !reg_or_val.respond_to?(:size)
484
- fail 'When suppling a value to JTAG::Driver#shift you must supply a :size in the options!'
485
- else
486
- size = reg_or_val.size
487
- end
488
- end
489
- size
490
- end
491
-
492
- # Combine any legacy options into a single global overlay and create
493
- # new bit collection to track any bit-wise overlays.
494
- def extract_overlay_data(reg_or_val, size, options = {})
495
- if reg_or_val.respond_to?(:data)
496
- ovl = reg_or_val.dup
497
- else
498
- ovl = Reg.dummy(size)
499
- end
500
-
501
- if options[:overlay]
502
- global = options[:overlay_label]
503
- elsif options.key?(:arm_debug_overlay) # prob don't need this anymore
504
- global = options[:arm_debug_overlay] # prob don't need this anymore
505
- else
506
- global = nil
507
- end
508
-
509
- [global, ovl]
510
- end
511
-
512
- # Create data that will be shifted in on TDI, create new bit collection
513
- # on the fly if reg_or_val arg is data only. Consider read operation
514
- # where caller has requested (specific) shift in data to be used.
515
- def extract_shift_in_data(reg_or_val, size, options = {})
516
- if reg_or_val.respond_to?(:data)
517
- if options[:read]
518
- data = options[:shift_in_data] || 0
519
- tdi = Reg.dummy(size)
520
- tdi.write(data)
521
- else
522
- tdi = reg_or_val.dup
523
- end
524
- else
525
- # Not a register model, so can't support bit-wise overlay
526
- tdi = Reg.dummy(size)
527
- if options[:read]
528
- data = options[:shift_in_data] || 0
529
- tdi.write(data)
530
- else
531
- tdi.write(reg_or_val)
532
- end
533
- end
534
- tdi
535
- end
536
-
537
- # Create data that will be shifted out on TDO, create new bit collection
538
- # on the fly if reg_or_val arg is data only. Consider write operation
539
- # where caller has requested (specific) shift out data to be compared.
540
- def extract_shift_out_data(reg_or_val, size, options = {})
541
- if reg_or_val.respond_to?(:data)
542
- if options[:read]
543
- tdo = reg_or_val.dup
544
- tdo.read(options) unless options[:mask].nil?
545
- else
546
- tdo = Reg.dummy(size) unless options[:shift_out_data].is_a?(Origen::Registers::Reg)
547
- end
548
- unless options[:read] # if this is a write operation
549
- if options[:shift_out_data]
550
- if options[:shift_out_data].class.to_s =~ /Origen::Registers/
551
- tdo = options[:shift_out_data]
552
- else
553
- tdo.write(options[:shift_out_data])
554
- tdo.read(options)
555
- end
556
- else
557
- tdo.write(0)
558
- end
559
- end
560
- else
561
- tdo = Reg.dummy(size)
562
- if options[:read]
563
- tdo.write(reg_or_val)
564
- tdo.read(options)
565
- else
566
- if options[:shift_out_data]
567
- if options[:shift_out_data].class.to_s =~ /Origen::Registers/
568
- tdo = options[:shift_out_data]
569
- else
570
- tdo.write(options[:shift_out_data])
571
- tdo.read(options)
572
- end
573
- else
574
- tdo.write(0)
575
- end
576
- end
577
- end
578
- tdo
579
- end
580
-
581
- # Validates that the parent object (the owner) has defined the necessary
582
- # pins to implement the JTAG
583
- def validate_pins
584
- REQUIRED_PINS.each do |name|
585
- owner.pin(name)
586
- end
587
- rescue
588
- puts 'Missing JTAG pins!'
589
- puts "In order to use the JTAG driver your #{owner.class} class must define"
590
- puts 'the following pins (an alias is fine):'
591
- puts REQUIRED_PINS
592
- raise 'JTAG driver error!'
593
- end
594
- end
595
- end
1
+ module OrigenJTAG
2
+ # This driver provides methods to read and write from a JTAG instruction
3
+ # and data registers.
4
+ #
5
+ # Low level methods are also provided for fine control of the TAP Controller
6
+ # state machine via the TAPController module.
7
+ #
8
+ # To use this driver the parent model must define the following pins (an alias is fine):
9
+ # :tclk
10
+ # :tdi
11
+ # :tdo
12
+ # :tms
13
+ class Driver
14
+ REQUIRED_PINS = [:tclk, :tdi, :tdo, :tms]
15
+
16
+ include TAPController
17
+ include Origen::Registers
18
+
19
+ # Returns the object that instantiated the JTAG
20
+ attr_reader :owner
21
+
22
+ # Returns the current value in the instruction register
23
+ attr_reader :ir_value
24
+
25
+ attr_accessor :tclk_format
26
+ # Set true to print out debug comments about all state transitions
27
+ attr_accessor :verbose
28
+ alias_method :verbose?, :verbose
29
+
30
+ # Log all state changes in pattern comments, false by default
31
+ attr_accessor :log_state_changes
32
+
33
+ def initialize(owner, options = {})
34
+ @owner = owner
35
+ validate_pins
36
+
37
+ # The parent can configure JTAG settings by defining this constant
38
+ if defined?(owner.class::JTAG_CONFIG)
39
+ options = owner.class::JTAG_CONFIG.merge(options)
40
+ end
41
+
42
+ # Fallback defaults
43
+ options = {
44
+ verbose: false,
45
+ tclk_format: :rh, # format of JTAG clock used: ReturnHigh (:rh), ReturnLo (:rl)
46
+ 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.
47
+ # e.g. @tclk_multiple = 2, @tclk_format = :rh, means one cycle with Tck low (non-return), one with Tck high (NR)
48
+ # @tclk_multiple = 4, @tclk_format = :rl, means 2 cycles with Tck high (NR), 2 with Tck low (NR)
49
+ tdo_strobe: :tclk_high, # when using multiple cycles for TCK, when to strobe for TDO, options include:
50
+ # :tclk_high - strobe TDO only when TCK is high
51
+ # :tclk_low - strobe TDO only when TCK is low
52
+ # :tclk_all - strobe TDO throughout TCK cycle
53
+ 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.)
54
+ # 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)
55
+ init_state: :unknown
56
+ }.merge(options)
57
+
58
+ init_tap_controller(options)
59
+
60
+ @verbose = options[:verbose]
61
+ @ir_value = :unknown
62
+ @tclk_format = options[:tclk_format]
63
+ @tclk_multiple = options[:tclk_multiple]
64
+ @tdo_strobe = options[:tdo_strobe]
65
+ @tdo_store_cycle = options[:tdo_store_cycle]
66
+ @state = options[:init_state]
67
+ @log_state_changes = options[:log_state_changes] || false
68
+ end
69
+
70
+ # Shift data into the TDI pin or out of the TDO pin.
71
+ #
72
+ # There is no TAP controller state checking or handling here, it just
73
+ # shifts some data directly into the pattern, so it is assumed that some
74
+ # higher level logic is co-ordinating the TAP Controller.
75
+ #
76
+ # Most applications should not call this method directly and should instead
77
+ # use the pre-packaged read/write_dr/ir methods.
78
+ # However it is provided as a public API for the corner cases like generating
79
+ # an overlay subroutine pattern where it would be necessary to generate some JTAG
80
+ # vectors outwith the normal state controller wrapper.
81
+ #
82
+ # @param [Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit] reg_or_val
83
+ # Value to be shifted. If a reg/bit collection is supplied this can be pre-marked for
84
+ # read, store or overlay and which will result in the requested action being applied to
85
+ # the cycles corresponding to those bits only (don't care cycles will be generated for the others).
86
+ # @param [Hash] options Options to customize the operation
87
+ # @option options [Integer] :size The number of bits to shift. This is optional
88
+ # when supplying a register or bit collection in which case the size will be derived from
89
+ # the number of bits supplied. If this option is supplied then it will override
90
+ # the size derived from the bits. If the size is greater than the number of bits
91
+ # provided then the additional space will be padded by 0s or don't cares as appropriate.
92
+ # @option options [Boolean] :read (false) When true the given value will be compared on the TDO pin
93
+ # instead of being shifted into the TDI pin. In the case of a register object being provided
94
+ # only those bits that are actually marked for read will be compared.
95
+ # @option options [Boolean] :cycle_last (false) Normally the last data bit is applied to the
96
+ # pins but not cycled, this is to integrate with the TAPController which usually
97
+ # requires that the TMS value is also changed on the last data bit. To override this
98
+ # default behavior and force a cycle for the last data bit set this to true.
99
+ # @option options [Boolean] :includes_last_bit (true) When true the TMS pin will be driven
100
+ # to 1 on the last cycle of the shift if :cycle_last has been specified. To override this
101
+ # and keep TMS low on the last cycle set this to false. One reason for doing this would be
102
+ # if generating some subroutine vectors which only represented a partial section of a shift
103
+ # operation.
104
+ def shift(reg_or_val, options = {})
105
+ options = {
106
+ read: false,
107
+ cycle_last: false,
108
+ includes_last_bit: true,
109
+ no_subr: false # do not use subroutine for any overlay
110
+ }.merge(options)
111
+
112
+ # save compression state for restoring afterwards
113
+ compression_on = !Origen.tester.dont_compress
114
+
115
+ # clean incoming data
116
+ size = extract_size(reg_or_val, options)
117
+ tdi_reg = extract_shift_in_data(reg_or_val, size, options)
118
+ tdo_reg = extract_shift_out_data(reg_or_val, size, options)
119
+ global_ovl, ovl_reg = extract_overlay_data(reg_or_val, size, options)
120
+
121
+ # let the tester handle overlay if possible
122
+ unless tester.respond_to?(:source_memory)
123
+ # tester does not support direct labels, so can't do
124
+ if options[:no_subr] && !$tester.respond_to?('label')
125
+ cc 'This tester does not support use of labels, cannot do no_subr option as requested'
126
+ cc ' going with subroutine overlay instead'
127
+ options[:no_subr] = false
128
+ end
129
+
130
+ # insert global label if specified
131
+ if global_ovl
132
+ if $tester.respond_to?('label')
133
+ $tester.label(global_ovl, true)
134
+ else
135
+ cc "Unsupported global label: #{global_ovl}"
136
+ end
137
+ end
138
+ end # of let tester handle overlay if possible
139
+
140
+ # loop through each data bit
141
+ last_overlay_label = ''
142
+ size.times do |i|
143
+ store_tdo_this_tclk = false
144
+
145
+ # Set up pin actions for bit transaction (tclk cycle)
146
+
147
+ # TDI
148
+ owner.pin(:tdi).drive(tdi_reg[i])
149
+
150
+ # TDO
151
+ owner.pin(:tdo).dont_care # default setting
152
+ if tdo_reg[i]
153
+ if tdo_reg[i].is_to_be_stored? # store
154
+ store_tdo_this_tclk = true
155
+ owner.pin(:tdo).dont_care if Origen.tester.j750?
156
+ elsif tdo_reg[i].is_to_be_read? # compare/assert
157
+ owner.pin(:tdo).assert(tdo_reg[i])
158
+ end
159
+ end
160
+
161
+ # TMS
162
+ owner.pin(:tms).drive(0)
163
+
164
+ # let tester handle overlay if implemented
165
+ overlay_options = {}
166
+ if tester.respond_to?(:source_memory)
167
+ if ovl_reg[i] && ovl_reg[i].has_overlay? && !Origen.mode.simulation?
168
+ overlay_options[:pins] = owner.pin(:tdi)
169
+ if global_ovl
170
+ overlay_options[:overlay_str] = global_ovl
171
+ else
172
+ overlay_options[:overlay_str] = ovl_reg[i].overlay_str
173
+ end
174
+ if options[:no_subr] || global_ovl
175
+ if global_ovl
176
+ overlay_options[:overlay_style] = :global_label
177
+ else
178
+ overlay_options[:overlay_style] = :label
179
+ end
180
+ end
181
+ tester_subr_overlay = !(options[:no_subr] || global_ovl) && tester.overlay_style == :subroutine
182
+ owner.pin(:tdi).drive(0) if tester_subr_overlay
183
+ owner.pin(:tdo).assert(tdo_reg[i]) if options[:read] unless tester_subr_overlay
184
+ # Force the last bit to be shifted from this method if overlay requested on the last bit
185
+ options[:cycle_last] = true if i == size - 1
186
+ end
187
+ else
188
+ # Overlay - reconfigure pin action for overlay if necessary
189
+ if ovl_reg[i] && ovl_reg[i].has_overlay? && !Origen.mode.simulation?
190
+ if options[:no_subr]
191
+ Origen.tester.dont_compress = true
192
+ if ovl_reg[i].overlay_str != last_overlay_label
193
+ $tester.label(ovl_reg[i].overlay_str)
194
+ last_overlay_label = ovl_reg[i].overlay_str
195
+ end
196
+ owner.pin(:tdo).assert(tdo_reg[i]) if options[:read]
197
+ else
198
+ owner.pin(:tdi).drive(0)
199
+ call_subroutine = ovl_reg[i].overlay_str
200
+ end
201
+ end
202
+ end # of let tester handle overlay
203
+
204
+ # With JTAG pin actions queued up, use block call to tclk_cycle to
205
+ # execute a single TCLK period. Special handling of subroutines,
206
+ # case of last bit in shift, and store vector (within a multi-cycle
207
+ # tclk config).
208
+ if call_subroutine || tester_subr_overlay
209
+ @last_data_vector_shifted = true
210
+ else
211
+ @last_data_vector_shifted = false
212
+ end
213
+
214
+ if call_subroutine
215
+ Origen.tester.call_subroutine(call_subroutine)
216
+ else
217
+ @next_data_vector_to_be_stored = false
218
+ # Don't latch the last bit, that will be done when leaving the state.
219
+ if i != size - 1 || options[:cycle_last]
220
+ if i == size - 1 && options[:includes_last_bit]
221
+ unless tester_subr_overlay
222
+ owner.pin(:tms).drive(1)
223
+ @last_data_vector_shifted = true
224
+ end
225
+ end
226
+ tclk_cycle do
227
+ if store_tdo_this_tclk && @next_data_vector_to_be_stored
228
+ Origen.tester.store_next_cycle(owner.pin(:tdo))
229
+ end
230
+ if overlay_options[:pins].nil?
231
+ Origen.tester.cycle
232
+ else
233
+ Origen.tester.cycle overlay: overlay_options
234
+ overlay_options[:change_data] = false # data change only on first cycle if overlay
235
+ end
236
+ end
237
+ owner.pin(:tdo).dont_care
238
+ else
239
+ @deferred_compare = true
240
+ @deferred_store = true if store_tdo_this_tclk
241
+ end
242
+ end
243
+ end
244
+
245
+ # Clear read and similar flags to reflect that the request has just been fulfilled
246
+ reg_or_val.clear_flags if reg_or_val.respond_to?(:clear_flags)
247
+
248
+ # put back compression if turned on above
249
+ Origen.tester.dont_compress = false if compression_on
250
+ end
251
+
252
+ # Cycles the tester through one TCLK cycle
253
+ # Adjusts for the TCLK format and cycle span
254
+ # Assumes caller will drive pattern to tester
255
+ # via .drive or similar
256
+ def tclk_cycle
257
+ case @tclk_format
258
+ when :rh
259
+ tclk_val = 0
260
+ when :rl
261
+ tclk_val = 1
262
+ else
263
+ fail 'ERROR: Invalid Tclk timing format!'
264
+ end
265
+
266
+ # determine whether to mask TDO on first half cycle
267
+ mask_tdo_half0 = ((@tclk_format == :rl) && (@tdo_strobe == :tclk_low) && (@tclk_multiple > 1)) ||
268
+ ((@tclk_format == :rh) && (@tdo_strobe == :tclk_high) && (@tclk_multiple > 1))
269
+
270
+ # determine whether to mask TDO on second half cycle
271
+ mask_tdo_half1 = ((@tclk_format == :rl) && (@tdo_strobe == :tclk_high) && (@tclk_multiple > 1)) ||
272
+ ((@tclk_format == :rh) && (@tdo_strobe == :tclk_low) && (@tclk_multiple > 1))
273
+
274
+ # determine whether TDO is set to capture for this TCLK cycle
275
+ tdo_to_be_captured = owner.pin(:tdo).to_be_captured?
276
+
277
+ # If TDO is already suspended (by an application) then don't do the
278
+ # suspends below since the resume will clear the application's suspend
279
+ tdo_already_suspended = owner.pin(:tdo).suspended? && !@tdo_suspended_by_driver
280
+
281
+ @tclk_multiple.times do |i|
282
+ # 50% duty cycle if @tclk_multiple is even, otherwise slightly off
283
+
284
+ @next_data_vector_to_be_stored = @tdo_store_cycle == i ? true : false
285
+
286
+ if i < (@tclk_multiple + 1) / 2
287
+ # first half of cycle
288
+ owner.pin(:tclk).drive(tclk_val)
289
+ unless tdo_already_suspended
290
+ unless tdo_to_be_captured
291
+ if mask_tdo_half0
292
+ @tdo_suspended_by_driver = true
293
+ owner.pin(:tdo).suspend
294
+ else
295
+ @tdo_suspended_by_driver = false
296
+ owner.pin(:tdo).resume
297
+ end
298
+ end
299
+ end
300
+ else
301
+ # second half of cycle
302
+ owner.pin(:tclk).drive(1 - tclk_val)
303
+ unless tdo_already_suspended
304
+ unless tdo_to_be_captured
305
+ if mask_tdo_half1
306
+ @tdo_suspended_by_driver = true
307
+ owner.pin(:tdo).suspend
308
+ else
309
+ @tdo_suspended_by_driver = false
310
+ owner.pin(:tdo).resume
311
+ end
312
+ end
313
+ end
314
+ end
315
+ yield
316
+ end
317
+ if @tdo_suspended_by_driver
318
+ owner.pin(:tdo).resume
319
+ @tdo_suspended_by_driver = false
320
+ end
321
+ end
322
+
323
+ # Applies the given value to the TMS pin and then
324
+ # cycles the tester for one TCLK
325
+ #
326
+ # @param [Integer] val Value to drive on the TMS pin, 0 or 1
327
+ def tms!(val)
328
+ if @deferred_compare
329
+ @deferred_compare = nil
330
+ else
331
+ owner.pin(:tdo).dont_care
332
+ end
333
+
334
+ if @deferred_store
335
+ @deferred_store = nil
336
+ store_tdo_this_tclk = true
337
+ else
338
+ store_tdo_this_tclk = false
339
+ end
340
+ @next_data_vector_to_be_stored = false
341
+
342
+ tclk_cycle do
343
+ if store_tdo_this_tclk && @next_data_vector_to_be_stored
344
+ Origen.tester.store_next_cycle(owner.pin(:tdo))
345
+ end
346
+ owner.pin(:tms).drive!(val)
347
+ end
348
+ end
349
+
350
+ # Write the given value, register or bit collection to the data register.
351
+ # This is a self contained method that will take care of the TAP controller
352
+ # state transitions, exiting with the TAP controller in Run-Test/Idle.
353
+ #
354
+ # @param [Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit] reg_or_val
355
+ # Value to be written. If a reg/bit collection is supplied this can be pre-marked for overlay.
356
+ # @param [Hash] options Options to customize the operation
357
+ # @option options [Integer] :size The number of bits to write. This is optional
358
+ # when supplying a register or bit collection in which case the size will be derived from
359
+ # the number of bits supplied. If this option is supplied then it will override
360
+ # the size derived from the bits. If the size is greater than the number of bits
361
+ # provided then the additional space will be padded by 0s.
362
+ # @option options [String] :msg By default will not make any comments directly here. Can pass
363
+ # a msg to be written out prior to shifting data.
364
+ def write_dr(reg_or_val, options = {})
365
+ if Origen.tester.respond_to?(:write_dr)
366
+ Origen.tester.write_dr(reg_or_val, options)
367
+ else
368
+ if options[:msg]
369
+ cc "#{options[:msg]}\n"
370
+ end
371
+ val = reg_or_val.respond_to?(:data) ? reg_or_val.data : reg_or_val
372
+ shift_dr(write: val.to_hex) do
373
+ shift(reg_or_val, options)
374
+ end
375
+ end
376
+ end
377
+
378
+ # Read the given value, register or bit collection from the data register.
379
+ # This is a self contained method that will take care of the TAP controller
380
+ # state transitions, exiting with the TAP controller in Run-Test/Idle.
381
+ #
382
+ # @param [Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit] reg_or_val
383
+ # Value to be read. If a reg/bit collection is supplied this can be pre-marked for read in which
384
+ # case only the marked bits will be read and the vectors corresponding to the data from the non-read
385
+ # bits will be set to don't care. Similarly the bits can be pre-marked for store (capture) or
386
+ # overlay.
387
+ # @param [Hash] options Options to customize the operation
388
+ # @option options [Integer] :size The number of bits to read. This is optional
389
+ # when supplying a register or bit collection in which case the size will be derived from
390
+ # the number of bits supplied. If the size is supplied then it will override
391
+ # the size derived from the bits. If the size is greater than the number of bits
392
+ # provided then the additional space will be padded by don't care cycles.
393
+ # @option options [String] :msg By default will not make any comments directly here. Can pass
394
+ # a msg to be written out prior to shifting data.
395
+ def read_dr(reg_or_val, options = {})
396
+ if Origen.tester.respond_to?(:read_dr)
397
+ Origen.tester.read_dr(reg_or_val, options)
398
+ else
399
+ options = {
400
+ read: true
401
+ }.merge(options)
402
+ if options[:msg]
403
+ cc "#{options[:msg]}\n"
404
+ end
405
+ shift_dr(read: Origen::Utility.read_hex(reg_or_val)) do
406
+ shift(reg_or_val, options)
407
+ end
408
+ end
409
+ end
410
+
411
+ # Write the given value, register or bit collection to the instruction register.
412
+ # This is a self contained method that will take care of the TAP controller
413
+ # state transitions, exiting with the TAP controller in Run-Test/Idle.
414
+ #
415
+ # @param [Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit] reg_or_val
416
+ # Value to be written. If a reg/bit collection is supplied this can be pre-marked for overlay.
417
+ # @param [Hash] options Options to customize the operation
418
+ # @option options [Integer] :size The number of bits to write. This is optional
419
+ # when supplying a register or bit collection in which case the size will be derived from
420
+ # the number of bits supplied. If this option is supplied then it will override
421
+ # the size derived from the bits. If the size is greater than the number of bits
422
+ # provided then the additional space will be padded by 0s.
423
+ # @option options [Boolean] :force By default multiple calls to this method will not generate
424
+ # multiple writes. This is to allow wrapper algorithms to remain efficient yet not have to
425
+ # manually track the IR state (and in many cases this may be impossible due to multiple
426
+ # protocols using the same JTAG). To force a write regardless of what the driver thinks the IR
427
+ # contains set this to true.
428
+ # @option options [String] :msg By default will not make any comments directly here. Can pass
429
+ # a msg to be written out prior to shifting in IR data. Will not write comment only if write
430
+ # occurs.
431
+ def write_ir(reg_or_val, options = {})
432
+ if Origen.tester.respond_to?(:write_ir)
433
+ Origen.tester.write_ir(reg_or_val, options)
434
+ else
435
+ val = reg_or_val.respond_to?(:data) ? reg_or_val.data : reg_or_val
436
+ if val != ir_value || options[:force]
437
+ if options[:msg]
438
+ cc "#{options[:msg]}\n"
439
+ end
440
+ shift_ir(write: val.to_hex) do
441
+ shift(reg_or_val, options)
442
+ end
443
+ @ir_value = val
444
+ end
445
+ end
446
+ end
447
+
448
+ # Read the given value, register or bit collection from the instruction register.
449
+ # This is a self contained method that will take care of the TAP controller
450
+ # state transitions, exiting with the TAP controller in Run-Test/Idle.
451
+ #
452
+ # @param [Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit] reg_or_val
453
+ # Value to be read. If a reg/bit collection is supplied this can be pre-marked for read in which
454
+ # case only the marked bits will be read and the vectors corresponding to the data from the non-read
455
+ # bits will be set to don't care. Similarly the bits can be pre-marked for store (capture) or
456
+ # overlay.
457
+ # @param [Hash] options Options to customize the operation
458
+ # @option options [Integer] :size The number of bits to read. This is optional
459
+ # when supplying a register or bit collection in which case the size will be derived from
460
+ # the number of bits supplied. If the size is supplied then it will override
461
+ # the size derived from the bits. If the size is greater than the number of bits
462
+ # provided then the additional space will be padded by don't care cycles.
463
+ # @option options [String] :msg By default will not make any comments directly here. Can pass
464
+ # a msg to be written out prior to shifting data.
465
+ def read_ir(reg_or_val, options = {})
466
+ if Origen.tester.respond_to?(:read_ir)
467
+ Origen.tester.read_ir(reg_or_val, options)
468
+ else
469
+ options = {
470
+ read: true
471
+ }.merge(options)
472
+ if options[:msg]
473
+ cc "#{options[:msg]}\n"
474
+ end
475
+ shift_ir(read: Origen::Utility.read_hex(reg_or_val)) do
476
+ shift(reg_or_val, options)
477
+ end
478
+ end
479
+ end
480
+
481
+ private
482
+
483
+ # Return size of transaction. Options[:size] has priority and need not match the
484
+ # register size. Any mismatch will be handled by the api.
485
+ def extract_size(reg_or_val, options = {})
486
+ size = options[:size]
487
+ unless size
488
+ if reg_or_val.is_a?(Fixnum) || !reg_or_val.respond_to?(:size)
489
+ fail 'When suppling a value to JTAG::Driver#shift you must supply a :size in the options!'
490
+ else
491
+ size = reg_or_val.size
492
+ end
493
+ end
494
+ size
495
+ end
496
+
497
+ # Combine any legacy options into a single global overlay and create
498
+ # new bit collection to track any bit-wise overlays.
499
+ def extract_overlay_data(reg_or_val, size, options = {})
500
+ if reg_or_val.respond_to?(:data)
501
+ ovl = reg_or_val.dup
502
+ else
503
+ ovl = Reg.dummy(size)
504
+ end
505
+
506
+ if options[:overlay]
507
+ global = options[:overlay_label]
508
+ elsif options.key?(:arm_debug_overlay) # prob don't need this anymore
509
+ global = options[:arm_debug_overlay] # prob don't need this anymore
510
+ else
511
+ global = nil
512
+ end
513
+
514
+ [global, ovl]
515
+ end
516
+
517
+ # Create data that will be shifted in on TDI, create new bit collection
518
+ # on the fly if reg_or_val arg is data only. Consider read operation
519
+ # where caller has requested (specific) shift in data to be used.
520
+ def extract_shift_in_data(reg_or_val, size, options = {})
521
+ if reg_or_val.respond_to?(:data)
522
+ if options[:read]
523
+ data = options[:shift_in_data] || 0
524
+ tdi = Reg.dummy(size)
525
+ tdi.write(data)
526
+ else
527
+ tdi = reg_or_val.dup
528
+ end
529
+ else
530
+ # Not a register model, so can't support bit-wise overlay
531
+ tdi = Reg.dummy(size)
532
+ if options[:read]
533
+ data = options[:shift_in_data] || 0
534
+ tdi.write(data)
535
+ else
536
+ tdi.write(reg_or_val)
537
+ end
538
+ end
539
+ tdi
540
+ end
541
+
542
+ # Create data that will be shifted out on TDO, create new bit collection
543
+ # on the fly if reg_or_val arg is data only. Consider write operation
544
+ # where caller has requested (specific) shift out data to be compared.
545
+ def extract_shift_out_data(reg_or_val, size, options = {})
546
+ if reg_or_val.respond_to?(:data)
547
+ if options[:read]
548
+ tdo = reg_or_val.dup
549
+ tdo.read(options) unless options[:mask].nil?
550
+ else
551
+ tdo = Reg.dummy(size) unless options[:shift_out_data].is_a?(Origen::Registers::Reg)
552
+ end
553
+ unless options[:read] # if this is a write operation
554
+ if options[:shift_out_data]
555
+ if options[:shift_out_data].class.to_s =~ /Origen::Registers/
556
+ tdo = options[:shift_out_data]
557
+ else
558
+ tdo.write(options[:shift_out_data])
559
+ tdo.read(options)
560
+ end
561
+ else
562
+ tdo.write(0)
563
+ end
564
+ end
565
+ else
566
+ tdo = Reg.dummy(size)
567
+ if options[:read]
568
+ tdo.write(reg_or_val)
569
+ tdo.read(options)
570
+ else
571
+ if options[:shift_out_data]
572
+ if options[:shift_out_data].class.to_s =~ /Origen::Registers/
573
+ tdo = options[:shift_out_data]
574
+ else
575
+ tdo.write(options[:shift_out_data])
576
+ tdo.read(options)
577
+ end
578
+ else
579
+ tdo.write(0)
580
+ end
581
+ end
582
+ end
583
+ tdo
584
+ end
585
+
586
+ # Validates that the parent object (the owner) has defined the necessary
587
+ # pins to implement the JTAG
588
+ def validate_pins
589
+ REQUIRED_PINS.each do |name|
590
+ owner.pin(name)
591
+ end
592
+ rescue
593
+ puts 'Missing JTAG pins!'
594
+ puts "In order to use the JTAG driver your #{owner.class} class must define"
595
+ puts 'the following pins (an alias is fine):'
596
+ puts REQUIRED_PINS
597
+ raise 'JTAG driver error!'
598
+ end
599
+ end
600
+ end