From dec2e23fc7129c3450e914d4843b3d87e2719635 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Fri, 4 Sep 2015 14:13:00 -0600 Subject: [PATCH] Remove code that will be into MiSoC or other packages. --- examples/basic/complex.py | 20 - examples/basic/hamming.py | 37 -- examples/basic/simple_gpio.py | 29 -- examples/dataflow/dma.py | 105 ----- examples/dataflow/misc.py | 41 -- examples/dataflow/structuring.py | 73 ---- migen/actorlib/__init__.py | 0 migen/actorlib/dma_wishbone.py | 56 --- migen/actorlib/fifo.py | 57 --- migen/actorlib/misc.py | 96 ----- migen/actorlib/packet.py | 365 ---------------- migen/actorlib/sim.py | 122 ------ migen/actorlib/spi.py | 184 -------- migen/actorlib/structuring.py | 269 ------------ migen/bank/__init__.py | 0 migen/bank/bank.py | 25 -- migen/bank/csrgen.py | 82 ---- migen/bank/description.py | 147 ------- migen/bank/eventmanager.py | 83 ---- migen/bank/wbgen.py | 27 -- migen/bus/__init__.py | 0 migen/bus/csr.py | 134 ------ migen/bus/memory.py | 36 -- migen/bus/transactions.py | 24 -- migen/bus/wishbone.py | 691 ------------------------------- migen/bus/wishbone2csr.py | 28 -- migen/flow/__init__.py | 0 migen/flow/actor.py | 184 -------- migen/flow/hooks.py | 44 -- migen/flow/isd.py | 71 ---- migen/flow/network.py | 330 --------------- migen/flow/perftools.py | 54 --- migen/flow/plumbing.py | 107 ----- migen/flow/transactions.py | 5 - migen/genlib/complex.py | 54 --- migen/genlib/mhamgen.py | 232 ----------- migen/genlib/rob.py | 78 ---- migen/test/test_actor.py | 71 ---- 38 files changed, 3961 deletions(-) delete mode 100644 examples/basic/complex.py delete mode 100644 examples/basic/hamming.py delete mode 100644 examples/basic/simple_gpio.py delete mode 100644 examples/dataflow/dma.py delete mode 100644 examples/dataflow/misc.py delete mode 100644 examples/dataflow/structuring.py delete mode 100644 migen/actorlib/__init__.py delete mode 100644 migen/actorlib/dma_wishbone.py delete mode 100644 migen/actorlib/fifo.py delete mode 100644 migen/actorlib/misc.py delete mode 100644 migen/actorlib/packet.py delete mode 100644 migen/actorlib/sim.py delete mode 100644 migen/actorlib/spi.py delete mode 100644 migen/actorlib/structuring.py delete mode 100644 migen/bank/__init__.py delete mode 100644 migen/bank/bank.py delete mode 100644 migen/bank/csrgen.py delete mode 100644 migen/bank/description.py delete mode 100644 migen/bank/eventmanager.py delete mode 100644 migen/bank/wbgen.py delete mode 100644 migen/bus/__init__.py delete mode 100644 migen/bus/csr.py delete mode 100644 migen/bus/memory.py delete mode 100644 migen/bus/transactions.py delete mode 100644 migen/bus/wishbone.py delete mode 100644 migen/bus/wishbone2csr.py delete mode 100644 migen/flow/__init__.py delete mode 100644 migen/flow/actor.py delete mode 100644 migen/flow/hooks.py delete mode 100644 migen/flow/isd.py delete mode 100644 migen/flow/network.py delete mode 100644 migen/flow/perftools.py delete mode 100644 migen/flow/plumbing.py delete mode 100644 migen/flow/transactions.py delete mode 100644 migen/genlib/complex.py delete mode 100644 migen/genlib/mhamgen.py delete mode 100644 migen/genlib/rob.py delete mode 100644 migen/test/test_actor.py diff --git a/examples/basic/complex.py b/examples/basic/complex.py deleted file mode 100644 index 8f654f81..00000000 --- a/examples/basic/complex.py +++ /dev/null @@ -1,20 +0,0 @@ -from migen.fhdl.std import * -from migen.genlib.complex import * -from migen.fhdl import verilog - - -class Example(Module): - def __init__(self): - w = Complex(32, 42) - A = SignalC(16) - B = SignalC(16) - Bw = SignalC(16) - C = SignalC(16) - D = SignalC(16) - self.comb += Bw.eq(B*w) - self.sync += [ - C.eq(A + Bw), - D.eq(A - Bw) - ] - -print(verilog.convert(Example())) diff --git a/examples/basic/hamming.py b/examples/basic/hamming.py deleted file mode 100644 index a9baa370..00000000 --- a/examples/basic/hamming.py +++ /dev/null @@ -1,37 +0,0 @@ -from migen.fhdl import verilog -from migen.fhdl.std import * -from migen.genlib.mhamgen import HammingGenerator, HammingChecker - - -# Instantiates Hamming code generator and checker modules back -# to back. Also creates an intermediate bus between generator -# and checker and injects a single-bit error on the bus, to -# demonstrate the correction. -class gen_check(Module): - def __init__(self, width=8): - # Save module parameters and instantiate generator and checker - self.width = width - hg = HammingGenerator(self.width) - hc = HammingChecker(self.width, correct=True) - self.submodules += hg - self.submodules += hc - - # Create the intermediate bus and inject a single-bit error on - # the bus. Position of the error bit is controllable by the - # error_bit input. - data = Signal(width) - error_bit = Signal(bits_for(width)) - self.comb += data.eq(hg.data_in ^ (1 << error_bit)) - self.comb += hc.code_in.eq(hg.code_out) - self.comb += hc.data_in.eq(data) - - # Call out I/O necessary for testing the generator/checker - self.io = set() - self.io.add(hg.data_in) - self.io.add(hc.enable) - self.io.add(error_bit) - self.io.add(hc.code_out) - self.io.add(hc.data_out) - -gc = gen_check() -print(verilog.convert(gc, gc.io, name="gen_check")) diff --git a/examples/basic/simple_gpio.py b/examples/basic/simple_gpio.py deleted file mode 100644 index a9d2a8a8..00000000 --- a/examples/basic/simple_gpio.py +++ /dev/null @@ -1,29 +0,0 @@ -from migen.fhdl.std import * -from migen.fhdl import verilog -from migen.genlib.cdc import MultiReg -from migen.bank import description, csrgen - - -class Example(Module): - def __init__(self, ninputs=32, noutputs=32): - r_o = description.CSRStorage(noutputs, atomic_write=True) - r_i = description.CSRStatus(ninputs) - - self.submodules.bank = csrgen.Bank([r_o, r_i]) - self.gpio_in = Signal(ninputs) - self.gpio_out = Signal(ninputs) - - ### - - gpio_in_s = Signal(ninputs) - self.specials += MultiReg(self.gpio_in, gpio_in_s) - self.comb += [ - self.gpio_out.eq(r_o.storage), - r_i.status.eq(gpio_in_s) - ] - -example = Example() -i = example.bank.bus -v = verilog.convert(example, {i.dat_r, i.adr, i.we, i.dat_w, - example.gpio_in, example.gpio_out}) -print(v) diff --git a/examples/dataflow/dma.py b/examples/dataflow/dma.py deleted file mode 100644 index 121fbb74..00000000 --- a/examples/dataflow/dma.py +++ /dev/null @@ -1,105 +0,0 @@ -from random import Random - -from migen.fhdl.std import * -from migen.flow.network import * -from migen.flow.transactions import * -from migen.actorlib import dma_wishbone -from migen.actorlib.sim import * -from migen.bus import wishbone -from migen.sim.generic import run_simulation - - -class MyModel: - def read(self, address): - return address + 4 - - -class MyModelWB(MyModel, wishbone.TargetModel): - def __init__(self): - self.prng = Random(763627) - - def can_ack(self, bus): - return self.prng.randrange(0, 2) - - -def adrgen_gen(): - for i in range(10): - print("Address: " + hex(i)) - yield Token("address", {"a": i}) - - -class SimAdrGen(SimActor): - def __init__(self, nbits): - self.address = Source([("a", nbits)]) - SimActor.__init__(self, adrgen_gen()) - - -def dumper_gen(): - while True: - t = Token("data", idle_wait=True) - yield t - print("Received: " + hex(t.value["d"])) - - -class SimDumper(SimActor): - def __init__(self): - self.data = Sink([("d", 32)]) - SimActor.__init__(self, dumper_gen()) - - -def trgen_gen(): - for i in range(10): - a = i - d = i+10 - print("Address: " + hex(a) + " Data: " + hex(d)) - yield Token("address_data", {"a": a, "d": d}) - - -class SimTrGen(SimActor): - def __init__(self, a_nbits): - self.address_data = Source([("a", a_nbits), ("d", 32)]) - SimActor.__init__(self, trgen_gen()) - - -class TBWishbone(Module): - def __init__(self, master): - self.submodules.peripheral = wishbone.Target(MyModelWB()) - self.submodules.tap = wishbone.Tap(self.peripheral.bus) - self.submodules.interconnect = wishbone.InterconnectPointToPoint(master.bus, - self.peripheral.bus) - - -class TBWishboneReader(TBWishbone): - def __init__(self): - self.adrgen = SimAdrGen(30) - self.reader = dma_wishbone.Reader() - self.dumper = SimDumper() - g = DataFlowGraph() - g.add_connection(self.adrgen, self.reader) - g.add_connection(self.reader, self.dumper) - self.submodules.comp = CompositeActor(g) - TBWishbone.__init__(self, self.reader) - - -class TBWishboneWriter(TBWishbone): - def __init__(self): - self.trgen = SimTrGen(30) - self.writer = dma_wishbone.Writer() - g = DataFlowGraph() - g.add_connection(self.trgen, self.writer) - self.submodules.comp = CompositeActor(g) - TBWishbone.__init__(self, self.writer) - - -def test_wb_reader(): - print("*** Testing Wishbone reader") - run_simulation(TBWishboneReader(), 100) - - -def test_wb_writer(): - print("*** Testing Wishbone writer") - run_simulation(TBWishboneWriter(), 100) - -if __name__ == "__main__": - test_wb_reader() - test_wb_writer() diff --git a/examples/dataflow/misc.py b/examples/dataflow/misc.py deleted file mode 100644 index 475997e2..00000000 --- a/examples/dataflow/misc.py +++ /dev/null @@ -1,41 +0,0 @@ -from migen.flow.network import * -from migen.flow.transactions import * -from migen.actorlib import misc -from migen.actorlib.sim import * -from migen.sim.generic import run_simulation - - -def source_gen(): - for i in range(10): - v = i + 5 - print("==> " + str(v)) - yield Token("source", {"maximum": v}) - - -class SimSource(SimActor): - def __init__(self): - self.source = Source([("maximum", 32)]) - SimActor.__init__(self, source_gen()) - - -def sink_gen(): - while True: - t = Token("sink") - yield t - print(t.value["value"]) - - -class SimSink(SimActor): - def __init__(self): - self.sink = Sink([("value", 32)]) - SimActor.__init__(self, sink_gen()) - -if __name__ == "__main__": - source = SimSource() - loop = misc.IntSequence(32) - sink = SimSink() - g = DataFlowGraph() - g.add_connection(source, loop) - g.add_connection(loop, sink) - comp = CompositeActor(g) - run_simulation(comp, ncycles=500) diff --git a/examples/dataflow/structuring.py b/examples/dataflow/structuring.py deleted file mode 100644 index db2758ee..00000000 --- a/examples/dataflow/structuring.py +++ /dev/null @@ -1,73 +0,0 @@ -from itertools import count - -import networkx as nx -import matplotlib.pyplot as plt - -from migen.flow.network import * -from migen.flow.transactions import * -from migen.actorlib import structuring -from migen.actorlib.sim import * -from migen.flow import perftools -from migen.sim.generic import run_simulation - -pack_factor = 5 -base_layout = [("value", 32)] -packed_layout = structuring.pack_layout(base_layout, pack_factor) -rawbits_layout = [("value", 32*pack_factor)] - - -def source_gen(): - for i in count(0): - yield Token("source", {"value": i}) - - -class SimSource(SimActor): - def __init__(self): - self.source = Source(base_layout) - SimActor.__init__(self, source_gen()) - - -def sink_gen(): - while True: - t = Token("sink") - yield t - print(t.value["value"]) - - -class SimSink(SimActor): - def __init__(self): - self.sink = Sink(base_layout) - SimActor.__init__(self, sink_gen()) - - -class TB(Module): - def __init__(self): - source = SimSource() - sink = SimSink() - - # A tortuous way of passing integer tokens. - packer = structuring.Pack(base_layout, pack_factor) - to_raw = structuring.Cast(packed_layout, rawbits_layout) - from_raw = structuring.Cast(rawbits_layout, packed_layout) - unpacker = structuring.Unpack(pack_factor, base_layout) - - self.g = DataFlowGraph() - self.g.add_connection(source, packer) - self.g.add_connection(packer, to_raw) - self.g.add_connection(to_raw, from_raw) - self.g.add_connection(from_raw, unpacker) - self.g.add_connection(unpacker, sink) - self.submodules.comp = CompositeActor(self.g) - self.submodules.reporter = perftools.DFGReporter(self.g) - -if __name__ == "__main__": - tb = TB() - run_simulation(tb, ncycles=1000) - - g = nx.MultiDiGraph() - for u, v, edge in tb.g.edges_iter(): - g.add_edge(u, v, **edge) - g_layout = nx.spectral_layout(g) - nx.draw(g, g_layout) - nx.draw_networkx_edge_labels(g, g_layout, tb.reporter.get_edge_labels()) - plt.show() diff --git a/migen/actorlib/__init__.py b/migen/actorlib/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/migen/actorlib/dma_wishbone.py b/migen/actorlib/dma_wishbone.py deleted file mode 100644 index 4f6908bb..00000000 --- a/migen/actorlib/dma_wishbone.py +++ /dev/null @@ -1,56 +0,0 @@ -from migen.fhdl.std import * -from migen.bus import wishbone -from migen.flow.actor import * - - -class Reader(Module): - def __init__(self): - self.bus = wishbone.Interface() - self.address = Sink([("a", 30)]) - self.data = Source([("d", 32)]) - self.busy = Signal() - - ### - - bus_stb = Signal() - data_reg_loaded = Signal() - data_reg = Signal(32) - - self.comb += [ - self.busy.eq(data_reg_loaded), - self.bus.we.eq(0), - bus_stb.eq(self.address.stb & (~data_reg_loaded | self.data.ack)), - self.bus.cyc.eq(bus_stb), - self.bus.stb.eq(bus_stb), - self.bus.adr.eq(self.address.a), - self.address.ack.eq(self.bus.ack), - self.data.stb.eq(data_reg_loaded), - self.data.d.eq(data_reg) - ] - self.sync += [ - If(self.data.ack, data_reg_loaded.eq(0)), - If(self.bus.ack, - data_reg_loaded.eq(1), - data_reg.eq(self.bus.dat_r) - ) - ] - - -class Writer(Module): - def __init__(self): - self.bus = wishbone.Interface() - self.address_data = Sink([("a", 30), ("d", 32)]) - self.busy = Signal() - - ### - - self.comb += [ - self.busy.eq(0), - self.bus.we.eq(1), - self.bus.cyc.eq(self.address_data.stb), - self.bus.stb.eq(self.address_data.stb), - self.bus.adr.eq(self.address_data.a), - self.bus.sel.eq(0xf), - self.bus.dat_w.eq(self.address_data.d), - self.address_data.ack.eq(self.bus.ack) - ] diff --git a/migen/actorlib/fifo.py b/migen/actorlib/fifo.py deleted file mode 100644 index 072e99c7..00000000 --- a/migen/actorlib/fifo.py +++ /dev/null @@ -1,57 +0,0 @@ -from migen.fhdl.std import * -from migen.flow.actor import * -from migen.genlib import fifo - - -class _FIFOActor(Module): - def __init__(self, fifo_class, layout, depth): - self.sink = Sink(layout) - self.source = Source(layout) - self.busy = Signal() - - ### - - description = self.sink.description - fifo_layout = [ - ("payload", description.payload_layout), - # Note : Can be optimized by passing parameters - # in another fifo. We will only have one - # data per packet. - ("param", description.param_layout) - ] - if description.packetized: - fifo_layout += [("sop", 1), ("eop", 1)] - - self.submodules.fifo = fifo_class(fifo_layout, depth) - - self.comb += [ - self.sink.ack.eq(self.fifo.writable), - self.fifo.we.eq(self.sink.stb), - self.fifo.din.payload.eq(self.sink.payload), - self.fifo.din.param.eq(self.sink.param), - - self.source.stb.eq(self.fifo.readable), - self.source.payload.eq(self.fifo.dout.payload), - self.source.param.eq(self.fifo.dout.param), - self.fifo.re.eq(self.source.ack) - ] - if description.packetized: - self.comb += [ - self.fifo.din.sop.eq(self.sink.sop), - self.fifo.din.eop.eq(self.sink.eop), - self.source.sop.eq(self.fifo.dout.sop), - self.source.eop.eq(self.fifo.dout.eop) - ] - - -class SyncFIFO(_FIFOActor): - def __init__(self, layout, depth, buffered=False): - _FIFOActor.__init__( - self, - fifo.SyncFIFOBuffered if buffered else fifo.SyncFIFO, - layout, depth) - - -class AsyncFIFO(_FIFOActor): - def __init__(self, layout, depth): - _FIFOActor.__init__(self, fifo.AsyncFIFO, layout, depth) diff --git a/migen/actorlib/misc.py b/migen/actorlib/misc.py deleted file mode 100644 index 3dca8823..00000000 --- a/migen/actorlib/misc.py +++ /dev/null @@ -1,96 +0,0 @@ -from migen.fhdl.std import * -from migen.genlib.record import * -from migen.genlib.fsm import * -from migen.flow.actor import * -from migen.flow.plumbing import Buffer - - -# Generates integers from start to maximum-1 -class IntSequence(Module): - def __init__(self, nbits, offsetbits=0, step=1): - parameters_layout = [("maximum", nbits)] - if offsetbits: - parameters_layout.append(("offset", offsetbits)) - - self.parameters = Sink(parameters_layout) - self.source = Source([("value", max(nbits, offsetbits))]) - self.busy = Signal() - - ### - - load = Signal() - ce = Signal() - last = Signal() - - maximum = Signal(nbits) - if offsetbits: - offset = Signal(offsetbits) - counter = Signal(nbits) - - if step > 1: - self.comb += last.eq(counter + step >= maximum) - else: - self.comb += last.eq(counter + 1 == maximum) - self.sync += [ - If(load, - counter.eq(0), - maximum.eq(self.parameters.maximum), - offset.eq(self.parameters.offset) if offsetbits else None - ).Elif(ce, - If(last, - counter.eq(0) - ).Else( - counter.eq(counter + step) - ) - ) - ] - if offsetbits: - self.comb += self.source.value.eq(counter + offset) - else: - self.comb += self.source.value.eq(counter) - - fsm = FSM() - self.submodules += fsm - fsm.act("IDLE", - load.eq(1), - self.parameters.ack.eq(1), - If(self.parameters.stb, NextState("ACTIVE")) - ) - fsm.act("ACTIVE", - self.busy.eq(1), - self.source.stb.eq(1), - If(self.source.ack, - ce.eq(1), - If(last, NextState("IDLE")) - ) - ) - -# Add buffers on Endpoints (can be used to improve timings) -class BufferizeEndpoints(ModuleTransformer): - def __init__(self, *names): - self.names = names - - def transform_instance(self, submodule): - endpoints = get_endpoints(submodule) - sinks = {} - sources = {} - for name, endpoint in endpoints.items(): - if not self.names or name in self.names: - if isinstance(endpoint, Sink): - sinks.update({name: endpoint}) - elif isinstance(endpoint, Source): - sources.update({name: endpoint}) - - # add buffer on sinks - for name, sink in sinks.items(): - buf = Buffer(sink.description) - submodule.submodules += buf - setattr(submodule, name, buf.d) - submodule.comb += Record.connect(buf.q, sink) - - # add buffer on sources - for name, source in sources.items(): - buf = Buffer(source.description) - submodule.submodules += buf - submodule.comb += Record.connect(source, buf.d) - setattr(submodule, name, buf.q) diff --git a/migen/actorlib/packet.py b/migen/actorlib/packet.py deleted file mode 100644 index 7af4a043..00000000 --- a/migen/actorlib/packet.py +++ /dev/null @@ -1,365 +0,0 @@ -from migen.fhdl.std import * -from migen.genlib.roundrobin import * -from migen.genlib.record import * -from migen.flow.actor import * -from migen.actorlib.fifo import SyncFIFO -from migen.genlib.fsm import FSM, NextState -from migen.genlib.misc import reverse_bytes, Counter - - -class Status(Module): - def __init__(self, endpoint): - self.sop = sop = Signal() - self.eop = eop =Signal() - self.ongoing = Signal() - - ongoing = Signal() - self.comb += \ - If(endpoint.stb, - sop.eq(endpoint.sop), - eop.eq(endpoint.eop & endpoint.ack) - ) - self.sync += ongoing.eq((sop | ongoing) & ~eop) - self.comb += self.ongoing.eq((sop | ongoing) & ~eop) - - -class Arbiter(Module): - def __init__(self, masters, slave): - if len(masters) == 0: - pass - elif len(masters) == 1: - self.grant = Signal() - self.comb += Record.connect(masters.pop(), slave) - else: - self.submodules.rr = RoundRobin(len(masters)) - self.grant = self.rr.grant - cases = {} - for i, master in enumerate(masters): - status = Status(master) - self.submodules += status - self.comb += self.rr.request[i].eq(status.ongoing) - cases[i] = [Record.connect(master, slave)] - self.comb += Case(self.grant, cases) - - -class Dispatcher(Module): - def __init__(self, master, slaves, one_hot=False): - if len(slaves) == 0: - self.sel = Signal() - elif len(slaves) == 1: - self.comb += Record.connect(master, slaves.pop()) - self.sel = Signal() - else: - if one_hot: - self.sel = Signal(len(slaves)) - else: - self.sel = Signal(max=len(slaves)) - - # # # - - status = Status(master) - self.submodules += status - - sel = Signal.like(self.sel) - sel_ongoing = Signal.like(self.sel) - self.sync += \ - If(status.sop, - sel_ongoing.eq(self.sel) - ) - self.comb += \ - If(status.sop, - sel.eq(self.sel) - ).Else( - sel.eq(sel_ongoing) - ) - cases = {} - for i, slave in enumerate(slaves): - if one_hot: - idx = 2**i - else: - idx = i - cases[idx] = [Record.connect(master, slave)] - cases["default"] = [master.ack.eq(1)] - self.comb += Case(sel, cases) - - -class HeaderField: - def __init__(self, byte, offset, width): - self.byte = byte - self.offset = offset - self.width = width - - -class Header: - def __init__(self, fields, length, swap_field_bytes=True): - self.fields = fields - self.length = length - self.swap_field_bytes = swap_field_bytes - - def get_layout(self): - layout = [] - for k, v in sorted(self.fields.items()): - layout.append((k, v.width)) - return layout - - def get_field(self, obj, name, width): - if "_lsb" in name: - field = getattr(obj, name.replace("_lsb", ""))[:width] - elif "_msb" in name: - field = getattr(obj, name.replace("_msb", ""))[width:2*width] - else: - field = getattr(obj, name) - return field - - def encode(self, obj, signal): - r = [] - for k, v in sorted(self.fields.items()): - start = v.byte*8+v.offset - end = start+v.width - field = self.get_field(obj, k, v.width) - if self.swap_field_bytes: - field = reverse_bytes(field) - r.append(signal[start:end].eq(field)) - return r - - def decode(self, signal, obj): - r = [] - for k, v in sorted(self.fields.items()): - start = v.byte*8+v.offset - end = start+v.width - field = self.get_field(obj, k, v.width) - if self.swap_field_bytes: - r.append(field.eq(reverse_bytes(signal[start:end]))) - else: - r.append(field.eq(signal[start:end])) - return r - - -class Packetizer(Module): - def __init__(self, sink_description, source_description, header): - self.sink = sink = Sink(sink_description) - self.source = source = Source(source_description) - self.header = Signal(header.length*8) - - # # # - - dw = flen(self.sink.data) - - header_reg = Signal(header.length*8) - header_words = (header.length*8)//dw - load = Signal() - shift = Signal() - counter = Counter(max=max(header_words, 2)) - self.submodules += counter - - self.comb += header.encode(sink, self.header) - if header_words == 1: - self.sync += [ - If(load, - header_reg.eq(self.header) - ) - ] - else: - self.sync += [ - If(load, - header_reg.eq(self.header) - ).Elif(shift, - header_reg.eq(Cat(header_reg[dw:], Signal(dw))) - ) - ] - - fsm = FSM(reset_state="IDLE") - self.submodules += fsm - - if header_words == 1: - idle_next_state = "COPY" - else: - idle_next_state = "SEND_HEADER" - - fsm.act("IDLE", - sink.ack.eq(1), - counter.reset.eq(1), - If(sink.stb & sink.sop, - sink.ack.eq(0), - source.stb.eq(1), - source.sop.eq(1), - source.eop.eq(0), - source.data.eq(self.header[:dw]), - If(source.stb & source.ack, - load.eq(1), - NextState(idle_next_state) - ) - ) - ) - if header_words != 1: - fsm.act("SEND_HEADER", - source.stb.eq(1), - source.sop.eq(0), - source.eop.eq(0), - source.data.eq(header_reg[dw:2*dw]), - If(source.stb & source.ack, - shift.eq(1), - counter.ce.eq(1), - If(counter.value == header_words-2, - NextState("COPY") - ) - ) - ) - fsm.act("COPY", - source.stb.eq(sink.stb), - source.sop.eq(0), - source.eop.eq(sink.eop), - source.data.eq(sink.data), - source.error.eq(sink.error), - If(source.stb & source.ack, - sink.ack.eq(1), - If(source.eop, - NextState("IDLE") - ) - ) - ) - - -class Depacketizer(Module): - def __init__(self, sink_description, source_description, header): - self.sink = sink = Sink(sink_description) - self.source = source = Source(source_description) - self.header = Signal(header.length*8) - - # # # - - dw = flen(sink.data) - - header_words = (header.length*8)//dw - - shift = Signal() - counter = Counter(max=max(header_words, 2)) - self.submodules += counter - - if header_words == 1: - self.sync += \ - If(shift, - self.header.eq(sink.data) - ) - else: - self.sync += \ - If(shift, - self.header.eq(Cat(self.header[dw:], sink.data)) - ) - - fsm = FSM(reset_state="IDLE") - self.submodules += fsm - - if header_words == 1: - idle_next_state = "COPY" - else: - idle_next_state = "RECEIVE_HEADER" - - fsm.act("IDLE", - sink.ack.eq(1), - counter.reset.eq(1), - If(sink.stb, - shift.eq(1), - NextState(idle_next_state) - ) - ) - if header_words != 1: - fsm.act("RECEIVE_HEADER", - sink.ack.eq(1), - If(sink.stb, - counter.ce.eq(1), - shift.eq(1), - If(counter.value == header_words-2, - NextState("COPY") - ) - ) - ) - no_payload = Signal() - self.sync += \ - If(fsm.before_entering("COPY"), - source.sop.eq(1), - no_payload.eq(sink.eop) - ).Elif(source.stb & source.ack, - source.sop.eq(0) - ) - - if hasattr(sink, "error"): - self.comb += source.error.eq(sink.error) - self.comb += [ - source.eop.eq(sink.eop | no_payload), - source.data.eq(sink.data), - header.decode(self.header, source) - ] - fsm.act("COPY", - sink.ack.eq(source.ack), - source.stb.eq(sink.stb | no_payload), - If(source.stb & source.ack & source.eop, - NextState("IDLE") - ) - ) - - -class Buffer(Module): - def __init__(self, description, data_depth, cmd_depth=4, almost_full=None): - self.sink = sink = Sink(description) - self.source = source = Source(description) - - # # # - - sink_status = Status(self.sink) - source_status = Status(self.source) - self.submodules += sink_status, source_status - - # store incoming packets - # cmds - def cmd_description(): - layout = [("error", 1)] - return EndpointDescription(layout) - cmd_fifo = SyncFIFO(cmd_description(), cmd_depth) - self.submodules += cmd_fifo - self.comb += cmd_fifo.sink.stb.eq(sink_status.eop) - if hasattr(sink, "error"): - self.comb += cmd_fifo.sink.error.eq(sink.error) - - # data - data_fifo = SyncFIFO(description, data_depth, buffered=True) - self.submodules += data_fifo - self.comb += [ - Record.connect(self.sink, data_fifo.sink), - data_fifo.sink.stb.eq(self.sink.stb & cmd_fifo.sink.ack), - self.sink.ack.eq(data_fifo.sink.ack & cmd_fifo.sink.ack), - ] - - # output packets - self.fsm = fsm = FSM(reset_state="IDLE") - self.submodules += fsm - fsm.act("IDLE", - If(cmd_fifo.source.stb, - NextState("SEEK_SOP") - ) - ) - fsm.act("SEEK_SOP", - If(~data_fifo.source.sop, - data_fifo.source.ack.eq(1) - ).Else( - NextState("OUTPUT") - ) - ) - if hasattr(source, "error"): - source_error = self.source.error - else: - source_error = Signal() - - fsm.act("OUTPUT", - Record.connect(data_fifo.source, self.source), - source_error.eq(cmd_fifo.source.error), - If(source_status.eop, - cmd_fifo.source.ack.eq(1), - NextState("IDLE") - ) - ) - - # compute almost full - if almost_full is not None: - self.almost_full = Signal() - self.comb += self.almost_full.eq(data_fifo.fifo.level > almost_full) diff --git a/migen/actorlib/sim.py b/migen/actorlib/sim.py deleted file mode 100644 index 9c7775eb..00000000 --- a/migen/actorlib/sim.py +++ /dev/null @@ -1,122 +0,0 @@ -from migen.fhdl.std import * -from migen.flow.actor import * -from migen.flow.transactions import * -from migen.util.misc import xdir - - -def _sim_multiread(sim, obj): - if isinstance(obj, Signal): - return sim.rd(obj) - else: - r = {} - for k, v in xdir(obj, True): - rd = _sim_multiread(sim, v) - if isinstance(rd, int) or rd: - r[k] = rd - return r - - -def _sim_multiwrite(sim, obj, value): - if isinstance(obj, Signal): - sim.wr(obj, value) - else: - for k, v in value.items(): - _sim_multiwrite(sim, getattr(obj, k), v) - - -# Generators yield None or a tuple of Tokens. -# Tokens for Sink endpoints are pulled and the "value" field filled in. -# Tokens for Source endpoints are pushed according to their "value" field. -# -# NB: the possibility to push several tokens at once is important to interact -# with actors that only accept a group of tokens when all of them are available. -class TokenExchanger(Module): - def __init__(self, generator, actor): - self.generator = generator - self.actor = actor - self.active = set() - self.busy = True - self.done = False - - def _process_transactions(self, selfp): - completed = set() - for token in self.active: - ep = getattr(self.actor, token.endpoint) - if isinstance(ep, Sink): - if selfp.simulator.rd(ep.ack) and selfp.simulator.rd(ep.stb): - token.value = _sim_multiread(selfp.simulator, ep.payload) - completed.add(token) - selfp.simulator.wr(ep.ack, 0) - elif isinstance(ep, Source): - if selfp.simulator.rd(ep.ack) and selfp.simulator.rd(ep.stb): - completed.add(token) - selfp.simulator.wr(ep.stb, 0) - else: - raise TypeError - self.active -= completed - if not self.active: - self.busy = True - - def _update_control_signals(self, selfp): - for token in self.active: - ep = getattr(self.actor, token.endpoint) - if isinstance(ep, Sink): - selfp.simulator.wr(ep.ack, 1) - elif isinstance(ep, Source): - _sim_multiwrite(selfp.simulator, ep.payload, token.value) - selfp.simulator.wr(ep.stb, 1) - else: - raise TypeError - - def _next_transactions(self): - try: - transactions = next(self.generator) - except StopIteration: - self.busy = False - self.done = True - raise StopSimulation - if isinstance(transactions, Token): - self.active = {transactions} - elif isinstance(transactions, (tuple, list, set)): - self.active = set(transactions) - elif transactions is None: - self.active = set() - else: - raise TypeError - if self.active and all(transaction.idle_wait for transaction in self.active): - self.busy = False - - def do_simulation(self, selfp): - if self.active: - self._process_transactions(selfp) - if not self.active: - self._next_transactions() - self._update_control_signals(selfp) - do_simulation.passive = True - - -class SimActor(Module): - def __init__(self, generator): - self.busy = Signal() - self.submodules.token_exchanger = TokenExchanger(generator, self) - - def do_simulation(self, selfp): - selfp.busy = self.token_exchanger.busy - do_simulation.passive = True - - -def _dumper_gen(prefix): - while True: - t = Token("result") - yield t - if len(t.value) > 1: - s = str(t.value) - else: - s = str(list(t.value.values())[0]) - print(prefix + s) - - -class Dumper(SimActor): - def __init__(self, layout, prefix=""): - self.result = Sink(layout) - SimActor.__init__(self, _dumper_gen(prefix)) diff --git a/migen/actorlib/spi.py b/migen/actorlib/spi.py deleted file mode 100644 index 340d4b83..00000000 --- a/migen/actorlib/spi.py +++ /dev/null @@ -1,184 +0,0 @@ -# Simple Processor Interface - -from migen.fhdl.std import * -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]) -# - (name, sublayout) - -def _convert_layout(layout): - r = [] - for element in layout: - if isinstance(element[1], list): - r.append((element[0], _convert_layout(element[1]))) - else: - r.append((element[0], element[1])) - return r - -(MODE_EXTERNAL, MODE_SINGLE_SHOT, MODE_CONTINUOUS) = range(3) - - -class SingleGenerator(Module, AutoCSR): - def __init__(self, layout, mode): - self.source = Source(_convert_layout(layout)) - self.busy = Signal() - - self.comb += self.busy.eq(self.source.stb) - - if mode == MODE_EXTERNAL: - self.trigger = Signal() - trigger = self.trigger - elif mode == MODE_SINGLE_SHOT: - self._shoot = CSR() - trigger = self._shoot.re - elif mode == MODE_CONTINUOUS: - self._enable = CSRStorage() - trigger = self._enable.storage - else: - raise ValueError - self.sync += If(self.source.ack | ~self.source.stb, self.source.stb.eq(trigger)) - - self._create_csrs(layout, self.source.payload, mode != MODE_SINGLE_SHOT) - - def _create_csrs(self, layout, target, atomic, prefix=""): - for element in layout: - if isinstance(element[1], list): - self._create_csrs(element[1], atomic, - getattr(target, element[0]), - element[0] + "_") - else: - name = element[0] - nbits = element[1] - if len(element) > 2: - reset = element[2] - else: - reset = 0 - if len(element) > 3: - alignment = element[3] - else: - alignment = 0 - regname = prefix + name - reg = CSRStorage(nbits + alignment, reset=reset, atomic_write=atomic, - alignment_bits=alignment, name=regname) - setattr(self, "_"+regname, reg) - self.sync += If(self.source.ack | ~self.source.stb, - getattr(target, name).eq(reg.storage)) - - -class Collector(Module, AutoCSR): - def __init__(self, layout, depth=1024): - self.sink = Sink(layout) - self.busy = Signal() - dw = sum(len(s) for s in self.sink.payload.flatten()) - - self._wa = CSRStorage(bits_for(depth-1), write_from_dev=True) - self._wc = CSRStorage(bits_for(depth), write_from_dev=True, atomic_write=True) - self._ra = CSRStorage(bits_for(depth-1)) - self._rd = CSRStatus(dw) - - ### - - mem = Memory(dw, depth) - self.specials += mem - wp = mem.get_port(write_capable=True) - rp = mem.get_port() - self.specials += wp, rp - - self.comb += [ - self.busy.eq(0), - - If(self._wc.r != 0, - self.sink.ack.eq(1), - If(self.sink.stb, - self._wa.we.eq(1), - self._wc.we.eq(1), - wp.we.eq(1) - ) - ), - self._wa.dat_w.eq(self._wa.storage + 1), - self._wc.dat_w.eq(self._wc.storage - 1), - - wp.adr.eq(self._wa.storage), - wp.dat_w.eq(self.sink.payload.raw_bits()), - - rp.adr.eq(self._ra.storage), - self._rd.status.eq(rp.dat_r) - ] - - -class _DMAController(Module): - def __init__(self, bus_accessor, bus_aw, bus_dw, mode, base_reset=0, length_reset=0): - self.alignment_bits = bits_for(bus_dw//8) - 1 - layout = [ - ("length", bus_aw + self.alignment_bits, length_reset, self.alignment_bits), - ("base", bus_aw + self.alignment_bits, base_reset, self.alignment_bits) - ] - self.generator = SingleGenerator(layout, mode) - self._busy = CSRStatus() - - self.length = self.generator._length.storage - self.base = self.generator._base.storage - if hasattr(self.generator, "trigger"): - self.trigger = self.generator.trigger - - def get_csrs(self): - return self.generator.get_csrs() + [self._busy] - - -class DMAReadController(_DMAController): - def __init__(self, bus_accessor, *args, **kwargs): - bus_aw = flen(bus_accessor.address.a) - bus_dw = flen(bus_accessor.data.d) - _DMAController.__init__(self, bus_accessor, bus_aw, bus_dw, *args, **kwargs) - - 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 - self.comb += self._busy.status.eq(self.busy) - - -class DMAWriteController(_DMAController): - def __init__(self, bus_accessor, *args, ack_when_inactive=False, **kwargs): - bus_aw = flen(bus_accessor.address_data.a) - bus_dw = flen(bus_accessor.address_data.d) - _DMAController.__init__(self, bus_accessor, bus_aw, bus_dw, *args, **kwargs) - - g = DataFlowGraph() - adr_buffer = AbstractActor(plumbing.Buffer) - int_sequence = misc.IntSequence(bus_aw, bus_aw) - g.add_pipeline(self.generator, - int_sequence, - adr_buffer) - g.add_connection(adr_buffer, bus_accessor, sink_subr=["a"]) - g.add_connection(AbstractActor(plumbing.Buffer), bus_accessor, sink_subr=["d"]) - comp_actor = CompositeActor(g) - self.submodules += comp_actor - - if ack_when_inactive: - demultiplexer = plumbing.Demultiplexer([("d", bus_dw)], 2) - self.comb += [ - demultiplexer.sel.eq(~adr_buffer.busy), - demultiplexer.source0.connect(comp_actor.d), - demultiplexer.source1.ack.eq(1), - ] - self.submodules += demultiplexer - self.data = demultiplexer.sink - else: - self.data = comp_actor.d - - self.busy = comp_actor.busy - self.comb += self._busy.status.eq(self.busy) diff --git a/migen/actorlib/structuring.py b/migen/actorlib/structuring.py deleted file mode 100644 index 476bdf72..00000000 --- a/migen/actorlib/structuring.py +++ /dev/null @@ -1,269 +0,0 @@ -from copy import copy - -from migen.fhdl.std import * -from migen.genlib.record import * -from migen.flow.actor import * - - -def _rawbits_layout(l): - if isinstance(l, int): - return [("rawbits", l)] - else: - return l - - -class Cast(CombinatorialActor): - def __init__(self, layout_from, layout_to, reverse_from=False, reverse_to=False): - self.sink = Sink(_rawbits_layout(layout_from)) - self.source = Source(_rawbits_layout(layout_to)) - CombinatorialActor.__init__(self) - - ### - - sigs_from = self.sink.payload.flatten() - if reverse_from: - sigs_from = list(reversed(sigs_from)) - sigs_to = self.source.payload.flatten() - if reverse_to: - sigs_to = list(reversed(sigs_to)) - if sum(flen(s) for s in sigs_from) != sum(flen(s) for s in sigs_to): - raise TypeError - self.comb += Cat(*sigs_to).eq(Cat(*sigs_from)) - - -def pack_layout(l, n): - return [("chunk"+str(i), l) for i in range(n)] - - -class Unpack(Module): - def __init__(self, n, layout_to, reverse=False): - self.source = source = Source(layout_to) - description_from = copy(source.description) - description_from.payload_layout = pack_layout(description_from.payload_layout, n) - self.sink = sink = Sink(description_from) - - self.busy = Signal() - - ### - - mux = Signal(max=n) - first = Signal() - last = Signal() - self.comb += [ - first.eq(mux == 0), - last.eq(mux == (n-1)), - source.stb.eq(sink.stb), - sink.ack.eq(last & source.ack) - ] - self.sync += [ - If(source.stb & source.ack, - If(last, - mux.eq(0) - ).Else( - mux.eq(mux + 1) - ) - ) - ] - cases = {} - for i in range(n): - chunk = n-i-1 if reverse else i - cases[i] = [source.payload.raw_bits().eq(getattr(sink.payload, "chunk"+str(chunk)).raw_bits())] - self.comb += Case(mux, cases).makedefault() - - for f in description_from.param_layout: - src = getattr(self.sink, f[0]) - dst = getattr(self.source, f[0]) - self.comb += dst.eq(src) - - if description_from.packetized: - self.comb += [ - source.sop.eq(sink.sop & first), - source.eop.eq(sink.eop & last) - ] - - -class Pack(Module): - def __init__(self, layout_from, n, reverse=False): - self.sink = sink = Sink(layout_from) - description_to = copy(sink.description) - description_to.payload_layout = pack_layout(description_to.payload_layout, n) - self.source = source = Source(description_to) - self.busy = Signal() - - ### - - demux = Signal(max=n) - - load_part = Signal() - strobe_all = Signal() - cases = {} - for i in range(n): - chunk = n-i-1 if reverse else i - cases[i] = [getattr(source.payload, "chunk"+str(chunk)).raw_bits().eq(sink.payload.raw_bits())] - self.comb += [ - self.busy.eq(strobe_all), - sink.ack.eq(~strobe_all | source.ack), - source.stb.eq(strobe_all), - load_part.eq(sink.stb & sink.ack) - ] - - for f in description_to.param_layout: - src = getattr(self.sink, f[0]) - dst = getattr(self.source, f[0]) - self.comb += dst.eq(src) - - if description_to.packetized: - demux_last = ((demux == (n - 1)) | sink.eop) - else: - demux_last = (demux == (n - 1)) - - self.sync += [ - If(source.ack, strobe_all.eq(0)), - If(load_part, - Case(demux, cases), - If(demux_last, - demux.eq(0), - strobe_all.eq(1) - ).Else( - demux.eq(demux + 1) - ) - ) - ] - - if description_to.packetized: - self.sync += [ - If(source.stb & source.ack, - source.sop.eq(sink.sop), - source.eop.eq(sink.eop), - ).Elif(sink.stb & sink.ack, - source.sop.eq(sink.sop | source.sop), - source.eop.eq(sink.eop | source.eop) - ) - ] - - -class Chunkerize(CombinatorialActor): - def __init__(self, layout_from, layout_to, n, reverse=False): - self.sink = Sink(layout_from) - if isinstance(layout_to, EndpointDescription): - layout_to = copy(layout_to) - layout_to.payload_layout = pack_layout(layout_to.payload_layout, n) - else: - layout_to = pack_layout(layout_to, n) - self.source = Source(layout_to) - CombinatorialActor.__init__(self) - - ### - - for i in range(n): - chunk = n-i-1 if reverse else i - for f in self.sink.description.payload_layout: - src = getattr(self.sink, f[0]) - dst = getattr(getattr(self.source, "chunk"+str(chunk)), f[0]) - self.comb += dst.eq(src[i*flen(src)//n:(i+1)*flen(src)//n]) - - for f in self.sink.description.param_layout: - src = getattr(self.sink, f[0]) - dst = getattr(self.source, f[0]) - self.comb += dst.eq(src) - - -class Unchunkerize(CombinatorialActor): - def __init__(self, layout_from, n, layout_to, reverse=False): - if isinstance(layout_from, EndpointDescription): - fields = layout_from.payload_layout - layout_from = copy(layout_from) - layout_from.payload_layout = pack_layout(layout_from.payload_layout, n) - else: - fields = layout_from - layout_from = pack_layout(layout_from, n) - self.sink = Sink(layout_from) - self.source = Source(layout_to) - CombinatorialActor.__init__(self) - - ### - - for i in range(n): - chunk = n-i-1 if reverse else i - for f in fields: - src = getattr(getattr(self.sink, "chunk"+str(chunk)), f[0]) - dst = getattr(self.source, f[0]) - self.comb += dst[i*flen(dst)//n:(i+1)*flen(dst)//n].eq(src) - - for f in self.sink.description.param_layout: - src = getattr(self.sink, f[0]) - dst = getattr(self.source, f[0]) - self.comb += dst.eq(src) - - -class Converter(Module): - def __init__(self, layout_from, layout_to, reverse=False): - self.sink = Sink(layout_from) - self.source = Source(layout_to) - self.busy = Signal() - - ### - - width_from = flen(self.sink.payload.raw_bits()) - width_to = flen(self.source.payload.raw_bits()) - - # downconverter - if width_from > width_to: - if width_from % width_to: - raise ValueError - ratio = width_from//width_to - self.submodules.chunkerize = Chunkerize(layout_from, layout_to, ratio, reverse) - self.submodules.unpack = Unpack(ratio, layout_to) - - self.comb += [ - Record.connect(self.sink, self.chunkerize.sink), - Record.connect(self.chunkerize.source, self.unpack.sink), - Record.connect(self.unpack.source, self.source), - self.busy.eq(self.unpack.busy) - ] - # upconverter - elif width_to > width_from: - if width_to % width_from: - raise ValueError - ratio = width_to//width_from - self.submodules.pack = Pack(layout_from, ratio) - self.submodules.unchunkerize = Unchunkerize(layout_from, ratio, layout_to, reverse) - - self.comb += [ - Record.connect(self.sink, self.pack.sink), - Record.connect(self.pack.source, self.unchunkerize.sink), - Record.connect(self.unchunkerize.source, self.source), - self.busy.eq(self.pack.busy) - ] - # direct connection - else: - self.comb += Record.connect(self.sink, self.source) - - -class Pipeline(Module): - def __init__(self, *modules): - self.busy = Signal() - n = len(modules) - m = modules[0] - # expose sink of first module - # if available - if hasattr(m, "sink"): - self.sink = m.sink - if hasattr(m, "busy"): - busy = m.busy - else: - busy = 0 - for i in range(1, n): - m_n = modules[i] - if hasattr(m_n, "busy"): - busy_n = m_n.busy - else: - busy_n = 0 - self.comb += m.source.connect(m_n.sink) - m = m_n - busy = busy | busy_n - # expose source of last module - # if available - if hasattr(m, "source"): - self.source = m.source - self.comb += self.busy.eq(busy) diff --git a/migen/bank/__init__.py b/migen/bank/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/migen/bank/bank.py b/migen/bank/bank.py deleted file mode 100644 index d8622011..00000000 --- a/migen/bank/bank.py +++ /dev/null @@ -1,25 +0,0 @@ -from migen.fhdl.std import Module, bits_for -from migen.bank.description import CSR - - -class GenericBank(Module): - def __init__(self, description, busword): - # Turn description into simple CSRs and claim ownership of compound CSR modules - self.simple_csrs = [] - for c in description: - if isinstance(c, CSR): - self.simple_csrs.append(c) - else: - c.finalize(busword) - self.simple_csrs += c.get_simple_csrs() - self.submodules += c - self.decode_bits = bits_for(len(self.simple_csrs)-1) - - -def get_offset(description, name, busword): - offset = 0 - for c in description: - if c.name == name: - return offset - offset += (c.size + busword - 1)//busword - raise KeyError("CSR not found: "+name) diff --git a/migen/bank/csrgen.py b/migen/bank/csrgen.py deleted file mode 100644 index 6ef6f41d..00000000 --- a/migen/bank/csrgen.py +++ /dev/null @@ -1,82 +0,0 @@ -from migen.util.misc import xdir -from migen.fhdl.std import * -from migen.bus import csr -from migen.bank.bank import GenericBank - - -class Bank(GenericBank): - def __init__(self, description, address=0, bus=None): - if bus is None: - bus = csr.Interface() - self.bus = bus - - ### - - GenericBank.__init__(self, description, flen(self.bus.dat_w)) - - sel = Signal() - self.comb += sel.eq(self.bus.adr[9:] == address) - - for i, c in enumerate(self.simple_csrs): - self.comb += [ - c.r.eq(self.bus.dat_w[:c.size]), - c.re.eq(sel & \ - self.bus.we & \ - (self.bus.adr[:self.decode_bits] == i)) - ] - - brcases = dict((i, self.bus.dat_r.eq(c.w)) for i, c in enumerate(self.simple_csrs)) - self.sync += [ - self.bus.dat_r.eq(0), - If(sel, Case(self.bus.adr[:self.decode_bits], brcases)) - ] - - -# address_map(name, memory) returns the CSR offset at which to map -# the CSR object (register bank or memory). -# If memory=None, the object is the register bank of object source.name. -# Otherwise, it is a memory object belonging to source.name. -# address_map is called exactly once for each object at each call to -# scan(), so it can have side effects. -class BankArray(Module): - def __init__(self, source, address_map, *ifargs, **ifkwargs): - self.source = source - self.address_map = address_map - self.scan(ifargs, ifkwargs) - - def scan(self, ifargs, ifkwargs): - self.banks = [] - self.srams = [] - for name, obj in xdir(self.source, True): - if hasattr(obj, "get_csrs"): - csrs = obj.get_csrs() - else: - csrs = [] - if hasattr(obj, "get_memories"): - memories = obj.get_memories() - for memory in memories: - mapaddr = self.address_map(name, memory) - if mapaddr is None: - continue - sram_bus = csr.Interface(*ifargs, **ifkwargs) - mmap = csr.SRAM(memory, mapaddr, bus=sram_bus) - self.submodules += mmap - csrs += mmap.get_csrs() - self.srams.append((name, memory, mapaddr, mmap)) - if csrs: - mapaddr = self.address_map(name, None) - if mapaddr is None: - continue - bank_bus = csr.Interface(*ifargs, **ifkwargs) - rmap = Bank(csrs, mapaddr, bus=bank_bus) - self.submodules += rmap - self.banks.append((name, csrs, mapaddr, rmap)) - - def get_rmaps(self): - return [rmap for name, csrs, mapaddr, rmap in self.banks] - - def get_mmaps(self): - return [mmap for name, memory, mapaddr, mmap in self.srams] - - def get_buses(self): - return [i.bus for i in self.get_rmaps() + self.get_mmaps()] diff --git a/migen/bank/description.py b/migen/bank/description.py deleted file mode 100644 index f6b267be..00000000 --- a/migen/bank/description.py +++ /dev/null @@ -1,147 +0,0 @@ -from migen.util.misc import xdir -from migen.fhdl.std import * -from migen.fhdl.tracer import get_obj_var_name - - -class _CSRBase(HUID): - def __init__(self, size, name): - HUID.__init__(self) - self.name = get_obj_var_name(name) - if self.name is None: - raise ValueError("Cannot extract CSR name from code, need to specify.") - self.size = size - - -class CSR(_CSRBase): - def __init__(self, size=1, name=None): - _CSRBase.__init__(self, size, name) - self.re = Signal(name=self.name + "_re") - self.r = Signal(self.size, name=self.name + "_r") - self.w = Signal(self.size, name=self.name + "_w") - - -class _CompoundCSR(_CSRBase, Module): - def __init__(self, size, name): - _CSRBase.__init__(self, size, name) - self.simple_csrs = [] - - def get_simple_csrs(self): - if not self.finalized: - raise FinalizeError - return self.simple_csrs - - def do_finalize(self, busword): - raise NotImplementedError - - -class CSRStatus(_CompoundCSR): - def __init__(self, size=1, reset=0, name=None): - _CompoundCSR.__init__(self, size, name) - self.status = Signal(self.size, reset=reset) - - def do_finalize(self, busword): - nwords = (self.size + busword - 1)//busword - for i in reversed(range(nwords)): - nbits = min(self.size - i*busword, busword) - sc = CSR(nbits, self.name + str(i) if nwords > 1 else self.name) - self.comb += sc.w.eq(self.status[i*busword:i*busword+nbits]) - self.simple_csrs.append(sc) - - -class CSRStorage(_CompoundCSR): - 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.alignment_bits = alignment_bits - self.storage_full = Signal(self.size, reset=reset) - self.storage = Signal(self.size - self.alignment_bits, reset=reset >> alignment_bits) - self.comb += self.storage.eq(self.storage_full[self.alignment_bits:]) - self.atomic_write = atomic_write - self.re = Signal() - if write_from_dev: - self.we = Signal() - 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 - if nwords > 1 and self.atomic_write: - backstore = Signal(self.size - busword, name=self.name + "_backstore") - 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 - 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_full.eq(Cat(sc.r, backstore))) - else: - self.sync += If(sc.re, self.storage_full[lo:hi].eq(sc.r)) - self.sync += self.re.eq(sc.re) - - -def csrprefix(prefix, csrs, done): - for csr in csrs: - if csr.huid not in done: - csr.name = prefix + csr.name - done.add(csr.huid) - - -def memprefix(prefix, memories, done): - for memory in memories: - if memory.huid not in done: - memory.name_override = prefix + memory.name_override - done.add(memory.huid) - - -class AutoCSR: - def get_memories(self): - try: - exclude = self.autocsr_exclude - except AttributeError: - exclude = {} - try: - prefixed = self.__prefixed - except AttributeError: - prefixed = self.__prefixed = set() - r = [] - for k, v in xdir(self, True): - if k not in exclude: - if isinstance(v, Memory): - r.append(v) - elif hasattr(v, "get_memories") and callable(v.get_memories): - memories = v.get_memories() - memprefix(k + "_", memories, prefixed) - r += memories - return sorted(r, key=lambda x: x.huid) - - def get_csrs(self): - try: - exclude = self.autocsr_exclude - except AttributeError: - exclude = {} - try: - prefixed = self.__prefixed - except AttributeError: - prefixed = self.__prefixed = set() - r = [] - for k, v in xdir(self, True): - if k not in exclude: - if isinstance(v, _CSRBase): - r.append(v) - elif hasattr(v, "get_csrs") and callable(v.get_csrs): - csrs = v.get_csrs() - csrprefix(k + "_", csrs, prefixed) - r += csrs - return sorted(r, key=lambda x: x.huid) diff --git a/migen/bank/eventmanager.py b/migen/bank/eventmanager.py deleted file mode 100644 index 1edfcb04..00000000 --- a/migen/bank/eventmanager.py +++ /dev/null @@ -1,83 +0,0 @@ -from migen.util.misc import xdir -from migen.fhdl.std import * -from migen.bank.description import * -from migen.genlib.misc import optree - - -class _EventSource(HUID): - def __init__(self): - HUID.__init__(self) - self.status = Signal() # value in the status register - self.pending = Signal() # value in the pending register + assert irq if unmasked - self.trigger = Signal() # trigger signal interface to the user design - self.clear = Signal() # clearing attempt by W1C to pending register, ignored by some event sources - - -# set on a positive trigger pulse -class EventSourcePulse(Module, _EventSource): - def __init__(self): - _EventSource.__init__(self) - self.comb += self.status.eq(0) - self.sync += [ - If(self.clear, self.pending.eq(0)), - If(self.trigger, self.pending.eq(1)) - ] - - -# set on the falling edge of the trigger, status = trigger -class EventSourceProcess(Module, _EventSource): - def __init__(self): - _EventSource.__init__(self) - self.comb += self.status.eq(self.trigger) - old_trigger = Signal() - self.sync += [ - If(self.clear, self.pending.eq(0)), - old_trigger.eq(self.trigger), - If(~self.trigger & old_trigger, self.pending.eq(1)) - ] - - -# all status set by external trigger -class EventSourceLevel(Module, _EventSource): - def __init__(self): - _EventSource.__init__(self) - self.comb += [ - self.status.eq(self.trigger), - self.pending.eq(self.trigger) - ] - - -class EventManager(Module, AutoCSR): - def __init__(self): - self.irq = Signal() - - def do_finalize(self): - sources_u = [v for k, v in xdir(self, True) if isinstance(v, _EventSource)] - sources = sorted(sources_u, key=lambda x: x.huid) - n = len(sources) - self.status = CSR(n) - self.pending = CSR(n) - self.enable = CSRStorage(n) - - for i, source in enumerate(sources): - self.comb += [ - self.status.w[i].eq(source.status), - If(self.pending.re & self.pending.r[i], source.clear.eq(1)), - self.pending.w[i].eq(source.pending) - ] - - irqs = [self.pending.w[i] & self.enable.storage[i] for i in range(n)] - self.comb += self.irq.eq(optree("|", irqs)) - - def __setattr__(self, name, value): - object.__setattr__(self, name, value) - if isinstance(value, _EventSource): - if self.finalized: - raise FinalizeError - self.submodules += value - - -class SharedIRQ(Module): - def __init__(self, *event_managers): - self.irq = Signal() - self.comb += self.irq.eq(optree("|", [ev.irq for ev in event_managers])) diff --git a/migen/bank/wbgen.py b/migen/bank/wbgen.py deleted file mode 100644 index e7f02242..00000000 --- a/migen/bank/wbgen.py +++ /dev/null @@ -1,27 +0,0 @@ -from migen.fhdl.std import * -from migen.bus import wishbone -from migen.bank.bank import GenericBank - - -class Bank(GenericBank): - def __init__(self, description, bus=None): - if bus is None: - bus = wishbone.Interface() - self.bus = bus - - ### - - GenericBank.__init__(self, description, flen(self.bus.dat_w)) - - for i, c in enumerate(self.simple_csrs): - self.comb += [ - c.r.eq(self.bus.dat_w[:c.size]), - c.re.eq(self.bus.cyc & self.bus.stb & ~self.bus.ack & self.bus.we & \ - (self.bus.adr[:self.decode_bits] == i)) - ] - - brcases = dict((i, self.bus.dat_r.eq(c.w)) for i, c in enumerate(self.simple_csrs)) - self.sync += [ - Case(self.bus.adr[:self.decode_bits], brcases), - If(bus.ack, bus.ack.eq(0)).Elif(bus.cyc & bus.stb, bus.ack.eq(1)) - ] diff --git a/migen/bus/__init__.py b/migen/bus/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/migen/bus/csr.py b/migen/bus/csr.py deleted file mode 100644 index 414363f9..00000000 --- a/migen/bus/csr.py +++ /dev/null @@ -1,134 +0,0 @@ -from migen.fhdl.std import * -from migen.bus.transactions import * -from migen.bank.description import CSRStorage -from migen.genlib.record import * -from migen.genlib.misc import chooser - -_layout = [ - ("adr", "address_width", DIR_M_TO_S), - ("we", 1, DIR_M_TO_S), - ("dat_w", "data_width", DIR_M_TO_S), - ("dat_r", "data_width", DIR_S_TO_M) -] - - -class Interface(Record): - def __init__(self, data_width=8, address_width=14): - Record.__init__(self, set_layout_parameters(_layout, - data_width=data_width, address_width=address_width)) - - -class Interconnect(Module): - def __init__(self, master, slaves): - self.comb += master.connect(*slaves) - - -class Initiator(Module): - def __init__(self, generator, bus=None): - self.generator = generator - if bus is None: - bus = Interface() - self.bus = bus - self.transaction = None - self.read_data_ready = False - self.done = False - - def do_simulation(self, selfp): - if not self.done: - if self.transaction is not None: - if isinstance(self.transaction, TRead): - if self.read_data_ready: - self.transaction.data = selfp.bus.dat_r - self.transaction = None - self.read_data_ready = False - else: - self.read_data_ready = True - else: - selfp.bus.we = 0 - self.transaction = None - if self.transaction is None: - try: - self.transaction = next(self.generator) - except StopIteration: - self.transaction = None - raise StopSimulation - if self.transaction is not None: - selfp.bus.adr = self.transaction.address - if isinstance(self.transaction, TWrite): - selfp.bus.we = 1 - selfp.bus.dat_w = self.transaction.data - - -class SRAM(Module): - def __init__(self, mem_or_size, address, read_only=None, init=None, bus=None): - if bus is None: - bus = Interface() - self.bus = bus - data_width = flen(self.bus.dat_w) - if isinstance(mem_or_size, Memory): - mem = mem_or_size - else: - mem = Memory(data_width, mem_or_size//(data_width//8), init=init) - csrw_per_memw = (mem.width + data_width - 1)//data_width - word_bits = log2_int(csrw_per_memw) - page_bits = log2_int((mem.depth*csrw_per_memw + 511)//512, False) - if page_bits: - self._page = CSRStorage(page_bits, name=mem.name_override + "_page") - else: - self._page = None - if read_only is None: - if hasattr(mem, "bus_read_only"): - read_only = mem.bus_read_only - else: - read_only = False - - ### - - port = mem.get_port(write_capable=not read_only) - self.specials += mem, port - - sel = Signal() - sel_r = Signal() - self.sync += sel_r.eq(sel) - self.comb += sel.eq(self.bus.adr[9:] == address) - - if word_bits: - word_index = Signal(word_bits) - word_expanded = Signal(csrw_per_memw*data_width) - self.sync += word_index.eq(self.bus.adr[:word_bits]) - self.comb += [ - word_expanded.eq(port.dat_r), - If(sel_r, - chooser(word_expanded, word_index, self.bus.dat_r, n=csrw_per_memw, reverse=True) - ) - ] - if not read_only: - wregs = [] - for i in range(csrw_per_memw-1): - wreg = Signal(data_width) - self.sync += If(sel & self.bus.we & (self.bus.adr[:word_bits] == i), wreg.eq(self.bus.dat_w)) - wregs.append(wreg) - memword_chunks = [self.bus.dat_w] + list(reversed(wregs)) - self.comb += [ - port.we.eq(sel & self.bus.we & (self.bus.adr[:word_bits] == csrw_per_memw - 1)), - port.dat_w.eq(Cat(*memword_chunks)) - ] - else: - self.comb += If(sel_r, self.bus.dat_r.eq(port.dat_r)) - if not read_only: - self.comb += [ - port.we.eq(sel & self.bus.we), - port.dat_w.eq(self.bus.dat_w) - ] - - if self._page is None: - self.comb += port.adr.eq(self.bus.adr[word_bits:word_bits+flen(port.adr)]) - else: - pv = self._page.storage - self.comb += port.adr.eq(Cat(self.bus.adr[word_bits:word_bits+flen(port.adr)-flen(pv)], pv)) - - def get_csrs(self): - if self._page is None: - return [] - else: - return [self._page] diff --git a/migen/bus/memory.py b/migen/bus/memory.py deleted file mode 100644 index fc720a2a..00000000 --- a/migen/bus/memory.py +++ /dev/null @@ -1,36 +0,0 @@ -from migen.fhdl.std import * -from migen.bus.transactions import * - - -def _byte_mask(orig, dat_w, sel): - r = 0 - shift = 0 - while sel: - if sel & 1: - r |= (dat_w & 0xff) << shift - else: - r |= (orig & 0xff) << shift - orig >>= 8 - dat_w >>= 8 - sel >>= 1 - shift += 8 - return r - - -class Initiator(Module): - def __init__(self, generator, mem): - self.generator = generator - self.mem = mem - - def do_simulation(self, selfp): - try: - transaction = next(self.generator) - except StopIteration: - transaction = None - raise StopSimulation - if isinstance(transaction, TRead): - transaction.data = selfp.mem[transaction.address] - elif isinstance(transaction, TWrite): - d = selfp.mem[transaction.address] - d_mask = _byte_mask(d, transaction.data, transaction.sel) - selfp.mem[transaction.address] = d_mask diff --git a/migen/bus/transactions.py b/migen/bus/transactions.py deleted file mode 100644 index 32379e57..00000000 --- a/migen/bus/transactions.py +++ /dev/null @@ -1,24 +0,0 @@ -from migen.fhdl.std import * - - -class Transaction: - def __init__(self, address, data=0, sel=None, busname=None): - self.address = address - self.data = data - if sel is None: - bytes = (bits_for(data) + 7)//8 - sel = 2**bytes - 1 - self.sel = sel - self.busname = busname - self.latency = 0 - - def __str__(self): - return "<" + self.__class__.__name__ + " adr:" + hex(self.address) + " dat:" + hex(self.data) + ">" - - -class TRead(Transaction): - pass - - -class TWrite(Transaction): - pass diff --git a/migen/bus/wishbone.py b/migen/bus/wishbone.py deleted file mode 100644 index a61f3aef..00000000 --- a/migen/bus/wishbone.py +++ /dev/null @@ -1,691 +0,0 @@ -from migen.fhdl.std import * -from migen.genlib import roundrobin -from migen.genlib.record import * -from migen.genlib.misc import split, displacer, optree, chooser -from migen.genlib.misc import FlipFlop, Counter -from migen.genlib.fsm import FSM, NextState -from migen.bus.transactions import * - -_layout = [ - ("adr", 30, DIR_M_TO_S), - ("dat_w", "data_width", DIR_M_TO_S), - ("dat_r", "data_width", DIR_S_TO_M), - ("sel", "sel_width", DIR_M_TO_S), - ("cyc", 1, DIR_M_TO_S), - ("stb", 1, DIR_M_TO_S), - ("ack", 1, DIR_S_TO_M), - ("we", 1, DIR_M_TO_S), - ("cti", 3, DIR_M_TO_S), - ("bte", 2, DIR_M_TO_S), - ("err", 1, DIR_S_TO_M) -] - - -class Interface(Record): - def __init__(self, data_width=32): - Record.__init__(self, set_layout_parameters(_layout, - data_width=data_width, - sel_width=data_width//8)) - - -class InterconnectPointToPoint(Module): - def __init__(self, master, slave): - self.comb += master.connect(slave) - - -class Arbiter(Module): - def __init__(self, masters, target): - self.submodules.rr = roundrobin.RoundRobin(len(masters)) - - # mux master->slave signals - for name, size, direction in _layout: - if direction == DIR_M_TO_S: - choices = Array(getattr(m, name) for m in masters) - self.comb += getattr(target, name).eq(choices[self.rr.grant]) - - # connect slave->master signals - for name, size, direction in _layout: - if direction == DIR_S_TO_M: - source = getattr(target, name) - for i, m in enumerate(masters): - dest = getattr(m, name) - if name == "ack" or name == "err": - self.comb += dest.eq(source & (self.rr.grant == i)) - else: - self.comb += dest.eq(source) - - # connect bus requests to round-robin selector - reqs = [m.cyc for m in masters] - self.comb += self.rr.request.eq(Cat(*reqs)) - - -class Decoder(Module): - # slaves is a list of pairs: - # 0) function that takes the address signal and returns a FHDL expression - # that evaluates to 1 when the slave is selected and 0 otherwise. - # 1) wishbone.Slave reference. - # register adds flip-flops after the address comparators. Improves timing, - # but breaks Wishbone combinatorial feedback. - def __init__(self, master, slaves, register=False): - ns = len(slaves) - slave_sel = Signal(ns) - slave_sel_r = Signal(ns) - - # decode slave addresses - self.comb += [slave_sel[i].eq(fun(master.adr)) - for i, (fun, bus) in enumerate(slaves)] - if register: - self.sync += slave_sel_r.eq(slave_sel) - else: - self.comb += slave_sel_r.eq(slave_sel) - - # connect master->slaves signals except cyc - for slave in slaves: - for name, size, direction in _layout: - if direction == DIR_M_TO_S and name != "cyc": - self.comb += getattr(slave[1], name).eq(getattr(master, name)) - - # combine cyc with slave selection signals - self.comb += [slave[1].cyc.eq(master.cyc & slave_sel[i]) - for i, slave in enumerate(slaves)] - - # generate master ack (resp. err) by ORing all slave acks (resp. errs) - self.comb += [ - master.ack.eq(optree("|", [slave[1].ack for slave in slaves])), - master.err.eq(optree("|", [slave[1].err for slave in slaves])) - ] - - # mux (1-hot) slave data return - masked = [Replicate(slave_sel_r[i], flen(master.dat_r)) & slaves[i][1].dat_r for i in range(ns)] - self.comb += master.dat_r.eq(optree("|", masked)) - - -class InterconnectShared(Module): - def __init__(self, masters, slaves, register=False): - shared = Interface() - self.submodules += Arbiter(masters, shared) - self.submodules += Decoder(shared, slaves, register) - - -class Crossbar(Module): - def __init__(self, masters, slaves, register=False): - matches, busses = zip(*slaves) - access = [[Interface() for j in slaves] for i in masters] - # decode each master into its access row - for row, master in zip(access, masters): - row = list(zip(matches, row)) - self.submodules += Decoder(master, row, register) - # arbitrate each access column onto its slave - for column, bus in zip(zip(*access), busses): - self.submodules += Arbiter(column, bus) - - -class DownConverter(Module): - """DownConverter - - This module splits Wishbone accesses from a master interface to a smaller - slave interface. - - Writes: - Writes from master are splitted N writes to the slave. Access is acked when the last - access is acked by the slave. - - Reads: - Read from master are splitted in N reads to the the slave. Read datas from - the slave are cached before being presented concatenated on the last access. - - TODO: - Manage err signal? (Not implemented since we generally don't use it on Migen/MiSoC modules) - """ - def __init__(self, master, slave): - dw_from = flen(master.dat_r) - dw_to = flen(slave.dat_w) - ratio = dw_from//dw_to - - # # # - - read = Signal() - write = Signal() - - counter = Counter(max=ratio) - self.submodules += counter - counter_done = Signal() - self.comb += counter_done.eq(counter.value == ratio-1) - - # Main FSM - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - counter.reset.eq(1), - If(master.stb & master.cyc, - If(master.we, - NextState("WRITE") - ).Else( - NextState("READ") - ) - ) - ) - fsm.act("WRITE", - write.eq(1), - slave.we.eq(1), - slave.cyc.eq(1), - If(master.stb & master.cyc, - slave.stb.eq(1), - If(slave.ack, - counter.ce.eq(1), - If(counter_done, - master.ack.eq(1), - NextState("IDLE") - ) - ) - ).Elif(~master.cyc, - NextState("IDLE") - ) - ) - fsm.act("READ", - read.eq(1), - slave.cyc.eq(1), - If(master.stb & master.cyc, - slave.stb.eq(1), - If(slave.ack, - counter.ce.eq(1), - If(counter_done, - master.ack.eq(1), - NextState("IDLE") - ) - ) - ).Elif(~master.cyc, - NextState("IDLE") - ) - ) - - # Address - self.comb += [ - If(counter_done, - slave.cti.eq(7) # indicate end of burst - ).Else( - slave.cti.eq(2) - ), - slave.adr.eq(Cat(counter.value, master.adr)) - ] - - # Datapath - cases = {} - for i in range(ratio): - cases[i] = [ - slave.sel.eq(master.sel[i*dw_to//8:(i+1)*dw_to]), - slave.dat_w.eq(master.dat_w[i*dw_to:(i+1)*dw_to]) - ] - self.comb += Case(counter.value, cases) - - - cached_data = Signal(dw_from) - self.comb += master.dat_r.eq(Cat(cached_data[dw_to:], slave.dat_r)) - self.sync += \ - If(read & counter.ce, - cached_data.eq(master.dat_r) - ) - - -class UpConverter(Module): - """UpConverter - - This module up-converts wishbone accesses and bursts from a master interface - to a wider slave interface. This allows efficient use wishbone bursts. - - Writes: - Wishbone writes are cached before being written to the slave. Access to - the slave is done at the end of a burst or when address reach end of burst - addressing. - - Reads: - Cache is refilled only at the beginning of each burst, the subsequent - reads of a burst use the cached data. - - TODO: - Manage err signal? (Not implemented since we generally don't use it on Migen/MiSoC modules) - """ - def __init__(self, master, slave): - dw_from = flen(master.dat_r) - dw_to = flen(slave.dat_w) - ratio = dw_to//dw_from - ratiobits = log2_int(ratio) - - # # # - - write = Signal() - evict = Signal() - refill = Signal() - read = Signal() - - address = FlipFlop(30) - self.submodules += address - self.comb += address.d.eq(master.adr) - - counter = Counter(max=ratio) - self.submodules += counter - counter_offset = Signal(max=ratio) - counter_done = Signal() - self.comb += [ - counter_offset.eq(address.q), - counter_done.eq((counter.value + counter_offset) == ratio-1) - ] - - cached_data = Signal(dw_to) - cached_sel = Signal(dw_to//8) - - end_of_burst = Signal() - self.comb += end_of_burst.eq(~master.cyc | - (master.stb & master.cyc & master.ack & ((master.cti == 7) | counter_done))) - - - need_refill = FlipFlop(reset=1) - self.submodules += need_refill - self.comb += [ - need_refill.reset.eq(end_of_burst), - need_refill.d.eq(0) - ] - - # Main FSM - self.submodules.fsm = fsm = FSM() - fsm.act("IDLE", - counter.reset.eq(1), - If(master.stb & master.cyc, - address.ce.eq(1), - If(master.we, - NextState("WRITE") - ).Else( - If(need_refill.q, - NextState("REFILL") - ).Else( - NextState("READ") - ) - ) - ) - ) - fsm.act("WRITE", - If(master.stb & master.cyc, - write.eq(1), - counter.ce.eq(1), - master.ack.eq(1), - If(counter_done, - NextState("EVICT") - ) - ).Elif(~master.cyc, - NextState("EVICT") - ) - ) - fsm.act("EVICT", - evict.eq(1), - slave.stb.eq(1), - slave.we.eq(1), - slave.cyc.eq(1), - slave.dat_w.eq(cached_data), - slave.sel.eq(cached_sel), - If(slave.ack, - NextState("IDLE") - ) - ) - fsm.act("REFILL", - refill.eq(1), - slave.stb.eq(1), - slave.cyc.eq(1), - If(slave.ack, - need_refill.ce.eq(1), - NextState("READ") - ) - ) - fsm.act("READ", - read.eq(1), - If(master.stb & master.cyc, - master.ack.eq(1) - ), - NextState("IDLE") - ) - - # Address - self.comb += [ - slave.cti.eq(7), # we are not able to generate bursts since up-converting - slave.adr.eq(address.q[ratiobits:]) - ] - - # Datapath - cached_datas = [FlipFlop(dw_from) for i in range(ratio)] - cached_sels = [FlipFlop(dw_from//8) for i in range(ratio)] - self.submodules += cached_datas, cached_sels - - cases = {} - for i in range(ratio): - write_sel = Signal() - cases[i] = write_sel.eq(1) - self.comb += [ - cached_sels[i].reset.eq(counter.reset), - If(write, - cached_datas[i].d.eq(master.dat_w), - ).Else( - cached_datas[i].d.eq(slave.dat_r[dw_from*i:dw_from*(i+1)]) - ), - cached_sels[i].d.eq(master.sel), - If((write & write_sel) | refill, - cached_datas[i].ce.eq(1), - cached_sels[i].ce.eq(1) - ) - ] - self.comb += Case(counter.value + counter_offset, cases) - - cases = {} - for i in range(ratio): - cases[i] = master.dat_r.eq(cached_datas[i].q) - self.comb += Case(address.q[:ratiobits], cases) - - self.comb += [ - cached_data.eq(Cat([cached_data.q for cached_data in cached_datas])), - cached_sel.eq(Cat([cached_sel.q for cached_sel in cached_sels])) - ] - - -class Converter(Module): - """Converter - - This module is a wrapper for DownConverter and UpConverter. - It should preferably be used rather than direct instantiations - of specific converters. - """ - def __init__(self, master, slave): - self.master = master - self.slave = slave - - # # # - - dw_from = flen(master.dat_r) - dw_to = flen(slave.dat_r) - if dw_from > dw_to: - downconverter = DownConverter(master, slave) - self.submodules += downconverter - elif dw_from < dw_to: - upconverter = UpConverter(master, slave) - self.submodules += upconverter - else: - Record.connect(master, slave) - - -class Cache(Module): - """Cache - - This module is a write-back wishbone cache that can be used as a L2 cache. - Cachesize (in 32-bit words) is the size of the data store and must be a power of 2 - """ - def __init__(self, cachesize, master, slave): - self.master = master - self.slave = slave - - ### - - dw_from = flen(master.dat_r) - dw_to = flen(slave.dat_r) - if dw_to > dw_from and (dw_to % dw_from) != 0: - raise ValueError("Slave data width must be a multiple of {dw}".format(dw=dw_from)) - if dw_to < dw_from and (dw_from % dw_to) != 0: - raise ValueError("Master data width must be a multiple of {dw}".format(dw=dw_to)) - - # Split address: - # TAG | LINE NUMBER | LINE OFFSET - offsetbits = log2_int(max(dw_to//dw_from, 1)) - addressbits = flen(slave.adr) + offsetbits - linebits = log2_int(cachesize) - offsetbits - tagbits = addressbits - linebits - wordbits = log2_int(max(dw_from//dw_to, 1)) - adr_offset, adr_line, adr_tag = split(master.adr, offsetbits, linebits, tagbits) - word = Signal(wordbits) if wordbits else None - - # Data memory - data_mem = Memory(dw_to*2**wordbits, 2**linebits) - data_port = data_mem.get_port(write_capable=True, we_granularity=8) - self.specials += data_mem, data_port - - write_from_slave = Signal() - if adr_offset is None: - adr_offset_r = None - else: - adr_offset_r = Signal(offsetbits) - self.sync += adr_offset_r.eq(adr_offset) - - self.comb += [ - data_port.adr.eq(adr_line), - If(write_from_slave, - displacer(slave.dat_r, word, data_port.dat_w), - displacer(Replicate(1, dw_to//8), word, data_port.we) - ).Else( - data_port.dat_w.eq(Replicate(master.dat_w, max(dw_to//dw_from, 1))), - If(master.cyc & master.stb & master.we & master.ack, - displacer(master.sel, adr_offset, data_port.we, 2**offsetbits, reverse=True) - ) - ), - chooser(data_port.dat_r, word, slave.dat_w), - slave.sel.eq(2**(dw_to//8)-1), - chooser(data_port.dat_r, adr_offset_r, master.dat_r, reverse=True) - ] - - - # Tag memory - tag_layout = [("tag", tagbits), ("dirty", 1)] - tag_mem = Memory(layout_len(tag_layout), 2**linebits) - tag_port = tag_mem.get_port(write_capable=True) - self.specials += tag_mem, tag_port - tag_do = Record(tag_layout) - tag_di = Record(tag_layout) - self.comb += [ - tag_do.raw_bits().eq(tag_port.dat_r), - tag_port.dat_w.eq(tag_di.raw_bits()) - ] - - self.comb += [ - tag_port.adr.eq(adr_line), - tag_di.tag.eq(adr_tag) - ] - if word is not None: - self.comb += slave.adr.eq(Cat(word, adr_line, tag_do.tag)) - else: - self.comb += slave.adr.eq(Cat(adr_line, tag_do.tag)) - - # slave word computation, word_clr and word_inc will be simplified - # at synthesis when wordbits=0 - word_clr = Signal() - word_inc = Signal() - if word is not None: - self.sync += \ - If(word_clr, - word.eq(0), - ).Elif(word_inc, - word.eq(word+1) - ) - - def word_is_last(word): - if word is not None: - return word == 2**wordbits-1 - else: - return 1 - - # Control FSM - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - If(master.cyc & master.stb, - NextState("TEST_HIT") - ) - ) - fsm.act("TEST_HIT", - word_clr.eq(1), - If(tag_do.tag == adr_tag, - master.ack.eq(1), - If(master.we, - tag_di.dirty.eq(1), - tag_port.we.eq(1) - ), - NextState("IDLE") - ).Else( - If(tag_do.dirty, - NextState("EVICT") - ).Else( - NextState("REFILL_WRTAG") - ) - ) - ) - - fsm.act("EVICT", - slave.stb.eq(1), - slave.cyc.eq(1), - slave.we.eq(1), - If(slave.ack, - word_inc.eq(1), - If(word_is_last(word), - NextState("REFILL_WRTAG") - ) - ) - ) - fsm.act("REFILL_WRTAG", - # Write the tag first to set the slave address - tag_port.we.eq(1), - word_clr.eq(1), - NextState("REFILL") - ) - fsm.act("REFILL", - slave.stb.eq(1), - slave.cyc.eq(1), - slave.we.eq(0), - If(slave.ack, - write_from_slave.eq(1), - word_inc.eq(1), - If(word_is_last(word), - NextState("TEST_HIT"), - ).Else( - NextState("REFILL") - ) - ) - ) - - -class Tap(Module): - def __init__(self, bus, handler=print): - self.bus = bus - self.handler = handler - - def do_simulation(self, selfp): - if selfp.bus.ack: - assert(selfp.bus.cyc and selfp.bus.stb) - if selfp.bus.we: - transaction = TWrite(selfp.bus.adr, - selfp.bus.dat_w, - selfp.bus.sel) - else: - transaction = TRead(selfp.bus.adr, - selfp.bus.dat_r) - self.handler(transaction) - do_simulation.passive = True - - -class Initiator(Module): - def __init__(self, generator, bus=None): - self.generator = generator - if bus is None: - bus = Interface() - self.bus = bus - self.transaction_start = 0 - self.transaction = None - - def do_simulation(self, selfp): - if self.transaction is None or selfp.bus.ack: - if self.transaction is not None: - self.transaction.latency = selfp.simulator.cycle_counter - self.transaction_start - 1 - if isinstance(self.transaction, TRead): - self.transaction.data = selfp.bus.dat_r - try: - self.transaction = next(self.generator) - except StopIteration: - selfp.bus.cyc = 0 - selfp.bus.stb = 0 - raise StopSimulation - if self.transaction is not None: - self.transaction_start = selfp.simulator.cycle_counter - selfp.bus.cyc = 1 - selfp.bus.stb = 1 - selfp.bus.adr = self.transaction.address - if isinstance(self.transaction, TWrite): - selfp.bus.we = 1 - selfp.bus.sel = self.transaction.sel - selfp.bus.dat_w = self.transaction.data - else: - selfp.bus.we = 0 - else: - selfp.bus.cyc = 0 - selfp.bus.stb = 0 - - -class TargetModel: - def read(self, address): - return 0 - - def write(self, address, data, sel): - pass - - def can_ack(self, bus): - return True - - -class Target(Module): - def __init__(self, model, bus=None): - if bus is None: - bus = Interface() - self.bus = bus - self.model = model - - def do_simulation(self, selfp): - bus = selfp.bus - if not bus.ack: - if self.model.can_ack(bus) and bus.cyc and bus.stb: - if bus.we: - self.model.write(bus.adr, bus.dat_w, bus.sel) - else: - bus.dat_r = self.model.read(bus.adr) - bus.ack = 1 - else: - bus.ack = 0 - do_simulation.passive = True - - -class SRAM(Module): - def __init__(self, mem_or_size, read_only=None, init=None, bus=None): - if bus is None: - bus = Interface() - self.bus = bus - bus_data_width = flen(self.bus.dat_r) - if isinstance(mem_or_size, Memory): - assert(mem_or_size.width <= bus_data_width) - self.mem = mem_or_size - else: - self.mem = Memory(bus_data_width, mem_or_size//(bus_data_width//8), init=init) - if read_only is None: - if hasattr(self.mem, "bus_read_only"): - read_only = self.mem.bus_read_only - else: - read_only = False - - ### - - # memory - port = self.mem.get_port(write_capable=not read_only, we_granularity=8) - self.specials += self.mem, port - # generate write enable signal - if not read_only: - self.comb += [port.we[i].eq(self.bus.cyc & self.bus.stb & self.bus.we & self.bus.sel[i]) - for i in range(4)] - # address and data - self.comb += [ - port.adr.eq(self.bus.adr[:flen(port.adr)]), - self.bus.dat_r.eq(port.dat_r) - ] - if not read_only: - self.comb += port.dat_w.eq(self.bus.dat_w), - # generate ack - self.sync += [ - self.bus.ack.eq(0), - If(self.bus.cyc & self.bus.stb & ~self.bus.ack, self.bus.ack.eq(1)) - ] diff --git a/migen/bus/wishbone2csr.py b/migen/bus/wishbone2csr.py deleted file mode 100644 index 2d43c77e..00000000 --- a/migen/bus/wishbone2csr.py +++ /dev/null @@ -1,28 +0,0 @@ -from migen.fhdl.std import * -from migen.bus import wishbone -from migen.bus import csr -from migen.genlib.misc import timeline - - -class WB2CSR(Module): - def __init__(self, bus_wishbone=None, bus_csr=None): - if bus_wishbone is None: - bus_wishbone = wishbone.Interface() - self.wishbone = bus_wishbone - if bus_csr is None: - bus_csr = csr.Interface() - self.csr = bus_csr - - ### - - self.sync += [ - self.csr.we.eq(0), - self.csr.dat_w.eq(self.wishbone.dat_w), - self.csr.adr.eq(self.wishbone.adr), - self.wishbone.dat_r.eq(self.csr.dat_r) - ] - self.sync += timeline(self.wishbone.cyc & self.wishbone.stb, [ - (1, [self.csr.we.eq(self.wishbone.we)]), - (2, [self.wishbone.ack.eq(1)]), - (3, [self.wishbone.ack.eq(0)]) - ]) diff --git a/migen/flow/__init__.py b/migen/flow/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/migen/flow/actor.py b/migen/flow/actor.py deleted file mode 100644 index a2012a98..00000000 --- a/migen/flow/actor.py +++ /dev/null @@ -1,184 +0,0 @@ -from migen.util.misc import xdir -from migen.fhdl.std import * -from migen.genlib.misc import optree -from migen.genlib.record import * - - -def _make_m2s(layout): - r = [] - for f in layout: - if isinstance(f[1], (int, tuple)): - r.append((f[0], f[1], DIR_M_TO_S)) - else: - r.append((f[0], _make_m2s(f[1]))) - return r - - -class EndpointDescription: - def __init__(self, payload_layout, param_layout=[], packetized=False): - self.payload_layout = payload_layout - self.param_layout = param_layout - self.packetized = packetized - - def get_full_layout(self): - reserved = {"stb", "ack", "payload", "param", "sop", "eop", "description"} - attributed = set() - for f in self.payload_layout + self.param_layout: - if f[0] in attributed: - raise ValueError(f[0] + " already attributed in payload or param layout") - if f[0] in reserved: - raise ValueError(f[0] + " cannot be used in endpoint layout") - attributed.add(f[0]) - - full_layout = [ - ("payload", _make_m2s(self.payload_layout)), - ("param", _make_m2s(self.param_layout)), - ("stb", 1, DIR_M_TO_S), - ("ack", 1, DIR_S_TO_M) - ] - if self.packetized: - full_layout += [ - ("sop", 1, DIR_M_TO_S), - ("eop", 1, DIR_M_TO_S) - ] - return full_layout - - -class _Endpoint(Record): - def __init__(self, description_or_layout): - if isinstance(description_or_layout, EndpointDescription): - self.description = description_or_layout - else: - self.description = EndpointDescription(description_or_layout) - Record.__init__(self, self.description.get_full_layout()) - - def __getattr__(self, name): - try: - return getattr(object.__getattribute__(self, "payload"), name) - except: - return getattr(object.__getattribute__(self, "param"), name) - - -class Source(_Endpoint): - def connect(self, sink): - return Record.connect(self, sink) - - -class Sink(_Endpoint): - def connect(self, source): - return source.connect(self) - - -def get_endpoints(obj, filt=_Endpoint): - if hasattr(obj, "get_endpoints") and callable(obj.get_endpoints): - return obj.get_endpoints(filt) - r = dict() - for k, v in xdir(obj, True): - if isinstance(v, filt): - r[k] = v - return r - - -def get_single_ep(obj, filt): - eps = get_endpoints(obj, filt) - if len(eps) != 1: - raise ValueError("More than one endpoint") - return list(eps.items())[0] - - -class BinaryActor(Module): - def __init__(self, *args, **kwargs): - self.busy = Signal() - sink = get_single_ep(self, Sink)[1] - source = get_single_ep(self, Source)[1] - self.build_binary_control(sink, source, *args, **kwargs) - - def build_binary_control(self, sink, source): - raise NotImplementedError("Binary actor classes must overload build_binary_control_fragment") - - -class CombinatorialActor(BinaryActor): - def build_binary_control(self, sink, source): - self.comb += [ - source.stb.eq(sink.stb), - sink.ack.eq(source.ack), - self.busy.eq(0) - ] - if sink.description.packetized: - self.comb += [ - source.sop.eq(sink.sop), - source.eop.eq(sink.eop) - ] - - -class SequentialActor(BinaryActor): - def __init__(self, delay): - self.trigger = Signal() - BinaryActor.__init__(self, delay) - - def build_binary_control(self, sink, source, delay): - ready = Signal() - timer = Signal(max=delay+1) - self.comb += ready.eq(timer == 0) - self.sync += If(self.trigger, - timer.eq(delay) - ).Elif(~ready, - timer.eq(timer - 1) - ) - - mask = Signal() - self.comb += [ - source.stb.eq(ready & mask), - self.trigger.eq(sink.stb & (source.ack | ~mask) & ready), - sink.ack.eq(self.trigger), - self.busy.eq(~ready) - ] - self.sync += [ - If(self.trigger, mask.eq(1)), - If(source.stb & source.ack, mask.eq(0)) - ] - if sink.packetized: - self.comb += [ - source.sop.eq(sink.sop), - source.eop.eq(sink.eop) - ] - - -class PipelinedActor(BinaryActor): - def __init__(self, latency): - self.pipe_ce = Signal() - BinaryActor.__init__(self, latency) - - def build_binary_control(self, sink, source, latency): - busy = 0 - valid = sink.stb - for i in range(latency): - valid_n = Signal() - self.sync += If(self.pipe_ce, valid_n.eq(valid)) - valid = valid_n - busy = busy | valid - - self.comb += [ - self.pipe_ce.eq(source.ack | ~valid), - sink.ack.eq(self.pipe_ce), - source.stb.eq(valid), - self.busy.eq(busy) - ] - if sink.description.packetized: - sop = sink.stb & sink.sop - eop = sink.stb & sink.eop - for i in range(latency): - sop_n = Signal() - eop_n = Signal() - self.sync += \ - If(self.pipe_ce, - sop_n.eq(sop), - eop_n.eq(eop) - ) - sop = sop_n - eop = eop_n - - self.comb += [ - source.eop.eq(eop), - source.sop.eq(sop) - ] diff --git a/migen/flow/hooks.py b/migen/flow/hooks.py deleted file mode 100644 index d8e97b4f..00000000 --- a/migen/flow/hooks.py +++ /dev/null @@ -1,44 +0,0 @@ -from collections import defaultdict - -from migen.fhdl.std import * -from migen.flow.actor import * - - -class EndpointSimHook(Module): - def __init__(self, endpoint): - self.endpoint = endpoint - - def on_ack(self): - pass - - def on_nack(self): - pass - - def on_inactive(self): - pass - - def do_simulation(self, selfp): - if selfp.endpoint.stb: - if selfp.endpoint.ack: - self.on_ack() - else: - self.on_nack() - else: - self.on_inactive() - - -class DFGHook(Module): - def __init__(self, dfg, create): - assert(not dfg.is_abstract()) - self.nodepair_to_ep = defaultdict(dict) - for hookn, (u, v, data) in enumerate(dfg.edges_iter(data=True)): - ep_to_hook = self.nodepair_to_ep[(u, v)] - ep = data["source"] - h = create(u, ep, v) - ep_to_hook[ep] = h - setattr(self.submodules, "hook"+str(hookn), h) - - def hooks_iter(self): - for v1 in self.nodepair_to_ep.values(): - for v2 in v1.values(): - yield v2 diff --git a/migen/flow/isd.py b/migen/flow/isd.py deleted file mode 100644 index 44be71b3..00000000 --- a/migen/flow/isd.py +++ /dev/null @@ -1,71 +0,0 @@ -from migen.fhdl.std import * -from migen.bank.description import * -from migen.flow.hooks import DFGHook - -ISD_MAGIC = 0x6ab4 - - -class EndpointReporter(Module, AutoCSR): - def __init__(self, endpoint, nbits): - self.reset = Signal() - self.freeze = Signal() - - self._ack_count = CSRStatus(nbits) - self._nack_count = CSRStatus(nbits) - self._cur_status = CSRStatus(2) - - ### - - stb = Signal() - ack = Signal() - self.comb += self._cur_status.status.eq(Cat(stb, ack)) - ack_count = Signal(nbits) - nack_count = Signal(nbits) - self.sync += [ - # register monitored signals - stb.eq(endpoint.stb), - ack.eq(endpoint.ack), - # count operations - If(self.reset, - ack_count.eq(0), - nack_count.eq(0) - ).Else( - If(stb, - If(ack, - ack_count.eq(ack_count + 1) - ).Else( - nack_count.eq(nack_count + 1) - ) - ) - ), - If(~self.freeze, - self._ack_count.status.eq(ack_count), - self._nack_count.status.eq(nack_count) - ) - ] - - -class DFGReporter(DFGHook, AutoCSR): - def __init__(self, dfg, nbits): - self._magic = CSRStatus(16) - self._neps = CSRStatus(8) - self._nbits = CSRStatus(8) - self._freeze = CSRStorage() - self._reset = CSR() - - ### - - DFGHook.__init__(self, dfg, - lambda u, ep, v: EndpointReporter(getattr(u, ep), nbits)) - hooks = list(self.hooks_iter()) - - self.comb += [ - self._magic.status.eq(ISD_MAGIC), - self._neps.status.eq(len(hooks)), - self._nbits.status.eq(nbits) - ] - for h in hooks: - self.comb += [ - h.freeze.eq(self._freeze.storage), - h.reset.eq(self._reset.re) - ] diff --git a/migen/flow/network.py b/migen/flow/network.py deleted file mode 100644 index 0c29ad70..00000000 --- a/migen/flow/network.py +++ /dev/null @@ -1,330 +0,0 @@ -from collections import defaultdict - -from migen.fhdl.std import * -from migen.genlib.misc import optree -from migen.flow.actor import * -from migen.flow import plumbing - -# Abstract actors mean that the actor class should be instantiated with the parameters -# from the dictionary. They are needed to enable actor duplication or sharing during -# elaboration, and automatic parametrization of plumbing actors. - - -class AbstractActor: - def __init__(self, actor_class, parameters=dict(), name=None): - self.actor_class = actor_class - self.parameters = parameters - self.name = name - self.busy = Signal() - - def create_instance(self): - return self.actor_class(**self.parameters) - - def __repr__(self): - r = " [sink1, ..., sinkn] - # source element is a (node, endpoint) pair. - # sink elements are (node, endpoint, source subrecord, sink subrecord) triples. - def _source_to_sinks(self): - d = dict() - for u, v, data in self.edges_iter(data=True): - el_src = (u, data["source"]) - el_dst = (v, data["sink"], data["source_subr"], data["sink_subr"]) - if el_src in d: - d[el_src].append(el_dst) - else: - d[el_src] = [el_dst] - return d - - # Returns a dictionary - # sink -> [source1, ... sourcen] - # sink element is a (node, endpoint) pair. - # source elements are (node, endpoint, sink subrecord, source subrecord) triples. - def _sink_to_sources(self): - d = dict() - for u, v, data in self.edges_iter(data=True): - el_src = (u, data["source"], data["sink_subr"], data["source_subr"]) - el_dst = (v, data["sink"]) - if el_dst in d: - d[el_dst].append(el_src) - else: - d[el_dst] = [el_src] - return d - - # List sources that feed more than one sink. - def _list_divergences(self): - d = self._source_to_sinks() - return dict((k, v) for k, v in d.items() if len(v) > 1) - - # A graph is abstract if any of these conditions is met: - # (1) A node is an abstract actor. - # (2) A subrecord is used. - # (3) A single source feeds more than one sink. - # NB: It is not allowed for a single sink to be fed by more than one source - # (except with subrecords, i.e. when a combinator is used) - def is_abstract(self): - return any(isinstance(x, AbstractActor) for x in self) \ - or any(d["source_subr"] is not None or d["sink_subr"] is not None - for u, v, d in self.edges_iter(data=True)) \ - or bool(self._list_divergences()) - - def _eliminate_subrecords_and_divergences(self): - # Insert combinators. - for (dst_node, dst_endpoint), sources in self._sink_to_sources().items(): - if len(sources) > 1 or sources[0][2] is not None: - # build combinator - # "layout" is filled in during instantiation - subrecords = [dst_subrecord for src_node, src_endpoint, dst_subrecord, src_subrecord in sources] - combinator = AbstractActor(plumbing.Combinator, {"subrecords": subrecords}) - # disconnect source1 -> sink ... sourcen -> sink - # connect source1 -> combinator_sink1 ... sourcen -> combinator_sinkn - for n, (src_node, src_endpoint, dst_subrecord, src_subrecord) in enumerate(sources): - self.del_connections(src_node, dst_node, - {"source": src_endpoint, "sink": dst_endpoint}) - self.add_connection(src_node, combinator, - src_endpoint, "sink{0}".format(n), source_subr=src_subrecord) - # connect combinator_source -> sink - self.add_connection(combinator, dst_node, "source", dst_endpoint) - # Insert splitters. - for (src_node, src_endpoint), sinks in self._source_to_sinks().items(): - if len(sinks) > 1 or sinks[0][2] is not None: - subrecords = [src_subrecord for dst_node, dst_endpoint, src_subrecord, dst_subrecord in sinks] - splitter = AbstractActor(plumbing.Splitter, {"subrecords": subrecords}) - # disconnect source -> sink1 ... source -> sinkn - # connect splitter_source1 -> sink1 ... splitter_sourcen -> sinkn - for n, (dst_node, dst_endpoint, src_subrecord, dst_subrecord) in enumerate(sinks): - self.del_connections(src_node, dst_node, - {"source": src_endpoint, "sink": dst_endpoint}) - self.add_connection(splitter, dst_node, - "source{0}".format(n), dst_endpoint) - # connect source -> splitter_sink - self.add_connection(src_node, splitter, src_endpoint, "sink") - - def _infer_plumbing_layout(self): - while True: - ap = [a for a in self if isinstance(a, AbstractActor) and a.actor_class in plumbing.actors] - if not ap: - break - for a in ap: - in_edges = self.in_edges(a, data=True) - out_edges = self.out_edges(a, data=True) - if a.actor_class in plumbing.layout_sink and len(in_edges) == 1: - other, me, data = in_edges[0] - if isinstance(other, AbstractActor): - continue - other_ep = data["source"] - if other_ep is None: - other_ep = get_single_ep(other, Source)[1] - else: - other_ep = getattr(other, other_ep) - elif a.actor_class in plumbing.layout_source and len(out_edges) == 1: - me, other, data = out_edges[0] - if isinstance(other, AbstractActor): - continue - other_ep = data["sink"] - if other_ep is None: - other_ep = get_single_ep(other, Sink)[1] - else: - other_ep = getattr(other, other_ep) - else: - raise AssertionError - layout = other_ep.payload.layout - a.parameters["layout"] = layout - self.instantiate(a) - - def _instantiate_actors(self): - # 1. instantiate all abstract non-plumbing actors - for actor in list(self): - if isinstance(actor, AbstractActor) and actor.actor_class not in plumbing.actors: - self.instantiate(actor) - # 2. infer plumbing layout and instantiate plumbing - self._infer_plumbing_layout() - # 3. resolve default eps - for u, v, d in self.edges_iter(data=True): - if d["source"] is None: - d["source"] = get_single_ep(u, Source)[0] - if d["sink"] is None: - d["sink"] = get_single_ep(v, Sink)[0] - - # Elaboration turns an abstract DFG into a physical one. - # Pass 1: eliminate subrecords and divergences - # by inserting Combinator/Splitter actors - # Pass 2: run optimizer (e.g. share and duplicate actors) - # Pass 3: instantiate all abstract actors and explicit "None" endpoints - def elaborate(self, optimizer=None): - if self.elaborated: - return - self.elaborated = True - - self._eliminate_subrecords_and_divergences() - if optimizer is not None: - optimizer(self) - self._instantiate_actors() - - -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) - - # connect abstract busy signals - for node in dfg: - try: - abstract_busy_signal = dfg.abstract_busy_signals[id(node)] - except KeyError: - pass - else: - self.comb += abstract_busy_signal.eq(node.busy) - - # generate busy signal - self.busy = Signal() - 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): - ep_src = getattr(u, d["source"]) - ep_dst = getattr(v, d["sink"]) - self.comb += ep_src.connect_flat(ep_dst) diff --git a/migen/flow/perftools.py b/migen/flow/perftools.py deleted file mode 100644 index 0072b66d..00000000 --- a/migen/flow/perftools.py +++ /dev/null @@ -1,54 +0,0 @@ -from migen.flow.hooks import * - - -class EndpointReporter(EndpointSimHook): - def __init__(self, endpoint): - EndpointSimHook.__init__(self, endpoint) - self.reset() - - def reset(self): - self.inactive = 0 - self.ack = 0 - self.nack = 0 - - # Total number of cycles per token (inverse token rate) - def cpt(self): - return (self.inactive + self.nack + self.ack)/self.ack - - # Inactivity cycles per token (slack) - def ipt(self): - return self.inactive/self.ack - - # NAK cycles per token (backpressure) - def npt(self): - return self.nack/self.ack - - def report_str(self): - if self.ack: - return "C/T={:.2f}\nI/T={:.2f}\nN/T={:.2f}".format(self.cpt(), self.ipt(), self.npt()) - else: - return "N/A" - - def on_ack(self): - self.ack += 1 - - def on_nack(self): - self.nack += 1 - - def on_inactive(self): - self.inactive += 1 - - -class DFGReporter(DFGHook): - def __init__(self, dfg): - DFGHook.__init__(self, dfg, lambda u, ep, v: EndpointReporter(getattr(u, ep))) - - def get_edge_labels(self): - d = dict() - for (u, v), eps in self.nodepair_to_ep.items(): - if len(eps) == 1: - d[(u, v)] = list(eps.values())[0].report_str() - else: - d[(u, v)] = "\n".join(ep + ":\n" + reporter.report_str() - for ep, reporter in eps) - return d diff --git a/migen/flow/plumbing.py b/migen/flow/plumbing.py deleted file mode 100644 index 85d0ceaf..00000000 --- a/migen/flow/plumbing.py +++ /dev/null @@ -1,107 +0,0 @@ -from migen.fhdl.std import * -from migen.flow.actor import * -from migen.genlib.record import * -from migen.genlib.misc import optree - - -class Buffer(PipelinedActor): - def __init__(self, layout): - self.d = Sink(layout) - self.q = Source(layout) - PipelinedActor.__init__(self, 1) - self.sync += \ - If(self.pipe_ce, - self.q.payload.eq(self.d.payload), - self.q.param.eq(self.d.param) - ) - - -class Combinator(Module): - def __init__(self, layout, subrecords): - self.source = Source(layout) - sinks = [] - for n, r in enumerate(subrecords): - s = Sink(layout_partial(layout, *r)) - setattr(self, "sink"+str(n), s) - sinks.append(s) - self.busy = Signal() - - ### - - self.comb += [ - self.busy.eq(0), - self.source.stb.eq(optree("&", [sink.stb for sink in sinks])) - ] - self.comb += [sink.ack.eq(self.source.ack & self.source.stb) for sink in sinks] - self.comb += [self.source.payload.eq(sink.payload) for sink in sinks] - self.comb += [self.source.param.eq(sink.param) for sink in sinks] - - -class Splitter(Module): - def __init__(self, layout, subrecords): - self.sink = Sink(layout) - sources = [] - for n, r in enumerate(subrecords): - s = Source(layout_partial(layout, *r)) - setattr(self, "source"+str(n), s) - sources.append(s) - self.busy = Signal() - - ### - - self.comb += [source.payload.eq(self.sink.payload) for source in sources] - self.comb += [source.param.eq(self.sink.param) for source in sources] - already_acked = Signal(len(sources)) - self.sync += If(self.sink.stb, - already_acked.eq(already_acked | Cat(*[s.ack for s in sources])), - If(self.sink.ack, already_acked.eq(0)) - ) - self.comb += self.sink.ack.eq(optree("&", - [s.ack | already_acked[n] for n, s in enumerate(sources)])) - for n, s in enumerate(sources): - self.comb += s.stb.eq(self.sink.stb & ~already_acked[n]) - - -class Multiplexer(Module): - def __init__(self, layout, n): - self.source = Source(layout) - sinks = [] - for i in range(n): - sink = Sink(layout) - setattr(self, "sink"+str(i), sink) - sinks.append(sink) - self.busy = Signal() - self.sel = Signal(max=n) - - ### - - cases = {} - for i, sink in enumerate(sinks): - cases[i] = Record.connect(sink, self.source) - self.comb += Case(self.sel, cases) - - -class Demultiplexer(Module): - def __init__(self, layout, n): - self.sink = Sink(layout) - sources = [] - for i in range(n): - source = Source(layout) - setattr(self, "source"+str(i), source) - sources.append(source) - self.busy = Signal() - self.sel = Signal(max=n) - - ### - - cases = {} - for i, source in enumerate(sources): - cases[i] = Record.connect(self.sink, source) - self.comb += Case(self.sel, cases) - -# Actors whose layout should be inferred from what their single sink is connected to. -layout_sink = {Buffer, Splitter} -# Actors whose layout should be inferred from what their single source is connected to. -layout_source = {Buffer, Combinator} -# All actors. -actors = layout_sink | layout_source diff --git a/migen/flow/transactions.py b/migen/flow/transactions.py deleted file mode 100644 index 342cad87..00000000 --- a/migen/flow/transactions.py +++ /dev/null @@ -1,5 +0,0 @@ -class Token: - def __init__(self, endpoint, value=None, idle_wait=False): - self.endpoint = endpoint - self.value = value - self.idle_wait = idle_wait diff --git a/migen/genlib/complex.py b/migen/genlib/complex.py deleted file mode 100644 index 79dff544..00000000 --- a/migen/genlib/complex.py +++ /dev/null @@ -1,54 +0,0 @@ -from migen.fhdl.std import * - - -class Complex: - def __init__(self, real, imag): - self.real = real - self.imag = imag - - def __neg__(self): - return Complex(-self.real, -self.imag) - - def __add__(self, other): - if isinstance(other, Complex): - return Complex(self.real + other.real, self.imag + other.imag) - else: - return Complex(self.real + other, self.imag) - __radd__ = __add__ - def __sub__(self, other): - if isinstance(other, Complex): - return Complex(self.real - other.real, self.imag - other.imag) - else: - return Complex(self.real - other, self.imag) - def __rsub__(self, other): - if isinstance(other, Complex): - return Complex(other.real - self.real, other.imag - self.imag) - else: - return Complex(other - self.real, -self.imag) - def __mul__(self, other): - if isinstance(other, Complex): - return Complex(self.real*other.real - self.imag*other.imag, - self.real*other.imag + self.imag*other.real) - else: - return Complex(self.real*other, self.imag*other) - __rmul__ = __mul__ - - def __lshift__(self, other): - return Complex(self.real << other, self.imag << other) - def __rshift__(self, other): - return Complex(self.real >> other, self.imag >> other) - - def __repr__(self): - return repr(self.real) + " + " + repr(self.imag) + "j" - - def eq(self, r): - if isinstance(r, Complex): - return self.real.eq(r.real), self.imag.eq(r.imag) - else: - return self.real.eq(r), self.imag.eq(0) - - -def SignalC(*args, **kwargs): - real = Signal(*args, **kwargs) - imag = Signal(*args, **kwargs) - return Complex(real, imag) diff --git a/migen/genlib/mhamgen.py b/migen/genlib/mhamgen.py deleted file mode 100644 index 958851b9..00000000 --- a/migen/genlib/mhamgen.py +++ /dev/null @@ -1,232 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (c) 2014 Guy Hutchison - -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: - -# 1. Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. - -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import migen -import operator -from migen.fhdl.std import * -from migen.fhdl.verilog import convert - - -# Join two lists a and b, such that redundant terms are removed -def join_lists(a, b): - z = [] - for x in a+b: - if x not in z: - z.append(x) - else: - z.remove(x) - return z - - -def join_operator(list, op): - if len(list) == 0: - return [] - elif len(list) == 1: - return list[0] - elif len(list) == 2: - return op(list[0], list[1]) - else: - return op(list[0], join_operator(list[1:], op)) - - -def calc_code_bits(data_bits): - m = 1 - c = 0 - - while c < data_bits: - m += 1 - c = 2**m - m - 1 - return m - - -# build_seq() is used to create the selection of bits which need -# to be checked for a particular data parity bit. -def build_seq(bnum, out_width): - tmp = [] - - ptr = 0 - cur = 0 - skip = 2**bnum-1 - if skip == 0: - check = 2**bnum - else: - check = 0 - while cur < out_width: - if check > 0: - if (cur != 2**bnum-1): - tmp.append(cur) - ptr += 1 - check -= 1 - if check == 0: - skip = 2**bnum - else: - skip -= 1 - if skip == 0: - check = 2**bnum - cur += 1 - - return tmp - - -# build_bits() is used for the generator portion, it combines the -# bit sequences for all input and parity bits which are used and -# removes redundant terms. -def build_bits(in_width, gen_parity=True): - pnum = 1 - innum = 0 - blist = [] - num_code_bits = calc_code_bits(in_width) - out_width = in_width + num_code_bits - v = [list()] * out_width - code_bit_list = [] - - for b in range(out_width): - if (b+1) == pnum: - pnum = 2*pnum - else: - v[b] = [innum] - innum += 1 - - for b in range(num_code_bits): - vindex = 2**b-1 - blist = build_seq(b, out_width) - for bli in blist: - v[vindex] = join_lists(v[vindex], v[bli]) - code_bit_list.append(v[vindex]) - - # Calculate parity bit - if gen_parity: - pbit = [] - for b in v: - pbit = join_lists(pbit, b) - code_bit_list.append(pbit) - return code_bit_list - - -# xor_tree() takes a signal and a list of bits to be applied from -# the signal and generates a balanced xor tree as output. -def xor_tree(in_signal, in_bits): - if len(in_bits) == 0: - print ("ERROR: in_bits must be > 0") - elif len(in_bits) == 1: - return in_signal[in_bits[0]] - elif len(in_bits) == 2: - return in_signal[in_bits[0]] ^ in_signal[in_bits[1]] - elif len(in_bits) == 3: - return in_signal[in_bits[0]] ^ in_signal[in_bits[1]] ^ in_signal[in_bits[2]] - else: - split = int(len(in_bits)/2) - return xor_tree(in_signal, in_bits[0:split]) ^ xor_tree(in_signal, in_bits[split:]) - - -# Base class for Hamming code generator/checker. - - -# Hamming code generator class - -# The class constructor takes a single required input, which is the number of -# bits of the input data. The module creates a single output, which is a set -# of code check bits and a parity bit. - -# This generator and its corresponding checker will only generate a single- -# error correct, double-error detect code. If double-error detection is -# not desired, the most-significant code_out bit can be left unconnected. - -# If generated as a top-level module, contains its suggested module name -# in self.name and list of ports in self.ports -class HammingGenerator(Module): - def __init__(self, input_size): - self.input_size = input_size - self.data_in = Signal(input_size) - self.code_out = Signal(calc_code_bits(input_size)+1) - - xor_bits = build_bits(self.input_size) - for b in range(len(xor_bits)): - self.comb += self.code_out[b].eq(xor_tree(self.data_in, xor_bits[b])) - - -# Hamming code checker class - -# Constructor takes two parameters: -# input_size (bits of data bus, not counting check bits) -# correct (boolean, True if output data should be corrected) - -# If used as a check/correct module, the module creates an -# enable input which can dynamically turn off error correction -# for debug. - -# If double-bit detection is not desired, the most-significant -# code_in bit can be tied to 0, and the dberr output port left -# unconnected. - -# If generated as a top-level module, contains its suggested module name -# in self.name and list of ports in self.ports -class HammingChecker(Module): - def __init__(self, input_size, correct=True, gen_parity=True): - self.input_size = input_size - self.correct = correct - self.data_in = Signal(input_size) - self.code_bits = calc_code_bits(input_size) - self.code_in = Signal(self.code_bits+1) - self.code_out = Signal(self.code_bits) - self.sberr = Signal() - if gen_parity: - self.dberr = Signal() - - # vector of which interleaved bit position represents a particular - # data bit, used for error correction - dbits = [] - - # Create interleaved vector of code bits and data bits with code bits - # in power-of-two positions - pnum = 0 - dnum = 0 - self.par_vec = Signal(input_size+self.code_bits) - for b in range(input_size+calc_code_bits(input_size)): - if b+1 == 2**pnum: - self.comb += self.par_vec[b].eq(self.code_in[pnum]) - pnum += 1 - else: - self.comb += self.par_vec[b].eq(self.data_in[dnum]) - dbits.append(b) - dnum += 1 - - if correct: - self.enable = Signal() - self.correct_out = Signal(input_size) - self.data_out = Signal(input_size, name='data_out') - for b in range(input_size): - self.comb += self.correct_out[b].eq((self.code_out == (dbits[b]+1)) ^ self.data_in[b]) - self.comb += If(self.enable, self.data_out.eq(self.correct_out)).Else(self.data_out.eq(self.data_in)) - - self.comb += self.sberr.eq(self.code_out != 0) - if gen_parity: - parity = Signal() - self.comb += parity.eq(xor_tree(self.data_in, range(input_size)) ^ xor_tree(self.code_in, range(self.code_bits+1))) - self.comb += self.dberr.eq(~parity) - - for b in range(calc_code_bits(self.input_size)): - bits = [2**b-1] - bits += build_seq(b, self.input_size+calc_code_bits(self.input_size)) - self.comb += self.code_out[b].eq(xor_tree(self.par_vec, bits)) diff --git a/migen/genlib/rob.py b/migen/genlib/rob.py deleted file mode 100644 index 1c94c463..00000000 --- a/migen/genlib/rob.py +++ /dev/null @@ -1,78 +0,0 @@ -from migen.fhdl.std import * - - -class ReorderSlot: - def __init__(self, tag_width, data_width): - self.wait_data = Signal() - self.has_data = Signal() - self.tag = Signal(tag_width) - self.data = Signal(data_width) - - -class ReorderBuffer(Module): - def __init__(self, tag_width, data_width, depth): - # issue - self.can_issue = Signal() - self.issue = Signal() - self.tag_issue = Signal(tag_width) - - # call - self.call = Signal() - self.tag_call = Signal(tag_width) - self.data_call = Signal(data_width) - - # readback - self.can_read = Signal() - self.read = Signal() - self.data_read = Signal(data_width) - - ### - - empty_count = Signal(max=depth+1, reset=depth) - produce = Signal(max=depth) - consume = Signal(max=depth) - slots = Array(ReorderSlot(tag_width, data_width) - for n in range(depth)) - - # issue - self.comb += self.can_issue.eq(empty_count != 0) - self.sync += If(self.issue & self.can_issue, - empty_count.eq(empty_count - 1), - If(produce == depth - 1, - produce.eq(0) - ).Else( - produce.eq(produce + 1) - ), - slots[produce].wait_data.eq(1), - slots[produce].tag.eq(self.tag_issue) - ) - - # call - for n, slot in enumerate(slots): - self.sync += If(self.call & slot.wait_data & (self.tag_call == slot.tag), - slot.wait_data.eq(0), - slot.has_data.eq(1), - slot.data.eq(self.data_call) - ) - - # readback - self.comb += [ - self.can_read.eq(slots[consume].has_data), - self.data_read.eq(slots[consume].data) - ] - self.sync += [ - If(self.read & self.can_read, - empty_count.eq(empty_count + 1), - If(consume == depth - 1, - consume.eq(0) - ).Else( - consume.eq(consume + 1) - ), - slots[consume].has_data.eq(0) - ) - ] - - # do not touch empty count when issuing and reading at the same time - self.sync += If(self.issue & self.can_issue & self.read & self.can_read, - empty_count.eq(empty_count) - ) diff --git a/migen/test/test_actor.py b/migen/test/test_actor.py deleted file mode 100644 index 1963d590..00000000 --- a/migen/test/test_actor.py +++ /dev/null @@ -1,71 +0,0 @@ -import unittest - -from migen.fhdl.std import * -from migen.flow.actor import * -from migen.flow.transactions import * -from migen.flow.network import * -from migen.actorlib.sim import * - -from migen.test.support import SimCase, SimBench - - -def source_gen(sent): - for i in range(10): - yield Token("source", {"value": i}) - sent.append(i) - - -class SimSource(SimActor): - def __init__(self): - self.source = Source([("value", 32)]) - self.sent = [] - SimActor.__init__(self, source_gen(self.sent)) - - -def sink_gen(received): - while True: - t = Token("sink") - yield t - received.append(t.value["value"]) - - -class SimSink(SimActor): - def __init__(self): - self.sink = Sink([("value", 32)]) - self.received = [] - SimActor.__init__(self, sink_gen(self.received)) - - -class SourceSinkCase(SimCase, unittest.TestCase): - class TestBench(SimBench): - def __init__(self): - self.source = SimSource() - self.sink = SimSink() - g = DataFlowGraph() - g.add_connection(self.source, self.sink) - self.submodules.comp = CompositeActor(g) - - def do_simulation(self, selfp): - if self.source.token_exchanger.done: - raise StopSimulation - - def test_equal(self): - self.run_with(lambda tb, tbp: None) - self.assertEqual(self.tb.source.sent, self.tb.sink.received) - - -class SourceSinkDirectCase(SimCase, unittest.TestCase): - class TestBench(SimBench): - def __init__(self): - self.source = SimSource() - self.sink = SimSink() - self.submodules += self.source, self.sink - self.comb += self.sink.sink.connect(self.source.source) - - def do_simulation(self, selfp): - if self.source.token_exchanger.done: - raise StopSimulation - - def test_equal(self): - self.run_with(lambda tb, tbp: None) - self.assertEqual(self.tb.source.sent, self.tb.sink.received) -- 2.30.2