lib/rggen/builtins/register_block/base_address.rb
simple_item :register_block, :base_address do
register_map do
field :start_address
field :end_address
field :byte_size
field :local_address_width
input_pattern %r{(#{number})-(#{number})}
build do |cell|
parse_address(cell)
case
when @start_address >= @end_address
error "start address is equal to or greater than end address: #{cell}"
when not_aligned_with_data_width?
error 'not aligned with data width' \
"(#{configuration.data_width}): #{cell}"
when not_aligned_with_local_address_width?
error 'not aligned with local address width' \
"(#{@local_address_width}): #{cell}"
when @end_address > max_address
error 'exceeds the maximum base address' \
"(0x#{max_address.to_s(16)}): #{cell}"
when overlapped_address?
error "overlapped base address: #{cell}"
end
end
def parse_address(cell)
if pattern_matched?
@start_address = Integer(captures[0])
@end_address = Integer(captures[1])
@byte_size = @end_address - @start_address + 1
@local_address_width = Math.clog2(@byte_size) if @byte_size > 0
else
error "invalid value for base address: #{cell.inspect}"
end
end
def not_aligned_with_data_width?
byte_width = configuration.byte_width
return true unless (@start_address + 0).multiple?(byte_width)
return true unless (@end_address + 1).multiple?(byte_width)
false
end
def not_aligned_with_local_address_width?
window_size = 2**@local_address_width
return true unless @start_address.multiple?(window_size)
false
end
def max_address
2**configuration.address_width - 1
end
def overlapped_address?
own_range = @start_address..@end_address
register_map.register_blocks.any? do |block|
own_range.overlap?(block.start_address..block.end_address)
end
end
end
end