origen_jtag 0.17.0 → 0.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,579 +1,595 @@
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
- overlay_options[:overlay_str] = ovl_reg[i].overlay_str
170
- overlay_options[:overlay_style] = :label if options[:no_subr]
171
- end
172
- else
173
- # Overlay - reconfigure pin action for overlay if necessary
174
- if ovl_reg[i] && ovl_reg[i].has_overlay? && !Origen.mode.simulation?
175
- if options[:no_subr]
176
- Origen.tester.dont_compress = true
177
- if ovl_reg[i].overlay_str != last_overlay_label
178
- $tester.label(ovl_reg[i].overlay_str)
179
- last_overlay_label = ovl_reg[i].overlay_str
180
- end
181
- owner.pin(:tdo).assert(tdo_reg[i]) if options[:read]
182
- else
183
- owner.pin(:tdi).drive(0)
184
- call_subroutine = ovl_reg[i].overlay_str
185
- end
186
- end
187
- end # of let tester handle overlay
188
-
189
- # With JTAG pin actions queued up, use block call to tclk_cycle to
190
- # execute a single TCLK period. Special handling of subroutines,
191
- # case of last bit in shift, and store vector (within a multi-cycle
192
- # tclk config).
193
- if call_subroutine && !tester.respond_to?(:source_memory)
194
- Origen.tester.call_subroutine(call_subroutine)
195
- @last_data_vector_shifted = true
196
- else
197
- @last_data_vector_shifted = false
198
- @next_data_vector_to_be_stored = false
199
-
200
- # Don't latch the last bit, that will be done when leaving the state.
201
- if i != size - 1 || options[:cycle_last]
202
- if i == size - 1 && options[:includes_last_bit]
203
- owner.pin(:tms).drive(1)
204
- end
205
- tclk_cycle do
206
- if store_tdo_this_tclk && @next_data_vector_to_be_stored
207
- Origen.tester.store_next_cycle(owner.pin(:tdo))
208
- end
209
- if overlay_options[:pins].nil?
210
- Origen.tester.cycle
211
- else
212
- Origen.tester.cycle overlay: overlay_options
213
- overlay_options[:change_data] = false # data change only on first cycle if overlay
214
- end
215
- end
216
- owner.pin(:tdo).dont_care
217
- else
218
- @deferred_compare = true
219
- @deferred_store = true if store_tdo_this_tclk
220
- end
221
- end
222
- end
223
-
224
- # Clear read and similar flags to reflect that the request has just been fulfilled
225
- reg_or_val.clear_flags if reg_or_val.respond_to?(:clear_flags)
226
-
227
- # put back compression if turned on above
228
- Origen.tester.dont_compress = false if compression_on
229
- end
230
-
231
- # Cycles the tester through one TCLK cycle
232
- # Adjusts for the TCLK format and cycle span
233
- # Assumes caller will drive pattern to tester
234
- # via .drive or similar
235
- def tclk_cycle
236
- case @tclk_format
237
- when :rh
238
- tclk_val = 0
239
- when :rl
240
- tclk_val = 1
241
- else
242
- fail 'ERROR: Invalid Tclk timing format!'
243
- end
244
-
245
- # determine whether to mask TDO on first half cycle
246
- mask_tdo_half0 = ((@tclk_format == :rl) && (@tdo_strobe == :tclk_low) && (@tclk_multiple > 1)) ||
247
- ((@tclk_format == :rh) && (@tdo_strobe == :tclk_high) && (@tclk_multiple > 1))
248
-
249
- # determine whether to mask TDO on second half cycle
250
- mask_tdo_half1 = ((@tclk_format == :rl) && (@tdo_strobe == :tclk_high) && (@tclk_multiple > 1)) ||
251
- ((@tclk_format == :rh) && (@tdo_strobe == :tclk_low) && (@tclk_multiple > 1))
252
-
253
- # determine whether TDO is set to capture for this TCLK cycle
254
- tdo_to_be_captured = owner.pin(:tdo).to_be_captured?
255
-
256
- # If TDO is already suspended (by an application) then don't do the
257
- # suspends below since the resume will clear the application's suspend
258
- tdo_already_suspended = owner.pin(:tdo).suspended? && !@tdo_suspended_by_driver
259
-
260
- @tclk_multiple.times do |i|
261
- # 50% duty cycle if @tclk_multiple is even, otherwise slightly off
262
-
263
- @next_data_vector_to_be_stored = @tdo_store_cycle == i ? true : false
264
-
265
- if i < (@tclk_multiple + 1) / 2
266
- # first half of cycle
267
- owner.pin(:tclk).drive(tclk_val)
268
- unless tdo_already_suspended
269
- unless tdo_to_be_captured
270
- if mask_tdo_half0
271
- @tdo_suspended_by_driver = true
272
- owner.pin(:tdo).suspend
273
- else
274
- @tdo_suspended_by_driver = false
275
- owner.pin(:tdo).resume
276
- end
277
- end
278
- end
279
- else
280
- # second half of cycle
281
- owner.pin(:tclk).drive(1 - tclk_val)
282
- unless tdo_already_suspended
283
- unless tdo_to_be_captured
284
- if mask_tdo_half1
285
- @tdo_suspended_by_driver = true
286
- owner.pin(:tdo).suspend
287
- else
288
- @tdo_suspended_by_driver = false
289
- owner.pin(:tdo).resume
290
- end
291
- end
292
- end
293
- end
294
- yield
295
- end
296
- if @tdo_suspended_by_driver
297
- owner.pin(:tdo).resume
298
- @tdo_suspended_by_driver = false
299
- end
300
- end
301
-
302
- # Applies the given value to the TMS pin and then
303
- # cycles the tester for one TCLK
304
- #
305
- # @param [Integer] val Value to drive on the TMS pin, 0 or 1
306
- def tms!(val)
307
- if @deferred_compare
308
- @deferred_compare = nil
309
- else
310
- owner.pin(:tdo).dont_care
311
- end
312
-
313
- if @deferred_store
314
- @deferred_store = nil
315
- store_tdo_this_tclk = true
316
- else
317
- store_tdo_this_tclk = false
318
- end
319
- @next_data_vector_to_be_stored = false
320
-
321
- tclk_cycle do
322
- if store_tdo_this_tclk && @next_data_vector_to_be_stored
323
- Origen.tester.store_next_cycle(owner.pin(:tdo))
324
- end
325
- owner.pin(:tms).drive!(val)
326
- end
327
- end
328
-
329
- # Write the given value, register or bit collection to the data register.
330
- # This is a self contained method that will take care of the TAP controller
331
- # state transitions, exiting with the TAP controller in Run-Test/Idle.
332
- #
333
- # @param [Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit] reg_or_val
334
- # Value to be written. If a reg/bit collection is supplied this can be pre-marked for overlay.
335
- # @param [Hash] options Options to customize the operation
336
- # @option options [Integer] :size The number of bits to write. This is optional
337
- # when supplying a register or bit collection in which case the size will be derived from
338
- # the number of bits supplied. If this option is supplied then it will override
339
- # the size derived from the bits. If the size is greater than the number of bits
340
- # provided then the additional space will be padded by 0s.
341
- # @option options [String] :msg By default will not make any comments directly here. Can pass
342
- # a msg to be written out prior to shifting data.
343
- def write_dr(reg_or_val, options = {})
344
- if Origen.tester.respond_to?(:write_dr)
345
- Origen.tester.write_dr(reg_or_val, options)
346
- else
347
- if options[:msg]
348
- cc "#{options[:msg]}\n"
349
- end
350
- val = reg_or_val.respond_to?(:data) ? reg_or_val.data : reg_or_val
351
- shift_dr(write: val.to_hex) do
352
- shift(reg_or_val, options)
353
- end
354
- end
355
- end
356
-
357
- # Read the given value, register or bit collection from the data register.
358
- # This is a self contained method that will take care of the TAP controller
359
- # state transitions, exiting with the TAP controller in Run-Test/Idle.
360
- #
361
- # @param [Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit] reg_or_val
362
- # Value to be read. If a reg/bit collection is supplied this can be pre-marked for read in which
363
- # case only the marked bits will be read and the vectors corresponding to the data from the non-read
364
- # bits will be set to don't care. Similarly the bits can be pre-marked for store (capture) or
365
- # overlay.
366
- # @param [Hash] options Options to customize the operation
367
- # @option options [Integer] :size The number of bits to read. This is optional
368
- # when supplying a register or bit collection in which case the size will be derived from
369
- # the number of bits supplied. If the size is supplied then it will override
370
- # the size derived from the bits. If the size is greater than the number of bits
371
- # provided then the additional space will be padded by don't care cycles.
372
- # @option options [String] :msg By default will not make any comments directly here. Can pass
373
- # a msg to be written out prior to shifting data.
374
- def read_dr(reg_or_val, options = {})
375
- if Origen.tester.respond_to?(:read_dr)
376
- Origen.tester.read_dr(reg_or_val, options)
377
- else
378
- options = {
379
- read: true
380
- }.merge(options)
381
- if options[:msg]
382
- cc "#{options[:msg]}\n"
383
- end
384
- shift_dr(read: Origen::Utility.read_hex(reg_or_val)) do
385
- shift(reg_or_val, options)
386
- end
387
- end
388
- end
389
-
390
- # Write the given value, register or bit collection to the instruction register.
391
- # This is a self contained method that will take care of the TAP controller
392
- # state transitions, exiting with the TAP controller in Run-Test/Idle.
393
- #
394
- # @param [Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit] reg_or_val
395
- # Value to be written. If a reg/bit collection is supplied this can be pre-marked for overlay.
396
- # @param [Hash] options Options to customize the operation
397
- # @option options [Integer] :size The number of bits to write. This is optional
398
- # when supplying a register or bit collection in which case the size will be derived from
399
- # the number of bits supplied. If this option is supplied then it will override
400
- # the size derived from the bits. If the size is greater than the number of bits
401
- # provided then the additional space will be padded by 0s.
402
- # @option options [Boolean] :force By default multiple calls to this method will not generate
403
- # multiple writes. This is to allow wrapper algorithms to remain efficient yet not have to
404
- # manually track the IR state (and in many cases this may be impossible due to multiple
405
- # protocols using the same JTAG). To force a write regardless of what the driver thinks the IR
406
- # contains set this to true.
407
- # @option options [String] :msg By default will not make any comments directly here. Can pass
408
- # a msg to be written out prior to shifting in IR data. Will not write comment only if write
409
- # occurs.
410
- def write_ir(reg_or_val, options = {})
411
- if Origen.tester.respond_to?(:write_ir)
412
- Origen.tester.write_ir(reg_or_val, options)
413
- else
414
- val = reg_or_val.respond_to?(:data) ? reg_or_val.data : reg_or_val
415
- if val != ir_value || options[:force]
416
- if options[:msg]
417
- cc "#{options[:msg]}\n"
418
- end
419
- shift_ir(write: val.to_hex) do
420
- shift(reg_or_val, options)
421
- end
422
- @ir_value = val
423
- end
424
- end
425
- end
426
-
427
- # Read the given value, register or bit collection from the instruction register.
428
- # This is a self contained method that will take care of the TAP controller
429
- # state transitions, exiting with the TAP controller in Run-Test/Idle.
430
- #
431
- # @param [Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit] reg_or_val
432
- # Value to be read. If a reg/bit collection is supplied this can be pre-marked for read in which
433
- # case only the marked bits will be read and the vectors corresponding to the data from the non-read
434
- # bits will be set to don't care. Similarly the bits can be pre-marked for store (capture) or
435
- # overlay.
436
- # @param [Hash] options Options to customize the operation
437
- # @option options [Integer] :size The number of bits to read. This is optional
438
- # when supplying a register or bit collection in which case the size will be derived from
439
- # the number of bits supplied. If the size is supplied then it will override
440
- # the size derived from the bits. If the size is greater than the number of bits
441
- # provided then the additional space will be padded by don't care cycles.
442
- # @option options [String] :msg By default will not make any comments directly here. Can pass
443
- # a msg to be written out prior to shifting data.
444
- def read_ir(reg_or_val, options = {})
445
- if Origen.tester.respond_to?(:read_ir)
446
- Origen.tester.read_ir(reg_or_val, options)
447
- else
448
- options = {
449
- read: true
450
- }.merge(options)
451
- if options[:msg]
452
- cc "#{options[:msg]}\n"
453
- end
454
- shift_ir(read: Origen::Utility.read_hex(reg_or_val)) do
455
- shift(reg_or_val, options)
456
- end
457
- end
458
- end
459
-
460
- private
461
-
462
- # Return size of transaction. Options[:size] has priority and need not match the
463
- # register size. Any mismatch will be handled by the api.
464
- def extract_size(reg_or_val, options = {})
465
- size = options[:size]
466
- unless size
467
- if reg_or_val.is_a?(Fixnum) || !reg_or_val.respond_to?(:size)
468
- fail 'When suppling a value to JTAG::Driver#shift you must supply a :size in the options!'
469
- else
470
- size = reg_or_val.size
471
- end
472
- end
473
- size
474
- end
475
-
476
- # Combine any legacy options into a single global overlay and create
477
- # new bit collection to track any bit-wise overlays.
478
- def extract_overlay_data(reg_or_val, size, options = {})
479
- if reg_or_val.respond_to?(:data)
480
- ovl = reg_or_val.dup
481
- else
482
- ovl = Reg.dummy(size)
483
- end
484
-
485
- if options[:overlay]
486
- global = options[:overlay_label]
487
- elsif options.key?(:arm_debug_overlay) # prob don't need this anymore
488
- global = options[:arm_debug_overlay] # prob don't need this anymore
489
- else
490
- global = nil
491
- end
492
-
493
- [global, ovl]
494
- end
495
-
496
- # Create data that will be shifted in on TDI, create new bit collection
497
- # on the fly if reg_or_val arg is data only. Consider read operation
498
- # where caller has requested (specific) shift in data to be used.
499
- def extract_shift_in_data(reg_or_val, size, options = {})
500
- if reg_or_val.respond_to?(:data)
501
- if options[:read]
502
- data = options[:shift_in_data] || 0
503
- tdi = Reg.dummy(size)
504
- tdi.write(data)
505
- else
506
- tdi = reg_or_val.dup
507
- end
508
- else
509
- # Not a register model, so can't support bit-wise overlay
510
- tdi = Reg.dummy(size)
511
- if options[:read]
512
- data = options[:shift_in_data] || 0
513
- tdi.write(data)
514
- else
515
- tdi.write(reg_or_val)
516
- end
517
- end
518
- tdi
519
- end
520
-
521
- # Create data that will be shifted out on TDO, create new bit collection
522
- # on the fly if reg_or_val arg is data only. Consider write operation
523
- # where caller has requested (specific) shift out data to be compared.
524
- def extract_shift_out_data(reg_or_val, size, options = {})
525
- if reg_or_val.respond_to?(:data)
526
- if options[:read]
527
- tdo = reg_or_val.dup
528
- tdo.read(options) unless options[:mask].nil?
529
- else
530
- tdo = Reg.dummy(size) unless options[:shift_out_data].is_a?(Origen::Registers::Reg)
531
- end
532
- unless options[:read] # if this is a write operation
533
- if options[:shift_out_data]
534
- if options[:shift_out_data].is_a?(Origen::Registers::Reg)
535
- tdo = options[:shift_out_data]
536
- else
537
- tdo.write(options[:shift_out_data])
538
- tdo.read(options)
539
- end
540
- else
541
- tdo.write(0)
542
- end
543
- end
544
- else
545
- tdo = Reg.dummy(size)
546
- if options[:read]
547
- tdo.write(reg_or_val)
548
- tdo.read(options)
549
- else
550
- if options[:shift_out_data]
551
- if options[:shift_out_data].is_a?(Origen::Registers::Reg)
552
- tdo = options[:shift_out_data]
553
- else
554
- tdo.write(options[:shift_out_data])
555
- tdo.read(options)
556
- end
557
- else
558
- tdo.write(0)
559
- end
560
- end
561
- end
562
- tdo
563
- end
564
-
565
- # Validates that the parent object (the owner) has defined the necessary
566
- # pins to implement the JTAG
567
- def validate_pins
568
- REQUIRED_PINS.each do |name|
569
- owner.pin(name)
570
- end
571
- rescue
572
- puts 'Missing JTAG pins!'
573
- puts "In order to use the JTAG driver your #{owner.class} class must define"
574
- puts 'the following pins (an alias is fine):'
575
- puts REQUIRED_PINS
576
- raise 'JTAG driver error!'
577
- end
578
- end
579
- 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
+ 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