origen 0.28.2 → 0.29.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/bin/origen +14 -2
  3. data/config/version.rb +2 -2
  4. data/lib/origen.rb +72 -45
  5. data/lib/origen/application.rb +29 -19
  6. data/lib/origen/application/deployer.rb +3 -1
  7. data/lib/origen/application/runner.rb +10 -8
  8. data/lib/origen/chip_mode.rb +1 -1
  9. data/lib/origen/commands.rb +24 -12
  10. data/lib/origen/commands/version.rb +1 -1
  11. data/lib/origen/commands_global.rb +32 -8
  12. data/lib/origen/core_ext.rb +1 -2
  13. data/lib/origen/core_ext/enumerable.rb +2 -2
  14. data/lib/origen/core_ext/integer.rb +85 -0
  15. data/lib/origen/core_ext/numeric.rb +28 -4
  16. data/lib/origen/global_app.rb +9 -0
  17. data/lib/origen/log.rb +1 -1
  18. data/lib/origen/model_initializer.rb +6 -1
  19. data/lib/origen/netlist/list.rb +2 -2
  20. data/lib/origen/org_file.rb +125 -0
  21. data/lib/origen/org_file/interceptable.rb +44 -0
  22. data/lib/origen/org_file/interceptor.rb +100 -0
  23. data/lib/origen/parameters/set.rb +1 -1
  24. data/lib/origen/pins.rb +4 -0
  25. data/lib/origen/pins/function_proxy.rb +8 -0
  26. data/lib/origen/pins/pin.rb +90 -38
  27. data/lib/origen/pins/pin_collection.rb +61 -21
  28. data/lib/origen/ports/port.rb +1 -1
  29. data/lib/origen/registers.rb +1 -1
  30. data/lib/origen/registers/reg.rb +1 -1
  31. data/lib/origen/remote_manager.rb +25 -15
  32. data/lib/origen/site_config.rb +140 -13
  33. data/lib/origen/specs/checkers.rb +2 -2
  34. data/lib/origen/sub_blocks.rb +6 -1
  35. data/lib/origen/value.rb +119 -0
  36. data/lib/origen/value/bin_str_val.rb +72 -0
  37. data/lib/origen/value/hex_str_val.rb +100 -0
  38. data/origen_site_config.yml +15 -8
  39. metadata +12 -6
  40. data/lib/origen/core_ext/bignum.rb +0 -38
  41. data/lib/origen/core_ext/fixnum.rb +0 -56
@@ -179,7 +179,7 @@ module Origen
179
179
  else
180
180
  results_hash["#{name}#{delimiter}#{k}"] = v
181
181
  if k == param_hash.keys.last
182
- name = nil
182
+ name = name.include?(delimiter) ? name.split(delimiter)[0..-2].join(delimiter) : nil
183
183
  end
184
184
  end
185
185
  end
@@ -227,8 +227,12 @@ module Origen
227
227
  name: ''
228
228
  }.merge(options)
229
229
 
230
+ rtl_name = options[:rtl_name]
231
+ force = options[:force]
230
232
  options.delete(:size).times do |i|
231
233
  options[:name] = "#{id}#{i}".to_sym
234
+ options[:rtl_name] = "#{rtl_name}#{i}".to_sym if rtl_name
235
+ options[:force] = force[i] if force
232
236
 
233
237
  if power_pin
234
238
  group[i] = PowerPin.new(i, self, options)
@@ -16,6 +16,14 @@ module Origen
16
16
  @pin
17
17
  end
18
18
 
19
+ # @api private
20
+ #
21
+ # To play nicely with == when a function proxy is wrapping a pin that is already
22
+ # wrapped by an OrgFile interceptor
23
+ def __object__
24
+ @pin.__object__
25
+ end
26
+
19
27
  # Intercept all calls to function-scoped attributes of the pin so
20
28
  # that we can inject the function that we want the attribute value for
21
29
  Pin::FUNCTION_SCOPED_ATTRIBUTES.each do |attribute|
@@ -2,6 +2,17 @@ module Origen
2
2
  module Pins
3
3
  class Pin
4
4
  include PinCommon
