From 038992e7d277da49a434a61fe8715e1b339de18c Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Fri, 6 Jan 2012 11:20:44 +0100 Subject: [PATCH] corelogic: record --- examples/using_record.py | 19 +++++++++++ migen/corelogic/record.py | 70 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 examples/using_record.py create mode 100644 migen/corelogic/record.py diff --git a/examples/using_record.py b/examples/using_record.py new file mode 100644 index 000000000..0940715ed --- /dev/null +++ b/examples/using_record.py @@ -0,0 +1,19 @@ +from migen.fhdl.structure import * +from migen.corelogic.record import * + +TPL = [ + ("x", BV(10)), + ("y", BV(10)), + ("level2", [ + ("a", BV(5)), + ("b", BV(5)) + ]) +] + +myrec = Record(TPL) +print(myrec.flatten()) +s = myrec.subrecord("level2/a", "x") +print(s.flatten()) +print(s.level2.template()) +myrec2 = myrec.copy() +print(myrec2.flatten()) diff --git a/migen/corelogic/record.py b/migen/corelogic/record.py new file mode 100644 index 000000000..5b3e40497 --- /dev/null +++ b/migen/corelogic/record.py @@ -0,0 +1,70 @@ +from migen.fhdl.structure import * +from migen.fhdl.structure import _make_signal_name + +class Record: + def __init__(self, template, name=None): + self.name = name or _make_signal_name() + for f in template: + 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 + else: + setattr(self, f, Signal(BV(1), self.name + "_" + f)) + + def template(self): + l = [] + for key in self.__dict__: + e = self.__dict__[key] + if isinstance(e, Signal): + l.append((key, e.bv)) + elif isinstance(e, Record): + l.append((key, e.template())) + return l + + def copy(self, name=None): + return Record(self.template(), 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) + try: + pos_fields = fields[hop] + except KeyError: + pos_fields = fields[hop] = {} + if not isinstance(pos_fields, dict): + raise ValueError + if last in pos_fields: + raise ValueError + pos_fields[last] = getattr(pos_self, last) + def dict_to_list(d): + l = [] + for key in d: + e = d[key] + if isinstance(e, dict): + l.append((key, dict_to_list(e))) + else: + l.append((key, e)) + return l + return Record(dict_to_list(fields), "subrecord") + + def flatten(self): + l = [] + for key in sorted(self.__dict__): + e = self.__dict__[key] + if isinstance(e, Signal): + l.append(e) + elif isinstance(e, Record): + l += e.flatten() + return l