Language reference

Warning

This reference is a work in progress and is seriously incomplete!

While the wording below states that anything not described in this document isn’t covered by the backwards compatibility guarantee, this should be ignored until the document is complete and this warning is removed.

This reference describes the Python classes that underlie the Amaranth language’s syntax. It assumes familiarity with thelanguage guide.

Backwards compatibility

As part of the Amaranth backwards compatibility guarantee, any behaviors described in this document will not change from a version to another without at least one version including a warning about the impending change. Any nontrivial change to these behaviors must also go through the public review as a part of theAmaranth Request for Comments process.

Conversely, any behavior not documented here is subject to change at any time with or without notice, and any names under theamaranth.hdl module that are not explicitly included in this document, even if they do not begin with an underscore, are internal to the implementation of the language.

Importing syntax

There are two ways to import the Amaranth syntax into a Python file: by importing theprelude or by importing individual names from theamaranth.hdl module. Since the prelude is kept small and rarely extended to avoid breaking downstream code that uses a glob import, there are some names that are only exported from theamaranth.hdl module. The following three snippets are equivalent:

fromamaranthimport*m=Module()
importamaranthasamm=am.Module()
fromamaranth.hdlimportModulem=Module()

The prelude exports exactly the following names:

  • Shape

  • unsigned()

  • signed()

  • Value

  • Const

  • C()

  • Mux()

  • Cat()

  • Array

  • Signal

  • ClockSignal

  • ResetSignal

  • Format

  • Print

  • Assert()

  • Module

  • ClockDomain

  • Elaboratable

  • Fragment

  • Instance

  • Memory

  • DomainRenamer

  • ResetInserter

  • EnableInserter

Source locations

Many functions and methods in Amaranth take thesrc_loc_at=0 keyword argument. These language constructs may inspect the call stack to determine the file and line of its call site, which will be used to annotate generated code when a netlist is generated or to improve diagnostic messages.

Some call sites are not relevant for an Amaranth designer; e.g. when an Amaranth language construct is called from a user-defined utility function, the source location of the call site within this utility function is usually not interesting to the designer. In these cases, one or more levels of function calls can be removed from consideration using thesrc_loc_at argument as follows (usingShape.cast() to demonstrate the concept):

defmy_shape_cast(obj,*,src_loc_at=0):...# additionally process `obj`...returnShape.cast(obj,src_loc_at=1+src_loc_at)

The number1 corresponds to the number of call stack frames that should be skipped.

Shapes

See also the introduction toshapes andcasting from shape-like objects in the language guide.

classamaranth.hdl.Shape(width=1,signed=False)

Bit width and signedness of aValue.

AShape can be obtained by:

  • constructing with explicit bit width and signedness;

  • using thesigned() andunsigned() aliases if the signedness is known upfront;

  • casting from a variety of objects using thecast() method.

Parameters:
  • width (int) – The number of bits in the representation of a value. This includes the sign bit for signedvalues. Cannot be zero if the value is signed.

  • signed (bool) – Whether the value is signed. Signed values use thetwo’s complement representation.

staticcast(obj,*,src_loc_at=0)

Castobj to a shape.

Manyshape-like objects can be cast to a shape:

  • aShape, where the result is itself;

  • anint, where the result isunsigned(obj);

  • arange, where the result has minimal width required to represent all elementsof the range, and is signed if any element of the range is signed;

  • anenum.Enum whose members are allconstant-castableorenum.IntEnum, where the result is wide enough to represent any member ofthe enumeration, and is signed if any member of the enumeration is signed;

  • aShapeCastable object, where the result is obtained by repeatedly callingobj.as_shape().

Raises:
__repr__()

Python code that creates this shape.

Returnsf"signed({self.width})" orf"unsigned({self.width})".

amaranth.hdl.unsigned(width)

ReturnsShape(width,signed=False).

amaranth.hdl.signed(width)

ReturnsShape(width,signed=True).

classamaranth.hdl.ShapeCastable

Interface class for objects that can be cast to aShape.

