REDAC Hardware Abstractions

The REDAC analog computer consists of a hierarchical structure of hardware modules.

This structure is represented by a tree-like structure of Entity objects and their sub-classes. Each entity has a unique Path defining its position in this hierarchy. You can iterate over the children of an entity via its Entity.children property. As described in Path, the hierarchy represented is as follows.

  1. Carrier boards implemented by pybrid.redac.carrier.Carrier

  2. Clusters implemented by pybrid.redac.cluster.Cluster

  3. Function blocks implemented by pybrid.redac.blocks.FunctionBlock, see REDAC Blocks and Configurations

  4. Functions (Elements) implemented by pybrid.redac.elements.ComputationElement

class pybrid.redac.entities.Entity(path: Path)

Base class for all entities inside a REDAC.

property children: list[pybrid.base.hybrid.entities.Entity]

Generator iterating through child entities.

property id_

ID of the object, which is the last element of its path. Not necessarily unique.

path: Path

Unique path to this entity.

class pybrid.redac.entities.EntityClass(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Entity class differentiates between carrier boards, different function blocks and so on. Max 5bit = 31.

class pybrid.redac.entities.EntityType(*, class_: EntityClass, type_: Optional[int] = None, version: Optional[Version] = None, variant: Optional[int] = None)

A unique identifier for an entity type.

Each hardware module in a REDAC analog computer contains hardware version information in their EEPROM. When the client library connects to an analog computer, it generally requests the tree of hardware modules present. This is given as a tree-like list of EntityType objects. Since it is also automatically converted to the respective python objects, you typically do not need to handle EntityType objects directly.

One notable exception is registering a python class for the auto-conversion from an EntityType to its respective Entity class as follows.

@EntityType.register(EntityClass.MBLOCK, 17, 3, 1)
class ACustomMBlock(ElementBlock):
    ...
class_: EntityClass

The class of the entity, see EntityClass. Different classes of entities can only be placed at their expected slots and can not be interchanged.

fallback_type()

Return a copy of this EntityType with one more field set to None.

classmethod lookup(type_, decay=False)

Lookup the implementation of an EntityType. Use the decay parameter if you want to allow finding a more generic implementation.

classmethod register(class_: EntityClass, type_=None, version=None, variant=None)

Register a class as an implementation of an EntityType.

type_: Optional[int] = None

The type of the entity, mostly relevant for pybrid.redac.blocks.MBlock. Different types of an entity have significantly different functionality, but may be placed in the same slots.

variant: Optional[int] = None

The variant of an entity. Different variants of an entity have practically identical functionality, but may differ in certain implementation details.

version: Optional[Version] = None

The version on an entity, following the semantic version definition.

exception pybrid.redac.entities.EntityTypeRegistryError

Exception for errors inside the EntityType registry.

class pybrid.redac.entities.Loc(args: [<class 'int'>])

Locator class for localization of one cluster

class pybrid.redac.entities.Path(iterable=(), /)

A tuple uniquely identifying an entity in the REDAC.

The path to an entity is a hierarchical combination of paths to its parent entities. Its structure in the REDAC is (<carrier board>, <cluster>, <block>, <function>). Carrier boards are defined by their MAC address, e.g. “04-E9-E5-14-74-BF”. Clusters are defined by their index sent as a string, e.g. “0”. Function blocks on them are identified by their abbreviation, one of “M0”, “M1”, “U”, “C”, “I”. Functions on blocks are defined by their index as integer, e.g. 7. The blocks’ functions are usually not directly accessed, but instead configured via their block.

Usage:

Combine the identifiers to the required depth

path_to_a_carrier_board = Path("00:00:5e:00:53:af")
path_to_second_cluster_on_it = Path("00:00:5e:00:53:af", "1")
path_to_m0_block_in_cluster0 = Path("00:00:5e:00:53:af", "0", "M0")
path_to_first_func_on_block = Path("00:00:5e:00:53:af", "0", "M0", 0)
SCHEMA = (<class 'str'>, <class 'str'>, <class 'str'>, <class 'int'>)

The schema defining the data types for the path’s subcomponents.

count(value, /)

Return number of occurrences of value.

index(value, start=0, stop=9223372036854775807, /)

Return first index of value.

Raises ValueError if the value is not present.

join(other)

Concatenates another path to this one and returns a copy.

to_block()

Returns the path until the block level.

Raises IndexError if path is not of sufficient depth.

to_carrier()

Returns the path until the carrier board level. This is equal to to_root() for carrier boards.

to_cluster()

Returns the path until the cluster level.

Raises IndexError if path is not of sufficient depth.

to_function()

Returns the path until the function level.

Raises IndexError if path is not of sufficient depth.

to_parent()

Returns the path until the parent entity level.

to_root()

Returns the path until the root entity level.

exception pybrid.redac.entities.UnknownEntityTypeError

Exception thrown when trying to get an unknown EntityType instance.

class pybrid.redac.computer.REDAC(*args, **kwargs)

Representation of the REDAC analog computer and its structure.

property carriers: list[pybrid.redac.carrier.Carrier]

The list of Carrier boards in this REDAC.

entities: list[pybrid.redac.carrier.Carrier]

The entities present in this analog computer.

get_entity(path: Path) Entity

Get an entity by path.

hierarchy = (<class 'pybrid.redac.carrier.Carrier'>, <class 'pybrid.redac.cluster.Cluster'>, <class 'pybrid.redac.blocks.block.FunctionBlock'>, <class 'pybrid.redac.elements.ComputationElement'>)

The hierarchy of this analog computer.

class pybrid.redac.carrier.Carrier(path: ~pybrid.redac.entities.Path, *, adc_channels: list[typing.Optional[int]] = <factory>, clusters: list[pybrid.redac.cluster.Cluster], tblock: ~pybrid.redac.blocks.tblock.TBlock, st0block: ~typing.Optional[~pybrid.redac.blocks.tblock.TBlock] = None, st1block: ~typing.Optional[~pybrid.redac.blocks.tblock.TBlock] = None)

A REDAC carrier board.

This is the smallest independent hardware unit inside a REDAC. It contains several cluster.Cluster objects.

property children

Generator iterating through child entities of type cluster.Cluster.

clusters: list[pybrid.redac.cluster.Cluster]

List of clusters on the carrier board.

property id_

ID of the object, which is the last element of its path. Not necessarily unique.

path: Path

Unique path to this entity.

class pybrid.redac.cluster.Cluster(path: Path, *, m0block: Optional[MBlock] = None, m1block: Optional[MBlock] = None, ublock: UBlock, cblock: CBlock, iblock: IBlock, shblock: object)

A REDAC computation cluster.

The cluster is the smallest unit capable of an analog computation. It always consists of two optional blocks.MBlock objects and one mandatory blocks.UBlock, blocks.CBlock and blocks.IBlock each.

property blocks: tuple[Optional[pybrid.redac.blocks.mblock.MBlock], Optional[pybrid.redac.blocks.mblock.MBlock], pybrid.redac.blocks.ublock.UBlock, pybrid.redac.blocks.cblock.CBlock, pybrid.redac.blocks.iblock.IBlock]

List of blocks.FunctionBlock objects in this cluster. Returns None elements for blocks that are not present.

cblock: CBlock

The blocks.CBlock in this cluster.

property children

Generator iterating through child entities of type blocks.FunctionBlock. Only returns blocks that are actually present (i.e. not None).

iblock: IBlock

The blocks.IBlock in this cluster.

property id_

ID of the object, which is the last element of its path. Not necessarily unique.

m0block: Optional[MBlock] = None

The first blocks.MBlock in this cluster. May be None if the slot is not filled.

m1block: Optional[MBlock] = None

The second blocks.MBlock in this cluster. May be None if the slot is not filled.

path: Path

Unique path to this entity.

route(m_out: int, u_out: int, c_factor: float, m_in: int)

Convenience function to connect a signal from before the blocks.UBlock through a coefficient on the blocks.CBlock and through the blocks.IBlock to an input on one of the blocks.MBlock slots.

Parameters:
  • m_out (int) – Output index from one of the MBlocks, respectively input index of the UBlock.

  • u_out (int) – Output index of the UBlock, respectively index of the coefficient.

  • c_factor (float) – Factor of the coefficient.

  • m_in (int) – Input index of one of the MBlocks, respectively output index of the IBlock.

Returns:

None

shblock: object

The SHBlock in this cluster.

ublock: UBlock

The blocks.UBlock in this cluster.

class pybrid.redac.elements.ComputationElement(*, path: Path, computation: BaseComputation)

A REDAC computation element (a function).

Each computation element implements one of the available analog computations in REDAC Blocks and Configurations.

property children: list[pybrid.base.hybrid.entities.Entity]

Generator iterating through child entities.

computation: BaseComputation

The computation done by this element.

property id_

ID of the object, which is the last element of its path. Not necessarily unique.

path: Path

Unique path to this entity.