Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/migen
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 746e45283803
Choose a base ref
...
head repository: m-labs/migen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: c8810a016f41
Choose a head ref
  • 6 commits
  • 3 files changed
  • 1 contributor

Commits on Apr 28, 2013

  1. actorlib/spi/Collector: cleanup, new APIs

    Sebastien Bourdeauducq committed Apr 28, 2013
    Copy the full SHA
    fb83794 View commit details

Commits on Apr 30, 2013

  1. flow/network/DataFlowGraph: add add_pipeline

    Sebastien Bourdeauducq committed Apr 30, 2013
    Copy the full SHA
    4f13c5b View commit details
  2. flow/network/CompositeActor: expose unconnected endpoints

    Sebastien Bourdeauducq committed Apr 30, 2013
    Copy the full SHA
    51f1ace View commit details
  3. bank/description/CSRStorage: support alignment bits

    Sebastien Bourdeauducq committed Apr 30, 2013
    Copy the full SHA
    dc0304a View commit details
  4. actorlib/spi/SingleGenerator: use CSR alignment bits

    Sebastien Bourdeauducq committed Apr 30, 2013
    Copy the full SHA
    c70c715 View commit details
  5. actorlib/spi: add DMA read controller

    Sebastien Bourdeauducq committed Apr 30, 2013
    Copy the full SHA
    c8810a0 View commit details
Showing with 92 additions and 27 deletions.
  1. +46 −17 migen/actorlib/spi.py
  2. +17 −9 migen/bank/description.py
  3. +29 −1 migen/flow/network.py
63 changes: 46 additions & 17 deletions migen/actorlib/spi.py
Original file line number Diff line number Diff line change
@@ -4,6 +4,9 @@
from migen.fhdl.specials import Memory
from migen.bank.description import *
from migen.flow.actor import *
from migen.flow.network import *
from migen.flow import plumbing
from migen.actorlib import misc

# layout is a list of tuples, either:
# - (name, nbits, [reset value], [alignment bits])
@@ -40,9 +43,10 @@ def _create_csrs_assign(layout, target, atomic, prefix=""):
alignment = element[3]
else:
alignment = 0
reg = CSRStorage(nbits + alignment, reset=reset, atomic_write=atomic, name=prefix + name)
reg = CSRStorage(nbits + alignment, reset=reset, atomic_write=atomic,
alignment_bits=alignment, name=prefix + name)
csrs.append(reg)
assigns.append(getattr(target, name).eq(reg.storage[alignment:]))
assigns.append(getattr(target, name).eq(reg.storage))
return csrs, assigns

(MODE_EXTERNAL, MODE_SINGLE_SHOT, MODE_CONTINUOUS) = range(3)
@@ -51,10 +55,10 @@ class SingleGenerator(Module):
def __init__(self, layout, mode):
self.source = Source(_convert_layout(layout))
self.busy = Signal()
self._csrs, assigns = _create_csrs_assign(layout, self.source.payload,
mode != MODE_SINGLE_SHOT)
self._csrs, assigns = _create_csrs_assign(layout, self.source.payload, mode != MODE_SINGLE_SHOT)
if mode == MODE_EXTERNAL:
trigger = self.trigger = Signal()
self.trigger = Signal()
trigger = self.trigger
elif mode == MODE_SINGLE_SHOT:
shoot = CSR()
self._csrs.insert(0, shoot)
@@ -67,7 +71,7 @@ def __init__(self, layout, mode):
raise ValueError
self.comb += self.busy.eq(self.source.stb)
stmts = [self.source.stb.eq(trigger)] + assigns
self.sync += [If(self.source.ack | ~self.source.stb, *stmts)]
self.sync += If(self.source.ack | ~self.source.stb, *stmts)

def get_csrs(self):
return self._csrs
@@ -76,17 +80,16 @@ class Collector(Module, AutoCSR):
def __init__(self, layout, depth=1024):
self.sink = Sink(layout)
self.busy = Signal()
self._depth = depth
self._dw = sum(len(s) for s in self.token("sink").flatten())

self._r_wa = CSRStorage(bits_for(self._depth-1), write_from_dev=True)
self._r_wc = CSRStorage(bits_for(self._depth), write_from_dev=True, atomic_write=True)
self._r_ra = CSRStorage(bits_for(self._depth-1))
self._r_rd = CSRStatus(self._dw)
dw = sum(len(s) for s in self.sink.payload.flatten())

self._r_wa = CSRStorage(bits_for(depth-1), write_from_dev=True)
self._r_wc = CSRStorage(bits_for(depth), write_from_dev=True, atomic_write=True)
self._r_ra = CSRStorage(bits_for(depth-1))
self._r_rd = CSRStatus(dw)

###

mem = Memory(self._dw, self._depth)
mem = Memory(dw, depth)
self.specials += mem
wp = mem.get_port(write_capable=True)
rp = mem.get_port()
@@ -95,8 +98,8 @@ def __init__(self, layout, depth=1024):
self.busy.eq(0),