Shapes of values in the Amaranth language are specified usingshape-like objects. Inheriting a class fromShapeCastable and implementing all ofthe methods described below adds instances of that class to the list of shape-like objectsrecognized by theShape.cast() method. This is a part of the mechanism for seamlesslyextending the Amaranth language in third-party code.

To illustrate their purpose, consider constructing a signal from a shape-castable objectshape_castable:

value_like=Signal(shape_castable,init=initializer)

The code above is equivalent to:

value_like=shape_castable(Signal(shape_castable.as_shape(),init=shape_castable.const(initializer)))

Note that theshape_castable(x) syntax performsshape_castable.__call__(x).

Tip

The source code of theamaranth.lib.data module can be used as a reference forimplementing a fully featured shape-castable object.

as_shape()

Convertself to ashape-like object.

This method is called by the Amaranth language to convertself to a concreteShape. It will usually return aShape object, but it may also returnanother shape-like object to delegate its functionality.

This method must be idempotent: when called twice on the same object, the result must beexactly the same.

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

Return type:

Any other object recognized byShape.cast().

Raises:

Exception – When the conversion cannot be done. This exception must be propagated by callers (except when checking whether an object is shape-castable or not), either directly or as a cause of another exception.

const(obj)

Convert a constant initializerobj to its value representation.

This method is called by the Amaranth language to convertobj, which may be anarbitrary Python object, to a concretevalue-like object.The objectobj will usually be a Python literal that can conveniently representa constant value whose shape is described byself. While not constrained here,the result will usually be an instance of the return type of__call__().

For anyobj, 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:

Avalue-like object that isconstant-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 beTypeError orValueError.

from_bits(raw)

Lift a bit pattern to a higher-level representation.

This method is called by the Amaranth language to liftraw, which is anint,to a higher-level representation, which may be any object accepted byconst().Most importantly, the simulator calls this method when the value of a shape-castableobject is retrieved.

For any valid bit patternraw, the following condition must hold:

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

Whileconst() will usually return an Amaranth value or a custom value-castableobject that is convenient to use while constructing the design, this method will usuallyreturn a Python object that is convenient to use while simulating the design. While notconstrained 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 beValueError.

__call__(obj)

Lift avalue-like object to a higher-level representation.

This method is called by the Amaranth language to liftobj, which may be anyvalue-like object whose shape equalsShape.cast(self),to a higher-level representation, which may be any value-like object with the sameshape. While not constrained here, usually aShapeCastable implementation willbe paired with aValueCastable implementation, and this method will returnan instance of the latter.

Ifobj is not as described above, this interface does not constrain the behaviorof this method. This may be used to implement another call-based protocol at the sametime.

For any compliantobj, the following condition must hold:

Value.cast(self(obj))==Value.cast(obj)

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

Return type:

Avalue-like object.

format(obj,spec)

Format a value.

This method is called by the Amaranth language to implement formatting for customshapes. Whenever"{obj:spec}" is encountered byFormat, andobjhas a custom shape that has aformat() method,obj.shape().format(obj,"spec")is called, and the format specifier is replaced with the result.

The defaultformat() implementation is:

defformat(self,obj,spec):returnFormat(f"{{:{spec}}}",Value.cast(obj))
Return type:

Format

classamaranth.hdl.ShapeLike

Abstract class representing all objects that can be cast to aShape.

issubclass(cls,ShapeLike) returnsTrue for:

isinstance(obj,ShapeLike) returnsTrue for:

This class cannot be instantiated or subclassed. It can only be used for checking types ofobjects.

Values

See also the introduction tovalues andcasting from value-like objects in the language guide.

classamaranth.hdl.Value(*,src_loc_at=0)

Abstract representation of a bit pattern computed in a circuit.

The Amaranth language gives Python code the ability to create a circuit netlist by manipulatingobjects representing the computations within that circuit. TheValue class representsthe bit pattern of a constant, or of a circuit input or output, or within a storage element; orthe result of an arithmetic, logical, or bit container operation.

