litex/migen/fhdl/structure.py

291 lines
7.1 KiB
Python
Raw Normal View History

import inspect
import re
import builtins
from collections import defaultdict
from migen.fhdl import tracer
2012-01-16 12:09:52 -05:00
class HUID:
__next_uid = 0
def __init__(self):
self.huid = HUID.__next_uid
HUID.__next_uid += 1
def __hash__(self):
return self.huid
class Value(HUID):
2011-12-08 15:15:44 -05:00
def __invert__(self):
2011-12-16 15:30:14 -05:00
return _Operator("~", [self])
2012-11-29 16:52:57 -05:00
def __neg__(self):
return _Operator("-", [self])
2011-12-08 15:15:44 -05:00
def __add__(self, other):
2011-12-16 15:30:14 -05:00
return _Operator("+", [self, other])
def __radd__(self, other):
2011-12-16 15:30:14 -05:00
return _Operator("+", [other, self])
def __sub__(self, other):
2011-12-16 15:30:14 -05:00
return _Operator("-", [self, other])
def __rsub__(self, other):
2011-12-16 15:30:14 -05:00
return _Operator("-", [other, self])
def __mul__(self, other):
2011-12-16 15:30:14 -05:00
return _Operator("*", [self, other])
def __rmul__(self, other):
2011-12-16 15:30:14 -05:00
return _Operator("*", [other, self])
def __lshift__(self, other):
return _Operator("<<<", [self, other])
def __rlshift__(self, other):
return _Operator("<<<", [other, self])
def __rshift__(self, other):
return _Operator(">>>", [self, other])
def __rrshift__(self, other):
return _Operator(">>>", [other, self])
def __and__(self, other):
2011-12-16 15:30:14 -05:00
return _Operator("&", [self, other])
def __rand__(self, other):
2011-12-16 15:30:14 -05:00
return _Operator("&", [other, self])
def __xor__(self, other):
2011-12-16 15:30:14 -05:00
return _Operator("^", [self, other])
def __rxor__(self, other):
2011-12-16 15:30:14 -05:00
return _Operator("^", [other, self])
def __or__(self, other):
2011-12-16 15:30:14 -05:00
return _Operator("|", [self, other])
def __ror__(self, other):
2011-12-16 15:30:14 -05:00
return _Operator("|", [other, self])
def __lt__(self, other):
2011-12-16 15:30:14 -05:00
return _Operator("<", [self, other])
def __le__(self, other):
2011-12-16 15:30:14 -05:00
return _Operator("<=", [self, other])
def __eq__(self, other):
2011-12-16 15:30:14 -05:00
return _Operator("==", [self, other])
def __ne__(self, other):
2011-12-16 15:30:14 -05:00
return _Operator("!=", [self, other])
def __gt__(self, other):
2011-12-16 15:30:14 -05:00
return _Operator(">", [self, other])
def __ge__(self, other):
2011-12-16 15:30:14 -05:00
return _Operator(">=", [self, other])
def __getitem__(self, key):
from migen.fhdl.size import flen
if isinstance(key, int):
2013-03-17 10:33:38 -04:00
if key < 0:
key += flen(self)
2011-12-21 16:57:07 -05:00
return _Slice(self, key, key+1)
elif isinstance(key, slice):
start, stop, step = key.indices(flen(self))
if step != 1:
return Cat(*(self[i] for i in range(start, stop, step)))
2011-12-21 16:57:07 -05:00
return _Slice(self, start, stop)
else:
raise KeyError
2011-12-16 15:30:14 -05:00
def eq(self, r):
2011-12-21 16:57:07 -05:00
return _Assign(self, r)
def __hash__(self):
2012-12-18 08:54:33 -05:00
return HUID.__hash__(self)
2011-12-16 15:30:14 -05:00
class _Operator(Value):
def __init__(self, op, operands):
2012-12-18 08:54:33 -05:00
Value.__init__(self)
self.op = op
2012-11-28 17:18:43 -05:00
self.operands = operands
2011-12-21 16:57:07 -05:00
class _Slice(Value):
def __init__(self, value, start, stop):
2012-12-18 08:54:33 -05:00
Value.__init__(self)
self.value = value
self.start = start
self.stop = stop
class Cat(Value):
def __init__(self, *args):
2012-12-18 08:54:33 -05:00
Value.__init__(self)
2012-11-28 17:18:43 -05:00
self.l = args
2011-12-09 07:11:34 -05:00
class Replicate(Value):
def __init__(self, v, n):
2012-12-18 08:54:33 -05:00
Value.__init__(self)
2012-11-28 17:18:43 -05:00
self.v = v
2011-12-09 07:11:34 -05:00
self.n = n
class Signal(Value):
def __init__(self, bits_sign=None, name=None, variable=False, reset=0, name_override=None, min=None, max=None, related=None):
from migen.fhdl.size import bits_for
2012-12-18 08:54:33 -05:00
Value.__init__(self)
# determine number of bits and signedness
if bits_sign is None:
if min is None:
min = 0
if max is None:
max = 2
max -= 1 # make both bounds inclusive
assert(min < max)
self.signed = min < 0 or max < 0
self.nbits = builtins.max(bits_for(min, self.signed), bits_for(max, self.signed))
else:
assert(min is None and max is None)
if isinstance(bits_sign, tuple):
self.nbits, self.signed = bits_sign
else:
self.nbits, self.signed = bits_sign, False
assert(isinstance(self.nbits, int))
2013-06-30 14:14:20 -04:00
self.variable = variable # deprecated
2012-11-28 17:18:43 -05:00
self.reset = reset
2012-01-16 12:09:52 -05:00
self.name_override = name_override
self.backtrace = tracer.trace_back(name)
self.related = related
2012-09-11 03:59:37 -04:00
2012-01-06 05:20:33 -05:00
def __repr__(self):
2012-09-09 13:33:55 -04:00
return "<Signal " + (self.backtrace[-1][0] or "anonymous") + " at " + hex(id(self)) + ">"
class ClockSignal(Value):
def __init__(self, cd="sys"):
Value.__init__(self)
self.cd = cd
class ResetSignal(Value):
def __init__(self, cd="sys"):
Value.__init__(self)
self.cd = cd
# statements
2011-12-21 16:57:07 -05:00
class _Assign:
def __init__(self, l, r):
self.l = l
2012-11-28 17:18:43 -05:00
self.r = r
2011-12-16 15:30:14 -05:00
class If:
def __init__(self, cond, *t):
self.cond = cond
2012-07-13 11:07:56 -04:00
self.t = list(t)
self.f = []
2011-12-16 15:30:14 -05:00
def Else(self, *f):
2012-07-13 11:07:56 -04:00
_insert_else(self, list(f))
2011-12-16 15:30:14 -05:00
return self
def Elif(self, cond, *t):
2012-07-13 11:07:56 -04:00
_insert_else(self, [If(cond, *t)])
2011-12-16 15:30:14 -05:00
return self
2011-12-17 14:31:42 -05:00
def _insert_else(obj, clause):
o = obj
2012-07-13 11:07:56 -04:00
while o.f:
assert(len(o.f) == 1)
assert(isinstance(o.f[0], If))
o = o.f[0]
2011-12-17 14:31:42 -05:00
o.f = clause
class Case:
2012-11-28 19:11:15 -05:00
def __init__(self, test, cases):
self.test = test
2012-11-28 19:11:15 -05:00
self.cases = cases
def makedefault(self, key=None):
if key is None:
for choice in self.cases.keys():
if key is None or choice > key:
key = choice
self.cases["default"] = self.cases[key]
del self.cases[key]
return self
# arrays
class _ArrayProxy(Value):
def __init__(self, choices, key):
self.choices = choices
self.key = key
def __getattr__(self, attr):
return _ArrayProxy([getattr(choice, attr) for choice in self.choices],
self.key)
def __getitem__(self, key):
return _ArrayProxy([choice.__getitem__(key) for choice in self.choices],
self.key)
class Array(list):
def __getitem__(self, key):
if isinstance(key, Value):
return _ArrayProxy(self, key)
else:
2012-12-18 08:54:33 -05:00
return list.__getitem__(self, key)
2013-03-15 13:17:33 -04:00
class ClockDomain:
2013-04-23 05:53:37 -04:00
def __init__(self, name=None, reset_less=False):
2013-03-15 13:17:33 -04:00
self.name = tracer.get_obj_var_name(name)
if self.name is None:
raise ValueError("Cannot extract clock domain name from code, need to specify.")
if len(self.name) > 3 and self.name[:3] == "cd_":
self.name = self.name[3:]
self.clk = Signal(name_override=self.name + "_clk")
2013-04-23 05:53:37 -04:00
if reset_less:
self.rst = None
else:
self.rst = Signal(name_override=self.name + "_rst")
2013-03-15 13:17:33 -04:00
def rename(self, new_name):
self.name = new_name
self.clk.name_override = new_name + "_clk"
2013-04-23 05:53:37 -04:00
if self.rst is not None:
self.rst.name_override = new_name + "_rst"
2013-03-15 13:17:33 -04:00
class _ClockDomainList(list):
def __getitem__(self, key):
if isinstance(key, str):
for cd in self:
if cd.name == key:
return cd
raise KeyError(key)
else:
return list.__getitem__(self, key)
(SPECIAL_INPUT, SPECIAL_OUTPUT, SPECIAL_INOUT) = range(3)
2013-07-25 12:52:54 -04:00
class _Fragment:
2013-03-15 13:17:33 -04:00
def __init__(self, comb=None, sync=None, specials=None, clock_domains=None, sim=None):
if comb is None: comb = []
if sync is None: sync = dict()
2013-02-22 11:56:35 -05:00
if specials is None: specials = set()
2013-03-15 13:17:33 -04:00
if clock_domains is None: clock_domains = _ClockDomainList()
if sim is None: sim = []
2012-07-13 11:07:56 -04:00
self.comb = comb
self.sync = sync
2013-07-25 12:52:54 -04:00
self.specials = specials
2013-03-15 13:17:33 -04:00
self.clock_domains = _ClockDomainList(clock_domains)
self.sim = sim
2011-12-05 11:43:56 -05:00
def __add__(self, other):
newsync = defaultdict(list)
for k, v in self.sync.items():
newsync[k] = v[:]
for k, v in other.sync.items():
newsync[k].extend(v)
2013-07-25 12:52:54 -04:00
return _Fragment(self.comb + other.comb, newsync,
2013-02-22 11:56:35 -05:00
self.specials | other.specials,
2013-03-15 13:17:33 -04:00
self.clock_domains + other.clock_domains,
self.sim + other.sim)
2013-08-11 17:11:30 -04:00
def __iadd__(self, other):
newsync = defaultdict(list)
for k, v in self.sync.items():
newsync[k] = v[:]
for k, v in other.sync.items():
newsync[k].extend(v)
self.comb += other.comb
self.sync = newsync
self.specials |= other.specials
self.clock_domains += other.clock_domains
self.sim += other.sim
return self