fhdl/simplify: add FullMemoryWE decorator that splits memories to remove partial WEs
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Thu, 12 Dec 2013 16:37:31 +0000 (17:37 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Thu, 12 Dec 2013 16:37:31 +0000 (17:37 +0100)
migen/fhdl/simplify.py [new file with mode: 0644]

diff --git a/migen/fhdl/simplify.py b/migen/fhdl/simplify.py
new file mode 100644 (file)
index 0000000..5876b01
--- /dev/null
@@ -0,0 +1,41 @@
+from migen.fhdl.std import *
+from migen.fhdl.specials import _MemoryPort
+from migen.fhdl.decorators import ModuleDecorator
+from migen.util.misc import gcd_multiple
+
+class FullMemoryWE(ModuleDecorator):
+       def transform_fragment(self, f):
+               newspecials = set()
+
+               for orig in f.specials:
+                       if not isinstance(orig, Memory):
+                               newspecials.add(orig)
+                               continue
+                       global_granularity = gcd_multiple([p.we_granularity if p.we_granularity else orig.width for p in orig.ports])
+                       if global_granularity == orig.width:
+                               newspecials.add(orig) # nothing to do
+                       else:
+                               for i in range(orig.width//global_granularity):
+                                       if orig.init is None:
+                                               newinit = None
+                                       else:
+                                               newinit = [(v >> i*global_granularity) & (2**global_granularity - 1) for v in orig.init]
+                                       newmem = Memory(global_granularity, orig.depth, newinit, orig.name_override + "_grain" + str(i))
+                                       newspecials.add(newmem)
+                                       for port in orig.ports:
+                                               port_granularity = port.we_granularity if port.we_granularity else orig.width
+                                               newport = _MemoryPort(adr=port.adr,
+                                                       
+                                                       dat_r=port.dat_r[i*global_granularity:(i+1)*global_granularity] if port.dat_r is not None else None,
+                                                       we=port.we[i*port_granularity//global_granularity] if port.we is not None else None,
+                                                       dat_w=port.dat_w[i*global_granularity:(i+1)*global_granularity] if port.dat_w is not None else None,
+
+                                                       async_read=port.async_read,
+                                                       re=port.re,
+                                                       we_granularity=0,
+                                                       mode=port.mode,
+                                                       clock_domain=port.clock)
+                                               newmem.ports.append(newport)
+                                               newspecials.add(newport)
+
+               f.specials = newspecials