origen_jtag 0.19.0 → 0.19.1

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