Operations on this class interpret this bit pattern either as an integer, which can be signedor unsigned depending on the value’sshape(), or as a bit container. In either case,the semantics of operations that implement Python’s syntax, like+ (also known as__add__()), are identical to the corresponding operation on a Pythonint (or ona Python sequence container). The bitwise inversion~ (also known as__invert__())is the sole exception to this rule.

Data that is not conveniently representable by a single integer or a bit container can berepresented by wrapping aValue in aValueCastable subclass that providesdomain-specific operations. It is possible to extend Amaranth in third-party code usingvalue-castable objects, and the Amaranth standard library provides several built-in ones:

  • amaranth.lib.enum classes are a drop-in replacement for the standard Pythonenum classes that can be defined with an Amaranth shape;

  • amaranth.lib.data classes allow defining complex data structures such as structuresand unions.

Operations onValue instances return anotherValue instance. Unless the exacttype and value of the result is explicitly specified below, it should be considered opaque, andmay change without notice between Amaranth releases as long as the semantics remains the same.

Note

In each of the descriptions below, you will see a line similar to:

Return type:Value,unsigned(1),assignable

The first part (Value) indicates that the returned object’s type is a subclassofValue. The second part (unsigned(1)) describes the shape of that value.The third part, if present, indicates that the value is assignable ifself isassignable.

staticcast(obj)

Castobj to an Amaranth value.

Manyvalue-like objects can be cast to a value:

  • aValue instance, where the result is itself;

  • abool orint instance, where the result isConst(obj);

  • anenum.IntEnum instance, or aenum.Enum instance whose members areall integers, where the result is aConst(obj,enum_shape) whereenum_shapeis a shape that can represent every member of the enumeration;

  • aValueCastable instance, where the result is obtained by repeatedly callingobj.as_value().

Raises:
abstractshape()

Shape ofself.

Return type:

shape-like object

as_unsigned()

Reinterpretation as an unsigned value.

Return type:

Value,unsigned(len(self)),assignable

as_signed()

Reinterpretation as a signed value.

Return type:

Value,signed(len(self)),assignable

Raises:

ValueError – Iflen(self)==0.

__bool__()

Forbidden conversion to boolean.

Python uses this operator for its built-in semantics, e.g.if, and requires it toreturn abool. Since this is not possible for Amaranth values, this operatoralways raises an exception.

Raises:

TypeError – Always.

bool()

Conversion to boolean.

Returns the same value asany(), but should be used whereself is semanticallya number.

Return type:

Value,unsigned(1)

__pos__()

Unary position,+self.

Returns:

self

Return type:

Value,self.shape()

__neg__()

Unary negation,-self.

Return type:

Value,signed(len(self)+1)

__add__(other)

Addition,self+other.

Returns:

  • Value,unsigned(max(self.width(),other.width())+1) – If bothself andother are unsigned.

  • Value,signed(max(self.width()+1,other.width())+1) – Ifself is unsigned andother is signed.

  • Value,signed(max(self.width(),other.width()+1)+1) – Ifself is signed andother is unsigned.

  • Value,signed(max(self.width(),other.width())+1) – If bothself andother are unsigned.

__radd__(other)

Addition,other+self (reflected).

Like__add__(), with operands swapped.

__sub__(other)

Subtraction,self-other.

Returns:

  • Value,signed(max(self.width(),other.width())+1) – If bothself andother are unsigned.

  • Value,signed(max(self.width()+1,other.width())+1) – Ifself is unsigned andother is signed.

  • Value,signed(max(self.width(),other.width()+1)+1) – Ifself is signed andother is unsigned.

  • Value,signed(max(self.width(),other.width())+1) – If bothself andother are unsigned.

Return type:

Value

__rsub__(other)

Subtraction,other-self (reflected).

Like__sub__(), with operands swapped.

__mul__(other)

Multiplication,self*other.

Returns:

  • Value,unsigned(len(self)+len(other)) – If bothself andother are unsigned.

  • Value,signed(len(self)+len(other)) – If eitherself orother are signed.

__rmul__(other)

