Class: Origen::Pins::Pin

Inherits:
Object show all
Includes:
OrgFile::Interceptable, PinCommon
Defined in:
lib/origen/pins/pin.rb

Direct Known Subclasses

GroundPin, OtherPin, PowerPin, VirtualPin

Constant Summary collapse

ORG_FILE_INTERCEPTED_METHODS =

Don't include the ! method in here, the cycle will be captured at the tester level and it would cause a double cycle in the org file if also captured at the pin

[
  :suspend, :resume, :repeat_previous=,
  :drive_hi, :write_hi, :drive_very_hi, :drive_lo, :write_lo, :drive_mem, :expect_mem,
  :assert_hi, :expect_hi, :compare_hi, :read_hi, :assert_lo, :expect_lo, :compare_lo, :read_lo, :dont_care,
  :drive, :write, :assert, :compare, :expect, :read, :assert_midband, :compare_midband, :expect_midband, :read_midband,
  :toggle, :capture, :store
]
FUNCTION_SCOPED_ATTRIBUTES =

Any attributes listed here will be looked up for the current function defined by the current mode and configuration context before falling back to a default

[:name, :direction, :option, :group, :ip_block, :meta]
PACKAGE_SCOPED_ATTRIBUTES =

Any attributes listed here will be looked up for the current package context before falling back to a default

[:location, :dib_assignment, :dib_meta]
TYPES =

Pin Types

[:analog, :digital]

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from OrgFile::Interceptable

#__interceptor__=, included, #myself

Methods included from PinCommon

#add_configuration, #add_mode, #add_package, #enabled?, #enabled_in_configuration?, #enabled_in_mode?, #enabled_in_package?, #finalize, #id=, #to_sym

Constructor Details

#initialize(id, owner, options = {}) ⇒ Pin

Should be instantiated through the HasPins macros



68
69
70
71
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
# File 'lib/origen/pins/pin.rb', line 68

def initialize(id, owner, options = {}) # :nodoc:
  options = {
    reset:        :dont_care,
    invert:       false,
    direction:    :io,
    open_drain:   false,
    ext_pullup:   false,
    ext_pulldown: false,
    rtl_name:     nil
  }.merge(options)
  @aliases = {}
  @functions = {}
  @direction = sanitize_direction(options[:direction])
  @invert = options[:invert]
  @reset = options[:reset]
  @force = options[:force] & 1
  @id = id
  @name = options[:name]
  @rtl_name = options[:rtl_name]
  @suspend = false
  @order = options[:order]
  @supply = options[:supply]
  @open_drain = options[:open_drain]
  @ext_pullup = options[:ext_pullup]
  @ext_pulldown = options[:ext_pulldown]
  @type = options[:type]
  @dib_assignment = [] # Array to handle multi-site testing
  @size = 1
  @value = 0
  @clock = nil
  @meta = options[:meta] || {}
  @dib_meta = options[:dib_meta] || {}
  @state_meta = {}
  @_saved_state = []
  @_saved_value = []
  @_saved_suspend = []
  @_saved_invert = []
  @_saved_repeat_previous = []
  on_init(owner, options)
  # Assign the initial state from the method so that any inversion is picked up...
  send(@reset)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(m, *args, &block) ⇒ Object



1154
1155
1156
1157
1158
1159
1160
# File 'lib/origen/pins/pin.rb', line 1154

def method_missing(m, *args, &block)
  if meta.include? m
    meta[m]
  else
    super
  end
end

Instance Attribute Details

#aliasesObject (readonly)

Returns a hash containing the aliases associated with the given pin



37
38
39
# File 'lib/origen/pins/pin.rb', line 37

def aliases
  @aliases
end

#descriptionObject

Returns the value of attribute description



56
57
58
# File 'lib/origen/pins/pin.rb', line 56

def description
  @description
end

#ext_pulldownObject

Boolean on whether pin has external pull-down



48
49
50
# File 'lib/origen/pins/pin.rb', line 48

def ext_pulldown
  @ext_pulldown
end

#ext_pullupObject

Boolean on whether pin has external pull-up



46
47
48
# File 'lib/origen/pins/pin.rb', line 46

def ext_pullup
  @ext_pullup
end

#forceObject

Value to be forced on the pin, e.g. during simulation



54
55
56
# File 'lib/origen/pins/pin.rb', line 54

def force
  @force
end

#functionsObject

Returns a hash containing the functions associated with the given pin



39
40
41
# File 'lib/origen/pins/pin.rb', line 39

def functions
  @functions
end

#invertObject

Inverts pin states for drive and compare, can be useful if a timing set change requires clocks to drive low for example when all pattern logic has been set up to drive them high.



30
31
32
# File 'lib/origen/pins/pin.rb', line 30

def invert
  @invert
end

#notesObject

Returns the value of attribute notes



57
58
59
# File 'lib/origen/pins/pin.rb', line 57

def notes
  @notes
end

#open_drainObject

Boolean on whether pin is open drain



44
45
46
# File 'lib/origen/pins/pin.rb', line 44

def open_drain
  @open_drain
end

#orderObject

Returns the value of attribute order



28
29
30
# File 'lib/origen/pins/pin.rb', line 28

def order
  @order
end

#ownerObject (readonly)

Returns the value of attribute owner



34
35
36
# File 'lib/origen/pins/pin.rb', line 34

def owner
  @owner
end

#repeat_previousObject

