def add_reg(id, address, size = nil, bit_info = {}, &_block)
      if address.is_a?(Hash)
        fail 'add_reg requires the address to be supplied as the 2nd argument, e.g. add_reg :my_reg, 0x1000'
      end
      size, bit_info = nil, size if size.is_a?(Hash)
      size ||= bit_info.delete(:size) || 32
      description = bit_info.delete(:description)

      local_vars = {}

      Reg::REG_LEVEL_ATTRIBUTES.each do |attribute, meta|
        aliases = [attribute[1..-1].to_sym]
        aliases += meta[:aliases] if meta[:aliases]
        aliases.each { |_a| local_vars[attribute] = bit_info.delete(_a) if bit_info.key?(_a) }
      end

      local_vars[:_reset] ||= :memory if local_vars[:_memory]
      @min_reg_address ||= address
      @max_reg_address ||= address
      # Must set an initial value, otherwise max_address_reg_size will be nil if a sub_block contains only
      # a single register.
      @max_address_reg_size = size unless @max_address_reg_size
      @min_reg_address = address if address < @min_reg_address
      if address > @max_reg_address
        @max_address_reg_size = size
        @max_reg_address = address
      end
      @reg_define_file ||= define_file(caller[0])

      if block_given?
        @new_reg_attrs = { meta: bit_info }
        yield self
        bit_info = @new_reg_attrs
      else
        # If no block given then init with all writable bits unless bit_info has
        # been supplied
        unless bit_info.any? { |k, v| v.is_a?(Hash) && v[:pos] }
          bit_info = { d: { pos: 0, bits: size }.merge(bit_info) }
        end
      end
      if _registers[id] && Origen.config.strict_errors
        puts ''
        puts "Add register error, you have already added a register named #{id} to #{self.class}"
        puts ''
        fail 'Duplicate register error!'
      else
        attributes = {
          define_file: @reg_define_file,
          address:     address,
          size:        size,
          bit_info:    bit_info,
          description: description
        }
        Reg::REG_LEVEL_ATTRIBUTES.each do |attribute, _meta|
          attributes[attribute] = local_vars[attribute]
        end
        _registers[id] = Placeholder.new(self, id, attributes)
      end
      @reg_define_file = nil
    end
def add_reg(id, address, size = nil, bit_info = {}, &_block)
      if address.is_a?(Hash)
        fail 'add_reg requires the address to be supplied as the 2nd argument, e.g. add_reg :my_reg, 0x1000'
      end
      size, bit_info = nil, size if size.is_a?(Hash)
      size ||= bit_info.delete(:size) || 32
      description = bit_info.delete(:description)

      local_vars = {}

      Reg::REG_LEVEL_ATTRIBUTES.each do |attribute, meta|
        aliases = [attribute[1..-1].to_sym]
        aliases += meta[:aliases] if meta[:aliases]
        aliases.each { |_a| local_vars[attribute] = bit_info.delete(_a) if bit_info.key?(_a) }
      end

      local_vars[:_reset] ||= :memory if local_vars[:_memory]
      @min_reg_address ||= address
      @max_reg_address ||= address
      # Must set an initial value, otherwise max_address_reg_size will be nil if a sub_block contains only
      # a single register.
      @max_address_reg_size = size unless @max_address_reg_size
      @min_reg_address = address if address < @min_reg_address
      if address > @max_reg_address
        @max_address_reg_size = size
        @max_reg_address = address
      end
      @reg_define_file ||= define_file(caller[0])

      if block_given?
        @new_reg_attrs = { meta: bit_info }
        yield self
        bit_info = @new_reg_attrs
      else
        # If no block given then init with all writable bits unless bit_info has
        # been supplied
        unless bit_info.any? { |k, v| v.is_a?(Hash) && v[:pos] }
          bit_info = { d: { pos: 0, bits: size }.merge(bit_info) }
        end
      end
      if _registers[id] && Origen.config.strict_errors
        puts ''
        puts "Add register error, you have already added a register named #{id} to #{self.class}"
        puts ''
        fail 'Duplicate register error!'
      else
        attributes = {
          define_file: @reg_define_file,
          address:     address,
          size:        size,
          bit_info:    bit_info,
          description: description
        }
        Reg::REG_LEVEL_ATTRIBUTES.each do |attribute, _meta|
          attributes[attribute] = local_vars[attribute]
        end
        _registers[id] = Placeholder.new(self, id, attributes)
      end
      @reg_define_file = nil
    end
Add a register.
 When adding a register you must supply a name, an address, size in bits, and bit definitions,
 any bits that are not declared will be filled with dummy bit objects that are
 not writable and will read back as 0.

 @example
             Name    Address  Size   Bit Definitions
   add_reg :control,  0x00,    16    :mode    => { :pos => 8, :bits => 8 },
                                     # Leaving out bits does 1 by default
                                     :launch  => { :pos => 6 },
                                     # The default reset state is 0, specify an alternative..
                                     :status  => { :pos => 4, :bits => 2, :res => 0b11 },
                                     :fail    => { :pos => 2 },
                                     :done    => { :pos => 0 }

 Can be called on any object to add a register to it