Class: Origen::Pins::PinCollection

Inherits:
Object
  • Object
show all
Includes:
Enumerable, PinCommon
Defined in:
lib/origen/pins/pin_collection.rb

Overview

A class that is used to wrap collections of one or more pins. Anytime a group of pins is fetched or returned by the Pin API it will be wrapped in a PinCollection.

Constant Summary

Constants included from Enumerable

Enumerable::PRIMATIVES

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Enumerable

#debug, #list

Methods included from PinCommon

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

Constructor Details

#initialize(owner, *pins) ⇒ PinCollection

Returns a new instance of PinCollection.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/origen/pins/pin_collection.rb', line 12

def initialize(owner, *pins)
  options = pins.last.is_a?(Hash) ? pins.pop : {}
  options = {
    endian: :big
  }.merge(options)
  @power_pins = options.delete(:power_pin) || options.delete(:power_pins)
  @ground_pins = options.delete(:ground_pin) || options.delete(:ground_pins)
  @endian = options[:endian]
  @description = options[:description] || options[:desc]
  @options = options
  @store = []
  pins.each_with_index do |pin, i|
    @store[i] = pin
  end
  on_init(owner, options)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object (private)



466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
# File 'lib/origen/pins/pin_collection.rb', line 466

def method_missing(method, *args, &block)
  # Where the collection is only comprised of one pin delegate missing methods/attributes
  # to that pin
  if size == 1
    first.send(method, *args, &block)
  # Send all assignment methods to all contained pins
  elsif method.to_s =~ /.*=$/
    each do |pin|
      pin.send(method, *args, &block)
    end
  else
    if block_given?
      fail 'Blocks are not currently supported by pin collections containing multiple pins!'
    else
      # Allow getters if all pins are the same
      ref = first.send(method, *args)
      if self.all? { |pin| pin.send(method, *args) == ref }
        ref
      else
        fail "The pins held by pin collection #{id} have different values for #{method}"
      end
    end
  end
end

Instance Attribute Details

#descriptionObject

Returns the value of attribute description.



10
11
12
# File 'lib/origen/pins/pin_collection.rb', line 10

def description
  @description
end

#endianObject

Returns the value of attribute endian.



9
10
11
# File 'lib/origen/pins/pin_collection.rb', line 9

def endian
  @endian
end

Instance Method Details

#[](*indexes) ⇒ Object



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

def [](*indexes)
  if indexes.size > 1 || indexes.first.is_a?(Range)
    p = PinCollection.new(owner, @options)
    expand_and_order(indexes).each do |index|
      p << @store[index]
    end
    p
  else
    @store[indexes.first]
  end
end

#[]=(index, pin) ⇒ Object



136
137
138
# File 'lib/origen/pins/pin_collection.rb', line 136

def []=(index, pin)
  @store[index] = pin
end

#add_pin(pin, _options = {}) ⇒ Object Also known as: <<



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/origen/pins/pin_collection.rb', line 165

def add_pin(pin, _options = {})
  if pin.is_a?(PinCollection)
    # Need this to bypass the endianness aware iteration, the storing order
    # is always the same. So can't use each and co here.
    pin.size.times do |i|
      pin[i].invalidate_group_cache
      @store.push(pin[i])
    end
  else
    # Convert any named reference to a pin object
    if power_pins?
      pin = owner.power_pins(pin)
    elsif ground_pins?
      pin = owner.ground_pins(pin)
    else
      pin = owner.pins(pin)
    end
    if @store.include?(pin)
      fail "Pin collection #{id} already contains pin #{pin.id}!"
    else
      pin.invalidate_group_cache
      @store.push(pin)
    end
  end
end

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



319
320
321
322
323
324
325
# File 'lib/origen/pins/pin_collection.rb', line 319

def assert(value, options = {})
  value = value.data if value.respond_to?('data')
  each_with_index do |pin, i|
    pin.assert(value[size - i - 1], options)
  end
  self
end

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



329
330
331
332
# File 'lib/origen/pins/pin_collection.rb', line 329

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

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

Set all pins in the pin group to expect 1’s on future cycles



