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


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


1060
1061
1062
1063
1064
1065
1066
# File 'lib/origen/pins/pin.rb', line 1060

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, 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

828
829
830
831
# File 'lib/origen/pins/pin.rb', line 828

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

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


836
837
838
839
# File 'lib/origen/pins/pin.rb', line 836

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


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

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

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


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

def assert_hi!
  assert_hi
  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


770
771
772
773
774
775
776
777
778
779
780
781
# File 'lib/origen/pins/pin.rb', line 770

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!, read_lo!


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

def assert_lo!
  assert_lo
  cycle
end

#assert_midbandObject Also known as: compare_midband, expect_midband, read_midband


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

def assert_midband
  set_state(:compare_midband)
end

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


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

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


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

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


918
919
920
921
# File 'lib/origen/pins/pin.rb', line 918

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)

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

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

#comparing_mem?Boolean

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

Returns:

  • (Boolean)

871
872
873
874
# File 'lib/origen/pins/pin.rb', line 871

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

#comparing_midband?Boolean

Returns true if the pin is currently in a compare state

Returns:

  • (Boolean)

877
878
879
880
# File 'lib/origen/pins/pin.rb', line 877

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.


1024
1025
1026
# File 'lib/origen/pins/pin.rb', line 1024

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


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

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

#dont_careObject

Set the pin to X on future cycles


795
796
797
# File 'lib/origen/pins/pin.rb', line 795

def dont_care
  set_state(:dont_care)
end

#dont_care!Object


799
800
801
802
# File 'lib/origen/pins/pin.rb', line 799

def dont_care!
  dont_care
  cycle
end

#drive(value) ⇒ 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

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

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

#drive!(value) ⇒ Object Also known as: write!


816
817
818
819
# File 'lib/origen/pins/pin.rb', line 816

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

#drive_hiObject Also known as: write_hi

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 Also known as: write_hi!


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

def drive_hi!
  drive_hi
  cycle
end

#drive_loObject Also known as: write_lo

Set the pin to drive a 0 on future cycles


722
723
724
725
# File 'lib/origen/pins/pin.rb', line 722

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

#drive_lo!Object Also known as: write_lo!


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

def drive_lo!
  drive_lo
  cycle
end

#drive_memObject


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

def drive_mem
  set_state(:drive_mem)
end

#drive_mem!Object


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

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”


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

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

#drive_very_hi!Object


716
717
718
719
# File 'lib/origen/pins/pin.rb', line 716

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)

883
884
885
886
# File 'lib/origen/pins/pin.rb', line 883

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)

889
890
891
892
# File 'lib/origen/pins/pin.rb', line 889

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

#duty_cyclesObject


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

def duty_cycles
  @clock.cycles_per_duty
end

#enable_clock(options = {}) ⇒ Object


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

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

#expect_memObject


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

def expect_mem
  set_state(:expect_mem)
end

#expect_mem!Object


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

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


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

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)

895
896
897
898
# File 'lib/origen/pins/pin.rb', line 895

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)

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

def inverted?
  @invert
end

#is_a_clock?Boolean

Returns:

  • (Boolean)

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

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

#is_a_running_clock?Boolean

Returns:

  • (Boolean)

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

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)

967
968
969
# File 'lib/origen/pins/pin.rb', line 967

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


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

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)

1068
1069
1070
# File 'lib/origen/pins/pin.rb', line 1068

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


958
959
960
961
962
963
964
965
# File 'lib/origen/pins/pin.rb', line 958

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

941
942
943
944
945
# File 'lib/origen/pins/pin.rb', line 941

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


949
950
951
952
953
954
955
# File 'lib/origen/pins/pin.rb', line 949

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


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

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


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

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)

925
926
927
# File 'lib/origen/pins/pin.rb', line 925

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


900
901
902
903
904
# File 'lib/origen/pins/pin.rb', line 900

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

#toggle!Object


906
907
908
909
# File 'lib/origen/pins/pin.rb', line 906

def toggle!
  toggle
  cycle
end

#toggle_clockObject


1015
1016
1017
1018
# File 'lib/origen/pins/pin.rb', line 1015

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

#update_clockObject


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

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