1 from abc
import ABCMeta
, abstractmethod
5 from collections
import OrderedDict
6 from collections
.abc
import Iterable
, MutableMapping
, MutableSet
, MutableSequence
14 "Value", "Const", "C", "AnyConst", "AnySeq", "Operator", "Mux", "Part", "Slice", "Cat", "Repl",
15 "Array", "ArrayProxy",
16 "Signal", "ClockSignal", "ResetSignal",
18 "Sample", "Past", "Stable", "Rose", "Fell", "Initial",
19 "Statement", "Assign", "Assert", "Assume", "Cover", "Switch", "Delay", "Tick",
20 "Passive", "ValueKey", "ValueDict", "ValueSet", "SignalKey", "SignalDict",
26 """Deterministic Unique IDentifier"""
29 self
.duid
= DUID
.__next
_uid
33 def _enum_shape(enum_type
):
34 min_value
= min(member
.value
for member
in enum_type
)
35 max_value
= max(member
.value
for member
in enum_type
)
36 if not isinstance(min_value
, int) or not isinstance(max_value
, int):
37 raise TypeError("Only enumerations with integer values can be converted to nMigen values")
38 signed
= min_value
< 0 or max_value
< 0
39 width
= max(bits_for(min_value
, signed
), bits_for(max_value
, signed
))
40 return (width
, signed
)
43 def _enum_to_bits(enum_value
):
44 width
, signed
= _enum_shape(type(enum_value
))
45 return format(enum_value
.value
& ((1 << width
) - 1), "b").rjust(width
, "0")
48 class Value(metaclass
=ABCMeta
):
51 """Ensures that the passed object is an nMigen value. Booleans and integers
52 are automatically wrapped into ``Const``."""
53 if isinstance(obj
, Value
):
55 elif isinstance(obj
, (bool, int)):
57 elif isinstance(obj
, Enum
):
58 return Const(obj
.value
, _enum_shape(type(obj
)))
60 raise TypeError("Object '{!r}' is not an nMigen value".format(obj
))
62 def __init__(self
, *, src_loc_at
=0):
64 self
.src_loc
= tracer
.get_src_loc(1 + src_loc_at
)
67 raise TypeError("Attempted to convert nMigen value to boolean")
70 return Operator("~", [self
])
72 return Operator("-", [self
])
74 def __add__(self
, other
):
75 return Operator("+", [self
, other
])
76 def __radd__(self
, other
):
77 return Operator("+", [other
, self
])
78 def __sub__(self
, other
):
79 return Operator("-", [self
, other
])
80 def __rsub__(self
, other
):
81 return Operator("-", [other
, self
])
82 def __mul__(self
, other
):
83 return Operator("*", [self
, other
])
84 def __rmul__(self
, other
):
85 return Operator("*", [other
, self
])
86 def __mod__(self
, other
):
87 return Operator("%", [self
, other
])
88 def __rmod__(self
, other
):
89 return Operator("%", [other
, self
])
90 def __div__(self
, other
):
91 return Operator("/", [self
, other
])
92 def __rdiv__(self
, other
):
93 return Operator("/", [other
, self
])
94 def __lshift__(self
, other
):
95 return Operator("<<", [self
, other
])
96 def __rlshift__(self
, other
):
97 return Operator("<<", [other
, self
])
98 def __rshift__(self
, other
):
99 return Operator(">>", [self
, other
])
100 def __rrshift__(self
, other
):
101 return Operator(">>", [other
, self
])
102 def __and__(self
, other
):
103 return Operator("&", [self
, other
])
104 def __rand__(self
, other
):
105 return Operator("&", [other
, self
])
106 def __xor__(self
, other
):
107 return Operator("^", [self
, other
])
108 def __rxor__(self
, other
):
109 return Operator("^", [other
, self
])
110 def __or__(self
, other
):
111 return Operator("|", [self
, other
])
112 def __ror__(self
, other
):
113 return Operator("|", [other
, self
])
115 def __eq__(self
, other
):
116 return Operator("==", [self
, other
])
117 def __ne__(self
, other
):
118 return Operator("!=", [self
, other
])
119 def __lt__(self
, other
):
120 return Operator("<", [self
, other
])
121 def __le__(self
, other
):
122 return Operator("<=", [self
, other
])
123 def __gt__(self
, other
):
124 return Operator(">", [self
, other
])
125 def __ge__(self
, other
):
126 return Operator(">=", [self
, other
])
129 return self
.shape()[0]
131 def __getitem__(self
, key
):
133 if isinstance(key
, int):
134 if key
not in range(-n
, n
):
135 raise IndexError("Cannot index {} bits into {}-bit value".format(key
, n
))
138 return Slice(self
, key
, key
+ 1)
139 elif isinstance(key
, slice):
140 start
, stop
, step
= key
.indices(n
)
142 return Cat(self
[i
] for i
in range(start
, stop
, step
))
143 return Slice(self
, start
, stop
)
145 raise TypeError("Cannot index value with {}".format(repr(key
)))
148 """Conversion to boolean.
153 ``1`` if any bits are set, ``0`` otherwise.
155 return Operator("b", [self
])
158 """Check if any bits are ``1``.
163 ``1`` if any bits are set, ``0`` otherwise.
165 return Operator("r|", [self
])
168 """Check if all bits are ``1``.
173 ``1`` if all bits are set, ``0`` otherwise.
175 return Operator("r&", [self
])
178 """Compute pairwise exclusive-or of every bit.
183 ``1`` if an odd number of bits are set, ``0`` if an even number of bits are set.
185 return Operator("r^", [self
])
187 def implies(premise
, conclusion
):
193 ``0`` if ``premise`` is true and ``conclusion`` is not, ``1`` otherwise.
195 return ~premise | conclusion
197 # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
198 @deprecated("instead of `.part`, use `.bit_select`")
199 def part(self
, offset
, width
):
200 return Part(self
, offset
, width
, src_loc_at
=1)
202 def bit_select(self
, offset
, width
):
203 """Part-select with bit granularity.
205 Selects a constant width but variable offset part of a ``Value``, such that successive
206 parts overlap by all but 1 bit.
211 Index of first selected bit.
213 Number of selected bits.
218 Selected part of the ``Value``
220 return Part(self
, offset
, width
, stride
=1, src_loc_at
=1)
222 def word_select(self
, offset
, width
):
223 """Part-select with word granularity.
225 Selects a constant width but variable offset part of a ``Value``, such that successive
226 parts do not overlap.
231 Index of first selected word.
233 Number of selected bits.
238 Selected part of the ``Value``
240 return Part(self
, offset
, width
, stride
=width
, src_loc_at
=1)
242 def matches(self
, *patterns
):
245 Matches against a set of patterns, which may be integers or bit strings, recognizing
246 the same grammar as ``Case()``.
250 patterns : int or str
251 Patterns to match against.
256 ``1`` if any pattern matches the value, ``0`` otherwise.
259 for pattern
in patterns
:
260 if not isinstance(pattern
, (int, str, Enum
)):
261 raise SyntaxError("Match pattern must be an integer, a string, or an enumeration, "
264 if isinstance(pattern
, str) and any(bit
not in "01-" for bit
in pattern
):
265 raise SyntaxError("Match pattern '{}' must consist of 0, 1, and - (don't care) "
268 if isinstance(pattern
, str) and len(pattern
) != len(self
):
269 raise SyntaxError("Match pattern '{}' must have the same width as match value "
271 .format(pattern
, len(self
)))
272 if isinstance(pattern
, int) and bits_for(pattern
) > len(self
):
273 warnings
.warn("Match pattern '{:b}' is wider than match value "
274 "(which has width {}); comparison will never be true"
275 .format(pattern
, len(self
)),
276 SyntaxWarning, stacklevel
=3)
278 if isinstance(pattern
, int):
279 matches
.append(self
== pattern
)
280 elif isinstance(pattern
, (str, Enum
)):
281 if isinstance(pattern
, Enum
):
282 pattern
= _enum_to_bits(pattern
)
283 mask
= int(pattern
.replace("0", "1").replace("-", "0"), 2)
284 pattern
= int(pattern
.replace("-", "0"), 2)
285 matches
.append((self
& mask
) == pattern
)
290 elif len(matches
) == 1:
293 return Cat(*matches
).any()
301 Value to be assigned.
306 Assignment statement that can be used in combinatorial or synchronous context.
308 return Assign(self
, value
, src_loc_at
=1)
312 """Bit length and signedness of a value.
317 Number of bits required to store `v` or available in `v`, followed by
318 whether `v` has a sign bit (included in the bit count).
322 >>> Value.shape(Signal(8))
324 >>> Value.shape(C(0xaa))
329 def _lhs_signals(self
):
330 raise TypeError("Value {!r} cannot be used in assignments".format(self
))
333 def _rhs_signals(self
):
337 raise TypeError("Value {!r} cannot be evaluated as constant".format(self
))
344 """A constant, literal integer value.
349 shape : int or tuple or None
350 Either an integer ``width`` or a tuple ``(width, signed)`` specifying the number of bits
351 in this constant and whether it is signed (can represent negative values).
352 ``shape`` defaults to the minimum possible width and signedness of ``value``.
362 def normalize(value
, shape
):
363 width
, signed
= shape
364 mask
= (1 << width
) - 1
366 if signed
and value
>> (width
- 1):
370 def __init__(self
, value
, shape
=None):
371 # We deliberately do not call Value.__init__ here.
372 self
.value
= int(value
)
374 shape
= bits_for(self
.value
), self
.value
< 0
375 if isinstance(shape
, int):
376 shape
= shape
, self
.value
< 0
377 self
.width
, self
.signed
= shape
378 if not isinstance(self
.width
, int) or self
.width
< 0:
379 raise TypeError("Width must be a non-negative integer, not '{!r}'"
381 self
.value
= self
.normalize(self
.value
, shape
)
383 # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
385 @deprecated("instead of `const.nbits`, use `const.width`")
390 return self
.width
, self
.signed
392 def _rhs_signals(self
):
399 return "(const {}'{}d{})".format(self
.width
, "s" if self
.signed
else "", self
.value
)
402 C
= Const
# shorthand
405 class AnyValue(Value
, DUID
):
406 def __init__(self
, shape
, *, src_loc_at
=0):
407 super().__init
__(src_loc_at
=src_loc_at
)
408 if isinstance(shape
, int):
410 self
.width
, self
.signed
= shape
411 if not isinstance(self
.width
, int) or self
.width
< 0:
412 raise TypeError("Width must be a non-negative integer, not '{!r}'"
416 return self
.width
, self
.signed
418 def _rhs_signals(self
):
423 class AnyConst(AnyValue
):
425 return "(anyconst {}'{})".format(self
.nbits
, "s" if self
.signed
else "")
429 class AnySeq(AnyValue
):
431 return "(anyseq {}'{})".format(self
.nbits
, "s" if self
.signed
else "")
435 class Operator(Value
):
436 def __init__(self
, op
, operands
, *, src_loc_at
=0):
437 super().__init
__(src_loc_at
=1 + src_loc_at
)
439 self
.operands
= [Value
.wrap(o
) for o
in operands
]
442 def _bitwise_binary_shape(a_shape
, b_shape
):
443 a_bits
, a_sign
= a_shape
444 b_bits
, b_sign
= b_shape
445 if not a_sign
and not b_sign
:
446 # both operands unsigned
447 return max(a_bits
, b_bits
), False
448 elif a_sign
and b_sign
:
449 # both operands signed
450 return max(a_bits
, b_bits
), True
451 elif not a_sign
and b_sign
:
452 # first operand unsigned (add sign bit), second operand signed
453 return max(a_bits
+ 1, b_bits
), True
455 # first signed, second operand unsigned (add sign bit)
456 return max(a_bits
, b_bits
+ 1), True
459 op_shapes
= list(map(lambda x
: x
.shape(), self
.operands
))
460 if len(op_shapes
) == 1:
461 (a_width
, a_signed
), = op_shapes
462 if self
.op
in ("+", "~"):
463 return a_width
, a_signed
466 return a_width
+ 1, True
468 return a_width
, a_signed
469 if self
.op
in ("b", "r|", "r&", "r^"):
471 elif len(op_shapes
) == 2:
472 (a_width
, a_signed
), (b_width
, b_signed
) = op_shapes
473 if self
.op
== "+" or self
.op
== "-":
474 width
, signed
= self
._bitwise
_binary
_shape
(*op_shapes
)
475 return width
+ 1, signed
477 return a_width
+ b_width
, a_signed
or b_signed
479 return a_width
, a_signed
480 if self
.op
in ("<", "<=", "==", "!=", ">", ">="):
482 if self
.op
in ("&", "^", "|"):
483 return self
._bitwise
_binary
_shape
(*op_shapes
)
486 extra
= 2 ** (b_width
- 1) - 1
488 extra
= 2 ** (b_width
) - 1
489 return a_width
+ extra
, a_signed
492 extra
= 2 ** (b_width
- 1)
495 return a_width
+ extra
, a_signed
496 elif len(op_shapes
) == 3:
498 s_shape
, a_shape
, b_shape
= op_shapes
499 return self
._bitwise
_binary
_shape
(a_shape
, b_shape
)
500 raise NotImplementedError("Operator {}/{} not implemented"
501 .format(self
.op
, len(op_shapes
))) # :nocov:
503 def _rhs_signals(self
):
504 return union(op
._rhs
_signals
() for op
in self
.operands
)
507 return "({} {})".format(self
.op
, " ".join(map(repr, self
.operands
)))
510 def Mux(sel
, val1
, val0
):
511 """Choose between two values.
524 Output ``Value``. If ``sel`` is asserted, the Mux returns ``val1``, else ``val0``.
526 return Operator("m", [sel
, val1
, val0
])
531 def __init__(self
, value
, start
, end
, *, src_loc_at
=0):
532 if not isinstance(start
, int):
533 raise TypeError("Slice start must be an integer, not '{!r}'".format(start
))
534 if not isinstance(end
, int):
535 raise TypeError("Slice end must be an integer, not '{!r}'".format(end
))
538 if start
not in range(-(n
+1), n
+1):
539 raise IndexError("Cannot start slice {} bits into {}-bit value".format(start
, n
))
542 if end
not in range(-(n
+1), n
+1):
543 raise IndexError("Cannot end slice {} bits into {}-bit value".format(end
, n
))
547 raise IndexError("Slice start {} must be less than slice end {}".format(start
, end
))
549 super().__init
__(src_loc_at
=src_loc_at
)
550 self
.value
= Value
.wrap(value
)
555 return self
.end
- self
.start
, False
557 def _lhs_signals(self
):
558 return self
.value
._lhs
_signals
()
560 def _rhs_signals(self
):
561 return self
.value
._rhs
_signals
()
564 return "(slice {} {}:{})".format(repr(self
.value
), self
.start
, self
.end
)
569 def __init__(self
, value
, offset
, width
, stride
=1, *, src_loc_at
=0):
570 if not isinstance(width
, int) or width
< 0:
571 raise TypeError("Part width must be a non-negative integer, not '{!r}'".format(width
))
572 if not isinstance(stride
, int) or stride
<= 0:
573 raise TypeError("Part stride must be a positive integer, not '{!r}'".format(stride
))
575 super().__init
__(src_loc_at
=src_loc_at
)
577 self
.offset
= Value
.wrap(offset
)
582 return self
.width
, False
584 def _lhs_signals(self
):
585 return self
.value
._lhs
_signals
()
587 def _rhs_signals(self
):
588 return self
.value
._rhs
_signals
() | self
.offset
._rhs
_signals
()
591 return "(part {} {} {} {})".format(repr(self
.value
), repr(self
.offset
),
592 self
.width
, self
.stride
)
597 """Concatenate values.
599 Form a compound ``Value`` from several smaller ones by concatenation.
600 The first argument occupies the lower bits of the result.
601 The return value can be used on either side of an assignment, that
602 is, the concatenated value can be used as an argument on the RHS or
603 as a target on the LHS. If it is used on the LHS, it must solely
604 consist of ``Signal`` s, slices of ``Signal`` s, and other concatenations
605 meeting these properties. The bit length of the return value is the sum of
606 the bit lengths of the arguments::
608 len(Cat(args)) == sum(len(arg) for arg in args)
612 *args : Values or iterables of Values, inout
613 ``Value`` s to be concatenated.
618 Resulting ``Value`` obtained by concatentation.
620 def __init__(self
, *args
, src_loc_at
=0):
621 super().__init
__(src_loc_at
=src_loc_at
)
622 self
.parts
= [Value
.wrap(v
) for v
in flatten(args
)]
625 return sum(len(part
) for part
in self
.parts
), False
627 def _lhs_signals(self
):
628 return union((part
._lhs
_signals
() for part
in self
.parts
), start
=ValueSet())
630 def _rhs_signals(self
):
631 return union((part
._rhs
_signals
() for part
in self
.parts
), start
=ValueSet())
635 for part
in reversed(self
.parts
):
637 value |
= part
._as
_const
()
641 return "(cat {})".format(" ".join(map(repr, self
.parts
)))
648 An input value is replicated (repeated) several times
649 to be used on the RHS of assignments::
651 len(Repl(s, n)) == len(s) * n
656 Input value to be replicated.
658 Number of replications.
665 def __init__(self
, value
, count
, *, src_loc_at
=0):
666 if not isinstance(count
, int) or count
< 0:
667 raise TypeError("Replication count must be a non-negative integer, not '{!r}'"
670 super().__init
__(src_loc_at
=src_loc_at
)
671 self
.value
= Value
.wrap(value
)
675 return len(self
.value
) * self
.count
, False
677 def _rhs_signals(self
):
678 return self
.value
._rhs
_signals
()
681 return "(repl {!r} {})".format(self
.value
, self
.count
)
685 class Signal(Value
, DUID
):
686 """A varying integer value.
690 shape : int or tuple or None
691 Either an integer ``width`` or a tuple ``(width, signed)`` specifying the number of bits
692 in this ``Signal`` and whether it is signed (can represent negative values).
693 ``shape`` defaults to 1-bit and non-signed.
695 Name hint for this signal. If ``None`` (default) the name is inferred from the variable
696 name this ``Signal`` is assigned to. Name collisions are automatically resolved by
697 prepending names of objects that contain this ``Signal`` and by appending integer
700 Reset (synchronous) or default (combinatorial) value.
701 When this ``Signal`` is assigned to in synchronous context and the corresponding clock
702 domain is reset, the ``Signal`` assumes the given value. When this ``Signal`` is unassigned
703 in combinatorial context (due to conditional assignments not being taken), the ``Signal``
704 assumes its ``reset`` value. Defaults to 0.
706 If ``True``, do not generate reset logic for this ``Signal`` in synchronous statements.
707 The ``reset`` value is only used as a combinatorial default or as the initial value.
708 Defaults to ``False``.
711 If ``shape`` is ``None``, the signal bit width and signedness are
712 determined by the integer range given by ``min`` (inclusive,
713 defaults to 0) and ``max`` (exclusive, defaults to 2).
715 Dictionary of synthesis attributes.
716 decoder : function or Enum
717 A function converting integer signal values to human-readable strings (e.g. FSM state
718 names). If an ``Enum`` subclass is passed, it is concisely decoded using format string
719 ``"{0.name:}/{0.value:}"``, or a number if the signal value is not a member of
732 def __init__(self
, shape
=None, name
=None, *, reset
=0, reset_less
=False, min=None, max=None,
733 attrs
=None, decoder
=None, src_loc_at
=0):
734 super().__init
__(src_loc_at
=src_loc_at
)
736 # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
737 if min is not None or max is not None:
738 warnings
.warn("instead of `Signal(min={min}, max={max})`, "
739 "use `Signal.range({min}, {max})`"
740 .format(min=min or 0, max=max or 2),
741 DeprecationWarning, stacklevel
=2 + src_loc_at
)
743 if name
is not None and not isinstance(name
, str):
744 raise TypeError("Name must be a string, not '{!r}'".format(name
))
745 self
.name
= name
or tracer
.get_var_name(depth
=2 + src_loc_at
, default
="$signal")
752 max -= 1 # make both bounds inclusive
754 raise ValueError("Lower bound {} should be less or equal to higher bound {}"
755 .format(min, max + 1))
756 self
.signed
= min < 0 or max < 0
760 self
.width
= builtins
.max(bits_for(min, self
.signed
),
761 bits_for(max, self
.signed
))
764 if not (min is None and max is None):
765 raise ValueError("Only one of bits/signedness or bounds may be specified")
766 if isinstance(shape
, int):
767 self
.width
, self
.signed
= shape
, False
769 self
.width
, self
.signed
= shape
771 if not isinstance(self
.width
, int) or self
.width
< 0:
772 raise TypeError("Width must be a non-negative integer, not '{!r}'".format(self
.width
))
774 reset_width
= bits_for(reset
, self
.signed
)
775 if reset
!= 0 and reset_width
> self
.width
:
776 warnings
.warn("Reset value {!r} requires {} bits to represent, but the signal "
778 .format(reset
, reset_width
, self
.width
),
779 SyntaxWarning, stacklevel
=2 + src_loc_at
)
781 self
.reset
= int(reset
)
782 self
.reset_less
= bool(reset_less
)
784 self
.attrs
= OrderedDict(() if attrs
is None else attrs
)
785 if isinstance(decoder
, type) and issubclass(decoder
, Enum
):
786 def enum_decoder(value
):
788 return "{0.name:}/{0.value:}".format(decoder(value
))
791 self
.decoder
= enum_decoder
793 self
.decoder
= decoder
796 def range(cls
, *args
, src_loc_at
=0, **kwargs
):
797 """Create Signal that can represent a given range.
799 The parameters to ``Signal.range`` are the same as for the built-in ``range`` function.
800 That is, for any given ``range(*args)``, ``Signal.range(*args)`` can represent any
801 ``x for x in range(*args)``.
803 value_range
= range(*args
)
804 if len(value_range
) > 0:
805 signed
= value_range
.start
< 0 or (value_range
.stop
- value_range
.step
) < 0
807 signed
= value_range
.start
< 0
808 width
= max(bits_for(value_range
.start
, signed
),
809 bits_for(value_range
.stop
- value_range
.step
, signed
))
810 return cls((width
, signed
), src_loc_at
=1 + src_loc_at
, **kwargs
)
813 def enum(cls
, enum_type
, *, src_loc_at
=0, **kwargs
):
814 """Create Signal that can represent a given enumeration.
818 enum : type (inheriting from :class:`enum.Enum`)
819 Enumeration to base this Signal on.
821 if not issubclass(enum_type
, Enum
):
822 raise TypeError("Type {!r} is not an enumeration")
823 return cls(_enum_shape(enum_type
), src_loc_at
=1 + src_loc_at
, decoder
=enum_type
, **kwargs
)
826 def like(cls
, other
, *, name
=None, name_suffix
=None, src_loc_at
=0, **kwargs
):
827 """Create Signal based on another.
832 Object to base this Signal on.
836 elif name_suffix
is not None:
837 new_name
= other
.name
+ str(name_suffix
)
839 new_name
= tracer
.get_var_name(depth
=2 + src_loc_at
, default
="$like")
840 kw
= dict(shape
=cls
.wrap(other
).shape(), name
=new_name
)
841 if isinstance(other
, cls
):
842 kw
.update(reset
=other
.reset
, reset_less
=other
.reset_less
,
843 attrs
=other
.attrs
, decoder
=other
.decoder
)
845 return cls(**kw
, src_loc_at
=1 + src_loc_at
)
847 # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
849 @deprecated("instead of `signal.nbits`, use `signal.width`")
854 @deprecated("instead of `signal.nbits = x`, use `signal.width = x`")
855 def nbits(self
, value
):
859 return self
.width
, self
.signed
861 def _lhs_signals(self
):
862 return ValueSet((self
,))
864 def _rhs_signals(self
):
865 return ValueSet((self
,))
868 return "(sig {})".format(self
.name
)
872 class ClockSignal(Value
):
873 """Clock signal for a clock domain.
875 Any ``ClockSignal`` is equivalent to ``cd.clk`` for a clock domain with the corresponding name.
876 All of these signals ultimately refer to the same signal, but they can be manipulated
877 independently of the clock domain, even before the clock domain is created.
882 Clock domain to obtain a clock signal for. Defaults to ``"sync"``.
884 def __init__(self
, domain
="sync", *, src_loc_at
=0):
885 super().__init
__(src_loc_at
=src_loc_at
)
886 if not isinstance(domain
, str):
887 raise TypeError("Clock domain name must be a string, not '{!r}'".format(domain
))
889 raise ValueError("Domain '{}' does not have a clock".format(domain
))
895 def _lhs_signals(self
):
896 return ValueSet((self
,))
898 def _rhs_signals(self
):
899 raise NotImplementedError("ClockSignal must be lowered to a concrete signal") # :nocov:
902 return "(clk {})".format(self
.domain
)
906 class ResetSignal(Value
):
907 """Reset signal for a clock domain.
909 Any ``ResetSignal`` is equivalent to ``cd.rst`` for a clock domain with the corresponding name.
910 All of these signals ultimately refer to the same signal, but they can be manipulated
911 independently of the clock domain, even before the clock domain is created.
916 Clock domain to obtain a reset signal for. Defaults to ``"sync"``.
917 allow_reset_less : bool
918 If the clock domain is reset-less, act as a constant ``0`` instead of reporting an error.
920 def __init__(self
, domain
="sync", allow_reset_less
=False, *, src_loc_at
=0):
921 super().__init
__(src_loc_at
=src_loc_at
)
922 if not isinstance(domain
, str):
923 raise TypeError("Clock domain name must be a string, not '{!r}'".format(domain
))
925 raise ValueError("Domain '{}' does not have a reset".format(domain
))
927 self
.allow_reset_less
= allow_reset_less
932 def _lhs_signals(self
):
933 return ValueSet((self
,))
935 def _rhs_signals(self
):
936 raise NotImplementedError("ResetSignal must be lowered to a concrete signal") # :nocov:
939 return "(rst {})".format(self
.domain
)
942 class Array(MutableSequence
):
943 """Addressable multiplexer.
945 An array is similar to a ``list`` that can also be indexed by ``Value``s; indexing by an integer or a slice works the same as for Python lists, but indexing by a ``Value`` results
948 The array proxy can be used as an ordinary ``Value``, i.e. participate in calculations and
949 assignments, provided that all elements of the array are values. The array proxy also supports
950 attribute access and further indexing, each returning another array proxy; this means that
951 the results of indexing into arrays, arrays of records, and arrays of arrays can all
952 be used as first-class values.
954 It is an error to change an array or any of its elements after an array proxy was created.
955 Changing the array directly will raise an exception. However, it is not possible to detect
956 the elements being modified; if an element's attribute or element is modified after the proxy
957 for it has been created, the proxy will refer to stale data.
964 gpios = Array(Signal() for _ in range(10))
966 m.d.sync += gpios[bus.addr].eq(bus.w_data)
968 m.d.sync += bus.r_data.eq(gpios[bus.addr])
970 Multidimensional array::
972 mult = Array(Array(x * y for y in range(10)) for x in range(10))
976 m.d.comb += r.eq(mult[a][b])
984 buses = Array(Record(layout) for busno in range(4))
985 master = Record(layout)
987 buses[sel].r_en.eq(master.r_en),
988 master.r_data.eq(buses[sel].r_data),
991 def __init__(self
, iterable
=()):
992 self
._inner
= list(iterable
)
993 self
._proxy
_at
= None
996 def __getitem__(self
, index
):
997 if isinstance(index
, Value
):
999 self
._proxy
_at
= tracer
.get_src_loc()
1000 self
._mutable
= False
1001 return ArrayProxy(self
, index
)
1003 return self
._inner
[index
]
1006 return len(self
._inner
)
1008 def _check_mutability(self
):
1009 if not self
._mutable
:
1010 raise ValueError("Array can no longer be mutated after it was indexed with a value "
1011 "at {}:{}".format(*self
._proxy
_at
))
1013 def __setitem__(self
, index
, value
):
1014 self
._check
_mutability
()
1015 self
._inner
[index
] = value
1017 def __delitem__(self
, index
):
1018 self
._check
_mutability
()
1019 del self
._inner
[index
]
1021 def insert(self
, index
, value
):
1022 self
._check
_mutability
()
1023 self
._inner
.insert(index
, value
)
1026 return "(array{} [{}])".format(" mutable" if self
._mutable
else "",
1027 ", ".join(map(repr, self
._inner
)))
1031 class ArrayProxy(Value
):
1032 def __init__(self
, elems
, index
, *, src_loc_at
=0):
1033 super().__init
__(src_loc_at
=1 + src_loc_at
)
1035 self
.index
= Value
.wrap(index
)
1037 def __getattr__(self
, attr
):
1038 return ArrayProxy([getattr(elem
, attr
) for elem
in self
.elems
], self
.index
)
1040 def __getitem__(self
, index
):
1041 return ArrayProxy([ elem
[index
] for elem
in self
.elems
], self
.index
)
1043 def _iter_as_values(self
):
1044 return (Value
.wrap(elem
) for elem
in self
.elems
)
1047 width
, signed
= 0, False
1048 for elem_width
, elem_signed
in (elem
.shape() for elem
in self
._iter
_as
_values
()):
1049 width
= max(width
, elem_width
+ elem_signed
)
1050 signed
= max(signed
, elem_signed
)
1051 return width
, signed
1053 def _lhs_signals(self
):
1054 signals
= union((elem
._lhs
_signals
() for elem
in self
._iter
_as
_values
()), start
=ValueSet())
1057 def _rhs_signals(self
):
1058 signals
= union((elem
._rhs
_signals
() for elem
in self
._iter
_as
_values
()), start
=ValueSet())
1059 return self
.index
._rhs
_signals
() | signals
1062 return "(proxy (array [{}]) {!r})".format(", ".join(map(repr, self
.elems
)), self
.index
)
1065 class UserValue(Value
):
1066 """Value with custom lowering.
1068 A ``UserValue`` is a value whose precise representation does not have to be immediately known,
1069 which is useful in certain metaprogramming scenarios. Instead of providing fixed semantics
1070 upfront, it is kept abstract for as long as possible, only being lowered to a concrete nMigen
1071 value when required.
1073 Note that the ``lower`` method will only be called once; this is necessary to ensure that
1074 nMigen's view of representation of all values stays internally consistent. If the class
1075 deriving from ``UserValue`` is mutable, then it must ensure that after ``lower`` is called,
1076 it is not mutated in a way that changes its representation.
1078 The following is an incomplete list of actions that, when applied to an ``UserValue`` directly
1079 or indirectly, will cause it to be lowered, provided as an illustrative reference:
1080 * Querying the shape using ``.shape()`` or ``len()``;
1081 * Creating a similarly shaped signal using ``Signal.like``;
1082 * Indexing or iterating through individual bits;
1083 * Adding an assignment to the value to a ``Module`` using ``m.d.<domain> +=``.
1085 def __init__(self
, *, src_loc_at
=0):
1086 super().__init
__(src_loc_at
=1 + src_loc_at
)
1087 self
.__lowered
= None
1091 """Conversion to a concrete representation."""
1094 def _lazy_lower(self
):
1095 if self
.__lowered
is None:
1096 self
.__lowered
= Value
.wrap(self
.lower())
1097 return self
.__lowered
1100 return self
._lazy
_lower
().shape()
1102 def _lhs_signals(self
):
1103 return self
._lazy
_lower
()._lhs
_signals
()
1105 def _rhs_signals(self
):
1106 return self
._lazy
_lower
()._rhs
_signals
()
1110 class Sample(Value
):
1111 """Value from the past.
1113 A ``Sample`` of an expression is equal to the value of the expression ``clocks`` clock edges
1114 of the ``domain`` clock back. If that moment is before the beginning of time, it is equal
1115 to the value of the expression calculated as if each signal had its reset value.
1117 def __init__(self
, expr
, clocks
, domain
, *, src_loc_at
=0):
1118 super().__init
__(src_loc_at
=1 + src_loc_at
)
1119 self
.value
= Value
.wrap(expr
)
1120 self
.clocks
= int(clocks
)
1121 self
.domain
= domain
1122 if not isinstance(self
.value
, (Const
, Signal
, ClockSignal
, ResetSignal
, Initial
)):
1123 raise TypeError("Sampled value must be a signal or a constant, not {!r}"
1124 .format(self
.value
))
1126 raise ValueError("Cannot sample a value {} cycles in the future"
1127 .format(-self
.clocks
))
1128 if not (self
.domain
is None or isinstance(self
.domain
, str)):
1129 raise TypeError("Domain name must be a string or None, not {!r}"
1130 .format(self
.domain
))
1133 return self
.value
.shape()
1135 def _rhs_signals(self
):
1136 return ValueSet((self
,))
1139 return "(sample {!r} @ {}[{}])".format(
1140 self
.value
, "<default>" if self
.domain
is None else self
.domain
, self
.clocks
)
1143 def Past(expr
, clocks
=1, domain
=None):
1144 return Sample(expr
, clocks
, domain
)
1147 def Stable(expr
, clocks
=0, domain
=None):
1148 return Sample(expr
, clocks
+ 1, domain
) == Sample(expr
, clocks
, domain
)
1151 def Rose(expr
, clocks
=0, domain
=None):
1152 return ~
Sample(expr
, clocks
+ 1, domain
) & Sample(expr
, clocks
, domain
)
1155 def Fell(expr
, clocks
=0, domain
=None):
1156 return Sample(expr
, clocks
+ 1, domain
) & ~
Sample(expr
, clocks
, domain
)
1160 class Initial(Value
):
1161 """Start indicator, for model checking.
1163 An ``Initial`` signal is ``1`` at the first cycle of model checking, and ``0`` at any other.
1165 def __init__(self
, *, src_loc_at
=0):
1166 super().__init
__(src_loc_at
=1 + src_loc_at
)
1171 def _rhs_signals(self
):
1172 return ValueSet((self
,))
1178 class _StatementList(list):
1180 return "({})".format(" ".join(map(repr, self
)))
1184 def __init__(self
, *, src_loc_at
=0):
1185 self
.src_loc
= tracer
.get_src_loc(1 + src_loc_at
)
1189 if isinstance(obj
, Iterable
):
1190 return _StatementList(sum((Statement
.wrap(e
) for e
in obj
), []))
1192 if isinstance(obj
, Statement
):
1193 return _StatementList([obj
])
1195 raise TypeError("Object '{!r}' is not an nMigen statement".format(obj
))
1199 class Assign(Statement
):
1200 def __init__(self
, lhs
, rhs
, *, src_loc_at
=0):
1201 super().__init
__(src_loc_at
=src_loc_at
)
1202 self
.lhs
= Value
.wrap(lhs
)
1203 self
.rhs
= Value
.wrap(rhs
)
1205 def _lhs_signals(self
):
1206 return self
.lhs
._lhs
_signals
()
1208 def _rhs_signals(self
):
1209 return self
.lhs
._rhs
_signals
() | self
.rhs
._rhs
_signals
()
1212 return "(eq {!r} {!r})".format(self
.lhs
, self
.rhs
)
1215 class Property(Statement
):
1216 def __init__(self
, test
, *, _check
=None, _en
=None, src_loc_at
=0):
1217 super().__init
__(src_loc_at
=src_loc_at
)
1218 self
.test
= Value
.wrap(test
)
1219 self
._check
= _check
1221 if self
._check
is None:
1222 self
._check
= Signal(reset_less
=True, name
="${}$check".format(self
._kind
))
1223 self
._check
.src_loc
= self
.src_loc
1225 self
._en
= Signal(reset_less
=True, name
="${}$en".format(self
._kind
))
1226 self
._en
.src_loc
= self
.src_loc
1228 def _lhs_signals(self
):
1229 return ValueSet((self
._en
, self
._check
))
1231 def _rhs_signals(self
):
1232 return self
.test
._rhs
_signals
()
1235 return "({} {!r})".format(self
._kind
, self
.test
)
1239 class Assert(Property
):
1244 class Assume(Property
):
1249 class Cover(Property
):
1254 class Switch(Statement
):
1255 def __init__(self
, test
, cases
, *, src_loc
=None, src_loc_at
=0, case_src_locs
={}):
1257 super().__init
__(src_loc_at
=src_loc_at
)
1259 # Switch is a bit special in terms of location tracking because it is usually created
1260 # long after the control has left the statement that directly caused its creation.
1261 self
.src_loc
= src_loc
1262 # Switch is also a bit special in that its parts also have location information. It can't
1263 # be automatically traced, so whatever constructs a Switch may optionally provide it.
1264 self
.case_src_locs
= {}
1266 self
.test
= Value
.wrap(test
)
1267 self
.cases
= OrderedDict()
1268 for orig_keys
, stmts
in cases
.items():
1269 # Map: None -> (); key -> (key,); (key...) -> (key...)
1273 if not isinstance(keys
, tuple):
1275 # Map: 2 -> "0010"; "0010" -> "0010"
1278 if isinstance(key
, (bool, int)):
1279 key
= "{:0{}b}".format(key
, len(self
.test
))
1280 elif isinstance(key
, str):
1282 elif isinstance(key
, Enum
):
1283 key
= _enum_to_bits(key
)
1285 raise TypeError("Object '{!r}' cannot be used as a switch key"
1287 assert len(key
) == len(self
.test
)
1288 new_keys
= (*new_keys
, key
)
1289 if not isinstance(stmts
, Iterable
):
1291 self
.cases
[new_keys
] = Statement
.wrap(stmts
)
1292 if orig_keys
in case_src_locs
:
1293 self
.case_src_locs
[new_keys
] = case_src_locs
[orig_keys
]
1295 def _lhs_signals(self
):
1296 signals
= union((s
._lhs
_signals
() for ss
in self
.cases
.values() for s
in ss
),
1300 def _rhs_signals(self
):
1301 signals
= union((s
._rhs
_signals
() for ss
in self
.cases
.values() for s
in ss
),
1303 return self
.test
._rhs
_signals
() | signals
1306 def case_repr(keys
, stmts
):
1307 stmts_repr
= " ".join(map(repr, stmts
))
1309 return "(default {})".format(stmts_repr
)
1310 elif len(keys
) == 1:
1311 return "(case {} {})".format(keys
[0], stmts_repr
)
1313 return "(case ({}) {})".format(" ".join(keys
), stmts_repr
)
1314 case_reprs
= [case_repr(keys
, stmts
) for keys
, stmts
in self
.cases
.items()]
1315 return "(switch {!r} {})".format(self
.test
, " ".join(case_reprs
))
1319 class Delay(Statement
):
1320 def __init__(self
, interval
=None, *, src_loc_at
=0):
1321 super().__init
__(src_loc_at
=src_loc_at
)
1322 self
.interval
= None if interval
is None else float(interval
)
1324 def _rhs_signals(self
):
1328 if self
.interval
is None:
1331 return "(delay {:.3}us)".format(self
.interval
* 1e6
)
1335 class Tick(Statement
):
1336 def __init__(self
, domain
="sync", *, src_loc_at
=0):
1337 super().__init
__(src_loc_at
=src_loc_at
)
1338 self
.domain
= str(domain
)
1340 def _rhs_signals(self
):
1344 return "(tick {})".format(self
.domain
)
1348 class Passive(Statement
):
1349 def __init__(self
, *, src_loc_at
=0):
1350 super().__init
__(src_loc_at
=src_loc_at
)
1352 def _rhs_signals(self
):
1359 class _MappedKeyCollection(metaclass
=ABCMeta
):
1361 def _map_key(self
, key
):
1365 def _unmap_key(self
, key
):
1369 class _MappedKeyDict(MutableMapping
, _MappedKeyCollection
):
1370 def __init__(self
, pairs
=()):
1371 self
._storage
= OrderedDict()
1372 for key
, value
in pairs
:
1375 def __getitem__(self
, key
):
1376 key
= None if key
is None else self
._map
_key
(key
)
1377 return self
._storage
[key
]
1379 def __setitem__(self
, key
, value
):
1380 key
= None if key
is None else self
._map
_key
(key
)
1381 self
._storage
[key
] = value
1383 def __delitem__(self
, key
):
1384 key
= None if key
is None else self
._map
_key
(key
)
1385 del self
._storage
[key
]
1388 for key
in self
._storage
:
1392 yield self
._unmap
_key
(key
)
1394 def __eq__(self
, other
):
1395 if not isinstance(other
, type(self
)):
1397 if len(self
) != len(other
):
1399 for ak
, bk
in zip(sorted(self
._storage
), sorted(other
._storage
)):
1402 if self
._storage
[ak
] != other
._storage
[bk
]:
1407 return len(self
._storage
)
1410 pairs
= ["({!r}, {!r})".format(k
, v
) for k
, v
in self
.items()]
1411 return "{}.{}([{}])".format(type(self
).__module
__, type(self
).__name
__,
1415 class _MappedKeySet(MutableSet
, _MappedKeyCollection
):
1416 def __init__(self
, elements
=()):
1417 self
._storage
= OrderedDict()
1418 for elem
in elements
:
1421 def add(self
, value
):
1422 self
._storage
[self
._map
_key
(value
)] = None
1424 def update(self
, values
):
1425 for value
in values
:
1428 def discard(self
, value
):
1430 del self
._storage
[self
._map
_key
(value
)]
1432 def __contains__(self
, value
):
1433 return self
._map
_key
(value
) in self
._storage
1436 for key
in [k
for k
in self
._storage
]:
1437 yield self
._unmap
_key
(key
)
1440 return len(self
._storage
)
1443 return "{}.{}({})".format(type(self
).__module
__, type(self
).__name
__,
1444 ", ".join(repr(x
) for x
in self
))
1448 def __init__(self
, value
):
1449 self
.value
= Value
.wrap(value
)
1450 if isinstance(self
.value
, Const
):
1451 self
._hash
= hash(self
.value
.value
)
1452 elif isinstance(self
.value
, (Signal
, AnyValue
)):
1453 self
._hash
= hash(self
.value
.duid
)
1454 elif isinstance(self
.value
, (ClockSignal
, ResetSignal
)):
1455 self
._hash
= hash(self
.value
.domain
)
1456 elif isinstance(self
.value
, Operator
):
1457 self
._hash
= hash((self
.value
.op
, tuple(ValueKey(o
) for o
in self
.value
.operands
)))
1458 elif isinstance(self
.value
, Slice
):
1459 self
._hash
= hash((ValueKey(self
.value
.value
), self
.value
.start
, self
.value
.end
))
1460 elif isinstance(self
.value
, Part
):
1461 self
._hash
= hash((ValueKey(self
.value
.value
), ValueKey(self
.value
.offset
),
1462 self
.value
.width
, self
.value
.stride
))
1463 elif isinstance(self
.value
, Cat
):
1464 self
._hash
= hash(tuple(ValueKey(o
) for o
in self
.value
.parts
))
1465 elif isinstance(self
.value
, ArrayProxy
):
1466 self
._hash
= hash((ValueKey(self
.value
.index
),
1467 tuple(ValueKey(e
) for e
in self
.value
._iter
_as
_values
())))
1468 elif isinstance(self
.value
, Sample
):
1469 self
._hash
= hash((ValueKey(self
.value
.value
), self
.value
.clocks
, self
.value
.domain
))
1470 elif isinstance(self
.value
, Initial
):
1473 raise TypeError("Object '{!r}' cannot be used as a key in value collections"
1474 .format(self
.value
))
1479 def __eq__(self
, other
):
1480 if type(other
) is not ValueKey
:
1482 if type(self
.value
) is not type(other
.value
):
1485 if isinstance(self
.value
, Const
):
1486 return self
.value
.value
== other
.value
.value
1487 elif isinstance(self
.value
, (Signal
, AnyValue
)):
1488 return self
.value
is other
.value
1489 elif isinstance(self
.value
, (ClockSignal
, ResetSignal
)):
1490 return self
.value
.domain
== other
.value
.domain
1491 elif isinstance(self
.value
, Operator
):
1492 return (self
.value
.op
== other
.value
.op
and
1493 len(self
.value
.operands
) == len(other
.value
.operands
) and
1494 all(ValueKey(a
) == ValueKey(b
)
1495 for a
, b
in zip(self
.value
.operands
, other
.value
.operands
)))
1496 elif isinstance(self
.value
, Slice
):
1497 return (ValueKey(self
.value
.value
) == ValueKey(other
.value
.value
) and
1498 self
.value
.start
== other
.value
.start
and
1499 self
.value
.end
== other
.value
.end
)
1500 elif isinstance(self
.value
, Part
):
1501 return (ValueKey(self
.value
.value
) == ValueKey(other
.value
.value
) and
1502 ValueKey(self
.value
.offset
) == ValueKey(other
.value
.offset
) and
1503 self
.value
.width
== other
.value
.width
and
1504 self
.value
.stride
== other
.value
.stride
)
1505 elif isinstance(self
.value
, Cat
):
1506 return all(ValueKey(a
) == ValueKey(b
)
1507 for a
, b
in zip(self
.value
.parts
, other
.value
.parts
))
1508 elif isinstance(self
.value
, ArrayProxy
):
1509 return (ValueKey(self
.value
.index
) == ValueKey(other
.value
.index
) and
1510 len(self
.value
.elems
) == len(other
.value
.elems
) and
1511 all(ValueKey(a
) == ValueKey(b
)
1512 for a
, b
in zip(self
.value
._iter
_as
_values
(),
1513 other
.value
._iter
_as
_values
())))
1514 elif isinstance(self
.value
, Sample
):
1515 return (ValueKey(self
.value
.value
) == ValueKey(other
.value
.value
) and
1516 self
.value
.clocks
== other
.value
.clocks
and
1517 self
.value
.domain
== self
.value
.domain
)
1518 elif isinstance(self
.value
, Initial
):
1521 raise TypeError("Object '{!r}' cannot be used as a key in value collections"
1522 .format(self
.value
))
1524 def __lt__(self
, other
):
1525 if not isinstance(other
, ValueKey
):
1527 if type(self
.value
) != type(other
.value
):
1530 if isinstance(self
.value
, Const
):
1531 return self
.value
< other
.value
1532 elif isinstance(self
.value
, (Signal
, AnyValue
)):
1533 return self
.value
.duid
< other
.value
.duid
1534 elif isinstance(self
.value
, Slice
):
1535 return (ValueKey(self
.value
.value
) < ValueKey(other
.value
.value
) and
1536 self
.value
.start
< other
.value
.start
and
1537 self
.value
.end
< other
.value
.end
)
1539 raise TypeError("Object '{!r}' cannot be used as a key in value collections")
1542 return "<{}.ValueKey {!r}>".format(__name__
, self
.value
)
1545 class ValueDict(_MappedKeyDict
):
1547 _unmap_key
= lambda self
, key
: key
.value
1550 class ValueSet(_MappedKeySet
):
1552 _unmap_key
= lambda self
, key
: key
.value
1556 def __init__(self
, signal
):
1557 self
.signal
= signal
1558 if type(signal
) is Signal
:
1559 self
._intern
= (0, signal
.duid
)
1560 elif type(signal
) is ClockSignal
:
1561 self
._intern
= (1, signal
.domain
)
1562 elif type(signal
) is ResetSignal
:
1563 self
._intern
= (2, signal
.domain
)
1565 raise TypeError("Object '{!r}' is not an nMigen signal".format(signal
))
1568 return hash(self
._intern
)
1570 def __eq__(self
, other
):
1571 if type(other
) is not SignalKey
:
1573 return self
._intern
== other
._intern
1575 def __lt__(self
, other
):
1576 if type(other
) is not SignalKey
:
1577 raise TypeError("Object '{!r}' cannot be compared to a SignalKey".format(signal
))
1578 return self
._intern
< other
._intern
1581 return "<{}.SignalKey {!r}>".format(__name__
, self
.signal
)
1584 class SignalDict(_MappedKeyDict
):
1585 _map_key
= SignalKey
1586 _unmap_key
= lambda self
, key
: key
.signal
1589 class SignalSet(_MappedKeySet
):
1590 _map_key
= SignalKey
1591 _unmap_key
= lambda self
, key
: key
.signal