337
338
339
340
# File 'lib/origen/pins/pin_collection.rb', line 337

def assert_hi(options = {})
  each { |pin| pin.assert_hi(options) }
  self
end

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



344
345
346
347
# File 'lib/origen/pins/pin_collection.rb', line 344

def assert_hi!
  assert_hi
  cycle
end

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

Set all pins in the pin group to expect 0’s on future cycles



352
353
354
355
# File 'lib/origen/pins/pin_collection.rb', line 352

def assert_lo(options = {})
  each { |pin| pin.assert_lo(options) }
  self
end

#assert_lo!Object Also known as: expect_lo!, compare_lo!



359
360
361
362
# File 'lib/origen/pins/pin_collection.rb', line 359

def assert_lo!
  assert_lo
  cycle
end

#captureObject Also known as: store

Mark the (data) from all the pins in the pin group to be captured



293
294
295
296
# File 'lib/origen/pins/pin_collection.rb', line 293

def capture
  each(&:capture)
  self
end

#capture!Object Also known as: store!



299
300
301
302
# File 'lib/origen/pins/pin_collection.rb', line 299

def capture!
  capture
  cycle
end

#comparing?Boolean

Returns:

  • (Boolean)


381
382
383
# File 'lib/origen/pins/pin_collection.rb', line 381

def comparing?
  all?(&:comparing?)
end

#comparing_mem?Boolean

Returns:

  • (Boolean)


385
386
387
# File 'lib/origen/pins/pin_collection.rb', line 385

def comparing_mem?
  all?(&:comparing_mem?)
end

#cycleObject



315
316
317
# File 'lib/origen/pins/pin_collection.rb', line 315

def cycle
  Origen.tester.cycle
end

#dataObject Also known as: val, value

Returns the data value held by the collection

Example

pins(:porta).write(0x55)
pins(:porta).data         #  => 0x55


263
264
265
266
267
# File 'lib/origen/pins/pin_collection.rb', line 263

def data
  data = 0
  each_with_index { |pin, i| data |= pin.data << (size - i - 1) }
  data
end

#data_bObject

Returns the inverse of the data value held by the collection



272
273
274
275
# File 'lib/origen/pins/pin_collection.rb', line 272

def data_b
  # (& operation takes care of Bignum formatting issues)
  ~data & ((1 << size) - 1)
end

#delete(p) ⇒ Object

Deletes all occurrences of a pin in a pin group



414
415
416
# File 'lib/origen/pins/pin_collection.rb', line 414

def delete(p)
  @store.delete(p)
end

#delete!Object

Delete this pingroup (self)



438
439
440
# File 'lib/origen/pins/pin_collection.rb', line 438

def delete!
  owner.delete_pin(self)
end

#delete_at(index) ⇒ Object

Deletes the pin at a particular numeric index within the pin group



419
420
421
# File 'lib/origen/pins/pin_collection.rb', line 419

def delete_at(index)
  @store.delete_at(index)
end

#describe(display = :id) ⇒ Object

Describe the pin group contents. Default is to display pin.id but passing in :name will display pin.name



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/origen/pins/pin_collection.rb', line 142

def describe(display = :id)
  desc = ['********************']
  desc << "Group id: #{id}"
  desc << "\nDescription: #{description}" if description
  desc << "\nEndianness: #{endian}"

  unless size == 0
    desc << ''
    desc << 'Pins'
    desc << '-------'
    if display == :id
      desc << map(&:id).join(', ')
    elsif display == :name
      desc << map(&:name).join(', ')
    else
      fail 'Error: Argument options for describe method are :id and :name.  Default is :id'
    end
  end

  desc << '********************'
  puts desc.join("\n")
end

#dont_careObject

Set all pins in the pin group to X on future cycles



367
368
369
370
# File 'lib/origen/pins/pin_collection.rb', line 367

def dont_care
  each(&:dont_care)
  self
end

#dont_care!Object



372
373
374
375
# File 'lib/origen/pins/pin_collection.rb', line 372

def dont_care!
  dont_care
  cycle
end

