record: support aligned flattening

This commit is contained in:
Sebastien Bourdeauducq 2012-01-09 19:16:11 +01:00
parent b06e70d849
commit 683e6b4a6c
2 changed files with 32 additions and 14 deletions

View File

@ -2,16 +2,17 @@ from migen.fhdl.structure import *
from migen.corelogic.record import * from migen.corelogic.record import *
L = [ L = [
("x", BV(10)), ("x", BV(10), 8),
("y", BV(10)), ("y", BV(10), 8),
("level2", [ ("level2", [
("a", BV(5)), ("a", BV(5), 32),
("b", BV(5)) ("b", BV(5), 16)
]) ])
] ]
myrec = Record(L) myrec = Record(L)
print(myrec.flatten()) print(myrec.flatten())
print(myrec.flatten(True))
s = myrec.subrecord("level2/a", "x") s = myrec.subrecord("level2/a", "x")
print(s.flatten()) print(s.flatten())
print(s.level2.layout()) print(s.level2.layout())

View File

@ -15,24 +15,30 @@ class Record:
setattr(self, f[0], Record(f[1], self.name + "_" + f[0])) setattr(self, f[0], Record(f[1], self.name + "_" + f[0]))
else: else:
raise TypeError raise TypeError
self.field_order.append(f[0]) if len(f) == 3:
self.field_order.append((f[0], f[2]))
else:
self.field_order.append((f[0], 1))
else: else:
setattr(self, f, Signal(BV(1), self.name + "_" + f)) setattr(self, f, Signal(BV(1), self.name + "_" + f))
self.field_order.append(f) self.field_order.append((f, 1))
def layout(self): def layout(self):
l = [] l = []
for key in self.field_order: for key, alignment in self.field_order:
e = self.__dict__[key] e = self.__dict__[key]
if isinstance(e, Signal): if isinstance(e, Signal):
l.append((key, e.bv)) l.append((key, e.bv, alignment))
elif isinstance(e, Record): elif isinstance(e, Record):
l.append((key, e.layout())) l.append((key, e.layout(), alignment))
return l return l
def copy(self, name=None): def copy(self, name=None):
return Record(self.layout(), name or _make_signal_name()) return Record(self.layout(), name or _make_signal_name())
def get_alignment(self, name):
return list(filter(lambda x: x[0] == name, self.field_order))[0][1]
def subrecord(self, *descr): def subrecord(self, *descr):
fields = [] fields = []
for item in descr: for item in descr:
@ -53,7 +59,7 @@ class Record:
raise ValueError raise ValueError
if len(list(filter(lambda x: x[0] == last, pos_fields))) > 0: if len(list(filter(lambda x: x[0] == last, pos_fields))) > 0:
raise ValueError raise ValueError
pos_fields.append((last, getattr(pos_self, last))) pos_fields.append((last, getattr(pos_self, last), pos_self.get_alignment(last)))
return Record(fields, "subrecord") return Record(fields, "subrecord")
def compatible(self, other): def compatible(self, other):
@ -61,14 +67,25 @@ class Record:
tpl2 = other.flatten() tpl2 = other.flatten()
return len(tpl1) == len(tpl2) return len(tpl1) == len(tpl2)
def flatten(self): def flatten(self, align=False, offset=0):
l = [] l = []
for key in self.field_order: 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
e = self.__dict__[key] e = self.__dict__[key]
if isinstance(e, Signal): if isinstance(e, Signal):
l.append(e) added = [e]
elif isinstance(e, Record): elif isinstance(e, Record):
l += e.flatten() added = e.flatten(align, offset)
else:
raise TypeError
for x in added:
offset += x.bv.width
l += added
return l return l
def __repr__(self): def __repr__(self):