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
- 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
oraxibridge.sv
- content : str¶
The content of the file generated by the backend
- 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 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 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_reference(ref: FileReference)¶
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.
- 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.- 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'
¶
-
MANAGER =
- 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
- 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 betweenModuleInstance
andModule
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
- 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 theInterfaceSignal.type
should be generated to represent it. In that case the value in this dictionary isNone
.
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'
¶
-
IN =
- 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.
- name : VariableName¶
- direction : PortDirection¶
- 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 aStructField
then its parent would be aBitStruct.
Port
orInterfaceSignal
- in case this represents a top-leveltype 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
- 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
orlogic[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.
- 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
- name : VariableName¶
- default_value : ElaboratableValue | None¶
If a value for this parameter was not provided during elaboration, this default will be used.