#drive(val) ⇒ Object



192
193
194
195
196
197
198
# File 'lib/origen/pins/pin_collection.rb', line 192

def drive(val)
  val = val.data if val.respond_to?('data')
  each_with_index do |pin, i|
    pin.drive(val[size - i - 1])
  end
  self
end

#drive!(val) ⇒ Object



200
201
202
203
# File 'lib/origen/pins/pin_collection.rb', line 200

def drive!(val)
  drive(val)
  cycle
end

#drive_hiObject

Set all pins in pin group to drive 1’s on future cycles



206
207
208
209
# File 'lib/origen/pins/pin_collection.rb', line 206

def drive_hi
  each(&:drive_hi)
  self
end

#drive_hi!Object



211
212
213
214
# File 'lib/origen/pins/pin_collection.rb', line 211

def drive_hi!
  drive_hi
  cycle
end

#drive_loObject

Set all pins in pin group to drive 0’s on future cycles



217
218
219
220
# File 'lib/origen/pins/pin_collection.rb', line 217

def drive_lo
  each(&:drive_lo)
  self
end

#drive_lo!Object



222
223
224
225
# File 'lib/origen/pins/pin_collection.rb', line 222

def drive_lo!
  drive_lo
  cycle
end

#drive_memObject



239
240
241
242
# File 'lib/origen/pins/pin_collection.rb', line 239

def drive_mem
  each(&:drive_mem)
  self
end

#drive_mem!Object



244
245
246
247
# File 'lib/origen/pins/pin_collection.rb', line 244

def drive_mem!
  drive_mem
  cycle
end

#drive_very_hiObject

Set all pins in the pin group 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”



229
230
231
232
# File 'lib/origen/pins/pin_collection.rb', line 229

def drive_very_hi
  each(&:drive_very_hi)
  self
end

#drive_very_hi!Object



234
235
236
237
# File 'lib/origen/pins/pin_collection.rb', line 234

def drive_very_hi!
  drive_very_hi
  cycle
end

#driving?Boolean

Returns:

  • (Boolean)


389
390
391
# File 'lib/origen/pins/pin_collection.rb', line 389

def driving?
  all?(&:driving?)
end

#driving_mem?Boolean

Returns:

  • (Boolean)


393
394
395
# File 'lib/origen/pins/pin_collection.rb', line 393

def driving_mem?
  all?(&:driving_mem?)
end

#eachObject

Overrides the regular Ruby array each to be endian aware. If the pin collection/group is defined as big endian then this will yield the least significant pin first, otherwise for little endian the most significant pin will come out first.



100
101
102
103
104
105
106
107
108
# File 'lib/origen/pins/pin_collection.rb', line 100

def each
  size.times do |i|
    if endian == :big
      yield @store[size - i - 1]
    else
      yield @store[i]
    end
  end
end

#expect_memObject



249
250
251
252
# File 'lib/origen/pins/pin_collection.rb', line 249

def expect_mem
  each(&:expect_mem)
  self
end

#expect_mem!Object



254
255
256
257
# File 'lib/origen/pins/pin_collection.rb', line 254

def expect_mem!
  expect_mem
  cycle
end

#ground_pins?Boolean

Returns true if the pin collection contains ground pins rather than regular pins

Returns:

  • (Boolean)


80
81
82
# File 'lib/origen/pins/pin_collection.rb', line 80

def ground_pins?
  @ground_pins
end

#high_voltage?Boolean

Returns:

  • (Boolean)


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

def high_voltage?
  all?(&:high_voltage?)
end

#idObject



84
85
86
# File 'lib/origen/pins/pin_collection.rb', line 84

def id
  @id
end

#id=(val) ⇒ Object



311
312
313
# File 'lib/origen/pins/pin_collection.rb', line 311

def id=(val)
  @id = val.to_sym
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.



45
46
47
# File 'lib/origen/pins/pin_collection.rb', line 45

def invalidate_vector_cache
  @vector_formatted_value = nil
end

#inverted?Boolean

Returns:

  • (Boolean)


377
378
379
# File 'lib/origen/pins/pin_collection.rb', line 377

