origen 0.27.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -41,6 +41,7 @@ module Origen
41
41
  end
42
42
 
43
43
  def method_missing(method, *args, &block) # :nodoc:
44
+ orig_method = method
44
45
  if method[-1] == '!'
45
46
  bang = true
46
47
  method = method.to_s.chop.to_sym
@@ -50,11 +51,11 @@ module Origen
50
51
  r.sync if bang
51
52
  r
52
53
  else
53
- super
54
+ super(orig_method, *args, &block)
54
55
  end
55
56
  end
56
57
 
57
- def respond_to?(sym) # :nodoc:
58
+ def respond_to?(sym, include_private = false) # :nodoc:
58
59
  if sym[-1] == '!'
59
60
  r = sym.to_s.chop.to_sym
60
61
  _registers.key?(r) || super(sym)
@@ -249,8 +250,8 @@ module Origen
249
250
  materialize.send(method, *args, &block)
250
251
  end
251
252
 
252
- def respond_to?(method)
253
- materialize.respond_to?(method)
253
+ def respond_to?(method, include_private = false)
254
+ materialize.respond_to?(method, include_private)
254
255
  end
255
256
 
256
257
  def materialize
@@ -502,13 +502,16 @@ module Origen
502
502
  result.to_s
503
503
  end
504
504
 
505
- # Write the bit value on silicon<br>
505
+ # Write the bit value on silicon.
506
506
  # This method will update the data value of the bits and then call $top.write_register
507
- # passing the owngin register as the first argument.<br>
507
+ # passing the owning register as the first argument.
508
508
  # This method is expected to handle writing the current state of the register to silicon.
509
509
  def write!(value = nil, options = {})
510
510
  value, options = nil, value if value.is_a?(Hash)
511
511
  write(value, options) if value
512
+ if block_given?
513
+ yield size == @reg.size ? @reg : self
514
+ end
512
515
  @reg.request(:write_register, options)
513
516
  self
514
517
  end
@@ -521,8 +524,10 @@ module Origen
521
524
  # reg(:data).read!(0x5555) # Read register :data, expecting 0x5555
522
525
  def read!(value = nil, options = {})
523
526
  value, options = nil, value if value.is_a?(Hash)
524
- read(value, options)
525
- # launch a read reg
527
+ read(value, options) unless block_given?
528
+ if block_given?
529
+ yield size == @reg.size ? @reg : self
530
+ end
526
531
  @reg.request(:read_register, options)
527
532
  self
528
533
  end
@@ -126,17 +126,53 @@ module Origen
126
126
  @updating_bound_bits
127
127
  end
128
128
 
129
- def inspect
129
+ def inspect(options = {})
130
+ # This fancy_output option is passed in via option hash
131
+ # Even better, the output could auto-detect 7-bit vs 8-bit terminal output and adjust the parameter, but that's for another day
132
+ fancy_output = options[:fancy_output].nil? ? true : options[:fancy_output]
133
+ if fancy_output
134
+ horiz_double_line = '═'
135
+ horiz_double_tee_down = '╤'
136
+ horiz_double_tee_up = '╧'
137
+ corner_double_up_left = '╒'
138
+ corner_double_up_right = '╕'
139
+ horiz_single_line = '─'
140
+ horiz_single_tee_down = '┬'
141
+ horiz_single_tee_up = '┴'
142
+ horiz_single_cross = '┼'
143
+ horiz_double_cross = '╪'
144
+ corner_single_down_left = '└'
145
+ corner_single_down_right = '┘'
146
+ vert_single_line = '│'
147
+ vert_single_tee_left = '┤'
148
+ vert_single_tee_right = '├'
149
+ else
150
+ horiz_double_line = '='
151
+ horiz_double_tee_down = '='
152
+ horiz_double_tee_up = '='
153
+ corner_double_up_left = '.'
154
+ corner_double_up_right = '.'
155
+ horiz_single_line = '-'
156
+ horiz_single_tee_down = '-'
157
+ horiz_single_tee_up = '-'
158
+ horiz_single_cross = '+'
159
+ horiz_double_cross = '='
160
+ corner_single_down_left = '`'
161
+ corner_single_down_right = '\''
162
+ vert_single_line = '|'
163
+ vert_single_tee_left = '<'
164
+ vert_single_tee_right = '>'
165
+ end
130
166
  bit_width = 13