Attribute used to generate vectors where the pin state is assigned the repeat_previous opcode, used by Tester#repeat_previous



33
34
35
# File 'lib/origen/pins/pin.rb', line 33

def repeat_previous
  @repeat_previous
end

#rtl_nameObject

Pin RTL name



52
53
54
# File 'lib/origen/pins/pin.rb', line 52

def rtl_name
  @rtl_name
end

#sizeObject (readonly)

Returns the value of attribute size



35
36
37
# File 'lib/origen/pins/pin.rb', line 35

def size
  @size
end

#state_metaObject (readonly)

Returns a hash containing any meta data associated with the current pin state

my_pin.read!(1, meta: { position: 10 })
my_pin.state_meta    # => { position: 10 }
my_pin.dont_care
my_pin.state_meta    # => {}


65
66
67
# File 'lib/origen/pins/pin.rb', line 65

def state_meta
  @state_meta
end

#supplyObject

Internal power supply pin is connected to



41
42
43
# File 'lib/origen/pins/pin.rb', line 41

def supply
  @supply
end

#supply_strObject

Returns the value of attribute supply_str



42
43
44
# File 'lib/origen/pins/pin.rb', line 42

def supply_str
  @supply_str
end

#typeObject

Pin type, either :analog or :digital



50
51
52
# File 'lib/origen/pins/pin.rb', line 50

def type
  @type
end

Instance Method Details

#<=>(other_pin) ⇒ Object

When sorting pins do it by ID



193
194
195
# File 'lib/origen/pins/pin.rb', line 193

def <=>(other_pin)
  @id <=> other_pin.id
end

#add_alias(id, options = {}) ⇒ Object

Add an alias to the given pin.

If the options contain a package, mode or configuration reference then the alias will only work under that context.



556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
# File 'lib/origen/pins/pin.rb', line 556

def add_alias(id, options = {})
  obj = options.delete(:obj) || myself
  if aliases[id]
    aliases[id][:packages] += resolve_packages(options)
    aliases[id][:modes] += resolve_modes(options)
    aliases[id][:configurations] += resolve_configurations(options)
    aliases[id][:packages].uniq!
    aliases[id][:modes].uniq!
    aliases[id][:configurations].uniq!
  else
    aliases[id] = {
      packages:       resolve_packages(options),
      modes:          resolve_modes(options),
      configurations: resolve_configurations(options)
    }
    Origen.pin_bank.register_alias(id, obj, options)
  end
end

#add_dib_assignment(str, options = {}) ⇒ Object Also known as: add_dib_info, add_channel

Add a Device Interface Board (e.g. probecard at wafer probe or loadboard at final package test) assignment to the pin. Some refer to this as a channel but API name is meant to be generic.



448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
# File 'lib/origen/pins/pin.rb', line 448

def add_dib_assignment(str, options = {})
  options = {
    site: 0
  }.merge(options)
  packages = resolve_packages(options)
  if packages.empty?
    @dib_assignment[options[:site]] = str
    add_alias str.to_s.symbolize, package: :all, mode: :all, configuration: :all
  else
    packages.each do |package_id|
      package_id = package_id.respond_to?(:id) ? package_id.id : package_id
      myself.packages[package_id] ||= {}
      myself.packages[package_id][:dib_assignment] ||= []
      myself.packages[package_id][:dib_assignment][options[:site]] = str
      add_alias str.to_s.symbolize, package: package_id, mode: :all, configuration: :all
    end
  end
end

#add_dib_meta(pkg, options) ⇒ Object



469
470
471
472
473
474
475
476
477
478
479
# File 'lib/origen/pins/pin.rb', line 469

def add_dib_meta(pkg, options)
  unless Origen.top_level.packages.include? pkg
    Origen.log.error("Cannot add DIB metadata for package '#{pkg}', that package has not been added yet!")
    fail
  end
  options.each do |attr, attr_value|
    packages[pkg][:dib_meta] ||= {}
    packages[pkg][:dib_meta][attr] = attr_value
    add_alias attr_value.to_s.symbolize, package: pkg, mode: :all, configuration: :all
  end
end

#add_function(id, options = {}) ⇒ Object

Add a function to the pin.

Examples:

Adding a mode-specific function

pin.add_function :tdi, :direction => :input
pin.add_function :nvm_fail, :mode => :nvmbist, :direction => :output


512
513
514
515
516
517
# File 'lib/origen/pins/pin.rb', line 512

def add_function(id, options = {})
  id = id.to_sym
  add_function_attributes(options.merge(name: id, id: id.to_sym))
  f = FunctionProxy.new(id, myself)
  add_alias id, packages: :all, obj: f
end

#add_function_attributes(options = {}) ⇒ Object



519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
# File 'lib/origen/pins/pin.rb', line 519

def add_function_attributes(options = {})
  id = options.delete(:id)
  modes = resolve_modes(options)
  configurations = resolve_configurations(options)
  options[:direction] = sanitize_direction(options[:direction]) if options[:direction]
  if modes.empty?
    modes = [:all]
  end
  if configurations.empty?
    configurations = [:all]
  end
  # Supports newer attribute lookup by function ID
  if id
    functions[:ids] ||= {}
    if functions[:ids][id]
      functions[:ids][id] = functions[:ids][id].merge!(options)
    else
      functions[:ids][id] = options.dup
    end
  end
  # Supports older attribute lookup by mode context
  modes.each do |mode|
    configurations.each do |configuration|
      functions[mode.to_sym] ||= {}
      if functions[mode.to_sym][configuration.to_sym]
        functions[mode.to_sym][configuration.to_sym] = functions[mode.to_sym][configuration.to_sym].merge!(options)
      else
        functions[mode.to_sym][configuration.to_sym] = options
      end
    end
  end
