origen 0.27.0 → 0.28.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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