1 from abc
import ABCMeta
, abstractmethod
4 from collections
import OrderedDict
5 from collections
.abc
import Iterable
, MutableMapping
, MutableSet
, MutableSequence
12 "Value", "Const", "C", "Operator", "Mux", "Part", "Slice", "Cat", "Repl",
13 "Array", "ArrayProxy",
14 "Signal", "ClockSignal", "ResetSignal",
15 "Statement", "Assign", "Assert", "Assume", "Switch", "Delay", "Tick",
16 "Passive", "ValueKey", "ValueDict", "ValueSet", "SignalKey", "SignalDict",
22 """Deterministic Unique IDentifier"""
25 self
.duid
= DUID
.__next
_uid
29 class Value(metaclass
=ABCMeta
):
32 """Ensures that the passed object is an nMigen value. Booleans and integers
33 are automatically wrapped into ``Const``."""
34 if isinstance(obj
, Value
):
36 elif isinstance(obj
, (bool, int)):
39 raise TypeError("Object '{!r}' is not an nMigen value".format(obj
))
41 def __init__(self
, src_loc_at
=0):
43 self
.src_loc
= tracer
.get_src_loc(1 + src_loc_at
)
46 raise TypeError("Attempted to convert nMigen value to boolean")
49 return Operator("~", [self
])
51 return Operator("-", [self
])
53 def __add__(self
, other
):
54 return Operator("+", [self
, other
])
55 def __radd__(self
, other
):
56 return Operator("+", [other
, self
])
57 def __sub__(self
, other
):
58 return Operator("-", [self
, other
])
59 def __rsub__(self
, other
):
60 return Operator("-", [other
, self
])
61 def __mul__(self
, other
):
62 return Operator("*", [self
, other
])
63 def __rmul__(self
, other
):
64 return Operator("*", [other
, self
])
65 def __mod__(self
, other
):
66 return Operator("%", [self
, other
])
67 def __rmod__(self
, other
):
68 return Operator("%", [other
, self
])
69 def __div__(self
, other
):
70 return Operator("/", [self
, other
])
71 def __rdiv__(self
, other
):
72 return Operator("/", [other
, self
])
73 def __lshift__(self
, other
):
74 return Operator("<<", [self
, other
])
75 def __rlshift__(self
, other
):
76 return Operator("<<", [other
, self
])
77 def __rshift__(self
, other
):
78 return Operator(">>", [self
, other
])
79 def __rrshift__(self
, other
):
80 return Operator(">>", [other
, self
])
81 def __and__(self
, other
):
82 return Operator("&", [self
, other
])
83 def __rand__(self
, other
):
84 return Operator("&", [other
, self
])
85 def __xor__(self
, other
):
86 return Operator("^", [self
, other
])
87 def __rxor__(self
, other
):
88 return Operator("^", [other
, self
])
89 def __or__(self
, other
):
90 return Operator("|", [self
, other
])
91 def __ror__(self
, other
):
92 return Operator("|", [other
, self
])
94 def __eq__(self
, other
):
95 return Operator("==", [self
, other
])
96 def __ne__(self
, other
):
97 return Operator("!=", [self
, other
])
98 def __lt__(self
, other
):
99 return Operator("<", [self
, other
])
100 def __le__(self
, other
):
101 return Operator("<=", [self
, other
])
102 def __gt__(self
, other
):
103 return Operator(">", [self
, other
])
104 def __ge__(self
, other
):
105 return Operator(">=", [self
, other
])
108 return self
.shape()[0]
110 def __getitem__(self
, key
):
112 if isinstance(key
, int):
113 if key
not in range(-n
, n
):
114 raise IndexError("Cannot index {} bits into {}-bit value".format(key
, n
))
117 return Slice(self
, key
, key
+ 1)
118 elif isinstance(key
, slice):
119 start
, stop
, step
= key
.indices(n
)
121 return Cat(self
[i
] for i
in range(start
, stop
, step
))
122 return Slice(self
, start
, stop
)
124 raise TypeError("Cannot index value with {}".format(repr(key
)))
127 """Conversion to boolean.
132 Output ``Value``. If any bits are set, returns ``1``, else ``0``.
134 return Operator("b", [self
])
136 def part(self
, offset
, width
):
137 """Indexed part-select.
139 Selects a constant width but variable offset part of a ``Value``.
144 start point of the selected bits
146 number of selected bits
151 Selected part of the ``Value``
153 return Part(self
, offset
, width
)
161 Value to be assigned.
166 Assignment statement that can be used in combinatorial or synchronous context.
168 return Assign(self
, value
)
172 """Bit length and signedness of a value.
177 Number of bits required to store `v` or available in `v`, followed by
178 whether `v` has a sign bit (included in the bit count).
182 >>> Value.shape(Signal(8))
184 >>> Value.shape(C(0xaa))
189 def _lhs_signals(self
):
190 raise TypeError("Value {!r} cannot be used in assignments".format(self
))
193 def _rhs_signals(self
):
197 raise TypeError("Value {!r} cannot be evaluated as constant".format(self
))
203 """A constant, literal integer value.
208 shape : int or tuple or None
209 Either an integer `bits` or a tuple `(bits, signed)`
210 specifying the number of bits in this `Const` and whether it is
211 signed (can represent negative values). `shape` defaults
212 to the minimum width and signedness of `value`.
222 def normalize(value
, shape
):
223 nbits
, signed
= shape
224 mask
= (1 << nbits
) - 1
226 if signed
and value
>> (nbits
- 1):
230 def __init__(self
, value
, shape
=None):
231 self
.value
= int(value
)
233 shape
= bits_for(self
.value
), self
.value
< 0
234 if isinstance(shape
, int):
235 shape
= shape
, self
.value
< 0
236 self
.nbits
, self
.signed
= shape
237 if not isinstance(self
.nbits
, int) or self
.nbits
< 0:
238 raise TypeError("Width must be a non-negative integer, not '{!r}'", self
.nbits
)
239 self
.value
= self
.normalize(self
.value
, shape
)
242 return self
.nbits
, self
.signed
244 def _rhs_signals(self
):
251 return "(const {}'{}d{})".format(self
.nbits
, "s" if self
.signed
else "", self
.value
)
254 C
= Const
# shorthand
257 class Operator(Value
):
258 def __init__(self
, op
, operands
, src_loc_at
=0):
259 super().__init
__(src_loc_at
=1 + src_loc_at
)
261 self
.operands
= [Value
.wrap(o
) for o
in operands
]
264 def _bitwise_binary_shape(a_shape
, b_shape
):
265 a_bits
, a_sign
= a_shape
266 b_bits
, b_sign
= b_shape
267 if not a_sign
and not b_sign
:
268 # both operands unsigned
269 return max(a_bits
, b_bits
), False
270 elif a_sign
and b_sign
:
271 # both operands signed
272 return max(a_bits
, b_bits
), True
273 elif not a_sign
and b_sign
:
274 # first operand unsigned (add sign bit), second operand signed
275 return max(a_bits
+ 1, b_bits
), True
277 # first signed, second operand unsigned (add sign bit)
278 return max(a_bits
, b_bits
+ 1), True
281 op_shapes
= list(map(lambda x
: x
.shape(), self
.operands
))
282 if len(op_shapes
) == 1:
283 (a_bits
, a_sign
), = op_shapes
284 if self
.op
in ("+", "~"):
285 return a_bits
, a_sign
288 return a_bits
+ 1, True
290 return a_bits
, a_sign
293 elif len(op_shapes
) == 2:
294 (a_bits
, a_sign
), (b_bits
, b_sign
) = op_shapes
295 if self
.op
== "+" or self
.op
== "-":
296 bits
, sign
= self
._bitwise
_binary
_shape
(*op_shapes
)
297 return bits
+ 1, sign
299 if not a_sign
and not b_sign
:
300 # both operands unsigned
301 return a_bits
+ b_bits
, False
302 if a_sign
and b_sign
:
303 # both operands signed
304 return a_bits
+ b_bits
- 1, True
305 # one operand signed, the other unsigned (add sign bit)
306 return a_bits
+ b_bits
+ 1 - 1, True
307 if self
.op
in ("<", "<=", "==", "!=", ">", ">=", "b"):
309 if self
.op
in ("&", "^", "|"):
310 return self
._bitwise
_binary
_shape
(*op_shapes
)
313 extra
= 2 ** (b_bits
- 1) - 1
315 extra
= 2 ** (b_bits
) - 1
316 return a_bits
+ extra
, a_sign
319 extra
= 2 ** (b_bits
- 1)
322 return a_bits
+ extra
, a_sign
323 elif len(op_shapes
) == 3:
325 s_shape
, a_shape
, b_shape
= op_shapes
326 return self
._bitwise
_binary
_shape
(a_shape
, b_shape
)
327 raise NotImplementedError("Operator {}/{} not implemented"
328 .format(self
.op
, len(op_shapes
))) # :nocov:
330 def _rhs_signals(self
):
331 return union(op
._rhs
_signals
() for op
in self
.operands
)
334 return "({} {})".format(self
.op
, " ".join(map(repr, self
.operands
)))
337 def Mux(sel
, val1
, val0
):
338 """Choose between two values.
351 Output ``Value``. If ``sel`` is asserted, the Mux returns ``val1``, else ``val0``.
353 return Operator("m", [sel
, val1
, val0
], src_loc_at
=1)
357 def __init__(self
, value
, start
, end
):
358 if not isinstance(start
, int):
359 raise TypeError("Slice start must be an integer, not '{!r}'".format(start
))
360 if not isinstance(end
, int):
361 raise TypeError("Slice end must be an integer, not '{!r}'".format(end
))
364 if start
not in range(-(n
+1), n
+1):
365 raise IndexError("Cannot start slice {} bits into {}-bit value".format(start
, n
))
368 if end
not in range(-(n
+1), n
+1):
369 raise IndexError("Cannot end slice {} bits into {}-bit value".format(end
, n
))
373 raise IndexError("Slice start {} must be less than slice end {}".format(start
, end
))
376 self
.value
= Value
.wrap(value
)
381 return self
.end
- self
.start
, False
383 def _lhs_signals(self
):
384 return self
.value
._lhs
_signals
()
386 def _rhs_signals(self
):
387 return self
.value
._rhs
_signals
()
390 return "(slice {} {}:{})".format(repr(self
.value
), self
.start
, self
.end
)
394 def __init__(self
, value
, offset
, width
):
395 if not isinstance(width
, int) or width
< 0:
396 raise TypeError("Part width must be a non-negative integer, not '{!r}'".format(width
))
400 self
.offset
= Value
.wrap(offset
)
404 return self
.width
, False
406 def _lhs_signals(self
):
407 return self
.value
._lhs
_signals
()
409 def _rhs_signals(self
):
410 return self
.value
._rhs
_signals
() | self
.offset
._rhs
_signals
()
413 return "(part {} {} {})".format(repr(self
.value
), repr(self
.offset
), self
.width
)
417 """Concatenate values.
419 Form a compound ``Value`` from several smaller ones by concatenation.
420 The first argument occupies the lower bits of the result.
421 The return value can be used on either side of an assignment, that
422 is, the concatenated value can be used as an argument on the RHS or
423 as a target on the LHS. If it is used on the LHS, it must solely
424 consist of ``Signal`` s, slices of ``Signal`` s, and other concatenations
425 meeting these properties. The bit length of the return value is the sum of
426 the bit lengths of the arguments::
428 len(Cat(args)) == sum(len(arg) for arg in args)
432 *args : Values or iterables of Values, inout
433 ``Value`` s to be concatenated.
438 Resulting ``Value`` obtained by concatentation.
440 def __init__(self
, *args
):
442 self
.parts
= [Value
.wrap(v
) for v
in flatten(args
)]
445 return sum(len(part
) for part
in self
.parts
), False
447 def _lhs_signals(self
):
448 return union(part
._lhs
_signals
() for part
in self
.parts
)
450 def _rhs_signals(self
):
451 return union(part
._rhs
_signals
() for part
in self
.parts
)
455 for part
in reversed(self
.parts
):
457 value |
= part
._as
_const
()
461 return "(cat {})".format(" ".join(map(repr, self
.parts
)))
467 An input value is replicated (repeated) several times
468 to be used on the RHS of assignments::
470 len(Repl(s, n)) == len(s) * n
475 Input value to be replicated.
477 Number of replications.
484 def __init__(self
, value
, count
):
485 if not isinstance(count
, int) or count
< 0:
486 raise TypeError("Replication count must be a non-negative integer, not '{!r}'"
490 self
.value
= Value
.wrap(value
)
494 return len(self
.value
) * self
.count
, False
496 def _rhs_signals(self
):
497 return self
.value
._rhs
_signals
()
500 return "(repl {!r} {})".format(self
.value
, self
.count
)
503 class Signal(Value
, DUID
):
504 """A varying integer value.
508 shape : int or tuple or None
509 Either an integer ``bits`` or a tuple ``(bits, signed)`` specifying the number of bits
510 in this ``Signal`` and whether it is signed (can represent negative values).
511 ``shape`` defaults to 1-bit and non-signed.
513 Name hint for this signal. If ``None`` (default) the name is inferred from the variable
514 name this ``Signal`` is assigned to. Name collisions are automatically resolved by
515 prepending names of objects that contain this ``Signal`` and by appending integer
518 Reset (synchronous) or default (combinatorial) value.
519 When this ``Signal`` is assigned to in synchronous context and the corresponding clock
520 domain is reset, the ``Signal`` assumes the given value. When this ``Signal`` is unassigned
521 in combinatorial context (due to conditional assignments not being taken), the ``Signal``
522 assumes its ``reset`` value. Defaults to 0.
524 If ``True``, do not generate reset logic for this ``Signal`` in synchronous statements.
525 The ``reset`` value is only used as a combinatorial default or as the initial value.
526 Defaults to ``False``.
529 If ``shape`` is ``None``, the signal bit width and signedness are
530 determined by the integer range given by ``min`` (inclusive,
531 defaults to 0) and ``max`` (exclusive, defaults to 2).
533 Dictionary of synthesis attributes.
535 A function converting integer signal values to human-readable strings (e.g. FSM state
548 def __init__(self
, shape
=None, name
=None, reset
=0, reset_less
=False, min=None, max=None,
549 attrs
=None, decoder
=None, src_loc_at
=0):
550 super().__init
__(src_loc_at
=src_loc_at
)
554 name
= tracer
.get_var_name(depth
=2 + src_loc_at
)
555 except tracer
.NameNotFound
:
564 max -= 1 # make both bounds inclusive
566 raise ValueError("Lower bound {} should be less than higher bound {}"
568 self
.signed
= min < 0 or max < 0
569 self
.nbits
= builtins
.max(bits_for(min, self
.signed
), bits_for(max, self
.signed
))
572 if not (min is None and max is None):
573 raise ValueError("Only one of bits/signedness or bounds may be specified")
574 if isinstance(shape
, int):
575 self
.nbits
, self
.signed
= shape
, False
577 self
.nbits
, self
.signed
= shape
579 if not isinstance(self
.nbits
, int) or self
.nbits
< 0:
580 raise TypeError("Width must be a non-negative integer, not '{!r}'".format(self
.nbits
))
581 self
.reset
= int(reset
)
582 self
.reset_less
= bool(reset_less
)
584 self
.attrs
= OrderedDict(() if attrs
is None else attrs
)
585 self
.decoder
= decoder
588 def like(cls
, other
, src_loc_at
=0, **kwargs
):
589 """Create Signal based on another.
594 Object to base this Signal on.
596 kw
= dict(shape
=cls
.wrap(other
).shape(),
597 name
=tracer
.get_var_name(depth
=2 + src_loc_at
))
598 if isinstance(other
, cls
):
599 kw
.update(reset
=other
.reset
, reset_less
=other
.reset_less
,
600 attrs
=other
.attrs
, decoder
=other
.decoder
)
602 return cls(**kw
, src_loc_at
=1 + src_loc_at
)
605 return self
.nbits
, self
.signed
607 def _lhs_signals(self
):
608 return ValueSet((self
,))
610 def _rhs_signals(self
):
611 return ValueSet((self
,))
614 return "(sig {})".format(self
.name
)
617 class ClockSignal(Value
):
618 """Clock signal for a clock domain.
620 Any ``ClockSignal`` is equivalent to ``cd.clk`` for a clock domain with the corresponding name.
621 All of these signals ultimately refer to the same signal, but they can be manipulated
622 independently of the clock domain, even before the clock domain is created.
627 Clock domain to obtain a clock signal for. Defaults to ``"sync"``.
629 def __init__(self
, domain
="sync"):
631 if not isinstance(domain
, str):
632 raise TypeError("Clock domain name must be a string, not '{!r}'".format(domain
))
638 def _rhs_signals(self
):
639 raise NotImplementedError("ClockSignal must be lowered to a concrete signal") # :nocov:
642 return "(clk {})".format(self
.domain
)
645 class ResetSignal(Value
):
646 """Reset signal for a clock domain.
648 Any ``ResetSignal`` is equivalent to ``cd.rst`` for a clock domain with the corresponding name.
649 All of these signals ultimately refer to the same signal, but they can be manipulated
650 independently of the clock domain, even before the clock domain is created.
655 Clock domain to obtain a reset signal for. Defaults to ``"sync"``.
656 allow_reset_less : bool
657 If the clock domain is reset-less, act as a constant ``0`` instead of reporting an error.
659 def __init__(self
, domain
="sync", allow_reset_less
=False):
661 if not isinstance(domain
, str):
662 raise TypeError("Clock domain name must be a string, not '{!r}'".format(domain
))
664 self
.allow_reset_less
= allow_reset_less
669 def _rhs_signals(self
):
670 raise NotImplementedError("ResetSignal must be lowered to a concrete signal") # :nocov:
673 return "(rst {})".format(self
.domain
)
676 class Array(MutableSequence
):
677 """Addressable multiplexer.
679 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
682 The array proxy can be used as an ordinary ``Value``, i.e. participate in calculations and
683 assignments, provided that all elements of the array are values. The array proxy also supports
684 attribute access and further indexing, each returning another array proxy; this means that
685 the results of indexing into arrays, arrays of records, and arrays of arrays can all
686 be used as first-class values.
688 It is an error to change an array or any of its elements after an array proxy was created.
689 Changing the array directly will raise an exception. However, it is not possible to detect
690 the elements being modified; if an element's attribute or element is modified after the proxy
691 for it has been created, the proxy will refer to stale data.
698 gpios = Array(Signal() for _ in range(10))
700 m.d.sync += gpios[bus.adr].eq(bus.dat_w)
702 m.d.sync += bus.dat_r.eq(gpios[bus.adr])
704 Multidimensional array::
706 mult = Array(Array(x * y for y in range(10)) for x in range(10))
710 m.d.comb += r.eq(mult[a][b])
718 buses = Array(Record(layout) for busno in range(4))
719 master = Record(layout)
721 buses[sel].re.eq(master.re),
722 master.dat_r.eq(buses[sel].dat_r),
725 def __init__(self
, iterable
=()):
726 self
._inner
= list(iterable
)
727 self
._proxy
_at
= None
730 def __getitem__(self
, index
):
731 if isinstance(index
, Value
):
733 self
._proxy
_at
= tracer
.get_src_loc()
734 self
._mutable
= False
735 return ArrayProxy(self
, index
)
737 return self
._inner
[index
]
740 return len(self
._inner
)
742 def _check_mutability(self
):
743 if not self
._mutable
:
744 raise ValueError("Array can no longer be mutated after it was indexed with a value "
745 "at {}:{}".format(*self
._proxy
_at
))
747 def __setitem__(self
, index
, value
):
748 self
._check
_mutability
()
749 self
._inner
[index
] = value
751 def __delitem__(self
, index
):
752 self
._check
_mutability
()
753 del self
._inner
[index
]
755 def insert(self
, index
, value
):
756 self
._check
_mutability
()
757 self
._inner
.insert(index
, value
)
760 return "(array{} [{}])".format(" mutable" if self
._mutable
else "",
761 ", ".join(map(repr, self
._inner
)))
764 class ArrayProxy(Value
):
765 def __init__(self
, elems
, index
):
766 super().__init
__(src_loc_at
=1)
768 self
.index
= Value
.wrap(index
)
770 def __getattr__(self
, attr
):
771 return ArrayProxy([getattr(elem
, attr
) for elem
in self
.elems
], self
.index
)
773 def __getitem__(self
, index
):
774 return ArrayProxy([ elem
[index
] for elem
in self
.elems
], self
.index
)
776 def _iter_as_values(self
):
777 return (Value
.wrap(elem
) for elem
in self
.elems
)
780 bits
, sign
= 0, False
781 for elem_bits
, elem_sign
in (elem
.shape() for elem
in self
._iter
_as
_values
()):
782 bits
= max(bits
, elem_bits
+ elem_sign
)
783 sign
= max(sign
, elem_sign
)
786 def _lhs_signals(self
):
787 signals
= union((elem
._lhs
_signals
() for elem
in self
._iter
_as
_values
()), start
=ValueSet())
790 def _rhs_signals(self
):
791 signals
= union((elem
._rhs
_signals
() for elem
in self
._iter
_as
_values
()), start
=ValueSet())
792 return self
.index
._rhs
_signals
() | signals
795 return "(proxy (array [{}]) {!r})".format(", ".join(map(repr, self
.elems
)), self
.index
)
798 class _StatementList(list):
800 return "({})".format(" ".join(map(repr, self
)))
806 if isinstance(obj
, Iterable
):
807 return _StatementList(sum((Statement
.wrap(e
) for e
in obj
), []))
809 if isinstance(obj
, Statement
):
810 return _StatementList([obj
])
812 raise TypeError("Object '{!r}' is not an nMigen statement".format(obj
))
815 class Assign(Statement
):
816 def __init__(self
, lhs
, rhs
):
817 self
.lhs
= Value
.wrap(lhs
)
818 self
.rhs
= Value
.wrap(rhs
)
820 def _lhs_signals(self
):
821 return self
.lhs
._lhs
_signals
()
823 def _rhs_signals(self
):
824 return self
.lhs
._rhs
_signals
() | self
.rhs
._rhs
_signals
()
827 return "(eq {!r} {!r})".format(self
.lhs
, self
.rhs
)
830 class Assert(Statement
):
831 def __init__(self
, test
, _check
=None, _en
=None):
832 self
.test
= Value
.wrap(test
)
835 if self
._check
is None:
836 self
._check
= Signal(reset_less
=True, name
="$assert$check")
837 self
._check
.src_loc
= self
.test
.src_loc
841 self
._en
= Signal(reset_less
=True, name
="$assert$en")
842 self
._en
.src_loc
= self
.test
.src_loc
844 def _lhs_signals(self
):
845 return ValueSet((self
._en
, self
._check
))
847 def _rhs_signals(self
):
848 return self
.test
._rhs
_signals
()
851 return "(assert {!r})".format(self
.test
)
854 class Assume(Statement
):
855 def __init__(self
, test
, _check
=None, _en
=None):
856 self
.test
= Value
.wrap(test
)
859 if self
._check
is None:
860 self
._check
= Signal(reset_less
=True, name
="$assume$check")
861 self
._check
.src_loc
= self
.test
.src_loc
865 self
._en
= Signal(reset_less
=True, name
="$assume$en")
866 self
._en
.src_loc
= self
.test
.src_loc
868 def _lhs_signals(self
):
869 return ValueSet((self
._en
, self
._check
))
871 def _rhs_signals(self
):
872 return self
.test
._rhs
_signals
()
875 return "(assume {!r})".format(self
.test
)
878 class Switch(Statement
):
879 def __init__(self
, test
, cases
):
880 self
.test
= Value
.wrap(test
)
881 self
.cases
= OrderedDict()
882 for key
, stmts
in cases
.items():
883 if isinstance(key
, (bool, int)):
884 key
= "{:0{}b}".format(key
, len(self
.test
))
885 assert len(key
) <= len(self
.test
)
886 elif isinstance(key
, str):
887 assert len(key
) == len(self
.test
)
889 raise TypeError("Object '{!r}' cannot be used as a switch key"
891 if not isinstance(stmts
, Iterable
):
893 self
.cases
[key
] = Statement
.wrap(stmts
)
895 def _lhs_signals(self
):
896 signals
= union((s
._lhs
_signals
() for ss
in self
.cases
.values() for s
in ss
),
900 def _rhs_signals(self
):
901 signals
= union((s
._rhs
_signals
() for ss
in self
.cases
.values() for s
in ss
),
903 return self
.test
._rhs
_signals
() | signals
906 cases
= ["(case {} {})".format(key
, " ".join(map(repr, stmts
)))
907 for key
, stmts
in self
.cases
.items()]
908 return "(switch {!r} {})".format(self
.test
, " ".join(cases
))
911 class Delay(Statement
):
912 def __init__(self
, interval
=None):
913 self
.interval
= None if interval
is None else float(interval
)
915 def _rhs_signals(self
):
919 if self
.interval
is None:
922 return "(delay {:.3}us)".format(self
.interval
* 10e6
)
925 class Tick(Statement
):
926 def __init__(self
, domain
="sync"):
927 self
.domain
= str(domain
)
929 def _rhs_signals(self
):
933 return "(tick {})".format(self
.domain
)
936 class Passive(Statement
):
937 def _rhs_signals(self
):
944 class _MappedKeyCollection(metaclass
=ABCMeta
):
946 def _map_key(self
, key
):
950 def _unmap_key(self
, key
):
954 class _MappedKeyDict(MutableMapping
, _MappedKeyCollection
):
955 def __init__(self
, pairs
=()):
956 self
._storage
= OrderedDict()
957 for key
, value
in pairs
:
960 def __getitem__(self
, key
):
961 key
= None if key
is None else self
._map
_key
(key
)
962 return self
._storage
[key
]
964 def __setitem__(self
, key
, value
):
965 key
= None if key
is None else self
._map
_key
(key
)
966 self
._storage
[key
] = value
968 def __delitem__(self
, key
):
969 key
= None if key
is None else self
._map
_key
(key
)
970 del self
._storage
[key
]
973 for key
in self
._storage
:
977 yield self
._unmap
_key
(key
)
979 def __eq__(self
, other
):
980 if not isinstance(other
, type(self
)):
982 if len(self
) != len(other
):
984 for ak
, bk
in zip(sorted(self
._storage
), sorted(other
._storage
)):
987 if self
._storage
[ak
] != other
._storage
[bk
]:
992 return len(self
._storage
)
995 pairs
= ["({!r}, {!r})".format(k
, v
) for k
, v
in self
.items()]
996 return "{}.{}([{}])".format(type(self
).__module
__, type(self
).__name
__,
1000 class _MappedKeySet(MutableSet
, _MappedKeyCollection
):
1001 def __init__(self
, elements
=()):
1002 self
._storage
= OrderedDict()
1003 for elem
in elements
:
1006 def add(self
, value
):
1007 self
._storage
[self
._map
_key
(value
)] = None
1009 def update(self
, values
):
1010 for value
in values
:
1013 def discard(self
, value
):
1015 del self
._storage
[self
._map
_key
(value
)]
1017 def __contains__(self
, value
):
1018 return self
._map
_key
(value
) in self
._storage
1021 for key
in [k
for k
in self
._storage
]:
1022 yield self
._unmap
_key
(key
)
1025 return len(self
._storage
)
1028 return "{}.{}({})".format(type(self
).__module
__, type(self
).__name
__,
1029 ", ".join(repr(x
) for x
in self
))
1033 def __init__(self
, value
):
1034 self
.value
= Value
.wrap(value
)
1037 if isinstance(self
.value
, Const
):
1038 return hash(self
.value
.value
)
1039 elif isinstance(self
.value
, Signal
):
1040 return hash(self
.value
.duid
)
1041 elif isinstance(self
.value
, Operator
):
1042 return hash((self
.value
.op
, tuple(ValueKey(o
) for o
in self
.value
.operands
)))
1043 elif isinstance(self
.value
, Slice
):
1044 return hash((ValueKey(self
.value
.value
), self
.value
.start
, self
.value
.end
))
1045 elif isinstance(self
.value
, Part
):
1046 return hash((ValueKey(self
.value
.value
), ValueKey(self
.value
.offset
),
1048 elif isinstance(self
.value
, Cat
):
1049 return hash(tuple(ValueKey(o
) for o
in self
.value
.operands
))
1050 elif isinstance(self
.value
, ArrayProxy
):
1051 return hash((ValueKey(self
.value
.index
),
1052 tuple(ValueKey(e
) for e
in self
.value
._iter
_as
_values
())))
1054 raise TypeError("Object '{!r}' cannot be used as a key in value collections"
1055 .format(self
.value
))
1057 def __eq__(self
, other
):
1058 if type(other
) is not ValueKey
:
1060 if type(self
.value
) is not type(other
.value
):
1063 if isinstance(self
.value
, Const
):
1064 return self
.value
.value
== other
.value
.value
1065 elif isinstance(self
.value
, Signal
):
1066 return self
.value
is other
.value
1067 elif isinstance(self
.value
, Operator
):
1068 return (self
.value
.op
== other
.value
.op
and
1069 len(self
.value
.operands
) == len(other
.value
.operands
) and
1070 all(ValueKey(a
) == ValueKey(b
)
1071 for a
, b
in zip(self
.value
.operands
, other
.value
.operands
)))
1072 elif isinstance(self
.value
, Slice
):
1073 return (ValueKey(self
.value
.value
) == ValueKey(other
.value
.value
) and
1074 self
.value
.start
== other
.value
.start
and
1075 self
.value
.end
== other
.value
.end
)
1076 elif isinstance(self
.value
, Part
):
1077 return (ValueKey(self
.value
.value
) == ValueKey(other
.value
.value
) and
1078 ValueKey(self
.value
.offset
) == ValueKey(other
.value
.offset
) and
1079 self
.value
.width
== other
.value
.width
)
1080 elif isinstance(self
.value
, Cat
):
1081 return all(ValueKey(a
) == ValueKey(b
)
1082 for a
, b
in zip(self
.value
.operands
, other
.value
.operands
))
1083 elif isinstance(self
.value
, ArrayProxy
):
1084 return (ValueKey(self
.value
.index
) == ValueKey(other
.value
.index
) and
1085 len(self
.value
.elems
) == len(other
.value
.elems
) and
1086 all(ValueKey(a
) == ValueKey(b
)
1087 for a
, b
in zip(self
.value
._iter
_as
_values
(),
1088 other
.value
._iter
_as
_values
())))
1090 raise TypeError("Object '{!r}' cannot be used as a key in value collections"
1091 .format(self
.value
))
1093 def __lt__(self
, other
):
1094 if not isinstance(other
, ValueKey
):
1096 if type(self
.value
) != type(other
.value
):
1099 if isinstance(self
.value
, Const
):
1100 return self
.value
< other
.value
1101 elif isinstance(self
.value
, Signal
):
1102 return self
.value
.duid
< other
.value
.duid
1103 elif isinstance(self
.value
, Slice
):
1104 return (ValueKey(self
.value
.value
) < ValueKey(other
.value
.value
) and
1105 self
.value
.start
< other
.value
.start
and
1106 self
.value
.end
< other
.value
.end
)
1108 raise TypeError("Object '{!r}' cannot be used as a key in value collections")
1111 return "<{}.ValueKey {!r}>".format(__name__
, self
.value
)
1114 class ValueDict(_MappedKeyDict
):
1116 _unmap_key
= lambda self
, key
: key
.value
1119 class ValueSet(_MappedKeySet
):
1121 _unmap_key
= lambda self
, key
: key
.value
1125 def __init__(self
, signal
):
1126 if type(signal
) is not Signal
:
1127 raise TypeError("Object '{!r}' is not an nMigen signal".format(signal
))
1128 self
.signal
= signal
1131 return hash(self
.signal
.duid
)
1133 def __eq__(self
, other
):
1134 if type(other
) is not SignalKey
:
1136 return self
.signal
is other
.signal
1138 def __lt__(self
, other
):
1139 if type(other
) is not SignalKey
:
1140 raise TypeError("Object '{!r}' cannot be compared to a SignalKey".format(signal
))
1141 return self
.signal
.duid
< other
.signal
.duid
1144 return "<{}.SignalKey {!r}>".format(__name__
, self
.signal
)
1147 class SignalDict(_MappedKeyDict
):
1148 _map_key
= SignalKey
1149 _unmap_key
= lambda self
, key
: key
.signal
1152 class SignalSet(_MappedKeySet
):
1153 _map_key
= SignalKey
1154 _unmap_key
= lambda self
, key
: key
.signal