hdl.{ast,dsl}, back.{pysim,rtlil}: allow multiple case values.
[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 keys, stmts in cases.items():
1023 # Map: None -> (); key -> (key,); (key...) -> (key...)
1024 if keys is None:
1025 keys = ()
1026 if not isinstance(keys, tuple):
1027 keys = (keys,)
1028 # Map: 2 -> "0010"; "0010" -> "0010"
1029 new_keys = ()
1030 for key in keys:
1031 if isinstance(key, (bool, int)):
1032 key = "{:0{}b}".format(key, len(self.test))
1033 elif isinstance(key, str):
1034 pass
1035 else:
1036 raise TypeError("Object '{!r}' cannot be used as a switch key"
1037 .format(key))
1038 assert len(key) == len(self.test)
1039 new_keys = (*new_keys, key)
1040 if not isinstance(stmts, Iterable):
1041 stmts = [stmts]
1042 self.cases[new_keys] = Statement.wrap(stmts)
1043
1044 def _lhs_signals(self):
1045 signals = union((s._lhs_signals() for ss in self.cases.values() for s in ss),
1046 start=ValueSet())
1047 return signals
1048
1049 def _rhs_signals(self):
1050 signals = union((s._rhs_signals() for ss in self.cases.values() for s in ss),
1051 start=ValueSet())
1052 return self.test._rhs_signals() | signals
1053
1054 def __repr__(self):
1055 def case_repr(keys, stmts):
1056 stmts_repr = " ".join(map(repr, stmts))
1057 if keys == ():
1058 return "(default {})".format(stmts_repr)
1059 elif len(keys) == 1:
1060 return "(case {} {})".format(keys[0], stmts_repr)
1061 else:
1062 return "(case ({}) {})".format(" ".join(keys), stmts_repr)
1063 case_reprs = [case_repr(keys, stmts) for keys, stmts in self.cases.items()]
1064 return "(switch {!r} {})".format(self.test, " ".join(case_reprs))
1065
1066
1067 @final
1068 class Delay(Statement):
1069 def __init__(self, interval=None):
1070 self.interval = None if interval is None else float(interval)
1071
1072 def _rhs_signals(self):
1073 return ValueSet()
1074
1075 def __repr__(self):
1076 if self.interval is None:
1077 return "(delay ε)"
1078 else:
1079 return "(delay {:.3}us)".format(self.interval * 1e6)
1080
1081
1082 @final
1083 class Tick(Statement):
1084 def __init__(self, domain="sync"):
1085 self.domain = str(domain)
1086
1087 def _rhs_signals(self):
1088 return ValueSet()
1089
1090 def __repr__(self):
1091 return "(tick {})".format(self.domain)
1092
1093
1094 @final
1095 class Passive(Statement):
1096 def _rhs_signals(self):
1097 return ValueSet()
1098
1099 def __repr__(self):
1100 return "(passive)"
1101
1102
1103 class _MappedKeyCollection(metaclass=ABCMeta):
1104 @abstractmethod
1105 def _map_key(self, key):
1106 pass # :nocov:
1107
1108 @abstractmethod
1109 def _unmap_key(self, key):
1110 pass # :nocov:
1111
1112
1113 class _MappedKeyDict(MutableMapping, _MappedKeyCollection):
1114 def __init__(self, pairs=()):
1115 self._storage = OrderedDict()
1116 for key, value in pairs:
1117 self[key] = value
1118
1119 def __getitem__(self, key):
1120 key = None if key is None else self._map_key(key)
1121 return self._storage[key]
1122
1123 def __setitem__(self, key, value):
1124 key = None if key is None else self._map_key(key)
1125 self._storage[key] = value
1126
1127 def __delitem__(self, key):
1128 key = None if key is None else self._map_key(key)
1129 del self._storage[key]
1130
1131 def __iter__(self):
1132 for key in self._storage:
1133 if key is None:
1134 yield None
1135 else:
1136 yield self._unmap_key(key)
1137
1138 def __eq__(self, other):
1139 if not isinstance(other, type(self)):
1140 return False
1141 if len(self) != len(other):
1142 return False
1143 for ak, bk in zip(sorted(self._storage), sorted(other._storage)):
1144 if ak != bk:
1145 return False
1146 if self._storage[ak] != other._storage[bk]:
1147 return False
1148 return True
1149
1150 def __len__(self):
1151 return len(self._storage)
1152
1153 def __repr__(self):
1154 pairs = ["({!r}, {!r})".format(k, v) for k, v in self.items()]
1155 return "{}.{}([{}])".format(type(self).__module__, type(self).__name__,
1156 ", ".join(pairs))
1157
1158
1159 class _MappedKeySet(MutableSet, _MappedKeyCollection):
1160 def __init__(self, elements=()):
1161 self._storage = OrderedDict()
1162 for elem in elements:
1163 self.add(elem)
1164
1165 def add(self, value):
1166 self._storage[self._map_key(value)] = None
1167
1168 def update(self, values):
1169 for value in values:
1170 self.add(value)
1171
1172 def discard(self, value):
1173 if value in self:
1174 del self._storage[self._map_key(value)]
1175
1176 def __contains__(self, value):
1177 return self._map_key(value) in self._storage
1178
1179 def __iter__(self):
1180 for key in [k for k in self._storage]:
1181 yield self._unmap_key(key)
1182
1183 def __len__(self):
1184 return len(self._storage)
1185
1186 def __repr__(self):
1187 return "{}.{}({})".format(type(self).__module__, type(self).__name__,
1188 ", ".join(repr(x) for x in self))
1189
1190
1191 class ValueKey:
1192 def __init__(self, value):
1193 self.value = Value.wrap(value)
1194
1195 def __hash__(self):
1196 if isinstance(self.value, Const):
1197 return hash(self.value.value)
1198 elif isinstance(self.value, (Signal, AnyValue)):
1199 return hash(self.value.duid)
1200 elif isinstance(self.value, (ClockSignal, ResetSignal)):
1201 return hash(self.value.domain)
1202 elif isinstance(self.value, Operator):
1203 return hash((self.value.op, tuple(ValueKey(o) for o in self.value.operands)))
1204 elif isinstance(self.value, Slice):
1205 return hash((ValueKey(self.value.value), self.value.start, self.value.end))
1206 elif isinstance(self.value, Part):
1207 return hash((ValueKey(self.value.value), ValueKey(self.value.offset),
1208 self.value.width))
1209 elif isinstance(self.value, Cat):
1210 return hash(tuple(ValueKey(o) for o in self.value.parts))
1211 elif isinstance(self.value, ArrayProxy):
1212 return hash((ValueKey(self.value.index),
1213 tuple(ValueKey(e) for e in self.value._iter_as_values())))
1214 elif isinstance(self.value, Sample):
1215 return hash((ValueKey(self.value.value), self.value.clocks, self.value.domain))
1216 else: # :nocov:
1217 raise TypeError("Object '{!r}' cannot be used as a key in value collections"
1218 .format(self.value))
1219
1220 def __eq__(self, other):
1221 if type(other) is not ValueKey:
1222 return False
1223 if type(self.value) is not type(other.value):
1224 return False
1225
1226 if isinstance(self.value, Const):
1227 return self.value.value == other.value.value
1228 elif isinstance(self.value, (Signal, AnyValue)):
1229 return self.value is other.value
1230 elif isinstance(self.value, (ClockSignal, ResetSignal)):
1231 return self.value.domain == other.value.domain
1232 elif isinstance(self.value, Operator):
1233 return (self.value.op == other.value.op and
1234 len(self.value.operands) == len(other.value.operands) and
1235 all(ValueKey(a) == ValueKey(b)
1236 for a, b in zip(self.value.operands, other.value.operands)))
1237 elif isinstance(self.value, Slice):
1238 return (ValueKey(self.value.value) == ValueKey(other.value.value) and
1239 self.value.start == other.value.start and
1240 self.value.end == other.value.end)
1241 elif isinstance(self.value, Part):
1242 return (ValueKey(self.value.value) == ValueKey(other.value.value) and
1243 ValueKey(self.value.offset) == ValueKey(other.value.offset) and
1244 self.value.width == other.value.width)
1245 elif isinstance(self.value, Cat):
1246 return all(ValueKey(a) == ValueKey(b)
1247 for a, b in zip(self.value.parts, other.value.parts))
1248 elif isinstance(self.value, ArrayProxy):
1249 return (ValueKey(self.value.index) == ValueKey(other.value.index) and
1250 len(self.value.elems) == len(other.value.elems) and
1251 all(ValueKey(a) == ValueKey(b)
1252 for a, b in zip(self.value._iter_as_values(),
1253 other.value._iter_as_values())))
1254 elif isinstance(self.value, Sample):
1255 return (ValueKey(self.value.value) == ValueKey(other.value.value) and
1256 self.value.clocks == other.value.clocks and
1257 self.value.domain == self.value.domain)
1258 else: # :nocov:
1259 raise TypeError("Object '{!r}' cannot be used as a key in value collections"
1260 .format(self.value))
1261
1262 def __lt__(self, other):
1263 if not isinstance(other, ValueKey):
1264 return False
1265 if type(self.value) != type(other.value):
1266 return False
1267
1268 if isinstance(self.value, Const):
1269 return self.value < other.value
1270 elif isinstance(self.value, (Signal, AnyValue)):
1271 return self.value.duid < other.value.duid
1272 elif isinstance(self.value, Slice):
1273 return (ValueKey(self.value.value) < ValueKey(other.value.value) and
1274 self.value.start < other.value.start and
1275 self.value.end < other.value.end)
1276 else: # :nocov:
1277 raise TypeError("Object '{!r}' cannot be used as a key in value collections")
1278
1279 def __repr__(self):
1280 return "<{}.ValueKey {!r}>".format(__name__, self.value)
1281
1282
1283 class ValueDict(_MappedKeyDict):
1284 _map_key = ValueKey
1285 _unmap_key = lambda self, key: key.value
1286
1287
1288 class ValueSet(_MappedKeySet):
1289 _map_key = ValueKey
1290 _unmap_key = lambda self, key: key.value
1291
1292
1293 class SignalKey:
1294 def __init__(self, signal):
1295 if type(signal) is Signal:
1296 self._intern = (0, signal.duid)
1297 elif type(signal) is ClockSignal:
1298 self._intern = (1, signal.domain)
1299 elif type(signal) is ResetSignal:
1300 self._intern = (2, signal.domain)
1301 else:
1302 raise TypeError("Object '{!r}' is not an nMigen signal".format(signal))
1303 self.signal = signal
1304
1305 def __hash__(self):
1306 return hash(self._intern)
1307
1308 def __eq__(self, other):
1309 if type(other) is not SignalKey:
1310 return False
1311 return self._intern == other._intern
1312
1313 def __lt__(self, other):
1314 if type(other) is not SignalKey:
1315 raise TypeError("Object '{!r}' cannot be compared to a SignalKey".format(signal))
1316 return self._intern < other._intern
1317
1318 def __repr__(self):
1319 return "<{}.SignalKey {!r}>".format(__name__, self.signal)
1320
1321
1322 class SignalDict(_MappedKeyDict):
1323 _map_key = SignalKey
1324 _unmap_key = lambda self, key: key.signal
1325
1326
1327 class SignalSet(_MappedKeySet):
1328 _map_key = SignalKey
1329 _unmap_key = lambda self, key: key.signal