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

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, :drive_hi, :drive_very_hi, :drive_lo, :drive_lo, :drive_mem, :expect_mem,
  :assert_hi, :expect_hi, :compare_hi, :assert_lo, :expect_lo, :compare_lo, :dont_care,
  :drive, :assert, :compare, :expect, :assert_midband, :compare_midband, :expect_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


60
61
62
63
64
65
66
67
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
# File 'lib/origen/pins/pin.rb', line 60

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] || {}
  @_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


1046
1047
1048
1049
1050
1051
1052
# File 'lib/origen/pins/pin.rb', line 1046

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

#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


184
185
186
# File 'lib/origen/pins/pin.rb', line 184

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.


547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
# File 'lib/origen/pins/pin.rb', line 547

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.


439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
# File 'lib/origen/pins/pin.rb', line 439

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


460
461
462
463
464
465
466
467
468
469
470
# File 'lib/origen/pins/pin.rb', line 460

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

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

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


510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
# File 'lib/origen/pins/pin.rb', line 510

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

421
422
423
424
425
426
427
428
429
430
431
432
433
434
# File 'lib/origen/pins/pin.rb', line 421

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

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

818
819
820
821
# File 'lib/origen/pins/pin.rb', line 818

def assert(value, _options = {})
  set_state(:compare)
  set_value(value)
end

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


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

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

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

Set the pin to expect a 1 on future cycles


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

def assert_hi(_options = {})
  set_state(:compare)
  set_value(1)
end

#assert_hi!Object Also known as: expect_hi!, compare_hi!


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

def assert_hi!
  assert_hi
  cycle
end

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

Set the pin to expect a 0 on future cycles


764
765
766
767
768
769
770
771
772
773
774
775
# File 'lib/origen/pins/pin.rb', line 764

def assert_lo(_options = {})
  set_state(:compare)
  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!Object Also known as: expect_lo!, compare_lo!


779
780
781
782
# File 'lib/origen/pins/pin.rb', line 779

def assert_lo!
  assert_lo
  cycle
end

#assert_midbandObject Also known as: compare_midband, expect_midband


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

def assert_midband
  set_state(:compare_midband)
end

#assert_midband!Object Also known as: compare_midband!, expect_midband!


838
839
840
841
# File 'lib/origen/pins/pin.rb', line 838

def assert_midband!
  assert_midband
  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)

608
609
610
# File 'lib/origen/pins/pin.rb', line 608

def belongs_to_a_pin_group?
  !groups.empty?
end

#captureObject Also known as: store

Mark the (data) from the pin to be captured


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

def capture
  set_state(:capture)
end

#capture!Object Also known as: store!

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


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

def capture!
  capture
  cycle
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.


128
129
130
131
132
133
134
135
136
# File 'lib/origen/pins/pin.rb', line 128

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)

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

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

#comparing_mem?Boolean

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

Returns:

  • (Boolean)

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

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

#comparing_midband?Boolean

Returns true if the pin is currently in a compare state

Returns:

  • (Boolean)

863
864
865
866
# File 'lib/origen/pins/pin.rb', line 863

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

#cycleObject

:nodoc:


683
684
685
# File 'lib/origen/pins/pin.rb', line 683

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.


1010
1011
1012
# File 'lib/origen/pins/pin.rb', line 1010

def delete!
  owner.delete_pin(myself)
end

#describe(options = {}) ⇒ Object


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
379
380
381
382
383
384
385
386
# File 'lib/origen/pins/pin.rb', line 313

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.


494
495
496
# File 'lib/origen/pins/pin.rb', line 494

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

#disable_clock(options = {}) ⇒ Object


969
970
971
972
# File 'lib/origen/pins/pin.rb', line 969

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

#dont_careObject

Set the pin to X on future cycles


787
788
789
# File 'lib/origen/pins/pin.rb', line 787

def dont_care
  set_state(:dont_care)
end

#dont_care!Object


791
792
793
794
# File 'lib/origen/pins/pin.rb', line 791

def dont_care!
  dont_care
  cycle
end

#drive(value) ⇒ Object

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

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

def drive(value)
  set_state(:drive)
  set_value(value)
end

#drive!(value) ⇒ Object


807
808
809
810
# File 'lib/origen/pins/pin.rb', line 807

def drive!(value)
  drive(value)
  cycle
end

#drive_hiObject

Set the pin to drive a 1 on future cycles


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

def drive_hi
  set_state(:drive)
  set_value(1)
end

#drive_hi!Object


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

def drive_hi!
  drive_hi
  cycle
end

#drive_loObject

Set the pin to drive a 0 on future cycles


720
721
722
723
# File 'lib/origen/pins/pin.rb', line 720

def drive_lo
  set_state(:drive)
  set_value(0)
end

#drive_lo!Object


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

def drive_lo!
  drive_lo
  cycle
end

#drive_memObject


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

def drive_mem
  set_state(:drive_mem)
end

#drive_mem!Object


734
735
736
737
# File 'lib/origen/pins/pin.rb', line 734

def drive_mem!
  drive_mem
  cycle
end

#drive_very_hiObject

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”


