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())