Skip to content

Address Map

Address Map.

Classes:

Name Description
AddrMap

Address Map.

Conflict

AddrMap Conflict Error.

AddrMap

Address Map.

Other Parameters:

Name Type Description
addrwidth int

Address width. Calculated automatically.

is_sub bool

Handle sub addresses only. Just the minimum number of address bits is evaluated.

# default (object

Default item, returned on unallocated address ranges.

allow_overlapping bool

Allow overlapping address ranges.

Example:

>>> a = AddrMap()
>>> a
AddrMap()
>>> a.add('T', size=0x400)
AddrRange('T', 0x0, '1 KB')
>>> a.add('A', 0x5000, 0x1000)
AddrRange('A', 0x5000, '4 KB')
>>> a.add('B', 0x2000, 0x1000)
AddrRange('B', 0x2000, '4 KB')
>>> a.add('C', 0xD000, 0x800)
AddrRange('C', 0xD000, '2 KB')
>>> a.add('Z', size=0x1000)
AddrRange('Z', 0xE000, '4 KB')
>>> a.add('X', 0xF0800000, 1024*1024*3)
AddrRange('X', 0xF0800000, '3 MB')

Addresses can be used only once:

>>> a.add('D', 0xE400, 0x0400)
Traceback (most recent call last):
    ...
icdutil.addrmap.Conflict: AddrRange('D', 0xE400, '1 KB'): overlaps with AddrRange('Z', 0xE000, '4 KB').
>>> a.add('D', 0x2000)
Traceback (most recent call last):
    ...
icdutil.addrmap.Conflict: AddrRange('D', 0x2000, '1 byte'): overlaps with AddrRange('B', 0x2000, '4 KB').
>>> a.add('D', 0x2000, '8 KB')
Traceback (most recent call last):
    ...
icdutil.addrmap.Conflict: AddrRange('D', 0x2000, '8 KB'): overlaps with AddrRange('B', 0x2000, '4 KB').
>>> a.add('D', 0x1800, '4 KB')
Traceback (most recent call last):
    ...
icdutil.addrmap.Conflict: AddrRange('D', 0x1800, '4 KB'): overlaps with AddrRange('B', 0x2000, '4 KB').

An iteration will serve :class:AddrRange objects sorted by baseaddr:

>>> for addrrange in a:
...     addrrange
AddrRange('T', 0x0, '1 KB')
AddrRange('B', 0x2000, '4 KB')
AddrRange('A', 0x5000, '4 KB')
AddrRange('C', 0xD000, '2 KB')
AddrRange('Z', 0xE000, '4 KB')
AddrRange('X', 0xF0800000, '3 MB')

The size is defined by the number of entries:

>>> len(a)
6

By using a default the gaps are filled with this item:

>>> for addrrange in a.get(default='d'):
...     addrrange
AddrRange('T', 0x0, '1 KB')
AddrRange('d', 0x400, '7 KB')
AddrRange('B', 0x2000, '4 KB')
AddrRange('d', 0x3000, '8 KB')
AddrRange('A', 0x5000, '4 KB')
AddrRange('d', 0x6000, '28 KB')
AddrRange('C', 0xD000, '2 KB')
AddrRange('d', 0xD800, '2 KB')
AddrRange('Z', 0xE000, '4 KB')
AddrRange('d', 0xF000, '3940292 KB')
AddrRange('X', 0xF0800000, '3 MB')
AddrRange('d', 0xF0B00000, '245 MB')
>>> len(tuple(a.get('d')))
12

The is_sub attribute defines the address range defaults:

>>> b = AddrMap(addrwidth=32, is_sub=True)
>>> b
AddrMap(addrwidth=32, is_sub=True)
>>> b.add('T', size=0x400)
AddrRange('T', 0x00000000, '1 KB', addrwidth=32, is_sub=True)
>>> b.add('A', 0x5000, 0x1000)
AddrRange('A', 0x00005000, '4 KB', addrwidth=32, is_sub=True)
>>> b.add('B', 0x2000, 0x1000)
AddrRange('B', 0x00002000, '4 KB', addrwidth=32, is_sub=True)
>>> b.add('C', 0xD000, 0x800)
AddrRange('C', 0x0000D000, '2 KB', addrwidth=32, is_sub=True)
>>> b.add('Z', size=0x1000)
AddrRange('Z', 0x0000E000, '4 KB', addrwidth=32, is_sub=True)
>>> b.add('X', 0xF0800000, 1024*1024*3, is_sub=False)
AddrRange('X', 0xF0800000, '3 MB', addrwidth=32)
>>> for addrrange in b:
...     addrrange
AddrRange('T', 0x00000000, '1 KB', addrwidth=32, is_sub=True)
AddrRange('B', 0x00002000, '4 KB', addrwidth=32, is_sub=True)
AddrRange('A', 0x00005000, '4 KB', addrwidth=32, is_sub=True)
AddrRange('C', 0x0000D000, '2 KB', addrwidth=32, is_sub=True)
AddrRange('Z', 0x0000E000, '4 KB', addrwidth=32, is_sub=True)
AddrRange('X', 0xF0800000, '3 MB', addrwidth=32)

The allow_overlapping attribute allows address ranges to intersect.

>>> c = AddrMap(allow_overlapping=True)
>>> c
AddrMap(allow_overlapping=True)
>>> c.add('L', size=0x1000)
AddrRange('L', 0x0, '4 KB')
>>> c.add('R', 0x400, size=0x1000)
AddrRange('R', 0x400, '4 KB')
>>> c.add('M', 0x200, '2 KB')
AddrRange('M', 0x200, '2 KB')
>>> for addrrange in c:
...     addrrange
AddrRange('L', 0x0, '4 KB')
AddrRange('M', 0x200, '2 KB')
AddrRange('R', 0x400, '4 KB')

Methods:

Name Description
cp_addrranges

Copy address ranges from other AddrMap.

add

Add item for address decoding.

get_free_baseaddr

Return baseaddress of free window with size.

get

Return all :any:AddrRange items and fill gaps with default.

cut

Cut out address range from baseaddr for size.

lookup

Lookup address range by addr.

match

Return address map with address ranges intersecting with range from baseaddr for size.

match_addrrange

Return address map with address ranges intersecting with range from baseaddr for size.

find

Return address map with address ranges containing item.

get_overview

Return overview table.

Attributes:

Name Type Description
firstaddr int | None

First used address.

lastaddr int | None

Last used address.

addrspace int | None

Allocated Address space.

eff_addrwidth int | None

Effective Address Width.

decode_lsb int | None

Address decoding LSB (counted from 0).

decode_msb int | None

Address decoding MSB (counted from 0).

decode_slice

Address Slice.

is_full

Return if entire address map range is covered.

firstaddr property

firstaddr

First used address.

Example:

>>> a = AddrMap()
>>> a.firstaddr
>>> a.add('A', 0x5000, '4 KB')
AddrRange('A', 0x5000, '4 KB')
>>> a.firstaddr
Hex('0x5000')
>>> a.add('B', 0x2000, '4 KB')
AddrRange('B', 0x2000, '4 KB')
>>> a.firstaddr
Hex('0x2000')

lastaddr property

lastaddr

Last used address.

addrspace property

addrspace

Allocated Address space.

Example:

>>> a = AddrMap()
>>> a.addrspace
>>> a.add('A', 0x5000, '4 KB')
AddrRange('A', 0x5000, '4 KB')
>>> str(a.addrspace)
'0x1000'
>>> a.add('B', 0x2000, '4 KB')
AddrRange('B', 0x2000, '4 KB')
>>> str(a.addrspace)
'0x4000'
>>> a.add('C', 0x7000, 13)
AddrRange('C', 0x7000, '13 bytes')
>>> str(a.addrspace)
'0x500D'

eff_addrwidth property

eff_addrwidth

Effective Address Width.

