Internal Representation

Topwrap uses a custom object hierarchy, further called “internal representation” or “IR”, in order to store block design and related data in memory and operate on it.

Frontend & Backend

The Frontend based classes converts external formats, such as SystemVerilog, VHDL or KPM into the IR. Complementarily, the Backend based classes convert our IR into external formats.

The reason for separating the logic like this is to be able to easily add support for multiple fronteds and backends formats and make them interchangeable.

API interface

exception FrontendParseException

Bases: TranslationError

Exception occurred during parsing sources by the frontend

class Frontend(modules: Iterable[Module] = (), interfaces: Iterable[InterfaceDefinition] = ())

Bases: ABC

parse_str(sources: Iterable[str]) Iterator[Module]

Parse a collection of string sources into IR modules

Parameters:
sources: Iterable[str]

Collection of string sources

abstract parse_files(sources: Iterable[Path]) Iterator[Module]

Parse a collection of source files into IR modules

Parameters:
sources: Iterable[Path]

Collection of paths to sources

class BackendOutputInfo(filename: str, content: str)

Bases: object

Output of the backend’s serialization process

filename : str

The filename for this output as suggested by the specific backend E.g. dataflow.kpm.json or axibridge.sv

content : str

The content of the file generated by the backend

save(path: Path)

Save this output as a file on the filesystem under a given path

Parameters:
path: Path

The path where to save the file. If it points only to a directory, then the file is saved with the self.filename name.

class Backend

Bases: ABC, Generic[_T]

The base class for backend implementations used to convert our IR represented by the Module class into various external formats, represented by the generic parameter _T.

abstract represent(module: Module, /) _T

Convert the IR into an arbitrary custom external format.

abstract serialize(repr: _T, /) Iterator[BackendOutputInfo]

Serialize the custom format object into one or more text files, represented by their content, alongside with additional information about them, like the suggested filename.

Module

class Module(*, id: Identifier, refs: Iterable[FileReference] = (), ports: Iterable[Port] = (), parameters: Iterable[Parameter] = (), interfaces: Iterable[Interface] = (), design: Design | None = None)

Bases: ModelBase

The top-level class of the IR. It fully represents the public interface of a HDL module, holding definitions of all of its structured ports and interfaces, parameters, and optionally its inner block design if available.

id : Identifier
property design

Returns the optional inner block design of this module

property ports : Sequence[Port]
property parameters : Sequence[Parameter]
property interfaces : Sequence[Interface]
property refs : Sequence[FileReference]

Returns references to external files that define this module, if any. This information is generally added by the respective frontend used to parse this module.

add_port(port: Port)
add_parameter(parameter: Parameter)
add_interface(interface: Interface)
add_reference(ref: FileReference)
non_intf_ports() Iterator[Port]

Yield ports that don’t realise signals of any interface

Design

class ModuleInstance(*, name: VariableName, module: Module, parameters: Mapping[ObjectId[Parameter], ElaboratableValue] = {})

Bases: ModelBase

Represents an instantiated module with values supplied for its appropriate respective parameters. This class is necessary to differentiate multiple instances of the same module in a design.

parent : Design

Reference to the design that contains this component

name : VariableName

The name of this instance. It corresponds to “instance_name” in this exemplary Verilog construct: MODULE #(.WIDTH(32)) instance_name (.clk(clk));

module : Module

The module that this is an instance of. Corresponds to “MODULE” in the Verilog construct defined above.

parameters : dict[ObjectId[Parameter], ElaboratableValue]

Concrete parameter values for the module that this is an instance of. Corresponds to “#(.WIDTH(32))” in the above Verilog construct.

class Design(*, components: Iterable[ModuleInstance] = (), interconnects: Iterable[Interconnect] = (), connections: Iterable[ConstantConnection | PortConnection | InterfaceConnection] = ())

Bases: ModelBase

This class represents the inner block design of a specific Module. It consists of instances of other modules (components) and connections between them, each other, and external ports of the module that this design represents.

