hdl.{ast,dst}: directly represent RTLIL default case.
[nmigen.git] / nmigen / hdl / ast.py
1 from abc import ABCMeta, abstractmethod
2 import builtins
3 import traceback
4 from collections import OrderedDict
5 from collections.abc import Iterable, MutableMapping, MutableSet, MutableSequence
6
7 from .. import tracer
8 from ..tools import *
9
10
11 __all__ = [
12 "Value", "Const", "C", "AnyConst", "AnySeq", "Operator", "Mux", "Part", "Slice", "Cat", "Repl",
13 "Array", "ArrayProxy",
14 "Sample", "Past", "Stable", "Rose", "Fell",
15 "Signal", "ClockSignal", "ResetSignal",
16 "UserValue",
17 "Statement", "Assign", "Assert", "Assume", "Switch", "Delay", "Tick",
18 "Passive", "ValueKey", "ValueDict", "ValueSet", "SignalKey", "SignalDict",
19 "SignalSet",
20 ]
21
22
23 class DUID:
24 """Deterministic Unique IDentifier"""
25 __next_uid = 0
26 def __init__(self):
27 self.duid = DUID.__next_uid
28 DUID.__next_uid += 1
29
30
31 class Value(metaclass=ABCMeta):
32 @staticmethod
33 def wrap(obj):
34 """Ensures that the passed object is an nMigen value. Booleans and integers
35 are automatically wrapped into ``Const``."""
36 if isinstance(obj, Value):
37 return obj
38 elif isinstance(obj, (bool, int)):
39 return Const(obj)
40 else:
41 raise TypeError("Object '{!r}' is not an nMigen value".format(obj))
42
43 def __init__(self, src_loc_at=0):
44 super().__init__()
45 self.src_loc = tracer.get_src_loc(1 + src_loc_at)
46
47 def __bool__(self):
48 raise TypeError("Attempted to convert nMigen value to boolean")
49
50 def __invert__(self):
51 return Operator("~", [self])
52 def __neg__(self):
53 return Operator("-", [self])
54
55 def __add__(self, other):
56 return Operator("+", [self, other])
57 def __radd__(self, other):
58 return Operator("+", [other, self])
59 def __sub__(self, other):
60 return Operator("-", [self, other])
61 def __rsub__(self, other):
62 return Operator("-", [other, self])
63 def __mul__(self, other):
64 return Operator("*", [self, other])
65 def __rmul__(self, other):
66 return Operator("*", [other, self])
67 def __mod__(self, other):
68 return Operator("%", [self, other])
69 def __rmod__(self, other):
70 return Operator("%", [other, self])
71 def __div__(self, other):
72 return Operator("/", [self, other])
73 def __rdiv__(self, other):
74 return Operator("/", [other, self])
75 def __lshift__(self, other):
76 return Operator("<<", [self, other])
77 def __rlshift__(self, other):
78 return Operator("<<", [other, self])
79 def __rshift__(self, other):
80 return Operator(">>", [self, other])
81 def __rrshift__(self, other):
82 return Operator(">>", [other, self])
83 def __and__(self, other):
84 return Operator("&", [self, other])
85 def __rand__(self, other):
86 return Operator("&", [other, self])
87 def __xor__(self, other):
88 return Operator("^", [self, other])
89 def __rxor__(self, other):
90 return Operator("^", [other, self])
91 def __or__(self, other):
92 return Operator("|", [self, other])
93 def __ror__(self, other):
94 return Operator("|", [other, self])
95
96 def __eq__(self, other):
97 return Operator("==", [self, other])
98 def __ne__(self, other):
99 return Operator("!=", [self, other])
100 def __lt__(self, other):
101 return Operator("<", [self, other])
102 def __le__(self, other):
103 return Operator("<=", [self, other])
104 def __gt__(self, other):
105 return Operator(">", [self, other])
106 def __ge__(self, other):
107 return Operator(">=", [self, other])
108
109 def __len__(self):
110 return self.shape()[0]
111
112 def __getitem__(self, key):
113 n = len(self)
114 if isinstance(key, int):
115 if key not in range(-n, n):
116 raise IndexError("Cannot index {} bits into {}-bit value".format(key, n))
117 if key < 0:
118 key += n
119 return Slice(self, key, key + 1)
120 elif isinstance(key, slice):
121 start, stop, step = key.indices(n)
122 if step != 1:
123 return Cat(self[i] for i in range(start, stop, step))
124 return Slice(self, start, stop)
125 else:
126 raise TypeError("Cannot index value with {}".format(repr(key)))
127
128 def bool(self):
129 """Conversion to boolean.
130
131 Returns
132 -------
133 Value, out
134 Output ``Value``. If any bits are set, returns ``1``, else ``0``.
135 """
136 return Operator("b", [self])
137
138 def implies(premise, conclusion):
139 """Implication.
140
141 Returns
142 -------
143 Value, out
144 ``0`` if ``premise`` is true and ``conclusion`` is not, ``1`` otherwise.
145 """
146 return ~premise | conclusion
147
148 def part(self, offset, width):
149 """Indexed part-select.
150
151 Selects a constant width but variable offset part of a ``Value``.
152
153 Parameters
154 ----------
155 offset : Value, in
156 start point of the selected bits
157 width : int
158 number of selected bits
159
160 Returns
161 -------
162 Part, out
163 Selected part of the ``Value``
164 """
165 return Part(self, offset, width)
166
167 def eq(self, value):
168 """Assignment.
169
170 Parameters
171 ----------
172 value : Value, in
173 Value to be assigned.
174
175 Returns
176 -------
177 Assign
178 Assignment statement that can be used in combinatorial or synchronous context.
179 """
180 return Assign(self, value)
181
182 @abstractmethod
183 def shape(self):
184 """Bit length and signedness of a value.
185
186 Returns
187 -------
188 int, bool
189 Number of bits required to store `v` or available in `v`, followed by
190 whether `v` has a sign bit (included in the bit count).
191
192 Examples
193 --------
194 >>> Value.shape(Signal(8))
195 8, False
196 >>> Value.shape(C(0xaa))
197 8, False
198 """
199 pass # :nocov:
200
201 def _lhs_signals(self):
202 raise TypeError("Value {!r} cannot be used in assignments".format(self))
203
204 @abstractmethod
205 def _rhs_signals(self):
206 pass # :nocov:
207
208 def _as_const(self):
209 raise TypeError("Value {!r} cannot be evaluated as constant".format(self))
210
211 __hash__ = None
212
213
214 @final
215 class Const(Value):
216 """A constant, literal integer value.
217
218 Parameters
219 ----------
220 value : int
221 shape : int or tuple or None
222 Either an integer `bits` or a tuple `(bits, signed)`
223 specifying the number of bits in this `Const` and whether it is
224 signed (can represent negative values). `shape` defaults
225 to the minimum width and signedness of `value`.
226
227 Attributes
228 ----------
229 nbits : int
230 signed : bool
231 """
232 src_loc = None
233
234 @staticmethod
235 def normalize(value, shape):
236 nbits, signed = shape
237 mask = (1 << nbits) - 1
238 value &= mask
239 if signed and value >> (nbits - 1):
240 value |= ~mask
241 return value
242
243 def __init__(self, value, shape=None):
244 self.value = int(value)
245 if shape is None:
246 shape = bits_for(self.value), self.value < 0
247 if isinstance(shape, int):
248 shape = shape, self.value < 0
249 self.nbits, self.signed = shape
250 if not isinstance(self.nbits, int) or self.nbits < 0:
251 raise TypeError("Width must be a non-negative integer, not '{!r}'"
252 .format(self.nbits))
253 self.value = self.normalize(self.value, shape)
254
255 def shape(self):
256 return self.nbits, self.signed
257
258 def _rhs_signals(self):
259 return ValueSet()
260
261 def _as_const(self):
262 return self.value
263
264 def __repr__(self):
265 return "(const {}'{}d{})".format(self.nbits, "s" if self.signed else "", self.value)
266
267
268 C = Const # shorthand
269
270
271 class AnyValue(Value, DUID):
272 def __init__(self, shape):
273 super().__init__(src_loc_at=0)
274 if isinstance(shape, int):
275 shape = shape, False
276 self.nbits, self.signed = shape
277 if not isinstance(self.nbits, int) or self.nbits < 0:
278 raise TypeError("Width must be a non-negative integer, not '{!r}'"
279 .format(self.nbits))
280
281 def shape(self):
282 return self.nbits, self.signed
283
284 def _rhs_signals(self):
285 return ValueSet()
286
287
288 @final
289 class AnyConst(AnyValue):
290 def __repr__(self):
291 return "(anyconst {}'{})".format(self.nbits, "s" if self.signed else "")
292
293
294 @final
295 class AnySeq(AnyValue):
296 def __repr__(self):
297 return "(anyseq {}'{})".format(self.nbits, "s" if self.signed else "")
298
299
300 @final
301 class Operator(Value):
302 def __init__(self, op, operands, src_loc_at=0):
303 super().__init__(src_loc_at=1 + src_loc_at)
304 self.op = op
305 self.operands = [Value.wrap(o) for o in operands]
306
307 @staticmethod
308 def _bitwise_binary_shape(a_shape, b_shape):
309 a_bits, a_sign = a_shape
310 b_bits, b_sign = b_shape
311 if not a_sign and not b_sign:
312 # both operands unsigned
313 return max(a_bits, b_bits), False
314 elif a_sign and b_sign:
315 # both operands signed
316 return max(a_bits, b_bits), True
317 elif not a_sign and b_sign:
318 # first operand unsigned (add sign bit), second operand signed
319 return max(a_bits + 1, b_bits), True
320 else:
321 # first signed, second operand unsigned (add sign bit)
322 return max(a_bits, b_bits + 1), True
323
324 def shape(self):
325 op_shapes = list(map(lambda x: x.shape(), self.operands))
326 if len(op_shapes) == 1:
327 (a_bits, a_sign), = op_shapes
328 if self.op in ("+", "~"):
329 return a_bits, a_sign
330 if self.op == "-":
331 if not a_sign:
332 return a_bits + 1, True
333 else:
334 return a_bits, a_sign
335 if self.op == "b":
336 return 1, False
337 elif len(op_shapes) == 2:
338 (a_bits, a_sign), (b_bits, b_sign) = op_shapes
339 if self.op == "+" or self.op == "-":
340 bits, sign = self._bitwise_binary_shape(*op_shapes)
341 return bits + 1, sign
342 if self.op == "*":
343 return a_bits + b_bits, a_sign or b_sign
344 if self.op == "%":
345 return a_bits, a_sign
346 if self.op in ("<", "<=", "==", "!=", ">", ">=", "b"):
347 return 1, False
348 if self.op in ("&", "^", "|"):
349 return self._bitwise_binary_shape(*op_shapes)
350 if self.op == "<<":
351 if b_sign:
352 extra = 2 ** (b_bits - 1) - 1
353 else:
354 extra = 2 ** (b_bits) - 1
355 return a_bits + extra, a_sign
356 if self.op == ">>":
357 if b_sign:
358 extra = 2 ** (b_bits - 1)
359 else:
360 extra = 0
361 return a_bits + extra, a_sign
362 elif len(op_shapes) == 3:
363 if self.op == "m":
364 s_shape, a_shape, b_shape = op_shapes
365 return self._bitwise_binary_shape(a_shape, b_shape)
366 raise NotImplementedError("Operator {}/{} not implemented"
367 .format(self.op, len(op_shapes))) # :nocov:
368
369 def _rhs_signals(self):
370 return union(op._rhs_signals() for op in self.operands)
371
372 def __repr__(self):
373 return "({} {})".format(self.op, " ".join(map(repr, self.operands)))
374
375
376 def Mux(sel, val1, val0):
377 """Choose between two values.
378
379 Parameters
380 ----------
381 sel : Value, in
382 Selector.
383 val1 : Value, in
384 val0 : Value, in
385 Input values.
386
387 Returns
388 -------
389 Value, out
390 Output ``Value``. If ``sel`` is asserted, the Mux returns ``val1``, else ``val0``.
391 """
392 return Operator("m", [sel, val1, val0], src_loc_at=1)
393
394
395 @final
396 class Slice(Value):
397 def __init__(self, value, start, end):
398 if not isinstance(start, int):
399 raise TypeError("Slice start must be an integer, not '{!r}'".format(start))
400 if not isinstance(end, int):
401 raise TypeError("Slice end must be an integer, not '{!r}'".format(end))
402
403 n = len(value)
404 if start not in range(-(n+1), n+1):
405 raise IndexError("Cannot start slice {} bits into {}-bit value".format(start, n))
406 if start < 0:
407 start += n
408 if end not in range(-(n+1), n+1):
409 raise IndexError("Cannot end slice {} bits into {}-bit value".format(end, n))
410 if end < 0:
411 end += n
412 if start > end:
413 raise IndexError("Slice start {} must be less than slice end {}".format(start, end))
414
415 super().__init__()
416 self.value = Value.wrap(value)
417 self.start = start
418 self.end = end
419
420 def shape(self):
421 return self.end - self.start, False
422
423 def _lhs_signals(self):
424 return self.value._lhs_signals()
425
426 def _rhs_signals(self):
427 return self.value._rhs_signals()
428
429 def __repr__(self):
430 return "(slice {} {}:{})".format(repr(self.value), self.start, self.end)
431
432
433 @final
434 class Part(Value):
435 def __init__(self, value, offset, width):
436 if not isinstance(width, int) or width < 0:
437 raise TypeError("Part width must be a non-negative integer, not '{!r}'".format(width))
438
439 super().__init__()
440 self.value = value
441 self.offset = Value.wrap(offset)
442 self.width = width
443
444 def shape(self):
445 return self.width, False
446
447 def _lhs_signals(self):
448 return self.value._lhs_signals()
449
450 def _rhs_signals(self):
451 return self.value._rhs_signals() | self.offset._rhs_signals()
452
453 def __repr__(self):
454 return "(part {} {} {})".format(repr(self.value), repr(self.offset), self.width)
455
456
457 @final
458 class Cat(Value):
459 """Concatenate values.
460
461 Form a compound ``Value`` from several smaller ones by concatenation.
462 The first argument occupies the lower bits of the result.
463 The return value can be used on either side of an assignment, that
464 is, the concatenated value can be used as an argument on the RHS or
465 as a target on the LHS. If it is used on the LHS, it must solely
466 consist of ``Signal`` s, slices of ``Signal`` s, and other concatenations
467 meeting these properties. The bit length of the return value is the sum of
468 the bit lengths of the arguments::
469
470 len(Cat(args)) == sum(len(arg) for arg in args)
471
472 Parameters
473 ----------
474 *args : Values or iterables of Values, inout
475 ``Value`` s to be concatenated.
476
477 Returns
478 -------
479 Value, inout
480 Resulting ``Value`` obtained by concatentation.
481 """
482 def __init__(self, *args):
483 super().__init__()
484 self.parts = [Value.wrap(v) for v in flatten(args)]
485
486 def shape(self):
487 return sum(len(part) for part in self.parts), False
488
489 def _lhs_signals(self):
490 return union((part._lhs_signals() for part in self.parts), start=ValueSet())
491
492 def _rhs_signals(self):
493 return union((part._rhs_signals() for part in self.parts), start=ValueSet())
494
495 def _as_const(self):
496 value = 0
497 for part in reversed(self.parts):
498 value <<= len(part)
499 value |= part._as_const()
500 return value
501
502 def __repr__(self):
503 return "(cat {})".format(" ".join(map(repr, self.parts)))
504
505
506 @final
507 class Repl(Value):
508 """Replicate a value
509
510 An input value is replicated (repeated) several times
511 to be used on the RHS of assignments::
512
513 len(Repl(s, n)) == len(s) * n
514
515 Parameters
516 ----------
517 value : Value, in
518 Input value to be replicated.
519 count : int
520 Number of replications.
521
522 Returns
523 -------
524 Repl, out
525 Replicated value.
526 """
527 def __init__(self, value, count):
528 if not isinstance(count, int) or count < 0:
529 raise TypeError("Replication count must be a non-negative integer, not '{!r}'"
530 .format(count))
531
532 super().__init__()
533 self.value = Value.wrap(value)
534 self.count = count
535
536 def shape(self):
537 return len(self.value) * self.count, False
538
539 def _rhs_signals(self):
540 return self.value._rhs_signals()
541
542 def __repr__(self):
543 return "(repl {!r} {})".format(self.value, self.count)
544
545
546 @final
547 class Signal(Value, DUID):
548 """A varying integer value.
549
550 Parameters
551 ----------
552 shape : int or tuple or None
553 Either an integer ``bits`` or a tuple ``(bits, signed)`` specifying the number of bits
554 in this ``Signal`` and whether it is signed (can represent negative values).
555 ``shape`` defaults to 1-bit and non-signed.
556 name : str
557 Name hint for this signal. If ``None`` (default) the name is inferred from the variable
558 name this ``Signal`` is assigned to. Name collisions are automatically resolved by
559 prepending names of objects that contain this ``Signal`` and by appending integer
560 sequences.
561 reset : int
562 Reset (synchronous) or default (combinatorial) value.
563 When this ``Signal`` is assigned to in synchronous context and the corresponding clock
564 domain is reset, the ``Signal`` assumes the given value. When this ``Signal`` is unassigned
565 in combinatorial context (due to conditional assignments not being taken), the ``Signal``
566 assumes its ``reset`` value. Defaults to 0.
567 reset_less : bool
568 If ``True``, do not generate reset logic for this ``Signal`` in synchronous statements.
569 The ``reset`` value is only used as a combinatorial default or as the initial value.
570 Defaults to ``False``.
571 min : int or None
572 max : int or None
573 If ``shape`` is ``None``, the signal bit width and signedness are
574 determined by the integer range given by ``min`` (inclusive,
575 defaults to 0) and ``max`` (exclusive, defaults to 2).
576 attrs : dict
577 Dictionary of synthesis attributes.
578 decoder : function
579 A function converting integer signal values to human-readable strings (e.g. FSM state
580 names).
581
582 Attributes
583 ----------
584 nbits : int
585 signed : bool
586 name : str
587 reset : int
588 reset_less : bool
589 attrs : dict
590 """
591
592 def __init__(self, shape=None, name=None, reset=0, reset_less=False, min=None, max=None,
593 attrs=None, decoder=None, src_loc_at=0):
594 super().__init__(src_loc_at=src_loc_at)
595
596 if name is not None and not isinstance(name, str):
597 raise TypeError("Name must be a string, not '{!r}'".format(name))
598 self.name = name or tracer.get_var_name(depth=2 + src_loc_at, default="$signal")
599
600 if shape is None:
601 if min is None:
602 min = 0
603 if max is None:
604 max = 2
605 max -= 1 # make both bounds inclusive
606 if min > max:
607 raise ValueError("Lower bound {} should be less or equal to higher bound {}"
608 .format(min, max + 1))
609 self.signed = min < 0 or max < 0
610 if min == max:
611 self.nbits = 0
612 else:
613 self.nbits = builtins.max(bits_for(min, self.signed),
614 bits_for(max, self.signed))
615
616 else:
617 if not (min is None and max is None):
618 raise ValueError("Only one of bits/signedness or bounds may be specified")
619 if isinstance(shape, int):
620 self.nbits, self.signed = shape, False
621 else:
622 self.nbits, self.signed = shape
623
624 if not isinstance(self.nbits, int) or self.nbits < 0:
625 raise TypeError("Width must be a non-negative integer, not '{!r}'".format(self.nbits))
626 self.reset = int(reset)
627 self.reset_less = bool(reset_less)
628
629 self.attrs = OrderedDict(() if attrs is None else attrs)
630 self.decoder = decoder
631
632 @classmethod
633 def like(cls, other, name=None, name_suffix=None, src_loc_at=0, **kwargs):
634 """Create Signal based on another.
635
636 Parameters
637 ----------
638 other : Value
639 Object to base this Signal on.
640 """
641 if name is not None:
642 new_name = str(name)
643 elif name_suffix is not None:
644 new_name = other.name + str(name_suffix)
645 else:
646 new_name = tracer.get_var_name(depth=2 + src_loc_at, default="$like")
647 kw = dict(shape=cls.wrap(other).shape(), name=new_name)
648 if isinstance(other, cls):
649 kw.update(reset=other.reset, reset_less=other.reset_less,
650 attrs=other.attrs, decoder=other.decoder)
651 kw.update(kwargs)
652 return cls(**kw, src_loc_at=1 + src_loc_at)
653
654 def shape(self):
655 return self.nbits, self.signed
656
657 def _lhs_signals(self):
658 return ValueSet((self,))
659
660 def _rhs_signals(self):
661 return ValueSet((self,))
662
663 def __repr__(self):
664 return "(sig {})".format(self.name)
665
666
667 @final
668 class ClockSignal(Value):
669 """Clock signal for a clock domain.
670
671 Any ``ClockSignal`` is equivalent to ``cd.clk`` for a clock domain with the corresponding name.
672 All of these signals ultimately refer to the same signal, but they can be manipulated
673 independently of the clock domain, even before the clock domain is created.
674
675 Parameters
676 ----------
677 domain : str
678 Clock domain to obtain a clock signal for. Defaults to ``"sync"``.
679 """
680 def __init__(self, domain="sync"):
681 super().__init__()
682 if not isinstance(domain, str):
683 raise TypeError("Clock domain name must be a string, not '{!r}'".format(domain))
684 self.domain = domain
685
686 def shape(self):
687 return 1, False
688
689 def _lhs_signals(self):
690 return ValueSet((self,))
691
692 def _rhs_signals(self):
693 raise NotImplementedError("ClockSignal must be lowered to a concrete signal") # :nocov:
694
695 def __repr__(self):
696 return "(clk {})".format(self.domain)
697
698
699 @final
700 class ResetSignal(Value):
701 """Reset signal for a clock domain.
702
703 Any ``ResetSignal`` is equivalent to ``cd.rst`` for a clock domain with the corresponding name.
704 All of these signals ultimately refer to the same signal, but they can be manipulated
705 independently of the clock domain, even before the clock domain is created.
706
707 Parameters
708 ----------
709 domain : str
710 Clock domain to obtain a reset signal for. Defaults to ``"sync"``.
711 allow_reset_less : bool
712 If the clock domain is reset-less, act as a constant ``0`` instead of reporting an error.
713 """
714 def __init__(self, domain="sync", allow_reset_less=False):
715 super().__init__()
716 if not isinstance(domain, str):
717 raise TypeError("Clock domain name must be a string, not '{!r}'".format(domain))
718 self.domain = domain
719 self.allow_reset_less = allow_reset_less
720
721 def shape(self):
722 return 1, False
723
724 def _lhs_signals(self):
725 return ValueSet((self,))
726
727 def _rhs_signals(self):
728 raise NotImplementedError("ResetSignal must be lowered to a concrete signal") # :nocov:
729
730 def __repr__(self):
731 return "(rst {})".format(self.domain)
732
733
734 class Array(MutableSequence):
735 """Addressable multiplexer.
736
737 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
738 in a proxy.
739
740 The array proxy can be used as an ordinary ``Value``, i.e. participate in calculations and
741 assignments, provided that all elements of the array are values. The array proxy also supports
742 attribute access and further indexing, each returning another array proxy; this means that
743 the results of indexing into arrays, arrays of records, and arrays of arrays can all
744 be used as first-class values.
745
746 It is an error to change an array or any of its elements after an array proxy was created.
747 Changing the array directly will raise an exception. However, it is not possible to detect
748 the elements being modified; if an element's attribute or element is modified after the proxy
749 for it has been created, the proxy will refer to stale data.
750
751 Examples
752 --------
753
754 Simple array::
755
756 gpios = Array(Signal() for _ in range(10))
757 with m.If(bus.we):
758 m.d.sync += gpios[bus.adr].eq(bus.dat_w)
759 with m.Else():
760 m.d.sync += bus.dat_r.eq(gpios[bus.adr])
761
762 Multidimensional array::
763
764 mult = Array(Array(x * y for y in range(10)) for x in range(10))
765 a = Signal(max=10)
766 b = Signal(max=10)
767 r = Signal(8)
768 m.d.comb += r.eq(mult[a][b])
769
770 Array of records::
771
772 layout = [
773 ("re", 1),
774 ("dat_r", 16),
775 ]
776 buses = Array(Record(layout) for busno in range(4))
777 master = Record(layout)
778 m.d.comb += [
779 buses[sel].re.eq(master.re),
780 master.dat_r.eq(buses[sel].dat_r),
781 ]
782 """
783 def __init__(self, iterable=()):
784 self._inner = list(iterable)
785 self._proxy_at = None
786 self._mutable = True
787
788 def __getitem__(self, index):
789 if isinstance(index, Value):
790 if self._mutable:
791 self._proxy_at = tracer.get_src_loc()
792 self._mutable = False
793 return ArrayProxy(self, index)
794 else:
795 return self._inner[index]
796
797 def __len__(self):
798 return len(self._inner)
799
800 def _check_mutability(self):
801 if not self._mutable:
802 raise ValueError("Array can no longer be mutated after it was indexed with a value "
803 "at {}:{}".format(*self._proxy_at))
804
805 def __setitem__(self, index, value):
806 self._check_mutability()
807 self._inner[index] = value
808
809 def __delitem__(self, index):
810 self._check_mutability()
811 del self._inner[index]
812
813 def insert(self, index, value):
814 self._check_mutability()
815 self._inner.insert(index, value)
816
817 def __repr__(self):
818 return "(array{} [{}])".format(" mutable" if self._mutable else "",
819 ", ".join(map(repr, self._inner)))
820
821
822 @final
823 class ArrayProxy(Value):
824 def __init__(self, elems, index):
825 super().__init__(src_loc_at=1)
826 self.elems = elems
827 self.index = Value.wrap(index)
828
829 def __getattr__(self, attr):
830 return ArrayProxy([getattr(elem, attr) for elem in self.elems], self.index)
831
832 def __getitem__(self, index):
833 return ArrayProxy([ elem[index] for elem in self.elems], self.index)
834
835 def _iter_as_values(self):
836 return (Value.wrap(elem) for elem in self.elems)
837
838 def shape(self):
839 bits, sign = 0, False
840 for elem_bits, elem_sign in (elem.shape() for elem in self._iter_as_values()):
841 bits = max(bits, elem_bits + elem_sign)
842 sign = max(sign, elem_sign)
843 return bits, sign
844
845 def _lhs_signals(self):
846 signals = union((elem._lhs_signals() for elem in self._iter_as_values()), start=ValueSet())
847 return signals
848
849 def _rhs_signals(self):
850 signals = union((elem._rhs_signals() for elem in self._iter_as_values()), start=ValueSet())
851 return self.index._rhs_signals() | signals
852
853 def __repr__(self):
854 return "(proxy (array [{}]) {!r})".format(", ".join(map(repr, self.elems)), self.index)
855
856
857 class UserValue(Value):
858 """Value with custom lowering.
859
860 A ``UserValue`` is a value whose precise representation does not have to be immediately known,
861 which is useful in certain metaprogramming scenarios. Instead of providing fixed semantics
862 upfront, it is kept abstract for as long as possible, only being lowered to a concrete nMigen
863 value when required.
864
865 Note that the ``lower`` method will only be called once; this is necessary to ensure that
866 nMigen's view of representation of all values stays internally consistent. If the class
867 deriving from ``UserValue`` is mutable, then it must ensure that after ``lower`` is called,
868 it is not mutated in a way that changes its representation.
869
870 The following is an incomplete list of actions that, when applied to an ``UserValue`` directly
871 or indirectly, will cause it to be lowered, provided as an illustrative reference:
872 * Querying the shape using ``.shape()`` or ``len()``;
873 * Creating a similarly shaped signal using ``Signal.like``;
874 * Indexing or iterating through individual bits;
875 * Adding an assignment to the value to a ``Module`` using ``m.d.<domain> +=``.
876 """
877 def __init__(self, src_loc_at=1):
878 super().__init__(src_loc_at=1 + src_loc_at)
879 self.__lowered = None
880
881 @abstractmethod
882 def lower(self):
883 """Conversion to a concrete representation."""
884 pass # :nocov:
885
886 def _lazy_lower(self):
887 if self.__lowered is None:
888 self.__lowered = Value.wrap(self.lower())
889 return self.__lowered
890
891 def shape(self):
892 return self._lazy_lower().shape()
893
894 def _lhs_signals(self):
895 return self._lazy_lower()._lhs_signals()
896
897 def _rhs_signals(self):
898 return self._lazy_lower()._rhs_signals()
899
900
901 @final
902 class Sample(Value):
903 """Value from the past.
904
905 A ``Sample`` of an expression is equal to the value of the expression ``clocks`` clock edges
906 of the ``domain`` clock back. If that moment is before the beginning of time, it is equal
907 to the value of the expression calculated as if each signal had its reset value.
908 """
909 def __init__(self, expr, clocks, domain):
910 super().__init__(src_loc_at=1)
911 self.value = Value.wrap(expr)
912 self.clocks = int(clocks)
913 self.domain = domain
914 if not isinstance(self.value, (Const, Signal, ClockSignal, ResetSignal)):
915 raise TypeError("Sampled value may only be a signal or a constant, not {!r}"
916 .format(self.value))
917 if self.clocks < 0:
918 raise ValueError("Cannot sample a value {} cycles in the future"
919 .format(-self.clocks))
920
921 def shape(self):
922 return self.value.shape()
923
924 def _rhs_signals(self):
925 return ValueSet((self,))
926
927 def __repr__(self):
928 return "(sample {!r} @ {}[{}])".format(
929 self.value, "<default>" if self.domain is None else self.domain, self.clocks)
930
931
932 def Past(expr, clocks=1, domain=None):
933 return Sample(expr, clocks, domain)
934
935
936 def Stable(expr, clocks=0, domain=None):
937 return Sample(expr, clocks + 1, domain) == Sample(expr, clocks, domain)
938
939
940 def Rose(expr, clocks=0, domain=None):
941 return ~Sample(expr, clocks + 1, domain) & Sample(expr, clocks, domain)
942
943
944 def Fell(expr, clocks=0, domain=None):
945 return Sample(expr, clocks + 1, domain) & ~Sample(expr, clocks, domain)
946
947
948 class _StatementList(list):
949 def __repr__(self):
950 return "({})".format(" ".join(map(repr, self)))
951
952
953 class Statement:
954 @staticmethod
955 def wrap(obj):
956 if isinstance(obj, Iterable):
957 return _StatementList(sum((Statement.wrap(e) for e in obj), []))
958 else:
959 if isinstance(obj, Statement):
960 return _StatementList([obj])
961 else:
962 raise TypeError("Object '{!r}' is not an nMigen statement".format(obj))
963
964
965 @final
966 class Assign(Statement):
967 def __init__(self, lhs, rhs):
968 self.lhs = Value.wrap(lhs)
969 self.rhs = Value.wrap(rhs)
970
971 def _lhs_signals(self):
972 return self.lhs._lhs_signals()
973
974 def _rhs_signals(self):
975 return self.lhs._rhs_signals() | self.rhs._rhs_signals()
976
977 def __repr__(self):
978 return "(eq {!r} {!r})".format(self.lhs, self.rhs)
979
980
981 class Property(Statement):
982 def __init__(self, test, _check=None, _en=None):
983 self.src_loc = tracer.get_src_loc()
984
985 self.test = Value.wrap(test)
986
987 self._check = _check
988 if self._check is None:
989 self._check = Signal(reset_less=True, name="${}$check".format(self._kind))
990 self._check.src_loc = self.src_loc
991
992 self._en = _en
993 if _en is None:
994 self._en = Signal(reset_less=True, name="${}$en".format(self._kind))
995 self._en.src_loc = self.src_loc
996
997 def _lhs_signals(self):
998 return ValueSet((self._en, self._check))
999
1000 def _rhs_signals(self):
1001 return self.test._rhs_signals()
1002
1003 def __repr__(self):
1004 return "({} {!r})".format(self._kind, self.test)
1005
1006
1007 @final
1008 class Assert(Property):
1009 _kind = "assert"
1010
1011
1012 @final
1013 class Assume(Property):
1014 _kind = "assume"
1015
1016
1017 # @final
1018 class Switch(Statement):
1019 def __init__(self, test, cases):
1020 self.test = Value.wrap(test)
1021 self.cases = OrderedDict()
1022 for key, stmts in cases.items():
1023 if isinstance(key, (bool, int)):
1024 key = "{:0{}b}".format(key, len(self.test))
1025 elif isinstance(key, str):
1026 pass
1027 elif key is None:
1028 pass
1029 else:
1030 raise TypeError("Object '{!r}' cannot be used as a switch key"
1031 .format(key))
1032 assert key is None or len(key) == len(self.test)
1033 if not isinstance(stmts, Iterable):
1034 stmts = [stmts]
1035 self.cases[key] = Statement.wrap(stmts)
1036
1037 def _lhs_signals(self):
1038 signals = union((s._lhs_signals() for ss in self.cases.values() for s in ss),
1039 start=ValueSet())
1040 return signals
1041
1042 def _rhs_signals(self):
1043 signals = union((s._rhs_signals() for ss in self.cases.values() for s in ss),
1044 start=ValueSet())
1045 return self.test._rhs_signals() | signals
1046
1047 def __repr__(self):
1048 cases = ["(default {})".format(" ".join(map(repr, stmts)))
1049 if key is None else
1050 "(case {} {})".format(key, " ".join(map(repr, stmts)))
1051 for key, stmts in self.cases.items()]
1052 return "(switch {!r} {})".format(self.test, " ".join(cases))
1053
1054
1055 @final
1056 class Delay(Statement):
1057 def __init__(self, interval=None):
1058 self.interval = None if interval is None else float(interval)
1059
1060 def _rhs_signals(self):
1061 return ValueSet()
1062
1063 def __repr__(self):
1064 if self.interval is None:
1065 return "(delay ε)"
1066 else:
1067 return "(delay {:.3}us)".format(self.interval * 1e6)
1068
1069
1070 @final
1071 class Tick(Statement):
1072 def __init__(self, domain="sync"):
1073 self.domain = str(domain)
1074
1075 def _rhs_signals(self):
1076 return ValueSet()
1077
1078 def __repr__(self):
1079 return "(tick {})".format(self.domain)
1080
1081
1082 @final
1083 class Passive(Statement):
1084 def _rhs_signals(self):
1085 return ValueSet()
1086
1087 def __repr__(self):
1088 return "(passive)"
1089
1090
1091 class _MappedKeyCollection(metaclass=ABCMeta):
1092 @abstractmethod
1093 def _map_key(self, key):
1094 pass # :nocov:
1095
1096 @abstractmethod
1097 def _unmap_key(self, key):
1098 pass # :nocov:
1099
1100
1101 class _MappedKeyDict(MutableMapping, _MappedKeyCollection):
1102 def __init__(self, pairs=()):
1103 self._storage = OrderedDict()
1104 for key, value in pairs:
1105 self[key] = value
1106
1107 def __getitem__(self, key):
1108 key = None if key is None else self._map_key(key)
1109 return self._storage[key]
1110
1111 def __setitem__(self, key, value):
1112 key = None if key is None else self._map_key(key)
1113 self._storage[key] = value
1114
1115 def __delitem__(self, key):
1116 key = None if key is None else self._map_key(key)
1117 del self._storage[key]
1118
1119 def __iter__(self):
1120 for key in self._storage:
1121 if key is None:
1122 yield None
1123 else:
1124 yield self._unmap_key(key)
1125
1126 def __eq__(self, other):
1127 if not isinstance(other, type(self)):
1128 return False
1129 if len(self) != len(other):
1130 return False
1131 for ak, bk in zip(sorted(self._storage), sorted(other._storage)):
1132 if ak != bk:
1133 return False
1134 if self._storage[ak] != other._storage[bk]:
1135 return False
1136 return True
1137
1138 def __len__(self):
1139 return len(self._storage)
1140
1141 def __repr__(self):
1142 pairs = ["({!r}, {!r})".format(k, v) for k, v in self.items()]
1143 return "{}.{}([{}])".format(type(self).__module__, type(self).__name__,
1144 ", ".join(pairs))
1145
1146
1147 class _MappedKeySet(MutableSet, _MappedKeyCollection):
1148 def __init__(self, elements=()):
1149 self._storage = OrderedDict()
1150 for elem in elements:
1151 self.add(elem)
1152
1153 def add(self, value):
1154 self._storage[self._map_key(value)] = None
1155
1156 def update(self, values):
1157 for value in values:
1158 self.add(value)
1159
1160 def discard(self, value):
1161 if value in self:
1162 del self._storage[self._map_key(value)]
1163
1164 def __contains__(self, value):
1165 return self._map_key(value) in self._storage
1166
1167 def __iter__(self):
1168 for key in [k for k in self._storage]:
1169 yield self._unmap_key(key)
1170
1171 def __len__(self):
1172 return len(self._storage)
1173
1174 def __repr__(self):
1175 return "{}.{}({})".format(type(self).__module__, type(self).__name__,
1176 ", ".join(repr(x) for x in self))
1177
1178
1179 class ValueKey:
1180 def __init__(self, value):
1181 self.value = Value.wrap(value)
1182
1183 def __hash__(self):
1184 if isinstance(self.value, Const):
1185 return hash(self.value.value)
1186 elif isinstance(self.value, (Signal, AnyValue)):
1187 return hash(self.value.duid)
1188 elif isinstance(self.value, (ClockSignal, ResetSignal)):
1189 return hash(self.value.domain)
1190 elif isinstance(self.value, Operator):
1191 return hash((self.value.op, tuple(ValueKey(o) for o in self.value.operands)))
1192 elif isinstance(self.value, Slice):
1193 return hash((ValueKey(self.value.value), self.value.start, self.value.end))
1194 elif isinstance(self.value, Part):
1195 return hash((ValueKey(self.value.value), ValueKey(self.value.offset),
1196 self.value.width))
1197 elif isinstance(self.value, Cat):
1198 return hash(tuple(ValueKey(o) for o in self.value.parts))
1199 elif isinstance(self.value, ArrayProxy):
1200 return hash((ValueKey(self.value.index),
1201 tuple(ValueKey(e) for e in self.value._iter_as_values())))
1202 elif isinstance(self.value, Sample):
1203 return hash((ValueKey(self.value.value), self.value.clocks, self.value.domain))
1204 else: # :nocov:
1205 raise TypeError("Object '{!r}' cannot be used as a key in value collections"
1206 .format(self.value))
1207
1208 def __eq__(self, other):
1209 if type(other) is not ValueKey:
1210 return False
1211 if type(self.value) is not type(other.value):
1212 return False
1213
1214 if isinstance(self.value, Const):
1215 return self.value.value == other.value.value
1216 elif isinstance(self.value, (Signal, AnyValue)):
1217 return self.value is other.value
1218 elif isinstance(self.value, (ClockSignal, ResetSignal)):
1219 return self.value.domain == other.value.domain
1220 elif isinstance(self.value, Operator):
1221 return (self.value.op == other.value.op and
1222 len(self.value.operands) == len(other.value.operands) and
1223 all(ValueKey(a) == ValueKey(b)
1224 for a, b in zip(self.value.operands, other.value.operands)))
1225 elif isinstance(self.value, Slice):
1226 return (ValueKey(self.value.value) == ValueKey(other.value.value) and
1227 self.value.start == other.value.start and
1228 self.value.end == other.value.end)
1229 elif isinstance(self.value, Part):
1230 return (ValueKey(self.value.value) == ValueKey(other.value.value) and
1231 ValueKey(self.value.offset) == ValueKey(other.value.offset) and
1232 self.value.width == other.value.width)
1233 elif isinstance(self.value, Cat):
1234 return all(ValueKey(a) == ValueKey(b)
1235 for a, b in zip(self.value.parts, other.value.parts))
1236 elif isinstance(self.value, ArrayProxy):
1237 return (ValueKey(self.value.index) == ValueKey(other.value.index) and
1238 len(self.value.elems) == len(other.value.elems) and
1239 all(ValueKey(a) == ValueKey(b)
1240 for a, b in zip(self.value._iter_as_values(),
1241 other.value._iter_as_values())))
1242 elif isinstance(self.value, Sample):
1243 return (ValueKey(self.value.value) == ValueKey(other.value.value) and
1244 self.value.clocks == other.value.clocks and
1245 self.value.domain == self.value.domain)
1246 else: # :nocov:
1247 raise TypeError("Object '{!r}' cannot be used as a key in value collections"
1248 .format(self.value))
1249
1250 def __lt__(self, other):
1251 if not isinstance(other, ValueKey):
1252 return False
1253 if type(self.value) != type(other.value):
1254 return False
1255
1256 if isinstance(self.value, Const):
1257 return self.value < other.value
1258 elif isinstance(self.value, (Signal, AnyValue)):
1259 return self.value.duid < other.value.duid
1260 elif isinstance(self.value, Slice):
1261 return (ValueKey(self.value.value) < ValueKey(other.value.value) and
1262 self.value.start < other.value.start and
1263 self.value.end < other.value.end)
1264 else: # :nocov:
1265 raise TypeError("Object '{!r}' cannot be used as a key in value collections")
1266
1267 def __repr__(self):
1268 return "<{}.ValueKey {!r}>".format(__name__, self.value)
1269
1270
1271 class ValueDict(_MappedKeyDict):
1272 _map_key = ValueKey
1273 _unmap_key = lambda self, key: key.value
1274
1275
1276 class ValueSet(_MappedKeySet):
1277 _map_key = ValueKey
1278 _unmap_key = lambda self, key: key.value
1279
1280
1281 class SignalKey:
1282 def __init__(self, signal):
1283 if type(signal) is Signal:
1284 self._intern = (0, signal.duid)
1285 elif type(signal) is ClockSignal:
1286 self._intern = (1, signal.domain)
1287 elif type(signal) is ResetSignal:
1288 self._intern = (2, signal.domain)
1289 else:
1290 raise TypeError("Object '{!r}' is not an nMigen signal".format(signal))
1291 self.signal = signal
1292
1293 def __hash__(self):
1294 return hash(self._intern)
1295
1296 def __eq__(self, other):
1297 if type(other) is not SignalKey:
1298 return False
1299 return self._intern == other._intern
1300
1301 def __lt__(self, other):
1302 if type(other) is not SignalKey:
1303 raise TypeError("Object '{!r}' cannot be compared to a SignalKey".format(signal))
1304 return self._intern < other._intern
1305
1306 def __repr__(self):
1307 return "<{}.SignalKey {!r}>".format(__name__, self.signal)
1308
1309
1310 class SignalDict(_MappedKeyDict):
1311 _map_key = SignalKey
1312 _unmap_key = lambda self, key: key.signal
1313
1314
1315 class SignalSet(_MappedKeySet):
1316 _map_key = SignalKey
1317 _unmap_key = lambda self, key: key.signal