Enumerations

The amaranth.lib.enum module is a drop-in replacement for the standard enum module that provides extended Enum, IntEnum, Flag, and IntFlag classes with the ability to specify a shape explicitly.

A shape can be specified for an enumeration with the shape= keyword argument:

from amaranth.lib import enum

class Funct(enum.Enum, shape=4):
    ADD = 0
    SUB = 1
    MUL = 2
>>> Shape.cast(Funct)
unsigned(4)
>>> Value.cast(Funct.ADD)
(const 4'd0)

Any constant-castable expression can be used as the value of a member:

class Op(enum.Enum, shape=1):
    REG = 0
    IMM = 1

class Instr(enum.Enum, shape=5):
    ADD  = Cat(Funct.ADD, Op.REG)
    ADDI = Cat(Funct.ADD, Op.IMM)
    SUB  = Cat(Funct.SUB, Op.REG)
    SUBI = Cat(Funct.SUB, Op.IMM)
    ...
>>> Instr.SUBI
<Instr.SUBI: 17>

The shape= argument is optional. If not specified, classes from this module behave exactly the same as classes from the standard enum module, and likewise, this module re-exports everything exported by the standard enum module.

import amaranth.lib.enum

class NormalEnum(amaranth.lib.enum.Enum):
    SPAM = 0
    HAM  = 1

In this way, this module is a drop-in replacement for the standard enum module, and in an Amaranth project, all import enum statements may be replaced with from amaranth.lib import enum.

Signals with Enum or Flag based shape are automatically wrapped in the EnumView or FlagView value-like wrappers, which ensure type safety. Any value-like can also be explicitly wrapped in a view class by casting it to the enum type:

>>> a = Signal(Funct)
>>> b = Signal(Op)
>>> type(a)
<class 'amaranth.lib.enum.EnumView'>
>>> a == b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: an EnumView can only be compared to value or other EnumView of the same enum type
>>> c = Signal(4)
>>> type(Funct(c))
<class 'amaranth.lib.enum.EnumView'>

Like the standard Python enum.IntEnum and enum.IntFlag classes, the Amaranth IntEnum and IntFlag classes are loosely typed and will not be subject to wrapping in view classes:

class TransparentEnum(enum.IntEnum, shape=unsigned(4)):
    FOO = 0
    BAR = 1
>>> a = Signal(TransparentEnum)
>>> type(a) is Signal
True

It is also possible to define a custom view class for a given enum:

class InstrView(enum.EnumView):
    def has_immediate(self):
        return (self == Instr.ADDI) | (self == Instr.SUBI)

class Instr(enum.Enum, shape=5, view_class=InstrView):
    ADD  = Cat(Funct.ADD, Op.REG)
    ADDI = Cat(Funct.ADD, Op.IMM)
    SUB  = Cat(Funct.SUB, Op.REG)
    SUBI = Cat(Funct.SUB, Op.IMM)
>>> a = Signal(Instr)
>>> type(a)
<class 'InstrView'>
>>> a.has_immediate()
(| (== (sig a) (const 5'd16)) (== (sig a) (const 5'd17)))

Metaclass

class amaranth.lib.enum.EnumMeta

Subclass of the standard enum.EnumMeta that implements the ShapeCastable protocol.

This metaclass provides the as_shape() method, making its instances shape-like, and accepts a shape= keyword argument to specify a shape explicitly. Other than this, it acts the same as the standard enum.EnumMeta class; if the shape= argument is not specified and as_shape() is never called, it places no restrictions on the enumeration class or the values of its members.

When a value-like is cast to an enum type that is an instance of this metaclass, it can be automatically wrapped in a view class. A custom view class can be specified by passing the view_class= keyword argument when creating the enum class.

as_shape()

Cast this enumeration to a shape.

Returns:

Explicitly provided shape. If not provided, returns the result of shape-casting this class as a standard Python enumeration.

Return type:

Shape

Raises:

TypeError – If the enumeration has neither an explicitly provided shape nor any members.

__call__(value, *args, **kwargs)

Cast the value to this enum type.

When given an integer constant, it returns the corresponding enum value, like a standard Python enumeration.

When given a value-like, it is cast to a value, then wrapped in the view_class specified for this enum type (EnumView for Enum, FlagView for Flag, or a custom user-defined class). If the type has no view_class (like IntEnum or IntFlag), a plain Value is returned.

Returns:

  • instance of itself – For integer values, or instances of itself.

  • EnumView or its subclass – For value-castables, as defined by the view_class keyword argument.

  • Value – For value-castables, when a view class is not specified for this enum.

const(obj)

Convert a constant initializer obj to its value representation.

This method is called by the Amaranth language to convert obj, which may be an arbitrary Python object, to a concrete value-like object. The object obj will usually be a Python literal that can conveniently represent a constant value whose shape is described by self. While not constrained here, the result will usually be an instance of the return type of __call__().

For any obj, the following condition must hold:

Shape.cast(self) == Const.cast(self.const(obj)).shape()

This method may also be called by code that is not a part of the Amaranth language.

Return type:

A value-like object that is constant-castable.

Raises:

Exception – When the conversion cannot be done. This exception must be propagated by callers, either directly or as a cause of another exception. While not constrained here, usually the exception class will be TypeError or ValueError.

from_bits(bits)

Lift a bit pattern to a higher-level representation.

This method is called by the Amaranth language to lift raw, which is an int, to a higher-level representation, which may be any object accepted by const(). Most importantly, the simulator calls this method when the value of a shape-castable object is retrieved.

For any valid bit pattern raw, the following condition must hold:

Const.cast(self.const(self.from_bits(raw))).value == raw

While const() will usually return an Amaranth value or a custom value-castable object that is convenient to use while constructing the design, this method will usually return a Python object that is convenient to use while simulating the design. While not constrained here, these objects should have the same type whenever feasible.

This method may also be called by code that is not a part of the Amaranth language.

Return type:

unspecified type

Raises:

Exception – When the bit pattern isn’t valid. This exception must be propagated by callers, either directly or as a cause of another exception. While not constrained here, usually the exception class will be ValueError.

Base classes

class amaranth.lib.enum.Enum

Subclass of the standard enum.Enum that has EnumMeta as its metaclass and EnumView as its view class.

class amaranth.lib.enum.IntEnum

Subclass of the standard enum.IntEnum that has EnumMeta as its metaclass.

class amaranth.lib.enum.Flag

Subclass of the standard enum.Flag that has EnumMeta as its metaclass and FlagView as its view class.

class amaranth.lib.enum.IntFlag

Subclass of the standard enum.IntFlag that has EnumMeta as its metaclass.

View classes

class amaranth.lib.enum.EnumView

The view class used for Enum.

Wraps a Value and only allows type-safe operations. The only operators allowed are equality comparisons (== and !=) with another EnumView of the same enum type.

__init__(enum, target)

Constructs a view with the given enum type and target (a value-like).

shape()

Returns the underlying enum type.

as_value()

Returns the underlying value.

eq(other)

Assign to the underlying value.

Returns:

self.as_value().eq(other)

Return type:

Assign

__eq__(other)

Compares the underlying value for equality.

The other operand has to be either another EnumView with the same enum type, or a plain value of the underlying enum.

Returns:

The result of the equality comparison, as a single-bit value.

Return type:

Value

class amaranth.lib.enum.FlagView

The view class used for Flag.

In addition to the operations allowed by EnumView, it allows bitwise operations among values of the same enum type.

__invert__()

Inverts all flags in this value and returns another FlagView.

Note that this is not equivalent to applying bitwise negation to the underlying value: just like the Python enum.Flag class, only bits corresponding to flags actually defined in the enumeration are included in the result.

Return type:

FlagView

__and__(other)

Performs a bitwise AND and returns another FlagView.

The other operand has to be either another FlagView of the same enum type, or a plain value of the underlying enum type.

Return type:

FlagView

__or__(other)

Performs a bitwise OR and returns another FlagView.

The other operand has to be either another FlagView of the same enum type, or a plain value of the underlying enum type.

Return type:

FlagView

__xor__(other)

Performs a bitwise XOR and returns another FlagView.

The other operand has to be either another FlagView of the same enum type, or a plain value of the underlying enum type.

Return type:

FlagView

__rand__(other)

Performs a bitwise AND and returns another FlagView.

The other operand has to be either another FlagView of the same enum type, or a plain value of the underlying enum type.

Return type:

FlagView

__ror__(other)

Performs a bitwise OR and returns another FlagView.

The other operand has to be either another FlagView of the same enum type, or a plain value of the underlying enum type.

Return type:

FlagView

__rxor__(other)

Performs a bitwise XOR and returns another FlagView.

The other operand has to be either another FlagView of the same enum type, or a plain value of the underlying enum type.

Return type:

FlagView