Class: OrigenJTAG::Driver

Inherits:
Object
  • Object
show all
Includes:
Origen::Model, TAPController
Defined in:
lib/origen_jtag/driver.rb

Overview

This driver provides methods to read and write from a JTAG instruction and data registers.

Low level methods are also provided for fine control of the TAP Controller state machine via the TAPController module.

To use this driver the parent model must define the following pins (an alias is fine):

:tck
:tdi
:tdo
:tms

Constant Summary collapse

REQUIRED_PINS =
[:tck, :tdi, :tdo, :tms]

Constants included from TAPController

TAPController::STATES

Instance Attribute Summary collapse

Attributes included from TAPController

#state

Instance Method Summary collapse

Methods included from TAPController

#idle, #pause_dr, #pause_ir, #reset, #shift_dr, #shift_ir, #state_str, #update_state

Constructor Details

#initialize(owner, options = {}) ⇒ Driver

Returns a new instance of Driver.



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/origen_jtag/driver.rb', line 72

def initialize(owner, options = {})
  if owner.is_a?(Hash)
    @owner = parent
    options = owner
  else
    @owner = owner
  end
  # The parent can configure JTAG settings by defining this constant
  if defined?(owner.class::JTAG_CONFIG)
    options = owner.class::JTAG_CONFIG.merge(options)
  end

  @cycle_callback = options[:cycle_callback]
  @given_options = options.dup  # Save these for later use in the pins method

  # Fallback defaults
  options = {
    verbose:         false,
    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.)
    # 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)
    init_state:      :unknown
  }.merge(options)

  init_tap_controller(options)

  @verbose = options[:verbose]
  @ir_value = :unknown
  @tck_format = options[:tck_format] || options[:tclk_format] || :rh
  @tck_multiple = options[:tck_multiple] || options[:tclk_multiple] || 1
  self.tdo_strobe = options[:tdo_strobe] || :tck_high
  @tdo_store_cycle = options[:tdo_store_cycle]
  @state = options[:init_state]
  @log_state_changes = options[:log_state_changes] || false
  if options[:tck_vals] || options[:tclk_vals]
    @tck_vals = options[:tck_vals] || options[:tclk_vals]
    unless @tck_vals.is_a?(Hash) && @tck_vals.key?(:on) && @tck_vals.key?(:off)
      fail "When specifying TCK values, you must supply a hash with both :on and :off keys, e.g. tck_vals: { on: 'P', off: 0 }"
    end
  end
  if @cycle_callback && @tck_multiple != 1
    fail 'A cycle_callback can only be used with a tck_multiple setting of 1'
  end

  @chained_ir_msb_length = options[:chained_ir_msb_length]
  @chained_ir_msb_data = options[:chained_ir_msb_data] || 0
  @chained_ir_lsb_length = options[:chained_ir_lsb_length]
  @chained_ir_lsb_data = options[:chained_ir_lsb_data] || 0
  @chained_dr_msb_length = options[:chained_dr_msb_length]
  @chained_dr_msb_data = options[:chained_dr_msb_data] || 0
  @chained_dr_lsb_length = options[:chained_dr_lsb_length]
  @chained_dr_lsb_data = options[:chained_dr_lsb_data] || 0
end

Instance Attribute Details

#chained_dr_lsb_data ⇒ Object

by default, the chained DR data is all zeros, this value overrides



70
71
72
# File 'lib/origen_jtag/driver.rb', line 70

def chained_dr_lsb_data
  @chained_dr_lsb_data
end

#chained_dr_lsb_length ⇒ Object

number of additional DR bits to add when chaining multiple devices, these additional bits are added to the LSB side



67
68
69
# File 'lib/origen_jtag/driver.rb', line 67

def chained_dr_lsb_length
  @chained_dr_lsb_length
end

#chained_dr_msb_data ⇒ Object

by default, the chained DR data is all zeros, this value overrides



64
65
66
# File 'lib/origen_jtag/driver.rb', line 64

def chained_dr_msb_data
  @chained_dr_msb_data
end

#chained_dr_msb_length ⇒ Object

number of additional DR bits to add when chaining multiple devices, these additional bits are added to the MSB side



61
62
63
# File 'lib/origen_jtag/driver.rb', line 61

def chained_dr_msb_length
  @chained_dr_msb_length
end

#chained_ir_lsb_data ⇒ Object