Multiplication,other*self (reflected).

Like__mul__(), with operands swapped.

__floordiv__(other)

Flooring division,self//other.

Ifother is zero, the result of this operation is zero.

Returns:

  • Value,unsigned(len(self)) – If bothself andother are unsigned.

  • Value,signed(len(self)+1) – Ifself is unsigned andother is signed.

  • Value,signed(len(self)) – Ifself is signed andother is unsigned.

  • Value,signed(len(self)+1) – If bothself andother are signed.

__rfloordiv__(other)

Flooring division,other//self (reflected).

Ifself is zero, the result of this operation is zero.

Like__floordiv__(), with operands swapped.

__mod__(other)

Flooring modulo or remainder,self%other.

Ifother is zero, the result of this operation is zero.

Return type:

Value,other.shape()

__rmod__(other)

Flooring modulo or remainder,other%self (reflected).

Like__mod__(), with operands swapped.

__eq__(other)

Equality comparison,self==other.

Return type:

Value,unsigned(1)

__ne__(other)

Inequality comparison,self!=other.

Return type:

Value,unsigned(1)

__lt__(other)

Less than comparison,self<other.

Return type:

Value,unsigned(1)

__le__(other)

Less than or equals comparison,self<=other.

Return type:

Value,unsigned(1)

__gt__(other)

Greater than comparison,self>other.

Return type:

Value,unsigned(1)

__ge__(other)

Greater than or equals comparison,self>=other.

Return type:

Value,unsigned(1)

__abs__()

Absolute value,abs(self).

Return type:

Value,unsigned(len(self))

__invert__()

Bitwise NOT,~self.

The shape of the result is the same as the shape ofself, even for unsigned values.

Warning

In Python,~0 equals-1. In Amaranth,~C(0) equalsC(1).This is the only case where an Amaranth operator deviates from the Python operatorwith the same name.

This deviation is necessary because Python does not allow overriding the logicaland,or, andnot operators. Amaranth uses&,|, and~ instead; if it wasn’t the case that~C(0)==C(1), that would havebeen impossible.

Return type:

Value,self.shape()

__and__(other)

Bitwise AND,self&other.

Returns:

  • Value,unsigned(max(self.width(),other.width())) – If bothself andother are unsigned.

  • Value,signed(max(self.width()+1,other.width())) – Ifself is unsigned andother is signed.

  • Value,signed(max(self.width(),other.width()+1)) – Ifself is signed andother is unsigned.

  • Value,signed(max(self.width(),other.width())) – If bothself andother are unsigned.

__rand__(other)

Bitwise AND,other&self.

Like__and__(), with operands swapped.

all()

Reduction AND; are all bits1?

Return type:

Value,unsigned(1)

__or__(other)

Bitwise OR,self|other.

Returns:

  • Value,unsigned(max(self.width(),other.width())) – If bothself andother are unsigned.

  • Value,signed(max(self.width()+1,other.width())) – Ifself is unsigned andother is signed.

  • Value,signed(max(self.width(),other.width()+1)) – Ifself is signed andother is unsigned.

  • Value,signed(max(self.width(),other.width())) – If bothself andother are unsigned.

__ror__(other)

Bitwise OR,other|self.

Like__or__(), with operands swapped.

any()

Reduction OR; is any bit1?

Performs the same operation asbool(), but should be used whereself issemantically a bit sequence.

Return type:

Value,unsigned(1)

__xor__(other)

Bitwise XOR,self^other.

Returns:

  • Value,unsigned(max(self.width(),other.width())) – If bothself andother are unsigned.

  • Value,signed(max(self.width()+1,other.width())) – Ifself is unsigned andother is signed.

  • Value,signed(max(self.width(),other.width()+1)) – Ifself is signed andother is unsigned.

  • Value,signed(max(self.width(),other.width())) – If bothself andother are unsigned.

__rxor__(other)

Bitwise XOR,other^self.

Like__xor__(), with operands swapped.

xor()

Reduction XOR; are an odd amount of bits1?

