Memory Map

class torii.lib.mem.map.MemoryMap(*, addr_width: int, data_width: int, alignment: int = 0, name: str | None = None) None

Memory map.

A memory map is a hierarchical description of an address space, describing the structure of address decoders of peripherals as well as bus bridges. It is built by adding resources (range allocations for registers, memory, etc) and windows (range allocations for bus bridges), and can be queried later to determine the address of any given resource from a specific vantage point in the design.

Address assignment

To simplify address assignment, each memory map has an implicit next address, starting at 0. If a resource or a window is added without specifying an address explicitly, the implicit next address is used. In any case, the implicit next address is set to the address immediately following the newly added resource or window.

Parameters:
  • addr_width (int) – Address width.

  • data_width (int) – Data width.

  • alignment (log2 of int) – Range alignment. Each added resource and window will be placed at an address that is a multiple of 2 ** alignment, and its size will be rounded up to be a multiple of 2 ** alignment.

  • name (str | None) – Name of the address range.

property addr_width: int

Todo

Document Me

property data_width: int

Todo

Document Me

property alignment: int

Todo

Document Me

property name: str | None

Todo

Document Me

freeze() None

Freeze the memory map.

Once the memory map is frozen, its visible state becomes immutable. Resources and windows cannot be added anymore, and its address width cannot be extended further.

align_to(alignment: int) int

Align the implicit next address.

Parameters:

alignment (log2 of int) – Address alignment. The start of the implicit next address will be a multiple of 2 ** max(alignment, self.alignment).

Return type:

int

Returns:

int – Implicit next address.

add_resource(resource: object, *, name: str, size: int, addr: int | None = None, alignment: int | None = None, extend: bool = False) tuple[int, int]

Add a resource.

A resource is any device on the bus that is a destination for bus transactions, e.g. a register or a memory block.

Parameters:
  • resource (object) – Arbitrary object representing a resource.

  • name (str) – Name of the resource. It must not collide with the name of other resources or windows present in this memory map.

  • addr (int | None) – Address of the resource. If None, the implicit next address will be used. Otherwise, the exact specified address (which must be a multiple of 2 ** max(alignment, self.alignment)) will be used.

  • size (int) – Size of the resource, in minimal addressable units. Rounded up to a multiple of 2 ** max(alignment, self.alignment).

  • alignment (log2 of int | None) – Alignment of the resource. If not specified, the memory map alignment is used.

  • extend (bool) – Allow memory map extension. If True, the upper bound of the address space is raised as needed, in order to fit a resource that would otherwise be out of bounds.

Return type:

tuple[int, int]

Returns:

tuple[int, int] – A tuple [start, end) describing the address range assigned to the resource.

Raises:

ValueError – If one of the following occurs: - this memory map is frozen; - the requested address and size, after alignment, would overlap with any resources or windows that have already been added, or would be out of bounds; - the resource has already been added to this memory map; - the name of the resource is already present in the namespace of this memory map;

resources()

Iterate local resources and their address ranges.

Non-recursively iterate resources in ascending order of their address.

Returns:

Generator[] – Yields a tuple resource, name, (start, end) describing the address range assigned to the resource.

add_window(window: MemoryMap, *, addr: int | None = None, sparse: int | None = None, extend: bool = False) tuple[int, int, int]

Add a window.

A window is a device on a bus that provides access to a different bus, i.e. a bus bridge. It performs address translation, such that the devices on a subordinate bus have different addresses; the memory map reflects this address translation when resources are looked up through the window.

Sparse addressing

If a narrow bus is bridged to a wide bus, the bridge can perform sparse or dense address translation. In the sparse case, each transaction on the wide bus results in one transaction on the narrow bus; high data bits on the wide bus are ignored, and any contiguous resource on the narrow bus becomes discontiguous on the wide bus. In the dense case, each transaction on the wide bus results in several transactions on the narrow bus, and any contiguous resource on the narrow bus stays contiguous on the wide bus.