by default, the chained IR data is all zeros, this value overrides



58
59
60
# File 'lib/origen_jtag/driver.rb', line 58

def chained_ir_lsb_data
  @chained_ir_lsb_data
end

#chained_ir_lsb_length ⇒ Object

number of additional IR bits to add when chaining multiple devices, these additional bits are added to the LSB side



55
56
57
# File 'lib/origen_jtag/driver.rb', line 55

def chained_ir_lsb_length
  @chained_ir_lsb_length
end

#chained_ir_msb_data ⇒ Object

by default, the chained IR data is all zeros, this value overrides



52
53
54
# File 'lib/origen_jtag/driver.rb', line 52

def chained_ir_msb_data
  @chained_ir_msb_data
end

#chained_ir_msb_length ⇒ Object

number of additional IR bits to add when chaining multiple devices, these additional bits are added to the MSB side



49
50
51
# File 'lib/origen_jtag/driver.rb', line 49

def chained_ir_msb_length
  @chained_ir_msb_length
end

#ir_value ⇒ Object (readonly)

Returns the current value in the instruction register



24
25
26
# File 'lib/origen_jtag/driver.rb', line 24

def ir_value
  @ir_value
end

#log_state_changes ⇒ Object

Log all state changes in pattern comments, false by default



46
47
48
# File 'lib/origen_jtag/driver.rb', line 46

def log_state_changes
  @log_state_changes
end

#owner ⇒ Object (readonly)

Returns the object that instantiated the JTAG



21
22
23
# File 'lib/origen_jtag/driver.rb', line 21

def owner
  @owner
end

#tck_format ⇒ Object Also known as: tclk_format

Wave/timing format of the JTAG clock: :rh (ReturnHigh) or :rl (ReturnLo), :rh is the default



34
35
36
# File 'lib/origen_jtag/driver.rb', line 34

def tck_format
  @tck_format
end

#tck_multiple ⇒ Object Also known as: tclk_multiple

The number of cycles for one clock pulse, assumes 50% duty cycle. Uses tester non-return format to spread TCK across multiple cycles. e.g. @tck_multiple = 2, @tck_format = :rh, means one cycle with Tck low (non-return), one with Tck high (NR) @tck_multiple = 4, @tck_format = :rl, means 2 cycles with Tck high (NR), 2 with Tck low (NR)



29
30
31
# File 'lib/origen_jtag/driver.rb', line 29

def tck_multiple
  @tck_multiple
end

#tdo_store_cycle ⇒ Object

Returns the value of attribute tdo_store_cycle.



39
40
41
# File 'lib/origen_jtag/driver.rb', line 39

def tdo_store_cycle
  @tdo_store_cycle
end

#tdo_strobe ⇒ Object

Returns the value of attribute tdo_strobe.



38
39
40
# File 'lib/origen_jtag/driver.rb', line 38

def tdo_strobe
  @tdo_strobe
end

#verbose ⇒ Object Also known as: verbose?

Set true to print out debug comments about all state transitions



42
43
44
# File 'lib/origen_jtag/driver.rb', line 42

def verbose
  @verbose
end

Instance Method Details

#apply_action(pin, actions) ⇒ Object



613
614
615
616
617
618
# File 'lib/origen_jtag/driver.rb', line 613

def apply_action(pin, actions)
  actions.each do |operation|
    method = operation.shift
    pin.send(method, *operation) if method
  end
end

#cycle_callback? ⇒ Boolean

When true it means that the application is dealing with how to handle the 4 JTAG signals for each JTAG cycle. In that case this driver calculates what state the 4 pins should be in each signal and then calls back to the application with that information and it is up to the application to decide what to do with that information and when/if to generate tester cycles.

Returns:

  • (Boolean)


170
171
172
# File 'lib/origen_jtag/driver.rb', line 170

def cycle_callback?
  !!@cycle_callback
end

#read_dr(reg_or_val, options = {}) ⇒ Object

Read the given value, register or bit collection from the data register. This is a self contained method that will take care of the TAP controller state transitions, exiting with the TAP controller in Run-Test/Idle.

Parameters:

  • reg_or_val (Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit) —

    Value to be read. If a reg/bit collection is supplied this can be pre-marked for read in which case only the marked bits will be read and the vectors corresponding to the data from the non-read bits will be set to don't care. Similarly the bits can be pre-marked for store (capture) or overlay.

  • options (Hash) (defaults to: {}) —

    Options to customize the operation