Return address width, either explicitly set or calculated from existing entries.

Example:

>>> a = AddrMap()
>>> a.eff_addrwidth
>>> a.add('A', 0x5000, '4 KB')
AddrRange('A', 0x5000, '4 KB')
>>> a.eff_addrwidth
15
>>> a = AddrMap(addrwidth=16)
>>> a.eff_addrwidth
16
>>> a.add('A', 2**18, '4 KB')
Traceback (most recent call last):
    ...
RuntimeError: AddrRange('A', 0x40000, '4 KB', addrwidth=16): exceeds maximum address range of 0x10000.

decode_lsb property

decode_lsb

Address decoding LSB (counted from 0).

Example:

>>> a = AddrMap()
>>> a.decode_lsb is None
True
>>> a.add('A', 0x2000, '8 KB')
AddrRange('A', 0x2000, '8 KB')
>>> a.decode_lsb
13
>>> a.add('B', 0x5000, '1 KB')
AddrRange('B', 0x5000, '1 KB')
>>> a.decode_lsb
10
>>> a.add('C', 0x6000, '2 KB')
AddrRange('C', 0x6000, '2 KB')
>>> a.decode_lsb
10

decode_msb property

decode_msb

Address decoding MSB (counted from 0).

Example:

>>> a = AddrMap(addrwidth=32)
>>> a.is_sub
False
>>> a.decode_msb
31
>>> a.add('A', 0x5000, '4 KB')
AddrRange('A', 0x00005000, '4 KB', addrwidth=32)
>>> a.decode_msb
31

>>> a = AddrMap(is_sub=True)
>>> a.is_sub
True
>>> a.decode_msb is None
True
>>> a.add('A', 0x1000, '1 KB')
AddrRange('A', 0x1000, '1 KB', is_sub=True)
>>> a.decode_msb
12
>>> a.add('B', 0x2000, '8 KB')
AddrRange('B', 0x2000, '8 KB', is_sub=True)
>>> a.decode_msb
13
>>> a.add('C', 0x4000, 1)
AddrRange('C', 0x4000, '1 byte', is_sub=True)
>>> a.decode_msb
14

decode_slice property

decode_slice

Address Slice.

Example:

>>> a = AddrMap()
>>> a.decode_slice is None
True
>>> a.add('A', 0x1000, '4 KB')
AddrRange('A', 0x1000, '4 KB')
>>> a.decode_slice
Slice('12')
>>> a.add('B', 0x3000, '8 KB')
AddrRange('B', 0x3000, '8 KB')
>>> a.decode_slice
Slice('14:12')

is_full property

is_full

Return if entire address map range is covered.

Example:

>>> a = AddrMap()
>>> a.is_full is None
True
>>> a.add('A', size='8 KB')
AddrRange('A', 0x0, '8 KB')
>>> a.is_full
True
>>> a.add('B', size='4 KB')
AddrRange('B', 0x2000, '4 KB')
>>> a.is_full
False
>>> a.add('C', size='4 KB')
AddrRange('C', 0x3000, '4 KB')
>>> a.is_full
True

>>> b = AddrMap(addrwidth=13)
>>> b.is_full is None
True
>>> b.add('A', 0x0, size='6 KB')
AddrRange('A', 0x0000, '6 KB', addrwidth=13)
>>> b.is_full
False
>>> b.add('B', size='2 KB')
AddrRange('B', 0x1800, '2 KB', addrwidth=13)
>>> b.is_full
True

__add

__add(addrrange)

Insert new AddrRange into AddrMap.

cp_addrranges

cp_addrranges(addranges)

Copy address ranges from other AddrMap.

add

add(
    item,
    baseaddr=None,
    size=1,
    is_sub=None,
    align=None,
    startsearch=None,
)

Add item for address decoding.

Parameters:

Name Type Description Default
item

any object managed by this address decoder

required

Other Parameters:

Name Type Description
baseaddr int | None

Base address. Behind last item by default.

size int

Size in bytes

is_sub bool | None