5
+ include OrgFile::Interceptable
6
+
7
+ # Don't include the ! method in here, the cycle will be captured at the tester level and
8
+ # it would cause a double cycle in the org file if also captured at the pin
9
+ ORG_FILE_INTERCEPTED_METHODS = [
10
+ :suspend, :resume, :repeat_previous=,
11
+ :drive_hi, :drive_hi, :drive_very_hi, :drive_lo, :drive_lo, :drive_mem, :expect_mem,
12
+ :assert_hi, :expect_hi, :compare_hi, :assert_lo, :expect_lo, :compare_lo, :dont_care,
13
+ :drive, :assert, :compare, :expect, :assert_midband, :compare_midband, :expect_midband,
14
+ :toggle, :capture, :store
15
+ ]
5
16
 
6
17
  # Any attributes listed here will be looked up for the current function defined
7
18
  # by the current mode and configuration context before falling back to a default
@@ -37,8 +48,10 @@ module Origen
37
48
  attr_accessor :ext_pulldown
38
49
  # Pin type, either :analog or :digital
39
50
  attr_accessor :type
40
- # Pin RTL name, short term solution for products that do not get full HDL path for pins
51
+ # Pin RTL name
41
52
  attr_accessor :rtl_name
53
+ # Value to be forced on the pin, e.g. during simulation
54
+ attr_accessor :force
42
55
 
43
56
  attr_accessor :description
44
57
  attr_accessor :notes
@@ -59,6 +72,7 @@ module Origen
59
72
  @direction = sanitize_direction(options[:direction])
60
73
  @invert = options[:invert]
61
74
  @reset = options[:reset]
75
+ @force = options[:force] & 1
62
76
  @id = id
63
77
  @name = options[:name]
64
78
  @rtl_name = options[:rtl_name]
@@ -75,11 +89,24 @@ module Origen
75
89
  @clock = nil
76
90
  @meta = options[:meta] || {}
77
91
  @dib_meta = options[:dib_meta] || {}
92
+ @_saved_state = []
93
+ @_saved_value = []
94
+ @_saved_suspend = []
95
+ @_saved_invert = []
96
+ @_saved_repeat_previous = []
78
97
  on_init(owner, options)
79
98
  # Assign the initial state from the method so that any inversion is picked up...
80
99
  send(@reset)
81
100
  end
82
101
 
102
+ def global_path_to
103
+ "dut.pins(:#{id})"
104
+ end
105
+
106
+ def org_file_intercepted_methods
107
+ ORG_FILE_INTERCEPTED_METHODS
108
+ end
109
+
83
110
  # Returns the drive cycle wave assigned to the pin based on the currently enabled timeset,
84
111
  # or nil if none is set.
85
112
  # Note that if a timeset is set then all pins will always return a wave as they will pick
@@ -90,7 +117,7 @@ module Origen
90
117
  # every cycle in some applications
91
118
  @drive_waves ||= {}
92
119
  @drive_waves[t.id] ||= {}
93
- @drive_waves[t.id][code] ||= dut.current_timeset.send(:wave_for, self, type: :drive, code: code)
120
+ @drive_waves[t.id][code] ||= dut.current_timeset.send(:wave_for, myself, type: :drive, code: code)
94
121
  end
95
122
  end
96
123
 
@@ -104,7 +131,15 @@ module Origen
104
131
  # every cycle in some applications
105
132
  @compare_waves ||= {}
106
133
  @compare_waves[t.id] ||= {}
107
- @compare_waves[t.id][code] ||= dut.current_timeset.send(:wave_for, self, type: :compare, code: code)
134
+ @compare_waves[t.id][code] ||= dut.current_timeset.send(:wave_for, myself, type: :compare, code: code)
135
+ end
136
+ end
137
+
138
+ def rtl_name
139
+ if primary_group
140
+ (@rtl_name || "#{primary_group.id}#{primary_group_index}").to_s
141
+ else
142
+ (@rtl_name || id).to_s
108
143
  end
109
144
  end
110
145
 
@@ -123,7 +158,7 @@ module Origen
123
158
  def hello
124
159
  drive_hi
125
160
  @@hello_pins ||= []
126
- @@hello_pins << self unless @@hello_pins.include?(self)
161
+ @@hello_pins << myself unless @@hello_pins.include?(myself)
127
162
  @@hello_loop ||= Thread.new do
128
163
  loop do
129
164
  @@hello_pins.each(&:toggle)
@@ -141,7 +176,7 @@ module Origen
141
176
 
142
177
  # See Pin#hello
143
178
  def goodbye