Options Hash (options):

  • :size (Integer) —

    The number of bits to read. This is optional when supplying a register or bit collection in which case the size will be derived from the number of bits supplied. If the size is supplied then it will override the size derived from the bits. If the size is greater than the number of bits provided then the additional space will be padded by don't care cycles.

  • :msg (String) —

    By default will not make any comments directly here. Can pass a msg to be written out prior to shifting data.



524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
# File 'lib/origen_jtag/driver.rb', line 524

def read_dr(reg_or_val, options = {})
  options = options.merge(get_chained_in_data(:dr))
  if Origen.tester.respond_to?(:read_dr)
    Origen.tester.read_dr(reg_or_val, options)
  else
    options = {
      read: true
    }.merge(options)
    if options[:msg]
      cc "#{options[:msg]}\n"
    end
    shift_dr(options.merge(read: Origen::Utility.read_hex(reg_or_val))) do
      shift(reg_or_val, options)
    end
  end
end

#read_ir(reg_or_val, options = {}) ⇒ Object

Read the given value, register or bit collection from the instruction register. This is a self contained method that will take care of the TAP controller state transitions, exiting with the TAP controller in Run-Test/Idle.

Parameters:

  • reg_or_val (Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit) —

    Value to be read. If a reg/bit collection is supplied this can be pre-marked for read in which case only the marked bits will be read and the vectors corresponding to the data from the non-read bits will be set to don't care. Similarly the bits can be pre-marked for store (capture) or overlay.

  • options (Hash) (defaults to: {}) —

    Options to customize the operation

Options Hash (options):

  • :size (Integer) —

    The number of bits to read. This is optional when supplying a register or bit collection in which case the size will be derived from the number of bits supplied. If the size is supplied then it will override the size derived from the bits. If the size is greater than the number of bits provided then the additional space will be padded by don't care cycles.

  • :msg (String) —

    By default will not make any comments directly here. Can pass a msg to be written out prior to shifting data.



596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
# File 'lib/origen_jtag/driver.rb', line 596

def read_ir(reg_or_val, options = {})
  options = options.merge(get_chained_in_data(:ir))
  if Origen.tester.respond_to?(:read_ir)
    Origen.tester.read_ir(reg_or_val, options)
  else
    options = {
      read: true
    }.merge(options)
    if options[:msg]
      cc "#{options[:msg]}\n"
    end
    shift_ir(options.merge(read: Origen::Utility.read_hex(reg_or_val))) do
      shift(reg_or_val, options)
    end
  end
end

#shift(reg_or_val, options = {}) ⇒ Object

Shift data into the TDI pin or out of the TDO pin.

There is no TAP controller state checking or handling here, it just shifts some data directly into the pattern, so it is assumed that some higher level logic is co-ordinating the TAP Controller.

Most applications should not call this method directly and should instead use the pre-packaged read/write_dr/ir methods. However it is provided as a public API for the corner cases like generating an overlay subroutine pattern where it would be necessary to generate some JTAG vectors outwith the normal state controller wrapper.

