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