131
167
  desc = ["\n0x%X - :#{name}" % address]
132
168
  r = size % 8
133
169
  if r == 0 || (size > 8 && bit_order == :msb0)
134
- desc << (' ' + ('=' * (bit_width + 1) * 8)).chop
170
+ desc << (' ' + corner_double_up_left + ((horiz_double_line * bit_width + horiz_double_tee_down) * 8)).chop + corner_double_up_right
135
171
  else
136
172
  if bit_order == :lsb0
137
- desc << (' ' + (' ' * (bit_width + 1) * (8 - r)) + ('=' * (bit_width + 1) * r)).chop
173
+ desc << (' ' + (' ' * (bit_width + 1) * (8 - r)) + corner_double_up_left + ((horiz_double_line * bit_width + horiz_double_tee_down) * r)).chop + corner_double_up_right
138
174
  else
139
- desc << (' ' + ('=' * (bit_width + 1) * r)).chop
175
+ desc << (' ' + corner_double_up_left + ((horiz_double_line * bit_width + horiz_double_tee_down) * r)).chop + corner_double_up_right
140
176
  end
141
177
  end
142
178
 
@@ -164,16 +200,16 @@ module Origen
164
200
  end
165
201
  if bit_num > size - 1
166
202
  if bit_order == :msb0 && bit_num == size
167
- line += '|'
203
+ line += vert_single_line
168
204
  line_complete = true
169
205
  else
170
- line << ' ' + ''.center(bit_width)
206
+ line << ' ' + ''.center(bit_width) unless line_complete
171
207
  end
172
208
  else
173
- line << '|' + "#{bit_num}".center(bit_width)
209
+ line << vert_single_line + "#{bit_num}".center(bit_width)
174
210
  end
175
211
  end
176
- line += '|' unless line_complete
212
+ line += vert_single_line unless line_complete
177
213
  desc << line
178
214
 
179
215
  # BIT NAME ROW
@@ -213,15 +249,15 @@ module Origen
213
249
  end
214
250
  width = (bit_width * bit_span) + bit_span - 1
215
251
  if bit_name.length > width
216
- line << '|' + "#{bit_name[0..width - 2]}*"
252
+ line << vert_single_line + "#{bit_name[0..width - 2]}*"
217
253
  else
218
- line << '|' + bit_name.center(width)
254
+ line << vert_single_line + bit_name.center(width)
219
255
  end
220
256
 
221
257
  else
222
258
  bit.shift_out_left do |bit|
223
259
  if _index_in_range?(bit.position, max_bit, min_bit)
224
- line << '|' + ''.center(bit_width)
260
+ line << vert_single_line + ''.center(bit_width)
225
261
  end
226
262
  end
227
263
  end
@@ -237,12 +273,12 @@ module Origen
237
273
  else
238
274
  txt = ''
239
275
  end
240
- line << '|' + txt.center(bit_width)
276
+ line << vert_single_line + txt.center(bit_width)
241
277
  end
242
278
  end
243
279
  first_done = true
244
280
  end
245
- line += '|'
281
+ line += vert_single_line
246
282
  desc << line
247
283
 
248
284
  # BIT STATE ROW
@@ -272,11 +308,11 @@ module Origen
272
308
  value += _state_desc(bit)
273
309
  bit_span = _num_bits_in_range(bit, max_bit, min_bit)
274
310
  width = bit_width * bit_span
275
- line << '|' + value.center(width + bit_span - 1)
311
+ line << vert_single_line + value.center(width + bit_span - 1)
276
312
  else
277
313
  bit.shift_out_left do |bit|