end

#add_location(str, options = {}) ⇒ Object Also known as: add_locn

Add a location identifier to the pin, this is a free format field which can be a pin number or BGA co-ordinate for example.

Examples:

Adding a location by package

$dut.pin(:pin3).add_location "B3", :package => :p1
$dut.pin(:pin3).add_location "B2", :package => :p2


430
431
432
433
434
435
436
437
438
439
440
441
442
443
# File 'lib/origen/pins/pin.rb', line 430

def add_location(str, options = {})
  packages = resolve_packages(options)
  if packages.empty?
    @location = str
    add_alias str.to_s.symbolize, package: :all, mode: :all, configuration: :all
  else
    packages.each do |package_id|
      package_id = package_id.respond_to?(:id) ? package_id.id : package_id
      myself.packages[package_id] ||= {}
      myself.packages[package_id][:location] = str
      add_alias str.to_s.symbolize, package: package_id, mode: :all, configuration: :all
    end
  end
end

#assert(value, options = {}) ⇒ Object Also known as: compare, expect, read

Pass in 0 or 1 to have the pin expect_lo or expect_hi respectively. This is useful when programatically setting the pin state.

Example

[0,1,1,0].each do |level|
    $pin(:d_in).assert(level)
end


843
844
845
846
# File 'lib/origen/pins/pin.rb', line 843

def assert(value, options = {})
  set_state_with_options(:compare, options)
  set_value(value)
end

#assert!(*args) ⇒ Object Also known as: compare!, expect!, read!



851
852
853
854
# File 'lib/origen/pins/pin.rb', line 851

def assert!(*args)
  assert(*args)
  cycle
end

#assert_hi(options = {}) ⇒ Object Also known as: expect_hi, compare_hi, read_hi

Set the pin to expect a 1 on future cycles



768
769
770
771
# File 'lib/origen/pins/pin.rb', line 768

def assert_hi(options = {})
  set_state_with_options(:compare, options)
  set_value(1)
end

#assert_hi!(options = {}) ⇒ Object Also known as: expect_hi!, compare_hi!, read_hi!



776
777
778
779
# File 'lib/origen/pins/pin.rb', line 776

def assert_hi!(options = {})
  assert_hi(options)
  cycle
end

#assert_lo(options = {}) ⇒ Object Also known as: expect_lo, compare_lo, read_lo

Set the pin to expect a 0 on future cycles



785
786
787
788
789
790
791
792
793
794
795
796
# File 'lib/origen/pins/pin.rb', line 785

def assert_lo(options = {})
  set_state_with_options(:compare, options)
  set_value(0)
  # Planning to add the active load logic to the tester instead...
  # options = { :active => false    #if active true means to take tester active load capability into account
  #          }.merge(options)
  # unless state_to_be_inverted?
  #  myself.state = ($tester.active_loads || !options[:active]) ? $tester.pin_state(:expect_lo) : $tester.pin_state(:dont_care)
  # else
  #  myself.state = ($tester.active_loads || !options[:active]) ? $tester.pin_state(:expect_hi) : $tester.pin_state(:dont_care)
  # end
end

#assert_lo!(options = {}) ⇒ Object Also known as: expect_lo!, compare_lo!, read_lo!



801
802
803
804
# File 'lib/origen/pins/pin.rb', line 801

def assert_lo!(options = {})
  assert_lo(options)
  cycle
end

#assert_midband(options = {}) ⇒ Object Also known as: compare_midband, expect_midband, read_midband



859
860
861
# File 'lib/origen/pins/pin.rb', line 859

def assert_midband(options = {})
  set_state_with_options(:compare_midband, options)
end

#assert_midband!(options = {}) ⇒ Object Also known as: compare_midband!, expect_midband!, read_midband!



866
867
868
869
# File 'lib/origen/pins/pin.rb', line 866

def assert_midband!(options = {})
  assert_midband(options)
  cycle
end

#belongs_to_a_pin_group?Boolean

Returns true if the pin belongs to a pin group.

add_pins :jtag, size: 6
add_pin  :done
add_pin_alias :fail, :jtag, pin: 4

pin(:done).belongs_to_a_pin_group?  # => false
pin(:fail).belongs_to_a_pin_group?  # => true

Returns:

  • (Boolean)


617
618
619
# File 'lib/origen/pins/pin.rb', line 617

def belongs_to_a_pin_group?
  !groups.empty?
end

#capture(options = {}) ⇒ Object Also known as: store

Mark the (data) from the pin to be captured



927
928
929
# File 'lib/origen/pins/pin.rb', line 927

def capture(options = {})
  set_state_with_options(:capture, options)
end

#capture!(options = {}) ⇒ Object Also known as: store!

Mark the (data) from the pin to be captured and trigger a cycle



933
934
935
936
# File 'lib/origen/pins/pin.rb', line 933

def capture!(options = {})
  capture(options)
  cycle
end

#clear_mask(context: nil, size: nil) ⇒ Object Also known as: clr_mask, cmask



1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
# File 'lib/origen/pins/pin.rb', line 1115