144
- @@hello_pins.delete(self)
179
+ @@hello_pins.delete(myself)
145
180
  puts "Pin #{name} has stopped toggling"
146
181
  end
147
182
 
@@ -244,7 +279,7 @@ module Origen
244
279
  # pin.expect_lo
245
280
  # pin.to_vector # => "L"
246
281
  def to_vector
247
- @vector_formatted_value ||= Origen.tester.format_pin_state(self)
282
+ @vector_formatted_value ||= Origen.tester.format_pin_state(myself)
248
283
  end
249
284
 
250
285
  # @api private
@@ -266,13 +301,13 @@ module Origen
266
301
  # pin.value # => 1
267
302
  def vector_formatted_value=(val)
268
303
  unless @vector_formatted_value == val
269
- Origen.tester.update_pin_from_formatted_state(self, val)
304
+ Origen.tester.update_pin_from_formatted_state(myself, val)
270
305
  @vector_formatted_value = val
271
306
  end
272
307
  end
273
308
 
274
309
  def inspect
275
- "<#{self.class}:#{object_id}>"
310
+ "<#{myself.class}:#{object_id}>"
276
311
  end
277
312
 
278
313
  def describe(options = {})
@@ -368,7 +403,7 @@ module Origen
368
403
  def groups
369
404
  # Origen.pin_bank.all_pin_groups.select do |name, group|
370
405
  @groups ||= Origen.pin_bank.pin_groups.select do |_name, group|
371
- group.include?(self)
406
+ group.include?(myself)
372
407
  end
373
408
  end
374
409
  alias_method :pin_groups, :groups
@@ -391,8 +426,8 @@ module Origen
391
426
  else
392
427
  packages.each do |package_id|
393
428
  package_id = package_id.respond_to?(:id) ? package_id.id : package_id
394
- self.packages[package_id] ||= {}
395
- self.packages[package_id][:location] = str
429
+ myself.packages[package_id] ||= {}
430
+ myself.packages[package_id][:location] = str
396
431
  add_alias str.to_s.symbolize, package: package_id, mode: :all, configuration: :all
397
432
  end
398
433
  end
@@ -412,9 +447,9 @@ module Origen
412
447
  else
413
448
  packages.each do |package_id|
414
449
  package_id = package_id.respond_to?(:id) ? package_id.id : package_id
415
- self.packages[package_id] ||= {}
416
- self.packages[package_id][:dib_assignment] ||= []
417
- self.packages[package_id][:dib_assignment][options[:site]] = str
450
+ myself.packages[package_id] ||= {}
451
+ myself.packages[package_id][:dib_assignment] ||= []
452
+ myself.packages[package_id][:dib_assignment][options[:site]] = str
418
453
  add_alias str.to_s.symbolize, package: package_id, mode: :all, configuration: :all
419
454
  end
420
455
  end
@@ -468,7 +503,7 @@ module Origen
468
503
  def add_function(id, options = {})
469
504
  id = id.to_sym
470
505
  add_function_attributes(options.merge(name: id, id: id.to_sym))
471
- f = FunctionProxy.new(id, self)
506
+ f = FunctionProxy.new(id, myself)
472
507
  add_alias id, packages: :all, obj: f
473
508
  end
474
509
 
@@ -510,7 +545,7 @@ module Origen
510
545
  # If the options contain a package, mode or configuration reference then the alias
511
546
  # will only work under that context.
512
547
  def add_alias(id, options = {})
513
- obj = options.delete(:obj) || self
548
+ obj = options.delete(:obj) || myself
514
549
  if aliases[id]
515
550
  aliases[id][:packages] += resolve_packages(options)
516
551
  aliases[id][:modes] += resolve_modes(options)
@@ -556,7 +591,7 @@ module Origen
556
591
  # Returns true if the pin is an alias of the given pin name
557
592
  def is_alias_of?(name)
558
593
  if Origen.pin_bank.find(name)
559
- Origen.pin_bank.find(name).id == Origen.pin_bank.find(self).id
594
+ Origen.pin_bank.find(name).id == Origen.pin_bank.find(myself).id
560
595
  else
561
596
  false
562
597
  end
@@ -610,18 +645,32 @@ module Origen
610
645
  end
611
646
 
612
647
  def set_value(val)
648
+ orig = val
613
649
  invalidate_vector_cache
614
650
  if val.is_a?(String) || val.is_a?(Symbol)
