origen_jtag 0.17.0 → 0.17.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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