76 lines
2.0 KiB
Python
76 lines
2.0 KiB
Python
from migen.fhdl.structure import *
|
|
from migen.fhdl.structure import _make_signal_name
|
|
|
|
class Record:
|
|
def __init__(self, layout, name=None):
|
|
self.name = name or _make_signal_name()
|
|
self.field_order = []
|
|
for f in layout:
|
|
if isinstance(f, tuple):
|
|
if isinstance(f[1], BV):
|
|
setattr(self, f[0], Signal(f[1], self.name + "_" + f[0]))
|
|
elif isinstance(f[1], Signal) or isinstance(f[1], Record):
|
|
setattr(self, f[0], f[1])
|
|
elif isinstance(f[1], list):
|
|
setattr(self, f[0], Record(f[1], self.name + "_" + f[0]))
|
|
else:
|
|
raise TypeError
|
|
self.field_order.append(f[0])
|
|
else:
|
|
setattr(self, f, Signal(BV(1), self.name + "_" + f))
|
|
self.field_order.append(f)
|
|
|
|
def layout(self):
|
|
l = []
|
|
for key in self.field_order:
|
|
e = self.__dict__[key]
|
|
if isinstance(e, Signal):
|
|
l.append((key, e.bv))
|
|
elif isinstance(e, Record):
|
|
l.append((key, e.layout()))
|
|
return l
|
|
|
|
def copy(self, name=None):
|
|
return Record(self.layout(), name or _make_signal_name())
|
|
|
|
def subrecord(self, *descr):
|
|
fields = []
|
|
for item in descr:
|
|
path = item.split('/')
|
|
last = path.pop()
|
|
pos_self = self
|
|
pos_fields = fields
|
|
for hop in path:
|
|
pos_self = getattr(pos_self, hop)
|
|
lu = list(filter(lambda x: x[0] == hop, pos_fields))
|
|
try:
|
|
pos_fields = lu[0][1]
|
|
except IndexError:
|
|
n = []
|
|
pos_fields.append((hop, n))
|
|
pos_fields = n
|
|
if not isinstance(pos_fields, list):
|
|
raise ValueError
|
|
if len(list(filter(lambda x: x[0] == last, pos_fields))) > 0:
|
|
raise ValueError
|
|
pos_fields.append((last, getattr(pos_self, last)))
|
|
return Record(fields, "subrecord")
|
|
|
|
def compatible(self, other):
|
|
tpl1 = self.flatten()
|
|
tpl2 = other.flatten()
|
|
return len(tpl1) == len(tpl2)
|
|
|
|
def flatten(self):
|
|
l = []
|
|
for key in self.field_order:
|
|
e = self.__dict__[key]
|
|
if isinstance(e, Signal):
|
|
l.append(e)
|
|
elif isinstance(e, Record):
|
|
l += e.flatten()
|
|
return l
|
|
|
|
def __repr__(self):
|
|
return repr(self.layout())
|