Return type:

Value,unsigned(1)

__lshift__(other)

Left shift by variable amount,self<<other.

Returns:

  • Value,unsigned(len(self)+2**len(other)-1) – Ifself is unsigned.

  • Value,signed(len(self)+2**len(other)-1) – Ifself is signed.

Raises:

TypeError – Ifother is signed.

__rlshift__(other)

Left shift by variable amount,other<<self.

Like__lshift__(), with operands swapped.

shift_left(amount)

Left shift by constant amount.

Ifamount<0, performs the same operation asself.shift_right(-amount).

Returns:

  • Value,unsigned(max(len(self)+amount,0)) – Ifself is unsigned.

  • Value,signed(max(len(self)+amount,1)) – Ifself is signed.

rotate_left(amount)

Left rotate by constant amount.

Ifamount<0, performs the same operation asself.rotate_right(-amount).

Return type:

Value,unsigned(len(self)),assignable

__rshift__(other)

Right shift by variable amount,self>>other.

Returns:

  • Value,unsigned(len(self)) – Ifself is unsigned.

  • Value,signed(len(self)) – Ifself is signed.

Raises:

TypeError – Ifother is signed.

__rrshift__(other)

Right shift by variable amount,other>>self.

Like__rshift__(), with operands swapped.

shift_right(amount)

Right shift by constant amount.

Ifamount<0, performs the same operation asself.shift_left(-amount).

Returns:

  • Value,unsigned(max(len(self)-amount,0)) – Ifself is unsigned.

  • Value,signed(max(len(self)-amount,1)) – Ifself is signed.

rotate_right(amount)

Right rotate by constant amount.

Ifamount<0, performs the same operation asself.rotate_left(-amount).

Return type:

Value,unsigned(len(self)),assignable

__len__()

Bit width ofself.

Returns:

self.shape().width

Return type:

int

__getitem__(key)

Bit slicing.

Selects a constant-width, constant-offset part ofself. All three slicing syntaxes(self[i],self[i:j], andself[i:j:k]) as well as negative indices aresupported. Like with other Python containers, out-of-bounds indices are trimmed tothe bounds ofself.

To select a variable-offset part ofself, usebit_select() orword_select() instead.

Returns:

__contains__(other)

Forbidden membership test operator.

Python requires this operator to return abool. Since this is not possiblefor Amaranth values, this operator always raises an exception.

To check membership in a set of constant integer values, usematches() instead.

Raises:

TypeError – Always.

bit_select(offset,width)

Part-select with bit granularity.

Selects a constant width, variable offset part ofself, where parts with successiveoffsets overlap bywidth-1 bits. Bits above the most significant bit ofselfmay be selected; they are equal to zero ifself is unsigned, toself[-1] ifself is signed, and assigning to them does nothing.

Whenoffset is a constant integer andoffset+width<=len(self),this operation is equivalent toself[offset:offset+width].

Parameters:
  • offset (value-like) – Index of the first selected bit.

  • width (int) – Amount of bits to select.

Return type:

Value,unsigned(width),assignable

Raises:
word_select(offset,width)

Part-select with word granularity.

Selects a constant width, variable offset part ofself, where parts with successiveoffsets are adjacent but do not overlap. Bits above the most significant bit ofselfmay be selected; they are equal to zero ifself is unsigned, toself[-1] ifself is signed, and assigning to them does nothing.

Whenoffset is a constant integer andwidth:(offset+1)*width<=len(self),this operation is equivalent toself[offset*width:(offset+1)*width].

Parameters:
  • offset (value-like) – Index of the first selected word.

  • width (int) – Amount of bits to select.

Return type:

Value,unsigned(width),assignable

Raises:
replicate(count)

Replication.

Equivalent toCat(selffor_inrange(count)), but not assignable.

Return type:

Value,unsigned(len(self)*count)

Raises:

TypeError – Ifcount is negative.

matches(*patterns)

Pattern matching.

Matches against a set of patterns, recognizing the same grammar aswithm.Case().The pattern syntax is described in thelanguage guide.