278
314
  if _index_in_range?(bit.position, max_bit, min_bit)
279
- line << '|' + ''.center(bit_width)
315
+ line << vert_single_line + ''.center(bit_width)
280
316
  end
281
317
  end
282
318
  end
@@ -292,31 +328,37 @@ module Origen
292
328
  end
293
329
  end
294
330
  value = "#{val}" + _state_desc(bit)
295
- line << '|' + value.center(bit_width)
331
+ line << vert_single_line + value.center(bit_width)
296
332
  else
297
- line << '|' + ''.center(bit_width)
333
+ line << vert_single_line + ''.center(bit_width)
298
334
  end
299
335
  end
300
336
  end
301
337
  first_done = true
302
338
  end
303
- line += '|'
339
+ line += vert_single_line
304
340
  desc << line
305
341
 
306
342
  if size >= 8
307
343
  r = size % 8
308
344
  if byte_index == 0 && r != 0 && bit_order == :lsb0
309
- desc << (' ' + ('=' * (bit_width + 1) * (8 - r)).chop + ' ' + ('-' * (bit_width + 1) * r)).chop
345
+ desc << (' ' + corner_double_up_left + ((horiz_double_line * bit_width + horiz_double_tee_down) * (8 - r)).chop + horiz_double_cross + (horiz_single_line * (bit_width + 1) * r)).chop + vert_single_tee_left
310
346
  elsif (byte_index == num_bytes - 1) && r != 0 && bit_order == :msb0
311
- desc << (' ' + ('-' * (bit_width + 1) * r)).chop
347
+ desc << (' ' + corner_single_down_left + ((horiz_single_line * bit_width + horiz_single_tee_up) * r)).chop + corner_single_down_right
348
+ elsif (byte_index == num_bytes - 2) && r != 0 && bit_order == :msb0
349
+ desc << ' ' + vert_single_tee_right + ((horiz_single_line * bit_width + horiz_single_cross) * r) + ((horiz_single_line * bit_width + horiz_single_tee_up) * (8 - r)).chop + corner_single_down_right
312
350
  else
313
- desc << (' ' + ('-' * (bit_width + 1) * 8)).chop
351
+ if byte_index == num_bytes - 1
352
+ desc << (' ' + corner_single_down_left + ((horiz_single_line * bit_width + horiz_single_tee_up) * 8)).chop + corner_single_down_right
353
+ else
354
+ desc << (' ' + vert_single_tee_right + ((horiz_single_line * bit_width + horiz_single_cross) * 8)).chop + vert_single_tee_left
355
+ end
314
356
  end
315
357
  else
316
358
  if bit_order == :lsb0
317
- desc << (' ' + (' ' * (bit_width + 1) * (8 - size)) + ('-' * (bit_width + 1) * size)).chop
359
+ desc << (' ' + (' ' * (bit_width + 1) * (8 - size)) + corner_single_down_left + ((horiz_single_line * bit_width + horiz_single_tee_up) * size)).chop + corner_single_down_right
318
360
  else
319
- desc << (' ' + ('-' * (bit_width + 1) * size)).chop
361
+ desc << (' ' + corner_single_down_left + ((horiz_single_line * bit_width + horiz_single_tee_up) * size)).chop + corner_single_down_right
320
362
  end
321
363
  end
322
364
  end
@@ -435,7 +477,7 @@ module Origen
435
477
  if line =~ /^\s*#(.*)/
436
478
  desc << Regexp.last_match[1].strip
437
479
  # http://rubular.com/r/D8lg2P5kK1 http://rubular.com/r/XP4ydPV8Fd
