fhdl: arrays (TODO: use correct BV for intermediate signals)
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Mon, 9 Jul 2012 13:16:38 +0000 (15:16 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Mon, 9 Jul 2012 13:16:38 +0000 (15:16 +0200)
examples/basic/arrays.py [new file with mode: 0644]
migen/corelogic/misc.py
migen/fhdl/structure.py
migen/fhdl/tools.py
migen/fhdl/verilog.py

diff --git a/examples/basic/arrays.py b/examples/basic/arrays.py
new file mode 100644 (file)
index 0000000..4081f85
--- /dev/null
@@ -0,0 +1,25 @@
+from migen.fhdl.structure import *
+from migen.fhdl import verilog
+
+dx = 5
+dy = 5
+
+x = Signal(BV(bits_for(dx)))
+y = Signal(BV(bits_for(dy)))
+out = Signal()
+
+my_2d_array = Array(Array(Signal() for a in range(dx)) for b in range(dy))
+comb = [
+       out.eq(my_2d_array[x][y])
+]
+
+we = Signal()
+inp = Signal()
+sync = [
+       If(we,
+               my_2d_array[x][y].eq(inp)
+       )
+]
+
+f = Fragment(comb)
+print(verilog.convert(f))
index 746433209f5be1a8f924ee2fb5c2cf9ead93e444..5c8bae4cb1dd2383d1a9cf4510f6aa01d318b511 100644 (file)
@@ -1,6 +1,8 @@
 from migen.fhdl.structure import *
 from migen.fhdl.structure import _Operator
 
+# multimux is deprecated - use Array instead
+# TODO: remove uses of multimux
 def multimux(sel, inputs, output):
        n = len(inputs)
        i = 0
index b4fb44afda4732ddb9dcd7eeccbbeff59c5c4ffb..ebb88fbb94f92a0cc48a4260cb86452c2f06a86f 100644 (file)
@@ -223,7 +223,29 @@ class Case:
                if self.default is None:
                        self.default = _StatementList()
 
-#
+# arrays
+
+class _ArrayProxy(Value):
+       def __init__(self, choices, key):
+               self.choices = choices
+               self.key = key
+       
+       def __getattr__(self, attr):
+               return _ArrayProxy([getattr(choice, attr) for choice in self.choices],
+                       self.key)
+       
+       def __getitem__(self, key):
+               return _ArrayProxy([choice.__getitem__(key) for choice in self.choices],
+                       self.key)
+
+class Array(list):
+       def __getitem__(self, key):
+               if isinstance(key, Value):
+                       return _ArrayProxy(self, key)
+               else:
+                       return super().__getitem__(key)
+
+# extras
 
 class Instance:
        def __init__(self, of, outs=[], ins=[], inouts=[], parameters=[], clkport="", rstport="", name=""):
@@ -270,6 +292,8 @@ class Memory:
                self.ports = ports
                self.init = init
 
+#
+
 class Fragment:
        def __init__(self, comb=None, sync=None, instances=None, memories=None, sim=None):
                if comb is None: comb = []
index bd8393d52204fd86ec5f3edb934c8230307ae58f..f790029669ec05bae8405633a884e4d8ab6b0316 100644 (file)
@@ -1,5 +1,7 @@
+from copy import copy
+
 from migen.fhdl.structure import *
-from migen.fhdl.structure import _Operator, _Slice, _Assign, _StatementList
+from migen.fhdl.structure import _Operator, _Slice, _Assign, _StatementList, _ArrayProxy
 
 def list_signals(node):
        if node is None:
@@ -123,3 +125,98 @@ def insert_reset(rst, sl):
        targets = list_targets(sl)
        resetcode = [t.eq(t.reset) for t in targets]
        return If(rst, *resetcode).Else(*sl.l)
+
+def _lower_arrays_values(vl):
+       r = []
+       extra_comb = []
+       for v in vl:
+               v2, e = _lower_arrays_value(v)
+               extra_comb += e
+               r.append(v2)
+       return r, extra_comb
+       
+def _lower_arrays_value(v):
+       if isinstance(v, _Operator):
+               op2, e = _lower_arrays_values(v.operands)
+               return _Operator(v.op, op2), e
+       elif isinstance(v, _Slice):
+               v2, e = _lower_arrays_value(v.value)
+               return _Slice(v2, v.start, v.stop), e
+       elif isinstance(v, Cat):
+               l2, e = _lower_arrays_values(v.l)
+               return Cat(*l2), e
+       elif isinstance(v, Replicate):
+               v2, e = _lower_arrays_value(v.v)
+               return Replicate(v2, v.n), e
+       elif isinstance(v, Constant):
+               return v, []
+       elif isinstance(v, Signal):
+               return v, []
+       elif isinstance(v, _ArrayProxy):
+               choices2, e = _lower_arrays_values(v.choices)
+               array_muxed = Signal(BV(32)) # TODO: use the correct BV
+               cases = [[Constant(n), _Assign(array_muxed, choice)]
+                       for n, choice in enumerate(choices2)]
+               cases[-1][0] = Default()
+               e.append(Case(v.key, *cases))
+               return array_muxed, e
+
+def _lower_arrays_assign(l, r):
+       extra_comb = []
+       if isinstance(l, _ArrayProxy):
+               k, e = _lower_arrays_value(l.key)
+               extra_comb += e
+               cases = []
+               for n, choice in enumerate(l.choices):
+                       assign, e = _lower_arrays_assign(choice, r)
+                       extra_comb += e
+                       cases.append([Constant(n), assign])
+               cases[-1][0] = Default()
+               return Case(k, *cases), extra_comb
+       else:
+               return _Assign(l, r), extra_comb
+               
+def _lower_arrays_sl(sl):
+       result = _StatementList()
+       rs = result.l
+       extra_comb = []
+       for statement in sl.l:
+               if isinstance(statement, _Assign):
+                       r, e = _lower_arrays_value(statement.r)
+                       extra_comb += e
+                       r, e = _lower_arrays_assign(statement.l, r)
+                       extra_comb += e
+                       rs.append(r)
+               elif isinstance(statement, If):
+                       cond, e = _lower_arrays_value(statement.cond)
+                       extra_comb += e
+                       t, e = _lower_arrays_sl(statement.t)
+                       extra_comb += e
+                       f, e = _lower_arrays_sl(statement.f)
+                       extra_comb += e
+                       i = If(cond)
+                       i.t = t
+                       i.f = f
+                       rs.append(i)
+               elif isinstance(statement, Case):
+                       test, e = _lower_arrays_value(statement.test)
+                       extra_comb += e
+                       c = Case(test)
+                       for cond, csl in statement.cases:
+                               stmts, e = _lower_arrays_sl(csl)
+                               extra_comb += e
+                               c.cases.append((cond, stmts))
+                       if statement.default is not None:
+                               c.default, e = _lower_arrays_sl(statement.default)
+                               extra_comb += e
+                       rs.append(c)
+               elif statement is not None:
+                       raise TypeError
+       return result, extra_comb
+
+def lower_arrays(f):
+       f = copy(f)
+       f.comb, ec1 = _lower_arrays_sl(f.comb)
+       f.sync, ec2 = _lower_arrays_sl(f.sync)
+       f.comb.l += ec1 + ec2
+       return f
index 81a02ac5e9b269acf5f365906b394e505e0d9b87..e06dee6624ef3ea2fa52c76606b703d4c2ec505b 100644 (file)
@@ -247,6 +247,8 @@ def convert(f, ios=set(), name="top",
        if rst_signal is None:
                rst_signal = Signal(name_override="sys_rst")
                ios.add(rst_signal)
+               
+       f = lower_arrays(f)
 
        ns = build_namespace(list_signals(f) \
                | list_inst_ios(f, True, True, True) \