def clear_mask(context: nil, size: nil)
  index = context.is_a?(Integer) ? context : self.index(context: context)

  if index.nil? && context.nil?
    # If the index is nil and no context was given, no implicit index could be resolved
    fail("Could not discern pin :#{name}'s implicit index!")
  elsif index.nil?
    # If the index is nil and some context was given, then the pin is not in the given context
    fail("Pin :#{name} is not a member of the given context!")
  end

  if size && context && !context.is_a?(Integer)
    # A context was given, that was not just an Integer, and size was given
    # Raise an exception as these two conflict.
    fail('Both a sized context (e.g. pin group) and a :size option cannot be used simultaneously!')
  elsif size
    # A size option was given. Use that.
    ((2**size) - 1) ^ (1 << index)
  elsif context.is_a?(Symbol)
    ((2**groups[context].instance_variable_get(:@store).size) - 1) ^ (1 << index)
  elsif context.respond_to?(:size) && !context.is_a?(Integer)
    # PinCollection or Array
    ((2**context.size) - 1) ^ (1 << index)
  else
    # No size option was given. Use the implicit index instead.
    (2**index) - 1
  end
end

#compare_wave(code = nil) ⇒ Object

Returns the compare cycle wave assigned to the pin based on the currently enabled timeset, or nil if none is set Note that if a timeset is set then all pins will always return a wave as they will pick up a default waveform if none is explicitly assigned to it.



137
138
139
140
141
142
143
144
145
# File 'lib/origen/pins/pin.rb', line 137

def compare_wave(code = nil)
  if t = dut.current_timeset
    # Cache this for performance since potentially this is something that could be called on
    # every cycle in some applications
    @compare_waves ||= {}
    @compare_waves[t.id] ||= {}
    @compare_waves[t.id][code] ||= dut.current_timeset.send(:wave_for, myself, type: :compare, code: code)
  end
end

#comparing?Boolean

Returns true if the pin is currently in a compare state

Returns:

  • (Boolean)


880
881
882
883
# File 'lib/origen/pins/pin.rb', line 880

def comparing?
  !@suspend &&
    state == :compare
end

#comparing_mem?Boolean

Returns true if the pin is currently in a compare mem state

Returns:

  • (Boolean)


886
887
888
889
# File 'lib/origen/pins/pin.rb', line 886

def comparing_mem?
  !@suspend &&
    state == :expect_mem
end

#comparing_midband?Boolean

Returns true if the pin is currently in a compare state

Returns:

  • (Boolean)


892
893
894
895
# File 'lib/origen/pins/pin.rb', line 892

def comparing_midband?
  !@suspend &&
    state == :compare_midband
end

#cycleObject

:nodoc:



697
698
699
# File 'lib/origen/pins/pin.rb', line 697

def cycle # :nodoc:
  Origen.tester.cycle
end

#delete!Object

Delete this pin (myself). Used bang in method name to keep same for pins and pin collections. Pin collections already had a delete method which deletes a pin from the collection. Needed delete! to indicate it is deleting the actual pin or pin group calling the method.



1039
1040
1041
# File 'lib/origen/pins/pin.rb', line 1039

def delete!
  owner.delete_pin(myself)
end

#describe(options = {}) ⇒ Object



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
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
# File 'lib/origen/pins/pin.rb', line 322

def describe(options = {})
  desc = ['********************']
  desc << "Pin id: #{id}"
  func_aliases = []
  unless functions.empty?
    desc << ''
    desc << 'Functions'
    desc << '---------'
    functions.each do |mode, configurations|
      unless mode == :ids
        configurations.each do |configuration, attrs|
          a = ":#{attrs[:name]}".ljust(30)
          func_aliases << attrs[:name]
          unless mode == :all
            a += ":modes => [#{[mode].flatten.map { |id| ':' + id.to_s }.join(', ')}]"
            prev = true
          end
          unless configuration == :all
            a += ' ; ' if prev
            a += ":configurations => [#{[configuration].flatten.map { |id| ':' + id.to_s }.join(', ')}]"
          end
          desc << a
        end
      end
    end
  end
  unless aliases.empty?
    desc << ''
    desc << 'Aliases'
    desc << '-------'
    aliases.each do |name, context|
      unless func_aliases.include?(name)
        a = ":#{name}".ljust(30)
        unless context[:packages].empty? || context[:packages] == [:all]
          a += ":packages => [#{context[:packages].map { |id| ':' + id.to_s }.join(', ')}]"
          prev = true
        end
        unless context[:modes].empty? || context[:modes] == [:all]
          a += ' ; ' if prev
          a += ":modes => [#{context[:modes].map { |id| ':' + id.to_s }.join(', ')}]"
          prev = true
        end
        unless context[:configurations].empty? || context[:configurations] == [:all]
          a += ' ; ' if prev
          a += ":configurations => [#{context[:configurations].map { |id| ':' + id.to_s }.join(', ')}]"
        end
        desc << a
      end
    end
  end
  unless Origen.top_level.modes.empty?
    desc << ''
    desc << 'Modes'
    desc << '-------'
    Origen.top_level.modes.each do |name|
      unless option(mode: name).nil?
        a = ":#{name}".ljust(30) + ":mode => #{option(mode: name)}"
        desc << a
      end
    end
  end
  unless groups.empty?
    desc << ''
    desc << 'Groups'
    desc << '------'
    desc << groups.map { |name, _group| ':' + name.to_s }.join(', ')
  end
  desc << '********************'
  if options[:return]
    desc
  else
    puts desc.join("\n")
  end