615
- @vector_formatted_value = val.to_s
651
+ val = val.to_s
652
+ if val =~ /^(b|h).+/
653
+ val = Origen::Value.new(val)
654
+ else
655
+ @vector_formatted_value = val
656
+ return
657
+ end
658
+ end
659
+ if val.is_a?(Origen::Value)
660
+ val = val[0]
616
661
  else
617
662
  # If val is a data bit extract the value of it
618
663
  val = val.respond_to?(:data) ? val.data : val
619
664
  # Assume driving/asserting a nil value means 0
620
665
  val = 0 unless val
621
- if val > 1
666
+ if !val.x_or_z? && val > 1
622
667
  fail "Attempt to set a value of #{val} on pin #{name}"
623
668
  end
624
- @repeat_previous = false
669
+ end
670
+ @repeat_previous = false
671
+ if val.x_or_z?
672
+ dont_care
673
+ else
625
674
  if inverted?
626
675
  @value = val == 0 ? 1 : 0
627
676
  else
@@ -719,9 +768,9 @@ module Origen
719
768
  # options = { :active => false #if active true means to take tester active load capability into account
720
769
  # }.merge(options)
721
770
  # unless state_to_be_inverted?
722
- # self.state = ($tester.active_loads || !options[:active]) ? $tester.pin_state(:expect_lo) : $tester.pin_state(:dont_care)
771
+ # myself.state = ($tester.active_loads || !options[:active]) ? $tester.pin_state(:expect_lo) : $tester.pin_state(:dont_care)
723
772
  # else
724
- # self.state = ($tester.active_loads || !options[:active]) ? $tester.pin_state(:expect_hi) : $tester.pin_state(:dont_care)
773
+ # myself.state = ($tester.active_loads || !options[:active]) ? $tester.pin_state(:expect_hi) : $tester.pin_state(:dont_care)
725
774
  # end
726
775
  end
727
776
  alias_method :expect_lo, :assert_lo
@@ -881,21 +930,24 @@ module Origen
881
930
  restore
882
931
  end
883
932
 
884
- def save # :nodoc:
885
- @_saved_state = @state
886
- @_saved_value = @value
887
- @_saved_suspend = @suspend
888
- @_saved_invert = @invert
889
- @_saved_repeat_previous = @repeat_previous
933
+ # Saves the current state of the pin, allowing it to be restored to the
934
+ # current state by calling the restore method
935
+ def save
936
+ @_saved_state << @state
937
+ @_saved_value << @value
938
+ @_saved_suspend << @suspend
939
+ @_saved_invert << @invert
940
+ @_saved_repeat_previous << @repeat_previous
890
941
  end
891
942
 
892
- def restore # :nodoc:
943
+ # Restores the state of the pin to the last time save was called
944
+ def restore
893
945
  invalidate_vector_cache
894
- @state = @_saved_state
895
- @value = @_saved_value
896
- @suspend = @_saved_suspend
897
- @invert = @_saved_invert
898
- @repeat_previous = @_saved_repeat_previous
946
+ @state = @_saved_state.pop
947
+ @value = @_saved_value.pop
948
+ @suspend = @_saved_suspend.pop
949
+ @invert = @_saved_invert.pop
950
+ @repeat_previous = @_saved_repeat_previous.pop
899
951
  end
900
952
 
901
953
  def is_not_a_clock?
@@ -911,7 +963,7 @@ module Origen
911
963
  end
912
964
 
913
965
  def enable_clock(options = {})
914
- @clock = PinClock.new(self, options)
966
+ @clock = PinClock.new(myself, options)
915
967
  end
916
968
 
917
969
  def disable_clock(options = {})
@@ -924,7 +976,7 @@ module Origen
924
976
  end
925
977
 
926
978
  def start_clock(options = {})
927
- enable_clock(options) if self.is_not_a_clock?
979
+ enable_clock(options) if myself.is_not_a_clock?
928
980
  @clock.start_clock(options)
929
981
  end
930
982
  alias_method :resume_clock, :start_clock
@@ -951,12 +1003,12 @@ module Origen
951
1003
  @clock.toggle
952
1004
  end
953
1005
 
954
- # Delete this pin (self). Used bang in method name to keep same for pins and
1006
+ # Delete this pin (myself). Used bang in method name to keep same for pins and
955
1007
  # pin collections. Pin collections already had a delete method which deletes
