hdl.ast: check type of Sample(domain=...).
[nmigen.git] / nmigen / hdl / ast.py
1 from abc import ABCMeta, abstractmethod
2 import builtins
3 import traceback
4 import warnings
5 from collections import OrderedDict
6 from collections.abc import Iterable, MutableMapping, MutableSet, MutableSequence
7 from enum import Enum
8
9 from .. import tracer
10 from ..tools import *
11
12
13 __all__ = [
14 "Value", "Const", "C", "AnyConst", "AnySeq", "Operator", "Mux", "Part", "Slice", "Cat", "Repl",
15 "Array", "ArrayProxy",
16 "Signal", "ClockSignal", "ResetSignal",
17 "UserValue",
18 "Sample", "Past", "Stable", "Rose", "Fell", "Initial",
19 "Statement", "Assign", "Assert", "Assume", "Cover", "Switch", "Delay", "Tick",
20 "Passive", "ValueKey", "ValueDict", "ValueSet", "SignalKey", "SignalDict",
21 "SignalSet",
22 ]
23
24
25 class DUID:
26 """Deterministic Unique IDentifier"""
27 __next_uid = 0
28 def __init__(self):
29 self.duid = DUID.__next_uid
30 DUID.__next_uid += 1
31
32
33 class Value(metaclass=ABCMeta):
34 @staticmethod
35 def wrap(obj):
36 """Ensures that the passed object is an nMigen value. Booleans and integers
37 are automatically wrapped into ``Const``."""
38 if isinstance(obj, Value):
39 return obj
40 elif isinstance(obj, (bool, int)):
41 return Const(obj)
42 else:
43 raise TypeError("Object '{!r}' is not an nMigen value".format(obj))
44
45 def __init__(self, *, src_loc_at=0):
46 super().__init__()
47 self.src_loc = tracer.get_src_loc(1 + src_loc_at)
48
49 def __bool__(self):
50 raise TypeError("Attempted to convert nMigen value to boolean")
51
52 def __invert__(self):
53 return Operator("~", [self])
54 def __neg__(self):
55 return Operator("-", [self])
56
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])
97
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])
110
111 def __len__(self):
112 return self.shape()[0]
113
114 def __getitem__(self, key):
115 n = len(self)
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))
119 if key < 0:
120 key += n
121 return Slice(self, key, key + 1)
122 elif isinstance(key, slice):
123 start, stop, step = key.indices(n)
124 if step != 1:
125 return Cat(self[i] for i in range(start, stop, step))
126 return Slice(self, start, stop)
127 else:
128 raise TypeError("Cannot index value with {}".format(repr(key)))
129
130 def bool(self):
131 """Conversion to boolean.
132
133 Returns
134 -------
135 Value, out
136 Output ``Value``. If any bits are set, returns ``1``, else ``0``.
137 """
138 return Operator("b", [self])
139
140 def implies(premise, conclusion):
141 """Implication.
142
143 Returns
144 -------
145 Value, out
146 ``0`` if ``premise`` is true and ``conclusion`` is not, ``1`` otherwise.
147 """
148 return ~premise | conclusion
149
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)
154
155 def bit_select(self, offset, width):
156 """Part-select with bit granularity.
157
158 Selects a constant width but variable offset part of a ``Value``, such that successive
159 parts overlap by all but 1 bit.
160
161 Parameters
162 ----------
163 offset : Value, in
164 index of first selected bit
165 width : int
166 number of selected bits
167
168 Returns
169 -------
170 Part, out
171 Selected part of the ``Value``
172 """
173 return Part(self, offset, width, stride=1, src_loc_at=1)
174
175 def word_select(self, offset, width):
176 """Part-select with word granularity.
177
178 Selects a constant width but variable offset part of a ``Value``, such that successive
179 parts do not overlap.
180
181 Parameters
182 ----------
183 offset : Value, in
184 index of first selected word
185 width : int
186 number of selected bits
187
188 Returns
189 -------
190 Part, out
191 Selected part of the ``Value``
192 """
193 return Part(self, offset, width, stride=width, src_loc_at=1)
194
195 def eq(self, value):
196 """Assignment.
197
198 Parameters
199 ----------
200 value : Value, in
201 Value to be assigned.
202
203 Returns
204 -------
205 Assign
206 Assignment statement that can be used in combinatorial or synchronous context.
207 """
208 return Assign(self, value, src_loc_at=1)
209
210 @abstractmethod
211 def shape(self):
212 """Bit length and signedness of a value.
213
214 Returns
215 -------
216 int, bool
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).
219
220 Examples
221 --------
222 >>> Value.shape(Signal(8))
223 8, False
224 >>> Value.shape(C(0xaa))
225 8, False
226 """
227 pass # :nocov:
228
229 def _lhs_signals(self):
230 raise TypeError("Value {!r} cannot be used in assignments".format(self))
231
232 @abstractmethod
233 def _rhs_signals(self):
234 pass # :nocov:
235
236 def _as_const(self):
237 raise TypeError("Value {!r} cannot be evaluated as constant".format(self))
238
239 __hash__ = None
240
241
242 @final
243 class Const(Value):
244 """A constant, literal integer value.
245
246 Parameters
247 ----------
248 value : int
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`.
254
255 Attributes
256 ----------
257 nbits : int
258 signed : bool
259 """
260 src_loc = None
261
262 @staticmethod
263 def normalize(value, shape):
264 nbits, signed = shape
265 mask = (1 << nbits) - 1
266 value &= mask
267 if signed and value >> (nbits - 1):
268 value |= ~mask
269 return value
270
271 def __init__(self, value, shape=None):
272 # We deliberately do not call Value.__init__ here.
273 self.value = int(value)
274 if shape is None:
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}'"
281 .format(self.nbits))
282 self.value = self.normalize(self.value, shape)
283
284 def shape(self):
285 return self.nbits, self.signed
286
287 def _rhs_signals(self):
288 return ValueSet()
289
290 def _as_const(self):
291 return self.value
292
293 def __repr__(self):
294 return "(const {}'{}d{})".format(self.nbits, "s" if self.signed else "", self.value)
295
296
297 C = Const # shorthand
298
299
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):
304 shape = shape, False
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}'"
308 .format(self.nbits))
309
310 def shape(self):
311 return self.nbits, self.signed
312
313 def _rhs_signals(self):
314 return ValueSet()
315
316
317 @final
318 class AnyConst(AnyValue):
319 def __repr__(self):
320 return "(anyconst {}'{})".format(self.nbits, "s" if self.signed else "")
321
322
323 @final
324 class AnySeq(AnyValue):
325 def __repr__(self):
326 return "(anyseq {}'{})".format(self.nbits, "s" if self.signed else "")
327
328
329 @final
330 class Operator(Value):
331 def __init__(self, op, operands, *, src_loc_at=0):
332 super().__init__(src_loc_at=1 + src_loc_at)
333 self.op = op
334 self.operands = [Value.wrap(o) for o in operands]
335
336 @staticmethod
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
349 else:
350 # first signed, second operand unsigned (add sign bit)
351 return max(a_bits, b_bits + 1), True
352
353 def shape(self):
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
359 if self.op == "-":
360 if not a_sign:
361 return a_bits + 1, True
362 else:
363 return a_bits, a_sign
364 if self.op == "b":
365 return 1, False
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
371 if self.op == "*":
372 return a_bits + b_bits, a_sign or b_sign
373 if self.op == "%":
374 return a_bits, a_sign
375 if self.op in ("<", "<=", "==", "!=", ">", ">=", "b"):
376 return 1, False
377 if self.op in ("&", "^", "|"):
378 return self._bitwise_binary_shape(*op_shapes)
379 if self.op == "<<":
380 if b_sign:
381 extra = 2 ** (b_bits - 1) - 1
382 else:
383 extra = 2 ** (b_bits) - 1
384 return a_bits + extra, a_sign
385 if self.op == ">>":
386 if b_sign:
387 extra = 2 ** (b_bits - 1)
388 else:
389 extra = 0
390 return a_bits + extra, a_sign
391 elif len(op_shapes) == 3:
392 if self.op == "m":
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:
397
398 def _rhs_signals(self):
399 return union(op._rhs_signals() for op in self.operands)
400
401 def __repr__(self):
402 return "({} {})".format(self.op, " ".join(map(repr, self.operands)))
403
404
405 def Mux(sel, val1, val0):
406 """Choose between two values.
407
408 Parameters
409 ----------
410 sel : Value, in
411 Selector.
412 val1 : Value, in
413 val0 : Value, in
414 Input values.
415
416 Returns
417 -------
418 Value, out
419 Output ``Value``. If ``sel`` is asserted, the Mux returns ``val1``, else ``val0``.
420 """
421 return Operator("m", [sel, val1, val0])
422
423
424 @final
425 class Slice(Value):
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))
431
432 n = len(value)
433 if start not in range(-(n+1), n+1):
434 raise IndexError("Cannot start slice {} bits into {}-bit value".format(start, n))
435 if start < 0:
436 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))
439 if end < 0:
440 end += n
441 if start > end:
442 raise IndexError("Slice start {} must be less than slice end {}".format(start, end))
443
444 super().__init__(src_loc_at=src_loc_at)
445 self.value = Value.wrap(value)
446 self.start = start
447 self.end = end
448
449 def shape(self):
450 return self.end - self.start, False
451
452 def _lhs_signals(self):
453 return self.value._lhs_signals()
454
455 def _rhs_signals(self):
456 return self.value._rhs_signals()
457
458 def __repr__(self):
459 return "(slice {} {}:{})".format(repr(self.value), self.start, self.end)
460
461
462 @final
463 class Part(Value):
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))
469
470 super().__init__(src_loc_at=src_loc_at)
471 self.value = value
472 self.offset = Value.wrap(offset)
473 self.width = width
474 self.stride = stride
475
476 def shape(self):
477 return self.width, False
478
479 def _lhs_signals(self):
480 return self.value._lhs_signals()
481
482 def _rhs_signals(self):
483 return self.value._rhs_signals() | self.offset._rhs_signals()
484
485 def __repr__(self):
486 return "(part {} {} {} {})".format(repr(self.value), repr(self.offset),
487 self.width, self.stride)
488
489
490 @final
491 class Cat(Value):
492 """Concatenate values.
493
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::
502
503 len(Cat(args)) == sum(len(arg) for arg in args)
504
505 Parameters
506 ----------
507 *args : Values or iterables of Values, inout
508 ``Value`` s to be concatenated.
509
510 Returns
511 -------
512 Value, inout
513 Resulting ``Value`` obtained by concatentation.
514 """
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)]
518
519 def shape(self):
520 return sum(len(part) for part in self.parts), False
521
522 def _lhs_signals(self):
523 return union((part._lhs_signals() for part in self.parts), start=ValueSet())
524
525 def _rhs_signals(self):
526 return union((part._rhs_signals() for part in self.parts), start=ValueSet())
527
528 def _as_const(self):
529 value = 0
530 for part in reversed(self.parts):
531 value <<= len(part)
532 value |= part._as_const()
533 return value
534
535 def __repr__(self):
536 return "(cat {})".format(" ".join(map(repr, self.parts)))
537
538
539 @final
540 class Repl(Value):
541 """Replicate a value
542
543 An input value is replicated (repeated) several times
544 to be used on the RHS of assignments::
545
546 len(Repl(s, n)) == len(s) * n
547
548 Parameters
549 ----------
550 value : Value, in
551 Input value to be replicated.
552 count : int
553 Number of replications.
554
555 Returns
556 -------
557 Repl, out
558 Replicated value.
559 """
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}'"
563 .format(count))
564
565 super().__init__(src_loc_at=src_loc_at)
566 self.value = Value.wrap(value)
567 self.count = count
568
569 def shape(self):
570 return len(self.value) * self.count, False
571
572 def _rhs_signals(self):
573 return self.value._rhs_signals()
574
575 def __repr__(self):
576 return "(repl {!r} {})".format(self.value, self.count)
577
578
579 @final
580 class Signal(Value, DUID):
581 """A varying integer value.
582
583 Parameters
584 ----------
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.
589 name : str
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
593 sequences.
594 reset : int
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.
600 reset_less : bool
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``.
604 min : int or None
605 max : int or None
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).
609 attrs : dict
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
615 the enumeration.
616
617 Attributes
618 ----------
619 nbits : int
620 signed : bool
621 name : str
622 reset : int
623 reset_less : bool
624 attrs : dict
625 """
626
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)
630
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)
637
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")
641
642 if shape is None:
643 if min is None:
644 min = 0
645 if max is None:
646 max = 2
647 max -= 1 # make both bounds inclusive
648 if min > max:
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
652 if min == max:
653 self.nbits = 0
654 else:
655 self.nbits = builtins.max(bits_for(min, self.signed),
656 bits_for(max, self.signed))
657
658 else:
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
663 else:
664 self.nbits, self.signed = shape
665
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)
670
671 self.attrs = OrderedDict(() if attrs is None else attrs)
672 if isinstance(decoder, type) and issubclass(decoder, Enum):
673 def enum_decoder(value):
674 try:
675 return "{0.name:}/{0.value:}".format(decoder(value))
676 except ValueError:
677 return str(value)
678 self.decoder = enum_decoder
679 else:
680 self.decoder = decoder
681
682 @classmethod
683 def range(cls, *args, src_loc_at=0, **kwargs):
684 """Create Signal that can represent a given range.
685
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)``.
689 """
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
693 else:
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)
698
699 @classmethod
700 def like(cls, other, *, name=None, name_suffix=None, src_loc_at=0, **kwargs):
701 """Create Signal based on another.
702
703 Parameters
704 ----------
705 other : Value
706 Object to base this Signal on.
707 """
708 if name is not None:
709 new_name = str(name)
710 elif name_suffix is not None:
711 new_name = other.name + str(name_suffix)
712 else:
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)
718 kw.update(kwargs)
719 return cls(**kw, src_loc_at=1 + src_loc_at)
720
721 def shape(self):
722 return self.nbits, self.signed
723
724 def _lhs_signals(self):
725 return ValueSet((self,))
726
727 def _rhs_signals(self):
728 return ValueSet((self,))
729
730 def __repr__(self):
731 return "(sig {})".format(self.name)
732
733
734 @final
735 class ClockSignal(Value):
736 """Clock signal for a clock domain.
737
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.
741
742 Parameters
743 ----------
744 domain : str
745 Clock domain to obtain a clock signal for. Defaults to ``"sync"``.
746 """
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))
751 if domain == "comb":
752 raise ValueError("Domain '{}' does not have a clock".format(domain))
753 self.domain = domain
754
755 def shape(self):
756 return 1, False
757
758 def _lhs_signals(self):
759 return ValueSet((self,))
760
761 def _rhs_signals(self):
762 raise NotImplementedError("ClockSignal must be lowered to a concrete signal") # :nocov:
763
764 def __repr__(self):
765 return "(clk {})".format(self.domain)
766
767
768 @final
769 class ResetSignal(Value):
770 """Reset signal for a clock domain.
771
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.
775
776 Parameters
777 ----------
778 domain : str
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.
782 """
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))
787 if domain == "comb":
788 raise ValueError("Domain '{}' does not have a reset".format(domain))
789 self.domain = domain
790 self.allow_reset_less = allow_reset_less
791
792 def shape(self):
793 return 1, False
794
795 def _lhs_signals(self):
796 return ValueSet((self,))
797
798 def _rhs_signals(self):
799 raise NotImplementedError("ResetSignal must be lowered to a concrete signal") # :nocov:
800
801 def __repr__(self):
802 return "(rst {})".format(self.domain)
803
804
805 class Array(MutableSequence):
806 """Addressable multiplexer.
807
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
809 in a proxy.
810
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.
816
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.
821
822 Examples
823 --------
824
825 Simple array::
826
827 gpios = Array(Signal() for _ in range(10))
828 with m.If(bus.we):
829 m.d.sync += gpios[bus.adr].eq(bus.dat_w)
830 with m.Else():
831 m.d.sync += bus.dat_r.eq(gpios[bus.adr])
832
833 Multidimensional array::
834
835 mult = Array(Array(x * y for y in range(10)) for x in range(10))
836 a = Signal(max=10)
837 b = Signal(max=10)
838 r = Signal(8)
839 m.d.comb += r.eq(mult[a][b])
840
841 Array of records::
842
843 layout = [
844 ("re", 1),
845 ("dat_r", 16),
846 ]
847 buses = Array(Record(layout) for busno in range(4))
848 master = Record(layout)
849 m.d.comb += [
850 buses[sel].re.eq(master.re),
851 master.dat_r.eq(buses[sel].dat_r),
852 ]
853 """
854 def __init__(self, iterable=()):
855 self._inner = list(iterable)
856 self._proxy_at = None
857 self._mutable = True
858
859 def __getitem__(self, index):
860 if isinstance(index, Value):
861 if self._mutable:
862 self._proxy_at = tracer.get_src_loc()
863 self._mutable = False
864 return ArrayProxy(self, index)
865 else:
866 return self._inner[index]
867
868 def __len__(self):
869 return len(self._inner)
870
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))
875
876 def __setitem__(self, index, value):
877 self._check_mutability()
878 self._inner[index] = value
879
880 def __delitem__(self, index):
881 self._check_mutability()
882 del self._inner[index]
883
884 def insert(self, index, value):
885 self._check_mutability()
886 self._inner.insert(index, value)
887
888 def __repr__(self):
889 return "(array{} [{}])".format(" mutable" if self._mutable else "",
890 ", ".join(map(repr, self._inner)))
891
892
893 @final
894 class ArrayProxy(Value):
895 def __init__(self, elems, index, *, src_loc_at=0):
896 super().__init__(src_loc_at=1 + src_loc_at)
897 self.elems = elems
898 self.index = Value.wrap(index)
899
900 def __getattr__(self, attr):
901 return ArrayProxy([getattr(elem, attr) for elem in self.elems], self.index)
902
903 def __getitem__(self, index):
904 return ArrayProxy([ elem[index] for elem in self.elems], self.index)
905
906 def _iter_as_values(self):
907 return (Value.wrap(elem) for elem in self.elems)
908
909 def shape(self):
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)
914 return bits, sign
915
916 def _lhs_signals(self):
917 signals = union((elem._lhs_signals() for elem in self._iter_as_values()), start=ValueSet())
918 return signals
919
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
923
924 def __repr__(self):
925 return "(proxy (array [{}]) {!r})".format(", ".join(map(repr, self.elems)), self.index)
926
927
928 class UserValue(Value):
929 """Value with custom lowering.
930
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
934 value when required.
935
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.
940
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> +=``.
947 """
948 def __init__(self, *, src_loc_at=0):
949 super().__init__(src_loc_at=1 + src_loc_at)
950 self.__lowered = None
951
952 @abstractmethod
953 def lower(self):
954 """Conversion to a concrete representation."""
955 pass # :nocov:
956
957 def _lazy_lower(self):
958 if self.__lowered is None:
959 self.__lowered = Value.wrap(self.lower())
960 return self.__lowered
961
962 def shape(self):
963 return self._lazy_lower().shape()
964
965 def _lhs_signals(self):
966 return self._lazy_lower()._lhs_signals()
967
968 def _rhs_signals(self):
969 return self._lazy_lower()._rhs_signals()
970
971
972 @final
973 class Sample(Value):
974 """Value from the past.
975
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.
979 """
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)
984 self.domain = domain
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}"
987 .format(self.value))
988 if self.clocks < 0:
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))
994
995 def shape(self):
996 return self.value.shape()
997
998 def _rhs_signals(self):
999 return ValueSet((self,))
1000
1001 def __repr__(self):
1002 return "(sample {!r} @ {}[{}])".format(
1003 self.value, "<default>" if self.domain is None else self.domain, self.clocks)
1004
1005
1006 def Past(expr, clocks=1, domain=None):
1007 return Sample(expr, clocks, domain)
1008
1009
1010 def Stable(expr, clocks=0, domain=None):
1011 return Sample(expr, clocks + 1, domain) == Sample(expr, clocks, domain)
1012
1013
1014 def Rose(expr, clocks=0, domain=None):
1015 return ~Sample(expr, clocks + 1, domain) & Sample(expr, clocks, domain)
1016
1017
1018 def Fell(expr, clocks=0, domain=None):
1019 return Sample(expr, clocks + 1, domain) & ~Sample(expr, clocks, domain)
1020
1021
1022 @final
1023 class Initial(Value):
1024 """Start indicator, for model checking.
1025
1026 An ``Initial`` signal is ``1`` at the first cycle of model checking, and ``0`` at any other.
1027 """
1028 def __init__(self, *, src_loc_at=0):
1029 super().__init__(src_loc_at=1 + src_loc_at)
1030
1031 def shape(self):
1032 return (1, False)
1033
1034 def _rhs_signals(self):
1035 return ValueSet((self,))
1036
1037 def __repr__(self):
1038 return "(initial)"
1039
1040
1041 class _StatementList(list):
1042 def __repr__(self):
1043 return "({})".format(" ".join(map(repr, self)))
1044
1045
1046 class Statement:
1047 def __init__(self, *, src_loc_at=0):
1048 self.src_loc = tracer.get_src_loc(1 + src_loc_at)
1049
1050 @staticmethod
1051 def wrap(obj):
1052 if isinstance(obj, Iterable):
1053 return _StatementList(sum((Statement.wrap(e) for e in obj), []))
1054 else:
1055 if isinstance(obj, Statement):
1056 return _StatementList([obj])
1057 else:
1058 raise TypeError("Object '{!r}' is not an nMigen statement".format(obj))
1059
1060
1061 @final
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)
1067
1068 def _lhs_signals(self):
1069 return self.lhs._lhs_signals()
1070
1071 def _rhs_signals(self):
1072 return self.lhs._rhs_signals() | self.rhs._rhs_signals()
1073
1074 def __repr__(self):
1075 return "(eq {!r} {!r})".format(self.lhs, self.rhs)
1076
1077
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
1083 self._en = _en
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
1087 if _en is None:
1088 self._en = Signal(reset_less=True, name="${}$en".format(self._kind))
1089 self._en.src_loc = self.src_loc
1090
1091 def _lhs_signals(self):
1092 return ValueSet((self._en, self._check))
1093
1094 def _rhs_signals(self):
1095 return self.test._rhs_signals()
1096
1097 def __repr__(self):
1098 return "({} {!r})".format(self._kind, self.test)
1099
1100
1101 @final
1102 class Assert(Property):
1103 _kind = "assert"
1104
1105
1106 @final
1107 class Assume(Property):
1108 _kind = "assume"
1109
1110
1111 @final
1112 class Cover(Property):
1113 _kind = "cover"
1114
1115
1116 # @final
1117 class Switch(Statement):
1118 def __init__(self, test, cases, *, src_loc=None, src_loc_at=0, case_src_locs={}):
1119 if src_loc is None:
1120 super().__init__(src_loc_at=src_loc_at)
1121 else:
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 = {}
1128
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...)
1133 keys = orig_keys
1134 if keys is None:
1135 keys = ()
1136 if not isinstance(keys, tuple):
1137 keys = (keys,)
1138 # Map: 2 -> "0010"; "0010" -> "0010"
1139 new_keys = ()
1140 for key in keys:
1141 if isinstance(key, (bool, int)):
1142 key = "{:0{}b}".format(key, len(self.test))
1143 elif isinstance(key, str):
1144 pass
1145 else:
1146 raise TypeError("Object '{!r}' cannot be used as a switch key"
1147 .format(key))
1148 assert len(key) == len(self.test)
1149 new_keys = (*new_keys, key)
1150 if not isinstance(stmts, Iterable):
1151 stmts = [stmts]
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]
1155
1156 def _lhs_signals(self):
1157 signals = union((s._lhs_signals() for ss in self.cases.values() for s in ss),
1158 start=ValueSet())
1159 return signals
1160
1161 def _rhs_signals(self):
1162 signals = union((s._rhs_signals() for ss in self.cases.values() for s in ss),
1163 start=ValueSet())
1164 return self.test._rhs_signals() | signals
1165
1166 def __repr__(self):
1167 def case_repr(keys, stmts):
1168 stmts_repr = " ".join(map(repr, stmts))
1169 if keys == ():
1170 return "(default {})".format(stmts_repr)
1171 elif len(keys) == 1:
1172 return "(case {} {})".format(keys[0], stmts_repr)
1173 else:
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))
1177
1178
1179 @final
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)
1184
1185 def _rhs_signals(self):
1186 return ValueSet()
1187
1188 def __repr__(self):
1189 if self.interval is None:
1190 return "(delay ε)"
1191 else:
1192 return "(delay {:.3}us)".format(self.interval * 1e6)
1193
1194
1195 @final
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)
1200
1201 def _rhs_signals(self):
1202 return ValueSet()
1203
1204 def __repr__(self):
1205 return "(tick {})".format(self.domain)
1206
1207
1208 @final
1209 class Passive(Statement):
1210 def __init__(self, *, src_loc_at=0):
1211 super().__init__(src_loc_at=src_loc_at)
1212
1213 def _rhs_signals(self):
1214 return ValueSet()
1215
1216 def __repr__(self):
1217 return "(passive)"
1218
1219
1220 class _MappedKeyCollection(metaclass=ABCMeta):
1221 @abstractmethod
1222 def _map_key(self, key):
1223 pass # :nocov:
1224
1225 @abstractmethod
1226 def _unmap_key(self, key):
1227 pass # :nocov:
1228
1229
1230 class _MappedKeyDict(MutableMapping, _MappedKeyCollection):
1231 def __init__(self, pairs=()):
1232 self._storage = OrderedDict()
1233 for key, value in pairs:
1234 self[key] = value
1235
1236 def __getitem__(self, key):
1237 key = None if key is None else self._map_key(key)
1238 return self._storage[key]
1239
1240 def __setitem__(self, key, value):
1241 key = None if key is None else self._map_key(key)
1242 self._storage[key] = value
1243
1244 def __delitem__(self, key):
1245 key = None if key is None else self._map_key(key)
1246 del self._storage[key]
1247
1248 def __iter__(self):
1249 for key in self._storage:
1250 if key is None:
1251 yield None
1252 else:
1253 yield self._unmap_key(key)
1254
1255 def __eq__(self, other):
1256 if not isinstance(other, type(self)):
1257 return False
1258 if len(self) != len(other):
1259 return False
1260 for ak, bk in zip(sorted(self._storage), sorted(other._storage)):
1261 if ak != bk:
1262 return False
1263 if self._storage[ak] != other._storage[bk]:
1264 return False
1265 return True
1266
1267 def __len__(self):
1268 return len(self._storage)
1269
1270 def __repr__(self):
1271 pairs = ["({!r}, {!r})".format(k, v) for k, v in self.items()]
1272 return "{}.{}([{}])".format(type(self).__module__, type(self).__name__,
1273 ", ".join(pairs))
1274
1275
1276 class _MappedKeySet(MutableSet, _MappedKeyCollection):
1277 def __init__(self, elements=()):
1278 self._storage = OrderedDict()
1279 for elem in elements:
1280 self.add(elem)
1281
1282 def add(self, value):
1283 self._storage[self._map_key(value)] = None
1284
1285 def update(self, values):
1286 for value in values:
1287 self.add(value)
1288
1289 def discard(self, value):
1290 if value in self:
1291 del self._storage[self._map_key(value)]
1292
1293 def __contains__(self, value):
1294 return self._map_key(value) in self._storage
1295
1296 def __iter__(self):
1297 for key in [k for k in self._storage]:
1298 yield self._unmap_key(key)
1299
1300 def __len__(self):
1301 return len(self._storage)
1302
1303 def __repr__(self):
1304 return "{}.{}({})".format(type(self).__module__, type(self).__name__,
1305 ", ".join(repr(x) for x in self))
1306
1307
1308 class ValueKey:
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):
1332 self._hash = 0
1333 else: # :nocov:
1334 raise TypeError("Object '{!r}' cannot be used as a key in value collections"
1335 .format(self.value))
1336
1337 def __hash__(self):
1338 return self._hash
1339
1340 def __eq__(self, other):
1341 if type(other) is not ValueKey:
1342 return False
1343 if type(self.value) is not type(other.value):
1344 return False
1345
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):
1380 return True
1381 else: # :nocov:
1382 raise TypeError("Object '{!r}' cannot be used as a key in value collections"
1383 .format(self.value))
1384
1385 def __lt__(self, other):
1386 if not isinstance(other, ValueKey):
1387 return False
1388 if type(self.value) != type(other.value):
1389 return False
1390
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)
1399 else: # :nocov:
1400 raise TypeError("Object '{!r}' cannot be used as a key in value collections")
1401
1402 def __repr__(self):
1403 return "<{}.ValueKey {!r}>".format(__name__, self.value)
1404
1405
1406 class ValueDict(_MappedKeyDict):
1407 _map_key = ValueKey
1408 _unmap_key = lambda self, key: key.value
1409
1410
1411 class ValueSet(_MappedKeySet):
1412 _map_key = ValueKey
1413 _unmap_key = lambda self, key: key.value
1414
1415
1416 class SignalKey:
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)
1425 else:
1426 raise TypeError("Object '{!r}' is not an nMigen signal".format(signal))
1427
1428 def __hash__(self):
1429 return hash(self._intern)
1430
1431 def __eq__(self, other):
1432 if type(other) is not SignalKey:
1433 return False
1434 return self._intern == other._intern
1435
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
1440
1441 def __repr__(self):
1442 return "<{}.SignalKey {!r}>".format(__name__, self.signal)
1443
1444
1445 class SignalDict(_MappedKeyDict):
1446 _map_key = SignalKey
1447 _unmap_key = lambda self, key: key.signal
1448
1449
1450 class SignalSet(_MappedKeySet):
1451 _map_key = SignalKey
1452 _unmap_key = lambda self, key: key.signal