If(self._r_wc.r != 0,
self.endpoints["sink"].ack.eq(1),
If(self.endpoints["sink"].stb,
self.sink.ack.eq(1),
If(self.sink.stb,
self._r_wa.we.eq(1),
self._r_wc.we.eq(1),
wp.we.eq(1)
@@ -106,8 +109,34 @@ def __init__(self, layout, depth=1024):
self._r_wc.dat_w.eq(self._r_wc.storage - 1),

wp.adr.eq(self._r_wa.storage),
wp.dat_w.eq(self.token("sink").raw_bits()),
wp.dat_w.eq(self.sink.payload.raw_bits()),

rp.adr.eq(self._r_ra.storage),
self._r_rd.status.eq(rp.dat_r)
]

class DMAReadController(Module):
def __init__(self, bus_accessor, mode, base_reset=0, length_reset=0):
bus_aw = len(bus_accessor.address.payload.a)
bus_dw = len(bus_accessor.data.payload.d)
alignment_bits = bits_for(bus_dw//8) - 1

layout = [
("length", bus_aw + alignment_bits, length_reset, alignment_bits),
("base", bus_aw + alignment_bits, base_reset, alignment_bits)
]
self.generator = SingleGenerator(layout, mode)
g = DataFlowGraph()
g.add_pipeline(self.generator,
misc.IntSequence(bus_aw, bus_aw),
AbstractActor(plumbing.Buffer),
bus_accessor,
AbstractActor(plumbing.Buffer))
comp_actor = CompositeActor(g)
self.submodules += comp_actor

self.data = comp_actor.q
self.busy = comp_actor.busy

def get_csrs(self):
return self.generator.get_csrs()
26 changes: 17 additions & 9 deletions migen/bank/description.py
Original file line number Diff line number Diff line change
@@ -47,14 +47,17 @@ def do_finalize(self, busword):
self.simple_csrs.append(sc)

class CSRStorage(_CompoundCSR):
def __init__(self, size=1, reset=0, atomic_write=False, write_from_dev=False, name=None):
def __init__(self, size=1, reset=0, atomic_write=False, write_from_dev=False, alignment_bits=0, name=None):
_CompoundCSR.__init__(self, size, name)
self.storage = Signal(self.size, reset=reset)
self.alignment_bits = alignment_bits
self.storage_full = Signal(self.size, reset=reset)
self.storage = Signal(self.size - self.alignment_bits)
self.comb += self.storage.eq(self.storage_full[self.alignment_bits:])
self.atomic_write = atomic_write
if write_from_dev:
self.we = Signal()
self.dat_w = Signal(self.size)
self.sync += If(self.we, self.storage.eq(self.dat_w))
self.dat_w = Signal(self.size - self.alignment_bits)
self.sync += If(self.we, self.storage_full.eq(self.dat_w << self.alignment_bits))

def do_finalize(self, busword):
nwords = (self.size + busword - 1)//busword
@@ -63,20 +66,25 @@ def do_finalize(self, busword):
for i in reversed(range(nwords)):
nbits = min(self.size - i*busword, busword)
sc = CSR(nbits, self.name + str(i) if nwords else self.name)
self.simple_csrs.append(sc)
lo = i*busword
hi = lo+nbits
# read
self.comb += sc.w.eq(self.storage[lo:hi])
if lo >= self.alignment_bits:
self.comb += sc.w.eq(self.storage_full[lo:hi])
elif hi > self.alignment_bits:
self.comb += sc.w.eq(Cat(Replicate(0, hi - self.alignment_bits),
self.storage_full[self.alignment_bits:hi]))
else:
self.comb += sc.w.eq(0)
# write
if nwords > 1 and self.atomic_write:
if i:
self.sync += If(sc.re, backstore[lo-busword:hi-busword].eq(sc.r))
else:
self.sync += If(sc.re, self.storage.eq(Cat(sc.r, backstore)))
self.sync += If(sc.re, self.storage_full.eq(Cat(sc.r, backstore)))
else:
self.sync += If(sc.re, self.storage[lo:hi].eq(sc.r))

self.simple_csrs.append(sc)
self.sync += If(sc.re, self.storage_full[lo:hi].eq(sc.r))

def csrprefix(prefix, csrs):
for csr in csrs:
30 changes: 29 additions & 1 deletion migen/flow/network.py
Original file line number Diff line number Diff line change
@@ -37,6 +37,10 @@ def add_connection(self, source_node, sink_node,
self.add_edge(source_node, sink_node,
source=source_ep, sink=sink_ep,
source_subr=source_subr, sink_subr=sink_subr)

def add_pipeline(self, *nodes):
for n1, n2 in zip(nodes, nodes[1:]):
self.add_connection(n1, n2)

def del_connections(self, source_node, sink_node, data_requirements):
edges_to_delete = []
@@ -203,8 +207,32 @@ def elaborate(self, optimizer=None):
class CompositeActor(Module):
def __init__(self, dfg):
dfg.elaborate()

# expose unconnected endpoints
uc_eps_by_node = dict((node, get_endpoints(node)) for node in dfg)
for u, v, d in dfg.edges_iter(data=True):
uc_eps_u = uc_eps_by_node[u]
source = d["source"]
try:
del uc_eps_u[source]
except KeyError:
pass
uc_eps_v = uc_eps_by_node[v]
sink = d["sink"]
try:
del uc_eps_v[sink]
except KeyError:
pass
for node, uc_eps in uc_eps_by_node.items():
for k, v in uc_eps.items():
assert(not hasattr(self, k))
setattr(self, k, v)

# generate busy signal
self.busy = Signal()
self.comb += [self.busy.eq(optree("|", [node.busy for node in dfg]))]
self.comb += self.busy.eq(optree("|", [node.busy for node in dfg]))

# claim ownership of sub-actors and establish connections
for node in dfg:
self.submodules += node
for u, v, d in dfg.edges_iter(data=True):