end

#direction=(val) ⇒ Object

Sets the default direction of the pin, :input, :output or :io (default). If a function specific direction has been specified that will override this value.



503
504
505
# File 'lib/origen/pins/pin.rb', line 503

def direction=(val)
  @direction = sanitize_direction(val)
end

#disable_clock(options = {}) ⇒ Object



998
999
1000
1001
# File 'lib/origen/pins/pin.rb', line 998

def disable_clock(options = {})
  @clock.stop_clock(options)
  @clock = nil
end

#dont_care(options = {}) ⇒ Object

Set the pin to X on future cycles



810
811
812
# File 'lib/origen/pins/pin.rb', line 810

def dont_care(options = {})
  set_state_with_options(:dont_care, options)
end

#dont_care!(options = {}) ⇒ Object



814
815
816
817
# File 'lib/origen/pins/pin.rb', line 814

def dont_care!(options = {})
  dont_care(options)
  cycle
end

#drive(value, options = {}) ⇒ Object Also known as: write

Pass in 0 or 1 to have the pin drive_lo or drive_hi respectively. This is useful when programatically setting the pin state.

Example

[0,1,1,0].each do |level|
    $pin(:d_in).drive(level)
end


825
826
827
828
# File 'lib/origen/pins/pin.rb', line 825

def drive(value, options = {})
  set_state_with_options(:drive, options)
  set_value(value)
end

#drive!(value, options = {}) ⇒ Object Also known as: write!



831
832
833
834
# File 'lib/origen/pins/pin.rb', line 831

def drive!(value, options = {})
  drive(value, options)
  cycle
end

#drive_hi(options = {}) ⇒ Object Also known as: write_hi

Set the pin to drive a 1 on future cycles



712
713
714
715
# File 'lib/origen/pins/pin.rb', line 712

def drive_hi(options = {})
  set_state_with_options(:drive, options)
  set_value(1)
end

#drive_hi!(options = {}) ⇒ Object Also known as: write_hi!



718
719
720
721
# File 'lib/origen/pins/pin.rb', line 718

def drive_hi!(options = {})
  drive_hi(options)
  cycle
end

#drive_lo(options = {}) ⇒ Object Also known as: write_lo

Set the pin to drive a 0 on future cycles



737
738
739
740
# File 'lib/origen/pins/pin.rb', line 737

def drive_lo(options = {})
  set_state_with_options(:drive, options)
  set_value(0)
end

#drive_lo!(options = {}) ⇒ Object Also known as: write_lo!



743
744
745
746
# File 'lib/origen/pins/pin.rb', line 743

def drive_lo!(options = {})
  drive_lo(options)
  cycle
end

#drive_mem(options = {}) ⇒ Object



749
750
751
# File 'lib/origen/pins/pin.rb', line 749

def drive_mem(options = {})
  set_state_with_options(:drive_mem, options)
end

#drive_mem!(options = {}) ⇒ Object



753
754
755
756
# File 'lib/origen/pins/pin.rb', line 753

def drive_mem!(options = {})
  drive_mem(options)
  cycle
end

#drive_very_hi(options = {}) ⇒ Object

Set the pin to drive a high voltage on future cycles (if the tester supports it). For example on a J750 high-voltage channel the pin state would be set to “2”



726
727
728
729
# File 'lib/origen/pins/pin.rb', line 726

def drive_very_hi(options = {})
  set_state_with_options(:drive_very_hi, options)
  set_value(1)
end

#drive_very_hi!(options = {}) ⇒ Object



731
732
733
734
# File 'lib/origen/pins/pin.rb', line 731

def drive_very_hi!(options = {})
  drive_very_hi(options)
  cycle
end

#drive_wave(code = nil) ⇒ Object

Returns the drive cycle wave assigned to the pin based on the currently enabled timeset, or nil if none is set. Note that if a timeset is set then all pins will always return a wave as they will pick up a default waveform if none is explicitly assigned to it.



123
124
125
126
127
128
129
130
131
# File 'lib/origen/pins/pin.rb', line 123

def drive_wave(code = nil)
  if t = dut.current_timeset
    # Cache this for performance since potentially this is something that could be called on
    # every cycle in some applications
    @drive_waves ||= {}
    @drive_waves[t.id] ||= {}
    @drive_waves[t.id][code] ||= dut.current_timeset.send(:wave_for, myself, type: :drive, code: code)
  end
end

#driving?Boolean

Returns true if the pin is currently in a drive state

Returns:

  • (Boolean)


898
899
900
901
# File 'lib/origen/pins/pin.rb', line 898

def driving?
  !@suspend &&
    (state == :drive || state == :drive_very_hi)
end

#driving_mem?Boolean

Returns true if the pin is currently in a drive mem state

Returns:

  • (Boolean)


904
905
906
907
# File 'lib/origen/pins/pin.rb', line 904

def driving_mem?
  !@suspend &&
    state == :drive_mem
end

#duty_cyclesObject



1022
1023
1024
# File 'lib/origen/pins/pin.rb', line 1022

def duty_cycles
  @clock.cycles_per_duty
end

#enable_clock(options = {}) ⇒ Object



994
995
996
# File 'lib/origen/pins/pin.rb', line 994

def enable_clock(options = {})
  @clock = PinClock.new(myself, options)