Overwrite sub address attribute.

align int | None

Alignment

startsearch int | None

Search of free address at given number (if baseaddr is None)

Example:

>>> a = AddrMap()
>>> a.add('A', baseaddr=0x3000, size='4 KB')
AddrRange('A', 0x3000, '4 KB')
>>> a.add('B', 0x1000, '1 KB', is_sub=True)
AddrRange('B', 0x1000, '1 KB', is_sub=True)
>>> a.add('C', 0x4500, '4 KB', align=0x1000)
AddrRange('C', 0x5000, '4 KB')

get_free_baseaddr

get_free_baseaddr(size, align=None, start=None)

Return baseaddress of free window with size.

Parameters:

Name Type Description Default
size int

Window Size

required

Other Parameters:

Name Type Description
align

Alignment, default aligned to size

start

Start search behind given address

Example:

>>> a = AddrMap(is_sub=True, addrwidth=16)
>>> a.get_free_baseaddr(0x10, start=0x0)
Hex('0x0')
>>> a.add('A', 0x1000, '1 KB')
AddrRange('A', 0x1000, '1 KB', addrwidth=16, is_sub=True)
>>> a.get_free_baseaddr(0x400)
Hex('0x1400')
>>> a.get_free_baseaddr('4 KB')
Hex('0x2000')
>>> a.get_free_baseaddr('8 KB', align=0x4000)
Hex('0x4000')
>>> a.get_free_baseaddr('1 KB', start=0x400)
Hex('0x400')
>>> a.get_free_baseaddr('1 KB', start=0x4000)
Hex('0x4000')
>>> a.add('B', 0x3000, '4 KB')
AddrRange('B', 0x3000, '4 KB', addrwidth=16, is_sub=True)
>>> a.get_free_baseaddr('4 KB', start=0x2800)
Hex('0x4000')

If the AddrMap has addrwidth set, a check for end range overflow is executed

>>> a.get_free_baseaddr('8 KB', start=0xF0000)
Traceback (most recent call last):
    ...
ValueError: No space left in address map (64 KB) for new range at 0xF0000 with size of 8 KB
>>> a.get_free_baseaddr('8 KB', align=0x1000, start=0xF000)
Traceback (most recent call last):
    ...
ValueError: No space left in address map (64 KB) for new range at 0xF000 with size of 8 KB

get

get(default=None)

Return all :any:AddrRange items and fill gaps with default.

Example:

>>> a = AddrMap()
>>> a.add('T', size=0x400)
AddrRange('T', 0x0, '1 KB')
>>> a.add('A', 0x5000, 0x1000)
AddrRange('A', 0x5000, '4 KB')
>>> a.add('B', 0x2000, 0x1000)
AddrRange('B', 0x2000, '4 KB')
>>> a.add('C', 0xD000, '2 KB')
AddrRange('C', 0xD000, '2 KB')
>>> a.add('Z', size=0x2000)
AddrRange('Z', 0xE000, '8 KB')

>>> for addrrange in a.get():
...     addrrange
AddrRange('T', 0x0, '1 KB')
AddrRange('B', 0x2000, '4 KB')
AddrRange('A', 0x5000, '4 KB')
AddrRange('C', 0xD000, '2 KB')
AddrRange('Z', 0xE000, '8 KB')

>>> for addrrange in a.get(default='reserved'):
...     addrrange
AddrRange('T', 0x0, '1 KB')
AddrRange('reserved', 0x400, '7 KB')
AddrRange('B', 0x2000, '4 KB')
AddrRange('reserved', 0x3000, '8 KB')
AddrRange('A', 0x5000, '4 KB')
AddrRange('reserved', 0x6000, '28 KB')
AddrRange('C', 0xD000, '2 KB')
AddrRange('reserved', 0xD800, '2 KB')
AddrRange('Z', 0xE000, '8 KB')

Empty:

