mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
actorlib/control: 'for' generator
This commit is contained in:
parent
c3d7b98b43
commit
e6bfad498d
2 changed files with 105 additions and 4 deletions
|
@ -1,10 +1,9 @@
|
||||||
import sys
|
|
||||||
import networkx as nx
|
import networkx as nx
|
||||||
|
|
||||||
from migen.fhdl import verilog
|
from migen.fhdl import verilog
|
||||||
from migen.flow.ala import *
|
from migen.flow.ala import *
|
||||||
from migen.flow.network import *
|
from migen.flow.network import *
|
||||||
from migen.actorlib import dma_wishbone
|
from migen.actorlib import dma_wishbone, control
|
||||||
|
|
||||||
L = [
|
L = [
|
||||||
("x", BV(10), 8),
|
("x", BV(10), 8),
|
||||||
|
@ -15,6 +14,14 @@ L = [
|
||||||
])
|
])
|
||||||
]
|
]
|
||||||
|
|
||||||
|
adrgen = control.For(10)
|
||||||
reader = dma_wishbone.Reader(L)
|
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))
|
||||||
|
|
94
migen/actorlib/control.py
Normal file
94
migen/actorlib/control.py
Normal file
|
@ -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()
|
Loading…
Reference in a new issue