Module: Origen::SubBlocks

Includes:
Domains, Parent, Path, RegBaseAddress
Defined in:
lib/origen/sub_blocks.rb

Defined Under Namespace

Modules: Domains, Parent, Path, RegBaseAddress Classes: Placeholder

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Path

#abs_path, #abs_path=, #path, #path=, #path_var

Methods included from RegBaseAddress

#base_address, #reg_base_address, #reg_base_address_for_domain

Methods included from Parent

#owner=, #parent

Methods included from Domains

#domain, #domain_specified?, #domains

Class Method Details

.lazy=(value) ⇒ Object



44
45
46
# File 'lib/origen/sub_blocks.rb', line 44

def self.lazy=(value)
  @lazy = value
end

.lazy?Boolean

Returns the default

Returns:

  • (Boolean)


40
41
42
# File 'lib/origen/sub_blocks.rb', line 40

def self.lazy?
  @lazy || false
end

Instance Method Details

#all_sub_blocksObject

Returns an array containing all descendant child objects of the given sub-block, i.e. this returns an array containing children’s children as well

Note that this returns an array instead of a hash since there could be naming collisions in the hash keys



267
268
269
# File 'lib/origen/sub_blocks.rb', line 267

def all_sub_blocks
  @all_sub_blocks ||= (sub_blocks_array + sub_blocks_array.map(&:all_sub_blocks)).flatten
end

#custom_attrsObject

Returns a hash containing all options that were passed to the sub_block definition



49
50
51
# File 'lib/origen/sub_blocks.rb', line 49

def custom_attrs
  @custom_attrs
end

#delete_sub_blocksObject

Delete all sub_blocks by emptying the Hash



253
254
255
# File 'lib/origen/sub_blocks.rb', line 253

def delete_sub_blocks
  @sub_blocks = {}
end

#has_fuses?Boolean

Returns:

  • (Boolean)


281
282
283
# File 'lib/origen/sub_blocks.rb', line 281

def has_fuses?
  fuses.empty? ? false : true
end

#has_tests?Boolean

Returns:

  • (Boolean)


285
286
287
# File 'lib/origen/sub_blocks.rb', line 285

def has_tests?
  tests.empty? ? false : true
end

#init_sub_blocks(*args) ⇒ Object

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.

This will be called whenever an object that includes this module is instantiated



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/origen/sub_blocks.rb', line 7

def init_sub_blocks(*args)
  options = args.find { |a| a.is_a?(Hash) }
  @custom_attrs = (options ? options.dup : {}).with_indifferent_access
  # Delete these keys which are either meta data added by Origen or are already covered by
  # dedicated methods
  %w(parent name base_address reg_base_address base).each do |key|
    @custom_attrs.delete(key)
  end
  if options
    # Using reg_base_address for storage to avoid class with the original Origen base
    # address API, but will accept any of these
    @reg_base_address = options.delete(:reg_base_address) ||
                        options.delete(:base_address) || options.delete(:base) || 0
    if options[:_instance] # to be deprecated as part of multi-instance removal below
      if @reg_base_address.is_a?(Array)
        @reg_base_address = @reg_base_address[options[:_instance]]
      elsif options[:base_address_step]
        @reg_base_address = @reg_base_address + (options[:_instance] * options[:base_address_step])
      end
    end
    @domain_names = [options.delete(:domain) || options.delete(:domains)].flatten.compact
    @domain_specified = !@domain_names.empty?
    @path = options.delete(:path)
    @abs_path = options.delete(:abs_path) || options.delete(:absolute_path)
  end
  if is_a?(SubBlock)
    options.each do |k, v|
      send("#{k}=", v)
    end
  end
end

#namespaceObject



427
428
429
# File 'lib/origen/sub_blocks.rb', line 427

def namespace
  self.class.to_s.sub(/::[^:]*$/, '')
end

#owns_registers?Boolean Also known as: has_regs?

Returns true if the given sub block owns at least one register

Returns:

  • (Boolean)


272
273
274
275
276
277
278
# File 'lib/origen/sub_blocks.rb', line 272

def owns_registers?
  if regs
    regs.is_a?(Origen::Registers::RegCollection) && !regs.empty?
  else
    false
  end
end

#sub_block(name = nil, options = {}) ⇒ Object



289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
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
# File 'lib/origen/sub_blocks.rb', line 289