709
710
711
712
# File 'lib/origen/pins/pin.rb', line 709

def drive_very_hi
  set_state(:drive_very_hi)
  set_value(1)
end

#drive_very_hi!Object


714
715
716
717
# File 'lib/origen/pins/pin.rb', line 714

def drive_very_hi!
  drive_very_hi
  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.


114
115
116
117
118
119
120
121
122
# File 'lib/origen/pins/pin.rb', line 114

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)

869
870
871
872
# File 'lib/origen/pins/pin.rb', line 869

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)

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

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

#duty_cyclesObject


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

def duty_cycles
  @clock.cycles_per_duty
end

#enable_clock(options = {}) ⇒ Object


965
966
967
# File 'lib/origen/pins/pin.rb', line 965

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

#expect_memObject


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

def expect_mem
  set_state(:expect_mem)
end

#expect_mem!Object


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

def expect_mem!
  expect_mem
  cycle
end

#function_scoped_nameObject


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

alias_method :function_scoped_name, :name

#global_path_toObject


102
103
104
# File 'lib/origen/pins/pin.rb', line 102

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

#goodbyeObject

See Pin#hello


178
179
180
181
# File 'lib/origen/pins/pin.rb', line 178

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


390
391
392
# File 'lib/origen/pins/pin.rb', line 390

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


397
398
399
# File 'lib/origen/pins/pin.rb', line 397

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


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

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


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

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)

567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
# File 'lib/origen/pins/pin.rb', line 567

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

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/origen/pins/pin.rb', line 158

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)

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

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

#inspectObject


309
310
311
# File 'lib/origen/pins/pin.rb', line 309

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

#invalidate_group_cacheObject


411
412
413
# File 'lib/origen/pins/pin.rb', line 411

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.


286
287
288
289
# File 'lib/origen/pins/pin.rb', line 286

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)

846
847
848
# File 'lib/origen/pins/pin.rb', line 846

def inverted?
  @invert
end

#is_a_clock?Boolean

Returns:

  • (Boolean)

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

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

#is_a_running_clock?Boolean

Returns:

  • (Boolean)

961
962
963
# File 'lib/origen/pins/pin.rb', line 961

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)

592
593
594
595
596
597
598
# File 'lib/origen/pins/pin.rb', line 592

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)

953
954
955
# File 'lib/origen/pins/pin.rb', line 953

def is_not_a_clock?
  @clock.nil?
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


268
269
270
271
# File 'lib/origen/pins/pin.rb', line 268

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


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

def name=(val)
  @name = val
end

#next_edgeObject


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

def next_edge
  @clock.next_edge
end

#org_file_intercepted_methodsObject


106
107
108
# File 'lib/origen/pins/pin.rb', line 106

def org_file_intercepted_methods
  ORG_FILE_INTERCEPTED_METHODS
end

#repeat_previous?Boolean

Returns:

  • (Boolean)

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

def repeat_previous?
  @repeat_previous
end

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

Returns:

  • (Boolean)

1054
1055
1056
# File 'lib/origen/pins/pin.rb', line 1054

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


944
945
946
947
948
949
950
951
# File 'lib/origen/pins/pin.rb', line 944

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

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

def restore_state
  save
  yield
  restore
end

#resumeObject

Will resume compares on this pin


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

def resume
  invalidate_vector_cache
  @suspend = false
end

#sanitize_direction(val) ⇒ Object


477
478
479
480
481
482
483
484
485
486
487
488
489
490
# File 'lib/origen/pins/pin.rb', line 477

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


935
936
937
938
939
940
941
# File 'lib/origen/pins/pin.rb', line 935

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

#set_state(state) ⇒ Object


641
642
643
644
645
# File 'lib/origen/pins/pin.rb', line 641

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

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


647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
# File 'lib/origen/pins/pin.rb', line 647

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


473
474
475
# File 'lib/origen/pins/pin.rb', line 473

def sites
  dib_assignment.size
end

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


978
979
980
981
# File 'lib/origen/pins/pin.rb', line 978

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

#stateObject


687
688
689
# File 'lib/origen/pins/pin.rb', line 687

def state
  @state
end

#state=(value) ⇒ Object


691
692
693
694
# File 'lib/origen/pins/pin.rb', line 691

def state=(value)
  invalidate_vector_cache
  @state = value
end

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


984
985
986
# File 'lib/origen/pins/pin.rb', line 984

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

#suspendObject


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

def suspend
  invalidate_vector_cache
  @suspend = true
end

#suspended?Boolean

Returns:

  • (Boolean)

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

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)

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

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"

281
282
283
# File 'lib/origen/pins/pin.rb', line 281

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

#toggleObject


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

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

#toggle!Object


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

def toggle!
  toggle
  cycle
end

#toggle_clockObject


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

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

#update_clockObject


974
975
976
# File 'lib/origen/pins/pin.rb', line 974

def update_clock
  @clock.update_clock
end

#valueObject Also known as: data


612
613
614
# File 'lib/origen/pins/pin.rb', line 612

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

302
303
304
305
306
307
# File 'lib/origen/pins/pin.rb', line 302

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