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 class Value(metaclass
=ABCMeta
):
36 """Ensures that the passed object is an nMigen value. Booleans and integers
37 are automatically wrapped into ``Const``."""
38 if isinstance(obj
, Value
):
40 elif isinstance(obj
, (bool, int)):
43 raise TypeError("Object '{!r}' is not an nMigen value".format(obj
))
45 def __init__(self
, *, src_loc_at
=0):
47 self
.src_loc
= tracer
.get_src_loc(1 + src_loc_at
)
50 raise TypeError("Attempted to convert nMigen value to boolean")
53 return Operator("~", [self
])
55 return Operator("-", [self
])
57 def __add__(self
, other
):
58 return Operator("+", [self
, other
])
59 def __radd__(self
, other
):
60 return Operator("+", [other
, self
])
61 def __sub__(self
, other
):
62 return Operator("-", [self
, other
])
63 def __rsub__(self
, other
):
64 return Operator("-", [other
, self
])
65 def __mul__(self
, other
):
66 return Operator("*", [self
, other
])
67 def __rmul__(self
, other
):
68 return Operator("*", [other
, self
])
69 def __mod__(self
, other
):
70 return Operator("%", [self
, other
])
71 def __rmod__(self
, other
):
72 return Operator("%", [other
, self
])
73 def __div__(self
, other
):
74 return Operator("/", [self
, other
])
75 def __rdiv__(self
, other
):
76 return Operator("/", [other
, self
])
77 def __lshift__(self
, other
):
78 return Operator("<<", [self
, other
])
79 def __rlshift__(self
, other
):
80 return Operator("<<", [other
, self
])
81 def __rshift__(self
, other
):
82 return Operator(">>", [self
, other
])
83 def __rrshift__(self
, other
):
84 return Operator(">>", [other
, self
])
85 def __and__(self
, other
):
86 return Operator("&", [self
, other
])
87 def __rand__(self
, other
):
88 return Operator("&", [other
, self
])
89 def __xor__(self
, other
):
90 return Operator("^", [self
, other
])
91 def __rxor__(self
, other
):
92 return Operator("^", [other
, self
])
93 def __or__(self
, other
):
94 return Operator("|", [self
, other
])
95 def __ror__(self
, other
):
96 return Operator("|", [other
, self
])
98 def __eq__(self
, other
):
99 return Operator("==", [self
, other
])
100 def __ne__(self
, other
):
101 return Operator("!=", [self
, other
])
102 def __lt__(self
, other
):
103 return Operator("<", [self
, other
])
104 def __le__(self
, other
):
105 return Operator("<=", [self
, other
])
106 def __gt__(self
, other
):
107 return Operator(">", [self
, other
])
108 def __ge__(self
, other
):
109 return Operator(">=", [self
, other
])
112 return self
.shape()[0]
114 def __getitem__(self
, key
):
116 if isinstance(key
, int):
117 if key
not in range(-n
, n
):
118 raise IndexError("Cannot index {} bits into {}-bit value".format(key
, n
))
121 return Slice(self
, key
, key
+ 1)
122 elif isinstance(key
, slice):
123 start
, stop
, step
= key
.indices(n
)
125 return Cat(self
[i
] for i
in range(start
, stop
, step
))
126 return Slice(self
, start
, stop
)
128 raise TypeError("Cannot index value with {}".format(repr(key
)))
131 """Conversion to boolean.
136 Output ``Value``. If any bits are set, returns ``1``, else ``0``.
138 return Operator("b", [self
])
140 def implies(premise
, conclusion
):
146 ``0`` if ``premise`` is true and ``conclusion`` is not, ``1`` otherwise.
148 return ~premise | conclusion
150 # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
151 @deprecated("instead of `.part`, use `.bit_select`")
152 def part(self
, offset
, width
):
153 return Part(self
, offset
, width
, src_loc_at
=1)
155 def bit_select(self
, offset
, width
):
156 """Part-select with bit granularity.
158 Selects a constant width but variable offset part of a ``Value``, such that successive
159 parts overlap by all but 1 bit.
164 index of first selected bit
166 number of selected bits
171 Selected part of the ``Value``
173 return Part(self
, offset
, width
, stride
=1, src_loc_at
=1)
175 def word_select(self
, offset
, width
):
176 """Part-select with word granularity.
178 Selects a constant width but variable offset part of a ``Value``, such that successive
179 parts do not overlap.
184 index of first selected word
186 number of selected bits
191 Selected part of the ``Value``
193 return Part(self
, offset
, width
, stride
=width
, src_loc_at
=1)
201 Value to be assigned.
206 Assignment statement that can be used in combinatorial or synchronous context.
208 return Assign(self
, value
, src_loc_at
=1)
212 """Bit length and signedness of a value.
217 Number of bits required to store `v` or available in `v`, followed by
218 whether `v` has a sign bit (included in the bit count).
222 >>> Value.shape(Signal(8))
224 >>> Value.shape(C(0xaa))
229 def _lhs_signals(self
):
230 raise TypeError("Value {!r} cannot be used in assignments".format(self
))
233 def _rhs_signals(self
):
237 raise TypeError("Value {!r} cannot be evaluated as constant".format(self
))
244 """A constant, literal integer value.
249 shape : int or tuple or None
250 Either an integer `bits` or a tuple `(bits, signed)`
251 specifying the number of bits in this `Const` and whether it is
252 signed (can represent negative values). `shape` defaults
253 to the minimum width and signedness of `value`.
263 def normalize(value
, shape
):
264 nbits
, signed
= shape
265 mask
= (1 << nbits
) - 1
267 if signed
and value
>> (nbits
- 1):
271 def __init__(self
, value
, shape
=None):
272 # We deliberately do not call Value.__init__ here.
273 self
.value
= int(value
)
275 shape
= bits_for(self
.value
), self
.value
< 0
276 if isinstance(shape
, int):
277 shape
= shape
, self
.value
< 0
278 self
.nbits
, self
.signed
= shape
279 if not isinstance(self
.nbits
, int) or self
.nbits
< 0:
280 raise TypeError("Width must be a non-negative integer, not '{!r}'"
282 self
.value
= self
.normalize(self
.value
, shape
)
285 return self
.nbits
, self
.signed
287 def _rhs_signals(self
):
294 return "(const {}'{}d{})".format(self
.nbits
, "s" if self
.signed
else "", self
.value
)
297 C
= Const
# shorthand
300 class AnyValue(Value
, DUID
):
301 def __init__(self
, shape
, *, src_loc_at
=0):
302 super().__init
__(src_loc_at
=src_loc_at
)
303 if isinstance(shape
, int):
305 self
.nbits
, self
.signed
= shape
306 if not isinstance(self
.nbits
, int) or self
.nbits
< 0:
307 raise TypeError("Width must be a non-negative integer, not '{!r}'"
311 return self
.nbits
, self
.signed
313 def _rhs_signals(self
):
318 class AnyConst(AnyValue
):
320 return "(anyconst {}'{})".format(self
.nbits
, "s" if self
.signed
else "")
324 class AnySeq(AnyValue
):
326 return "(anyseq {}'{})".format(self
.nbits
, "s" if self
.signed
else "")
330 class Operator(Value
):
331 def __init__(self
, op
, operands
, *, src_loc_at
=0):
332 super().__init
__(src_loc_at
=1 + src_loc_at
)
334 self
.operands
= [Value
.wrap(o
) for o
in operands
]
337 def _bitwise_binary_shape(a_shape
, b_shape
):
338 a_bits
, a_sign
= a_shape
339 b_bits
, b_sign
= b_shape
340 if not a_sign
and not b_sign
:
341 # both operands unsigned
342 return max(a_bits
, b_bits
), False
343 elif a_sign
and b_sign
:
344 # both operands signed
345 return max(a_bits
, b_bits
), True
346 elif not a_sign
and b_sign
:
347 # first operand unsigned (add sign bit), second operand signed
348 return max(a_bits
+ 1, b_bits
), True
350 # first signed, second operand unsigned (add sign bit)
351 return max(a_bits
, b_bits
+ 1), True
354 op_shapes
= list(map(lambda x
: x
.shape(), self
.operands
))
355 if len(op_shapes
) == 1:
356 (a_bits
, a_sign
), = op_shapes
357 if self
.op
in ("+", "~"):
358 return a_bits
, a_sign
361 return a_bits
+ 1, True
363 return a_bits
, a_sign
366 elif len(op_shapes
) == 2:
367 (a_bits
, a_sign
), (b_bits
, b_sign
) = op_shapes
368 if self
.op
== "+" or self
.op
== "-":
369 bits
, sign
= self
._bitwise
_binary
_shape
(*op_shapes
)
370 return bits
+ 1, sign
372 return a_bits
+ b_bits
, a_sign
or b_sign
374 return a_bits
, a_sign
375 if self
.op
in ("<", "<=", "==", "!=", ">", ">=", "b"):
377 if self
.op
in ("&", "^", "|"):
378 return self
._bitwise
_binary
_shape
(*op_shapes
)
381 extra
= 2 ** (b_bits
- 1) - 1
383 extra
= 2 ** (b_bits
) - 1
384 return a_bits
+ extra
, a_sign
387 extra
= 2 ** (b_bits
- 1)
390 return a_bits
+ extra
, a_sign
391 elif len(op_shapes
) == 3:
393 s_shape
, a_shape
, b_shape
= op_shapes
394 return self
._bitwise
_binary
_shape
(a_shape
, b_shape
)
395 raise NotImplementedError("Operator {}/{} not implemented"
396 .format(self
.op
, len(op_shapes
))) # :nocov:
398 def _rhs_signals(self
):
399 return union(op
._rhs
_signals
() for op
in self
.operands
)
402 return "({} {})".format(self
.op
, " ".join(map(repr, self
.operands
)))
405 def Mux(sel
, val1
, val0
):
406 """Choose between two values.
419 Output ``Value``. If ``sel`` is asserted, the Mux returns ``val1``, else ``val0``.
421 return Operator("m", [sel
, val1
, val0
])
426 def __init__(self
, value
, start
, end
, *, src_loc_at
=0):
427 if not isinstance(start
, int):
428 raise TypeError("Slice start must be an integer, not '{!r}'".format(start
))
429 if not isinstance(end
, int):
430 raise TypeError("Slice end must be an integer, not '{!r}'".format(end
))
433 if start
not in range(-(n
+1), n
+1):
434 raise IndexError("Cannot start slice {} bits into {}-bit value".format(start
, n
))
437 if end
not in range(-(n
+1), n
+1):
438 raise IndexError("Cannot end slice {} bits into {}-bit value".format(end
, n
))
442 raise IndexError("Slice start {} must be less than slice end {}".format(start
, end
))
444 super().__init
__(src_loc_at
=src_loc_at
)
445 self
.value
= Value
.wrap(value
)
450 return self
.end
- self
.start
, False
452 def _lhs_signals(self
):
453 return self
.value
._lhs
_signals
()
455 def _rhs_signals(self
):
456 return self
.value
._rhs
_signals
()
459 return "(slice {} {}:{})".format(repr(self
.value
), self
.start
, self
.end
)
464 def __init__(self
, value
, offset
, width
, stride
=1, *, src_loc_at
=0):
465 if not isinstance(width
, int) or width
< 0:
466 raise TypeError("Part width must be a non-negative integer, not '{!r}'".format(width
))
467 if not isinstance(stride
, int) or stride
<= 0:
468 raise TypeError("Part stride must be a positive integer, not '{!r}'".format(stride
))
470 super().__init
__(src_loc_at
=src_loc_at
)
472 self
.offset
= Value
.wrap(offset
)
477 return self
.width
, False
479 def _lhs_signals(self
):
480 return self
.value
._lhs
_signals
()
482 def _rhs_signals(self
):
483 return self
.value
._rhs
_signals
() | self
.offset
._rhs
_signals
()
486 return "(part {} {} {} {})".format(repr(self
.value
), repr(self
.offset
),
487 self
.width
, self
.stride
)
492 """Concatenate values.
494 Form a compound ``Value`` from several smaller ones by concatenation.
495 The first argument occupies the lower bits of the result.
496 The return value can be used on either side of an assignment, that
497 is, the concatenated value can be used as an argument on the RHS or
498 as a target on the LHS. If it is used on the LHS, it must solely
499 consist of ``Signal`` s, slices of ``Signal`` s, and other concatenations
500 meeting these properties. The bit length of the return value is the sum of
501 the bit lengths of the arguments::
503 len(Cat(args)) == sum(len(arg) for arg in args)
507 *args : Values or iterables of Values, inout
508 ``Value`` s to be concatenated.
513 Resulting ``Value`` obtained by concatentation.
515 def __init__(self
, *args
, src_loc_at
=0):
516 super().__init
__(src_loc_at
=src_loc_at
)
517 self
.parts
= [Value
.wrap(v
) for v
in flatten(args
)]
520 return sum(len(part
) for part
in self
.parts
), False
522 def _lhs_signals(self
):
523 return union((part
._lhs
_signals
() for part
in self
.parts
), start
=ValueSet())
525 def _rhs_signals(self
):
526 return union((part
._rhs
_signals
() for part
in self
.parts
), start
=ValueSet())
530 for part
in reversed(self
.parts
):
532 value |
= part
._as
_const
()
536 return "(cat {})".format(" ".join(map(repr, self
.parts
)))
543 An input value is replicated (repeated) several times
544 to be used on the RHS of assignments::
546 len(Repl(s, n)) == len(s) * n
551 Input value to be replicated.
553 Number of replications.
560 def __init__(self
, value
, count
, *, src_loc_at
=0):
561 if not isinstance(count
, int) or count
< 0:
562 raise TypeError("Replication count must be a non-negative integer, not '{!r}'"
565 super().__init
__(src_loc_at
=src_loc_at
)
566 self
.value
= Value
.wrap(value
)
570 return len(self
.value
) * self
.count
, False
572 def _rhs_signals(self
):
573 return self
.value
._rhs
_signals
()
576 return "(repl {!r} {})".format(self
.value
, self
.count
)
580 class Signal(Value
, DUID
):
581 """A varying integer value.
585 shape : int or tuple or None
586 Either an integer ``bits`` or a tuple ``(bits, signed)`` specifying the number of bits
587 in this ``Signal`` and whether it is signed (can represent negative values).
588 ``shape`` defaults to 1-bit and non-signed.
590 Name hint for this signal. If ``None`` (default) the name is inferred from the variable
591 name this ``Signal`` is assigned to. Name collisions are automatically resolved by
592 prepending names of objects that contain this ``Signal`` and by appending integer
595 Reset (synchronous) or default (combinatorial) value.
596 When this ``Signal`` is assigned to in synchronous context and the corresponding clock
597 domain is reset, the ``Signal`` assumes the given value. When this ``Signal`` is unassigned
598 in combinatorial context (due to conditional assignments not being taken), the ``Signal``
599 assumes its ``reset`` value. Defaults to 0.
601 If ``True``, do not generate reset logic for this ``Signal`` in synchronous statements.
602 The ``reset`` value is only used as a combinatorial default or as the initial value.
603 Defaults to ``False``.
606 If ``shape`` is ``None``, the signal bit width and signedness are
607 determined by the integer range given by ``min`` (inclusive,
608 defaults to 0) and ``max`` (exclusive, defaults to 2).
610 Dictionary of synthesis attributes.
611 decoder : function or Enum
612 A function converting integer signal values to human-readable strings (e.g. FSM state
613 names). If an ``Enum`` subclass is passed, it is concisely decoded using format string
614 ``"{0.name:}/{0.value:}"``, or a number if the signal value is not a member of
627 def __init__(self
, shape
=None, name
=None, *, reset
=0, reset_less
=False, min=None, max=None,
628 attrs
=None, decoder
=None, src_loc_at
=0):
629 super().__init
__(src_loc_at
=src_loc_at
)
631 # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
632 if min is not None or max is not None:
633 warnings
.warn("instead of `Signal(min={min}, max={max})`, "
634 "use `Signal.range({min}, {max})`"
635 .format(min=min or 0, max=max or 2),
636 DeprecationWarning, stacklevel
=2 + src_loc_at
)
638 if name
is not None and not isinstance(name
, str):
639 raise TypeError("Name must be a string, not '{!r}'".format(name
))
640 self
.name
= name
or tracer
.get_var_name(depth
=2 + src_loc_at
, default
="$signal")
647 max -= 1 # make both bounds inclusive
649 raise ValueError("Lower bound {} should be less or equal to higher bound {}"
650 .format(min, max + 1))
651 self
.signed
= min < 0 or max < 0
655 self
.nbits
= builtins
.max(bits_for(min, self
.signed
),
656 bits_for(max, self
.signed
))
659 if not (min is None and max is None):
660 raise ValueError("Only one of bits/signedness or bounds may be specified")
661 if isinstance(shape
, int):
662 self
.nbits
, self
.signed
= shape
, False
664 self
.nbits
, self
.signed
= shape
666 if not isinstance(self
.nbits
, int) or self
.nbits
< 0:
667 raise TypeError("Width must be a non-negative integer, not '{!r}'".format(self
.nbits
))
668 self
.reset
= int(reset
)
669 self
.reset_less
= bool(reset_less
)
671 self
.attrs
= OrderedDict(() if attrs
is None else attrs
)
672 if isinstance(decoder
, type) and issubclass(decoder
, Enum
):
673 def enum_decoder(value
):
675 return "{0.name:}/{0.value:}".format(decoder(value
))
678 self
.decoder
= enum_decoder
680 self
.decoder
= decoder
683 def range(cls
, *args
, src_loc_at
=0, **kwargs
):
684 """Create Signal that can represent a given range.
686 The parameters to ``Signal.range`` are the same as for the built-in ``range`` function.
687 That is, for any given ``range(*args)``, ``Signal.range(*args)`` can represent any
688 ``x for x in range(*args)``.
690 value_range
= range(*args
)
691 if len(value_range
) > 0:
692 signed
= value_range
.start
< 0 or (value_range
.stop
- value_range
.step
) < 0
694 signed
= value_range
.start
< 0
695 nbits
= max(bits_for(value_range
.start
, signed
),
696 bits_for(value_range
.stop
- value_range
.step
, signed
))
697 return cls((nbits
, signed
), src_loc_at
=1 + src_loc_at
, **kwargs
)
700 def like(cls
, other
, *, name
=None, name_suffix
=None, src_loc_at
=0, **kwargs
):
701 """Create Signal based on another.
706 Object to base this Signal on.
710 elif name_suffix
is not None:
711 new_name
= other
.name
+ str(name_suffix
)
713 new_name
= tracer
.get_var_name(depth
=2 + src_loc_at
, default
="$like")
714 kw
= dict(shape
=cls
.wrap(other
).shape(), name
=new_name
)
715 if isinstance(other
, cls
):
716 kw
.update(reset
=other
.reset
, reset_less
=other
.reset_less
,
717 attrs
=other
.attrs
, decoder
=other
.decoder
)
719 return cls(**kw
, src_loc_at
=1 + src_loc_at
)
722 return self
.nbits
, self
.signed
724 def _lhs_signals(self
):
725 return ValueSet((self
,))
727 def _rhs_signals(self
):
728 return ValueSet((self
,))
731 return "(sig {})".format(self
.name
)
735 class ClockSignal(Value
):
736 """Clock signal for a clock domain.
738 Any ``ClockSignal`` is equivalent to ``cd.clk`` for a clock domain with the corresponding name.
739 All of these signals ultimately refer to the same signal, but they can be manipulated
740 independently of the clock domain, even before the clock domain is created.
745 Clock domain to obtain a clock signal for. Defaults to ``"sync"``.
747 def __init__(self
, domain
="sync", *, src_loc_at
=0):
748 super().__init
__(src_loc_at
=src_loc_at
)
749 if not isinstance(domain
, str):
750 raise TypeError("Clock domain name must be a string, not '{!r}'".format(domain
))
752 raise ValueError("Domain '{}' does not have a clock".format(domain
))
758 def _lhs_signals(self
):
759 return ValueSet((self
,))
761 def _rhs_signals(self
):
762 raise NotImplementedError("ClockSignal must be lowered to a concrete signal") # :nocov:
765 return "(clk {})".format(self
.domain
)
769 class ResetSignal(Value
):
770 """Reset signal for a clock domain.
772 Any ``ResetSignal`` is equivalent to ``cd.rst`` for a clock domain with the corresponding name.
773 All of these signals ultimately refer to the same signal, but they can be manipulated
774 independently of the clock domain, even before the clock domain is created.
779 Clock domain to obtain a reset signal for. Defaults to ``"sync"``.
780 allow_reset_less : bool
781 If the clock domain is reset-less, act as a constant ``0`` instead of reporting an error.
783 def __init__(self
, domain
="sync", allow_reset_less
=False, *, src_loc_at
=0):
784 super().__init
__(src_loc_at
=src_loc_at
)
785 if not isinstance(domain
, str):
786 raise TypeError("Clock domain name must be a string, not '{!r}'".format(domain
))
788 raise ValueError("Domain '{}' does not have a reset".format(domain
))
790 self
.allow_reset_less
= allow_reset_less
795 def _lhs_signals(self
):
796 return ValueSet((self
,))
798 def _rhs_signals(self
):
799 raise NotImplementedError("ResetSignal must be lowered to a concrete signal") # :nocov:
802 return "(rst {})".format(self
.domain
)
805 class Array(MutableSequence
):
806 """Addressable multiplexer.
808 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
811 The array proxy can be used as an ordinary ``Value``, i.e. participate in calculations and
812 assignments, provided that all elements of the array are values. The array proxy also supports
813 attribute access and further indexing, each returning another array proxy; this means that
814 the results of indexing into arrays, arrays of records, and arrays of arrays can all
815 be used as first-class values.
817 It is an error to change an array or any of its elements after an array proxy was created.
818 Changing the array directly will raise an exception. However, it is not possible to detect
819 the elements being modified; if an element's attribute or element is modified after the proxy
820 for it has been created, the proxy will refer to stale data.
827 gpios = Array(Signal() for _ in range(10))
829 m.d.sync += gpios[bus.adr].eq(bus.dat_w)
831 m.d.sync += bus.dat_r.eq(gpios[bus.adr])
833 Multidimensional array::
835 mult = Array(Array(x * y for y in range(10)) for x in range(10))
839 m.d.comb += r.eq(mult[a][b])
847 buses = Array(Record(layout) for busno in range(4))
848 master = Record(layout)
850 buses[sel].re.eq(master.re),
851 master.dat_r.eq(buses[sel].dat_r),
854 def __init__(self
, iterable
=()):
855 self
._inner
= list(iterable
)
856 self
._proxy
_at
= None
859 def __getitem__(self
, index
):
860 if isinstance(index
, Value
):
862 self
._proxy
_at
= tracer
.get_src_loc()
863 self
._mutable
= False
864 return ArrayProxy(self
, index
)
866 return self
._inner
[index
]
869 return len(self
._inner
)
871 def _check_mutability(self
):
872 if not self
._mutable
:
873 raise ValueError("Array can no longer be mutated after it was indexed with a value "
874 "at {}:{}".format(*self
._proxy
_at
))
876 def __setitem__(self
, index
, value
):
877 self
._check
_mutability
()
878 self
._inner
[index
] = value
880 def __delitem__(self
, index
):
881 self
._check
_mutability
()
882 del self
._inner
[index
]
884 def insert(self
, index
, value
):
885 self
._check
_mutability
()
886 self
._inner
.insert(index
, value
)
889 return "(array{} [{}])".format(" mutable" if self
._mutable
else "",
890 ", ".join(map(repr, self
._inner
)))
894 class ArrayProxy(Value
):
895 def __init__(self
, elems
, index
, *, src_loc_at
=0):
896 super().__init
__(src_loc_at
=1 + src_loc_at
)
898 self
.index
= Value
.wrap(index
)
900 def __getattr__(self
, attr
):
901 return ArrayProxy([getattr(elem
, attr
) for elem
in self
.elems
], self
.index
)
903 def __getitem__(self
, index
):
904 return ArrayProxy([ elem
[index
] for elem
in self
.elems
], self
.index
)
906 def _iter_as_values(self
):
907 return (Value
.wrap(elem
) for elem
in self
.elems
)
910 bits
, sign
= 0, False
911 for elem_bits
, elem_sign
in (elem
.shape() for elem
in self
._iter
_as
_values
()):
912 bits
= max(bits
, elem_bits
+ elem_sign
)
913 sign
= max(sign
, elem_sign
)
916 def _lhs_signals(self
):
917 signals
= union((elem
._lhs
_signals
() for elem
in self
._iter
_as
_values
()), start
=ValueSet())
920 def _rhs_signals(self
):
921 signals
= union((elem
._rhs
_signals
() for elem
in self
._iter
_as
_values
()), start
=ValueSet())
922 return self
.index
._rhs
_signals
() | signals
925 return "(proxy (array [{}]) {!r})".format(", ".join(map(repr, self
.elems
)), self
.index
)
928 class UserValue(Value
):
929 """Value with custom lowering.
931 A ``UserValue`` is a value whose precise representation does not have to be immediately known,
932 which is useful in certain metaprogramming scenarios. Instead of providing fixed semantics
933 upfront, it is kept abstract for as long as possible, only being lowered to a concrete nMigen
936 Note that the ``lower`` method will only be called once; this is necessary to ensure that
937 nMigen's view of representation of all values stays internally consistent. If the class
938 deriving from ``UserValue`` is mutable, then it must ensure that after ``lower`` is called,
939 it is not mutated in a way that changes its representation.
941 The following is an incomplete list of actions that, when applied to an ``UserValue`` directly
942 or indirectly, will cause it to be lowered, provided as an illustrative reference:
943 * Querying the shape using ``.shape()`` or ``len()``;
944 * Creating a similarly shaped signal using ``Signal.like``;
945 * Indexing or iterating through individual bits;
946 * Adding an assignment to the value to a ``Module`` using ``m.d.<domain> +=``.
948 def __init__(self
, *, src_loc_at
=0):
949 super().__init
__(src_loc_at
=1 + src_loc_at
)
950 self
.__lowered
= None
954 """Conversion to a concrete representation."""
957 def _lazy_lower(self
):
958 if self
.__lowered
is None:
959 self
.__lowered
= Value
.wrap(self
.lower())
960 return self
.__lowered
963 return self
._lazy
_lower
().shape()
965 def _lhs_signals(self
):
966 return self
._lazy
_lower
()._lhs
_signals
()
968 def _rhs_signals(self
):
969 return self
._lazy
_lower
()._rhs
_signals
()
974 """Value from the past.
976 A ``Sample`` of an expression is equal to the value of the expression ``clocks`` clock edges
977 of the ``domain`` clock back. If that moment is before the beginning of time, it is equal
978 to the value of the expression calculated as if each signal had its reset value.
980 def __init__(self
, expr
, clocks
, domain
, *, src_loc_at
=0):
981 super().__init
__(src_loc_at
=1 + src_loc_at
)
982 self
.value
= Value
.wrap(expr
)
983 self
.clocks
= int(clocks
)
985 if not isinstance(self
.value
, (Const
, Signal
, ClockSignal
, ResetSignal
, Initial
)):
986 raise TypeError("Sampled value must be a signal or a constant, not {!r}"
989 raise ValueError("Cannot sample a value {} cycles in the future"
990 .format(-self
.clocks
))
991 if not (self
.domain
is None or isinstance(self
.domain
, str)):
992 raise TypeError("Domain name must be a string or None, not {!r}"
993 .format(self
.domain
))
996 return self
.value
.shape()
998 def _rhs_signals(self
):
999 return ValueSet((self
,))
1002 return "(sample {!r} @ {}[{}])".format(
1003 self
.value
, "<default>" if self
.domain
is None else self
.domain
, self
.clocks
)
1006 def Past(expr
, clocks
=1, domain
=None):
1007 return Sample(expr
, clocks
, domain
)
1010 def Stable(expr
, clocks
=0, domain
=None):
1011 return Sample(expr
, clocks
+ 1, domain
) == Sample(expr
, clocks
, domain
)
1014 def Rose(expr
, clocks
=0, domain
=None):
1015 return ~
Sample(expr
, clocks
+ 1, domain
) & Sample(expr
, clocks
, domain
)
1018 def Fell(expr
, clocks
=0, domain
=None):
1019 return Sample(expr
, clocks
+ 1, domain
) & ~
Sample(expr
, clocks
, domain
)
1023 class Initial(Value
):
1024 """Start indicator, for model checking.
1026 An ``Initial`` signal is ``1`` at the first cycle of model checking, and ``0`` at any other.
1028 def __init__(self
, *, src_loc_at
=0):
1029 super().__init
__(src_loc_at
=1 + src_loc_at
)
1034 def _rhs_signals(self
):
1035 return ValueSet((self
,))
1041 class _StatementList(list):
1043 return "({})".format(" ".join(map(repr, self
)))
1047 def __init__(self
, *, src_loc_at
=0):
1048 self
.src_loc
= tracer
.get_src_loc(1 + src_loc_at
)
1052 if isinstance(obj
, Iterable
):
1053 return _StatementList(sum((Statement
.wrap(e
) for e
in obj
), []))
1055 if isinstance(obj
, Statement
):
1056 return _StatementList([obj
])
1058 raise TypeError("Object '{!r}' is not an nMigen statement".format(obj
))
1062 class Assign(Statement
):
1063 def __init__(self
, lhs
, rhs
, *, src_loc_at
=0):
1064 super().__init
__(src_loc_at
=src_loc_at
)
1065 self
.lhs
= Value
.wrap(lhs
)
1066 self
.rhs
= Value
.wrap(rhs
)
1068 def _lhs_signals(self
):
1069 return self
.lhs
._lhs
_signals
()
1071 def _rhs_signals(self
):
1072 return self
.lhs
._rhs
_signals
() | self
.rhs
._rhs
_signals
()
1075 return "(eq {!r} {!r})".format(self
.lhs
, self
.rhs
)
1078 class Property(Statement
):
1079 def __init__(self
, test
, *, _check
=None, _en
=None, src_loc_at
=0):
1080 super().__init
__(src_loc_at
=src_loc_at
)
1081 self
.test
= Value
.wrap(test
)
1082 self
._check
= _check
1084 if self
._check
is None:
1085 self
._check
= Signal(reset_less
=True, name
="${}$check".format(self
._kind
))
1086 self
._check
.src_loc
= self
.src_loc
1088 self
._en
= Signal(reset_less
=True, name
="${}$en".format(self
._kind
))
1089 self
._en
.src_loc
= self
.src_loc
1091 def _lhs_signals(self
):
1092 return ValueSet((self
._en
, self
._check
))
1094 def _rhs_signals(self
):
1095 return self
.test
._rhs
_signals
()
1098 return "({} {!r})".format(self
._kind
, self
.test
)
1102 class Assert(Property
):
1107 class Assume(Property
):
1112 class Cover(Property
):
1117 class Switch(Statement
):
1118 def __init__(self
, test
, cases
, *, src_loc
=None, src_loc_at
=0, case_src_locs
={}):
1120 super().__init
__(src_loc_at
=src_loc_at
)
1122 # Switch is a bit special in terms of location tracking because it is usually created
1123 # long after the control has left the statement that directly caused its creation.
1124 self
.src_loc
= src_loc
1125 # Switch is also a bit special in that its parts also have location information. It can't
1126 # be automatically traced, so whatever constructs a Switch may optionally provide it.
1127 self
.case_src_locs
= {}
1129 self
.test
= Value
.wrap(test
)
1130 self
.cases
= OrderedDict()
1131 for orig_keys
, stmts
in cases
.items():
1132 # Map: None -> (); key -> (key,); (key...) -> (key...)
1136 if not isinstance(keys
, tuple):
1138 # Map: 2 -> "0010"; "0010" -> "0010"
1141 if isinstance(key
, (bool, int)):
1142 key
= "{:0{}b}".format(key
, len(self
.test
))
1143 elif isinstance(key
, str):
1146 raise TypeError("Object '{!r}' cannot be used as a switch key"
1148 assert len(key
) == len(self
.test
)
1149 new_keys
= (*new_keys
, key
)
1150 if not isinstance(stmts
, Iterable
):
1152 self
.cases
[new_keys
] = Statement
.wrap(stmts
)
1153 if orig_keys
in case_src_locs
:
1154 self
.case_src_locs
[new_keys
] = case_src_locs
[orig_keys
]
1156 def _lhs_signals(self
):
1157 signals
= union((s
._lhs
_signals
() for ss
in self
.cases
.values() for s
in ss
),
1161 def _rhs_signals(self
):
1162 signals
= union((s
._rhs
_signals
() for ss
in self
.cases
.values() for s
in ss
),
1164 return self
.test
._rhs
_signals
() | signals
1167 def case_repr(keys
, stmts
):
1168 stmts_repr
= " ".join(map(repr, stmts
))
1170 return "(default {})".format(stmts_repr
)
1171 elif len(keys
) == 1:
1172 return "(case {} {})".format(keys
[0], stmts_repr
)
1174 return "(case ({}) {})".format(" ".join(keys
), stmts_repr
)
1175 case_reprs
= [case_repr(keys
, stmts
) for keys
, stmts
in self
.cases
.items()]
1176 return "(switch {!r} {})".format(self
.test
, " ".join(case_reprs
))
1180 class Delay(Statement
):
1181 def __init__(self
, interval
=None, *, src_loc_at
=0):
1182 super().__init
__(src_loc_at
=src_loc_at
)
1183 self
.interval
= None if interval
is None else float(interval
)
1185 def _rhs_signals(self
):
1189 if self
.interval
is None:
1192 return "(delay {:.3}us)".format(self
.interval
* 1e6
)
1196 class Tick(Statement
):
1197 def __init__(self
, domain
="sync", *, src_loc_at
=0):
1198 super().__init
__(src_loc_at
=src_loc_at
)
1199 self
.domain
= str(domain
)
1201 def _rhs_signals(self
):
1205 return "(tick {})".format(self
.domain
)
1209 class Passive(Statement
):
1210 def __init__(self
, *, src_loc_at
=0):
1211 super().__init
__(src_loc_at
=src_loc_at
)
1213 def _rhs_signals(self
):
1220 class _MappedKeyCollection(metaclass
=ABCMeta
):
1222 def _map_key(self
, key
):
1226 def _unmap_key(self
, key
):
1230 class _MappedKeyDict(MutableMapping
, _MappedKeyCollection
):
1231 def __init__(self
, pairs
=()):
1232 self
._storage
= OrderedDict()
1233 for key
, value
in pairs
:
1236 def __getitem__(self
, key
):
1237 key
= None if key
is None else self
._map
_key
(key
)
1238 return self
._storage
[key
]
1240 def __setitem__(self
, key
, value
):
1241 key
= None if key
is None else self
._map
_key
(key
)
1242 self
._storage
[key
] = value
1244 def __delitem__(self
, key
):
1245 key
= None if key
is None else self
._map
_key
(key
)
1246 del self
._storage
[key
]
1249 for key
in self
._storage
:
1253 yield self
._unmap
_key
(key
)
1255 def __eq__(self
, other
):
1256 if not isinstance(other
, type(self
)):
1258 if len(self
) != len(other
):
1260 for ak
, bk
in zip(sorted(self
._storage
), sorted(other
._storage
)):
1263 if self
._storage
[ak
] != other
._storage
[bk
]:
1268 return len(self
._storage
)
1271 pairs
= ["({!r}, {!r})".format(k
, v
) for k
, v
in self
.items()]
1272 return "{}.{}([{}])".format(type(self
).__module
__, type(self
).__name
__,
1276 class _MappedKeySet(MutableSet
, _MappedKeyCollection
):
1277 def __init__(self
, elements
=()):
1278 self
._storage
= OrderedDict()
1279 for elem
in elements
:
1282 def add(self
, value
):
1283 self
._storage
[self
._map
_key
(value
)] = None
1285 def update(self
, values
):
1286 for value
in values
:
1289 def discard(self
, value
):
1291 del self
._storage
[self
._map
_key
(value
)]
1293 def __contains__(self
, value
):
1294 return self
._map
_key
(value
) in self
._storage
1297 for key
in [k
for k
in self
._storage
]:
1298 yield self
._unmap
_key
(key
)
1301 return len(self
._storage
)
1304 return "{}.{}({})".format(type(self
).__module
__, type(self
).__name
__,
1305 ", ".join(repr(x
) for x
in self
))
1309 def __init__(self
, value
):
1310 self
.value
= Value
.wrap(value
)
1311 if isinstance(self
.value
, Const
):
1312 self
._hash
= hash(self
.value
.value
)
1313 elif isinstance(self
.value
, (Signal
, AnyValue
)):
1314 self
._hash
= hash(self
.value
.duid
)
1315 elif isinstance(self
.value
, (ClockSignal
, ResetSignal
)):
1316 self
._hash
= hash(self
.value
.domain
)
1317 elif isinstance(self
.value
, Operator
):
1318 self
._hash
= hash((self
.value
.op
, tuple(ValueKey(o
) for o
in self
.value
.operands
)))
1319 elif isinstance(self
.value
, Slice
):
1320 self
._hash
= hash((ValueKey(self
.value
.value
), self
.value
.start
, self
.value
.end
))
1321 elif isinstance(self
.value
, Part
):
1322 self
._hash
= hash((ValueKey(self
.value
.value
), ValueKey(self
.value
.offset
),
1323 self
.value
.width
, self
.value
.stride
))
1324 elif isinstance(self
.value
, Cat
):
1325 self
._hash
= hash(tuple(ValueKey(o
) for o
in self
.value
.parts
))
1326 elif isinstance(self
.value
, ArrayProxy
):
1327 self
._hash
= hash((ValueKey(self
.value
.index
),
1328 tuple(ValueKey(e
) for e
in self
.value
._iter
_as
_values
())))
1329 elif isinstance(self
.value
, Sample
):
1330 self
._hash
= hash((ValueKey(self
.value
.value
), self
.value
.clocks
, self
.value
.domain
))
1331 elif isinstance(self
.value
, Initial
):
1334 raise TypeError("Object '{!r}' cannot be used as a key in value collections"
1335 .format(self
.value
))
1340 def __eq__(self
, other
):
1341 if type(other
) is not ValueKey
:
1343 if type(self
.value
) is not type(other
.value
):
1346 if isinstance(self
.value
, Const
):
1347 return self
.value
.value
== other
.value
.value
1348 elif isinstance(self
.value
, (Signal
, AnyValue
)):
1349 return self
.value
is other
.value
1350 elif isinstance(self
.value
, (ClockSignal
, ResetSignal
)):
1351 return self
.value
.domain
== other
.value
.domain
1352 elif isinstance(self
.value
, Operator
):
1353 return (self
.value
.op
== other
.value
.op
and
1354 len(self
.value
.operands
) == len(other
.value
.operands
) and
1355 all(ValueKey(a
) == ValueKey(b
)
1356 for a
, b
in zip(self
.value
.operands
, other
.value
.operands
)))
1357 elif isinstance(self
.value
, Slice
):
1358 return (ValueKey(self
.value
.value
) == ValueKey(other
.value
.value
) and
1359 self
.value
.start
== other
.value
.start
and
1360 self
.value
.end
== other
.value
.end
)
1361 elif isinstance(self
.value
, Part
):
1362 return (ValueKey(self
.value
.value
) == ValueKey(other
.value
.value
) and
1363 ValueKey(self
.value
.offset
) == ValueKey(other
.value
.offset
) and
1364 self
.value
.width
== other
.value
.width
and
1365 self
.value
.stride
== other
.value
.stride
)
1366 elif isinstance(self
.value
, Cat
):
1367 return all(ValueKey(a
) == ValueKey(b
)
1368 for a
, b
in zip(self
.value
.parts
, other
.value
.parts
))
1369 elif isinstance(self
.value
, ArrayProxy
):
1370 return (ValueKey(self
.value
.index
) == ValueKey(other
.value
.index
) and
1371 len(self
.value
.elems
) == len(other
.value
.elems
) and
1372 all(ValueKey(a
) == ValueKey(b
)
1373 for a
, b
in zip(self
.value
._iter
_as
_values
(),
1374 other
.value
._iter
_as
_values
())))
1375 elif isinstance(self
.value
, Sample
):
1376 return (ValueKey(self
.value
.value
) == ValueKey(other
.value
.value
) and
1377 self
.value
.clocks
== other
.value
.clocks
and
1378 self
.value
.domain
== self
.value
.domain
)
1379 elif isinstance(self
.value
, Initial
):
1382 raise TypeError("Object '{!r}' cannot be used as a key in value collections"
1383 .format(self
.value
))
1385 def __lt__(self
, other
):
1386 if not isinstance(other
, ValueKey
):
1388 if type(self
.value
) != type(other
.value
):
1391 if isinstance(self
.value
, Const
):
1392 return self
.value
< other
.value
1393 elif isinstance(self
.value
, (Signal
, AnyValue
)):
1394 return self
.value
.duid
< other
.value
.duid
1395 elif isinstance(self
.value
, Slice
):
1396 return (ValueKey(self
.value
.value
) < ValueKey(other
.value
.value
) and
1397 self
.value
.start
< other
.value
.start
and
1398 self
.value
.end
< other
.value
.end
)
1400 raise TypeError("Object '{!r}' cannot be used as a key in value collections")
1403 return "<{}.ValueKey {!r}>".format(__name__
, self
.value
)
1406 class ValueDict(_MappedKeyDict
):
1408 _unmap_key
= lambda self
, key
: key
.value
1411 class ValueSet(_MappedKeySet
):
1413 _unmap_key
= lambda self
, key
: key
.value
1417 def __init__(self
, signal
):
1418 self
.signal
= signal
1419 if type(signal
) is Signal
:
1420 self
._intern
= (0, signal
.duid
)
1421 elif type(signal
) is ClockSignal
:
1422 self
._intern
= (1, signal
.domain
)
1423 elif type(signal
) is ResetSignal
:
1424 self
._intern
= (2, signal
.domain
)
1426 raise TypeError("Object '{!r}' is not an nMigen signal".format(signal
))
1429 return hash(self
._intern
)
1431 def __eq__(self
, other
):
1432 if type(other
) is not SignalKey
:
1434 return self
._intern
== other
._intern
1436 def __lt__(self
, other
):
1437 if type(other
) is not SignalKey
:
1438 raise TypeError("Object '{!r}' cannot be compared to a SignalKey".format(signal
))
1439 return self
._intern
< other
._intern
1442 return "<{}.SignalKey {!r}>".format(__name__
, self
.signal
)
1445 class SignalDict(_MappedKeyDict
):
1446 _map_key
= SignalKey
1447 _unmap_key
= lambda self
, key
: key
.signal
1450 class SignalSet(_MappedKeySet
):
1451 _map_key
= SignalKey
1452 _unmap_key
= lambda self
, key
: key
.signal