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 = caller[0].split(':')
        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_singleton_method "#{id}" do
        if options[:class_name]
          b = Object.const_get(options[:class_name]).new
        else
          b = []
        end
        my_group.each do |group_id|
          b << send(group_id)
        end
        b                         # return array inside new singleton method
      end
      @current_group = nil   # close group
    end
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 = caller[0].split(':')
        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_singleton_method "#{id}" do
        if options[:class_name]
          b = Object.const_get(options[:class_name]).new
        else
          b = []
        end
        my_group.each do |group_id|
          b << send(group_id)
        end
        b                         # return array inside new singleton method
      end
      @current_group = nil   # close group
    end
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