end

#expect_mem(options = {}) ⇒ Object



758
759
760
# File 'lib/origen/pins/pin.rb', line 758

def expect_mem(options = {})
  set_state_with_options(:expect_mem, options)
end

#expect_mem!(options = {}) ⇒ Object



762
763
764
765
# File 'lib/origen/pins/pin.rb', line 762

def expect_mem!(options = {})
  expect_mem(options)
  cycle
end

#function_scoped_nameObject



272
# File 'lib/origen/pins/pin.rb', line 272

alias_method :function_scoped_name, :name

#global_path_toObject



111
112
113
# File 'lib/origen/pins/pin.rb', line 111

def global_path_to
  "dut.pins(:#{id})"
end

#goodbyeObject

See Pin#hello



187
188
189
190
# File 'lib/origen/pins/pin.rb', line 187

def goodbye
  @@hello_pins.delete(myself)
  puts "Pin #{name} has stopped toggling"
end

#groupObject Also known as: primary_group

If the pin was defined initially as part of a group then this will return that group, otherwise it will return nil



399
400
401
# File 'lib/origen/pins/pin.rb', line 399

def group
  @primary_group
end

#group_indexObject Also known as: primary_group_index

If the pin is a member of a primary group, this returns its index number within that group, otherwise returns nil



406
407
408
# File 'lib/origen/pins/pin.rb', line 406

def group_index
  @primary_group_index
end

#groupsObject Also known as: pin_groups

Returns a hash containing the pin groups that the given pin is a member of



412
413
414
415
416
417
# File 'lib/origen/pins/pin.rb', line 412

def groups
  # Origen.pin_bank.all_pin_groups.select do |name, group|
  @groups ||= Origen.pin_bank.pin_groups.select do |_name, group|
    group.include?(myself)
  end
end

#half_periodObject



1026
1027
1028
# File 'lib/origen/pins/pin.rb', line 1026

def half_period
  @clock.cycles_per_half_period
end

#has_alias?(id, options = {}) ⇒ Boolean

Returns true if the pin has the given alias within the given or current context

Returns:

  • (Boolean)


576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
# File 'lib/origen/pins/pin.rb', line 576

def has_alias?(id, options = {})
  if aliases[id]
    if options[:ignore_context]
      true
    else
      packages = resolve_packages(options)
      modes = resolve_modes(options)
      configurations = resolve_configurations(options)
      begin
        aliases[id][:packages].include?(:all) || aliases[id][:packages].empty? ||
          packages.any? { |package| aliases[id][:packages].include?(package) }
      end && begin
        aliases[id][:modes].include?(:all) || aliases[id][:modes].empty? ||
          modes.any? { |mode| aliases[id][:modes].include?(mode) }
      end && begin
        aliases[id][:configurations].include?(:all) || aliases[id][:configurations].empty? ||
          configurations.any? { |config| aliases[id][:configurations].include?(config) }
      end
    end
  else
    false
  end
end

#helloObject

Causes the pin to continuously drive 1 for 2 seconds and then drive 0 for 2 seconds.

This is not an API that is intended to be used within a pattern. Rather it is a debug aid when setting up something like a bench test environment that uses Origen Link. For example you would call this method on a pin from a console session, then confirm with a multimeter that the pin is toggling on the relevant hardware.

Call Pin#goodbye to stop it.

Examples:

Call from an origen console like this


dut.pin(:tdi).hello


167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/origen/pins/pin.rb', line 167

def hello
  drive_hi
  @@hello_pins ||= []
  @@hello_pins << myself unless @@hello_pins.include?(myself)
  @@hello_loop ||= Thread.new do
    loop do
      @@hello_pins.each(&:toggle)
      if $tester
        # Add a dummy timeset if one is not set yet, doesn't really matter what it is in this case
        # and better not to force the user to setup a debug workaround due to running outside of a pattern
        $tester.set_timeset('hello_world', 40) unless $tester.timeset
        $tester.cycle
      end
      sleep 2
    end
  end
  puts "Pin #{name} is toggling with a period of 2 seconds"
end

#high_voltage?Boolean

Returns true if pin is in high voltage state

Returns:

  • (Boolean)


910
911
912
913
# File 'lib/origen/pins/pin.rb', line 910

def high_voltage?
  !@suspend &&
    state == :drive_very_hi
end

#index(context: nil) ⇒ Object



1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
# File 'lib/origen/pins/pin.rb', line 1079

def index(context: nil)
  if context.is_a?(Symbol)
    # Context pin group provided
    group = groups[context].instance_variable_get(:@store)
    if group
      group.index(self)
    end
  elsif context.is_a?(Array)
    # Anonymous pin group given
    context.map { |p| p.is_a?(Symbol) ? owner.pin(p) : p }.index(self)
  else
    # Try an index based off of the pin name.
    # Only works if the pin ends in a decimal. Otherwise, returns nil.
    i = name.to_s.index(/\d+$/)
    if i
      name.to_s[i..-1].to_i
    end
  end
end

#index?(context: nil) ⇒ Boolean

Returns:

  • (Boolean)


1075
1076
1077
# File 'lib/origen/pins/pin.rb', line 1075

def index?(context: nil)
  !!index(context: context).nil?
end

#inspectObject



318
319
320
# File 'lib/origen/pins/pin.rb', line 318

def inspect
  "<#{myself.class}:#{object_id}>"
end