Each of thepatterns may be astr or aconstant-castable object.

Return type:

Value,unsigned(1)

Raises:

SyntaxError – If a pattern has invalid syntax.

eq(value,*,src_loc_at=0)

Assignment.

Once it is placed in a domain, an assignment changes the bit pattern ofself toequalvalue. If the bit width ofvalue is less than that ofself,it is zero-extended (for unsignedvalues) or sign-extended (for signedvalues). If the bit width ofvalue is greater than that ofself,it is truncated.

Return type:

Statement

__hash__=None

Forbidden hashing.

Python objects arehashable if they provide a__hash__ methodthat returns anint and an__eq__ method that returns abool.Amaranth values define__eq__() to return aValue, which precludes themfrom being hashable.

To use aValue as a key in adict, use the following pattern:

value=Signal()assoc={}assoc[id(value)]=value,"a signal"_,info=assoc[id(value)]assertinfo=="a signal"
__format__(format_desc)

Forbidden formatting.

Since normal Python formatting (f-strings andstr.format) must immediately returna string, it is unsuitable for formatting Amaranth values. To format a value at simulationtime, useFormat instead. If you really want to dump the AST at elaboration time,userepr instead (for instance, viaf"{value!r}").

classamaranth.hdl.ValueCastable

Interface class for objects that can be cast to aValue.

Computations in the Amaranth language are described by combiningvalue-like objects. Inheriting a class fromValueCastable and implementingall of the methods described below adds instances of that class to the list ofvalue-like objects recognized by theValue.cast() method. This is a part of the mechanismfor seamlessly extending the Amaranth language in third-party code.

Note

All methods and operators defined by theValue class will implicitly castaValueCastable object to aValue, with the exception of arithmeticoperators, which will prefer calling a reflected arithmetic operation ontheValueCastable argument if it defines one.

For example, ifvalue_castable implements__radd__, thenC(1)+value_castable will performvalue_castable.__radd__(C(1)), and otherwiseit will performC(1).__add__(value_castable.as_value()).

as_value()

Convertself to avalue-like object.

This method is called by the Amaranth language to convertself to a concreteValue. It will usually return aValue object, but it may also returnanother value-like object to delegate its functionality.

This method must be idempotent: when called twice on the same object, the result must beexactly the same.

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

Return type:

Any other object recognized byValue.cast().

Raises:

Exception – When the conversion cannot be done. This exception must be propagated by callers, either directly or as a cause of another exception. It is recommended that, in cases where this method raises an exception, theshape() method also raises an exception.

shape()

Compute the shape ofself.

This method is not called by the Amaranth language itself; whenever it needs to discoverthe shape of a value-castable object, it callsself.as_value().shape(). However,that method must return aShape, andValueCastable subclasses may havea richer representation of their shape provided by an instance of aShapeCastablesubclass. This method may return such a representation.

This method must be idempotent: when called twice on the same object, the result must beexactly the same.

The following condition must hold:

Shape.cast(self.shape())==Value.cast(self).shape()
Return type:

Ashape-like object.

Raises:

Exception – When the conversion cannot be done. This exception must be propagated by callers, either directly or as a cause of another exception. It is recommended that, in cases where this method raises an exception, theas_value() method also raises an exception.

classamaranth.hdl.ValueLike

Abstract class representing all objects that can be cast to aValue.

issubclass(cls,ValueLike) returnsTrue for:

isinstance(obj,ValueLike) returns the same value asissubclass(type(obj),ValueLike).

This class cannot be instantiated or subclassed. It can only be used for checking types ofobjects.

Note

It is possible to define an enumeration with a member that isvalue-like but notconstant-castable,meaning thatissubclass(BadEnum,ValueLike) returnsTrue, butValue.cast(BadEnum.MEMBER) raises an exception.

Theamaranth.lib.enum module prevents such enumerations from being defined whenthe shape is specified explicitly. Usingamaranth.lib.enum and specifying the shapeensures that all of your enumeration members are constant-castable and fit in the providedshape.