import migen in litex/gen
[litex.git] / litex / gen / migen / fhdl / structure.py
1 import builtins as _builtins
2 import collections as _collections
3
4 from migen.fhdl import tracer as _tracer
5 from migen.util.misc import flat_iteration as _flat_iteration
6
7
8 class DUID:
9 """Deterministic Unique IDentifier"""
10 __next_uid = 0
11 def __init__(self):
12 self.duid = DUID.__next_uid
13 DUID.__next_uid += 1
14
15
16 class _Value(DUID):
17 """Base class for operands
18
19 Instances of `_Value` or its subclasses can be operands to
20 arithmetic, comparison, bitwise, and logic operators.
21 They can be assigned (:meth:`eq`) or indexed/sliced (using the usual
22 Python indexing and slicing notation).
23
24 Values created from integers have the minimum bit width to necessary to
25 represent the integer.
26 """
27 def __bool__(self):
28 # Special case: Constants and Signals are part of a set or used as
29 # dictionary keys, and Python needs to check for equality.
30 if isinstance(self, _Operator) and self.op == "==":
31 a, b = self.operands
32 if isinstance(a, Constant) and isinstance(b, Constant):
33 return a.value == b.value
34 if isinstance(a, Signal) and isinstance(b, Signal):
35 return a is b
36 if (isinstance(a, Constant) and isinstance(b, Signal)
37 or isinstance(a, Signal) and isinstance(a, Constant)):
38 return False
39 raise TypeError("Attempted to convert Migen value to boolean")
40
41 def __invert__(self):
42 return _Operator("~", [self])
43 def __neg__(self):
44 return _Operator("-", [self])
45
46 def __add__(self, other):
47 return _Operator("+", [self, other])
48 def __radd__(self, other):
49 return _Operator("+", [other, self])
50 def __sub__(self, other):
51 return _Operator("-", [self, other])
52 def __rsub__(self, other):
53 return _Operator("-", [other, self])
54 def __mul__(self, other):
55 return _Operator("*", [self, other])
56 def __rmul__(self, other):
57 return _Operator("*", [other, self])
58 def __lshift__(self, other):
59 return _Operator("<<<", [self, other])
60 def __rlshift__(self, other):
61 return _Operator("<<<", [other, self])
62 def __rshift__(self, other):
63 return _Operator(">>>", [self, other])
64 def __rrshift__(self, other):
65 return _Operator(">>>", [other, self])
66 def __and__(self, other):
67 return _Operator("&", [self, other])
68 def __rand__(self, other):
69 return _Operator("&", [other, self])
70 def __xor__(self, other):
71 return _Operator("^", [self, other])
72 def __rxor__(self, other):
73 return _Operator("^", [other, self])
74 def __or__(self, other):
75 return _Operator("|", [self, other])
76 def __ror__(self, other):
77 return _Operator("|", [other, self])
78
79 def __lt__(self, other):
80 return _Operator("<", [self, other])
81 def __le__(self, other):
82 return _Operator("<=", [self, other])
83 def __eq__(self, other):
84 return _Operator("==", [self, other])
85 def __ne__(self, other):
86 return _Operator("!=", [self, other])
87 def __gt__(self, other):
88 return _Operator(">", [self, other])
89 def __ge__(self, other):
90 return _Operator(">=", [self, other])
91
92 def __len__(self):
93 from migen.fhdl.bitcontainer import value_bits_sign
94 return value_bits_sign(self)[0]
95
96 def __getitem__(self, key):
97 n = len(self)
98 if isinstance(key, int):
99 if key >= n:
100 raise IndexError
101 if key < 0:
102 key += n
103 return _Slice(self, key, key+1)
104 elif isinstance(key, slice):
105 start, stop, step = key.indices(n)
106 if step != 1:
107 return Cat(self[i] for i in range(start, stop, step))
108 return _Slice(self, start, stop)
109 else:
110 raise TypeError
111
112 def eq(self, r):
113 """Assignment
114
115 Parameters
116 ----------
117 r : _Value, in
118 Value to be assigned.
119
120 Returns
121 -------
122 _Assign
123 Assignment statement that can be used in combinatorial or
124 synchronous context.
125 """
126 return _Assign(self, r)
127
128 def __hash__(self):
129 raise TypeError("unhashable type: '{}'".format(type(self).__name__))
130
131
132 def wrap(value):
133 """Ensures that the passed object is a Migen value. Booleans and integers
134 are automatically wrapped into ``Constant``."""
135 if isinstance(value, (bool, int)):
136 value = Constant(value)
137 if not isinstance(value, _Value):
138 raise TypeError("Object is not a Migen value")
139 return value
140
141
142 class _Operator(_Value):
143 def __init__(self, op, operands):
144 _Value.__init__(self)
145 self.op = op
146 self.operands = [wrap(o) for o in operands]
147
148
149 def Mux(sel, val1, val0):
150 """Multiplex between two values
151
152 Parameters
153 ----------
154 sel : _Value(1), in
155 Selector.
156 val1 : _Value(N), in
157 val0 : _Value(N), in
158 Input values.
159
160 Returns
161 -------
162 _Value(N), out
163 Output `_Value`. If `sel` is asserted, the Mux returns
164 `val1`, else `val0`.
165 """
166 return _Operator("m", [sel, val1, val0])
167
168
169 class _Slice(_Value):
170 def __init__(self, value, start, stop):
171 _Value.__init__(self)
172 if not isinstance(start, int) or not isinstance(stop, int):
173 raise TypeError("Slice boundaries must be integers")
174 self.value = wrap(value)
175 self.start = start
176 self.stop = stop
177
178
179 class Cat(_Value):
180 """Concatenate values
181
182 Form a compound `_Value` from several smaller ones by concatenation.
183 The first argument occupies the lower bits of the result.
184 The return value can be used on either side of an assignment, that
185 is, the concatenated value can be used as an argument on the RHS or
186 as a target on the LHS. If it is used on the LHS, it must solely
187 consist of `Signal` s, slices of `Signal` s, and other concatenations
188 meeting these properties. The bit length of the return value is the sum of
189 the bit lengths of the arguments::
190
191 len(Cat(args)) == sum(len(arg) for arg in args)
192
193 Parameters
194 ----------
195 *args : _Values or iterables of _Values, inout
196 `_Value` s to be concatenated.
197
198 Returns
199 -------
200 Cat, inout
201 Resulting `_Value` obtained by concatentation.
202 """
203 def __init__(self, *args):
204 _Value.__init__(self)
205 self.l = [wrap(v) for v in _flat_iteration(args)]
206
207
208 class Replicate(_Value):
209 """Replicate a value
210
211 An input value is replicated (repeated) several times
212 to be used on the RHS of assignments::
213
214 len(Replicate(s, n)) == len(s)*n
215
216 Parameters
217 ----------
218 v : _Value, in
219 Input value to be replicated.
220 n : int
221 Number of replications.
222
223 Returns
224 -------
225 Replicate, out
226 Replicated value.
227 """
228 def __init__(self, v, n):
229 _Value.__init__(self)
230 if not isinstance(n, int) or n < 0:
231 raise TypeError("Replication count must be a positive integer")
232 self.v = wrap(v)
233 self.n = n
234
235
236 class Constant(_Value):
237 """A constant, HDL-literal integer `_Value`
238
239 Parameters
240 ----------
241 value : int
242 bits_sign : int or tuple or None
243 Either an integer `bits` or a tuple `(bits, signed)`
244 specifying the number of bits in this `Constant` and whether it is
245 signed (can represent negative values). `bits_sign` defaults
246 to the minimum width and signedness of `value`.
247 """
248 def __init__(self, value, bits_sign=None):
249 from migen.fhdl.bitcontainer import bits_for
250
251 _Value.__init__(self)
252
253 self.value = int(value)
254 if bits_sign is None:
255 bits_sign = bits_for(self.value), self.value < 0
256 elif isinstance(bits_sign, int):
257 bits_sign = bits_sign, self.value < 0
258 self.nbits, self.signed = bits_sign
259 if not isinstance(self.nbits, int) or self.nbits <= 0:
260 raise TypeError("Width must be a strictly positive integer")
261
262 def __hash__(self):
263 return self.value
264
265
266 C = Constant # shorthand
267
268
269 class Signal(_Value):
270 """A `_Value` that can change
271
272 The `Signal` object represents a value that is expected to change
273 in the circuit. It does exactly what Verilog's `wire` and
274 `reg` and VHDL's `signal` do.
275
276 A `Signal` can be indexed to access a subset of its bits. Negative
277 indices (`signal[-1]`) and the extended Python slicing notation
278 (`signal[start:stop:step]`) are supported.
279 The indices 0 and -1 are the least and most significant bits
280 respectively.
281
282 Parameters
283 ----------
284 bits_sign : int or tuple
285 Either an integer `bits` or a tuple `(bits, signed)`
286 specifying the number of bits in this `Signal` and whether it is
287 signed (can represent negative values). `signed` defaults to
288 `False`.
289 name : str or None
290 Name hint for this signal. If `None` (default) the name is
291 inferred from the variable name this `Signal` is assigned to.
292 Name collisions are automatically resolved by prepending
293 names of objects that contain this `Signal` and by
294 appending integer sequences.
295 variable : bool
296 Deprecated.
297 reset : int
298 Reset (synchronous) or default (combinatorial) value.
299 When this `Signal` is assigned to in synchronous context and the
300 corresponding clock domain is reset, the `Signal` assumes the
301 given value. When this `Signal` is unassigned in combinatorial
302 context (due to conditional assignments not being taken),
303 the `Signal` assumes its `reset` value. Defaults to 0.
304 name_override : str or None
305 Do not use the inferred name but the given one.
306 min : int or None
307 max : int or None
308 If `bits_sign` is `None`, the signal bit width and signedness are
309 determined by the integer range given by `min` (inclusive,
310 defaults to 0) and `max` (exclusive, defaults to 2).
311 related : Signal or None
312 """
313 def __init__(self, bits_sign=None, name=None, variable=False, reset=0, name_override=None, min=None, max=None, related=None):
314 from migen.fhdl.bitcontainer import bits_for
315
316 _Value.__init__(self)
317
318 # determine number of bits and signedness
319 if bits_sign is None:
320 if min is None:
321 min = 0
322 if max is None:
323 max = 2
324 max -= 1 # make both bounds inclusive
325 assert(min < max)
326 self.signed = min < 0 or max < 0
327 self.nbits = _builtins.max(bits_for(min, self.signed), bits_for(max, self.signed))
328 else:
329 assert(min is None and max is None)
330 if isinstance(bits_sign, tuple):
331 self.nbits, self.signed = bits_sign
332 else:
333 self.nbits, self.signed = bits_sign, False
334 if not isinstance(self.nbits, int) or self.nbits <= 0:
335 raise ValueError("Signal width must be a strictly positive integer")
336
337 self.variable = variable # deprecated
338 self.reset = reset
339 self.name_override = name_override
340 self.backtrace = _tracer.trace_back(name)
341 self.related = related
342
343 def __setattr__(self, k, v):
344 if k == "reset":
345 v = wrap(v)
346 _Value.__setattr__(self, k, v)
347
348 def __repr__(self):
349 return "<Signal " + (self.backtrace[-1][0] or "anonymous") + " at " + hex(id(self)) + ">"
350
351 @classmethod
352 def like(cls, other, **kwargs):
353 """Create Signal based on another.
354
355 Parameters
356 ----------
357 other : _Value
358 Object to base this Signal on.
359
360 See `migen.fhdl.bitcontainer.value_bits_sign` for details.
361 """
362 from migen.fhdl.bitcontainer import value_bits_sign
363 return cls(bits_sign=value_bits_sign(other), **kwargs)
364
365 def __hash__(self):
366 return self.duid
367
368
369 class ClockSignal(_Value):
370 """Clock signal for a given clock domain
371
372 `ClockSignal` s for a given clock domain can be retrieved multiple
373 times. They all ultimately refer to the same signal.
374
375 Parameters
376 ----------
377 cd : str
378 Clock domain to obtain a clock signal for. Defaults to `"sys"`.
379 """
380 def __init__(self, cd="sys"):
381 _Value.__init__(self)
382 if not isinstance(cd, str):
383 raise TypeError("Argument of ClockSignal must be a string")
384 self.cd = cd
385
386
387 class ResetSignal(_Value):
388 """Reset signal for a given clock domain
389
390 `ResetSignal` s for a given clock domain can be retrieved multiple
391 times. They all ultimately refer to the same signal.
392
393 Parameters
394 ----------
395 cd : str
396 Clock domain to obtain a reset signal for. Defaults to `"sys"`.
397 allow_reset_less : bool
398 If the clock domain is resetless, return 0 instead of reporting an
399 error.
400 """
401 def __init__(self, cd="sys", allow_reset_less=False):
402 _Value.__init__(self)
403 if not isinstance(cd, str):
404 raise TypeError("Argument of ResetSignal must be a string")
405 self.cd = cd
406 self.allow_reset_less = allow_reset_less
407
408
409 # statements
410
411
412 class _Statement:
413 pass
414
415
416 class _Assign(_Statement):
417 def __init__(self, l, r):
418 self.l = wrap(l)
419 self.r = wrap(r)
420
421
422 def _check_statement(s):
423 if isinstance(s, _collections.Iterable):
424 return all(_check_statement(ss) for ss in s)
425 else:
426 return isinstance(s, _Statement)
427
428
429 class If(_Statement):
430 """Conditional execution of statements
431
432 Parameters
433 ----------
434 cond : _Value(1), in
435 Condition
436 *t : Statements
437 Statements to execute if `cond` is asserted.
438
439 Examples
440 --------
441 >>> a = Signal()
442 >>> b = Signal()
443 >>> c = Signal()
444 >>> d = Signal()
445 >>> If(a,
446 ... b.eq(1)
447 ... ).Elif(c,
448 ... b.eq(0)
449 ... ).Else(
450 ... b.eq(d)
451 ... )
452 """
453 def __init__(self, cond, *t):
454 if not _check_statement(t):
455 raise TypeError("Not all test body objects are Migen statements")
456 self.cond = wrap(cond)
457 self.t = list(t)
458 self.f = []
459
460 def Else(self, *f):
461 """Add an `else` conditional block
462
463 Parameters
464 ----------
465 *f : Statements
466 Statements to execute if all previous conditions fail.
467 """
468 if not _check_statement(f):
469 raise TypeError("Not all test body objects are Migen statements")
470 _insert_else(self, list(f))
471 return self
472
473 def Elif(self, cond, *t):
474 """Add an `else if` conditional block
475
476 Parameters
477 ----------
478 cond : _Value(1), in
479 Condition
480 *t : Statements
481 Statements to execute if previous conditions fail and `cond`
482 is asserted.
483 """
484 _insert_else(self, [If(cond, *t)])
485 return self
486
487
488 def _insert_else(obj, clause):
489 o = obj
490 while o.f:
491 assert(len(o.f) == 1)
492 assert(isinstance(o.f[0], If))
493 o = o.f[0]
494 o.f = clause
495
496
497 class Case(_Statement):
498 """Case/Switch statement
499
500 Parameters
501 ----------
502 test : _Value, in
503 Selector value used to decide which block to execute
504 cases : dict
505 Dictionary of cases. The keys are numeric constants to compare
506 with `test`. The values are statements to be executed the
507 corresponding key matches `test`. The dictionary may contain a
508 string key `"default"` to mark a fall-through case that is
509 executed if no other key matches.
510
511 Examples
512 --------
513 >>> a = Signal()
514 >>> b = Signal()
515 >>> Case(a, {
516 ... 0: b.eq(1),
517 ... 1: b.eq(0),
518 ... "default": b.eq(0),
519 ... })
520 """
521 def __init__(self, test, cases):
522 self.test = wrap(test)
523 self.cases = dict()
524 for k, v in cases.items():
525 if isinstance(k, (bool, int)):
526 k = Constant(k)
527 if (not isinstance(k, Constant)
528 and not (isinstance(k, str) and k == "default")):
529 raise TypeError("Case object is not a Migen constant")
530 if not isinstance(v, _collections.Iterable):
531 v = [v]
532 if not _check_statement(v):
533 raise TypeError("Not all objects for case {} "
534 "are Migen statements".format(k))
535 self.cases[k] = v
536
537 def makedefault(self, key=None):
538 """Mark a key as the default case
539
540 Deletes/substitutes any previously existing default case.
541
542 Parameters
543 ----------
544 key : int or None
545 Key to use as default case if no other key matches.
546 By default, the largest key is the default key.
547 """
548 if key is None:
549 for choice in self.cases.keys():
550 if key is None or choice.value > key.value:
551 key = choice
552 self.cases["default"] = self.cases[key]
553 del self.cases[key]
554 return self
555
556
557 # arrays
558
559
560 class _ArrayProxy(_Value):
561 def __init__(self, choices, key):
562 _Value.__init__(self)
563 self.choices = []
564 for c in choices:
565 if isinstance(c, (bool, int)):
566 c = Constant(c)
567 self.choices.append(c)
568 self.key = key
569
570 def __getattr__(self, attr):
571 return _ArrayProxy([getattr(choice, attr) for choice in self.choices],
572 self.key)
573
574 def __getitem__(self, key):
575 return _ArrayProxy([choice.__getitem__(key) for choice in self.choices],
576 self.key)
577
578
579 class Array(list):
580 """Addressable multiplexer
581
582 An array is created from an iterable of values and indexed using the
583 usual Python simple indexing notation (no negative indices or
584 slices). It can be indexed by numeric constants, `_Value` s, or
585 `Signal` s.
586
587 The result of indexing the array is a proxy for the entry at the
588 given index that can be used on either RHS or LHS of assignments.
589
590 An array can be indexed multiple times.
591
592 Multidimensional arrays are supported by packing inner arrays into
593 outer arrays.
594
595 Parameters
596 ----------
597 values : iterable of ints, _Values, Signals
598 Entries of the array. Each entry can be a numeric constant, a
599 `Signal` or a `Record`.
600
601 Examples
602 --------
603 >>> a = Array(range(10))
604 >>> b = Signal(max=10)
605 >>> c = Signal(max=10)
606 >>> b.eq(a[9 - c])
607 """
608 def __getitem__(self, key):
609 if isinstance(key, Constant):
610 return list.__getitem__(self, key.value)
611 elif isinstance(key, _Value):
612 return _ArrayProxy(self, key)
613 else:
614 return list.__getitem__(self, key)
615
616
617 class ClockDomain:
618 """Synchronous domain
619
620 Parameters
621 ----------
622 name : str or None
623 Domain name. If None (the default) the name is inferred from the
624 variable name this `ClockDomain` is assigned to (stripping any
625 `"cd_"` prefix).
626 reset_less : bool
627 The domain does not use a reset signal. Registers within this
628 domain are still all initialized to their reset state once, e.g.
629 through Verilog `"initial"` statements.
630
631 Attributes
632 ----------
633 clk : Signal, inout
634 The clock for this domain. Can be driven or used to drive other
635 signals (preferably in combinatorial context).
636 rst : Signal or None, inout
637 Reset signal for this domain. Can be driven or used to drive.
638 """
639 def __init__(self, name=None, reset_less=False):
640 self.name = _tracer.get_obj_var_name(name)
641 if self.name is None:
642 raise ValueError("Cannot extract clock domain name from code, need to specify.")
643 if self.name.startswith("cd_"):
644 self.name = self.name[3:]
645 if self.name[0].isdigit():
646 raise ValueError("Clock domain name cannot start with a number.")
647 self.clk = Signal(name_override=self.name + "_clk")
648 if reset_less:
649 self.rst = None
650 else:
651 self.rst = Signal(name_override=self.name + "_rst")
652
653 def rename(self, new_name):
654 """Rename the clock domain
655
656 Parameters
657 ----------
658 new_name : str
659 New name
660 """
661 self.name = new_name
662 self.clk.name_override = new_name + "_clk"
663 if self.rst is not None:
664 self.rst.name_override = new_name + "_rst"
665
666
667 class _ClockDomainList(list):
668 def __getitem__(self, key):
669 if isinstance(key, str):
670 for cd in self:
671 if cd.name == key:
672 return cd
673 raise KeyError(key)
674 else:
675 return list.__getitem__(self, key)
676
677
678 (SPECIAL_INPUT, SPECIAL_OUTPUT, SPECIAL_INOUT) = range(3)
679
680
681 class _Fragment:
682 def __init__(self, comb=None, sync=None, specials=None, clock_domains=None):
683 if comb is None: comb = []
684 if sync is None: sync = dict()
685 if specials is None: specials = set()
686 if clock_domains is None: clock_domains = _ClockDomainList()
687
688 self.comb = comb
689 self.sync = sync
690 self.specials = specials
691 self.clock_domains = _ClockDomainList(clock_domains)
692
693 def __add__(self, other):
694 newsync = _collections.defaultdict(list)
695 for k, v in self.sync.items():
696 newsync[k] = v[:]
697 for k, v in other.sync.items():
698 newsync[k].extend(v)
699 return _Fragment(self.comb + other.comb, newsync,
700 self.specials | other.specials,
701 self.clock_domains + other.clock_domains)
702
703 def __iadd__(self, other):
704 newsync = _collections.defaultdict(list)
705 for k, v in self.sync.items():
706 newsync[k] = v[:]
707 for k, v in other.sync.items():
708 newsync[k].extend(v)
709 self.comb += other.comb
710 self.sync = newsync
711 self.specials |= other.specials
712 self.clock_domains += other.clock_domains
713 return self