From 683e6b4a6cac98095ffff12c1e33d19e3ea18682 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 9 Jan 2012 19:16:11 +0100 Subject: [PATCH] record: support aligned flattening --- examples/using_record.py | 9 +++++---- migen/corelogic/record.py | 37 +++++++++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/examples/using_record.py b/examples/using_record.py index 0b61430c3..7c757aa4f 100644 --- a/examples/using_record.py +++ b/examples/using_record.py @@ -2,16 +2,17 @@ from migen.fhdl.structure import * from migen.corelogic.record import * L = [ - ("x", BV(10)), - ("y", BV(10)), + ("x", BV(10), 8), + ("y", BV(10), 8), ("level2", [ - ("a", BV(5)), - ("b", BV(5)) + ("a", BV(5), 32), + ("b", BV(5), 16) ]) ] myrec = Record(L) print(myrec.flatten()) +print(myrec.flatten(True)) s = myrec.subrecord("level2/a", "x") print(s.flatten()) print(s.level2.layout()) diff --git a/migen/corelogic/record.py b/migen/corelogic/record.py index b8a8b434d..e2722a9ab 100644 --- a/migen/corelogic/record.py +++ b/migen/corelogic/record.py @@ -15,24 +15,30 @@ class Record: setattr(self, f[0], Record(f[1], self.name + "_" + f[0])) else: 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: setattr(self, f, Signal(BV(1), self.name + "_" + f)) - self.field_order.append(f) + self.field_order.append((f, 1)) def layout(self): l = [] - for key in self.field_order: + for key, alignment in self.field_order: e = self.__dict__[key] if isinstance(e, Signal): - l.append((key, e.bv)) + l.append((key, e.bv, alignment)) elif isinstance(e, Record): - l.append((key, e.layout())) + l.append((key, e.layout(), alignment)) return l def copy(self, name=None): 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): fields = [] for item in descr: @@ -53,7 +59,7 @@ class Record: raise ValueError if len(list(filter(lambda x: x[0] == last, pos_fields))) > 0: 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") def compatible(self, other): @@ -61,14 +67,25 @@ class Record: tpl2 = other.flatten() return len(tpl1) == len(tpl2) - def flatten(self): + def flatten(self, align=False, offset=0): 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] if isinstance(e, Signal): - l.append(e) + added = [e] 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 def __repr__(self):