parent : Module
property components : Sequence[ModuleInstance]
property interconnects : Sequence[Interconnect]
property connections : Sequence[ConstantConnection | PortConnection | InterfaceConnection]
add_component(component: ModuleInstance)
add_interconnect(interconnect: Interconnect)
add_connection(connection: ConstantConnection | PortConnection | InterfaceConnection)
connections_with(io: ReferencedPort | ReferencedInterface) Iterator[ElaboratableValue | ReferencedPort | ReferencedInterface]

Yields everything that is connected to a given IO.

Parameters:
io: ReferencedPort | ReferencedInterface

The IO of which connections to yield.

Interface

class InterfaceMode(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: Enum

MANAGER = 'manager'
SUBORDINATE = 'subordinate'
UNSPECIFIED = 'unspecified'
class InterfaceSignalConfiguration(direction: PortDirection, required: bool, default: ElaboratableValue | None = None)

Bases: object

Holds the mode-specific configuration of an interface signal

direction : PortDirection

The direction of this signal in a given InterfaceMode

required : bool

Whether this signal is required or optional

default : ElaboratableValue | None = None

The default value for this signal, if any

class InterfaceSignal(*, name: str, regexp: Pattern[str], type: Logic, modes: Mapping[InterfaceMode, InterfaceSignalConfiguration])

Bases: ModelBase

This class represents a signal in an interface definition. E.g.: The awaddr signal in the AXI interface etc.

name : VariableName
regexp : re.Pattern[str]

While automatically deducing interfaces, if an arbitrary signal’s name matches this regular expression then that signal is considered as a candidate for realizing this signal definition

type : Logic

The logical type of this signal. Fulfills the same function as Port.type

modes : dict[InterfaceMode, InterfaceSignalConfiguration]

A dictionary of modes for this signal and their specific configurations E.g.: A signal that only has an InterfaceMode.MANAGER entry in this dictionary means that it’s valid only on the manager’s side.

class InterfaceDefinition(*, id: Identifier, signals: Iterable[InterfaceSignal])

Bases: object

This represents a definition of an entire interface/bus. E.g. AXI, AHB, Wishbone, etc.

id : Identifier
signals : list[InterfaceSignal]

A list of signal definitions that make up this interface E.g. awaddr, araddr, wdata, rdata, etc…. in AXI

class Interface(name: str, mode: ~topwrap.model.interface.InterfaceMode, definition: ~topwrap.model.interface.InterfaceDefinition, signals: dict[~topwrap.model.misc.ObjectId[~topwrap.model.interface.InterfaceSignal], ~topwrap.model.hdl_types.LogicSlice | None] = <factory>)

Bases: object

A realised instance of an interface that can be connected with other interface instances through InterfaceConnection.

The relationship between this class and InterfaceDefinition is similar to the relationship between ModuleInstance and Module classes.

name : VariableName

Name for this interface instance

mode : InterfaceMode

The mode of this instance (e.g. manager/subordinate)

definition : InterfaceDefinition

The definition of the interface that this is an instance of

parent : Module

The module definition that contains this interface instance

signals : dict[ObjectId[InterfaceSignal], LogicSlice | None]

Realization of signals defined in this interface. A signal can be realized either by:

  • Slicing an already existing external port of the module that this instance belongs to (self.parent), in that case the value in this dictionary is the aforementioned slice.

  • Independently, meaning that whenever necessary, e.g. during output generation by a Backend that does not support interfaces, an arbitrarily generated port based on the InterfaceSignal.type should be generated to represent it. In that case the value in this dictionary is None.

If an entry for a specific signal that exists in the definition is not present in this dictionary, then that signal will not be realized at all. E.g. when it was configured as optional or was given a default value in InterfaceSignalConfiguration.

Connections

class PortDirection(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: Enum

IN = 'in'
OUT = 'out'
INOUT = 'inout'
class Port(*, name: str, direction: PortDirection, type: Logic | None = None)

Bases: object

This represents an external port of a HDL module that can be connected to other ports or constant values in a design.

parent : Module

The module definition that exposes this port

name : VariableName
direction : PortDirection
type : Logic

The type of this port. (Bit, BitStruct, LogicArray etc.)

class ReferencedPort(*, instance: ModuleInstance | None = None, io: _REFIO)

Bases: _ReferencedIO[LogicSlice]

Represents a correctly typed reference to a port

class ReferencedInterface(*, instance: ModuleInstance | None = None, io: _REFIO)

Bases: _ReferencedIO[Interface]

Represents a correctly typed reference to an interface

class ConstantConnection(source: _SRC, target: _TRG)

Bases: _Connection[ElaboratableValue, ReferencedPort]

Represents a connection between a constant value and a port of a component

class PortConnection(source: _SRC, target: _TRG)

Bases: _Connection[ReferencedPort, ReferencedPort]

Represents a connection between two ports of some components

class InterfaceConnection(source: _SRC, target: _TRG)

Bases: _Connection[ReferencedInterface, ReferencedInterface]

Represents a connection between two interfaces of some components

HDL Types

class Dimensions(upper: ~topwrap.model.misc.ElaboratableValue = <factory>, lower: ~topwrap.model.misc.ElaboratableValue = <factory>)

Bases: object

A pair of values representing bounds for a single dimension of a Logic type. Verilog examples: - logic -> upper == lower == 0 - logic[31:0] -> upper == 31, lower == 0 - logic[0:64] -> upper == 0, lower == 64

upper : ElaboratableValue
lower : ElaboratableValue
class Logic

Bases: ABC

An abstract class representing anything that can be used as a logical type for a port or a signal in a module.

name : VariableName | None
parent : Logic | Port | InterfaceSignal | None

The parent of this type. Can be either:

  • Logic - e.g. if this is a StructField then its parent would be a

    BitStruct.

  • Port or InterfaceSignal - in case this represents a top-level

    type definition for an IO.

  • None - in case this is a standalone top-level type definition (e.g. typedef struct)

abstract property size : ElaboratableValue

All Logic subclasses should have an elaboratable size (the number of bits)

property outer : Port | InterfaceSignal | None

Recursively traverses through parents and returns the IO definition that uses this type if encountered.

class LogicSlice(*, logic: Logic, upper: ElaboratableValue | None = None, lower: ElaboratableValue | None = None)

Bases: object

Represents a slicing operation on a logical type

logic : Logic
property upper : ElaboratableValue

Upper bound of the slice

property lower : ElaboratableValue

Lower bound of the slice

class Bit

Bases: Logic

A single bit type. Equivalent to logic or logic[0:0] type in Verilog.

property size : ElaboratableValue

All Logic subclasses should have an elaboratable size (the number of bits)

class LogicArray(*, dimensions: list[Dimensions], item: _ArrayItemOrField)

Bases: Logic, Generic[_ArrayItemOrField]

A type representing a multidimensional array of logical elements.

property size

All Logic subclasses should have an elaboratable size (the number of bits)

dimensions : list[Dimensions]
item : _ArrayItemOrField
class Bits(*, dimensions: list[Dimensions])

Bases: LogicArray[Bit]

A multidimensional array of bits

class StructField(*, name: str, type: _ArrayItemOrField)

Bases: Logic, Generic[_ArrayItemOrField]

A field in a BitStruct

property size

All Logic subclasses should have an elaboratable size (the number of bits)

field_name : VariableName
type : _ArrayItemOrField
class BitStruct(*, fields: list[StructField[Logic]])

Bases: Logic

A complex structural type equivalent to a struct {...} construct in SystemVerilog.

property size

All Logic subclasses should have an elaboratable size (the number of bits)

fields : list[StructField[Logic]]

Interconnects

class InterconnectParams

Bases: object

Base class for parameters/settings specific to a concrete interconnect type

class InterconnectManagerParams

Bases: object

Base class for manager parameters specific to a concrete interconnect type

class InterconnectSubordinateParams(address: ~topwrap.model.misc.ElaboratableValue = <factory>, size: ~topwrap.model.misc.ElaboratableValue = <factory>)

Bases: object

Base class for subordinate parameters specific to a concrete interconnect type.

Transactions to addresses in range [self.address; self.address + self.size) will be routed to this subordinate.

address : ElaboratableValue

The start address of this subordinate in the memory map

size : ElaboratableValue

The size in bytes of this subordinate’s address space

class Interconnect(*, name: str, clock: ReferencedPort, reset: ReferencedPort, params: _IPAR, managers: Mapping[ObjectId[ReferencedInterface], _MANPAR], subordinates: Mapping[ObjectId[ReferencedInterface], _SUBPAR])

Bases: ABC, Generic[_IPAR, _MANPAR, _SUBPAR]

Base class for multiple interconnect generator implementations.

Interconnects connect multiple interface instances together in a many-to-many topology, combining multiple subordinates into a unified address space so that one or multiple managers can access them.

parent : Design

The design containing this interconnect

name : VariableName
clock : ReferencedPort

The clock signal for this interconnect

reset : ReferencedPort

The reset signal for this interconnect

params : _IPAR

Interconnect-wide type-specific parameters

managers : dict[ObjectId[ReferencedInterface], _MANPAR]

Manager interfaces controlling this interconnect described as a mapping between a referenced interface in a design and the type-specific manager configuration

subordinates : dict[ObjectId[ReferencedInterface], _SUBPAR]

Subordinate interfaces subject to this interconnect described in the same format as managers

Miscellaneous

exception TranslationError

Bases: Exception

Fatal error while translating between IR and other formats

exception RelationshipError

Bases: Exception

Logic error of an IR hierarchy, like trying to double-assign a parent to an object

set_parent(child: Any, parent: Any)
VariableName

A placeholder for a future, possibly bounded type for IR object names. For example we may want to reduce possible names to only alphanumerical strings in the future.

class ModelBase

Bases: ABC

This is a base class for all IR objects implementing common behavior that should be shared by all of them. Currently it only assigns them unique ObjectId s.

class ObjectId(obj: _T)

Bases: Generic[_T]

Represents a runtime-unique id for an IR object that can always be resolved to that object and can be used as a dictionary key/set value.

resolve() _T

Resolve this id to a concrete object instance

class ElaboratableValue(expr: int | str)

Bases: object

A WIP class aiming to represent any generic value that can be resolved to a concrete constant during elaboration.

It should be able to e.g. reference multiple Parameter s by name and perform arbitrary arithmetic operations on them.

value : str
class DataclassRepr(*, load_default: ~typing.Any = <marshmallow.missing>, missing: ~typing.Any = <marshmallow.missing>, dump_default: ~typing.Any = <marshmallow.missing>, default: ~typing.Any = <marshmallow.missing>, data_key: str | None = None, attribute: str | None = None, validate: ~typing.Callable[[~typing.Any], ~typing.Any] | ~typing.Iterable[~typing.Callable[[~typing.Any], ~typing.Any]] | None = None, required: bool = False, allow_none: bool | None = None, load_only: bool = False, dump_only: bool = False, error_messages: dict[str, str] | None = None, metadata: ~typing.Mapping[str, ~typing.Any] | None = None, **additional_metadata)

Bases: Field

Field

alias of ElaboratableValue[ElaboratableValue]

class Identifier(name: str, vendor: str = 'vendor', library: str = 'libdefault')

Bases: ModelBase

An advanced identifier of some IR objects that can benefit from storing more information than just their name. Based on the VLNV convention.

name : str
vendor : str = 'vendor'
library : str = 'libdefault'
combined() str
class FileReference(file: Path, line: int, column: int)

Bases: object

A reference to a particular location in a text file on the filesystem

file : Path
line : int
column : int
class Parameter(*, name: str, default_value: ElaboratableValue | None = None)

Bases: ModelBase

Represents a parameter definition for a HDL module

parent : Module
name : VariableName
default_value : ElaboratableValue | None

If a value for this parameter was not provided during elaboration, this default will be used.


Last update: 2025-05-15