def inverted?
  all?(&:inverted?)
end

#nameObject



93
94
95
# File 'lib/origen/pins/pin_collection.rb', line 93

def name
  @name || id
end

#name=(val) ⇒ Object

Explicitly set the name of a pin group/collection



89
90
91
# File 'lib/origen/pins/pin_collection.rb', line 89

def name=(val)
  @name = val
end

#pins(nick = :id) ⇒ Object



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

def pins(nick = :id)
  Origen.deprecate <<-END
The PinCollection#pins method is deprecated, if you want to get a list of pin IDs
in the given collection just do pins(:some_group).map(&:id)
Note that the pins method (confusingly) also does a sort, to replicate that:
pins(:some_group).map(&:id).sort
  END
  if nick == :id
    @store.map(&:id).sort
  elsif nick == :name
    @store.map(&:name).sort
  end
end

#power_pins?Boolean

Returns true if the pin collection contains power pins rather than regular pins

Returns:

  • (Boolean)


75
76
77
# File 'lib/origen/pins/pin_collection.rb', line 75

def power_pins?
  @power_pins
end

#repeat_previous=(bool) ⇒ Object



287
288
289
290
# File 'lib/origen/pins/pin_collection.rb', line 287

def repeat_previous=(bool)
  each { |pin| pin.repeat_previous = bool }
  self
end

#repeat_previous?Boolean

Returns:

  • (Boolean)


401
402
403
# File 'lib/origen/pins/pin_collection.rb', line 401

def repeat_previous?
  all?(&:repeat_previous?)
end

#restore_stateObject



305
306
307
308
309
# File 'lib/origen/pins/pin_collection.rb', line 305

def restore_state
  each(&:save)
  yield
  each(&:restore)
end

#sizeObject



110
111
112
# File 'lib/origen/pins/pin_collection.rb', line 110

def size
  @store.size
end

#sort!(&block) ⇒ Object



126
127
128
129
# File 'lib/origen/pins/pin_collection.rb', line 126

def sort!(&block)
  @store = sort(&block)
  self
end

#sort_by!Object



131
132
133
134
# File 'lib/origen/pins/pin_collection.rb', line 131

def sort_by!
  @store = sort_by
  self
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 port is marked to be captured

Returns:

  • (Boolean)


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

def to_be_captured?
  all?(&:to_be_captured?)
end

#to_vectorObject

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

Examples:


pin_group.drive_hi
pin_group.to_vector   # => "11111111"
pin_group.expect_lo
pin_group.to_vector   # => "LLLLLLLL"


37
38
39
40
41
42
# File 'lib/origen/pins/pin_collection.rb', line 37

def to_vector
  return @vector_formatted_value if @vector_formatted_value
  vals = map(&:to_vector)
  vals.reverse! if endian == :little
  @vector_formatted_value = vals.join('')
end

#toggleObject



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

def toggle
  each(&:toggle)
  self
end

#toggle!Object



282
283
284
285
# File 'lib/origen/pins/pin_collection.rb', line 282

def toggle!
  toggle
  cycle
end

#vector_formatted_value=(val) ⇒ Object

Set the values and states of the pin group’s pins from a string formatted to the current tester’s pattern syntax, this is the opposite of the to_vector method

Examples:


pin_group.vector_formatted_value = "LLLLLLLL"
pin_group[0].driving?                          # => false
pin_group[0].value                             # => 0
pin_group.vector_formatted_value = "HHHH1111"
pin_group[0].driving?                          # => true
pin_group[0].value                             # => 1
pin_group[7].driving?                          # => false
pin_group[7].value                             # => 1


62
63
64
65
66
67
68
69
70
71
72
# File 'lib/origen/pins/pin_collection.rb', line 62

def vector_formatted_value=(val)
  unless @vector_formatted_value == val
    unless val.size == size
      fail 'When setting vector_formatted_value on a pin group you must supply values for all pins!'
    end
    val.split(//).reverse.each_with_index do |val, i|
      self[i].vector_formatted_value = val
    end
    @vector_formatted_value = val
  end
end