add redirection of __Cat__ to allow overrides for more advanced behaviour
[nmigen.git] / nmigen / hdl / ast.py
1 from abc import ABCMeta, abstractmethod
2 import warnings
3 import functools
4 from collections import OrderedDict
5 from collections.abc import Iterable, MutableMapping, MutableSet, MutableSequence
6 from enum import Enum
7 from itertools import chain
8
9 from .. import tracer
10 from .._utils import *
11 from .._unused import *
12
13
14 __all__ = [
15 "Shape", "signed", "unsigned",
16 "Value", "Const", "C", "AnyConst", "AnySeq", "Operator", "Mux", "Part", "Slice", "Cat", "Repl",
17 "Array", "ArrayProxy",
18 "_InternalSwitch", "_InternalAssign", "_InternalRepl", "_InternalCat",
19 "Signal", "ClockSignal", "ResetSignal",
20 "UserValue", "ValueCastable",
21 "Sample", "Past", "Stable", "Rose", "Fell", "Initial",
22 "Statement", "Switch",
23 "Property", "Assign", "Assert", "Assume", "Cover",
24 "ValueKey", "ValueDict", "ValueSet", "SignalKey", "SignalDict", "SignalSet",
25 ]
26
27
28 class DUID:
29 """Deterministic Unique IDentifier."""
30 __next_uid = 0
31 def __init__(self):
32 self.duid = DUID.__next_uid
33 DUID.__next_uid += 1
34
35
36 class Shape:
37 """Bit width and signedness of a value.
38
39 A ``Shape`` can be constructed using:
40 * explicit bit width and signedness;
41 * aliases :func:`signed` and :func:`unsigned`;
42 * casting from a variety of objects.
43
44 A ``Shape`` can be cast from:
45 * an integer, where the integer specifies the bit width;
46 * a range, where the result is wide enough to represent any element of the range, and is
47 signed if any element of the range is signed;
48 * an :class:`Enum` with all integer members or :class:`IntEnum`, where the result is wide
49 enough to represent any member of the enumeration, and is signed if any member of
50 the enumeration is signed.
51
52 Parameters
53 ----------
54 width : int
55 The number of bits in the representation, including the sign bit (if any).
56 signed : bool
57 If ``False``, the value is unsigned. If ``True``, the value is signed two's complement.
58 """
59 def __init__(self, width=1, signed=False):
60 if not isinstance(width, int) or width < 0:
61 raise TypeError("Width must be a non-negative integer, not {!r}"
62 .format(width))
63 self.width = width
64 self.signed = signed
65
66 def __iter__(self):
67 return iter((self.width, self.signed))
68
69 @staticmethod
70 def cast(obj, *, src_loc_at=0):
71 if isinstance(obj, Shape):
72 return obj
73 if isinstance(obj, int):
74 return Shape(obj)
75 if isinstance(obj, tuple):
76 width, signed = obj
77 warnings.warn("instead of `{tuple}`, use `{constructor}({width})`"
78 .format(constructor="signed" if signed else "unsigned", width=width,
79 tuple=obj),
80 DeprecationWarning, stacklevel=2 + src_loc_at)
81 return Shape(width, signed)
82 if isinstance(obj, range):
83 if len(obj) == 0:
84 return Shape(0, obj.start < 0)
85 signed = obj.start < 0 or (obj.stop - obj.step) < 0
86 width = max(bits_for(obj.start, signed),
87 bits_for(obj.stop - obj.step, signed))
88 return Shape(width, signed)
89 if isinstance(obj, type) and issubclass(obj, Enum):
90 min_value = min(member.value for member in obj)
91 max_value = max(member.value for member in obj)
92 if not isinstance(min_value, int) or not isinstance(max_value, int):
93 raise TypeError("Only enumerations with integer values can be used "
94 "as value shapes")
95 signed = min_value < 0 or max_value < 0
96 width = max(bits_for(min_value, signed), bits_for(max_value, signed))
97 return Shape(width, signed)
98 raise TypeError("Object {!r} cannot be used as value shape".format(obj))
99
100 def __repr__(self):
101 if self.signed:
102 return "signed({})".format(self.width)
103 else:
104 return "unsigned({})".format(self.width)
105
106 def __eq__(self, other):
107 if isinstance(other, tuple) and len(other) == 2:
108 width, signed = other
109 if isinstance(width, int) and isinstance(signed, bool):
110 return self.width == width and self.signed == signed
111 else:
112 raise TypeError("Shapes may be compared with other Shapes and (int, bool) tuples, "
113 "not {!r}"
114 .format(other))
115 if not isinstance(other, Shape):
116 raise TypeError("Shapes may be compared with other Shapes and (int, bool) tuples, "
117 "not {!r}"
118 .format(other))
119 return self.width == other.width and self.signed == other.signed
120
121
122 def unsigned(width):
123 """Shorthand for ``Shape(width, signed=False)``."""
124 return Shape(width, signed=False)
125
126
127 def signed(width):
128 """Shorthand for ``Shape(width, signed=True)``."""
129 return Shape(width, signed=True)
130
131
132 class Value(metaclass=ABCMeta):
133 @staticmethod
134 def cast(obj):
135 """Converts ``obj`` to an nMigen value.
136
137 Booleans and integers are wrapped into a :class:`Const`. Enumerations whose members are
138 all integers are converted to a :class:`Const` with a shape that fits every member.
139 """
140 if isinstance(obj, Value):
141 return obj
142 if isinstance(obj, int):
143 return Const(obj)
144 if isinstance(obj, Enum):
145 return Const(obj.value, Shape.cast(type(obj)))
146 if isinstance(obj, ValueCastable):
147 return obj.as_value()
148 raise TypeError("Object {!r} cannot be converted to an nMigen value".format(obj))
149
150 def __init__(self, *, src_loc_at=0):
151 super().__init__()
152 self.src_loc = tracer.get_src_loc(1 + src_loc_at)
153
154 def __Repl__(self, count, *, src_loc_at=0):
155 return _InternalRepl(self, count, src_loc_at=src_loc_at)
156
157 def __Cat__(self, *args, src_loc_at=0):
158 args = [self] + list(args)
159 return _InternalCat(*args, src_loc_at=src_loc_at)
160
161 def __Mux__(self, val1, val0):
162 return _InternalMux(self, val1, val0)
163
164 def __Switch__(self, cases, *, src_loc=None, src_loc_at=0, case_src_locs={}):
165 return _InternalSwitch(self, cases, src_loc=src_loc,
166 src_loc_at=src_loc_at,
167 case_src_locs=case_src_locs)
168
169 def __Assign__(self, rhs, *, src_loc_at=0):
170 return _InternalAssign(self, rhs, src_loc_at=src_loc_at)
171
172 def __bool__(self):
173 raise TypeError("Attempted to convert nMigen value to Python boolean")
174
175 def __invert__(self):
176 return Operator("~", [self])
177 def __neg__(self):
178 return Operator("-", [self])
179
180 def __add__(self, other):
181 return Operator("+", [self, other])
182 def __radd__(self, other):
183 return Operator("+", [other, self])
184 def __sub__(self, other):
185 return Operator("-", [self, other])
186 def __rsub__(self, other):
187 return Operator("-", [other, self])
188
189 def __mul__(self, other):
190 return Operator("*", [self, other])
191 def __rmul__(self, other):
192 return Operator("*", [other, self])
193
194 def __check_divisor(self):
195 width, signed = self.shape()
196 if signed:
197 # Python's division semantics and Verilog's division semantics differ for negative
198 # divisors (Python uses div/mod, Verilog uses quo/rem); for now, avoid the issue
199 # completely by prohibiting such division operations.
200 raise NotImplementedError("Division by a signed value is not supported")
201 def __mod__(self, other):
202 other = Value.cast(other)
203 other.__check_divisor()
204 return Operator("%", [self, other])
205 def __rmod__(self, other):
206 self.__check_divisor()
207 return Operator("%", [other, self])
208 def __floordiv__(self, other):
209 other = Value.cast(other)
210 other.__check_divisor()
211 return Operator("//", [self, other])
212 def __rfloordiv__(self, other):
213 self.__check_divisor()
214 return Operator("//", [other, self])
215
216 def __check_shamt(self):
217 width, signed = self.shape()
218 if signed:
219 # Neither Python nor HDLs implement shifts by negative values; prohibit any shifts
220 # by a signed value to make sure the shift amount can always be interpreted as
221 # an unsigned value.
222 raise TypeError("Shift amount must be unsigned")
223 def __lshift__(self, other):
224 other = Value.cast(other)
225 other.__check_shamt()
226 return Operator("<<", [self, other])
227 def __rlshift__(self, other):
228 self.__check_shamt()
229 return Operator("<<", [other, self])
230 def __rshift__(self, other):
231 other = Value.cast(other)
232 other.__check_shamt()
233 return Operator(">>", [self, other])
234 def __rrshift__(self, other):
235 self.__check_shamt()
236 return Operator(">>", [other, self])
237
238 def __and__(self, other):
239 return Operator("&", [self, other])
240 def __rand__(self, other):
241 return Operator("&", [other, self])
242 def __xor__(self, other):
243 return Operator("^", [self, other])
244 def __rxor__(self, other):
245 return Operator("^", [other, self])
246 def __or__(self, other):
247 return Operator("|", [self, other])
248 def __ror__(self, other):
249 return Operator("|", [other, self])
250
251 def __eq__(self, other):
252 return Operator("==", [self, other])
253 def __ne__(self, other):
254 return Operator("!=", [self, other])
255 def __lt__(self, other):
256 return Operator("<", [self, other])
257 def __le__(self, other):
258 return Operator("<=", [self, other])
259 def __gt__(self, other):
260 return Operator(">", [self, other])
261 def __ge__(self, other):
262 return Operator(">=", [self, other])
263
264 def __abs__(self):
265 width, signed = self.shape()
266 if signed:
267 return Mux(self >= 0, self, -self)
268 else:
269 return self
270
271 def __len__(self):
272 return self.shape().width
273
274 def __getitem__(self, key):
275 n = len(self)
276 if isinstance(key, int):
277 if key not in range(-n, n):
278 raise IndexError(f"Index {key} is out of bounds for a {n}-bit value")
279 if key < 0:
280 key += n
281 return Slice(self, key, key + 1)
282 elif isinstance(key, slice):
283 start, stop, step = key.indices(n)
284 if step != 1:
285 return Cat(self[i] for i in range(start, stop, step))
286 return Slice(self, start, stop)
287 else:
288 raise TypeError("Cannot index value with {}".format(repr(key)))
289
290 def as_unsigned(self):
291 """Conversion to unsigned.
292
293 Returns
294 -------
295 Value, out
296 This ``Value`` reinterpreted as a unsigned integer.
297 """
298 return Operator("u", [self])
299
300 def as_signed(self):
301 """Conversion to signed.
302
303 Returns
304 -------
305 Value, out
306 This ``Value`` reinterpreted as a signed integer.
307 """
308 return Operator("s", [self])
309
310 def bool(self):
311 """Conversion to boolean.
312
313 Returns
314 -------
315 Value, out
316 ``1`` if any bits are set, ``0`` otherwise.
317 """
318 return Operator("b", [self])
319
320 def any(self):
321 """Check if any bits are ``1``.
322
323 Returns
324 -------
325 Value, out
326 ``1`` if any bits are set, ``0`` otherwise.
327 """
328 return Operator("r|", [self])
329
330 def all(self):
331 """Check if all bits are ``1``.
332
333 Returns
334 -------
335 Value, out
336 ``1`` if all bits are set, ``0`` otherwise.
337 """
338 return Operator("r&", [self])
339
340 def xor(self):
341 """Compute pairwise exclusive-or of every bit.
342
343 Returns
344 -------
345 Value, out
346 ``1`` if an odd number of bits are set, ``0`` if an even number of bits are set.
347 """
348 return Operator("r^", [self])
349
350 def implies(premise, conclusion):
351 """Implication.
352
353 Returns
354 -------
355 Value, out
356 ``0`` if ``premise`` is true and ``conclusion`` is not, ``1`` otherwise.
357 """
358 return ~premise | conclusion
359
360 def bit_select(self, offset, width):
361 """Part-select with bit granularity.
362
363 Selects a constant width but variable offset part of a ``Value``, such that successive
364 parts overlap by all but 1 bit.
365
366 Parameters
367 ----------
368 offset : Value, int
369 Index of first selected bit.
370 width : int
371 Number of selected bits.
372
373 Returns
374 -------
375 Part, out
376 Selected part of the ``Value``
377 """
378 offset = Value.cast(offset)
379 if type(offset) is Const and isinstance(width, int):
380 return self[offset.value:offset.value + width]
381 return Part(self, offset, width, stride=1, src_loc_at=1)
382
383 def word_select(self, offset, width):
384 """Part-select with word granularity.
385
386 Selects a constant width but variable offset part of a ``Value``, such that successive
387 parts do not overlap.
388
389 Parameters
390 ----------
391 offset : Value, int
392 Index of first selected word.
393 width : int
394 Number of selected bits.
395
396 Returns
397 -------
398 Part, out
399 Selected part of the ``Value``
400 """
401 offset = Value.cast(offset)
402 if type(offset) is Const and isinstance(width, int):
403 return self[offset.value * width:(offset.value + 1) * width]
404 return Part(self, offset, width, stride=width, src_loc_at=1)
405
406 def matches(self, *patterns):
407 """Pattern matching.
408
409 Matches against a set of patterns, which may be integers or bit strings, recognizing
410 the same grammar as ``Case()``.
411
412 Parameters
413 ----------
414 patterns : int or str
415 Patterns to match against.
416
417 Returns
418 -------
419 Value, out
420 ``1`` if any pattern matches the value, ``0`` otherwise.
421 """
422 matches = []
423 for pattern in patterns:
424 if not isinstance(pattern, (int, str, Enum)):
425 raise SyntaxError("Match pattern must be an integer, a string, or an enumeration, "
426 "not {!r}"
427 .format(pattern))
428 if isinstance(pattern, str) and any(bit not in "01- \t" for bit in pattern):
429 raise SyntaxError("Match pattern '{}' must consist of 0, 1, and - (don't care) "
430 "bits, and may include whitespace"
431 .format(pattern))
432 if (isinstance(pattern, str) and
433 len("".join(pattern.split())) != len(self)):
434 raise SyntaxError("Match pattern '{}' must have the same width as match value "
435 "(which is {})"
436 .format(pattern, len(self)))
437 if isinstance(pattern, int) and bits_for(pattern) > len(self):
438 warnings.warn("Match pattern '{:b}' is wider than match value "
439 "(which has width {}); comparison will never be true"
440 .format(pattern, len(self)),
441 SyntaxWarning, stacklevel=3)
442 continue
443 if isinstance(pattern, str):
444 pattern = "".join(pattern.split()) # remove whitespace
445 mask = int(pattern.replace("0", "1").replace("-", "0"), 2)
446 pattern = int(pattern.replace("-", "0"), 2)
447 matches.append((self & mask) == pattern)
448 elif isinstance(pattern, int):
449 matches.append(self == pattern)
450 elif isinstance(pattern, Enum):
451 matches.append(self == pattern.value)
452 else:
453 assert False
454 if not matches:
455 return Const(0)
456 elif len(matches) == 1:
457 return matches[0]
458 else:
459 return Cat(*matches).any()
460
461 def shift_left(self, amount):
462 """Shift left by constant amount.
463
464 Parameters
465 ----------
466 amount : int
467 Amount to shift by.
468
469 Returns
470 -------
471 Value, out
472 If the amount is positive, the input shifted left. Otherwise, the input shifted right.
473 """
474 if not isinstance(amount, int):
475 raise TypeError("Shift amount must be an integer, not {!r}".format(amount))
476 if amount < 0:
477 return self.shift_right(-amount)
478 if self.shape().signed:
479 return Cat(Const(0, amount), self).as_signed()
480 else:
481 return Cat(Const(0, amount), self) # unsigned
482
483 def shift_right(self, amount):
484 """Shift right by constant amount.
485
486 Parameters
487 ----------
488 amount : int
489 Amount to shift by.
490
491 Returns
492 -------
493 Value, out
494 If the amount is positive, the input shifted right. Otherwise, the input shifted left.
495 """
496 if not isinstance(amount, int):
497 raise TypeError("Shift amount must be an integer, not {!r}".format(amount))
498 if amount < 0:
499 return self.shift_left(-amount)
500 if self.shape().signed:
501 return self[amount:].as_signed()
502 else:
503 return self[amount:] # unsigned
504
505 def rotate_left(self, amount):
506 """Rotate left by constant amount.
507
508 Parameters
509 ----------
510 amount : int
511 Amount to rotate by.
512
513 Returns
514 -------
515 Value, out
516 If the amount is positive, the input rotated left. Otherwise, the input rotated right.
517 """
518 if not isinstance(amount, int):
519 raise TypeError("Rotate amount must be an integer, not {!r}".format(amount))
520 amount %= len(self)
521 return Cat(self[-amount:], self[:-amount]) # meow :3
522
523 def rotate_right(self, amount):
524 """Rotate right by constant amount.
525
526 Parameters
527 ----------
528 amount : int
529 Amount to rotate by.
530
531 Returns
532 -------
533 Value, out
534 If the amount is positive, the input rotated right. Otherwise, the input rotated right.
535 """
536 if not isinstance(amount, int):
537 raise TypeError("Rotate amount must be an integer, not {!r}".format(amount))
538 amount %= len(self)
539 return Cat(self[amount:], self[:amount])
540
541 def eq(self, value):
542 """Assignment.
543
544 Parameters
545 ----------
546 value : Value, in
547 Value to be assigned.
548
549 Returns
550 -------
551 Assign
552 Assignment statement that can be used in combinatorial or synchronous context.
553 """
554 return Assign(self, value, src_loc_at=1)
555
556 @abstractmethod
557 def shape(self):
558 """Bit width and signedness of a value.
559
560 Returns
561 -------
562 Shape
563 See :class:`Shape`.
564
565 Examples
566 --------
567 >>> Signal(8).shape()
568 Shape(width=8, signed=False)
569 >>> Const(0xaa).shape()
570 Shape(width=8, signed=False)
571 """
572 pass # :nocov:
573
574 def _lhs_signals(self):
575 raise TypeError("Value {!r} cannot be used in assignments".format(self))
576
577 @abstractmethod
578 def _rhs_signals(self):
579 pass # :nocov:
580
581 def _as_const(self):
582 raise TypeError("Value {!r} cannot be evaluated as constant".format(self))
583
584 __hash__ = None
585
586
587 @final
588 class Const(Value):
589 """A constant, literal integer value.
590
591 Parameters
592 ----------
593 value : int
594 shape : int or tuple or None
595 Either an integer ``width`` or a tuple ``(width, signed)`` specifying the number of bits
596 in this constant and whether it is signed (can represent negative values).
597 ``shape`` defaults to the minimum possible width and signedness of ``value``.
598
599 Attributes
600 ----------
601 width : int
602 signed : bool
603 """
604 src_loc = None
605
606 @staticmethod
607 def normalize(value, shape):
608 width, signed = shape
609 mask = (1 << width) - 1
610 value &= mask
611 if signed and value >> (width - 1):
612 value |= ~mask
613 return value
614
615 def __init__(self, value, shape=None, *, src_loc_at=0):
616 # We deliberately do not call Value.__init__ here.
617 self.value = int(value)
618 if shape is None:
619 shape = Shape(bits_for(self.value), signed=self.value < 0)
620 elif isinstance(shape, int):
621 shape = Shape(shape, signed=self.value < 0)
622 else:
623 shape = Shape.cast(shape, src_loc_at=1 + src_loc_at)
624 self.width, self.signed = shape
625 self.value = self.normalize(self.value, shape)
626
627 def shape(self):
628 return Shape(self.width, self.signed)
629
630 def _rhs_signals(self):
631 return SignalSet()
632
633 def _as_const(self):
634 return self.value
635
636 def __repr__(self):
637 return "(const {}'{}d{})".format(self.width, "s" if self.signed else "", self.value)
638
639
640 C = Const # shorthand
641
642
643 class AnyValue(Value, DUID):
644 def __init__(self, shape, *, src_loc_at=0):
645 super().__init__(src_loc_at=src_loc_at)
646 self.width, self.signed = Shape.cast(shape, src_loc_at=1 + src_loc_at)
647 if not isinstance(self.width, int) or self.width < 0:
648 raise TypeError("Width must be a non-negative integer, not {!r}"
649 .format(self.width))
650
651 def shape(self):
652 return Shape(self.width, self.signed)
653
654 def _rhs_signals(self):
655 return SignalSet()
656
657
658 @final
659 class AnyConst(AnyValue):
660 def __repr__(self):
661 return "(anyconst {}'{})".format(self.width, "s" if self.signed else "")
662
663
664 @final
665 class AnySeq(AnyValue):
666 def __repr__(self):
667 return "(anyseq {}'{})".format(self.width, "s" if self.signed else "")
668
669
670 @final
671 class Operator(Value):
672 def __init__(self, operator, operands, *, src_loc_at=0):
673 super().__init__(src_loc_at=1 + src_loc_at)
674 self.operator = operator
675 self.operands = [Value.cast(op) for op in operands]
676
677 def shape(self):
678 def _bitwise_binary_shape(a_shape, b_shape):
679 a_bits, a_sign = a_shape
680 b_bits, b_sign = b_shape
681 if not a_sign and not b_sign:
682 # both operands unsigned
683 return Shape(max(a_bits, b_bits), False)
684 elif a_sign and b_sign:
685 # both operands signed
686 return Shape(max(a_bits, b_bits), True)
687 elif not a_sign and b_sign:
688 # first operand unsigned (add sign bit), second operand signed
689 return Shape(max(a_bits + 1, b_bits), True)
690 else:
691 # first signed, second operand unsigned (add sign bit)
692 return Shape(max(a_bits, b_bits + 1), True)
693
694 op_shapes = list(map(lambda x: x.shape(), self.operands))
695 if len(op_shapes) == 1:
696 (a_width, a_signed), = op_shapes
697 if self.operator in ("+", "~"):
698 return Shape(a_width, a_signed)
699 if self.operator == "-":
700 return Shape(a_width + 1, True)
701 if self.operator in ("b", "r|", "r&", "r^"):
702 return Shape(1, False)
703 if self.operator == "u":
704 return Shape(a_width, False)
705 if self.operator == "s":
706 return Shape(a_width, True)
707 elif len(op_shapes) == 2:
708 (a_width, a_signed), (b_width, b_signed) = op_shapes
709 if self.operator in ("+", "-"):
710 width, signed = _bitwise_binary_shape(*op_shapes)
711 return Shape(width + 1, signed)
712 if self.operator == "*":
713 return Shape(a_width + b_width, a_signed or b_signed)
714 if self.operator in ("//", "%"):
715 assert not b_signed
716 return Shape(a_width, a_signed)
717 if self.operator in ("<", "<=", "==", "!=", ">", ">="):
718 return Shape(1, False)
719 if self.operator in ("&", "^", "|"):
720 return _bitwise_binary_shape(*op_shapes)
721 if self.operator == "<<":
722 assert not b_signed
723 return Shape(a_width + 2 ** b_width - 1, a_signed)
724 if self.operator == ">>":
725 assert not b_signed
726 return Shape(a_width, a_signed)
727 elif len(op_shapes) == 3:
728 if self.operator == "m":
729 s_shape, a_shape, b_shape = op_shapes
730 return _bitwise_binary_shape(a_shape, b_shape)
731 raise NotImplementedError("Operator {}/{} not implemented"
732 .format(self.operator, len(op_shapes))) # :nocov:
733
734 def _rhs_signals(self):
735 return union(op._rhs_signals() for op in self.operands)
736
737 def __repr__(self):
738 return "({} {})".format(self.operator, " ".join(map(repr, self.operands)))
739
740
741 def Mux(sel, val1, val0):
742 if isinstance(sel, bool): # one instance where Mux is passed an actual bool
743 sel = Value.cast(sel)
744 return sel.__Mux__(val1, val0)
745
746
747 def _InternalMux(sel, val1, val0):
748 """Choose between two values.
749
750 Parameters
751 ----------
752 sel : Value, in
753 Selector.
754 val1 : Value, in
755 val0 : Value, in
756 Input values.
757
758 Returns
759 -------
760 Value, out
761 Output ``Value``. If ``sel`` is asserted, the Mux returns ``val1``, else ``val0``.
762 """
763 sel = Value.cast(sel)
764 if len(sel) != 1:
765 sel = sel.bool()
766 return Operator("m", [sel, val1, val0])
767
768
769 @final
770 class Slice(Value):
771 def __init__(self, value, start, stop, *, src_loc_at=0):
772 if not isinstance(start, int):
773 raise TypeError("Slice start must be an integer, not {!r}".format(start))
774 if not isinstance(stop, int):
775 raise TypeError("Slice stop must be an integer, not {!r}".format(stop))
776
777 n = len(value)
778 if start not in range(-(n+1), n+1):
779 raise IndexError("Cannot start slice {} bits into {}-bit value".format(start, n))
780 if start < 0:
781 start += n
782 if stop not in range(-(n+1), n+1):
783 raise IndexError("Cannot stop slice {} bits into {}-bit value".format(stop, n))
784 if stop < 0:
785 stop += n
786 if start > stop:
787 raise IndexError("Slice start {} must be less than slice stop {}".format(start, stop))
788
789 super().__init__(src_loc_at=src_loc_at)
790 self.value = Value.cast(value)
791 self.start = int(start)
792 self.stop = int(stop)
793
794 def shape(self):
795 return Shape(self.stop - self.start)
796
797 def _lhs_signals(self):
798 return self.value._lhs_signals()
799
800 def _rhs_signals(self):
801 return self.value._rhs_signals()
802
803 def __repr__(self):
804 return "(slice {} {}:{})".format(repr(self.value), self.start, self.stop)
805
806
807 @final
808 class Part(Value):
809 def __init__(self, value, offset, width, stride=1, *, src_loc_at=0):
810 if not isinstance(width, int) or width < 0:
811 raise TypeError("Part width must be a non-negative integer, not {!r}".format(width))
812 if not isinstance(stride, int) or stride <= 0:
813 raise TypeError("Part stride must be a positive integer, not {!r}".format(stride))
814
815 super().__init__(src_loc_at=src_loc_at)
816 self.value = value
817 self.offset = Value.cast(offset)
818 self.width = width
819 self.stride = stride
820
821 def shape(self):
822 return Shape(self.width)
823
824 def _lhs_signals(self):
825 return self.value._lhs_signals()
826
827 def _rhs_signals(self):
828 return self.value._rhs_signals() | self.offset._rhs_signals()
829
830 def __repr__(self):
831 return "(part {} {} {} {})".format(repr(self.value), repr(self.offset),
832 self.width, self.stride)
833
834
835 @final
836 def Cat(*args, src_loc_at=0):
837 """Concatenate values.
838
839 Behaviour is required to be identical to _InternalCat.
840 The first argument "defines" the way that all others are
841 handled. If the first argument is derived from UserValue,
842 it is not downcast to a type Value because doing so would
843 lose the opportunity for "redirection" (Value.__Cat__ would
844 always be called).
845 """
846 # flatten the args and convert to tuple (not a generator)
847 args = tuple(flatten(args))
848 # check if there are no arguments (zero-length Signal).
849 if len(args) == 0:
850 return _InternalCat(*args, src_loc_at=src_loc_at)
851 # determine if the first is a UserValue.
852 if isinstance(args[0], UserValue):
853 first = args[0] # take UserValue directly, do not downcast
854 else:
855 first = Value.cast(args[0]) # ok to downcast to Value
856 # all other arguments are safe to downcast to Value
857 rest = [Value.cast(v) for v in flatten(args[1:])]
858 # assume first item defines the "handling" for all others
859 return first.__Cat__(*rest, src_loc_at=src_loc_at)
860
861
862 class _InternalCat(Value):
863 """Concatenate values.
864
865 Form a compound ``Value`` from several smaller ones by concatenation.
866 The first argument occupies the lower bits of the result.
867 The return value can be used on either side of an assignment, that
868 is, the concatenated value can be used as an argument on the RHS or
869 as a target on the LHS. If it is used on the LHS, it must solely
870 consist of ``Signal`` s, slices of ``Signal`` s, and other concatenations
871 meeting these properties. The bit length of the return value is the sum of
872 the bit lengths of the arguments::
873
874 len(Cat(args)) == sum(len(arg) for arg in args)
875
876 Parameters
877 ----------
878 *args : Values or iterables of Values, inout
879 ``Value`` s to be concatenated.
880
881 Returns
882 -------
883 Value, inout
884 Resulting ``Value`` obtained by concatentation.
885 """
886 def __init__(self, *args, src_loc_at=0):
887 super().__init__(src_loc_at=src_loc_at)
888 self.parts = [Value.cast(v) for v in flatten(args)]
889
890 def shape(self):
891 return Shape(sum(len(part) for part in self.parts))
892
893 def _lhs_signals(self):
894 return union((part._lhs_signals() for part in self.parts), start=SignalSet())
895
896 def _rhs_signals(self):
897 return union((part._rhs_signals() for part in self.parts), start=SignalSet())
898
899 def _as_const(self):
900 value = 0
901 for part in reversed(self.parts):
902 value <<= len(part)
903 value |= part._as_const()
904 return value
905
906 def __repr__(self):
907 return "(cat {})".format(" ".join(map(repr, self.parts)))
908
909
910 @final
911 def Repl(value, count, *, src_loc_at=0):
912 return value.__Repl__(count, src_loc_at=src_loc_at)
913
914
915 class _InternalRepl(Value):
916 """Replicate a value
917
918 An input value is replicated (repeated) several times
919 to be used on the RHS of assignments::
920
921 len(Repl(s, n)) == len(s) * n
922
923 Parameters
924 ----------
925 value : Value, in
926 Input value to be replicated.
927 count : int
928 Number of replications.
929
930 Returns
931 -------
932 Repl, out
933 Replicated value.
934 """
935 def __init__(self, value, count, *, src_loc_at=0):
936 if not isinstance(count, int) or count < 0:
937 raise TypeError("Replication count must be a non-negative integer, not {!r}"
938 .format(count))
939
940 super().__init__(src_loc_at=src_loc_at)
941 self.value = Value.cast(value)
942 self.count = count
943
944 def shape(self):
945 return Shape(len(self.value) * self.count)
946
947 def _rhs_signals(self):
948 return self.value._rhs_signals()
949
950 def __repr__(self):
951 return "(repl {!r} {})".format(self.value, self.count)
952
953
954 # @final
955 class Signal(Value, DUID):
956 """A varying integer value.
957
958 Parameters
959 ----------
960 shape : ``Shape``-castable object or None
961 Specification for the number of bits in this ``Signal`` and its signedness (whether it
962 can represent negative values). See ``Shape.cast`` for details.
963 If not specified, ``shape`` defaults to 1-bit and non-signed.
964 name : str
965 Name hint for this signal. If ``None`` (default) the name is inferred from the variable
966 name this ``Signal`` is assigned to.
967 reset : int or integral Enum
968 Reset (synchronous) or default (combinatorial) value.
969 When this ``Signal`` is assigned to in synchronous context and the corresponding clock
970 domain is reset, the ``Signal`` assumes the given value. When this ``Signal`` is unassigned
971 in combinatorial context (due to conditional assignments not being taken), the ``Signal``
972 assumes its ``reset`` value. Defaults to 0.
973 reset_less : bool
974 If ``True``, do not generate reset logic for this ``Signal`` in synchronous statements.
975 The ``reset`` value is only used as a combinatorial default or as the initial value.
976 Defaults to ``False``.
977 attrs : dict
978 Dictionary of synthesis attributes.
979 decoder : function or Enum
980 A function converting integer signal values to human-readable strings (e.g. FSM state
981 names). If an ``Enum`` subclass is passed, it is concisely decoded using format string
982 ``"{0.name:}/{0.value:}"``, or a number if the signal value is not a member of
983 the enumeration.
984
985 Attributes
986 ----------
987 width : int
988 signed : bool
989 name : str
990 reset : int
991 reset_less : bool
992 attrs : dict
993 decoder : function
994 """
995
996 def __init__(self, shape=None, *, name=None, reset=0, reset_less=False,
997 attrs=None, decoder=None, src_loc_at=0):
998 super().__init__(src_loc_at=src_loc_at)
999
1000 if name is not None and not isinstance(name, str):
1001 raise TypeError("Name must be a string, not {!r}".format(name))
1002 self.name = name or tracer.get_var_name(depth=2 + src_loc_at, default="$signal")
1003
1004 if shape is None:
1005 shape = unsigned(1)
1006 self.width, self.signed = Shape.cast(shape, src_loc_at=1 + src_loc_at)
1007
1008 if isinstance(reset, Enum):
1009 reset = reset.value
1010 if not isinstance(reset, int):
1011 raise TypeError("Reset value has to be an int or an integral Enum")
1012
1013 reset_width = bits_for(reset, self.signed)
1014 if reset != 0 and reset_width > self.width:
1015 warnings.warn("Reset value {!r} requires {} bits to represent, but the signal "
1016 "only has {} bits"
1017 .format(reset, reset_width, self.width),
1018 SyntaxWarning, stacklevel=2 + src_loc_at)
1019
1020 self.reset = reset
1021 self.reset_less = bool(reset_less)
1022
1023 self.attrs = OrderedDict(() if attrs is None else attrs)
1024
1025 if decoder is None and isinstance(shape, type) and issubclass(shape, Enum):
1026 decoder = shape
1027 if isinstance(decoder, type) and issubclass(decoder, Enum):
1028 def enum_decoder(value):
1029 try:
1030 return "{0.name:}/{0.value:}".format(decoder(value))
1031 except ValueError:
1032 return str(value)
1033 self.decoder = enum_decoder
1034 self._enum_class = decoder
1035 else:
1036 self.decoder = decoder
1037 self._enum_class = None
1038
1039 # Not a @classmethod because nmigen.compat requires it.
1040 @staticmethod
1041 def like(other, *, name=None, name_suffix=None, src_loc_at=0, **kwargs):
1042 """Create Signal based on another.
1043
1044 Parameters
1045 ----------
1046 other : Value
1047 Object to base this Signal on.
1048 """
1049 if name is not None:
1050 new_name = str(name)
1051 elif name_suffix is not None:
1052 new_name = other.name + str(name_suffix)
1053 else:
1054 new_name = tracer.get_var_name(depth=2 + src_loc_at, default="$like")
1055 kw = dict(shape=Value.cast(other).shape(), name=new_name)
1056 if isinstance(other, Signal):
1057 kw.update(reset=other.reset, reset_less=other.reset_less,
1058 attrs=other.attrs, decoder=other.decoder)
1059 kw.update(kwargs)
1060 return Signal(**kw, src_loc_at=1 + src_loc_at)
1061
1062 def shape(self):
1063 return Shape(self.width, self.signed)
1064
1065 def _lhs_signals(self):
1066 return SignalSet((self,))
1067
1068 def _rhs_signals(self):
1069 return SignalSet((self,))
1070
1071 def __repr__(self):
1072 return "(sig {})".format(self.name)
1073
1074
1075 @final
1076 class ClockSignal(Value):
1077 """Clock signal for a clock domain.
1078
1079 Any ``ClockSignal`` is equivalent to ``cd.clk`` for a clock domain with the corresponding name.
1080 All of these signals ultimately refer to the same signal, but they can be manipulated
1081 independently of the clock domain, even before the clock domain is created.
1082
1083 Parameters
1084 ----------
1085 domain : str
1086 Clock domain to obtain a clock signal for. Defaults to ``"sync"``.
1087 """
1088 def __init__(self, domain="sync", *, src_loc_at=0):
1089 super().__init__(src_loc_at=src_loc_at)
1090 if not isinstance(domain, str):
1091 raise TypeError("Clock domain name must be a string, not {!r}".format(domain))
1092 if domain == "comb":
1093 raise ValueError("Domain '{}' does not have a clock".format(domain))
1094 self.domain = domain
1095
1096 def shape(self):
1097 return Shape(1)
1098
1099 def _lhs_signals(self):
1100 return SignalSet((self,))
1101
1102 def _rhs_signals(self):
1103 raise NotImplementedError("ClockSignal must be lowered to a concrete signal") # :nocov:
1104
1105 def __repr__(self):
1106 return "(clk {})".format(self.domain)
1107
1108
1109 @final
1110 class ResetSignal(Value):
1111 """Reset signal for a clock domain.
1112
1113 Any ``ResetSignal`` is equivalent to ``cd.rst`` for a clock domain with the corresponding name.
1114 All of these signals ultimately refer to the same signal, but they can be manipulated
1115 independently of the clock domain, even before the clock domain is created.
1116
1117 Parameters
1118 ----------
1119 domain : str
1120 Clock domain to obtain a reset signal for. Defaults to ``"sync"``.
1121 allow_reset_less : bool
1122 If the clock domain is reset-less, act as a constant ``0`` instead of reporting an error.
1123 """
1124 def __init__(self, domain="sync", allow_reset_less=False, *, src_loc_at=0):
1125 super().__init__(src_loc_at=src_loc_at)
1126 if not isinstance(domain, str):
1127 raise TypeError("Clock domain name must be a string, not {!r}".format(domain))
1128 if domain == "comb":
1129 raise ValueError("Domain '{}' does not have a reset".format(domain))
1130 self.domain = domain
1131 self.allow_reset_less = allow_reset_less
1132
1133 def shape(self):
1134 return Shape(1)
1135
1136 def _lhs_signals(self):
1137 return SignalSet((self,))
1138
1139 def _rhs_signals(self):
1140 raise NotImplementedError("ResetSignal must be lowered to a concrete signal") # :nocov:
1141
1142 def __repr__(self):
1143 return "(rst {})".format(self.domain)
1144
1145
1146 class Array(MutableSequence):
1147 """Addressable multiplexer.
1148
1149 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
1150 in a proxy.
1151
1152 The array proxy can be used as an ordinary ``Value``, i.e. participate in calculations and
1153 assignments, provided that all elements of the array are values. The array proxy also supports
1154 attribute access and further indexing, each returning another array proxy; this means that
1155 the results of indexing into arrays, arrays of records, and arrays of arrays can all
1156 be used as first-class values.
1157
1158 It is an error to change an array or any of its elements after an array proxy was created.
1159 Changing the array directly will raise an exception. However, it is not possible to detect
1160 the elements being modified; if an element's attribute or element is modified after the proxy
1161 for it has been created, the proxy will refer to stale data.
1162
1163 Examples
1164 --------
1165
1166 Simple array::
1167
1168 gpios = Array(Signal() for _ in range(10))
1169 with m.If(bus.we):
1170 m.d.sync += gpios[bus.addr].eq(bus.w_data)
1171 with m.Else():
1172 m.d.sync += bus.r_data.eq(gpios[bus.addr])
1173
1174 Multidimensional array::
1175
1176 mult = Array(Array(x * y for y in range(10)) for x in range(10))
1177 a = Signal.range(10)
1178 b = Signal.range(10)
1179 r = Signal(8)
1180 m.d.comb += r.eq(mult[a][b])
1181
1182 Array of records::
1183
1184 layout = [
1185 ("r_data", 16),
1186 ("r_en", 1),
1187 ]
1188 buses = Array(Record(layout) for busno in range(4))
1189 master = Record(layout)
1190 m.d.comb += [
1191 buses[sel].r_en.eq(master.r_en),
1192 master.r_data.eq(buses[sel].r_data),
1193 ]
1194 """
1195 def __init__(self, iterable=()):
1196 self._inner = list(iterable)
1197 self._proxy_at = None
1198 self._mutable = True
1199
1200 def __getitem__(self, index):
1201 if isinstance(index, Value):
1202 if self._mutable:
1203 self._proxy_at = tracer.get_src_loc()
1204 self._mutable = False
1205 return ArrayProxy(self, index)
1206 else:
1207 return self._inner[index]
1208
1209 def __len__(self):
1210 return len(self._inner)
1211
1212 def _check_mutability(self):
1213 if not self._mutable:
1214 raise ValueError("Array can no longer be mutated after it was indexed with a value "
1215 "at {}:{}".format(*self._proxy_at))
1216
1217 def __setitem__(self, index, value):
1218 self._check_mutability()
1219 self._inner[index] = value
1220
1221 def __delitem__(self, index):
1222 self._check_mutability()
1223 del self._inner[index]
1224
1225 def insert(self, index, value):
1226 self._check_mutability()
1227 self._inner.insert(index, value)
1228
1229 def __repr__(self):
1230 return "(array{} [{}])".format(" mutable" if self._mutable else "",
1231 ", ".join(map(repr, self._inner)))
1232
1233
1234 @final
1235 class ArrayProxy(Value):
1236 def __init__(self, elems, index, *, src_loc_at=0):
1237 super().__init__(src_loc_at=1 + src_loc_at)
1238 self.elems = elems
1239 self.index = Value.cast(index)
1240
1241 def __getattr__(self, attr):
1242 return ArrayProxy([getattr(elem, attr) for elem in self.elems], self.index)
1243
1244 def __getitem__(self, index):
1245 return ArrayProxy([ elem[index] for elem in self.elems], self.index)
1246
1247 def _iter_as_values(self):
1248 return (Value.cast(elem) for elem in self.elems)
1249
1250 def shape(self):
1251 unsigned_width = signed_width = 0
1252 has_unsigned = has_signed = False
1253 for elem_width, elem_signed in (elem.shape() for elem in self._iter_as_values()):
1254 if elem_signed:
1255 has_signed = True
1256 signed_width = max(signed_width, elem_width)
1257 else:
1258 has_unsigned = True
1259 unsigned_width = max(unsigned_width, elem_width)
1260 # The shape of the proxy must be such that it preserves the mathematical value of the array
1261 # elements. I.e., shape-wise, an array proxy must be identical to an equivalent mux tree.
1262 # To ensure this holds, if the array contains both signed and unsigned values, make sure
1263 # that every unsigned value is zero-extended by at least one bit.
1264 if has_signed and has_unsigned and unsigned_width >= signed_width:
1265 # Array contains both signed and unsigned values, and at least one of the unsigned
1266 # values won't be zero-extended otherwise.
1267 return signed(unsigned_width + 1)
1268 else:
1269 # Array contains values of the same signedness, or else all of the unsigned values
1270 # are zero-extended.
1271 return Shape(max(unsigned_width, signed_width), has_signed)
1272
1273 def _lhs_signals(self):
1274 signals = union((elem._lhs_signals() for elem in self._iter_as_values()),
1275 start=SignalSet())
1276 return signals
1277
1278 def _rhs_signals(self):
1279 signals = union((elem._rhs_signals() for elem in self._iter_as_values()),
1280 start=SignalSet())
1281 return self.index._rhs_signals() | signals
1282
1283 def __repr__(self):
1284 return "(proxy (array [{}]) {!r})".format(", ".join(map(repr, self.elems)), self.index)
1285
1286
1287 # TODO(nmigen-0.4): remove
1288 class UserValue(Value):
1289 """Value with custom lowering.
1290
1291 A ``UserValue`` is a value whose precise representation does not have to be immediately known,
1292 which is useful in certain metaprogramming scenarios. Instead of providing fixed semantics
1293 upfront, it is kept abstract for as long as possible, only being lowered to a concrete nMigen
1294 value when required.
1295
1296 Note that the ``lower`` method will only be called once; this is necessary to ensure that
1297 nMigen's view of representation of all values stays internally consistent. If the class
1298 deriving from ``UserValue`` is mutable, then it must ensure that after ``lower`` is called,
1299 it is not mutated in a way that changes its representation.
1300
1301 The following is an incomplete list of actions that, when applied to an ``UserValue`` directly
1302 or indirectly, will cause it to be lowered, provided as an illustrative reference:
1303 * Querying the shape using ``.shape()`` or ``len()``;
1304 * Creating a similarly shaped signal using ``Signal.like``;
1305 * Indexing or iterating through individual bits;
1306 * Adding an assignment to the value to a ``Module`` using ``m.d.<domain> +=``.
1307 """
1308 @deprecated("instead of `UserValue`, use `ValueCastable`", stacklevel=3)
1309 def __init__(self, *, src_loc_at=0):
1310 super().__init__(src_loc_at=1 + src_loc_at)
1311 self.__lowered = None
1312
1313 @abstractmethod
1314 def lower(self):
1315 """Conversion to a concrete representation."""
1316 pass # :nocov:
1317
1318 def _lazy_lower(self):
1319 if self.__lowered is None:
1320 lowered = self.lower()
1321 if isinstance(lowered, UserValue):
1322 lowered = lowered._lazy_lower()
1323 self.__lowered = Value.cast(lowered)
1324 return self.__lowered
1325
1326 def shape(self):
1327 return self._lazy_lower().shape()
1328
1329 def _lhs_signals(self):
1330 return self._lazy_lower()._lhs_signals()
1331
1332 def _rhs_signals(self):
1333 return self._lazy_lower()._rhs_signals()
1334
1335
1336 class ValueCastable:
1337 """Base class for classes which can be cast to Values.
1338
1339 A ``ValueCastable`` can be cast to ``Value``, meaning its precise representation does not have
1340 to be immediately known. This is useful in certain metaprogramming scenarios. Instead of
1341 providing fixed semantics upfront, it is kept abstract for as long as possible, only being
1342 cast to a concrete nMigen value when required.
1343
1344 Note that it is necessary to ensure that nMigen's view of representation of all values stays
1345 internally consistent. The class deriving from ``ValueCastable`` must decorate the ``as_value``
1346 method with the ``lowermethod`` decorator, which ensures that all calls to ``as_value`` return
1347 the same ``Value`` representation. If the class deriving from ``ValueCastable`` is mutable,
1348 it is up to the user to ensure that it is not mutated in a way that changes its representation
1349 after the first call to ``as_value``.
1350 """
1351 def __new__(cls, *args, **kwargs):
1352 self = super().__new__(cls)
1353 if not hasattr(self, "as_value"):
1354 raise TypeError(f"Class '{cls.__name__}' deriving from `ValueCastable` must override "
1355 "the `as_value` method")
1356
1357 if not hasattr(self.as_value, "_ValueCastable__memoized"):
1358 raise TypeError(f"Class '{cls.__name__}' deriving from `ValueCastable` must decorate "
1359 "the `as_value` method with the `ValueCastable.lowermethod` decorator")
1360 return self
1361
1362 @staticmethod
1363 def lowermethod(func):
1364 """Decorator to memoize lowering methods.
1365
1366 Ensures the decorated method is called only once, with subsequent method calls returning the
1367 object returned by the first first method call.
1368
1369 This decorator is required to decorate the ``as_value`` method of ``ValueCastable`` subclasses.
1370 This is to ensure that nMigen's view of representation of all values stays internally
1371 consistent.
1372 """
1373 @functools.wraps(func)
1374 def wrapper_memoized(self, *args, **kwargs):
1375 if not hasattr(self, "_ValueCastable__lowered_to"):
1376 self.__lowered_to = func(self, *args, **kwargs)
1377 return self.__lowered_to
1378 wrapper_memoized.__memoized = True
1379 return wrapper_memoized
1380
1381
1382 @final
1383 class Sample(Value):
1384 """Value from the past.
1385
1386 A ``Sample`` of an expression is equal to the value of the expression ``clocks`` clock edges
1387 of the ``domain`` clock back. If that moment is before the beginning of time, it is equal
1388 to the value of the expression calculated as if each signal had its reset value.
1389 """
1390 def __init__(self, expr, clocks, domain, *, src_loc_at=0):
1391 super().__init__(src_loc_at=1 + src_loc_at)
1392 self.value = Value.cast(expr)
1393 self.clocks = int(clocks)
1394 self.domain = domain
1395 if not isinstance(self.value, (Const, Signal, ClockSignal, ResetSignal, Initial)):
1396 raise TypeError("Sampled value must be a signal or a constant, not {!r}"
1397 .format(self.value))
1398 if self.clocks < 0:
1399 raise ValueError("Cannot sample a value {} cycles in the future"
1400 .format(-self.clocks))
1401 if not (self.domain is None or isinstance(self.domain, str)):
1402 raise TypeError("Domain name must be a string or None, not {!r}"
1403 .format(self.domain))
1404
1405 def shape(self):
1406 return self.value.shape()
1407
1408 def _rhs_signals(self):
1409 return SignalSet((self,))
1410
1411 def __repr__(self):
1412 return "(sample {!r} @ {}[{}])".format(
1413 self.value, "<default>" if self.domain is None else self.domain, self.clocks)
1414
1415
1416 def Past(expr, clocks=1, domain=None):
1417 return Sample(expr, clocks, domain)
1418
1419
1420 def Stable(expr, clocks=0, domain=None):
1421 return Sample(expr, clocks + 1, domain) == Sample(expr, clocks, domain)
1422
1423
1424 def Rose(expr, clocks=0, domain=None):
1425 return ~Sample(expr, clocks + 1, domain) & Sample(expr, clocks, domain)
1426
1427
1428 def Fell(expr, clocks=0, domain=None):
1429 return Sample(expr, clocks + 1, domain) & ~Sample(expr, clocks, domain)
1430
1431
1432 @final
1433 class Initial(Value):
1434 """Start indicator, for model checking.
1435
1436 An ``Initial`` signal is ``1`` at the first cycle of model checking, and ``0`` at any other.
1437 """
1438 def __init__(self, *, src_loc_at=0):
1439 super().__init__(src_loc_at=src_loc_at)
1440
1441 def shape(self):
1442 return Shape(1)
1443
1444 def _rhs_signals(self):
1445 return SignalSet((self,))
1446
1447 def __repr__(self):
1448 return "(initial)"
1449
1450
1451 class _StatementList(list):
1452 def __repr__(self):
1453 return "({})".format(" ".join(map(repr, self)))
1454
1455
1456 class Statement:
1457 def __init__(self, *, src_loc_at=0):
1458 self.src_loc = tracer.get_src_loc(1 + src_loc_at)
1459
1460 @staticmethod
1461 def cast(obj):
1462 if isinstance(obj, Iterable):
1463 return _StatementList(list(chain.from_iterable(map(Statement.cast, obj))))
1464 else:
1465 if isinstance(obj, Statement):
1466 return _StatementList([obj])
1467 else:
1468 raise TypeError("Object {!r} is not an nMigen statement".format(obj))
1469
1470
1471 @final
1472 def Assign(lhs, rhs, *, src_loc_at=0):
1473 return lhs.__Assign__(rhs, src_loc_at=src_loc_at)
1474
1475
1476 class _InternalAssign(Statement):
1477 def __init__(self, lhs, rhs, *, src_loc_at=0):
1478 super().__init__(src_loc_at=src_loc_at)
1479 self.lhs = Value.cast(lhs)
1480 self.rhs = Value.cast(rhs)
1481
1482 def _lhs_signals(self):
1483 return self.lhs._lhs_signals()
1484
1485 def _rhs_signals(self):
1486 return self.lhs._rhs_signals() | self.rhs._rhs_signals()
1487
1488 def __repr__(self):
1489 return "(eq {!r} {!r})".format(self.lhs, self.rhs)
1490
1491
1492 class UnusedProperty(UnusedMustUse):
1493 pass
1494
1495
1496 class Property(Statement, MustUse):
1497 _MustUse__warning = UnusedProperty
1498
1499 def __init__(self, test, *, _check=None, _en=None, src_loc_at=0):
1500 super().__init__(src_loc_at=src_loc_at)
1501 self.test = Value.cast(test)
1502 self._check = _check
1503 self._en = _en
1504 if self._check is None:
1505 self._check = Signal(reset_less=True, name="${}$check".format(self._kind))
1506 self._check.src_loc = self.src_loc
1507 if _en is None:
1508 self._en = Signal(reset_less=True, name="${}$en".format(self._kind))
1509 self._en.src_loc = self.src_loc
1510
1511 def _lhs_signals(self):
1512 return SignalSet((self._en, self._check))
1513
1514 def _rhs_signals(self):
1515 return self.test._rhs_signals()
1516
1517 def __repr__(self):
1518 return "({} {!r})".format(self._kind, self.test)
1519
1520
1521 @final
1522 class Assert(Property):
1523 _kind = "assert"
1524
1525
1526 @final
1527 class Assume(Property):
1528 _kind = "assume"
1529
1530
1531 @final
1532 class Cover(Property):
1533 _kind = "cover"
1534
1535
1536 # @final
1537 def Switch(test, cases, *, src_loc=None, src_loc_at=0, case_src_locs={}):
1538 return test.__Switch__(cases, src_loc=src_loc, src_loc_at=src_loc_at,
1539 case_src_locs=case_src_locs)
1540
1541
1542 class _InternalSwitch(Statement):
1543 def __init__(self, test, cases, *, src_loc=None, src_loc_at=0, case_src_locs={}):
1544 if src_loc is None:
1545 super().__init__(src_loc_at=src_loc_at)
1546 else:
1547 # Switch is a bit special in terms of location tracking because it is usually created
1548 # long after the control has left the statement that directly caused its creation.
1549 self.src_loc = src_loc
1550 # Switch is also a bit special in that its parts also have location information. It can't
1551 # be automatically traced, so whatever constructs a Switch may optionally provide it.
1552 self.case_src_locs = {}
1553
1554 self.test = Value.cast(test)
1555 self.cases = OrderedDict()
1556 for orig_keys, stmts in cases.items():
1557 # Map: None -> (); key -> (key,); (key...) -> (key...)
1558 keys = orig_keys
1559 if keys is None:
1560 keys = ()
1561 if not isinstance(keys, tuple):
1562 keys = (keys,)
1563 # Map: 2 -> "0010"; "0010" -> "0010"
1564 new_keys = ()
1565 key_mask = (1 << len(self.test)) - 1
1566 for key in keys:
1567 if isinstance(key, str):
1568 key = "".join(key.split()) # remove whitespace
1569 elif isinstance(key, int):
1570 key = format(key & key_mask, "b").rjust(len(self.test), "0")
1571 elif isinstance(key, Enum):
1572 key = format(key.value & key_mask, "b").rjust(len(self.test), "0")
1573 else:
1574 raise TypeError("Object {!r} cannot be used as a switch key"
1575 .format(key))
1576 assert len(key) == len(self.test)
1577 new_keys = (*new_keys, key)
1578 if not isinstance(stmts, Iterable):
1579 stmts = [stmts]
1580 self.cases[new_keys] = Statement.cast(stmts)
1581 if orig_keys in case_src_locs:
1582 self.case_src_locs[new_keys] = case_src_locs[orig_keys]
1583
1584 def _lhs_signals(self):
1585 signals = union((s._lhs_signals() for ss in self.cases.values() for s in ss),
1586 start=SignalSet())
1587 return signals
1588
1589 def _rhs_signals(self):
1590 signals = union((s._rhs_signals() for ss in self.cases.values() for s in ss),
1591 start=SignalSet())
1592 return self.test._rhs_signals() | signals
1593
1594 def __repr__(self):
1595 def case_repr(keys, stmts):
1596 stmts_repr = " ".join(map(repr, stmts))
1597 if keys == ():
1598 return "(default {})".format(stmts_repr)
1599 elif len(keys) == 1:
1600 return "(case {} {})".format(keys[0], stmts_repr)
1601 else:
1602 return "(case ({}) {})".format(" ".join(keys), stmts_repr)
1603 case_reprs = [case_repr(keys, stmts) for keys, stmts in self.cases.items()]
1604 return "(switch {!r} {})".format(self.test, " ".join(case_reprs))
1605
1606
1607 class _MappedKeyCollection(metaclass=ABCMeta):
1608 @abstractmethod
1609 def _map_key(self, key):
1610 pass # :nocov:
1611
1612 @abstractmethod
1613 def _unmap_key(self, key):
1614 pass # :nocov:
1615
1616
1617 class _MappedKeyDict(MutableMapping, _MappedKeyCollection):
1618 def __init__(self, pairs=()):
1619 self._storage = OrderedDict()
1620 for key, value in pairs:
1621 self[key] = value
1622
1623 def __getitem__(self, key):
1624 key = None if key is None else self._map_key(key)
1625 return self._storage[key]
1626
1627 def __setitem__(self, key, value):
1628 key = None if key is None else self._map_key(key)
1629 self._storage[key] = value
1630
1631 def __delitem__(self, key):
1632 key = None if key is None else self._map_key(key)
1633 del self._storage[key]
1634
1635 def __iter__(self):
1636 for key in self._storage:
1637 if key is None:
1638 yield None
1639 else:
1640 yield self._unmap_key(key)
1641
1642 def __eq__(self, other):
1643 if not isinstance(other, type(self)):
1644 return False
1645 if len(self) != len(other):
1646 return False
1647 for ak, bk in zip(sorted(self._storage), sorted(other._storage)):
1648 if ak != bk:
1649 return False
1650 if self._storage[ak] != other._storage[bk]:
1651 return False
1652 return True
1653
1654 def __len__(self):
1655 return len(self._storage)
1656
1657 def __repr__(self):
1658 pairs = ["({!r}, {!r})".format(k, v) for k, v in self.items()]
1659 return "{}.{}([{}])".format(type(self).__module__, type(self).__name__,
1660 ", ".join(pairs))
1661
1662
1663 class _MappedKeySet(MutableSet, _MappedKeyCollection):
1664 def __init__(self, elements=()):
1665 self._storage = OrderedDict()
1666 for elem in elements:
1667 self.add(elem)
1668
1669 def add(self, value):
1670 self._storage[self._map_key(value)] = None
1671
1672 def update(self, values):
1673 for value in values:
1674 self.add(value)
1675
1676 def discard(self, value):
1677 if value in self:
1678 del self._storage[self._map_key(value)]
1679
1680 def __contains__(self, value):
1681 return self._map_key(value) in self._storage
1682
1683 def __iter__(self):
1684 for key in [k for k in self._storage]:
1685 yield self._unmap_key(key)
1686
1687 def __len__(self):
1688 return len(self._storage)
1689
1690 def __repr__(self):
1691 return "{}.{}({})".format(type(self).__module__, type(self).__name__,
1692 ", ".join(repr(x) for x in self))
1693
1694
1695 class ValueKey:
1696 def __init__(self, value):
1697 self.value = Value.cast(value)
1698 if isinstance(self.value, Const):
1699 self._hash = hash(self.value.value)
1700 elif isinstance(self.value, (Signal, AnyValue)):
1701 self._hash = hash(self.value.duid)
1702 elif isinstance(self.value, (ClockSignal, ResetSignal)):
1703 self._hash = hash(self.value.domain)
1704 elif isinstance(self.value, Operator):
1705 self._hash = hash((self.value.operator,
1706 tuple(ValueKey(o) for o in self.value.operands)))
1707 elif isinstance(self.value, Slice):
1708 self._hash = hash((ValueKey(self.value.value), self.value.start, self.value.stop))
1709 elif isinstance(self.value, Part):
1710 self._hash = hash((ValueKey(self.value.value), ValueKey(self.value.offset),
1711 self.value.width, self.value.stride))
1712 elif isinstance(self.value, _InternalCat):
1713 self._hash = hash(tuple(ValueKey(o) for o in self.value.parts))
1714 elif isinstance(self.value, ArrayProxy):
1715 self._hash = hash((ValueKey(self.value.index),
1716 tuple(ValueKey(e) for e in self.value._iter_as_values())))
1717 elif isinstance(self.value, Sample):
1718 self._hash = hash((ValueKey(self.value.value), self.value.clocks, self.value.domain))
1719 elif isinstance(self.value, Initial):
1720 self._hash = 0
1721 else: # :nocov:
1722 raise TypeError("Object {!r} cannot be used as a key in value collections"
1723 .format(self.value))
1724
1725 def __hash__(self):
1726 return self._hash
1727
1728 def __eq__(self, other):
1729 if type(other) is not ValueKey:
1730 return False
1731 if type(self.value) is not type(other.value):
1732 return False
1733
1734 if isinstance(self.value, Const):
1735 return self.value.value == other.value.value
1736 elif isinstance(self.value, (Signal, AnyValue)):
1737 return self.value is other.value
1738 elif isinstance(self.value, (ClockSignal, ResetSignal)):
1739 return self.value.domain == other.value.domain
1740 elif isinstance(self.value, Operator):
1741 return (self.value.operator == other.value.operator and
1742 len(self.value.operands) == len(other.value.operands) and
1743 all(ValueKey(a) == ValueKey(b)
1744 for a, b in zip(self.value.operands, other.value.operands)))
1745 elif isinstance(self.value, Slice):
1746 return (ValueKey(self.value.value) == ValueKey(other.value.value) and
1747 self.value.start == other.value.start and
1748 self.value.stop == other.value.stop)
1749 elif isinstance(self.value, Part):
1750 return (ValueKey(self.value.value) == ValueKey(other.value.value) and
1751 ValueKey(self.value.offset) == ValueKey(other.value.offset) and
1752 self.value.width == other.value.width and
1753 self.value.stride == other.value.stride)
1754 elif isinstance(self.value, _InternalCat):
1755 return all(ValueKey(a) == ValueKey(b)
1756 for a, b in zip(self.value.parts, other.value.parts))
1757 elif isinstance(self.value, ArrayProxy):
1758 return (ValueKey(self.value.index) == ValueKey(other.value.index) and
1759 len(self.value.elems) == len(other.value.elems) and
1760 all(ValueKey(a) == ValueKey(b)
1761 for a, b in zip(self.value._iter_as_values(),
1762 other.value._iter_as_values())))
1763 elif isinstance(self.value, Sample):
1764 return (ValueKey(self.value.value) == ValueKey(other.value.value) and
1765 self.value.clocks == other.value.clocks and
1766 self.value.domain == self.value.domain)
1767 elif isinstance(self.value, Initial):
1768 return True
1769 else: # :nocov:
1770 raise TypeError("Object {!r} cannot be used as a key in value collections"
1771 .format(self.value))
1772
1773 def __lt__(self, other):
1774 if not isinstance(other, ValueKey):
1775 return False
1776 if type(self.value) != type(other.value):
1777 return False
1778
1779 if isinstance(self.value, Const):
1780 return self.value < other.value
1781 elif isinstance(self.value, (Signal, AnyValue)):
1782 return self.value.duid < other.value.duid
1783 elif isinstance(self.value, Slice):
1784 return (ValueKey(self.value.value) < ValueKey(other.value.value) and
1785 self.value.start < other.value.start and
1786 self.value.end < other.value.end)
1787 else: # :nocov:
1788 raise TypeError("Object {!r} cannot be used as a key in value collections")
1789
1790 def __repr__(self):
1791 return "<{}.ValueKey {!r}>".format(__name__, self.value)
1792
1793
1794 class ValueDict(_MappedKeyDict):
1795 _map_key = ValueKey
1796 _unmap_key = lambda self, key: key.value
1797
1798
1799 class ValueSet(_MappedKeySet):
1800 _map_key = ValueKey
1801 _unmap_key = lambda self, key: key.value
1802
1803
1804 class SignalKey:
1805 def __init__(self, signal):
1806 self.signal = signal
1807 if isinstance(signal, Signal):
1808 self._intern = (0, signal.duid)
1809 elif type(signal) is ClockSignal:
1810 self._intern = (1, signal.domain)
1811 elif type(signal) is ResetSignal:
1812 self._intern = (2, signal.domain)
1813 else:
1814 raise TypeError("Object {!r} is not an nMigen signal".format(signal))
1815
1816 def __hash__(self):
1817 return hash(self._intern)
1818
1819 def __eq__(self, other):
1820 if type(other) is not SignalKey:
1821 return False
1822 return self._intern == other._intern
1823
1824 def __lt__(self, other):
1825 if type(other) is not SignalKey:
1826 raise TypeError("Object {!r} cannot be compared to a SignalKey".format(signal))
1827 return self._intern < other._intern
1828
1829 def __repr__(self):
1830 return "<{}.SignalKey {!r}>".format(__name__, self.signal)
1831
1832
1833 class SignalDict(_MappedKeyDict):
1834 _map_key = SignalKey
1835 _unmap_key = lambda self, key: key.signal
1836
1837
1838 class SignalSet(_MappedKeySet):
1839 _map_key = SignalKey
1840 _unmap_key = lambda self, key: key.signal