>>> a = AddrMap()
>>> list(a.get())
[]
>>> list(a.get(default="<default>"))
[]
>>> a = AddrMap(addrwidth=16)
>>> list(a.get(default="<default>"))
[AddrRange('<default>', 0x0000, '64 KB', addrwidth=16)]

Default items before and after real AddrRange:

>>> a.add('A', 0x5000, 0x1000)
AddrRange('A', 0x5000, '4 KB', addrwidth=16)
>>> for addrrange in a.get(default='reserved'):
...     addrrange
AddrRange('reserved', 0x0000, '20 KB', addrwidth=16)
AddrRange('A', 0x5000, '4 KB', addrwidth=16)
AddrRange('reserved', 0x6000, '40 KB', addrwidth=16)

>>> a.add('Z', 0xE000, size=0x2000)
AddrRange('Z', 0xE000, '8 KB', addrwidth=16)
>>> for addrrange in a.get(default='reserved'):
...     addrrange
AddrRange('reserved', 0x0000, '20 KB', addrwidth=16)
AddrRange('A', 0x5000, '4 KB', addrwidth=16)
AddrRange('reserved', 0x6000, '32 KB', addrwidth=16)
AddrRange('Z', 0xE000, '8 KB', addrwidth=16)

cut

cut(baseaddr, size=1)

Cut out address range from baseaddr for size.

Return address map with cut address ranges.

Example:

>>> a = AddrMap()
>>> a.add('A', 0x0000, 0x1000)
AddrRange('A', 0x0, '4 KB')
>>> a.add('B', 0x1000, 0x1000)
AddrRange('B', 0x1000, '4 KB')
>>> a.add('C', 0x2000, 0x1000)
AddrRange('C', 0x2000, '4 KB')
>>> a.add('D', 0x3000, 0x1000)
AddrRange('D', 0x3000, '4 KB')
>>> print(a.get_overview())
Baseaddr    Size           Sub    Item
----------  -------------  -----  ------
0x0         0x1000 (4 KB)  No     'A'
0x1000      0x1000 (4 KB)  No     'B'
0x2000      0x1000 (4 KB)  No     'C'
0x3000      0x1000 (4 KB)  No     'D'

Cut multiple address ranges:

>>> c = a.cut(0x1800, 0x1000)
>>> print(a.get_overview())
Baseaddr    Size           Sub    Item
----------  -------------  -----  ------
0x0         0x1000 (4 KB)  No     'A'
0x1000      0x800 (2 KB)   No     'B'
0x2800      0x800 (2 KB)   No     'C'
0x3000      0x1000 (4 KB)  No     'D'
>>> print(c.get_overview())
Baseaddr    Size          Sub    Item
----------  ------------  -----  ------
0x1800      0x800 (2 KB)  No     'B'
0x2000      0x800 (2 KB)  No     'C'

Cut at the front:

>>> c = a.cut(0, 0x1000)
>>> print(a.get_overview())
Baseaddr    Size           Sub    Item
----------  -------------  -----  ------
0x1000      0x800 (2 KB)   No     'B'
0x2800      0x800 (2 KB)   No     'C'
0x3000      0x1000 (4 KB)  No     'D'
>>> print(c.get_overview())
Baseaddr    Size           Sub    Item
----------  -------------  -----  ------
0x0         0x1000 (4 KB)  No     'A'

Cut at the end:

>>> c = a.cut(0x3C00, 0x1000)
>>> print(a.get_overview())
Baseaddr    Size          Sub    Item
----------  ------------  -----  ------
0x1000      0x800 (2 KB)  No     'B'
0x2800      0x800 (2 KB)  No     'C'
0x3000      0xC00 (3 KB)  No     'D'
>>> print(c.get_overview())
Baseaddr    Size          Sub    Item
----------  ------------  -----  ------
0x3C00      0x400 (1 KB)  No     'D'

Cut exactly one:

>>> c = a.cut(0x2800, '2 KB')
>>> print(a.get_overview())
Baseaddr    Size          Sub    Item
----------  ------------  -----  ------
0x1000      0x800 (2 KB)  No     'B'
0x3000      0xC00 (3 KB)  No     'D'
>>> print(c.get_overview())
Baseaddr    Size          Sub    Item
----------  ------------  -----  ------
0x2800      0x800 (2 KB)  No     'C'