def sub_block(name = nil, options = {})
  name, options = nil, name if name.is_a?(Hash)
  return sub_blocks unless name

  if name.is_a?(Class)
    return sub_blocks.select { |n, s| s.is_a?(name) }
  elsif name.origen_sub_block?
    return sub_block(name.class)
  end

  if i = options.delete(:instances)
    # permit creating multiple instances of a particular sub_block class
    # can pass array for base_address, which will be processed above
    Origen.deprecate 'instances: option to sub_block is deprecated, use sub_block_groups instead'
    group_name = name =~ /s$/ ? name : "#{name}s" # take care if name already with 's' is passed
    unless respond_to?(group_name)
      sub_block_groups group_name do
        i.times do |j|
          o = options.dup
          o[:_instance] = j
          sub_block("#{name}#{j}", o)
        end
      end
    end
  else
    block = Placeholder.new(self, name, options)
    # Allow additional attributes to be added to an existing sub-block if it hasn't
    # been instantiated yet. This is not supported yet for instantiated sub-blocks since
    # there are probably a lot more corner-cases to consider, and hopefully no one will
    # really need this anyway.
    # Note that override is to recreate an existing sub-block, not adding additional
    # attributes to an existing one
    if options[:override]
      sub_blocks.delete(name.to_s)
      if options[:class_name]
        constantizable = !!options[:class_name].safe_constantize
        # this is to handle the case where a previously instantiated subblock wont allow
        # the current class name to exist
        # e.g. NamespaceA::B::C
        # =>  NameSpaceX::Y::Z
        # After requiring the files, constants become sane again:
        # e.g. NamespaceA::B::C
        # =>  NameSpaceA::B::C
        if constantizable && (options[:class_name] != options[:class_name].constantize.to_s)
          block_dir = options[:block_file] || _find_block_dir(options)
          # files that aren't initializing a new namespace and have special loading shouldn't be required
          # the code they contain may try to call methods that dont exist yet
          skip_require_files = options[:skip_require_files] || %w(attributes parameters pins registers sub_blocks timesets)
          Dir.glob("#{block_dir}/*.rb").each do |file|
            next if skip_require_files.include?(Pathname.new(file).basename('.rb').to_s)

            require file
          end
        end
      end
    else
      if sub_blocks[name] && !sub_blocks[name].is_a?(Placeholder)
        fail "You have already defined a sub-block named #{name} within class #{self.class}"
      end
    end
    if respond_to?(name) && !(singleton_class.instance_methods.include?(name) && options[:override])
      callers = Origen.split_caller_line caller[0]
      Origen.log.warning "The sub_block defined at #{Pathname.new(callers[0]).relative_path_from(Pathname.pwd)}:#{callers[1]} is overriding an existing method called #{name}"
    end
    define_singleton_method name do
      sub_blocks[name]
    end
    if sub_blocks[name] && sub_blocks[name].is_a?(Placeholder)
      sub_blocks[name].add_attributes(options)
    else
      sub_blocks[name] = block
    end
    unless @current_group.nil? # a group is currently open, store sub_block id only
      @current_group << name
    end
    if options.key?(:lazy)
      lazy = options[:lazy]
    else
      lazy = Origen::SubBlocks.lazy?
    end
    lazy ? block : block.materialize
  end
end

#sub_block_group(id, options = {}) ⇒ Object Also known as: sub_blocks_group

Create a group of associated sub_blocks under a group name permits each sub_block to be of a different class e.g. sub_block_group :my_ip_group do

sub_block :ip0, class_name: 'IP0', base_address: 0x000000
sub_block :ip1, class_name: 'IP1', base_address: 0x000200
sub_block :ip2, class_name: 'IP2', base_address: 0x000400
sub_block :ip3, class_name: 'IP3', base_address: 0x000600

end

creates an array referenced by method called ‘my_ip_group’ which contains the sub_blocks ‘ip0’, ‘ip1’, ‘ip2’, ‘ip3’.

Can also indicate a custom class container to hold these. This custom class container MUST support a ‘<<’ method in order to add new sub_blocks to the container instance.

e.g. sub_block_group :my_ip_group, class_name: ‘MYGRP’ do

sub_block :ip0, class_name: 'IP0', base_address: 0x000000
sub_block :ip1, class_name: 'IP1', base_address: 0x000200
sub_block :ip2, class_name: 'IP2', base_address: 0x000400
sub_block :ip3, class_name: 'IP3', base_address: 0x000600

end



399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
# File 'lib/origen/sub_blocks.rb', line 399

def sub_block_group(id, options = {})
  @current_group = []    # open group
  yield                  # any sub_block calls within this block will have their ID added to @current_group
  my_group = @current_group.dup
  if respond_to?(id)
    callers = Origen.split_caller_line caller[0]
    Origen.log.warning "The sub_block_group defined at #{Pathname.new(callers[0]).relative_path_from(Pathname.pwd)}:#{callers[1]} is overriding an existing method called #{id}"
  end
  # Define a singleton method which will be called every time the sub_block_group is referenced
  # This is not called here but later when referenced
  define_singleton_method "#{id}" do
    sub_block_groups[id]
  end
  # Instantiate group
  if options[:class_name]
    b = Object.const_get(options[:class_name]).new
  else
    b = [] # Will use Array if no class defined
  end
  # Add sub_blocks to group
  my_group.each do |group_id|
    b << send(group_id)
  end
  sub_block_groups[id] = b
  @current_group = nil # close group
end

#sub_block_groups(*args, &block) ⇒ Object

Returns a hash containing all sub block groups thus far added if no arguments given. If given a code block, will serve as alias to sub_block_group method. Does not handle arguments, no need at this time.



240
241
242
243
244
245
246
247
248
249
250
# File 'lib/origen/sub_blocks.rb', line 240

def sub_block_groups(*args, &block)
  if block_given?
    sub_block_group(*args, &block)
  else
    if args.empty?
      @sub_block_groups ||= {}.with_indifferent_access
    else
      fail 'sub_block_groups not meant to take arguments!'
    end
  end
end

#sub_blocks(*args) ⇒ Object Also known as: children

Returns a hash containing all immediate children of the given sub-block



227
228
229
230
231
232
233
# File 'lib/origen/sub_blocks.rb', line 227

def sub_blocks(*args)
  if args.empty?
    @sub_blocks ||= {}.with_indifferent_access
  else
    sub_block(*args)
  end
end

#sub_blocks_arrayObject Also known as: children_array



257
258
259
# File 'lib/origen/sub_blocks.rb', line 257

def sub_blocks_array
  sub_blocks.map { |_name, sub_block| sub_block }
end