Parameters:
  • window (MemoryMap) – A memory map describing the layout of the window. It is frozen as a side-effect of being added to this memory map.

  • addr (int or None) – Address of the window. If None, the implicit next address will be used after aligning it to 2 ** window.addr_width. Otherwise, the exact specified address (which must be a multiple of 2 ** window.addr_width) will be used.

  • sparse (bool or None) – Address translation type. Ignored if the datapath widths of both memory maps are equal; must be specified otherwise.

  • extend (bool) – Allow memory map extension. If True, the upper bound of the address space is raised as needed, in order to fit a window that would otherwise be out of bounds.

Return type:

tuple[int, int, int]

Returns:

tuple[int, int, int] – A tuple (start, end, ratio) describing the address range assigned to the window. When bridging buses of unequal data width, ratio is the amount of contiguous addresses on the narrower bus that are accessed for each transaction on the wider bus. Otherwise, it is always 1.

Raises:

ValueError – If one of the following occurs: - this memory map is frozen; - the requested address and size, after alignment, would overlap with any resources or windows that have already been added, or would be out of bounds; - the added memory map has a wider datapath than this memory map; - dense address translation is used and the datapath width of this memory map is not an integer multiple of the datapath of the added memory map; - the name of the added memory map is already present in the namespace of this memory map; - the added memory map has no name, and the name of one of its subordinate resources or windows is already present in the namespace of this memory map;

windows()

Iterate local windows and their address ranges.

Non-recursively iterate windows in ascending order of their address.

Returns:

Generator – Yields a tuple window, (start, end, ratio) describing the address range assigned to the window. When bridging buses of unequal data width, ratio is the amount of contiguous addresses on the narrower bus that are accessed for each transaction on the wider bus. Otherwise, it is always 1.

window_patterns() Generator[tuple[MemoryMap, tuple[str, int]]]

Iterate local windows and patterns that match their address ranges.

Non-recursively iterate windows in ascending order of their address.

Return type:

Generator[tuple[MemoryMap, tuple[str, int]]]

Returns:

Generator[tuple[MemoryMap, tuple[str, int]]] – Yields a tuple window, (pattern, ratio) describing the address range assigned to the window. pattern is a self.addr_width wide pattern that may be used in Case or match to determine if an address signal is within the address range of window. When bridging buses of unequal data width, ratio is the amount of contiguous addresses on the narrower bus that are accessed for each transaction on the wider bus. Otherwise, it is always 1.

all_resources() Generator[ResourceInfo]

Iterate all resources and their address ranges.

Recursively iterate all resources in ascending order of their address, performing address translation for resources that are located behind a window.

Return type:

Generator[ResourceInfo]

Returns:

Generator[ResourceInfo] – Yields instances of ResourceInfo describing the resource and its address range.

find_resource(resource: object) ResourceInfo

Find address range corresponding to a resource.

Recursively find the address range of a resource, performing address translation for resources that are located behind a window.

Parameters:

resource (object) – Resource previously added to this memory map or any windows.

Return type:

ResourceInfo

Returns:

ResourceInfo – An instance of ResourceInfo describing the resource and its address range.

Raises:

KeyError – If the resource is not found.

decode_address(address: int) object | None

Decode an address to a resource.

Parameters:

address (int) – Address of interest.

Return type:

object | None

Returns:

  • object – A resource mapped to the provided address.

  • None – There is no such resource.

class torii.lib.mem.map.ResourceInfo(resource: object, name: str | Iterable[str], start: int, end: int, width: int) None

Resource metadata.

A wrapper class for resource objects, with their assigned name and address range.

Parameters:
  • resource (object) – Arbitrary object representing a resource. See MemoryMap.add_resource() for details.

  • name (iter(str)) – Name assigned to the resource. It is prefixed by the name of each window sitting between the resource and the memory map from which this ResourceInfo was obtained. See MemoryMap.add_window() for details.

  • start (int) – Start of the address range assigned to the resource.

  • end (int) – End of the address range assigned to the resource.

  • width (int) – Amount of data bits accessed at each address. It may be equal to the data width of the memory map from which this ResourceInfo was obtained, or less if the resource is located behind a window that uses sparse addressing.

property resource: object

Todo

Document Me

property name: tuple[str, ...]

Todo

Document Me

property start: int

Todo

Document Me

property end: int

Todo

Document Me

property width: int

Todo

Document Me