Parameters:

  • reg_or_val (Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit) —

    Value to be shifted. If a reg/bit collection is supplied this can be pre-marked for read, store or overlay and which will result in the requested action being applied to the cycles corresponding to those bits only (don't care cycles will be generated for the others).

  • options (Hash) (defaults to: {}) —

    Options to customize the operation

Options Hash (options):

  • :size (Integer) —

    The number of bits to shift. This is optional when supplying a register or bit collection in which case the size will be derived from the number of bits supplied. If this option is supplied then it will override the size derived from the bits. If the size is greater than the number of bits provided then the additional space will be padded by 0s or don't cares as appropriate.

  • :read (Boolean) — default: false —

    When true the given value will be compared on the TDO pin instead of being shifted into the TDI pin. In the case of a register object being provided only those bits that are actually marked for read will be compared.

  • :cycle_last (Boolean) — default: false —

    Normally the last data bit is applied to the pins but not cycled, this is to integrate with the TAPController which usually requires that the TMS value is also changed on the last data bit. To override this default behavior and force a cycle for the last data bit set this to true.

  • :includes_last_bit (Boolean) — default: true —

    When true the TMS pin will be driven to 1 on the last cycle of the shift if :cycle_last has been specified. To override this and keep TMS low on the last cycle set this to false. One reason for doing this would be if generating some subroutine vectors which only represented a partial section of a shift operation.



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
# File 'lib/origen_jtag/driver.rb', line 208

def shift(reg_or_val, options = {})
  options = {
    read:              false,
    cycle_last:        false,
    includes_last_bit: true,
    no_subr:           false      # do not use subroutine for any overlay
  }.merge(options)

  # save compression state for restoring afterwards
  compression_on = !Origen.tester.dont_compress

  # clean incoming data
  size = extract_size(reg_or_val, options)
  tdi_reg = extract_shift_in_data(reg_or_val, size, options)
  tdo_reg = extract_shift_out_data(reg_or_val, size, options)
  global_ovl, ovl_reg = extract_overlay_data(reg_or_val, size, options)

  # let the tester handle overlay if possible
  unless tester.respond_to?(:source_memory)
    # tester does not support direct labels, so can't do
    if options[:no_subr] && !$tester.respond_to?('label')
      cc 'This tester does not support use of labels, cannot do no_subr option as requested'
      cc '  going with subroutine overlay instead'
      options[:no_subr] = false
    end

    # insert global label if specified
    if global_ovl
      if $tester.respond_to?('label')
        $tester.label(global_ovl, true)
      else
        cc "Unsupported global label: #{global_ovl}"
      end
    end
  end # of let tester handle overlay if possible

  # loop through any LSB appended bits
  if options[:tdi_lsb_append_size]
    # tdo is always don't care for appended bits
    action :tdo, :dont_care
    cc "appending #{options[:tdi_lsb_append_size]} LSB bits"
    options[:tdi_lsb_append_size].times do |i|
      action :tdi, :drive, options[:tdi_lsb_append_data][i]
      tck_cycle { cycle }
    end
  end

  # loop through each data bit
  last_overlay_label = ''
  size.times do |i|
    store_tdo_this_tck = false

    # Set up pin actions for bit transaction (tck cycle)

    # TDI
    action :tdi, :drive, tdi_reg[i]

    # TDO
    action :tdo, :dont_care                                 # default setting
    if tdo_reg[i]
      if tdo_reg[i].is_to_be_stored?                        # store
        store_tdo_this_tck = true
        action :tdo, :dont_care if Origen.tester.j750?
      elsif tdo_reg[i].is_to_be_read?                       # compare/assert
        action :tdo, :assert, tdo_reg[i], meta: { position: i }
      end
    end

    # TMS
    action :tms, :drive, 0

    # let tester handle overlay if implemented
    overlay_options = {}
    if tester.respond_to?(:source_memory) && !cycle_callback?
      if ovl_reg[i] && ovl_reg[i].has_overlay? && !Origen.mode.simulation?
        overlay_options[:pins] = pins[:tdi]
        if global_ovl
          overlay_options[:overlay_str] = global_ovl
        else
          overlay_options[:overlay_str] = ovl_reg[i].overlay_str
        end
        if options[:no_subr] || global_ovl
          if global_ovl
            overlay_options[:overlay_style] = :global_label
          else
            overlay_options[:overlay_style] = :label
          end
        end
        tester_subr_overlay = !(options[:no_subr] || global_ovl) && tester.overlay_style == :subroutine
        action :tdi, :drive, 0 if tester_subr_overlay
        action :tdo, :assert, tdo_reg[i], meta: { position: i } unless tester_subr_overlay || !options[:read]
        # Force the last bit to be shifted from this method if overlay requested on the last bit
        options[:cycle_last] = true if i == size - 1
      end
    else
      # Overlay - reconfigure pin action for overlay if necessary
      if ovl_reg[i] && ovl_reg[i].has_overlay? && !Origen.mode.simulation?
        if options[:no_subr]
          Origen.tester.dont_compress = true
          if ovl_reg[i].overlay_str != last_overlay_label
            $tester.label(ovl_reg[i].overlay_str)
            last_overlay_label = ovl_reg[i].overlay_str
          end
          action :tdo, :assert, tdo_reg[i], meta: { position: i } if options[:read]
        else
          action :tdi, :drive, 0
          call_subroutine = ovl_reg[i].overlay_str
        end
      end
    end # of let tester handle overlay

    # With JTAG pin actions queued up, use block call to tck_cycle to
    #   execute a single TCK period.  Special handling of subroutines,
    #   case of last bit in shift, and store vector (within a multi-cycle
    #   tck config).
    if (call_subroutine || tester_subr_overlay) && !options[:tdi_msb_append_size]
      @last_data_vector_shifted = true
    else
      @last_data_vector_shifted = false
    end

    if call_subroutine
      Origen.tester.call_subroutine(call_subroutine)
    else
      @next_data_vector_to_be_stored = false
      # Don't latch the last bit, that will be done when leaving the state.
      if i != size - 1 || options[:cycle_last] || options[:tdi_msb_append_size]
        if i == size - 1 && options[:includes_last_bit] && !options[:tdi_msb_append_size]
          unless tester_subr_overlay
            action :tms, :drive, 1
            @last_data_vector_shifted = true
          end
        end
        tck_cycle do
          if store_tdo_this_tck && @next_data_vector_to_be_stored
            action :store
          end
          if overlay_options[:pins].nil? || cycle_callback?
            cycle
          else
            cycle overlay: overlay_options
            overlay_options[:change_data] = false			# data change only on first cycle if overlay
          end
        end
        pins[:tdo].dont_care unless cycle_callback?
      else
        @deferred_compare = true
        @deferred_store = true if store_tdo_this_tck
      end
    end
  end

  # loop through any MSB append bits
  if options[:tdi_msb_append_size]
    # last tdi bit was left applied, so tck cycle first, then apply new tdi and leave last one for state machine driver
    options[:tdi_msb_append_size].times do |i|
      if i == 0
        cc "appending #{options[:tdi_msb_append_size]} MSB bits"
        action :tdo, :dont_care
      end
      action :tdi, :drive, options[:tdi_msb_append_data][i]
      tck_cycle { cycle } unless i == options[:tdi_msb_append_size] - 1
    end
  end

  # Clear read and similar flags to reflect that the request has just been fulfilled
  reg_or_val.clear_flags if reg_or_val.respond_to?(:clear_flags)

  # put back compression if turned on above
  Origen.tester.dont_compress = false if compression_on
end

#tck_cycle ⇒ Object Also known as: tclk_cycle

Cycles the tester through one TCK cycle Adjusts for the TCK format and cycle span Assumes caller will drive pattern to tester via .drive or similar



384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
# File 'lib/origen_jtag/driver.rb', line 384

def tck_cycle
  if cycle_callback?
    @next_data_vector_to_be_stored = @tdo_store_cycle
    yield
  else
    case @tck_format
      when :rh
        tck_val = 0
      when :rl
        tck_val = 1
      else
        fail 'ERROR: Invalid Tclk timing format!'
    end

    # determine whether to mask TDO on first half cycle
    mask_tdo_half0 =  ((@tck_format == :rl) && (@tdo_strobe == :tck_low) && (@tck_multiple > 1)) ||
                      ((@tck_format == :rh) && (@tdo_strobe == :tck_high) && (@tck_multiple > 1))

    # determine whether to mask TDO on second half cycle
    mask_tdo_half1 =  ((@tck_format == :rl) && (@tdo_strobe == :tck_high) && (@tck_multiple > 1)) ||
                      ((@tck_format == :rh) && (@tdo_strobe == :tck_low) && (@tck_multiple > 1))

    # If TDO is already suspended (by an application) then don't do the
    # suspends below since the resume will clear the application's suspend
    tdo_already_suspended = !cycle_callback? && pins[:tdo].suspended? && !@tdo_suspended_by_driver

    @tck_multiple.times do |i|
      # 50% duty cycle if @tck_multiple is even, otherwise slightly off

      @next_data_vector_to_be_stored = @tdo_store_cycle == i ? true : false

      if i < (@tck_multiple + 1) / 2
        # first half of cycle
        pins[:tck].drive(@tck_vals ? @tck_vals[:on] : tck_val)
        unless tdo_already_suspended
          if mask_tdo_half0
            @tdo_suspended_by_driver = true
            pins[:tdo].suspend
          else
            @tdo_suspended_by_driver = false
            pins[:tdo].resume
          end
        end
      else
        # second half of cycle
        pins[:tck].drive(@tck_vals ? @tck_vals[:off] : (1 - tck_val))
        unless tdo_already_suspended
          if mask_tdo_half1
            @tdo_suspended_by_driver = true
            pins[:tdo].suspend
          else
            @tdo_suspended_by_driver = false
            pins[:tdo].resume
          end
        end
      end
      yield
    end
    if @tdo_suspended_by_driver
      @tdo_suspended_by_driver = false
      pins[:tdo].resume
    end
  end
end

#tms!(val) ⇒ Object

Applies the given value to the TMS pin and then cycles the tester for one TCK

Parameters:

  • val (Integer) —

    Value to drive on the TMS pin, 0 or 1



454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
# File 'lib/origen_jtag/driver.rb', line 454

def tms!(val)
  if @deferred_compare
    @deferred_compare = nil
  else
    action :tdo, :dont_care
  end

  if @deferred_store
    @deferred_store = nil
    store_tdo_this_tck = true
  else
    store_tdo_this_tck = false
  end
  @next_data_vector_to_be_stored = false

  tck_cycle do
    if store_tdo_this_tck && @next_data_vector_to_be_stored
      action :store
    end
    action :tms, :drive, val
    cycle
  end
end

#write_dr(reg_or_val, options = {}) ⇒ Object

Write the given value, register or bit collection to the data register. This is a self contained method that will take care of the TAP controller state transitions, exiting with the TAP controller in Run-Test/Idle.

Parameters:

  • reg_or_val (Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit) —

    Value to be written. If a reg/bit collection is supplied this can be pre-marked for overlay.

  • options (Hash) (defaults to: {}) —

    Options to customize the operation

Options Hash (options):

  • :size (Integer) —

    The number of bits to write. This is optional when supplying a register or bit collection in which case the size will be derived from the number of bits supplied. If this option is supplied then it will override the size derived from the bits. If the size is greater than the number of bits provided then the additional space will be padded by 0s.

  • :msg (String) —

    By default will not make any comments directly here. Can pass a msg to be written out prior to shifting data.



492
493
494
495
496
497
498
499
500
501
502
503
504
505
# File 'lib/origen_jtag/driver.rb', line 492

def write_dr(reg_or_val, options = {})
  options = options.merge(get_chained_in_data(:dr))
  if Origen.tester.respond_to?(:write_dr)
    Origen.tester.write_dr(reg_or_val, options)
  else
    if options[:msg]
      cc "#{options[:msg]}\n"
    end
    val = reg_or_val.respond_to?(:data) ? reg_or_val.data : reg_or_val
    shift_dr(options.merge(write: val.to_hex)) do
      shift(reg_or_val, options)
    end
  end
end

#write_ir(reg_or_val, options = {}) ⇒ Object

Write the given value, register or bit collection to the instruction register. This is a self contained method that will take care of the TAP controller state transitions, exiting with the TAP controller in Run-Test/Idle.

Parameters:

  • reg_or_val (Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit) —

    Value to be written. If a reg/bit collection is supplied this can be pre-marked for overlay.

  • options (Hash) (defaults to: {}) —

    Options to customize the operation

Options Hash (options):

  • :size (Integer) —

    The number of bits to write. This is optional when supplying a register or bit collection in which case the size will be derived from the number of bits supplied. If this option is supplied then it will override the size derived from the bits. If the size is greater than the number of bits provided then the additional space will be padded by 0s.

  • :force (Boolean) —

    By default multiple calls to this method will not generate multiple writes. This is to allow wrapper algorithms to remain efficient yet not have to manually track the IR state (and in many cases this may be impossible due to multiple protocols using the same JTAG). To force a write regardless of what the driver thinks the IR contains set this to true.

  • :msg (String) —

    By default will not make any comments directly here. Can pass a msg to be written out prior to shifting in IR data. Will not write comment only if write occurs.



561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
# File 'lib/origen_jtag/driver.rb', line 561

def write_ir(reg_or_val, options = {})
  options = options.merge(get_chained_in_data(:ir))
  val = reg_or_val.respond_to?(:data) ? reg_or_val.data : reg_or_val
  if val != ir_value || options[:force]
    if options[:msg]
      cc "#{options[:msg]}\n"
    end
    if Origen.tester.respond_to?(:write_ir)
      Origen.tester.write_ir(reg_or_val, options)
    else
      shift_ir(options.merge(write: val.to_hex)) do
        shift(reg_or_val, options)
      end
    end
    @ir_value = val
  end
end