Cut nothing:

>>> c = a.cut(0x2000, 0x100)
>>> print(a.get_overview())
Baseaddr    Size          Sub    Item
----------  ------------  -----  ------
0x1000      0x800 (2 KB)  No     'B'
0x3000      0xC00 (3 KB)  No     'D'
>>> print(c.get_overview())
Baseaddr    Size      Sub    Item
----------  --------  -----  ------

lookup

lookup(addr)

Lookup address range by addr.

Example:

>>> a = AddrMap()
>>> a.add('A', 0x5000, 0x1000)
AddrRange('A', 0x5000, '4 KB')
>>> a.add('B', 0x2000, 0x1000)
AddrRange('B', 0x2000, '4 KB')
>>> a.add('C', 0xD000, 0x800)
AddrRange('C', 0xD000, '2 KB')

>>> a.lookup(0x2000)
AddrRange('B', 0x2000, '4 KB')
>>> a.lookup(0x2FFF)
AddrRange('B', 0x2000, '4 KB')
>>> a.lookup(0x3000)

match

match(baseaddr, size=1)

Return address map with address ranges intersecting with range from baseaddr for size.

Example:

>>> a = AddrMap()
>>> a.add('A', 0x1000, 0x1000)
AddrRange('A', 0x1000, '4 KB')
>>> a.add('B', 0x2000, 0x1000)
AddrRange('B', 0x2000, '4 KB')
>>> a.add('C', 0x3000, 0x800)
AddrRange('C', 0x3000, '2 KB')
>>> m = a.match(0x1800, 0x1000)
>>> m
AddrMap()
>>> list(m)
[AddrRange('A', 0x1000, '4 KB'), AddrRange('B', 0x2000, '4 KB')]

match_addrrange

match_addrrange(addrrange)

Return address map with address ranges intersecting with range from baseaddr for size.

Example:

>>> a = AddrMap()
>>> a.add('A', 0x1000, 0x1000)
AddrRange('A', 0x1000, '4 KB')
>>> a.add('B', 0x2000, 0x1000)
AddrRange('B', 0x2000, '4 KB')
>>> a.add('C', 0x3000, 0x800)
AddrRange('C', 0x3000, '2 KB')
>>> m = a.match_addrrange(AddrRange(0x1800, 0x1000))
>>> m
AddrMap()
>>> list(m)
[AddrRange('A', 0x1000, '4 KB'), AddrRange('B', 0x2000, '4 KB')]

find

find(item)

Return address map with address ranges containing item.

Example:

>>> a = AddrMap()
>>> a.add('A', 0x5000, 0x1000)
AddrRange('A', 0x5000, '4 KB')
>>> a.add('B', 0x2000, 0x1000)
AddrRange('B', 0x2000, '4 KB')
>>> a.add('A', 0xD000, 0x800)
AddrRange('A', 0xD000, '2 KB')
>>> list(a.find('A'))
[AddrRange('A', 0x5000, '4 KB'), AddrRange('A', 0xD000, '2 KB')]

get_overview

get_overview()

Return overview table.

Example:

>>> a = AddrMap()
>>> a.add('A', 0x5000, 0x1000)
AddrRange('A', 0x5000, '4 KB')
>>> a.add('B', 0x2000, 0x1000)
AddrRange('B', 0x2000, '4 KB')
>>> a.add('C', 0xD000, 0x800)
AddrRange('C', 0xD000, '2 KB')
>>> print(a.get_overview())
Baseaddr    Size           Sub    Item
----------  -------------  -----  ------
0x2000      0x1000 (4 KB)  No     'B'
0x5000      0x1000 (4 KB)  No     'A'
0xD000      0x800 (2 KB)   No     'C'

Conflict

Bases: RuntimeError

AddrMap Conflict Error.