#invalidate_group_cacheObject



420
421
422
# File 'lib/origen/pins/pin.rb', line 420

def invalidate_group_cache
  @groups = nil
end

#invalidate_vector_cacheObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



295
296
297
298
# File 'lib/origen/pins/pin.rb', line 295

def invalidate_vector_cache
  @vector_formatted_value = nil
  groups.each { |_name, group| group.invalidate_vector_cache }
end

#inverted?Boolean

Returns the state of invert

Returns:

  • (Boolean)


875
876
877
# File 'lib/origen/pins/pin.rb', line 875

def inverted?
  @invert
end

#is_a_clock?Boolean

Returns:

  • (Boolean)


986
987
988
# File 'lib/origen/pins/pin.rb', line 986

def is_a_clock?
  !(@clock.nil?)
end

#is_a_running_clock?Boolean

Returns:

  • (Boolean)


990
991
992
# File 'lib/origen/pins/pin.rb', line 990

def is_a_running_clock?
  @clock.running?
end

#is_alias_of?(name) ⇒ Boolean

Returns true if the pin is an alias of the given pin name

Returns:

  • (Boolean)


601
602
603
604
605
606
607
# File 'lib/origen/pins/pin.rb', line 601

def is_alias_of?(name)
  if Origen.pin_bank.find(name)
    Origen.pin_bank.find(name).id == Origen.pin_bank.find(myself).id
  else
    false
  end
end

#is_not_a_clock?Boolean

Returns:

  • (Boolean)


982
983
984
# File 'lib/origen/pins/pin.rb', line 982

def is_not_a_clock?
  @clock.nil?
end

#mask(context: nil) ⇒ Object Also known as: set_mask, smask



1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
# File 'lib/origen/pins/pin.rb', line 1099

def mask(context: nil)
  index = context.is_a?(Integer) ? context : self.index(context: context)

  if index.nil? && context.nil?
    # If the index is nil and no context was given, no implicit index could be resolved
    fail("Could not discern pin :#{name}'s implicit index!")
  elsif index.nil?
    # If the index is nil and some context was given, then the pin is not in the given context
    fail("Pin :#{name} is not a member of the given context!")
  end

  2**index
end

#name(options = {}) ⇒ Object

Returns the name of the pin, if a name has been specifically assigned by the application (via name=) then this will be returned, otherwise the name of the current function if present will be returned, and then as a last resort the ID of the pin



277
278
279
280
# File 'lib/origen/pins/pin.rb', line 277

def name(options = {})
  # Return a specifically assigned name in preference to a function name
  (options.empty? ? @name : nil) || function_scoped_name(options) || @id
end

#name=(val) ⇒ Object



197
198
199
# File 'lib/origen/pins/pin.rb', line 197

def name=(val)
  @name = val
end

#named?(n) ⇒ Boolean

Returns:

  • (Boolean)


1146
1147
1148
1149
1150
1151
1152
# File 'lib/origen/pins/pin.rb', line 1146

def named?(n)
  if n.is_a?(Regexp)
    [name.to_s, *aliases.keys].any? { |na| na =~ n }
  else
    [name.to_s, *aliases.keys.map(&:to_s)].include?(n.to_s)
  end
end

#next_edgeObject



1018
1019
1020
# File 'lib/origen/pins/pin.rb', line 1018

def next_edge
  @clock.next_edge
end

#org_file_intercepted_methodsObject



115
116
117
# File 'lib/origen/pins/pin.rb', line 115

def org_file_intercepted_methods
  ORG_FILE_INTERCEPTED_METHODS
end

#repeat_previous?Boolean

Returns:

  • (Boolean)


646
647
648
# File 'lib/origen/pins/pin.rb', line 646

def repeat_previous?
  @repeat_previous
end

#respond_to_missing?(m, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


1162
1163
1164
# File 'lib/origen/pins/pin.rb', line 1162

def respond_to_missing?(m, include_private = false)
  meta[m] || super
end

#restoreObject

Restores the state of the pin to the last time save was called



973
974
975
976
977
978
979
980
# File 'lib/origen/pins/pin.rb', line 973

def restore
  invalidate_vector_cache
  @state = @_saved_state.pop
  @value = @_saved_value.pop
  @suspend = @_saved_suspend.pop
  @invert = @_saved_invert.pop
  @repeat_previous = @_saved_repeat_previous.pop
end

#restore_stateObject

Restores the state of the pin at the end of the given block to the state it was in at the start of the block

pin(:invoke).driving?  # => true
pin(:invoke).restore_state do
  pin(:invoke).dont_care
  pin(:invoke).driving?  # => false
end
pin(:invoke).driving?  # => true


956
957
958
959
960
# File 'lib/origen/pins/pin.rb', line 956

def restore_state
  save
  yield
  restore
end

#resumeObject

Will resume compares on this pin



636
637
638
639
# File 'lib/origen/pins/pin.rb', line 636

def resume
  invalidate_vector_cache
  @suspend = false
end

#sanitize_direction(val) ⇒ Object



486
487
488
489
490
491
492
493
494
495
496
497
498
499
# File 'lib/origen/pins/pin.rb', line 486