956
1008
  # a pin from the collection. Needed delete! to indicate it is deleting the
957
1009
  # actual pin or pin group calling the method.
958
1010
  def delete!
959
- owner.delete_pin(self)
1011
+ owner.delete_pin(myself)
960
1012
  end
961
1013
 
962
1014
  def type=(value)
@@ -5,6 +5,14 @@ module Origen
5
5
  class PinCollection
6
6
  include PinCommon
7
7
  include Enumerable
8
+ include OrgFile::Interceptable
9
+
10
+ ORG_FILE_INTERCEPTED_METHODS = [
11
+ :drive, :drive_hi, :drive_lo, :drive_very_hi, :drive_mem, :expect_mem, :toggle,
12
+ :repeat_previous=, :capture, :assert, :compare, :expect,
13
+ :assert_hi, :expect_hi, :compare_hi, :assert_lo, :expect_lo, :compare_lo,
14
+ :dont_care
15
+ ]
8
16
 
9
17
  attr_accessor :endian
10
18
  attr_accessor :description
@@ -22,6 +30,7 @@ module Origen
22
30
  @virtual_pins = options.delete(:virtual_pin) || options.delete(:virtual_pins)
23
31
  @other_pins = options.delete(:other_pin) || options.delete(:other_pins)
24
32
  @endian = options[:endian]
33
+ @rtl_name = options[:rtl_name]
25
34
  @description = options[:description] || options[:desc]
26
35
  @options = options
27
36
  @store = []
@@ -31,6 +40,18 @@ module Origen
31
40
  on_init(owner, options)
32
41
  end
33
42
 
43
+ def rtl_name
44
+ (@rtl_name || id).to_s
45
+ end
46
+
47
+ def global_path_to
48
+ "dut.pins(:#{id})"
49
+ end
50
+
51
+ def org_file_intercepted_methods
52
+ ORG_FILE_INTERCEPTED_METHODS
53
+ end
54
+
34
55
  # Returns the value held by the pin group as a string formatted to the current tester's pattern syntax
35
56
  #
36
57
  # @example
@@ -70,7 +91,7 @@ module Origen
70
91
  fail 'When setting vector_formatted_value on a pin group you must supply values for all pins!'
71
92
  end
