litex/migen/corelogic/record.py

99 lines
2.5 KiB
Python
Raw Normal View History

2012-01-06 05:20:44 -05:00
from migen.fhdl.structure import *
class Record:
2012-01-16 13:38:14 -05:00
def __init__(self, layout, name=""):
self.name = name
2012-01-09 09:14:42 -05:00
self.field_order = []
2012-01-16 13:38:14 -05:00
if self.name:
prefix = self.name + "_"
else:
prefix = ""
2012-01-09 09:14:42 -05:00
for f in layout:
2012-01-06 05:20:44 -05:00
if isinstance(f, tuple):
if isinstance(f[1], BV):
2012-01-16 13:38:14 -05:00
setattr(self, f[0], Signal(f[1], prefix + f[0]))
2012-01-06 05:20:44 -05:00
elif isinstance(f[1], Signal) or isinstance(f[1], Record):
setattr(self, f[0], f[1])
elif isinstance(f[1], list):
2012-01-16 13:38:14 -05:00
setattr(self, f[0], Record(f[1], prefix + f[0]))
2012-01-06 05:20:44 -05:00
else:
raise TypeError
2012-01-09 13:16:11 -05:00
if len(f) == 3:
self.field_order.append((f[0], f[2]))
else:
self.field_order.append((f[0], 1))
2012-01-06 05:20:44 -05:00
else:
2012-01-16 13:38:14 -05:00
setattr(self, f, Signal(BV(1), prefix + f))
2012-01-09 13:16:11 -05:00
self.field_order.append((f, 1))
2012-01-06 05:20:44 -05:00
2012-01-09 09:14:42 -05:00
def layout(self):
2012-01-06 05:20:44 -05:00
l = []
2012-01-09 13:16:11 -05:00
for key, alignment in self.field_order:
2012-01-06 05:20:44 -05:00
e = self.__dict__[key]
if isinstance(e, Signal):
2012-01-09 13:16:11 -05:00
l.append((key, e.bv, alignment))
2012-01-06 05:20:44 -05:00
elif isinstance(e, Record):
2012-01-09 13:16:11 -05:00
l.append((key, e.layout(), alignment))
2012-01-06 05:20:44 -05:00
return l
def copy(self, name=None):
2012-01-16 12:09:52 -05:00
return Record(self.layout(), name)
2012-01-06 05:20:44 -05:00
2012-01-09 13:16:11 -05:00
def get_alignment(self, name):
return list(filter(lambda x: x[0] == name, self.field_order))[0][1]
2012-01-06 05:20:44 -05:00
def subrecord(self, *descr):
2012-01-09 09:14:42 -05:00
fields = []
2012-01-06 05:20:44 -05:00
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)
2012-01-09 09:17:24 -05:00
lu = list(filter(lambda x: x[0] == hop, pos_fields))
2012-01-06 05:20:44 -05:00
try:
2012-01-09 09:14:42 -05:00
pos_fields = lu[0][1]
except IndexError:
n = []
pos_fields.append((hop, n))
pos_fields = n
if not isinstance(pos_fields, list):
2012-01-06 05:20:44 -05:00
raise ValueError
2012-01-09 09:14:42 -05:00
if len(list(filter(lambda x: x[0] == last, pos_fields))) > 0:
2012-01-06 05:20:44 -05:00
raise ValueError
2012-01-09 13:16:11 -05:00
pos_fields.append((last, getattr(pos_self, last), pos_self.get_alignment(last)))
2012-01-09 09:14:42 -05:00
return Record(fields, "subrecord")
2012-01-06 05:20:44 -05:00
2012-01-06 17:00:23 -05:00
def compatible(self, other):
2012-01-08 07:56:11 -05:00
tpl1 = self.flatten()
tpl2 = other.flatten()
return len(tpl1) == len(tpl2)
2012-01-06 17:00:23 -05:00
2012-01-10 11:10:03 -05:00
def flatten(self, align=False, offset=0, return_offset=False):
2012-01-06 05:20:44 -05:00
l = []
2012-01-09 13:16:11 -05:00
for key, alignment in self.field_order:
if align:
pad_size = alignment - (offset % alignment)
if pad_size < alignment:
l.append(Constant(0, BV(pad_size)))
offset += pad_size
2012-01-06 05:20:44 -05:00
e = self.__dict__[key]
if isinstance(e, Signal):
2012-01-09 13:16:11 -05:00
added = [e]
2012-01-06 05:20:44 -05:00
elif isinstance(e, Record):
2012-01-09 13:16:11 -05:00
added = e.flatten(align, offset)
else:
raise TypeError
for x in added:
offset += x.bv.width
l += added
2012-01-10 11:10:03 -05:00
if return_offset:
return (l, offset)
else:
return l
2012-01-06 18:33:28 -05:00
def __repr__(self):
2012-01-09 09:14:42 -05:00
return repr(self.layout())