def sanitize_direction(val)
  if val
    val = val.to_s.downcase.gsub(/\//, '')
    if val =~ /i.*o/
      :io
    elsif val =~ /^i/
      :input
    elsif val =~ /^o/
      :output
    else
      fail "Unknown pin direction: #{val}"
    end
  end
end

#saveObject

Saves the current state of the pin, allowing it to be restored to the current state by calling the restore method



964
965
966
967
968
969
970
# File 'lib/origen/pins/pin.rb', line 964

def save
  @_saved_state << @state
  @_saved_value << @value
  @_saved_suspend << @suspend
  @_saved_invert << @invert
  @_saved_repeat_previous << @repeat_previous
end

#set_state(state) ⇒ Object



655
656
657
658
659
# File 'lib/origen/pins/pin.rb', line 655

def set_state(state)
  invalidate_vector_cache
  @repeat_previous = false
  @state = state
end

#set_state_with_options(state, options = {}) ⇒ Object



650
651
652
653
# File 'lib/origen/pins/pin.rb', line 650

def set_state_with_options(state, options = {})
  @state_meta = options[:meta] || {}
  set_state(state)
end

#set_value(val) ⇒ Object Also known as: data=



661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
# File 'lib/origen/pins/pin.rb', line 661

def set_value(val)
  orig = val
  invalidate_vector_cache
  if val.is_a?(String) || val.is_a?(Symbol)
    val = val.to_s
    if val =~ /^(b|h).+/
      val = Origen::Value.new(val)
    else
      @vector_formatted_value = val
      return
    end
  end
  if val.is_a?(Origen::Value)
    val = val[0]
  else
    # If val is a data bit extract the value of it
    val = val.respond_to?(:data) ? val.data : val
    # Assume driving/asserting a nil value means 0
    val = 0 unless val
    if !val.x_or_z? && val > 1
      fail "Attempt to set a value of #{val} on pin #{name}"
    end
  end
  @repeat_previous = false
  if val.x_or_z?
    dont_care
  else
    if inverted?
      @value = val == 0 ? 1 : 0
    else
      @value = val
    end
  end
end

#sitesObject

Returns the number of test sites enabled for the pin



482
483
484
# File 'lib/origen/pins/pin.rb', line 482

def sites
  dib_assignment.size
end

#start_clock(options = {}) ⇒ Object Also known as: resume_clock



1007
1008
1009
1010
# File 'lib/origen/pins/pin.rb', line 1007

def start_clock(options = {})
  enable_clock(options) if myself.is_not_a_clock?
  @clock.start_clock(options)
end

#stateObject



701
702
703
# File 'lib/origen/pins/pin.rb', line 701

def state
  @state
end

#state=(value) ⇒ Object



705
706
707
708
709
# File 'lib/origen/pins/pin.rb', line 705

def state=(value)
  invalidate_vector_cache
  @state_meta = {}
  @state = value
end

#stop_clock(options = {}) ⇒ Object Also known as: pause_clock



1013
1014
1015
# File 'lib/origen/pins/pin.rb', line 1013

def stop_clock(options = {})
  @clock.stop_clock(options)
end

#suspendObject



626
627
628
629
# File 'lib/origen/pins/pin.rb', line 626

def suspend
  invalidate_vector_cache
  @suspend = true
end

#suspended?Boolean

Returns:

  • (Boolean)


631
632
633
# File 'lib/origen/pins/pin.rb', line 631

def suspended?
  @suspend
end

#to_be_captured?Boolean Also known as: to_be_stored?, is_to_be_stored?, is_to_be_captured?

Returns true if the (data) from the pin is marked to be captured

Returns:

  • (Boolean)


940
941
942
# File 'lib/origen/pins/pin.rb', line 940

def to_be_captured?
  state == :capture
end

#to_vectorObject

Returns the value held by the pin as a string formatted to the current tester's pattern syntax

Examples:


pin.drive_hi
pin.to_vector   # => "1"
pin.expect_lo
pin.to_vector   # => "L"


290
291
292
# File 'lib/origen/pins/pin.rb', line 290

def to_vector
  @vector_formatted_value ||= Origen.tester.format_pin_state(myself)
end

#toggleObject



915
916
917
918
919
# File 'lib/origen/pins/pin.rb', line 915

def toggle
  unless state == :dont_care
    set_value(value == 0 ? 1 : 0)
  end
end

#toggle!Object



921
922
923
924
# File 'lib/origen/pins/pin.rb', line 921

def toggle!
  toggle
  cycle
end

#toggle_clockObject



1030
1031
1032
1033
# File 'lib/origen/pins/pin.rb', line 1030

def toggle_clock
  fail "ERROR: Clock on #{@owner.name} not running." unless is_a_running_clock?
  @clock.toggle
end

#update_clockObject



1003
1004
1005
# File 'lib/origen/pins/pin.rb', line 1003

def update_clock
  @clock.update_clock
end

#valueObject Also known as: data



621
622
623
# File 'lib/origen/pins/pin.rb', line 621

def value
  @value
end

#vector_formatted_value=(val) ⇒ Object

Set the pin value and state from a string formatted to the current tester's pattern syntax, this is the opposite of the to_vector method

Examples:


pin.vector_formatted_value = "L"
pin.driving?                      # => false
pin.value                         # => 0
pin.vector_formatted_value = "1"
pin.driving?                      # => true
pin.value                         # => 1


311
312
313
314
315
316
# File 'lib/origen/pins/pin.rb', line 311

def vector_formatted_value=(val)
  unless @vector_formatted_value == val
    Origen.tester.update_pin_from_formatted_state(myself, val)
    @vector_formatted_value = val
  end
end