72
93
  val.split(//).reverse.each_with_index do |val, i|
73
- self[i].vector_formatted_value = val
94
+ myself[i].vector_formatted_value = val
74
95
  end
75
96
  @vector_formatted_value = val
76
97
  end
@@ -140,12 +161,12 @@ module Origen
140
161
 
141
162
  def sort!(&block)
142
163
  @store = sort(&block)
143
- self
164
+ myself
144
165
  end
145
166
 
146
167
  def sort_by!
147
168
  @store = sort_by
148
- self
169
+ myself
149
170
  end
150
171
 
151
172
  def []=(index, pin)
@@ -207,11 +228,11 @@ module Origen
207
228
  alias_method :<<, :add_pin
208
229
 
209
230
  def drive(val)
210
- val = val.data if val.respond_to?('data')
231
+ value = clean_value(value)
211
232
  each_with_index do |pin, i|
212
233
  pin.drive(val[size - i - 1])
213
234
  end
214
- self
235
+ myself
215
236
  end
216
237
 
217
238
  def drive!(val)
@@ -222,7 +243,7 @@ module Origen
222
243
  # Set all pins in pin group to drive 1's on future cycles
223
244
  def drive_hi
224
245
  each(&:drive_hi)
225
- self
246
+ myself
226
247
  end
227
248
 
228
249
  def drive_hi!
@@ -233,7 +254,7 @@ module Origen
233
254
  # Set all pins in pin group to drive 0's on future cycles
234
255
  def drive_lo
235
256
  each(&:drive_lo)
236
- self
257
+ myself
237
258
  end
238
259
 
239
260
  def drive_lo!
@@ -245,7 +266,7 @@ module Origen
245
266
  # For example on a J750 high-voltage channel the pin state would be set to "2"
246
267
  def drive_very_hi
247
268
  each(&:drive_very_hi)
248
- self
269
+ myself
249
270
  end
250
271
 
251
272
  def drive_very_hi!
@@ -255,7 +276,7 @@ module Origen
255
276
 
256
277
  def drive_mem
257
278
  each(&:drive_mem)
258
- self
279
+ myself
259
280
  end
260
281
 
261
282
  def drive_mem!
@@ -265,7 +286,7 @@ module Origen
265
286
 
266
287
  def expect_mem
267
288
  each(&:expect_mem)
268
- self
289
+ myself
269
290
  end
270
291
 
271
292
  def expect_mem!
@@ -293,7 +314,7 @@ module Origen
293
314
 
294
315
  def toggle
295
316
  each(&:toggle)
296
- self
317
+ myself
297
318
  end
298
319
 
299
320
  def toggle!
@@ -303,13 +324,13 @@ module Origen
303
324
 
304
325
  def repeat_previous=(bool)
305
326
  each { |pin| pin.repeat_previous = bool }
306
- self
327
+ myself
307
328
  end
308
329
 
309
330
  # Mark the (data) from all the pins in the pin group to be captured
310
331
  def capture
311
332
  each(&:capture)
312
- self
333
+ myself
313
334
  end
314
335
  alias_method :store, :capture
315
336
 
@@ -320,8 +341,16 @@ module Origen
320
341
  alias_method :store!, :capture!
321
342
 
322
343
  def restore_state
323
- each(&:save)
344
+ save
324
345
  yield
346
+ restore
347
+ end
348
+
349
+ def save
350
+ each(&:save)
351
+ end
352
+
353
+ def restore
325
354
  each(&:restore)
326
355
  end
327
356
 
@@ -334,6 +363,7 @@ module Origen
334
363
  end
335
364
 
336
365
  def assert(value, options = {})
366
+ value = clean_value(value)
337
367
  each_with_index do |pin, i|
338
368
  if !value.respond_to?('data')
339
369
  pin.assert(value[size - i - 1], options)
@@ -343,7 +373,7 @@ module Origen
343
373
  pin.dont_care
344
374
  end
345
375
  end
346
- self
376
+ myself
347
377
  end
348
378
  alias_method :compare, :assert
349
379
  alias_method :expect, :assert
@@ -358,7 +388,7 @@ module Origen
358
388
  # Set all pins in the pin group to expect 1's on future cycles
359
389
  def assert_hi(options = {})
360
390
  each { |pin| pin.assert_hi(options) }
361
- self
391
+ myself
362
392
  end
363
393
  alias_method :expect_hi, :assert_hi
364
394
  alias_method :compare_hi, :assert_hi
@@ -373,7 +403,7 @@ module Origen
373
403
  # Set all pins in the pin group to expect 0's on future cycles
374
404
  def assert_lo(options = {})
375
405
  each { |pin| pin.assert_lo(options) }
376
- self
406
+ myself
377
407
  end
378
408
  alias_method :expect_lo, :assert_lo
379
409
  alias_method :compare_lo, :assert_lo
@@ -388,7 +418,7 @@ module Origen
388
418
  # Set all pins in the pin group to X on future cycles
389
419
  def dont_care
390
420
  each(&:dont_care)
391
- self
421
+ myself
392
422
  end
393
423
 
394
424
  def dont_care!
@@ -456,13 +486,23 @@ pins(:some_group).map(&:id).sort
456
486
  end
457
487
  end
458
488
 
459
- # Delete this pingroup (self)
489
+ # Delete this pingroup (myself)
460
490
  def delete!
461
- owner.delete_pin(self)
491
+ owner.delete_pin(myself)
462
492
  end
463
493
 
464
494
  private
465
495
 
496
+ def clean_value(val)
497
+ return val if val.respond_to?(:contains_bits?)
498
+ val = val.data if val.respond_to?('data')
499
+ if val.is_a?(String) || val.is_a?(Symbol)
500
+ Origen::Value.new(val)
501
+ else
502
+ val
503
+ end
504
+ end
505
+
466
506
  # Cleans up indexed references to pins, e.g. makes these equal:
467
507
  #
468
508
  # pins(:pb)[0,1,2,3]
@@ -501,7 +541,7 @@ pins(:some_group).map(&:id).sort
501
541
  else
502
542
  # Allow getters if all pins are the same
503
543
  ref = first.send(method, *args)
504
- if self.all? { |pin| pin.send(method, *args) == ref }
544
+ if myself.all? { |pin| pin.send(method, *args) == ref }
505
545
  ref
506
546
  else
507
547
  fail "The pins held by pin collection #{id} have different values for #{method}"