actorlib/control: 'for' generator
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Sun, 15 Jan 2012 21:08:33 +0000 (22:08 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Sun, 15 Jan 2012 21:08:33 +0000 (22:08 +0100)
examples/dataflow_dma.py
migen/actorlib/control.py [new file with mode: 0644]

index 2671769168ef7ecab7ee373f3b63e37341ec7a1f..5e6649adaab68bf905f6063fab1a53fd3f152d4b 100644 (file)
@@ -1,10 +1,9 @@
-import sys
 import networkx as nx
 
 from migen.fhdl import verilog
 from migen.flow.ala import *
 from migen.flow.network import *
-from migen.actorlib import dma_wishbone
+from migen.actorlib import dma_wishbone, control
 
 L = [
        ("x", BV(10), 8),
@@ -15,6 +14,14 @@ L = [
        ])
 ]
 
+adrgen = control.For(10)
 reader = dma_wishbone.Reader(L)
-frag = reader.get_fragment()
-print(verilog.convert(frag, ios=set(reader.bus.signals())))
+
+g = nx.MultiDiGraph()
+add_connection(g, adrgen, reader)
+comp = CompositeActor(g)
+
+frag = comp.get_fragment()
+ios = set(reader.bus.signals())
+ios.add(comp.busy)
+print(verilog.convert(frag, ios=ios))
diff --git a/migen/actorlib/control.py b/migen/actorlib/control.py
new file mode 100644 (file)
index 0000000..9819c5d
--- /dev/null
@@ -0,0 +1,94 @@
+from operator import mul
+from functools import reduce
+
+from migen.fhdl.structure import *
+from migen.corelogic.record import *
+from migen.corelogic.fsm import *
+from migen.flow.actor import *
+
+# Generates integers from start to maximum-1
+class For(Actor):
+       def __init__(self, *maxima, start=False, step=False):
+               self.dimensions = len(maxima)
+               self.start = start
+               self.step = step
+               params = ["end"]
+               if start: params.append("start")
+               if step: params.append("step")
+               self.d_bv = [BV(bits_for(dimension)) for dimension in maxima]
+               l_sink = [("d{0}".format(n), [(p, bv) for p in params])
+                       for n, bv in zip(range(len(self.d_bv)), self.d_bv)]
+               l_source = [("d{0}".format(n), bv)
+                       for n, bv in zip(range(len(self.d_bv)), self.d_bv)]
+               Actor.__init__(self, SchedulingModel(SchedulingModel.DYNAMIC),
+                       ("sink", Sink, l_sink),
+                       ("source", Source, l_source))
+       
+       def get_fragment(self):
+               load = Signal()
+               ce = Signal()
+               last = Signal()
+               
+               counters_v = [Signal(bv, variable=True) for bv in self.d_bv]
+               counters = [getattr(self.token("source"), "d{0}".format(n))
+                       for n in range(self.dimensions)]
+               
+               params = [getattr(self.token("sink"), "d{0}".format(n))
+                       for n in range(self.dimensions)]
+               if self.start:
+                       starts = [p.start for p in params]
+                       start_rs = [Signal(s.bv, variable=True) for s in starts]
+               else:
+                       start_rs = [Constant(0, bv) for bv in self.d_bv]
+               if self.step:
+                       steps = [p.step for p in params]
+                       step_rs = [Signal(s.bv, variable=True) for s in steps]
+               else:
+                       step_rs = [Constant(1, bv) for bv in self.d_bv]
+               ends = [p.end for p in params]
+               end_rs = [Signal(s.bv, variable=True) for s in ends]
+               
+               lasts = Signal(BV(self.dimensions))
+               
+               on_ce = [
+                       If(lasts[n],
+                               counter.eq(start)
+                       ).Else(
+                               counter.eq(counter + step)
+                       )
+                       for n, counter, start, step
+                         in zip(range(self.dimensions), counters_v, start_rs, step_rs)
+               ]
+               lasts_gen = [
+                       lasts[n].eq(counter + step >= end if self.step else counter + step == end)
+                       for n, counter, step, end
+                         in zip(range(self.dimensions), counters_v, step_rs, end_rs)
+               ]
+               sync = [
+                       If(load,
+                               Cat(*start_rs).eq(Cat(*starts)) if self.start else None,
+                               Cat(*step_rs).eq(Cat(*steps)) if self.step else None,
+                               Cat(*end_rs).eq(Cat(*ends)),
+                               Cat(*counters_v).eq(Cat(*start_rs))
+                       ),
+                       If(ce, *on_ce)
+               ] + lasts_gen + [
+                       Cat(*counters).eq(Cat(*counters_v))
+               ]
+               counters_fragment = Fragment(sync=sync)
+               
+               fsm = FSM("IDLE", "ACTIVE")
+               fsm.act(fsm.IDLE,
+                       load.eq(1),
+                       self.endpoints["sink"].ack.eq(1),
+                       If(self.endpoints["sink"].stb, fsm.next_state(fsm.ACTIVE))
+               )
+               fsm.act(fsm.ACTIVE,
+                       self.busy.eq(1),
+                       self.endpoints["source"].stb.eq(1),
+                       If(self.endpoints["source"].ack,
+                               ce.eq(1),
+                               If(last, fsm.next_state(fsm.IDLE))
+                       )
+               )
+               return counters_fragment + fsm.get_fragment()