438
- elsif line =~ /^\s*reg\(?\s*[:"'](\w+)["']?\s*,.*\sdo/ || line =~ /^\s*add_reg\(?\s*[:"'](\w+)["']?\s*,.*/
480
+ elsif line =~ /^\s*reg\(?\s*[:"'](\w+)["']?\s*,.*\sdo/ || line =~ /^\s*.*add_reg\(?\s*[:"'](\w+)["']?\s*,.*/
439
481
  @current_reg_name = Regexp.last_match[1].to_sym
440
482
  description_lookup[define_file] ||= {}
441
483
  description_lookup[define_file][@current_reg_name] ||= {}
@@ -56,7 +56,7 @@ module Origen
56
56
  elsif FALSE_VALUES.include?(val)
57
57
  return false
58
58
  end
59
- config
59
+ val
60
60
  else
61
61
  config = configs.find { |c| c.key?(val) }
62
62
  config ? config[val] : nil
@@ -212,7 +212,7 @@ module Origen
212
212
  end
213
213
  alias_method :children, :sub_blocks
214
214
 
215
- # Delete all sub_blocks by emptyig the Hash
215
+ # Delete all sub_blocks by emptying the Hash
216
216
  def delete_sub_blocks
217
217
  @sub_blocks = {}
218
218
  end
@@ -265,47 +265,22 @@ module Origen
265
265
  end
266
266
  a
267
267
  else
268
- class_name = options.delete(:class_name)
269
- if class_name
270
- if eval("defined? ::#{namespace}::#{class_name}")
271
- klass = eval("::#{namespace}::#{class_name}")
268
+ block = Placeholder.new(self, name, options)
269
+ if sub_blocks[name]
270
+ # Allow additional attributes to be added to an existing sub-block if it hasn't
271
+ # been instantiated yet. This is not supported yet for instantiated sub-blocks since
272
+ # there are probably a lot more corner-cases to consider, and hopefully no one will
273
+ # really need this anyway.
274
+ if sub_blocks[name].is_a?(Placeholder)
275
+ sub_blocks[name].add_attributes(options)
272
276
  else
273
- if eval("defined? #{class_name}")
274
- klass = eval(class_name)
275
- else
276
- if eval("defined? #{self.class}::#{class_name}")
277
- klass = eval("#{self.class}::#{class_name}")
278
- else
279
- puts "Could not find class: #{class_name}"
280
- fail 'Unknown sub block class!'
281
- end
282
- end
277
+ fail "You have already defined a sub-block named #{name} within class #{self.class}"
283
278
  end
284
- else
285
- klass = Origen::SubBlock
286
- end
287
- unless klass.respond_to?(:includes_origen_model)
288
- puts 'Any class which is to be instantiated as a sub_block must include Origen::Model,'
289
- puts "add this to #{klass}:"
290
- puts ''
291
- puts ' include Origen::Model'
292
- puts ''
293
- fail 'Sub block does not include Origen::Model!'
294
- end
295
- block = klass.new(options.merge(parent: self, name: name))
296
- if sub_blocks[name]
297
- fail "You have already defined a sub-block named #{name} within class #{self.class}"
298
279
  else
299
280
  sub_blocks[name] = block
300
- if respond_to?(name)
301
- # puts "Tried to create a sub-block named #{name} in #{self.class}, but it already has a method with this name!"
302
- # puts "To avoid confusion rename one of them and try again!"
303
- # raise "Non-unique sub-block name!"
304
- else
305
- define_singleton_method name do
306
- sub_blocks[name]
307
- end
308
- end
281
+ end
282
+ define_singleton_method name do
283
+ get_sub_block(name)
309
284
  end
310
285
  block
311
286
  end
@@ -314,6 +289,116 @@ module Origen
314
289
  def namespace
315
290
  self.class.to_s.sub(/::[^:]*$/, '')
316
291
  end
292
+
293
+ private
294
+
295
+ def get_sub_block(name)
296
+ sub_blocks[name]
297
+ end
298
+
299
+ def instantiate_sub_block(name, klass, options)
300
+ return sub_blocks[name] unless sub_blocks[name].is_a?(Placeholder)
301
+ sub_blocks[name] = klass.new(options.merge(parent: self, name: name))
302
+ end
303
+
304
+ class Placeholder
305
+ attr_reader :name, :owner, :attributes
306
+
307
+ def initialize(owner, name, attributes)
308
+ @owner = owner
309
+ @name = name
310
+ @attributes = attributes
311
+ end
312
+
313
+ def add_attributes(attrs)
314
+ @attributes = @attributes.merge(attrs)
315
+ end
316
+
317
+ # Make this appear like a sub-block to any application code
318
+ def is_a?(klass)
319
+ klass == self.klass || klass == self.class
320
+ end
321
+
322
+ # Make it look like a sub-block in the console to avoid confusion
323
+ def inspect
324
+ "<SubBlock: #{name}>"
325
+ end
326
+
327
+ def method_missing(method, *args, &block)
328
+ materialize.send(method, *args, &block)
329
+ end
330
+
331
+ def respond_to?(method, include_private = false)
332
+ materialize.respond_to?(method, include_private)
333
+ end
334
+
335
+ def materialize
336
+ file = attributes.delete(:file)
337
+ block = owner.send(:instantiate_sub_block, name, klass, attributes)
338
+ if file
339
+ require File.join(owner.send(:export_dir), file)
340
+ block.extend owner.send(:export_module_names_from_path, file).join('::').constantize
341
+ end
342
+ block
343
+ end
344
+
345
+ def ==(obj)
346
+ materialize == obj
347
+ end
348
+
349
+ def !=(obj)
350
+ materialize != obj
351
+ end
352
+
353
+ def freeze
354
+ materialize.freeze
355
+ end
356
+
357
+ def clone
358
+ materialize.clone
359
+ end
360
+
361
+ def dup
362
+ materialize.dup
363
+ end
364
+
365
+ def to_json(*args)
366
+ materialize.to_json(*args)
367
+ end
368
+
369
+ def klass
370
+ @klass ||= begin
371
+ class_name = attributes.delete(:class_name)
372
+ if class_name
373
+ if eval("defined? ::#{owner.namespace}::#{class_name}")
374
+ klass = eval("::#{owner.namespace}::#{class_name}")
375
+ else
376
+ if eval("defined? #{class_name}")
377
+ klass = eval(class_name)
378
+ else
379
+ if eval("defined? #{owner.class}::#{class_name}")
380
+ klass = eval("#{owner.class}::#{class_name}")
381
+ else
382
+ puts "Could not find class: #{class_name}"
383
+ fail 'Unknown sub block class!'
384
+ end
385
+ end
386
+ end
387
+ else
388
+ klass = Origen::SubBlock
389
+ end
390
+ unless klass.respond_to?(:includes_origen_model)
391
+ puts 'Any class which is to be instantiated as a sub_block must include Origen::Model,'
392
+ puts "add this to #{klass}:"
393
+ puts ''
394
+ puts ' include Origen::Model'
395
+ puts ''
396
+ fail 'Sub block does not include Origen::Model!'
397
+ end
398
+ klass
399
+ end
400
+ end
401
+ end
317
402
  end
318
403
 
319
404
  # A simple class that will be instantiated by default when a sub block is
@@ -328,6 +413,8 @@ module Origen
328
413
  # On first call of a missing method a method is generated to avoid the missing lookup
329
414
  # next time, this should be faster for repeated lookups of the same method, e.g. reg
330
415
  def method_missing(method, *args, &block)
416
+ super
417
+ rescue NoMethodError
331
418
  return regs(method) if self.has_reg?(method)
332
419
  return ports(method) if self.has_port?(method)
333
420
  if method.to_s =~ /=$/
@@ -63,7 +63,12 @@ module Origen
63
63
  #
64
64
  # This allows different pin configurations to be specified by package.
65
65
  def current_package=(val)
66
- @current_package_id = val.is_a?(ChipPackage) ? val.id : val
66
+ @current_package_id = case val
67
+ when ChipPackage
68
+ val.id
69
+ else
70
+ packages.include?(val) ? val : nil
71
+ end
67
72
  end
68
73
  alias_method :package=, :current_package=
69
74