corelogic: record
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Fri, 6 Jan 2012 10:20:44 +0000 (11:20 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Fri, 6 Jan 2012 10:20:44 +0000 (11:20 +0100)
examples/using_record.py [new file with mode: 0644]
migen/corelogic/record.py [new file with mode: 0644]

diff --git a/examples/using_record.py b/examples/using_record.py
new file mode 100644 (file)
index 0000000..0940715
--- /dev/null
@@ -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 (file)
index 0000000..5b3e404
--- /dev/null
@@ -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