From: Florent Kermarrec Date: Mon, 13 Apr 2015 18:07:07 +0000 (+0200) Subject: global: pep8 (replace tabs with spaces) X-Git-Tag: 24jan2021_ls180~2099^2~114 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=17e5249be03ccc08ca3cbc3b935480d695cc391b;p=litex.git global: pep8 (replace tabs with spaces) --- diff --git a/doc/conf.py b/doc/conf.py index 773d7cf4..9bac6059 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -26,12 +26,12 @@ import sys, os # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ - 'sphinx.ext.pngmath', - 'sphinx.ext.autodoc', - 'sphinx.ext.doctest', - 'sphinx.ext.autosummary', - 'numpydoc', # to preprocess docstrings - ] + 'sphinx.ext.pngmath', + 'sphinx.ext.autodoc', + 'sphinx.ext.doctest', + 'sphinx.ext.autosummary', + 'numpydoc', # to preprocess docstrings + ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/examples/basic/arrays.py b/examples/basic/arrays.py index 8b10eaf9..7049b520 100644 --- a/examples/basic/arrays.py +++ b/examples/basic/arrays.py @@ -2,25 +2,25 @@ from migen.fhdl.std import * from migen.fhdl import verilog class Example(Module): - def __init__(self): - dx = 2 - dy = 2 + def __init__(self): + dx = 2 + dy = 2 - x = Signal(max=dx) - y = Signal(max=dy) - out = Signal() + x = Signal(max=dx) + y = Signal(max=dy) + out = Signal() - my_2d_array = Array(Array(Signal() for a in range(dx)) for b in range(dy)) - self.comb += out.eq(my_2d_array[x][y]) + my_2d_array = Array(Array(Signal() for a in range(dx)) for b in range(dy)) + self.comb += out.eq(my_2d_array[x][y]) - we = Signal() - inp = Signal() - self.sync += If(we, - my_2d_array[x][y].eq(inp) - ) + we = Signal() + inp = Signal() + self.sync += If(we, + my_2d_array[x][y].eq(inp) + ) - ina = Array(Signal() for a in range(dx)) - outa = Array(Signal() for a in range(dy)) - self.specials += Instance("test", o_O=outa[y], i_I=ina[x]) + ina = Array(Signal() for a in range(dx)) + outa = Array(Signal() for a in range(dy)) + self.specials += Instance("test", o_O=outa[y], i_I=ina[x]) print(verilog.convert(Example())) diff --git a/examples/basic/complex.py b/examples/basic/complex.py index 0837365d..60479ab6 100644 --- a/examples/basic/complex.py +++ b/examples/basic/complex.py @@ -3,17 +3,17 @@ 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) - ] + 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/fsm.py b/examples/basic/fsm.py index 76924675..bb85b03a 100644 --- a/examples/basic/fsm.py +++ b/examples/basic/fsm.py @@ -3,27 +3,27 @@ from migen.fhdl import verilog from migen.genlib.fsm import FSM, NextState, NextValue class Example(Module): - def __init__(self): - self.s = Signal() - self.counter = Signal(8) + def __init__(self): + self.s = Signal() + self.counter = Signal(8) - myfsm = FSM() - self.submodules += myfsm + myfsm = FSM() + self.submodules += myfsm - myfsm.act("FOO", - self.s.eq(1), - NextState("BAR") - ) - myfsm.act("BAR", - self.s.eq(0), - NextValue(self.counter, self.counter + 1), - NextState("FOO") - ) + myfsm.act("FOO", + self.s.eq(1), + NextState("BAR") + ) + myfsm.act("BAR", + self.s.eq(0), + NextValue(self.counter, self.counter + 1), + NextState("FOO") + ) - self.be = myfsm.before_entering("FOO") - self.ae = myfsm.after_entering("FOO") - self.bl = myfsm.before_leaving("FOO") - self.al = myfsm.after_leaving("FOO") + self.be = myfsm.before_entering("FOO") + self.ae = myfsm.after_entering("FOO") + self.bl = myfsm.before_leaving("FOO") + self.al = myfsm.after_leaving("FOO") example = Example() print(verilog.convert(example, {example.s, example.counter, example.be, example.ae, example.bl, example.al})) diff --git a/examples/basic/graycounter.py b/examples/basic/graycounter.py index be1b1838..8d330a51 100644 --- a/examples/basic/graycounter.py +++ b/examples/basic/graycounter.py @@ -5,15 +5,15 @@ from migen.genlib.cdc import GrayCounter from migen.sim.generic import run_simulation class TB(Module): - def __init__(self, width=3): - self.width = width - self.submodules.gc = GrayCounter(self.width) - self.prng = Random(7345) + def __init__(self, width=3): + self.width = width + self.submodules.gc = GrayCounter(self.width) + self.prng = Random(7345) - def do_simulation(self, selfp): - print("{0:0{1}b} CE={2} bin={3}".format(selfp.gc.q, - self.width, selfp.gc.ce, selfp.gc.q_binary)) - selfp.gc.ce = self.prng.getrandbits(1) + def do_simulation(self, selfp): + print("{0:0{1}b} CE={2} bin={3}".format(selfp.gc.q, + self.width, selfp.gc.ce, selfp.gc.q_binary)) + selfp.gc.ce = self.prng.getrandbits(1) if __name__ == "__main__": - run_simulation(TB(), ncycles=35) + run_simulation(TB(), ncycles=35) diff --git a/examples/basic/local_cd.py b/examples/basic/local_cd.py index ca7dd842..97edf339 100644 --- a/examples/basic/local_cd.py +++ b/examples/basic/local_cd.py @@ -3,14 +3,14 @@ from migen.fhdl import verilog from migen.genlib.divider import Divider class CDM(Module): - def __init__(self): - self.submodules.divider = Divider(5) - self.clock_domains.cd_sys = ClockDomain(reset_less=True) + def __init__(self): + self.submodules.divider = Divider(5) + self.clock_domains.cd_sys = ClockDomain(reset_less=True) class MultiMod(Module): - def __init__(self): - self.submodules.foo = CDM() - self.submodules.bar = CDM() + def __init__(self): + self.submodules.foo = CDM() + self.submodules.bar = CDM() mm = MultiMod() print(verilog.convert(mm, {mm.foo.cd_sys.clk, mm.bar.cd_sys.clk})) diff --git a/examples/basic/memory.py b/examples/basic/memory.py index 352a05b5..bd26f948 100644 --- a/examples/basic/memory.py +++ b/examples/basic/memory.py @@ -2,13 +2,13 @@ from migen.fhdl.std import * from migen.fhdl import verilog class Example(Module): - def __init__(self): - self.specials.mem = Memory(32, 100, init=[5, 18, 32]) - p1 = self.mem.get_port(write_capable=True, we_granularity=8) - p2 = self.mem.get_port(has_re=True, clock_domain="rd") - self.specials += p1, p2 - self.ios = {p1.adr, p1.dat_r, p1.we, p1.dat_w, - p2.adr, p2.dat_r, p2.re} + def __init__(self): + self.specials.mem = Memory(32, 100, init=[5, 18, 32]) + p1 = self.mem.get_port(write_capable=True, we_granularity=8) + p2 = self.mem.get_port(has_re=True, clock_domain="rd") + self.specials += p1, p2 + self.ios = {p1.adr, p1.dat_r, p1.we, p1.dat_w, + p2.adr, p2.dat_r, p2.re} example = Example() print(verilog.convert(example, example.ios)) diff --git a/examples/basic/namer.py b/examples/basic/namer.py index 72511679..a614cab7 100644 --- a/examples/basic/namer.py +++ b/examples/basic/namer.py @@ -3,35 +3,35 @@ from migen.fhdl import verilog from migen.genlib.misc import optree def gen_list(n): - s = [Signal() for i in range(n)] - return s + s = [Signal() for i in range(n)] + return s def gen_2list(n): - s = [Signal(2) for i in range(n)] - return s + s = [Signal(2) for i in range(n)] + return s class Foo: - def __init__(self): - la = gen_list(3) - lb = gen_2list(2) - self.sigs = la + lb + def __init__(self): + la = gen_list(3) + lb = gen_2list(2) + self.sigs = la + lb class Bar: - def __init__(self): - self.sigs = gen_list(2) + def __init__(self): + self.sigs = gen_list(2) class Example(Module): - def __init__(self): - a = [Bar() for x in range(3)] - b = [Foo() for x in range(3)] - c = b - b = [Bar() for x in range(2)] + def __init__(self): + a = [Bar() for x in range(3)] + b = [Foo() for x in range(3)] + c = b + b = [Bar() for x in range(2)] - output = Signal() - allsigs = [] - for lst in [a, b, c]: - for obj in lst: - allsigs.extend(obj.sigs) - self.comb += output.eq(optree("|", allsigs)) + output = Signal() + allsigs = [] + for lst in [a, b, c]: + for obj in lst: + allsigs.extend(obj.sigs) + self.comb += output.eq(optree("|", allsigs)) print(verilog.convert(Example())) diff --git a/examples/basic/psync.py b/examples/basic/psync.py index 4db02da1..67467d25 100644 --- a/examples/basic/psync.py +++ b/examples/basic/psync.py @@ -4,15 +4,15 @@ from migen.fhdl import verilog from migen.genlib.cdc import * class XilinxMultiRegImpl(MultiRegImpl): - def __init__(self, *args, **kwargs): - MultiRegImpl.__init__(self, *args, **kwargs) - self.specials += set(SynthesisDirective("attribute shreg_extract of {r} is no", r=r) - for r in self.regs) + def __init__(self, *args, **kwargs): + MultiRegImpl.__init__(self, *args, **kwargs) + self.specials += set(SynthesisDirective("attribute shreg_extract of {r} is no", r=r) + for r in self.regs) class XilinxMultiReg: - @staticmethod - def lower(dr): - return XilinxMultiRegImpl(dr.i, dr.o, dr.odomain, dr.n) + @staticmethod + def lower(dr): + return XilinxMultiRegImpl(dr.i, dr.o, dr.odomain, dr.n) ps = PulseSynchronizer("from", "to") v = verilog.convert(ps, {ps.i, ps.o}, special_overrides={MultiReg: XilinxMultiReg}) diff --git a/examples/basic/record.py b/examples/basic/record.py index aec89c64..c5cc26f1 100644 --- a/examples/basic/record.py +++ b/examples/basic/record.py @@ -3,20 +3,20 @@ from migen.fhdl import verilog from migen.genlib.record import * L = [ - ("position", [ - ("x", 10, DIR_M_TO_S), - ("y", 10, DIR_M_TO_S), - ]), - ("color", 32, DIR_M_TO_S), - ("stb", 1, DIR_M_TO_S), - ("ack", 1, DIR_S_TO_M) + ("position", [ + ("x", 10, DIR_M_TO_S), + ("y", 10, DIR_M_TO_S), + ]), + ("color", 32, DIR_M_TO_S), + ("stb", 1, DIR_M_TO_S), + ("ack", 1, DIR_S_TO_M) ] class Test(Module): - def __init__(self): - master = Record(L) - slave = Record(L) - self.comb += master.connect(slave) + def __init__(self): + master = Record(L) + slave = Record(L) + self.comb += master.connect(slave) print(verilog.convert(Test())) print(layout_len(L)) diff --git a/examples/basic/reslice.py b/examples/basic/reslice.py index eee3951f..b6ee48cf 100644 --- a/examples/basic/reslice.py +++ b/examples/basic/reslice.py @@ -2,15 +2,15 @@ from migen.fhdl.std import * from migen.fhdl import verilog class Example(Module): - def __init__(self): - a = Signal(3) - b = Signal(4) - c = Signal(5) - d = Signal(7) - s1 = c[:3][:2] - s2 = Cat(a, b)[:6] - s3 = Cat(s1, s2)[-5:] - self.comb += s3.eq(0) - self.comb += d.eq(Cat(d[::-1], Cat(s1[:1], s3[-4:])[:3])) + def __init__(self): + a = Signal(3) + b = Signal(4) + c = Signal(5) + d = Signal(7) + s1 = c[:3][:2] + s2 = Cat(a, b)[:6] + s3 = Cat(s1, s2)[-5:] + self.comb += s3.eq(0) + self.comb += d.eq(Cat(d[::-1], Cat(s1[:1], s3[-4:])[:3])) print(verilog.convert(Example())) diff --git a/examples/basic/simple_gpio.py b/examples/basic/simple_gpio.py index ab2502ee..631e4bb6 100644 --- a/examples/basic/simple_gpio.py +++ b/examples/basic/simple_gpio.py @@ -4,25 +4,25 @@ 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) + 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) + 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) - ] + 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}) + example.gpio_in, example.gpio_out}) print(v) diff --git a/examples/basic/tristate.py b/examples/basic/tristate.py index 47696fd3..af181697 100644 --- a/examples/basic/tristate.py +++ b/examples/basic/tristate.py @@ -2,10 +2,10 @@ from migen.fhdl.std import * from migen.fhdl import verilog class Example(Module): - def __init__(self, n=6): - self.pad = Signal(n) - self.t = TSTriple(n) - self.specials += self.t.get_tristate(self.pad) + def __init__(self, n=6): + self.pad = Signal(n) + self.t = TSTriple(n) + self.specials += self.t.get_tristate(self.pad) e = Example() print(verilog.convert(e, ios={e.pad, e.t.o, e.t.oe, e.t.i})) diff --git a/examples/basic/two_dividers.py b/examples/basic/two_dividers.py index 79519d4a..d895bf70 100644 --- a/examples/basic/two_dividers.py +++ b/examples/basic/two_dividers.py @@ -5,13 +5,13 @@ from migen.genlib import divider @ResetInserter() @CEInserter() class Example(Module): - def __init__(self, width): - d1 = divider.Divider(width) - d2 = divider.Divider(width) - self.submodules += d1, d2 - self.ios = { - d1.ready_o, d1.quotient_o, d1.remainder_o, d1.start_i, d1.dividend_i, d1.divisor_i, - d2.ready_o, d2.quotient_o, d2.remainder_o, d2.start_i, d2.dividend_i, d2.divisor_i} + def __init__(self, width): + d1 = divider.Divider(width) + d2 = divider.Divider(width) + self.submodules += d1, d2 + self.ios = { + d1.ready_o, d1.quotient_o, d1.remainder_o, d1.start_i, d1.dividend_i, d1.divisor_i, + d2.ready_o, d2.quotient_o, d2.remainder_o, d2.start_i, d2.dividend_i, d2.divisor_i} example = Example(16) print(verilog.convert(example, example.ios | {example.ce, example.reset})) diff --git a/examples/dataflow/dma.py b/examples/dataflow/dma.py index c96a6565..99190a91 100644 --- a/examples/dataflow/dma.py +++ b/examples/dataflow/dma.py @@ -9,84 +9,84 @@ from migen.bus import wishbone from migen.sim.generic import run_simulation class MyModel: - def read(self, address): - return address + 4 + def read(self, address): + return address + 4 class MyModelWB(MyModel, wishbone.TargetModel): - def __init__(self): - self.prng = Random(763627) + def __init__(self): + self.prng = Random(763627) - def can_ack(self, bus): - return self.prng.randrange(0, 2) + 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}) + 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 __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"])) + 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 __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}) + 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()) + 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) + 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) + 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 __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) + print("*** Testing Wishbone reader") + run_simulation(TBWishboneReader(), 100) def test_wb_writer(): - print("*** Testing Wishbone writer") - run_simulation(TBWishboneWriter(), 100) + print("*** Testing Wishbone writer") + run_simulation(TBWishboneWriter(), 100) if __name__ == "__main__": - test_wb_reader() - test_wb_writer() + test_wb_reader() + test_wb_writer() diff --git a/examples/dataflow/misc.py b/examples/dataflow/misc.py index 9eda30d8..095ca3ef 100644 --- a/examples/dataflow/misc.py +++ b/examples/dataflow/misc.py @@ -5,33 +5,33 @@ 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}) + 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 __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"]) + 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()) + 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) + 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 index 6cc1306b..b1b6574e 100644 --- a/examples/dataflow/structuring.py +++ b/examples/dataflow/structuring.py @@ -16,53 +16,53 @@ 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}) + 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 __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"]) + 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()) + def __init__(self): + self.sink = Sink(base_layout) + SimActor.__init__(self, sink_gen()) class TB(Module): - def __init__(self): - source = SimSource() - sink = SimSink() + 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) + # 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) + 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) + 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() + 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/examples/sim/abstract_transactions_wb.py b/examples/sim/abstract_transactions_wb.py index 431a6460..084876c9 100644 --- a/examples/sim/abstract_transactions_wb.py +++ b/examples/sim/abstract_transactions_wb.py @@ -8,53 +8,53 @@ from migen.sim.generic import run_simulation # Our bus master. # Python generators let us program bus transactions in an elegant sequential style. def my_generator(): - prng = Random(92837) + prng = Random(92837) - # Write to the first addresses. - for x in range(10): - t = TWrite(x, 2*x) - yield t - print("Wrote in " + str(t.latency) + " cycle(s)") - # Insert some dead cycles to simulate bus inactivity. - for delay in range(prng.randrange(0, 3)): - yield None + # Write to the first addresses. + for x in range(10): + t = TWrite(x, 2*x) + yield t + print("Wrote in " + str(t.latency) + " cycle(s)") + # Insert some dead cycles to simulate bus inactivity. + for delay in range(prng.randrange(0, 3)): + yield None - # Read from the first addresses. - for x in range(10): - t = TRead(x) - yield t - print("Read " + str(t.data) + " in " + str(t.latency) + " cycle(s)") - for delay in range(prng.randrange(0, 3)): - yield None + # Read from the first addresses. + for x in range(10): + t = TRead(x) + yield t + print("Read " + str(t.data) + " in " + str(t.latency) + " cycle(s)") + for delay in range(prng.randrange(0, 3)): + yield None # Our bus slave. class MyModelWB(wishbone.TargetModel): - def __init__(self): - self.prng = Random(763627) + def __init__(self): + self.prng = Random(763627) - def read(self, address): - return address + 4 + def read(self, address): + return address + 4 - def can_ack(self, bus): - # Simulate variable latency. - return self.prng.randrange(0, 2) + def can_ack(self, bus): + # Simulate variable latency. + return self.prng.randrange(0, 2) class TB(Module): - def __init__(self): - # The "wishbone.Initiator" library component runs our generator - # and manipulates the bus signals accordingly. - self.submodules.master = wishbone.Initiator(my_generator()) - # The "wishbone.Target" library component examines the bus signals - # and calls into our model object. - self.submodules.slave = wishbone.Target(MyModelWB()) - # The "wishbone.Tap" library component examines the bus at the slave port - # and displays the transactions on the console (/). - self.submodules.tap = wishbone.Tap(self.slave.bus) - # Connect the master to the slave. - self.submodules.intercon = wishbone.InterconnectPointToPoint(self.master.bus, self.slave.bus) + def __init__(self): + # The "wishbone.Initiator" library component runs our generator + # and manipulates the bus signals accordingly. + self.submodules.master = wishbone.Initiator(my_generator()) + # The "wishbone.Target" library component examines the bus signals + # and calls into our model object. + self.submodules.slave = wishbone.Target(MyModelWB()) + # The "wishbone.Tap" library component examines the bus at the slave port + # and displays the transactions on the console (/). + self.submodules.tap = wishbone.Tap(self.slave.bus) + # Connect the master to the slave. + self.submodules.intercon = wishbone.InterconnectPointToPoint(self.master.bus, self.slave.bus) if __name__ == "__main__": - run_simulation(TB()) + run_simulation(TB()) # Output: # diff --git a/examples/sim/basic1.py b/examples/sim/basic1.py index a1d0bbe9..0726f8e5 100644 --- a/examples/sim/basic1.py +++ b/examples/sim/basic1.py @@ -4,25 +4,25 @@ from migen.sim.generic import run_simulation # Our simple counter, which increments at every cycle # and prints its current value in simulation. class Counter(Module): - def __init__(self): - self.count = Signal(4) + def __init__(self): + self.count = Signal(4) - # At each cycle, increase the value of the count signal. - # We do it with convertible/synthesizable FHDL code. - self.sync += self.count.eq(self.count + 1) + # At each cycle, increase the value of the count signal. + # We do it with convertible/synthesizable FHDL code. + self.sync += self.count.eq(self.count + 1) - # This function will be called at every cycle. - def do_simulation(self, selfp): - # Simply read the count signal and print it. - # The output is: - # Count: 0 - # Count: 1 - # Count: 2 - # ... - print("Count: " + str(selfp.count)) + # This function will be called at every cycle. + def do_simulation(self, selfp): + # Simply read the count signal and print it. + # The output is: + # Count: 0 + # Count: 1 + # Count: 2 + # ... + print("Count: " + str(selfp.count)) if __name__ == "__main__": - dut = Counter() - # Since we do not use StopSimulation, limit the simulation - # to some number of cycles. - run_simulation(dut, ncycles=20) + dut = Counter() + # Since we do not use StopSimulation, limit the simulation + # to some number of cycles. + run_simulation(dut, ncycles=20) diff --git a/examples/sim/basic2.py b/examples/sim/basic2.py index 1a0358da..fd4f8693 100644 --- a/examples/sim/basic2.py +++ b/examples/sim/basic2.py @@ -5,22 +5,22 @@ from migen.sim.generic import run_simulation # Has a clock enable (CE) signal, counts on more bits # and resets with a negative number. class Counter(Module): - def __init__(self): - self.ce = Signal() - # Demonstrate negative numbers and signals larger than 32 bits. - self.count = Signal((37, True), reset=-5) + def __init__(self): + self.ce = Signal() + # Demonstrate negative numbers and signals larger than 32 bits. + self.count = Signal((37, True), reset=-5) - self.sync += If(self.ce, self.count.eq(self.count + 1)) + self.sync += If(self.ce, self.count.eq(self.count + 1)) - def do_simulation(self, selfp): - # Only assert CE every second cycle. - # => each counter value is held for two cycles. - if selfp.simulator.cycle_counter % 2: - selfp.ce = 0 # This is how you write to a signal. - else: - selfp.ce = 1 - print("Cycle: " + str(selfp.simulator.cycle_counter) + " Count: " + \ - str(selfp.count)) + def do_simulation(self, selfp): + # Only assert CE every second cycle. + # => each counter value is held for two cycles. + if selfp.simulator.cycle_counter % 2: + selfp.ce = 0 # This is how you write to a signal. + else: + selfp.ce = 1 + print("Cycle: " + str(selfp.simulator.cycle_counter) + " Count: " + \ + str(selfp.count)) # Output is: # Cycle: 0 Count: -5 @@ -31,6 +31,6 @@ class Counter(Module): # ... if __name__ == "__main__": - dut = Counter() - # Demonstrate VCD output - run_simulation(dut, vcd_name="my.vcd", ncycles=20) + dut = Counter() + # Demonstrate VCD output + run_simulation(dut, vcd_name="my.vcd", ncycles=20) diff --git a/examples/sim/dataflow.py b/examples/sim/dataflow.py index bc8c6b3d..ea606736 100644 --- a/examples/sim/dataflow.py +++ b/examples/sim/dataflow.py @@ -6,37 +6,37 @@ from migen.actorlib.sim import * from migen.sim.generic import run_simulation def source_gen(): - for i in range(10): - print("Sending: " + str(i)) - yield Token("source", {"value": i}) + for i in range(10): + print("Sending: " + str(i)) + yield Token("source", {"value": i}) class SimSource(SimActor): - def __init__(self): - self.source = Source([("value", 32)]) - SimActor.__init__(self, source_gen()) + def __init__(self): + self.source = Source([("value", 32)]) + SimActor.__init__(self, source_gen()) def sink_gen(): - while True: - t = Token("sink") - yield t - print("Received: " + str(t.value["value"])) + while True: + t = Token("sink") + yield t + print("Received: " + str(t.value["value"])) class SimSink(SimActor): - def __init__(self): - self.sink = Sink([("value", 32)]) - SimActor.__init__(self, sink_gen()) + def __init__(self): + self.sink = Sink([("value", 32)]) + SimActor.__init__(self, sink_gen()) class TB(Module): - def __init__(self): - self.source = SimSource() - self.sink = SimSink() - g = DataFlowGraph() - g.add_connection(self.source, self.sink) - self.submodules.comp = CompositeActor(g) + 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 do_simulation(self, selfp): + if self.source.token_exchanger.done: + raise StopSimulation if __name__ == "__main__": - run_simulation(TB()) + run_simulation(TB()) diff --git a/examples/sim/fir.py b/examples/sim/fir.py index 4b6fa1ea..4b64d427 100644 --- a/examples/sim/fir.py +++ b/examples/sim/fir.py @@ -9,61 +9,61 @@ from migen.sim.generic import run_simulation # A synthesizable FIR filter. class FIR(Module): - def __init__(self, coef, wsize=16): - self.coef = coef - self.wsize = wsize - self.i = Signal((self.wsize, True)) - self.o = Signal((self.wsize, True)) + def __init__(self, coef, wsize=16): + self.coef = coef + self.wsize = wsize + self.i = Signal((self.wsize, True)) + self.o = Signal((self.wsize, True)) - ### + ### - muls = [] - src = self.i - for c in self.coef: - sreg = Signal((self.wsize, True)) - self.sync += sreg.eq(src) - src = sreg - c_fp = int(c*2**(self.wsize - 1)) - muls.append(c_fp*sreg) - sum_full = Signal((2*self.wsize-1, True)) - self.sync += sum_full.eq(optree("+", muls)) - self.comb += self.o.eq(sum_full[self.wsize-1:]) + muls = [] + src = self.i + for c in self.coef: + sreg = Signal((self.wsize, True)) + self.sync += sreg.eq(src) + src = sreg + c_fp = int(c*2**(self.wsize - 1)) + muls.append(c_fp*sreg) + sum_full = Signal((2*self.wsize-1, True)) + self.sync += sum_full.eq(optree("+", muls)) + self.comb += self.o.eq(sum_full[self.wsize-1:]) # A test bench for our FIR filter. # Generates a sine wave at the input and records the output. class TB(Module): - def __init__(self, coef, frequency): - self.submodules.fir = FIR(coef) - self.frequency = frequency - self.inputs = [] - self.outputs = [] + def __init__(self, coef, frequency): + self.submodules.fir = FIR(coef) + self.frequency = frequency + self.inputs = [] + self.outputs = [] - def do_simulation(self, selfp): - f = 2**(self.fir.wsize - 1) - v = 0.1*cos(2*pi*self.frequency*selfp.simulator.cycle_counter) - selfp.fir.i = int(f*v) - self.inputs.append(v) - self.outputs.append(selfp.fir.o/f) + def do_simulation(self, selfp): + f = 2**(self.fir.wsize - 1) + v = 0.1*cos(2*pi*self.frequency*selfp.simulator.cycle_counter) + selfp.fir.i = int(f*v) + self.inputs.append(v) + self.outputs.append(selfp.fir.o/f) if __name__ == "__main__": - # Compute filter coefficients with SciPy. - coef = signal.remez(30, [0, 0.1, 0.2, 0.4, 0.45, 0.5], [0, 1, 0]) + # Compute filter coefficients with SciPy. + coef = signal.remez(30, [0, 0.1, 0.2, 0.4, 0.45, 0.5], [0, 1, 0]) - # Simulate for different frequencies and concatenate - # the results. - in_signals = [] - out_signals = [] - for frequency in [0.05, 0.1, 0.25]: - tb = TB(coef, frequency) - run_simulation(tb, ncycles=200) - in_signals += tb.inputs - out_signals += tb.outputs + # Simulate for different frequencies and concatenate + # the results. + in_signals = [] + out_signals = [] + for frequency in [0.05, 0.1, 0.25]: + tb = TB(coef, frequency) + run_simulation(tb, ncycles=200) + in_signals += tb.inputs + out_signals += tb.outputs - # Plot data from the input and output waveforms. - plt.plot(in_signals) - plt.plot(out_signals) - plt.show() + # Plot data from the input and output waveforms. + plt.plot(in_signals) + plt.plot(out_signals) + plt.show() - # Print the Verilog source for the filter. - fir = FIR(coef) - print(verilog.convert(fir, ios={fir.i, fir.o})) + # Print the Verilog source for the filter. + fir = FIR(coef) + print(verilog.convert(fir, ios={fir.i, fir.o})) diff --git a/examples/sim/memory.py b/examples/sim/memory.py index 3b608905..a7321c36 100644 --- a/examples/sim/memory.py +++ b/examples/sim/memory.py @@ -2,24 +2,24 @@ from migen.fhdl.std import * from migen.sim.generic import run_simulation class Mem(Module): - def __init__(self): - # Initialize the beginning of the memory with integers - # from 0 to 19. - self.specials.mem = Memory(16, 2**12, init=list(range(20))) + def __init__(self): + # Initialize the beginning of the memory with integers + # from 0 to 19. + self.specials.mem = Memory(16, 2**12, init=list(range(20))) - def do_simulation(self, selfp): - # Read the memory. Use the cycle counter as address. - value = selfp.mem[selfp.simulator.cycle_counter] - # Print the result. Output is: - # 0 - # 1 - # 2 - # ... - print(value) - # Raising StopSimulation disables the current (and here, only one) - # simulation function. Simulator stops when all functions are disabled. - if value == 10: - raise StopSimulation + def do_simulation(self, selfp): + # Read the memory. Use the cycle counter as address. + value = selfp.mem[selfp.simulator.cycle_counter] + # Print the result. Output is: + # 0 + # 1 + # 2 + # ... + print(value) + # Raising StopSimulation disables the current (and here, only one) + # simulation function. Simulator stops when all functions are disabled. + if value == 10: + raise StopSimulation if __name__ == "__main__": - run_simulation(Mem()) + run_simulation(Mem()) diff --git a/mibuild/altera/platform.py b/mibuild/altera/platform.py index c98f987f..1e2d6453 100644 --- a/mibuild/altera/platform.py +++ b/mibuild/altera/platform.py @@ -2,24 +2,24 @@ from mibuild.generic_platform import GenericPlatform from mibuild.altera import common, quartus class AlteraPlatform(GenericPlatform): - bitstream_ext = ".sof" + bitstream_ext = ".sof" - def __init__(self, *args, toolchain="quartus", **kwargs): - GenericPlatform.__init__(self, *args, **kwargs) - if toolchain == "quartus": - self.toolchain = quartus.AlteraQuartusToolchain() - else: - raise ValueError("Unknown toolchain") + def __init__(self, *args, toolchain="quartus", **kwargs): + GenericPlatform.__init__(self, *args, **kwargs) + if toolchain == "quartus": + self.toolchain = quartus.AlteraQuartusToolchain() + else: + raise ValueError("Unknown toolchain") - def get_verilog(self, *args, special_overrides=dict(), **kwargs): - so = dict(common.altera_special_overrides) - so.update(special_overrides) - return GenericPlatform.get_verilog(self, *args, special_overrides=so, **kwargs) + def get_verilog(self, *args, special_overrides=dict(), **kwargs): + so = dict(common.altera_special_overrides) + so.update(special_overrides) + return GenericPlatform.get_verilog(self, *args, special_overrides=so, **kwargs) - def build(self, *args, **kwargs): - return self.toolchain.build(self, *args, **kwargs) + def build(self, *args, **kwargs): + return self.toolchain.build(self, *args, **kwargs) - def add_period_constraint(self, clk, period): - if hasattr(clk, "p"): - clk = clk.p - self.toolchain.add_period_constraint(self, clk, period) + def add_period_constraint(self, clk, period): + if hasattr(clk, "p"): + clk = clk.p + self.toolchain.add_period_constraint(self, clk, period) diff --git a/mibuild/altera/programmer.py b/mibuild/altera/programmer.py index c6f25cbe..a60ec091 100644 --- a/mibuild/altera/programmer.py +++ b/mibuild/altera/programmer.py @@ -3,8 +3,8 @@ import subprocess from mibuild.generic_programmer import GenericProgrammer class USBBlaster(GenericProgrammer): - needs_bitreverse = False + needs_bitreverse = False - def load_bitstream(self, bitstream_file, port=0): - usb_port = "[USB-"+str(port)+"]" - subprocess.call(["quartus_pgm", "-m", "jtag", "-c", "USB-Blaster"+usb_port, "-o", "p;"+bitstream_file]) + def load_bitstream(self, bitstream_file, port=0): + usb_port = "[USB-"+str(port)+"]" + subprocess.call(["quartus_pgm", "-m", "jtag", "-c", "USB-Blaster"+usb_port, "-o", "p;"+bitstream_file]) diff --git a/mibuild/altera/quartus.py b/mibuild/altera/quartus.py index bdf14a68..e28cbd8c 100644 --- a/mibuild/altera/quartus.py +++ b/mibuild/altera/quartus.py @@ -10,53 +10,53 @@ from mibuild import tools from mibuild.xilinx import common def _format_constraint(c): - if isinstance(c, Pins): - return "set_location_assignment PIN_" + c.identifiers[0] - elif isinstance(c, IOStandard): - return "set_instance_assignment -name IO_STANDARD " + "\"" + c.name + "\"" - elif isinstance(c, Misc): - return c.misc + if isinstance(c, Pins): + return "set_location_assignment PIN_" + c.identifiers[0] + elif isinstance(c, IOStandard): + return "set_instance_assignment -name IO_STANDARD " + "\"" + c.name + "\"" + elif isinstance(c, Misc): + return c.misc def _format_qsf(signame, pin, others, resname): - fmt_c = [_format_constraint(c) for c in ([Pins(pin)] + others)] - fmt_r = resname[0] + ":" + str(resname[1]) - if resname[2] is not None: - fmt_r += "." + resname[2] - r = "" - for c in fmt_c: - r += c + " -to " + signame + " # " + fmt_r + "\n" - return r + fmt_c = [_format_constraint(c) for c in ([Pins(pin)] + others)] + fmt_r = resname[0] + ":" + str(resname[1]) + if resname[2] is not None: + fmt_r += "." + resname[2] + r = "" + for c in fmt_c: + r += c + " -to " + signame + " # " + fmt_r + "\n" + return r def _build_qsf(named_sc, named_pc): - r = "" - for sig, pins, others, resname in named_sc: - if len(pins) > 1: - for i, p in enumerate(pins): - r += _format_qsf(sig + "[" + str(i) + "]", p, others, resname) - else: - r += _format_qsf(sig, pins[0], others, resname) - if named_pc: - r += "\n" + "\n\n".join(named_pc) - r += "set_global_assignment -name top_level_entity top\n" - return r + r = "" + for sig, pins, others, resname in named_sc: + if len(pins) > 1: + for i, p in enumerate(pins): + r += _format_qsf(sig + "[" + str(i) + "]", p, others, resname) + else: + r += _format_qsf(sig, pins[0], others, resname) + if named_pc: + r += "\n" + "\n\n".join(named_pc) + r += "set_global_assignment -name top_level_entity top\n" + return r def _build_files(device, sources, vincpaths, named_sc, named_pc, build_name): - qsf_contents = "" - for filename, language in sources: - # Enforce use of SystemVerilog (Quartus does not support global parameters in Verilog) - if language == "verilog": - language = "systemverilog" - qsf_contents += "set_global_assignment -name "+language.upper()+"_FILE " + filename.replace("\\","/") + "\n" + qsf_contents = "" + for filename, language in sources: + # Enforce use of SystemVerilog (Quartus does not support global parameters in Verilog) + if language == "verilog": + language = "systemverilog" + qsf_contents += "set_global_assignment -name "+language.upper()+"_FILE " + filename.replace("\\","/") + "\n" - for path in vincpaths: - qsf_contents += "set_global_assignment -name SEARCH_PATH " + path.replace("\\","/") + "\n" + for path in vincpaths: + qsf_contents += "set_global_assignment -name SEARCH_PATH " + path.replace("\\","/") + "\n" - qsf_contents += _build_qsf(named_sc, named_pc) - qsf_contents += "set_global_assignment -name DEVICE " + device - tools.write_to_file(build_name + ".qsf", qsf_contents) + qsf_contents += _build_qsf(named_sc, named_pc) + qsf_contents += "set_global_assignment -name DEVICE " + device + tools.write_to_file(build_name + ".qsf", qsf_contents) def _run_quartus(build_name, quartus_path): - build_script_contents = """# Autogenerated by mibuild + build_script_contents = """# Autogenerated by mibuild quartus_map --read_settings_files=on --write_settings_files=off {build_name} -c {build_name} quartus_fit --read_settings_files=off --write_settings_files=off {build_name} -c {build_name} @@ -64,37 +64,37 @@ quartus_asm --read_settings_files=off --write_settings_files=off {build_name} -c quartus_sta {build_name} -c {build_name} """.format(build_name=build_name) - build_script_file = "build_" + build_name + ".sh" - tools.write_to_file(build_script_file, build_script_contents, force_unix=True) + build_script_file = "build_" + build_name + ".sh" + tools.write_to_file(build_script_file, build_script_contents, force_unix=True) - r = subprocess.call(["bash", build_script_file]) - if r != 0: - raise OSError("Subprocess failed") + r = subprocess.call(["bash", build_script_file]) + if r != 0: + raise OSError("Subprocess failed") class AlteraQuartusToolchain: - def build(self, platform, fragment, build_dir="build", build_name="top", - quartus_path="/opt/Altera", run=True): - tools.mkdir_noerror(build_dir) - os.chdir(build_dir) - - if not isinstance(fragment, _Fragment): - fragment = fragment.get_fragment() - platform.finalize(fragment) - - v_output = platform.get_verilog(fragment) - named_sc, named_pc = platform.resolve_signals(v_output.ns) - v_file = build_name + ".v" - v_output.write(v_file) - sources = platform.sources | {(v_file, "verilog")} - _build_files(platform.device, sources, platform.verilog_include_paths, named_sc, named_pc, build_name) - if run: - _run_quartus(build_name, quartus_path) - - os.chdir("..") - - return v_output.ns - - def add_period_constraint(self, platform, clk, period): - # TODO: handle differential clk - platform.add_platform_command("""set_global_assignment -name DUTY_CYCLE 50 -section_id {clk}""", clk=clk) - platform.add_platform_command("""set_global_assignment -name FMAX_REQUIREMENT "{freq} MHz" -section_id {clk}\n""".format(freq=str(float(1/period)*1000), clk="{clk}"), clk=clk) + def build(self, platform, fragment, build_dir="build", build_name="top", + quartus_path="/opt/Altera", run=True): + tools.mkdir_noerror(build_dir) + os.chdir(build_dir) + + if not isinstance(fragment, _Fragment): + fragment = fragment.get_fragment() + platform.finalize(fragment) + + v_output = platform.get_verilog(fragment) + named_sc, named_pc = platform.resolve_signals(v_output.ns) + v_file = build_name + ".v" + v_output.write(v_file) + sources = platform.sources | {(v_file, "verilog")} + _build_files(platform.device, sources, platform.verilog_include_paths, named_sc, named_pc, build_name) + if run: + _run_quartus(build_name, quartus_path) + + os.chdir("..") + + return v_output.ns + + def add_period_constraint(self, platform, clk, period): + # TODO: handle differential clk + platform.add_platform_command("""set_global_assignment -name DUTY_CYCLE 50 -section_id {clk}""", clk=clk) + platform.add_platform_command("""set_global_assignment -name FMAX_REQUIREMENT "{freq} MHz" -section_id {clk}\n""".format(freq=str(float(1/period)*1000), clk="{clk}"), clk=clk) diff --git a/mibuild/generic_platform.py b/mibuild/generic_platform.py index 4c13fe72..0a6b65e8 100644 --- a/mibuild/generic_platform.py +++ b/mibuild/generic_platform.py @@ -10,278 +10,278 @@ from migen.util.misc import autotype from mibuild import tools class ConstraintError(Exception): - pass + pass class Pins: - def __init__(self, *identifiers): - self.identifiers = [] - for i in identifiers: - self.identifiers += i.split() + def __init__(self, *identifiers): + self.identifiers = [] + for i in identifiers: + self.identifiers += i.split() class IOStandard: - def __init__(self, name): - self.name = name + def __init__(self, name): + self.name = name class Drive: - def __init__(self, strength): - self.strength = strength + def __init__(self, strength): + self.strength = strength class Misc: - def __init__(self, misc): - self.misc = misc + def __init__(self, misc): + self.misc = misc class Subsignal: - def __init__(self, name, *constraints): - self.name = name - self.constraints = list(constraints) + def __init__(self, name, *constraints): + self.name = name + self.constraints = list(constraints) class PlatformInfo: - def __init__(self, info): - self.info = info + def __init__(self, info): + self.info = info def _lookup(description, name, number): - for resource in description: - if resource[0] == name and (number is None or resource[1] == number): - return resource - raise ConstraintError("Resource not found: " + name + ":" + str(number)) + for resource in description: + if resource[0] == name and (number is None or resource[1] == number): + return resource + raise ConstraintError("Resource not found: " + name + ":" + str(number)) def _resource_type(resource): - t = None - for element in resource[2:]: - if isinstance(element, Pins): - assert(t is None) - t = len(element.identifiers) - elif isinstance(element, Subsignal): - if t is None: - t = [] - assert(isinstance(t, list)) - n_bits = None - for c in element.constraints: - if isinstance(c, Pins): - assert(n_bits is None) - n_bits = len(c.identifiers) - t.append((element.name, n_bits)) - return t + t = None + for element in resource[2:]: + if isinstance(element, Pins): + assert(t is None) + t = len(element.identifiers) + elif isinstance(element, Subsignal): + if t is None: + t = [] + assert(isinstance(t, list)) + n_bits = None + for c in element.constraints: + if isinstance(c, Pins): + assert(n_bits is None) + n_bits = len(c.identifiers) + t.append((element.name, n_bits)) + return t class ConnectorManager: - def __init__(self, connectors): - self.connector_table = dict() - for connector in connectors: - cit = iter(connector) - conn_name = next(cit) - if isinstance(connector[1], str): - pin_list = [] - for pins in cit: - pin_list += pins.split() - pin_list = [None if pin == "None" else pin for pin in pin_list] - elif isinstance(connector[1], dict): - pin_list = connector[1] - else: - raise ValueError("Unsupported pin list type {} for connector" - " {}".format(type(connector[1]), conn_name)) - if conn_name in self.connector_table: - raise ValueError("Connector specified more than once: "+conn_name) - self.connector_table[conn_name] = pin_list - - def resolve_identifiers(self, identifiers): - r = [] - for identifier in identifiers: - if ":" in identifier: - conn, pn = identifier.split(":") - if pn.isdigit(): - pn = int(pn) - r.append(self.connector_table[conn][pn]) - else: - r.append(identifier) - return r + def __init__(self, connectors): + self.connector_table = dict() + for connector in connectors: + cit = iter(connector) + conn_name = next(cit) + if isinstance(connector[1], str): + pin_list = [] + for pins in cit: + pin_list += pins.split() + pin_list = [None if pin == "None" else pin for pin in pin_list] + elif isinstance(connector[1], dict): + pin_list = connector[1] + else: + raise ValueError("Unsupported pin list type {} for connector" + " {}".format(type(connector[1]), conn_name)) + if conn_name in self.connector_table: + raise ValueError("Connector specified more than once: "+conn_name) + self.connector_table[conn_name] = pin_list + + def resolve_identifiers(self, identifiers): + r = [] + for identifier in identifiers: + if ":" in identifier: + conn, pn = identifier.split(":") + if pn.isdigit(): + pn = int(pn) + r.append(self.connector_table[conn][pn]) + else: + r.append(identifier) + return r def _separate_pins(constraints): - pins = None - others = [] - for c in constraints: - if isinstance(c, Pins): - assert(pins is None) - pins = c.identifiers - else: - others.append(c) - return pins, others + pins = None + others = [] + for c in constraints: + if isinstance(c, Pins): + assert(pins is None) + pins = c.identifiers + else: + others.append(c) + return pins, others class ConstraintManager: - def __init__(self, io, connectors): - self.available = list(io) - self.matched = [] - self.platform_commands = [] - self.connector_manager = ConnectorManager(connectors) - - def add_extension(self, io): - self.available.extend(io) - - def request(self, name, number=None): - resource = _lookup(self.available, name, number) - rt = _resource_type(resource) - if isinstance(rt, int): - obj = Signal(rt, name_override=resource[0]) - else: - obj = Record(rt, name=resource[0]) - for element in resource[2:]: - if isinstance(element, PlatformInfo): - obj.platform_info = element.info - break - self.available.remove(resource) - self.matched.append((resource, obj)) - return obj - - def lookup_request(self, name, number=None): - for resource, obj in self.matched: - if resource[0] == name and (number is None or resource[1] == number): - return obj - raise ConstraintError("Resource not found: " + name + ":" + str(number)) - - def add_platform_command(self, command, **signals): - self.platform_commands.append((command, signals)) - - def get_io_signals(self): - r = set() - for resource, obj in self.matched: - if isinstance(obj, Signal): - r.add(obj) - else: - r.update(obj.flatten()) - return r - - def get_sig_constraints(self): - r = [] - for resource, obj in self.matched: - name = resource[0] - number = resource[1] - has_subsignals = False - top_constraints = [] - for element in resource[2:]: - if isinstance(element, Subsignal): - has_subsignals = True - else: - top_constraints.append(element) - if has_subsignals: - for element in resource[2:]: - if isinstance(element, Subsignal): - sig = getattr(obj, element.name) - pins, others = _separate_pins(top_constraints + element.constraints) - pins = self.connector_manager.resolve_identifiers(pins) - r.append((sig, pins, others, (name, number, element.name))) - else: - pins, others = _separate_pins(top_constraints) - pins = self.connector_manager.resolve_identifiers(pins) - r.append((obj, pins, others, (name, number, None))) - return r - - def get_platform_commands(self): - return self.platform_commands + def __init__(self, io, connectors): + self.available = list(io) + self.matched = [] + self.platform_commands = [] + self.connector_manager = ConnectorManager(connectors) + + def add_extension(self, io): + self.available.extend(io) + + def request(self, name, number=None): + resource = _lookup(self.available, name, number) + rt = _resource_type(resource) + if isinstance(rt, int): + obj = Signal(rt, name_override=resource[0]) + else: + obj = Record(rt, name=resource[0]) + for element in resource[2:]: + if isinstance(element, PlatformInfo): + obj.platform_info = element.info + break + self.available.remove(resource) + self.matched.append((resource, obj)) + return obj + + def lookup_request(self, name, number=None): + for resource, obj in self.matched: + if resource[0] == name and (number is None or resource[1] == number): + return obj + raise ConstraintError("Resource not found: " + name + ":" + str(number)) + + def add_platform_command(self, command, **signals): + self.platform_commands.append((command, signals)) + + def get_io_signals(self): + r = set() + for resource, obj in self.matched: + if isinstance(obj, Signal): + r.add(obj) + else: + r.update(obj.flatten()) + return r + + def get_sig_constraints(self): + r = [] + for resource, obj in self.matched: + name = resource[0] + number = resource[1] + has_subsignals = False + top_constraints = [] + for element in resource[2:]: + if isinstance(element, Subsignal): + has_subsignals = True + else: + top_constraints.append(element) + if has_subsignals: + for element in resource[2:]: + if isinstance(element, Subsignal): + sig = getattr(obj, element.name) + pins, others = _separate_pins(top_constraints + element.constraints) + pins = self.connector_manager.resolve_identifiers(pins) + r.append((sig, pins, others, (name, number, element.name))) + else: + pins, others = _separate_pins(top_constraints) + pins = self.connector_manager.resolve_identifiers(pins) + r.append((obj, pins, others, (name, number, None))) + return r + + def get_platform_commands(self): + return self.platform_commands class GenericPlatform: - def __init__(self, device, io, connectors=[], name=None): - self.device = device - self.constraint_manager = ConstraintManager(io, connectors) - if name is None: - name = self.__module__.split(".")[-1] - self.name = name - self.sources = set() - self.verilog_include_paths = set() - self.finalized = False - - def request(self, *args, **kwargs): - return self.constraint_manager.request(*args, **kwargs) - - def lookup_request(self, *args, **kwargs): - return self.constraint_manager.lookup_request(*args, **kwargs) - - def add_period_constraint(self, clk, period): - raise NotImplementedError - - def add_platform_command(self, *args, **kwargs): - return self.constraint_manager.add_platform_command(*args, **kwargs) - - def add_extension(self, *args, **kwargs): - return self.constraint_manager.add_extension(*args, **kwargs) - - def finalize(self, fragment, *args, **kwargs): - if self.finalized: - raise ConstraintError("Already finalized") - # if none exists, create a default clock domain and drive it - if not fragment.clock_domains: - if not hasattr(self, "default_clk_name"): - raise NotImplementedError("No default clock and no clock domain defined") - crg = CRG(self.request(self.default_clk_name)) - fragment += crg.get_fragment() - self.do_finalize(fragment, *args, **kwargs) - self.finalized = True - - def do_finalize(self, fragment, *args, **kwargs): - """overload this and e.g. add_platform_command()'s after the modules had their say""" - if hasattr(self, "default_clk_period"): - try: - self.add_period_constraint(self.lookup_request(self.default_clk_name), self.default_clk_period) - except ConstraintError: - pass - - def add_source(self, filename, language=None): - if language is None: - language = tools.language_by_filename(filename) - if language is None: - language = "verilog" # default to Verilog - filename = os.path.abspath(filename) - self.sources.add((filename, language)) - - def add_sources(self, path, *filenames, language=None): - for f in filenames: - self.add_source(os.path.join(path, f), language) - - def add_source_dir(self, path, recursive=True): - dir_files = [] - if recursive: - for root, dirs, files in os.walk(path): - for filename in files: - dir_files.append(os.path.join(root, filename)) - else: - for item in os.listdir(path): - if os.path.isfile(os.path.join(path, item)): - dir_files.append(os.path.join(path, item)) - for filename in dir_files: - language = tools.language_by_filename(filename) - if language is not None: - self.add_source(filename, language) - - def add_verilog_include_path(self, path): - self.verilog_include_paths.add(os.path.abspath(path)) - - def resolve_signals(self, vns): - # resolve signal names in constraints - sc = self.constraint_manager.get_sig_constraints() - named_sc = [(vns.get_name(sig), pins, others, resource) for sig, pins, others, resource in sc] - # resolve signal names in platform commands - pc = self.constraint_manager.get_platform_commands() - named_pc = [] - for template, args in pc: - name_dict = dict((k, vns.get_name(sig)) for k, sig in args.items()) - named_pc.append(template.format(**name_dict)) - return named_sc, named_pc - - def get_verilog(self, fragment, **kwargs): - return verilog.convert(fragment, self.constraint_manager.get_io_signals(), create_clock_domains=False, **kwargs) - - def get_edif(self, fragment, cell_library, vendor, device, **kwargs): - return edif.convert(fragment, self.constraint_manager.get_io_signals(), cell_library, vendor, device, **kwargs) - - def build(self, fragment): - raise NotImplementedError("GenericPlatform.build must be overloaded") - - def build_cmdline(self, *args, **kwargs): - arg = sys.argv[1:] - if len(arg) % 2: - print("Missing value for option: "+sys.argv[-1]) - sys.exit(1) - argdict = dict((k, autotype(v)) for k, v in zip(*[iter(arg)]*2)) - kwargs.update(argdict) - self.build(*args, **kwargs) - - def create_programmer(self): - raise NotImplementedError + def __init__(self, device, io, connectors=[], name=None): + self.device = device + self.constraint_manager = ConstraintManager(io, connectors) + if name is None: + name = self.__module__.split(".")[-1] + self.name = name + self.sources = set() + self.verilog_include_paths = set() + self.finalized = False + + def request(self, *args, **kwargs): + return self.constraint_manager.request(*args, **kwargs) + + def lookup_request(self, *args, **kwargs): + return self.constraint_manager.lookup_request(*args, **kwargs) + + def add_period_constraint(self, clk, period): + raise NotImplementedError + + def add_platform_command(self, *args, **kwargs): + return self.constraint_manager.add_platform_command(*args, **kwargs) + + def add_extension(self, *args, **kwargs): + return self.constraint_manager.add_extension(*args, **kwargs) + + def finalize(self, fragment, *args, **kwargs): + if self.finalized: + raise ConstraintError("Already finalized") + # if none exists, create a default clock domain and drive it + if not fragment.clock_domains: + if not hasattr(self, "default_clk_name"): + raise NotImplementedError("No default clock and no clock domain defined") + crg = CRG(self.request(self.default_clk_name)) + fragment += crg.get_fragment() + self.do_finalize(fragment, *args, **kwargs) + self.finalized = True + + def do_finalize(self, fragment, *args, **kwargs): + """overload this and e.g. add_platform_command()'s after the modules had their say""" + if hasattr(self, "default_clk_period"): + try: + self.add_period_constraint(self.lookup_request(self.default_clk_name), self.default_clk_period) + except ConstraintError: + pass + + def add_source(self, filename, language=None): + if language is None: + language = tools.language_by_filename(filename) + if language is None: + language = "verilog" # default to Verilog + filename = os.path.abspath(filename) + self.sources.add((filename, language)) + + def add_sources(self, path, *filenames, language=None): + for f in filenames: + self.add_source(os.path.join(path, f), language) + + def add_source_dir(self, path, recursive=True): + dir_files = [] + if recursive: + for root, dirs, files in os.walk(path): + for filename in files: + dir_files.append(os.path.join(root, filename)) + else: + for item in os.listdir(path): + if os.path.isfile(os.path.join(path, item)): + dir_files.append(os.path.join(path, item)) + for filename in dir_files: + language = tools.language_by_filename(filename) + if language is not None: + self.add_source(filename, language) + + def add_verilog_include_path(self, path): + self.verilog_include_paths.add(os.path.abspath(path)) + + def resolve_signals(self, vns): + # resolve signal names in constraints + sc = self.constraint_manager.get_sig_constraints() + named_sc = [(vns.get_name(sig), pins, others, resource) for sig, pins, others, resource in sc] + # resolve signal names in platform commands + pc = self.constraint_manager.get_platform_commands() + named_pc = [] + for template, args in pc: + name_dict = dict((k, vns.get_name(sig)) for k, sig in args.items()) + named_pc.append(template.format(**name_dict)) + return named_sc, named_pc + + def get_verilog(self, fragment, **kwargs): + return verilog.convert(fragment, self.constraint_manager.get_io_signals(), create_clock_domains=False, **kwargs) + + def get_edif(self, fragment, cell_library, vendor, device, **kwargs): + return edif.convert(fragment, self.constraint_manager.get_io_signals(), cell_library, vendor, device, **kwargs) + + def build(self, fragment): + raise NotImplementedError("GenericPlatform.build must be overloaded") + + def build_cmdline(self, *args, **kwargs): + arg = sys.argv[1:] + if len(arg) % 2: + print("Missing value for option: "+sys.argv[-1]) + sys.exit(1) + argdict = dict((k, autotype(v)) for k, v in zip(*[iter(arg)]*2)) + kwargs.update(argdict) + self.build(*args, **kwargs) + + def create_programmer(self): + raise NotImplementedError diff --git a/mibuild/generic_programmer.py b/mibuild/generic_programmer.py index da3b0c26..9285112a 100644 --- a/mibuild/generic_programmer.py +++ b/mibuild/generic_programmer.py @@ -1,30 +1,30 @@ import os class GenericProgrammer: - def __init__(self, flash_proxy_basename=None): - self.flash_proxy_basename = flash_proxy_basename - self.flash_proxy_dirs = [ - "~/.migen", "/usr/local/share/migen", "/usr/share/migen", - "~/.mlabs", "/usr/local/share/mlabs", "/usr/share/mlabs"] + def __init__(self, flash_proxy_basename=None): + self.flash_proxy_basename = flash_proxy_basename + self.flash_proxy_dirs = [ + "~/.migen", "/usr/local/share/migen", "/usr/share/migen", + "~/.mlabs", "/usr/local/share/mlabs", "/usr/share/mlabs"] - def set_flash_proxy_dir(self, flash_proxy_dir): - if flash_proxy_dir is not None: - self.flash_proxy_dirs = [flash_proxy_dir] + def set_flash_proxy_dir(self, flash_proxy_dir): + if flash_proxy_dir is not None: + self.flash_proxy_dirs = [flash_proxy_dir] - def find_flash_proxy(self): - for d in self.flash_proxy_dirs: - fulldir = os.path.abspath(os.path.expanduser(d)) - fullname = os.path.join(fulldir, self.flash_proxy_basename) - if os.path.exists(fullname): - return fullname - raise OSError("Failed to find flash proxy bitstream") + def find_flash_proxy(self): + for d in self.flash_proxy_dirs: + fulldir = os.path.abspath(os.path.expanduser(d)) + fullname = os.path.join(fulldir, self.flash_proxy_basename) + if os.path.exists(fullname): + return fullname + raise OSError("Failed to find flash proxy bitstream") - # must be overloaded by specific programmer - def load_bitstream(self, bitstream_file): - raise NotImplementedError + # must be overloaded by specific programmer + def load_bitstream(self, bitstream_file): + raise NotImplementedError - # must be overloaded by specific programmer - def flash(self, address, data_file): - raise NotImplementedError + # must be overloaded by specific programmer + def flash(self, address, data_file): + raise NotImplementedError diff --git a/mibuild/lattice/common.py b/mibuild/lattice/common.py index 0cf8a07f..39bf3c63 100644 --- a/mibuild/lattice/common.py +++ b/mibuild/lattice/common.py @@ -4,34 +4,34 @@ from migen.genlib.io import * from migen.genlib.resetsync import AsyncResetSynchronizer class LatticeAsyncResetSynchronizerImpl(Module): - def __init__(self, cd, async_reset): - rst1 = Signal() - self.specials += [ - Instance("FD1S3BX", i_D=0, i_PD=async_reset, - i_CK=cd.clk, o_Q=rst1), - Instance("FD1S3BX", i_D=rst1, i_PD=async_reset, - i_CK=cd.clk, o_Q=cd.rst) - ] + def __init__(self, cd, async_reset): + rst1 = Signal() + self.specials += [ + Instance("FD1S3BX", i_D=0, i_PD=async_reset, + i_CK=cd.clk, o_Q=rst1), + Instance("FD1S3BX", i_D=rst1, i_PD=async_reset, + i_CK=cd.clk, o_Q=cd.rst) + ] class LatticeAsyncResetSynchronizer: - @staticmethod - def lower(dr): - return LatticeAsyncResetSynchronizerImpl(dr.cd, dr.async_reset) + @staticmethod + def lower(dr): + return LatticeAsyncResetSynchronizerImpl(dr.cd, dr.async_reset) class LatticeDDROutputImpl(Module): - def __init__(self, i1, i2, o, clk): - self.specials += Instance("ODDRXD1", - synthesis_directive="ODDRAPPS=\"SCLK_ALIGNED\"", - i_SCLK=clk, - i_DA=i1, i_DB=i2, o_Q=o, - ) + def __init__(self, i1, i2, o, clk): + self.specials += Instance("ODDRXD1", + synthesis_directive="ODDRAPPS=\"SCLK_ALIGNED\"", + i_SCLK=clk, + i_DA=i1, i_DB=i2, o_Q=o, + ) class LatticeDDROutput: - @staticmethod - def lower(dr): - return LatticeDDROutputImpl(dr.i1, dr.i2, dr.o, dr.clk) + @staticmethod + def lower(dr): + return LatticeDDROutputImpl(dr.i1, dr.i2, dr.o, dr.clk) lattice_special_overrides = { - AsyncResetSynchronizer: LatticeAsyncResetSynchronizer, - DDROutput: LatticeDDROutput + AsyncResetSynchronizer: LatticeAsyncResetSynchronizer, + DDROutput: LatticeDDROutput } diff --git a/mibuild/lattice/diamond.py b/mibuild/lattice/diamond.py index b04f3154..2217ef5e 100644 --- a/mibuild/lattice/diamond.py +++ b/mibuild/lattice/diamond.py @@ -10,87 +10,87 @@ from mibuild import tools from mibuild.lattice import common def _format_constraint(c): - if isinstance(c, Pins): - return ("LOCATE COMP ", " SITE " + "\"" + c.identifiers[0] + "\"") - elif isinstance(c, IOStandard): - return ("IOBUF PORT ", " IO_TYPE=" + c.name) - elif isinstance(c, Misc): - return c.misc + if isinstance(c, Pins): + return ("LOCATE COMP ", " SITE " + "\"" + c.identifiers[0] + "\"") + elif isinstance(c, IOStandard): + return ("IOBUF PORT ", " IO_TYPE=" + c.name) + elif isinstance(c, Misc): + return c.misc def _format_lpf(signame, pin, others, resname): - fmt_c = [_format_constraint(c) for c in ([Pins(pin)] + others)] - r = "" - for pre, suf in fmt_c: - r += pre + "\""+ signame +"\"" + suf + ";\n" - return r + fmt_c = [_format_constraint(c) for c in ([Pins(pin)] + others)] + r = "" + for pre, suf in fmt_c: + r += pre + "\""+ signame +"\"" + suf + ";\n" + return r def _build_lpf(named_sc, named_pc): - r = "BLOCK RESETPATHS;\n" - r += "BLOCK ASYNCPATHS;\n" - for sig, pins, others, resname in named_sc: - if len(pins) > 1: - for i, p in enumerate(pins): - r += _format_lpf(sig + "[" + str(i) + "]", p, others, resname) - else: - r += _format_lpf(sig, pins[0], others, resname) - if named_pc: - r += "\n" + "\n\n".join(named_pc) - return r + r = "BLOCK RESETPATHS;\n" + r += "BLOCK ASYNCPATHS;\n" + for sig, pins, others, resname in named_sc: + if len(pins) > 1: + for i, p in enumerate(pins): + r += _format_lpf(sig + "[" + str(i) + "]", p, others, resname) + else: + r += _format_lpf(sig, pins[0], others, resname) + if named_pc: + r += "\n" + "\n\n".join(named_pc) + return r def _build_files(device, sources, vincpaths, build_name): - tcl = [] - tcl.append("prj_project new -name \"%s\" -impl \"implementation\" -dev %s -synthesis \"synplify\"" %(build_name, device)) - for path in vincpaths: - tcl.append("prj_impl option {include path} {\"" + path.replace("\\", "/") + "\"}") - for filename, language in sources: - tcl.append("prj_src add \"" + filename.replace("\\", "/") + "\"") - tcl.append("prj_run Synthesis -impl implementation -forceOne") - tcl.append("prj_run Translate -impl implementation") - tcl.append("prj_run Map -impl implementation") - tcl.append("prj_run PAR -impl implementation") - tcl.append("prj_run Export -impl implementation -task Bitgen") - tools.write_to_file(build_name + ".tcl", "\n".join(tcl)) + tcl = [] + tcl.append("prj_project new -name \"%s\" -impl \"implementation\" -dev %s -synthesis \"synplify\"" %(build_name, device)) + for path in vincpaths: + tcl.append("prj_impl option {include path} {\"" + path.replace("\\", "/") + "\"}") + for filename, language in sources: + tcl.append("prj_src add \"" + filename.replace("\\", "/") + "\"") + tcl.append("prj_run Synthesis -impl implementation -forceOne") + tcl.append("prj_run Translate -impl implementation") + tcl.append("prj_run Map -impl implementation") + tcl.append("prj_run PAR -impl implementation") + tcl.append("prj_run Export -impl implementation -task Bitgen") + tools.write_to_file(build_name + ".tcl", "\n".join(tcl)) def _run_diamond(build_name, source, ver=None): - if sys.platform == "win32" or sys.platform == "cygwin": - build_script_contents = "REM Autogenerated by mibuild\n" - build_script_contents = "pnmainc " + build_name + ".tcl\n" - build_script_file = "build_" + build_name + ".bat" - tools.write_to_file(build_script_file, build_script_contents) - r = subprocess.call([build_script_file]) - shutil.copy(os.path.join("implementation", build_name + "_implementation.bit"), build_name + ".bit") - else: - raise NotImplementedError() - - if r != 0: - raise OSError("Subprocess failed") + if sys.platform == "win32" or sys.platform == "cygwin": + build_script_contents = "REM Autogenerated by mibuild\n" + build_script_contents = "pnmainc " + build_name + ".tcl\n" + build_script_file = "build_" + build_name + ".bat" + tools.write_to_file(build_script_file, build_script_contents) + r = subprocess.call([build_script_file]) + shutil.copy(os.path.join("implementation", build_name + "_implementation.bit"), build_name + ".bit") + else: + raise NotImplementedError() + + if r != 0: + raise OSError("Subprocess failed") class LatticeDiamondToolchain: - def build(self, platform, fragment, build_dir="build", build_name="top", - diamond_path="/opt/Diamond", run=True): - tools.mkdir_noerror(build_dir) - os.chdir(build_dir) + def build(self, platform, fragment, build_dir="build", build_name="top", + diamond_path="/opt/Diamond", run=True): + tools.mkdir_noerror(build_dir) + os.chdir(build_dir) - if not isinstance(fragment, _Fragment): - fragment = fragment.get_fragment() - platform.finalize(fragment) + if not isinstance(fragment, _Fragment): + fragment = fragment.get_fragment() + platform.finalize(fragment) - v_output = platform.get_verilog(fragment) - named_sc, named_pc = platform.resolve_signals(v_output.ns) - v_file = build_name + ".v" - v_output.write(v_file) - sources = platform.sources + [(v_file, "verilog")] - _build_files(platform.device, sources, platform.verilog_include_paths, build_name) + v_output = platform.get_verilog(fragment) + named_sc, named_pc = platform.resolve_signals(v_output.ns) + v_file = build_name + ".v" + v_output.write(v_file) + sources = platform.sources + [(v_file, "verilog")] + _build_files(platform.device, sources, platform.verilog_include_paths, build_name) - tools.write_to_file(build_name + ".lpf", _build_lpf(named_sc, named_pc)) + tools.write_to_file(build_name + ".lpf", _build_lpf(named_sc, named_pc)) - if run: - _run_diamond(build_name, diamond_path) + if run: + _run_diamond(build_name, diamond_path) - os.chdir("..") + os.chdir("..") - return v_output.ns + return v_output.ns - def add_period_constraint(self, platform, clk, period): - # TODO: handle differential clk - platform.add_platform_command("""FREQUENCY PORT "{clk}" {freq} MHz;""".format(freq=str(float(1/period)*1000), clk="{clk}"), clk=clk) + def add_period_constraint(self, platform, clk, period): + # TODO: handle differential clk + platform.add_platform_command("""FREQUENCY PORT "{clk}" {freq} MHz;""".format(freq=str(float(1/period)*1000), clk="{clk}"), clk=clk) diff --git a/mibuild/lattice/platform.py b/mibuild/lattice/platform.py index f3586daa..88961512 100644 --- a/mibuild/lattice/platform.py +++ b/mibuild/lattice/platform.py @@ -2,24 +2,24 @@ from mibuild.generic_platform import GenericPlatform from mibuild.lattice import common, diamond class LatticePlatform(GenericPlatform): - bitstream_ext = ".bit" + bitstream_ext = ".bit" - def __init__(self, *args, toolchain="diamond", **kwargs): - GenericPlatform.__init__(self, *args, **kwargs) - if toolchain == "diamond": - self.toolchain = diamond.LatticeDiamondToolchain() - else: - raise ValueError("Unknown toolchain") + def __init__(self, *args, toolchain="diamond", **kwargs): + GenericPlatform.__init__(self, *args, **kwargs) + if toolchain == "diamond": + self.toolchain = diamond.LatticeDiamondToolchain() + else: + raise ValueError("Unknown toolchain") - def get_verilog(self, *args, special_overrides=dict(), **kwargs): - so = dict(common.lattice_special_overrides) - so.update(special_overrides) - return GenericPlatform.get_verilog(self, *args, special_overrides=so, **kwargs) + def get_verilog(self, *args, special_overrides=dict(), **kwargs): + so = dict(common.lattice_special_overrides) + so.update(special_overrides) + return GenericPlatform.get_verilog(self, *args, special_overrides=so, **kwargs) - def build(self, *args, **kwargs): - return self.toolchain.build(self, *args, **kwargs) + def build(self, *args, **kwargs): + return self.toolchain.build(self, *args, **kwargs) - def add_period_constraint(self, clk, period): - if hasattr(clk, "p"): - clk = clk.p - self.toolchain.add_period_constraint(self, clk, period) + def add_period_constraint(self, clk, period): + if hasattr(clk, "p"): + clk = clk.p + self.toolchain.add_period_constraint(self, clk, period) diff --git a/mibuild/lattice/programmer.py b/mibuild/lattice/programmer.py index 726e5e12..ea6d119a 100644 --- a/mibuild/lattice/programmer.py +++ b/mibuild/lattice/programmer.py @@ -6,46 +6,46 @@ from mibuild import tools # XXX Lattice programmer need an .xcf file, will need clean up and support for more parameters _xcf_template = """ - + - - - JTAG - - - 1 - Lattice - LatticeECP3 - LFE3-35EA - {bitstream_file} - Fast Program - - - - SEQUENTIAL - ENTIRED CHAIN - No Override - TLR - TLR - - - - USB2 - FTUSB-0 - Dual RS232-HS A Location 0000 Serial A - - TRST ABSENT; - ISPEN ABSENT; - - + + + JTAG + + + 1 + Lattice + LatticeECP3 + LFE3-35EA + {bitstream_file} + Fast Program + + + + SEQUENTIAL + ENTIRED CHAIN + No Override + TLR + TLR + + + + USB2 + FTUSB-0 + Dual RS232-HS A Location 0000 Serial A + + TRST ABSENT; + ISPEN ABSENT; + + """ class LatticeProgrammer(GenericProgrammer): - needs_bitreverse = False + needs_bitreverse = False - def load_bitstream(self, bitstream_file): - xcf_file = bitstream_file.replace(".bit", ".xcf") - xcf_content = _xcf_template.format(bitstream_file=bitstream_file) - tools.write_to_file(xcf_file, xcf_content) - subprocess.call(["pgrcmd", "-infile", xcf_file]) + def load_bitstream(self, bitstream_file): + xcf_file = bitstream_file.replace(".bit", ".xcf") + xcf_content = _xcf_template.format(bitstream_file=bitstream_file) + tools.write_to_file(xcf_file, xcf_content) + subprocess.call(["pgrcmd", "-infile", xcf_file]) diff --git a/mibuild/platforms/apf27.py b/mibuild/platforms/apf27.py index fc2fe653..383e8daa 100644 --- a/mibuild/platforms/apf27.py +++ b/mibuild/platforms/apf27.py @@ -2,147 +2,147 @@ from mibuild.generic_platform import * from mibuild.xilinx import XilinxPlatform _ios = [ - ("clk0", 0, Pins("N9"), IOStandard("LVCMOS18")), - ("fpga_reset", 0, Pins("T9"), IOStandard("LVCMOS18"), Drive("8")), - ("fpga_initb", 0, Pins("T12"), IOStandard("LVCMOS18"), Drive("8")), - ("weim", 0, - Subsignal("cs4_dtack", Pins("R3"), IOStandard("LVCMOS18"), Drive("8")), - Subsignal("cs5n", Pins("P10"), IOStandard("LVCMOS18")), - Subsignal("eb0n", Pins("P9"), IOStandard("LVCMOS18")), - Subsignal("oen", Pins("R9"), IOStandard("LVCMOS18")), - Subsignal("data", - Pins("T5 T6 P7 N8 P12 T13 R13 T14 P5 N6 T3 T11 T4 R5 M10 T10"), - IOStandard("LVCMOS18"), Drive("8")), - Subsignal("addr", - Pins("N5 L7 M7 M8 L8 L9 L10 M11 P11 N11 N12 P13"), - IOStandard("LVCMOS18")) - ) + ("clk0", 0, Pins("N9"), IOStandard("LVCMOS18")), + ("fpga_reset", 0, Pins("T9"), IOStandard("LVCMOS18"), Drive("8")), + ("fpga_initb", 0, Pins("T12"), IOStandard("LVCMOS18"), Drive("8")), + ("weim", 0, + Subsignal("cs4_dtack", Pins("R3"), IOStandard("LVCMOS18"), Drive("8")), + Subsignal("cs5n", Pins("P10"), IOStandard("LVCMOS18")), + Subsignal("eb0n", Pins("P9"), IOStandard("LVCMOS18")), + Subsignal("oen", Pins("R9"), IOStandard("LVCMOS18")), + Subsignal("data", + Pins("T5 T6 P7 N8 P12 T13 R13 T14 P5 N6 T3 T11 T4 R5 M10 T10"), + IOStandard("LVCMOS18"), Drive("8")), + Subsignal("addr", + Pins("N5 L7 M7 M8 L8 L9 L10 M11 P11 N11 N12 P13"), + IOStandard("LVCMOS18")) + ) ] _connectors = [ ("J2", - "None", # no 0 pin - "None", # 1 +3v3 - "None", # 2 +3v3 - "None", # 3 GND - "None", # 4 GND - "None", # 5 DP USB_OTG_PHY +3V3 - "None", # 6 DM USB_OTG_PHY +3V3 - "None", # 7 VBUS USB_OTG_ PHY +3V3 - "None", # 8 PSW_N USB_OTG_PHY +3V3 - "None", # 9 ID USB_OTG_PHY +3V3 - "None", # 10 FAULT USB_OTG_PHY +3V3 - "None", # 11 RXP Ethernet_PHY +3V3 - "None", # 12 RXN Ethernet_PHY +3V3 - "None", # 13 ETH_LINK Ethernet_PHY +2V8 - "None", # 14 PC_VS2 PC +2V8 PF13 - "None", # 15 PC_VS1 PC +2V8 PF14 - "None", # 16 PC_PWRON PC +2V8 PF16 - "None", # 17 PC_READY PC +2V8 PF17 - "None", # 18 PWM0 PWM0 +2V8 PE5 - "None", # 19 TOUT GPT +2V8 PC14 - "None", # 20 GND POWER - "None", # 21 VCC01 (IN) BANK1 SUPPLY VCCO1 - "C16", # 22 IO_L24P_1 FPGA_BANK1 VCC01 - "C15", # 23 IO_L24N_1 FPGA_BANK1 VCC01 - "D16", # 24 IO_L22_P1 FPGA_BANK1 VCC01 - "None", # 25 GND POWER - "B14", # 26 IO_L02N_0 FPGA_BANK0 VCCO0 - "B15", # 27 IO_L02P_0 FPGA_BANK0 - "A13", # 28 IO_L04N_0 FPGA_BANK0 - "A14", # 29 IO_L04P_0 FPGA_BANK0 VCCO0 - "D11", # 30 IO_L03N_0 FPGA_BANK0 VCCO0 - "C12", # 31 IO_L03P_0 FPGA_BANK0 VCCO0 - "A10", # 32 IO_L08N_0 FPGA_BANK0 VCCO0 - "B10", # 33 IO_L08P_0 FPGA_BANK0 VCCO0 - "A9", # 34 IO_L10N_0 / GLCK7 FPGA_BANK0 VCCO0 - "C9", # 35 IO_L10P_0 / GCLK6 FPGA_BANK0 VCCO0 - "B8", # 36 IO_L12N_0 / GCLK11 FPGA_BANK0 VCCO0 - "A8", # 37 IO_L12P_0 / GCLK10 FPGA_BANK0 VCCO0 - "B6", # 38 IO_L15N_0 FPGA_BANK0 VCCO0 - "A6", # 39 IO_L15P_0 FPGA_BANK0 VCCO0 - "B4", # 40 IO_L18N_0 FPGA_BANK0 VCCO0 - "A4", # 41 IO_L18P_0 FPGA_BANK0 VCCO0 - "None", # 42 GND POWER - "N3", # 43 IO_L24P_3 FPGA_BANK3 VCCO3 - "R1", # 44 IO_L23P_3 FPGA_BANK3 VCCO3 - "P1", # 45 IO_L22N_3 FPGA_BANK3 VCCO3 - "N1", # 46 IO_L20N_3 FPGA_BANK3 VCCO3 - "M1", # 47 IO_L20P_3 FPGA_BANK3 VCCO3 - "H3", # 48 IO_L12P_3 FPGA_BANK3 VCCO3 - "K1", # 49 IO_L15N_3 FPGA_BANK3 VCCO3 - "J1", # 50 IO_L14N_3 FPGA_BANK3 VCCO3 - "H1", # 51 IO_L11N_3 FPGA_BANK3 VCCO3 - "G1", # 52 IO_L08N_3 FPGA_BANK3 VCCO3 - "F1", # 53 IO_L08P_3 FPGA_BANK3 VCCO3 - "E1", # 54 IO_L03N_3 FPGA_BANK3 VCCO3 - "D1", # 55 IO_LO3P_3 FPGA_BANK3 VCCO3 - "C1", # 56 IO_L01N_3 FPGA_BANK3 VCCO3 - "None", # 57 GND POWER - "None", # 58 TRSTN JTAG +2V8 - "None", # 59 TDI JTAG +2V8 - "None", # 60 TCK JTAG +2V8 - "None", # 61 TDO JTAG +2V8 - "None", # 62 TMS JTAG +2V8 - "None", # 63 GND POWER - "C2", # 64 IO_L01P_3 FPGA_BANK3 VCCO3 - "D3", # 65 IO_L02N_3 FPGA_BANK3 VCCO3 - "D4", # 66 IO_L02P_3 FPGA_BANK3 VCCO3 - "F4", # 67 IP_LO4N_3 FPGA_BANK3 VCCO3 - "G2", # 68 IO_L11P_3 FPGA_BANK3 VCCO3 - "J2", # 69 IO_L14P_3 FPGA_BANK3 VCCO3 - "K3", # 70 IO_L15P_3 FPGA_BANK3 VCCO3 - "J3", # 71 IO_L12N_3 FPGA_BANK3 VCCO3 - "N2", # 72 IO_L22P_3 FPGA_BANK3 VCCO3 - "P2", # 73 IO_L23N_3 FPGA_BANK3 VCCO3 - "M4", # 74 IO_L24N_3 FPGA_BANK3 VCCO3 - "L6", # 75 IP_L25N_3 FPGA_BANK3 VCCO3 - "None", # 76 VCCO3 (IN) BANK3 SUPPLY VCCO3 (3.3Vmax) - "None", # 77 VCCO3 (IN) BANK3 SUPPLY VCCO3 (3.3Vmax) - "A3", # 78 IO_L19P_0 FPGA_BANK0 VCCO0 - "B3", # 79 IO_L19N_0 FPGA_BANK0 VCCO0 - "A5", # 80 IO_L17P_0 FPGA_BANK0 VCCO0 - "C5", # 81 IO_L17N_0 FPGA_BANK0 VCCO0 - "D7", # 82 IO_L16P_0 FPGA_BANK0 VCCO0 - "C6", # 83 IO_L16N_0 FPGA_BANK0 VCCO0 - "C8", # 84 IO_L11P_0 / GCLK8 FPGA_BANK0 VCCO0 - "D8", # 85 IO_L11N_0 / GCLK9 FPGA_BANK0 VCCO0 - "C10", # 86 IO_L09P_0 / GCLK4 FPGA_BANK0 VCCO0 - "D9", # 87 IO_L09N_0 / GCLK5 FPGA_BANK0 VCCO0 - "C11", # 88 IO_L07P_0 FPGA_BANK0 VCCO0 - "A11", # 89 IO_L07N_0 FPGA_BANK0 VCCO0 - "D13", # 90 IO_L01P_0 FPGA_BANK0 VCCO0 - "C13", # 91 IO_L01N_0 FPGA_BANK0 VCCO0 - "None", # 92 VCCO0 (IN) BANK0 SUPPLY VCCO0 (3.3Vmax) - "None", # 93 VCCO0 (IN) BANK0 SUPPLY VCCO0 (3.3Vmax) - "None", # 94 GND POWER VCCO0 A13 - "D15", # 95 IO_L22N_1 FPGA_BANK1 VCC01 - "E13", # 96 IO_L23P_1 FPGA_BANK1 VCC01 - "D14", # 97 IO_L23N_1 FPGA_BANK1 VCC01 - "E14", # 98 IO_L20P_1 FPGA_BANK1 VCC01 - "F13", # 99 IO_L20N_1 FPGA_BANK1 VCC01 - "None", # 100 GND POWER (3.3Vmax) - "None", # 101 USR_RESETN (open CONFIG Pos PC15 +2V8 drain with pullup) - "None", # 102 TIN GPT +2V8 - "None", # 103 EXTAL_26M CONFIG +2V5 - "None", # 104 RX3 RS232_3 RS232 - "None", # 105 TX3 RS232_3 RS232 - "None", # 106 RX1 RS232_1 RS232 - "None", # 107 TX1 RS232_1 RS232 - "None", # 108 BOOT CONFIG +2V8 - "None", # 109 TXN Ethernet_PHY +3V3 - "None", # 110 TXP Ethernet_PHY +3V3 - "None", # 111 ETH_ACTIVITY Ethernet_PHY +2V8 - "None", # 112 USBH2_NXT USB_HOST2 +2V5 PA3 - "None", # 113 USBH2_DIR USB_HOST2 +2V5 PA1 - "None", # 114 USBH2_DATA7 USB_HOST2 +2V5 PA2 - "None", # 115 USBH2_STP USB_HOST2 +2V5 PA4 - "None") # 116 USBH2_CLK USB_HOST2 +2V5 PA0 + "None", # no 0 pin + "None", # 1 +3v3 + "None", # 2 +3v3 + "None", # 3 GND + "None", # 4 GND + "None", # 5 DP USB_OTG_PHY +3V3 + "None", # 6 DM USB_OTG_PHY +3V3 + "None", # 7 VBUS USB_OTG_ PHY +3V3 + "None", # 8 PSW_N USB_OTG_PHY +3V3 + "None", # 9 ID USB_OTG_PHY +3V3 + "None", # 10 FAULT USB_OTG_PHY +3V3 + "None", # 11 RXP Ethernet_PHY +3V3 + "None", # 12 RXN Ethernet_PHY +3V3 + "None", # 13 ETH_LINK Ethernet_PHY +2V8 + "None", # 14 PC_VS2 PC +2V8 PF13 + "None", # 15 PC_VS1 PC +2V8 PF14 + "None", # 16 PC_PWRON PC +2V8 PF16 + "None", # 17 PC_READY PC +2V8 PF17 + "None", # 18 PWM0 PWM0 +2V8 PE5 + "None", # 19 TOUT GPT +2V8 PC14 + "None", # 20 GND POWER + "None", # 21 VCC01 (IN) BANK1 SUPPLY VCCO1 + "C16", # 22 IO_L24P_1 FPGA_BANK1 VCC01 + "C15", # 23 IO_L24N_1 FPGA_BANK1 VCC01 + "D16", # 24 IO_L22_P1 FPGA_BANK1 VCC01 + "None", # 25 GND POWER + "B14", # 26 IO_L02N_0 FPGA_BANK0 VCCO0 + "B15", # 27 IO_L02P_0 FPGA_BANK0 + "A13", # 28 IO_L04N_0 FPGA_BANK0 + "A14", # 29 IO_L04P_0 FPGA_BANK0 VCCO0 + "D11", # 30 IO_L03N_0 FPGA_BANK0 VCCO0 + "C12", # 31 IO_L03P_0 FPGA_BANK0 VCCO0 + "A10", # 32 IO_L08N_0 FPGA_BANK0 VCCO0 + "B10", # 33 IO_L08P_0 FPGA_BANK0 VCCO0 + "A9", # 34 IO_L10N_0 / GLCK7 FPGA_BANK0 VCCO0 + "C9", # 35 IO_L10P_0 / GCLK6 FPGA_BANK0 VCCO0 + "B8", # 36 IO_L12N_0 / GCLK11 FPGA_BANK0 VCCO0 + "A8", # 37 IO_L12P_0 / GCLK10 FPGA_BANK0 VCCO0 + "B6", # 38 IO_L15N_0 FPGA_BANK0 VCCO0 + "A6", # 39 IO_L15P_0 FPGA_BANK0 VCCO0 + "B4", # 40 IO_L18N_0 FPGA_BANK0 VCCO0 + "A4", # 41 IO_L18P_0 FPGA_BANK0 VCCO0 + "None", # 42 GND POWER + "N3", # 43 IO_L24P_3 FPGA_BANK3 VCCO3 + "R1", # 44 IO_L23P_3 FPGA_BANK3 VCCO3 + "P1", # 45 IO_L22N_3 FPGA_BANK3 VCCO3 + "N1", # 46 IO_L20N_3 FPGA_BANK3 VCCO3 + "M1", # 47 IO_L20P_3 FPGA_BANK3 VCCO3 + "H3", # 48 IO_L12P_3 FPGA_BANK3 VCCO3 + "K1", # 49 IO_L15N_3 FPGA_BANK3 VCCO3 + "J1", # 50 IO_L14N_3 FPGA_BANK3 VCCO3 + "H1", # 51 IO_L11N_3 FPGA_BANK3 VCCO3 + "G1", # 52 IO_L08N_3 FPGA_BANK3 VCCO3 + "F1", # 53 IO_L08P_3 FPGA_BANK3 VCCO3 + "E1", # 54 IO_L03N_3 FPGA_BANK3 VCCO3 + "D1", # 55 IO_LO3P_3 FPGA_BANK3 VCCO3 + "C1", # 56 IO_L01N_3 FPGA_BANK3 VCCO3 + "None", # 57 GND POWER + "None", # 58 TRSTN JTAG +2V8 + "None", # 59 TDI JTAG +2V8 + "None", # 60 TCK JTAG +2V8 + "None", # 61 TDO JTAG +2V8 + "None", # 62 TMS JTAG +2V8 + "None", # 63 GND POWER + "C2", # 64 IO_L01P_3 FPGA_BANK3 VCCO3 + "D3", # 65 IO_L02N_3 FPGA_BANK3 VCCO3 + "D4", # 66 IO_L02P_3 FPGA_BANK3 VCCO3 + "F4", # 67 IP_LO4N_3 FPGA_BANK3 VCCO3 + "G2", # 68 IO_L11P_3 FPGA_BANK3 VCCO3 + "J2", # 69 IO_L14P_3 FPGA_BANK3 VCCO3 + "K3", # 70 IO_L15P_3 FPGA_BANK3 VCCO3 + "J3", # 71 IO_L12N_3 FPGA_BANK3 VCCO3 + "N2", # 72 IO_L22P_3 FPGA_BANK3 VCCO3 + "P2", # 73 IO_L23N_3 FPGA_BANK3 VCCO3 + "M4", # 74 IO_L24N_3 FPGA_BANK3 VCCO3 + "L6", # 75 IP_L25N_3 FPGA_BANK3 VCCO3 + "None", # 76 VCCO3 (IN) BANK3 SUPPLY VCCO3 (3.3Vmax) + "None", # 77 VCCO3 (IN) BANK3 SUPPLY VCCO3 (3.3Vmax) + "A3", # 78 IO_L19P_0 FPGA_BANK0 VCCO0 + "B3", # 79 IO_L19N_0 FPGA_BANK0 VCCO0 + "A5", # 80 IO_L17P_0 FPGA_BANK0 VCCO0 + "C5", # 81 IO_L17N_0 FPGA_BANK0 VCCO0 + "D7", # 82 IO_L16P_0 FPGA_BANK0 VCCO0 + "C6", # 83 IO_L16N_0 FPGA_BANK0 VCCO0 + "C8", # 84 IO_L11P_0 / GCLK8 FPGA_BANK0 VCCO0 + "D8", # 85 IO_L11N_0 / GCLK9 FPGA_BANK0 VCCO0 + "C10", # 86 IO_L09P_0 / GCLK4 FPGA_BANK0 VCCO0 + "D9", # 87 IO_L09N_0 / GCLK5 FPGA_BANK0 VCCO0 + "C11", # 88 IO_L07P_0 FPGA_BANK0 VCCO0 + "A11", # 89 IO_L07N_0 FPGA_BANK0 VCCO0 + "D13", # 90 IO_L01P_0 FPGA_BANK0 VCCO0 + "C13", # 91 IO_L01N_0 FPGA_BANK0 VCCO0 + "None", # 92 VCCO0 (IN) BANK0 SUPPLY VCCO0 (3.3Vmax) + "None", # 93 VCCO0 (IN) BANK0 SUPPLY VCCO0 (3.3Vmax) + "None", # 94 GND POWER VCCO0 A13 + "D15", # 95 IO_L22N_1 FPGA_BANK1 VCC01 + "E13", # 96 IO_L23P_1 FPGA_BANK1 VCC01 + "D14", # 97 IO_L23N_1 FPGA_BANK1 VCC01 + "E14", # 98 IO_L20P_1 FPGA_BANK1 VCC01 + "F13", # 99 IO_L20N_1 FPGA_BANK1 VCC01 + "None", # 100 GND POWER (3.3Vmax) + "None", # 101 USR_RESETN (open CONFIG Pos PC15 +2V8 drain with pullup) + "None", # 102 TIN GPT +2V8 + "None", # 103 EXTAL_26M CONFIG +2V5 + "None", # 104 RX3 RS232_3 RS232 + "None", # 105 TX3 RS232_3 RS232 + "None", # 106 RX1 RS232_1 RS232 + "None", # 107 TX1 RS232_1 RS232 + "None", # 108 BOOT CONFIG +2V8 + "None", # 109 TXN Ethernet_PHY +3V3 + "None", # 110 TXP Ethernet_PHY +3V3 + "None", # 111 ETH_ACTIVITY Ethernet_PHY +2V8 + "None", # 112 USBH2_NXT USB_HOST2 +2V5 PA3 + "None", # 113 USBH2_DIR USB_HOST2 +2V5 PA1 + "None", # 114 USBH2_DATA7 USB_HOST2 +2V5 PA2 + "None", # 115 USBH2_STP USB_HOST2 +2V5 PA4 + "None") # 116 USBH2_CLK USB_HOST2 +2V5 PA0 ] class Platform(XilinxPlatform): - default_clk_name = "clk0" - default_clk_period = 10 + default_clk_name = "clk0" + default_clk_period = 10 - def __init__(self): - XilinxPlatform.__init__(self, "xc3s200a-ft256-4", _ios, _connectors) + def __init__(self): + XilinxPlatform.__init__(self, "xc3s200a-ft256-4", _ios, _connectors) diff --git a/mibuild/platforms/apf51.py b/mibuild/platforms/apf51.py index d83dd16e..26823882 100644 --- a/mibuild/platforms/apf51.py +++ b/mibuild/platforms/apf51.py @@ -2,174 +2,174 @@ from mibuild.generic_platform import * from mibuild.xilinx import XilinxPlatform _ios = [ - ("clk3", 0, Pins("N8"), IOStandard("LVCMOS33")), - ("clko", 0, Pins("N7"), IOStandard("LVCMOS33")), - ("fpga_initb", 0, Pins("P3"), IOStandard("LVCMOS33")), - ("fpga_program", 0, Pins("R2"), IOStandard("LVCMOS33")), - ("eim", 0, - Subsignal("bclk", Pins("N12")), - Subsignal("eb1", Pins("P13")), - Subsignal("cs1", Pins("R11")), - Subsignal("cs2", Pins("N9")), - Subsignal("lba", Pins("R9")), - Subsignal("eb0", Pins("P7")), - Subsignal("oe", Pins("R7")), - Subsignal("rw", Pins("R6")), - Subsignal("dtack", Pins("N4")), - Subsignal("wait", Pins("R4")), - Subsignal("da", Pins("N6 L5 L6 R5 P5 N11 M11 P11 L8 K8 M8 M10 L9 R10 N5 M5")), - IOStandard("LVCMOS33") - ) + ("clk3", 0, Pins("N8"), IOStandard("LVCMOS33")), + ("clko", 0, Pins("N7"), IOStandard("LVCMOS33")), + ("fpga_initb", 0, Pins("P3"), IOStandard("LVCMOS33")), + ("fpga_program", 0, Pins("R2"), IOStandard("LVCMOS33")), + ("eim", 0, + Subsignal("bclk", Pins("N12")), + Subsignal("eb1", Pins("P13")), + Subsignal("cs1", Pins("R11")), + Subsignal("cs2", Pins("N9")), + Subsignal("lba", Pins("R9")), + Subsignal("eb0", Pins("P7")), + Subsignal("oe", Pins("R7")), + Subsignal("rw", Pins("R6")), + Subsignal("dtack", Pins("N4")), + Subsignal("wait", Pins("R4")), + Subsignal("da", Pins("N6 L5 L6 R5 P5 N11 M11 P11 L8 K8 M8 M10 L9 R10 N5 M5")), + IOStandard("LVCMOS33") + ) ] _connectors = [ - ("J2", - "None", # No 0 pin - "None", # 1 FPGA Bank1 power - "None", # 2 FPGA Bank1 power - "None", # 3 GND - "B14", # 4 IO_L1P_A25_1 - "B15", # 5 IO_L1N_A24_VREF_1 - "C14", # 6 IO_L33P_A15_M1A10_1 - "C15", # 7 IO_L33N_A14_M1A4_1 - "D13", # 8 IO_L35P_A11_M1A7_1 - "D15", # 9 IO_L35N_A10_M1A2_1 - "E14", # 10 IO_L37P_A7_M1A0_1 - "E15", # 11 IO_L37N_A6_M1A1_1 - "None", # 12 GND - "F13", # 13 IO_L39P_M1A3_1 - "F15", # 14 IO_L39N_M1ODT_1 - "G14", # 15 IO_L41P_GCLK9_IRDY1_M1RASN_1 - "G15", # 16 IO_L41N_GCLK8_M1CASN_1 - "H13", # 17 IO_L42P_GCLK7_M1UDM_1 - "H15", # 18 IO_L42N_GCLK6_TRDY1_M1LDM - "J14", # 19 IO_L43P_GCLK5_M1DQ4_1 - "J15", # 20 IO_L43N_GCLK4_M1DQ5_1 - "K13", # 21 IO_L44P_A3_M1DQ6_1 - "K15", # 22 IO_L44N_A2_M1DQ7_1 - "L14", # 23 IO_L45P_A1_M1LDQS_1 - "L15", # 24 IO_L45N_A0_M1LDQSN_1 - "None", # 25 GND - "E2", # 26 IO_L52P_M3A8_3 - "E1", # 27 IO_L52N_M3A9_3 - "D3", # 28 IO_L54P_M3RESET_3 - "D1", # 29 IO_L54N_M3A11_3 - "F3", # 30 IO_L46P_M3CLK_3 - "F1", # 31 IO_L46N_M3CLKN_3 - "G2", # 32 IO_L44P_GCLK21_M3A5_3 - "G1", # 33 IO_L44N_GCLK20_M3A6_3 - "H3", # 34 IO_L42P_GCLK25_TRDY2_M3UDM_3 - "H1", # 35 IO_L42N_GCLK24_M3LDM_3 - "K3", # 36 IO_L40P_M3DQ6_3 - "K1", # 37 IO_L40N_M3DQ7_3 - "None", # 38 GND - "None", # 39 GPIO4_16 - "None", # 40 GPIO4_17 - "None", # 41 BOOT_MODE0 - "None", # 42 AUD5_RXFS - "None", # 43 AUD5_RXC - "None", # 44 GND - "None", # 45 AUD5_RXD - "None", # 46 AUD5_TXC - "None", # 47 AUD5_TXFS - "None", # 48 GND - "None", # 49 SPI2_SCLK_GPT_CMPOUT3 - "None", # 50 SPI2_MISO - "None", # 51 SPI2_MOSI - "None", # 52 SPI2_SS1 - "None", # 53 SPI2_SS2 - "None", # 54 SPI2_SS3 - "None", # 55 SPI2_RDY - "None", # 56 OWIRE - "None", # 57 GND - "None", # 58 SPI1_SCLK - "None", # 59 SPI1_MISO - "None", # 60 SPI1_MOSI - "None", # 61 SPI1_SS0 - "None", # 62 SPI1_SS1 - "None", # 63 SPI1_RDY - "None", # 64 RESET# - "None", # 65 VIO_H2 - "None", # 66 PMIC_GPIO6 - "None", # 67 TOUCH_X+ - "None", # 68 TOUCH_X- - "None", # 69 TOUCH_Y+ - "None", # 70 TOUCH_Y- - "None", # 71 AUXADCIN4 - "None", # 72 AUXADCIN3 - "None", # 73 AUXADCIN2 - "None", # 74 AUXADCIN1 - "None", # 75 PMIC_GPIO7 - "None", # 76 +1v8 - "None", # 77 RESERVED - "None", # 78 UART3_TXD - "None", # 79 UART_3_RXD - "None", # 80 UART2_TXD - "None", # 81 UART2_RXD - "None", # 82 UART2_RTS_KEY_COL7 - "None", # 83 UART2_CTS_KEY_COL6 - "None", # 84 UART1_TXD - "None", # 85 UART1_RXD - "None", # 86 UART1_RTS - "None", # 87 UART1_CTS - "None", # 88 GND - "None", # 89 AUD3_TXD - "None", # 90 AUD3_RXD - "None", # 91 AUD3_FS - "None", # 92 AUD3_CK - "None", # 93 GND - "None", # 94 AUD6_TXFS_KEY_ROW7 - "None", # 95 AUD6_TXC_KEY_ROW6 - "None", # 96 AUD6_RXD_KEY_ROW5 - "None", # 97 AUD6_TXD_KEY_ROW4 - "None", # 98 I2C2_SDA_UART3_CTS - "None", # 99 I2C2_SCL_UART3_RTS - "None", # 100 BOOT_MODE1 - "None", # 101 PWM2 - "None", # 102 PWM1 - "None", # 103 GND - "L1", # 104 IO_L39N_M3LDQSN_3 - "L2", # 105 IO_L39P_M3LDQS_3 - "J1", # 106 IO_L41N_GCLK26_M3DQ5_3 - "J2", # 107 IO_L41P_GCLK27_M3DQ4_3 - "J3", # 108 IO_L43N_GCLK22_IRDY2_M3CASN_3 - "K4", # 109 IO_L43P_GCLK23_M3RASN_3 - "J4", # 110 IO_L45N_M3ODT_3 - "K5", # 111 IO_L45P_M3A3_3 - "C1", # 112 IO_L83N_VREF_3 - "C2", # 113 IO_L83P_3 - "E3", # 114 IO_L53N_M3A12_3 - "D4", # 115 IO_L53P_M3CKE_3 - "None", # 116 GND - "P15", # 117 IO_L74N_DOUT_BUSY_1 - "P14", # 118 IO_L74P_AWAKE_1 - "N15", # 119 IO_L47N_LDC_M1DQ1_1 - "N14", # 120 IO_L47P_FWE_B_M1DQ0_1 - "M15", # 121 IO_L46N_FOE_B_M1DQ3_1 - "M13", # 122 IO_L46P_FCS_B_M1DQS2_1 - "L12", # 123 IO_L40N_GCLK10_M1A6_1 - "K12", # 124 IO_L40P_GCLK11_M1A5_1 - "K11", # 125 IO_L38N_A4_M1CLKN_1 - "K10", # 126 IO_L38P_A5_M1CLK_1 - "J13", # 127 IO_L36N_A8_M1BA1_1 - "J11", # 128 IO_L36P_A9_M1BA0_1 - "None", # 129 GND - "G13", # 130 IO_L34N_A12_M1BA2_1_NOTLX4 - "H12", # 131 IO_L34P_A13_M1WE_1_NOTLX4 - "H11", # 132 IO_L32N_A16_M1A9_1_NOTLX4 - "H10", # 133 IO_L32P_A17_M1A8_1_NOTLX4 - "F12", # 134 IO_L31N_A18_M1A12_1_NOTLX4 - "F11", # 135 IO_L31P_A19_M1CKE_1_NOTLX4 - "G12", # 136 IO_L30N_A20_M1A11_1_NOTLX4 - "G11", # 137 IO_L30P_A21_M1RESET_1_NOTLX4 - "None", # 138 GND - "None", # 139 FPGA_BANK3_POWER - "None") # 140 FPGA_BANK3_POWER + ("J2", + "None", # No 0 pin + "None", # 1 FPGA Bank1 power + "None", # 2 FPGA Bank1 power + "None", # 3 GND + "B14", # 4 IO_L1P_A25_1 + "B15", # 5 IO_L1N_A24_VREF_1 + "C14", # 6 IO_L33P_A15_M1A10_1 + "C15", # 7 IO_L33N_A14_M1A4_1 + "D13", # 8 IO_L35P_A11_M1A7_1 + "D15", # 9 IO_L35N_A10_M1A2_1 + "E14", # 10 IO_L37P_A7_M1A0_1 + "E15", # 11 IO_L37N_A6_M1A1_1 + "None", # 12 GND + "F13", # 13 IO_L39P_M1A3_1 + "F15", # 14 IO_L39N_M1ODT_1 + "G14", # 15 IO_L41P_GCLK9_IRDY1_M1RASN_1 + "G15", # 16 IO_L41N_GCLK8_M1CASN_1 + "H13", # 17 IO_L42P_GCLK7_M1UDM_1 + "H15", # 18 IO_L42N_GCLK6_TRDY1_M1LDM + "J14", # 19 IO_L43P_GCLK5_M1DQ4_1 + "J15", # 20 IO_L43N_GCLK4_M1DQ5_1 + "K13", # 21 IO_L44P_A3_M1DQ6_1 + "K15", # 22 IO_L44N_A2_M1DQ7_1 + "L14", # 23 IO_L45P_A1_M1LDQS_1 + "L15", # 24 IO_L45N_A0_M1LDQSN_1 + "None", # 25 GND + "E2", # 26 IO_L52P_M3A8_3 + "E1", # 27 IO_L52N_M3A9_3 + "D3", # 28 IO_L54P_M3RESET_3 + "D1", # 29 IO_L54N_M3A11_3 + "F3", # 30 IO_L46P_M3CLK_3 + "F1", # 31 IO_L46N_M3CLKN_3 + "G2", # 32 IO_L44P_GCLK21_M3A5_3 + "G1", # 33 IO_L44N_GCLK20_M3A6_3 + "H3", # 34 IO_L42P_GCLK25_TRDY2_M3UDM_3 + "H1", # 35 IO_L42N_GCLK24_M3LDM_3 + "K3", # 36 IO_L40P_M3DQ6_3 + "K1", # 37 IO_L40N_M3DQ7_3 + "None", # 38 GND + "None", # 39 GPIO4_16 + "None", # 40 GPIO4_17 + "None", # 41 BOOT_MODE0 + "None", # 42 AUD5_RXFS + "None", # 43 AUD5_RXC + "None", # 44 GND + "None", # 45 AUD5_RXD + "None", # 46 AUD5_TXC + "None", # 47 AUD5_TXFS + "None", # 48 GND + "None", # 49 SPI2_SCLK_GPT_CMPOUT3 + "None", # 50 SPI2_MISO + "None", # 51 SPI2_MOSI + "None", # 52 SPI2_SS1 + "None", # 53 SPI2_SS2 + "None", # 54 SPI2_SS3 + "None", # 55 SPI2_RDY + "None", # 56 OWIRE + "None", # 57 GND + "None", # 58 SPI1_SCLK + "None", # 59 SPI1_MISO + "None", # 60 SPI1_MOSI + "None", # 61 SPI1_SS0 + "None", # 62 SPI1_SS1 + "None", # 63 SPI1_RDY + "None", # 64 RESET# + "None", # 65 VIO_H2 + "None", # 66 PMIC_GPIO6 + "None", # 67 TOUCH_X+ + "None", # 68 TOUCH_X- + "None", # 69 TOUCH_Y+ + "None", # 70 TOUCH_Y- + "None", # 71 AUXADCIN4 + "None", # 72 AUXADCIN3 + "None", # 73 AUXADCIN2 + "None", # 74 AUXADCIN1 + "None", # 75 PMIC_GPIO7 + "None", # 76 +1v8 + "None", # 77 RESERVED + "None", # 78 UART3_TXD + "None", # 79 UART_3_RXD + "None", # 80 UART2_TXD + "None", # 81 UART2_RXD + "None", # 82 UART2_RTS_KEY_COL7 + "None", # 83 UART2_CTS_KEY_COL6 + "None", # 84 UART1_TXD + "None", # 85 UART1_RXD + "None", # 86 UART1_RTS + "None", # 87 UART1_CTS + "None", # 88 GND + "None", # 89 AUD3_TXD + "None", # 90 AUD3_RXD + "None", # 91 AUD3_FS + "None", # 92 AUD3_CK + "None", # 93 GND + "None", # 94 AUD6_TXFS_KEY_ROW7 + "None", # 95 AUD6_TXC_KEY_ROW6 + "None", # 96 AUD6_RXD_KEY_ROW5 + "None", # 97 AUD6_TXD_KEY_ROW4 + "None", # 98 I2C2_SDA_UART3_CTS + "None", # 99 I2C2_SCL_UART3_RTS + "None", # 100 BOOT_MODE1 + "None", # 101 PWM2 + "None", # 102 PWM1 + "None", # 103 GND + "L1", # 104 IO_L39N_M3LDQSN_3 + "L2", # 105 IO_L39P_M3LDQS_3 + "J1", # 106 IO_L41N_GCLK26_M3DQ5_3 + "J2", # 107 IO_L41P_GCLK27_M3DQ4_3 + "J3", # 108 IO_L43N_GCLK22_IRDY2_M3CASN_3 + "K4", # 109 IO_L43P_GCLK23_M3RASN_3 + "J4", # 110 IO_L45N_M3ODT_3 + "K5", # 111 IO_L45P_M3A3_3 + "C1", # 112 IO_L83N_VREF_3 + "C2", # 113 IO_L83P_3 + "E3", # 114 IO_L53N_M3A12_3 + "D4", # 115 IO_L53P_M3CKE_3 + "None", # 116 GND + "P15", # 117 IO_L74N_DOUT_BUSY_1 + "P14", # 118 IO_L74P_AWAKE_1 + "N15", # 119 IO_L47N_LDC_M1DQ1_1 + "N14", # 120 IO_L47P_FWE_B_M1DQ0_1 + "M15", # 121 IO_L46N_FOE_B_M1DQ3_1 + "M13", # 122 IO_L46P_FCS_B_M1DQS2_1 + "L12", # 123 IO_L40N_GCLK10_M1A6_1 + "K12", # 124 IO_L40P_GCLK11_M1A5_1 + "K11", # 125 IO_L38N_A4_M1CLKN_1 + "K10", # 126 IO_L38P_A5_M1CLK_1 + "J13", # 127 IO_L36N_A8_M1BA1_1 + "J11", # 128 IO_L36P_A9_M1BA0_1 + "None", # 129 GND + "G13", # 130 IO_L34N_A12_M1BA2_1_NOTLX4 + "H12", # 131 IO_L34P_A13_M1WE_1_NOTLX4 + "H11", # 132 IO_L32N_A16_M1A9_1_NOTLX4 + "H10", # 133 IO_L32P_A17_M1A8_1_NOTLX4 + "F12", # 134 IO_L31N_A18_M1A12_1_NOTLX4 + "F11", # 135 IO_L31P_A19_M1CKE_1_NOTLX4 + "G12", # 136 IO_L30N_A20_M1A11_1_NOTLX4 + "G11", # 137 IO_L30P_A21_M1RESET_1_NOTLX4 + "None", # 138 GND + "None", # 139 FPGA_BANK3_POWER + "None") # 140 FPGA_BANK3_POWER ] class Platform(XilinxPlatform): - default_clk_name = "clk3" - default_clk_period = 10.526 + default_clk_name = "clk3" + default_clk_period = 10.526 - def __init__(self): - XilinxPlatform.__init__(self, "xc6slx9-2csg225", _ios, _connectors) + def __init__(self): + XilinxPlatform.__init__(self, "xc6slx9-2csg225", _ios, _connectors) diff --git a/mibuild/platforms/de0nano.py b/mibuild/platforms/de0nano.py index c04987ea..f4d065a8 100644 --- a/mibuild/platforms/de0nano.py +++ b/mibuild/platforms/de0nano.py @@ -6,96 +6,96 @@ from mibuild.altera import AlteraPlatform from mibuild.altera.programmer import USBBlaster _io = [ - ("clk50", 0, Pins("R8"), IOStandard("3.3-V LVTTL")), + ("clk50", 0, Pins("R8"), IOStandard("3.3-V LVTTL")), - ("user_led", 0, Pins("A15"), IOStandard("3.3-V LVTTL")), - ("user_led", 1, Pins("A13"), IOStandard("3.3-V LVTTL")), - ("user_led", 2, Pins("B13"), IOStandard("3.3-V LVTTL")), - ("user_led", 3, Pins("A11"), IOStandard("3.3-V LVTTL")), - ("user_led", 4, Pins("D1"), IOStandard("3.3-V LVTTL")), - ("user_led", 5, Pins("F3"), IOStandard("3.3-V LVTTL")), - ("user_led", 6, Pins("B1"), IOStandard("3.3-V LVTTL")), - ("user_led", 7, Pins("L3"), IOStandard("3.3-V LVTTL")), + ("user_led", 0, Pins("A15"), IOStandard("3.3-V LVTTL")), + ("user_led", 1, Pins("A13"), IOStandard("3.3-V LVTTL")), + ("user_led", 2, Pins("B13"), IOStandard("3.3-V LVTTL")), + ("user_led", 3, Pins("A11"), IOStandard("3.3-V LVTTL")), + ("user_led", 4, Pins("D1"), IOStandard("3.3-V LVTTL")), + ("user_led", 5, Pins("F3"), IOStandard("3.3-V LVTTL")), + ("user_led", 6, Pins("B1"), IOStandard("3.3-V LVTTL")), + ("user_led", 7, Pins("L3"), IOStandard("3.3-V LVTTL")), - ("key", 0, Pins("J15"), IOStandard("3.3-V LVTTL")), - ("key", 1, Pins("E1"), IOStandard("3.3-V LVTTL")), + ("key", 0, Pins("J15"), IOStandard("3.3-V LVTTL")), + ("key", 1, Pins("E1"), IOStandard("3.3-V LVTTL")), - ("sw", 0, Pins("M1"), IOStandard("3.3-V LVTTL")), - ("sw", 1, Pins("T9"), IOStandard("3.3-V LVTTL")), - ("sw", 2, Pins("B9"), IOStandard("3.3-V LVTTL")), - ("sw", 3, Pins("M15"), IOStandard("3.3-V LVTTL")), + ("sw", 0, Pins("M1"), IOStandard("3.3-V LVTTL")), + ("sw", 1, Pins("T9"), IOStandard("3.3-V LVTTL")), + ("sw", 2, Pins("B9"), IOStandard("3.3-V LVTTL")), + ("sw", 3, Pins("M15"), IOStandard("3.3-V LVTTL")), - ("serial", 0, - Subsignal("tx", Pins("D3"), IOStandard("3.3-V LVTTL")), - Subsignal("rx", Pins("C3"), IOStandard("3.3-V LVTTL")) - ), + ("serial", 0, + Subsignal("tx", Pins("D3"), IOStandard("3.3-V LVTTL")), + Subsignal("rx", Pins("C3"), IOStandard("3.3-V LVTTL")) + ), - ("sdram_clock", 0, Pins("R4"), IOStandard("3.3-V LVTTL")), - ("sdram", 0, - Subsignal("a", Pins("P2 N5 N6 M8 P8 T7 N8 T6 R1 P1 N2 N1 L4")), - Subsignal("ba", Pins("M7 M6")), - Subsignal("cs_n", Pins("P6")), - Subsignal("cke", Pins("L7")), - Subsignal("ras_n", Pins("L2")), - Subsignal("cas_n", Pins("L1")), - Subsignal("we_n", Pins("C2")), - Subsignal("dq", Pins("G2 G1 L8 K5 K2 J2 J1 R7 T4 T2 T3 R3 R5 P3 N3 K1")), - Subsignal("dm", Pins("R6","T5")), - IOStandard("3.3-V LVTTL") - ), + ("sdram_clock", 0, Pins("R4"), IOStandard("3.3-V LVTTL")), + ("sdram", 0, + Subsignal("a", Pins("P2 N5 N6 M8 P8 T7 N8 T6 R1 P1 N2 N1 L4")), + Subsignal("ba", Pins("M7 M6")), + Subsignal("cs_n", Pins("P6")), + Subsignal("cke", Pins("L7")), + Subsignal("ras_n", Pins("L2")), + Subsignal("cas_n", Pins("L1")), + Subsignal("we_n", Pins("C2")), + Subsignal("dq", Pins("G2 G1 L8 K5 K2 J2 J1 R7 T4 T2 T3 R3 R5 P3 N3 K1")), + Subsignal("dm", Pins("R6","T5")), + IOStandard("3.3-V LVTTL") + ), - ("epcs", 0, - Subsignal("data0", Pins("H2")), - Subsignal("dclk", Pins("H1")), - Subsignal("ncs0", Pins("D2")), - Subsignal("asd0", Pins("C1")), - IOStandard("3.3-V LVTTL") - ), + ("epcs", 0, + Subsignal("data0", Pins("H2")), + Subsignal("dclk", Pins("H1")), + Subsignal("ncs0", Pins("D2")), + Subsignal("asd0", Pins("C1")), + IOStandard("3.3-V LVTTL") + ), - ("i2c", 0, - Subsignal("sclk", Pins("F2")), - Subsignal("sdat", Pins("F1")), - IOStandard("3.3-V LVTTL") - ), + ("i2c", 0, + Subsignal("sclk", Pins("F2")), + Subsignal("sdat", Pins("F1")), + IOStandard("3.3-V LVTTL") + ), - ("g_sensor", 0, - Subsignal("cs_n", Pins("G5")), - Subsignal("int", Pins("M2")), - IOStandard("3.3-V LVTTL") - ), + ("g_sensor", 0, + Subsignal("cs_n", Pins("G5")), + Subsignal("int", Pins("M2")), + IOStandard("3.3-V LVTTL") + ), - ("adc", 0, - Subsignal("cs_n", Pins("A10")), - Subsignal("saddr", Pins("B10")), - Subsignal("sclk", Pins("B14")), - Subsignal("sdat", Pins("A9")), - IOStandard("3.3-V LVTTL") - ), + ("adc", 0, + Subsignal("cs_n", Pins("A10")), + Subsignal("saddr", Pins("B10")), + Subsignal("sclk", Pins("B14")), + Subsignal("sdat", Pins("A9")), + IOStandard("3.3-V LVTTL") + ), - ("gpio_0", 0, - Pins("D3 C3 A2 A3 B3 B4 A4 B5 A5 D5 B6 A6 B7 D6 A7 C6", - "C8 E6 E7 D8 E8 F8 F9 E9 C9 D9 E11 E10 C11 B11 A12 D11", - "D12 B12"), - IOStandard("3.3-V LVTTL") - ), - ("gpio_1", 0, - Pins("F13 T15 T14 T13 R13 T12 R12 T11 T10 R11 P11 R10 N12 P9 N9 N11", - "L16 K16 R16 L15 P15 P16 R14 N16 N15 P14 L14 N14 M10 L13 J16 K15", - "J13 J14"), - IOStandard("3.3-V LVTTL") - ), - ("gpio_2", 0, - Pins("A14 B16 C14 C16 C15 D16 D15 D14 F15 F16 F14 G16 G15"), - IOStandard("3.3-V LVTTL") - ), + ("gpio_0", 0, + Pins("D3 C3 A2 A3 B3 B4 A4 B5 A5 D5 B6 A6 B7 D6 A7 C6", + "C8 E6 E7 D8 E8 F8 F9 E9 C9 D9 E11 E10 C11 B11 A12 D11", + "D12 B12"), + IOStandard("3.3-V LVTTL") + ), + ("gpio_1", 0, + Pins("F13 T15 T14 T13 R13 T12 R12 T11 T10 R11 P11 R10 N12 P9 N9 N11", + "L16 K16 R16 L15 P15 P16 R14 N16 N15 P14 L14 N14 M10 L13 J16 K15", + "J13 J14"), + IOStandard("3.3-V LVTTL") + ), + ("gpio_2", 0, + Pins("A14 B16 C14 C16 C15 D16 D15 D14 F15 F16 F14 G16 G15"), + IOStandard("3.3-V LVTTL") + ), ] class Platform(AlteraPlatform): - default_clk_name = "clk50" - default_clk_period = 20 + default_clk_name = "clk50" + default_clk_period = 20 - def __init__(self): - AlteraPlatform.__init__(self, "EP4CE22F17C6", _io) + def __init__(self): + AlteraPlatform.__init__(self, "EP4CE22F17C6", _io) - def create_programmer(self): - return USBBlaster() + def create_programmer(self): + return USBBlaster() diff --git a/mibuild/platforms/kc705.py b/mibuild/platforms/kc705.py index 82ee9ef1..6f3cccb7 100644 --- a/mibuild/platforms/kc705.py +++ b/mibuild/platforms/kc705.py @@ -3,414 +3,414 @@ from mibuild.xilinx import XilinxPlatform, XC3SProg, VivadoProgrammer, iMPACT from mibuild.xilinx.ise import XilinxISEToolchain _io = [ - ("user_led", 0, Pins("AB8"), IOStandard("LVCMOS15")), - ("user_led", 1, Pins("AA8"), IOStandard("LVCMOS15")), - ("user_led", 2, Pins("AC9"), IOStandard("LVCMOS15")), - ("user_led", 3, Pins("AB9"), IOStandard("LVCMOS15")), - ("user_led", 4, Pins("AE26"), IOStandard("LVCMOS25")), - ("user_led", 5, Pins("G19"), IOStandard("LVCMOS25")), - ("user_led", 6, Pins("E18"), IOStandard("LVCMOS25")), - ("user_led", 7, Pins("F16"), IOStandard("LVCMOS25")), + ("user_led", 0, Pins("AB8"), IOStandard("LVCMOS15")), + ("user_led", 1, Pins("AA8"), IOStandard("LVCMOS15")), + ("user_led", 2, Pins("AC9"), IOStandard("LVCMOS15")), + ("user_led", 3, Pins("AB9"), IOStandard("LVCMOS15")), + ("user_led", 4, Pins("AE26"), IOStandard("LVCMOS25")), + ("user_led", 5, Pins("G19"), IOStandard("LVCMOS25")), + ("user_led", 6, Pins("E18"), IOStandard("LVCMOS25")), + ("user_led", 7, Pins("F16"), IOStandard("LVCMOS25")), - ("cpu_reset", 0, Pins("AB7"), IOStandard("LVCMOS15")), + ("cpu_reset", 0, Pins("AB7"), IOStandard("LVCMOS15")), - ("user_btn_c", 0, Pins("G12"), IOStandard("LVCMOS25")), - ("user_btn_n", 0, Pins("AA12"), IOStandard("LVCMOS15")), - ("user_btn_s", 0, Pins("AB12"), IOStandard("LVCMOS15")), - ("user_btn_w", 0, Pins("AC6"), IOStandard("LVCMOS15")), - ("user_btn_e", 0, Pins("AG5"), IOStandard("LVCMOS15")), + ("user_btn_c", 0, Pins("G12"), IOStandard("LVCMOS25")), + ("user_btn_n", 0, Pins("AA12"), IOStandard("LVCMOS15")), + ("user_btn_s", 0, Pins("AB12"), IOStandard("LVCMOS15")), + ("user_btn_w", 0, Pins("AC6"), IOStandard("LVCMOS15")), + ("user_btn_e", 0, Pins("AG5"), IOStandard("LVCMOS15")), - ("user_dip_btn", 0, Pins("Y29"), IOStandard("LVCMOS25")), - ("user_dip_btn", 1, Pins("W29"), IOStandard("LVCMOS25")), - ("user_dip_btn", 2, Pins("AA28"), IOStandard("LVCMOS25")), - ("user_dip_btn", 3, Pins("Y28"), IOStandard("LVCMOS25")), + ("user_dip_btn", 0, Pins("Y29"), IOStandard("LVCMOS25")), + ("user_dip_btn", 1, Pins("W29"), IOStandard("LVCMOS25")), + ("user_dip_btn", 2, Pins("AA28"), IOStandard("LVCMOS25")), + ("user_dip_btn", 3, Pins("Y28"), IOStandard("LVCMOS25")), - ("user_sma_clock", 0, - Subsignal("p", Pins("L25"), IOStandard("LVDS_25")), - Subsignal("n", Pins("K25"), IOStandard("LVDS_25")) - ), + ("user_sma_clock", 0, + Subsignal("p", Pins("L25"), IOStandard("LVDS_25")), + Subsignal("n", Pins("K25"), IOStandard("LVDS_25")) + ), - ("clk200", 0, - Subsignal("p", Pins("AD12"), IOStandard("LVDS")), - Subsignal("n", Pins("AD11"), IOStandard("LVDS")) - ), + ("clk200", 0, + Subsignal("p", Pins("AD12"), IOStandard("LVDS")), + Subsignal("n", Pins("AD11"), IOStandard("LVDS")) + ), - ("clk156", 0, - Subsignal("p", Pins("K28"), IOStandard("LVDS_25")), - Subsignal("n", Pins("K29"), IOStandard("LVDS_25")) - ), + ("clk156", 0, + Subsignal("p", Pins("K28"), IOStandard("LVDS_25")), + Subsignal("n", Pins("K29"), IOStandard("LVDS_25")) + ), - ("i2c", 0, - Subsignal("scl", Pins("K21")), - Subsignal("sda", Pins("L21")), - IOStandard("LVCMOS25")), + ("i2c", 0, + Subsignal("scl", Pins("K21")), + Subsignal("sda", Pins("L21")), + IOStandard("LVCMOS25")), - ("serial", 0, - Subsignal("cts", Pins("L27")), - Subsignal("rts", Pins("K23")), - Subsignal("tx", Pins("K24")), - Subsignal("rx", Pins("M19")), - IOStandard("LVCMOS25")), + ("serial", 0, + Subsignal("cts", Pins("L27")), + Subsignal("rts", Pins("K23")), + Subsignal("tx", Pins("K24")), + Subsignal("rx", Pins("M19")), + IOStandard("LVCMOS25")), - ("spiflash", 0, # clock needs to be accessed through STARTUPE2 - Subsignal("cs_n", Pins("U19")), - Subsignal("dq", Pins("P24", "R25", "R20", "R21")), - IOStandard("LVCMOS25") - ), + ("spiflash", 0, # clock needs to be accessed through STARTUPE2 + Subsignal("cs_n", Pins("U19")), + Subsignal("dq", Pins("P24", "R25", "R20", "R21")), + IOStandard("LVCMOS25") + ), - ("mmc", 0, - Subsignal("wp", Pins("Y21")), - Subsignal("det", Pins("AA21")), - Subsignal("cmd", Pins("AB22")), - Subsignal("clk", Pins("AB23")), - Subsignal("dat", Pins("AC20 AA23 AA22 AC21")), - IOStandard("LVCMOS25")), + ("mmc", 0, + Subsignal("wp", Pins("Y21")), + Subsignal("det", Pins("AA21")), + Subsignal("cmd", Pins("AB22")), + Subsignal("clk", Pins("AB23")), + Subsignal("dat", Pins("AC20 AA23 AA22 AC21")), + IOStandard("LVCMOS25")), - ("lcd", 0, - Subsignal("db", Pins("AA13 AA10 AA11 Y10")), - Subsignal("e", Pins("AB10")), - Subsignal("rs", Pins("Y11")), - Subsignal("rw", Pins("AB13")), - IOStandard("LVCMOS15")), + ("lcd", 0, + Subsignal("db", Pins("AA13 AA10 AA11 Y10")), + Subsignal("e", Pins("AB10")), + Subsignal("rs", Pins("Y11")), + Subsignal("rw", Pins("AB13")), + IOStandard("LVCMOS15")), - ("rotary", 0, - Subsignal("a", Pins("Y26")), - Subsignal("b", Pins("Y25")), - Subsignal("push", Pins("AA26")), - IOStandard("LVCMOS25")), + ("rotary", 0, + Subsignal("a", Pins("Y26")), + Subsignal("b", Pins("Y25")), + Subsignal("push", Pins("AA26")), + IOStandard("LVCMOS25")), - ("hdmi", 0, - Subsignal("d", Pins("B23 A23 E23 D23 F25 E25 E24 D24 F26 E26 G23 G24 J19 H19 L17 L18 K19 K20")), - Subsignal("de", Pins("H17")), - Subsignal("clk", Pins("K18")), - Subsignal("vsync", Pins("H20")), - Subsignal("hsync", Pins("J18")), - Subsignal("int", Pins("AH24")), - Subsignal("spdif", Pins("J17")), - Subsignal("spdif_out", Pins("G20")), - IOStandard("LVCMOS25")), + ("hdmi", 0, + Subsignal("d", Pins("B23 A23 E23 D23 F25 E25 E24 D24 F26 E26 G23 G24 J19 H19 L17 L18 K19 K20")), + Subsignal("de", Pins("H17")), + Subsignal("clk", Pins("K18")), + Subsignal("vsync", Pins("H20")), + Subsignal("hsync", Pins("J18")), + Subsignal("int", Pins("AH24")), + Subsignal("spdif", Pins("J17")), + Subsignal("spdif_out", Pins("G20")), + IOStandard("LVCMOS25")), - ("ddram", 0, - Subsignal("a", Pins( - "AH12 AG13 AG12 AF12 AJ12 AJ13 AJ14 AH14", - "AK13 AK14 AF13 AE13 AJ11 AH11 AK10 AK11"), - IOStandard("SSTL15")), - Subsignal("ba", Pins("AH9 AG9 AK9"), IOStandard("SSTL15")), - Subsignal("ras_n", Pins("AD9"), IOStandard("SSTL15")), - Subsignal("cas_n", Pins("AC11"), IOStandard("SSTL15")), - Subsignal("we_n", Pins("AE9"), IOStandard("SSTL15")), - Subsignal("cs_n", Pins("AC12"), IOStandard("SSTL15")), - Subsignal("dm", Pins("Y16 AB17 AF17 AE16 AK5 AJ3 AF6 AC7"), - IOStandard("SSTL15")), - Subsignal("dq", Pins( - "AA15 AA16 AC14 AD14 AA17 AB15 AE15 Y15", - "AB19 AD16 AC19 AD17 AA18 AB18 AE18 AD18", - "AG19 AK19 AG18 AF18 AH19 AJ19 AE19 AD19", - "AK16 AJ17 AG15 AF15 AH17 AG14 AH15 AK15", - "AK8 AK6 AG7 AF7 AF8 AK4 AJ8 AJ6", - "AH5 AH6 AJ2 AH2 AH4 AJ4 AK1 AJ1", - "AF1 AF2 AE4 AE3 AF3 AF5 AE1 AE5", - "AC1 AD3 AC4 AC5 AE6 AD6 AC2 AD4"), - IOStandard("SSTL15_T_DCI")), - Subsignal("dqs_p", Pins("AC16 Y19 AJ18 AH16 AH7 AG2 AG4 AD2"), - IOStandard("DIFF_SSTL15")), - Subsignal("dqs_n", Pins("AC15 Y18 AK18 AJ16 AJ7 AH1 AG3 AD1"), - IOStandard("DIFF_SSTL15")), - Subsignal("clk_p", Pins("AG10"), IOStandard("DIFF_SSTL15")), - Subsignal("clk_n", Pins("AH10"), IOStandard("DIFF_SSTL15")), - Subsignal("cke", Pins("AF10"), IOStandard("SSTL15")), - Subsignal("odt", Pins("AD8"), IOStandard("SSTL15")), - Subsignal("reset_n", Pins("AK3"), IOStandard("LVCMOS15")), - Misc("SLEW=FAST"), - Misc("VCCAUX_IO=HIGH") - ), + ("ddram", 0, + Subsignal("a", Pins( + "AH12 AG13 AG12 AF12 AJ12 AJ13 AJ14 AH14", + "AK13 AK14 AF13 AE13 AJ11 AH11 AK10 AK11"), + IOStandard("SSTL15")), + Subsignal("ba", Pins("AH9 AG9 AK9"), IOStandard("SSTL15")), + Subsignal("ras_n", Pins("AD9"), IOStandard("SSTL15")), + Subsignal("cas_n", Pins("AC11"), IOStandard("SSTL15")), + Subsignal("we_n", Pins("AE9"), IOStandard("SSTL15")), + Subsignal("cs_n", Pins("AC12"), IOStandard("SSTL15")), + Subsignal("dm", Pins("Y16 AB17 AF17 AE16 AK5 AJ3 AF6 AC7"), + IOStandard("SSTL15")), + Subsignal("dq", Pins( + "AA15 AA16 AC14 AD14 AA17 AB15 AE15 Y15", + "AB19 AD16 AC19 AD17 AA18 AB18 AE18 AD18", + "AG19 AK19 AG18 AF18 AH19 AJ19 AE19 AD19", + "AK16 AJ17 AG15 AF15 AH17 AG14 AH15 AK15", + "AK8 AK6 AG7 AF7 AF8 AK4 AJ8 AJ6", + "AH5 AH6 AJ2 AH2 AH4 AJ4 AK1 AJ1", + "AF1 AF2 AE4 AE3 AF3 AF5 AE1 AE5", + "AC1 AD3 AC4 AC5 AE6 AD6 AC2 AD4"), + IOStandard("SSTL15_T_DCI")), + Subsignal("dqs_p", Pins("AC16 Y19 AJ18 AH16 AH7 AG2 AG4 AD2"), + IOStandard("DIFF_SSTL15")), + Subsignal("dqs_n", Pins("AC15 Y18 AK18 AJ16 AJ7 AH1 AG3 AD1"), + IOStandard("DIFF_SSTL15")), + Subsignal("clk_p", Pins("AG10"), IOStandard("DIFF_SSTL15")), + Subsignal("clk_n", Pins("AH10"), IOStandard("DIFF_SSTL15")), + Subsignal("cke", Pins("AF10"), IOStandard("SSTL15")), + Subsignal("odt", Pins("AD8"), IOStandard("SSTL15")), + Subsignal("reset_n", Pins("AK3"), IOStandard("LVCMOS15")), + Misc("SLEW=FAST"), + Misc("VCCAUX_IO=HIGH") + ), - ("eth_clocks", 0, - Subsignal("tx", Pins("M28")), - Subsignal("gtx", Pins("K30")), - Subsignal("rx", Pins("U27")), - IOStandard("LVCMOS25") - ), - ("eth", 0, - Subsignal("rst_n", Pins("L20")), - Subsignal("int_n", Pins("N30")), - Subsignal("mdio", Pins("J21")), - Subsignal("mdc", Pins("R23")), - Subsignal("dv", Pins("R28")), - Subsignal("rx_er", Pins("V26")), - Subsignal("rx_data", Pins("U30 U25 T25 U28 R19 T27 T26 T28")), - Subsignal("tx_en", Pins("M27")), - Subsignal("tx_er", Pins("N29")), - Subsignal("tx_data", Pins("N27 N25 M29 L28 J26 K26 L30 J28")), - Subsignal("col", Pins("W19")), - Subsignal("crs", Pins("R30")), - IOStandard("LVCMOS25") - ), + ("eth_clocks", 0, + Subsignal("tx", Pins("M28")), + Subsignal("gtx", Pins("K30")), + Subsignal("rx", Pins("U27")), + IOStandard("LVCMOS25") + ), + ("eth", 0, + Subsignal("rst_n", Pins("L20")), + Subsignal("int_n", Pins("N30")), + Subsignal("mdio", Pins("J21")), + Subsignal("mdc", Pins("R23")), + Subsignal("dv", Pins("R28")), + Subsignal("rx_er", Pins("V26")), + Subsignal("rx_data", Pins("U30 U25 T25 U28 R19 T27 T26 T28")), + Subsignal("tx_en", Pins("M27")), + Subsignal("tx_er", Pins("N29")), + Subsignal("tx_data", Pins("N27 N25 M29 L28 J26 K26 L30 J28")), + Subsignal("col", Pins("W19")), + Subsignal("crs", Pins("R30")), + IOStandard("LVCMOS25") + ), ] _connectors = [ - ("HPC", - { - "DP1_M2C_P": "D6", - "DP1_M2C_N": "D5", - "DP2_M2C_P": "B6", - "DP2_M2C_N": "B5", - "DP3_M2C_P": "A8", - "DP3_M2C_N": "A7", - "DP1_C2M_P": "C4", - "DP1_C2M_N": "C3", - "DP2_C2M_P": "B2", - "DP2_C2M_N": "B1", - "DP3_C2M_P": "A4", - "DP3_C2M_N": "A3", - "DP0_C2M_P": "D2", - "DP0_C2M_N": "D1", - "DP0_M2C_P": "E4", - "DP0_M2C_N": "E3", - "LA06_P": "H30", - "LA06_N": "G30", - "LA10_P": "D29", - "LA10_N": "C30", - "LA14_P": "B28", - "LA14_N": "A28", - "LA18_CC_P": "F21", - "LA18_CC_N": "E21", - "LA27_P": "C19", - "LA27_N": "B19", - "HA01_CC_P": "H14", - "HA01_CC_N": "G14", - "HA05_P": "F15", - "HA05_N": "E16", - "HA09_P": "F12", - "HA09_N": "E13", - "HA13_P": "L16", - "HA13_N": "K16", - "HA16_P": "L15", - "HA16_N": "K15", - "HA20_P": "K13", - "HA20_N": "J13", - "CLK1_M2C_P": "D17", - "CLK1_M2C_N": "D18", - "LA00_CC_P": "C25", - "LA00_CC_N": "B25", - "LA03_P": "H26", - "LA03_N": "H27", - "LA08_P": "E29", - "LA08_N": "E30", - "LA12_P": "C29", - "LA12_N": "B29", - "LA16_P": "B27", - "LA16_N": "A27", - "LA20_P": "E19", - "LA20_N": "D19", - "LA22_P": "C20", - "LA22_N": "B20", - "LA25_P": "G17", - "LA25_N": "F17", - "LA29_P": "C17", - "LA29_N": "B17", - "LA31_P": "G22", - "LA31_N": "F22", - "LA33_P": "H21", - "LA33_N": "H22", - "HA03_P": "C12", - "HA03_N": "B12", - "HA07_P": "B14", - "HA07_N": "A15", - "HA11_P": "B13", - "HA11_N": "A13", - "HA14_P": "J16", - "HA14_N": "H16", - "HA18_P": "K14", - "HA18_N": "J14", - "HA22_P": "L11", - "HA22_N": "K11", - "GBTCLK1_M2C_P": "E8", - "GBTCLK1_M2C_N": "E7", - "GBTCLK0_M2C_P": "C8", - "GBTCLK0_M2C_N": "C7", - "LA01_CC_P": "D26", - "LA01_CC_N": "C26", - "LA05_P": "G29", - "LA05_N": "F30", - "LA09_P": "B30", - "LA09_N": "A30", - "LA13_P": "A25", - "LA13_N": "A26", - "LA17_CC_P": "F20", - "LA17_CC_N": "E20", - "LA23_P": "B22", - "LA23_N": "A22", - "LA26_P": "B18", - "LA26_N": "A18", - "PG_M2C": "J29", - "HA00_CC_P": "D12", - "HA00_CC_N": "D13", - "HA04_P": "F11", - "HA04_N": "E11", - "HA08_P": "E14", - "HA08_N": "E15", - "HA12_P": "C15", - "HA12_N": "B15", - "HA15_P": "H15", - "HA15_N": "G15", - "HA19_P": "H11", - "HA19_N": "H12", - "PRSNT_M2C_B": "M20", - "CLK0_M2C_P": "D27", - "CLK0_M2C_N": "C27", - "LA02_P": "H24", - "LA02_N": "H25", - "LA04_P": "G28", - "LA04_N": "F28", - "LA07_P": "E28", - "LA07_N": "D28", - "LA11_P": "G27", - "LA11_N": "F27", - "LA15_P": "C24", - "LA15_N": "B24", - "LA19_P": "G18", - "LA19_N": "F18", - "LA21_P": "A20", - "LA21_N": "A21", - "LA24_P": "A16", - "LA24_N": "A17", - "LA28_P": "D16", - "LA28_N": "C16", - "LA30_P": "D22", - "LA30_N": "C22", - "LA32_P": "D21", - "LA32_N": "C21", - "HA02_P": "D11", - "HA02_N": "C11", - "HA06_P": "D14", - "HA06_N": "C14", - "HA10_P": "A11", - "HA10_N": "A12", - "HA17_CC_P": "G13", - "HA17_CC_N": "F13", - "HA21_P": "J11", - "HA21_N": "J12", - "HA23_P": "L12", - "HA23_N": "L13", - } - ), - ("LPC", - { - "GBTCLK0_M2C_P": "N8", - "GBTCLK0_M2C_N": "N7", - "LA01_CC_P": "AE23", - "LA01_CC_N": "AF23", - "LA05_P": "AG22", - "LA05_N": "AH22", - "LA09_P": "AK23", - "LA09_N": "AK24", - "LA13_P": "AB24", - "LA13_N": "AC25", - "LA17_CC_P": "AB27", - "LA17_CC_N": "AC27", - "LA23_P": "AH26", - "LA23_N": "AH27", - "LA26_P": "AK29", - "LA26_N": "AK30", - "CLK0_M2C_P": "AF22", - "CLK0_M2C_N": "AG23", - "LA02_P": "AF20", - "LA02_N": "AF21", - "LA04_P": "AH21", - "LA04_N": "AJ21", - "LA07_P": "AG25", - "LA07_N": "AH25", - "LA11_P": "AE25", - "LA11_N": "AF25", - "LA15_P": "AC24", - "LA15_N": "AD24", - "LA19_P": "AJ26", - "LA19_N": "AK26", - "LA21_P": "AG27", - "LA21_N": "AG28", - "LA24_P": "AG30", - "LA24_N": "AH30", - "LA28_P": "AE30", - "LA28_N": "AF30", - "LA30_P": "AB29", - "LA30_N": "AB30", - "LA32_P": "Y30", - "LA32_N": "AA30", - "LA06_P": "AK20", - "LA06_N": "AK21", - "LA10_P": "AJ24", - "LA10_N": "AK25", - "LA14_P": "AD21", - "LA14_N": "AE21", - "LA18_CC_P": "AD27", - "LA18_CC_N": "AD28", - "LA27_P": "AJ28", - "LA27_N": "AJ29", - "CLK1_M2C_P": "AG29", - "CLK1_M2C_N": "AH29", - "LA00_CC_P": "AD23", - "LA00_CC_N": "AE24", - "LA03_P": "AG20", - "LA03_N": "AH20", - "LA08_P": "AJ22", - "LA08_N": "AJ23", - "LA12_P": "AA20", - "LA12_N": "AB20", - "LA16_P": "AC22", - "LA16_N": "AD22", - "LA20_P": "AF26", - "LA20_N": "AF27", - "LA22_P": "AJ27", - "LA22_N": "AK28", - "LA25_P": "AC26", - "LA25_N": "AD26", - "LA29_P": "AE28", - "LA29_N": "AF28", - "LA31_P": "AD29", - "LA31_N": "AE29", - "LA33_P": "AC29", - "LA33_N": "AC30", - } - ) + ("HPC", + { + "DP1_M2C_P": "D6", + "DP1_M2C_N": "D5", + "DP2_M2C_P": "B6", + "DP2_M2C_N": "B5", + "DP3_M2C_P": "A8", + "DP3_M2C_N": "A7", + "DP1_C2M_P": "C4", + "DP1_C2M_N": "C3", + "DP2_C2M_P": "B2", + "DP2_C2M_N": "B1", + "DP3_C2M_P": "A4", + "DP3_C2M_N": "A3", + "DP0_C2M_P": "D2", + "DP0_C2M_N": "D1", + "DP0_M2C_P": "E4", + "DP0_M2C_N": "E3", + "LA06_P": "H30", + "LA06_N": "G30", + "LA10_P": "D29", + "LA10_N": "C30", + "LA14_P": "B28", + "LA14_N": "A28", + "LA18_CC_P": "F21", + "LA18_CC_N": "E21", + "LA27_P": "C19", + "LA27_N": "B19", + "HA01_CC_P": "H14", + "HA01_CC_N": "G14", + "HA05_P": "F15", + "HA05_N": "E16", + "HA09_P": "F12", + "HA09_N": "E13", + "HA13_P": "L16", + "HA13_N": "K16", + "HA16_P": "L15", + "HA16_N": "K15", + "HA20_P": "K13", + "HA20_N": "J13", + "CLK1_M2C_P": "D17", + "CLK1_M2C_N": "D18", + "LA00_CC_P": "C25", + "LA00_CC_N": "B25", + "LA03_P": "H26", + "LA03_N": "H27", + "LA08_P": "E29", + "LA08_N": "E30", + "LA12_P": "C29", + "LA12_N": "B29", + "LA16_P": "B27", + "LA16_N": "A27", + "LA20_P": "E19", + "LA20_N": "D19", + "LA22_P": "C20", + "LA22_N": "B20", + "LA25_P": "G17", + "LA25_N": "F17", + "LA29_P": "C17", + "LA29_N": "B17", + "LA31_P": "G22", + "LA31_N": "F22", + "LA33_P": "H21", + "LA33_N": "H22", + "HA03_P": "C12", + "HA03_N": "B12", + "HA07_P": "B14", + "HA07_N": "A15", + "HA11_P": "B13", + "HA11_N": "A13", + "HA14_P": "J16", + "HA14_N": "H16", + "HA18_P": "K14", + "HA18_N": "J14", + "HA22_P": "L11", + "HA22_N": "K11", + "GBTCLK1_M2C_P": "E8", + "GBTCLK1_M2C_N": "E7", + "GBTCLK0_M2C_P": "C8", + "GBTCLK0_M2C_N": "C7", + "LA01_CC_P": "D26", + "LA01_CC_N": "C26", + "LA05_P": "G29", + "LA05_N": "F30", + "LA09_P": "B30", + "LA09_N": "A30", + "LA13_P": "A25", + "LA13_N": "A26", + "LA17_CC_P": "F20", + "LA17_CC_N": "E20", + "LA23_P": "B22", + "LA23_N": "A22", + "LA26_P": "B18", + "LA26_N": "A18", + "PG_M2C": "J29", + "HA00_CC_P": "D12", + "HA00_CC_N": "D13", + "HA04_P": "F11", + "HA04_N": "E11", + "HA08_P": "E14", + "HA08_N": "E15", + "HA12_P": "C15", + "HA12_N": "B15", + "HA15_P": "H15", + "HA15_N": "G15", + "HA19_P": "H11", + "HA19_N": "H12", + "PRSNT_M2C_B": "M20", + "CLK0_M2C_P": "D27", + "CLK0_M2C_N": "C27", + "LA02_P": "H24", + "LA02_N": "H25", + "LA04_P": "G28", + "LA04_N": "F28", + "LA07_P": "E28", + "LA07_N": "D28", + "LA11_P": "G27", + "LA11_N": "F27", + "LA15_P": "C24", + "LA15_N": "B24", + "LA19_P": "G18", + "LA19_N": "F18", + "LA21_P": "A20", + "LA21_N": "A21", + "LA24_P": "A16", + "LA24_N": "A17", + "LA28_P": "D16", + "LA28_N": "C16", + "LA30_P": "D22", + "LA30_N": "C22", + "LA32_P": "D21", + "LA32_N": "C21", + "HA02_P": "D11", + "HA02_N": "C11", + "HA06_P": "D14", + "HA06_N": "C14", + "HA10_P": "A11", + "HA10_N": "A12", + "HA17_CC_P": "G13", + "HA17_CC_N": "F13", + "HA21_P": "J11", + "HA21_N": "J12", + "HA23_P": "L12", + "HA23_N": "L13", + } + ), + ("LPC", + { + "GBTCLK0_M2C_P": "N8", + "GBTCLK0_M2C_N": "N7", + "LA01_CC_P": "AE23", + "LA01_CC_N": "AF23", + "LA05_P": "AG22", + "LA05_N": "AH22", + "LA09_P": "AK23", + "LA09_N": "AK24", + "LA13_P": "AB24", + "LA13_N": "AC25", + "LA17_CC_P": "AB27", + "LA17_CC_N": "AC27", + "LA23_P": "AH26", + "LA23_N": "AH27", + "LA26_P": "AK29", + "LA26_N": "AK30", + "CLK0_M2C_P": "AF22", + "CLK0_M2C_N": "AG23", + "LA02_P": "AF20", + "LA02_N": "AF21", + "LA04_P": "AH21", + "LA04_N": "AJ21", + "LA07_P": "AG25", + "LA07_N": "AH25", + "LA11_P": "AE25", + "LA11_N": "AF25", + "LA15_P": "AC24", + "LA15_N": "AD24", + "LA19_P": "AJ26", + "LA19_N": "AK26", + "LA21_P": "AG27", + "LA21_N": "AG28", + "LA24_P": "AG30", + "LA24_N": "AH30", + "LA28_P": "AE30", + "LA28_N": "AF30", + "LA30_P": "AB29", + "LA30_N": "AB30", + "LA32_P": "Y30", + "LA32_N": "AA30", + "LA06_P": "AK20", + "LA06_N": "AK21", + "LA10_P": "AJ24", + "LA10_N": "AK25", + "LA14_P": "AD21", + "LA14_N": "AE21", + "LA18_CC_P": "AD27", + "LA18_CC_N": "AD28", + "LA27_P": "AJ28", + "LA27_N": "AJ29", + "CLK1_M2C_P": "AG29", + "CLK1_M2C_N": "AH29", + "LA00_CC_P": "AD23", + "LA00_CC_N": "AE24", + "LA03_P": "AG20", + "LA03_N": "AH20", + "LA08_P": "AJ22", + "LA08_N": "AJ23", + "LA12_P": "AA20", + "LA12_N": "AB20", + "LA16_P": "AC22", + "LA16_N": "AD22", + "LA20_P": "AF26", + "LA20_N": "AF27", + "LA22_P": "AJ27", + "LA22_N": "AK28", + "LA25_P": "AC26", + "LA25_N": "AD26", + "LA29_P": "AE28", + "LA29_N": "AF28", + "LA31_P": "AD29", + "LA31_N": "AE29", + "LA33_P": "AC29", + "LA33_N": "AC30", + } + ) ] class Platform(XilinxPlatform): - identifier = 0x4B37 - default_clk_name = "clk156" - default_clk_period = 6.4 + identifier = 0x4B37 + default_clk_name = "clk156" + default_clk_period = 6.4 - def __init__(self, toolchain="vivado", programmer="xc3sprog"): - XilinxPlatform.__init__(self, "xc7k325t-ffg900-2", _io, _connectors, - toolchain=toolchain) - if toolchain == "ise": - self.toolchain.bitgen_opt = "-g LCK_cycle:6 -g Binary:Yes -w -g ConfigRate:12 -g SPI_buswidth:4" - elif toolchain == "vivado": - self.toolchain.bitstream_commands = ["set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]"] - self.toolchain.additional_commands = ["write_cfgmem -force -format bin -interface spix4 -size 16 -loadbit \"up 0x0 {build_name}.bit\" -file {build_name}.bin"] - self.programmer = programmer + def __init__(self, toolchain="vivado", programmer="xc3sprog"): + XilinxPlatform.__init__(self, "xc7k325t-ffg900-2", _io, _connectors, + toolchain=toolchain) + if toolchain == "ise": + self.toolchain.bitgen_opt = "-g LCK_cycle:6 -g Binary:Yes -w -g ConfigRate:12 -g SPI_buswidth:4" + elif toolchain == "vivado": + self.toolchain.bitstream_commands = ["set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]"] + self.toolchain.additional_commands = ["write_cfgmem -force -format bin -interface spix4 -size 16 -loadbit \"up 0x0 {build_name}.bit\" -file {build_name}.bin"] + self.programmer = programmer - def create_programmer(self): - if self.programmer == "xc3sprog": - return XC3SProg("jtaghs1_fast", "bscan_spi_kc705.bit") - elif self.programmer == "vivado": - return VivadoProgrammer() - elif self.programmer == "impact": - return iMPACT() - else: - raise ValueError("{} programmer is not supported".format(programmer)) + def create_programmer(self): + if self.programmer == "xc3sprog": + return XC3SProg("jtaghs1_fast", "bscan_spi_kc705.bit") + elif self.programmer == "vivado": + return VivadoProgrammer() + elif self.programmer == "impact": + return iMPACT() + else: + raise ValueError("{} programmer is not supported".format(programmer)) - def do_finalize(self, fragment): - XilinxPlatform.do_finalize(self, fragment) - try: - self.add_period_constraint(self.lookup_request("clk200").p, 5.0) - except ConstraintError: - pass - try: - self.add_period_constraint(self.lookup_request("eth_clocks").rx, 8.0) - except ConstraintError: - pass - if isinstance(self.toolchain, XilinxISEToolchain): - self.add_platform_command("CONFIG DCI_CASCADE = \"33 32 34\";") - else: - self.add_platform_command("set_property DCI_CASCADE {{32 34}} [get_iobanks 33]") + def do_finalize(self, fragment): + XilinxPlatform.do_finalize(self, fragment) + try: + self.add_period_constraint(self.lookup_request("clk200").p, 5.0) + except ConstraintError: + pass + try: + self.add_period_constraint(self.lookup_request("eth_clocks").rx, 8.0) + except ConstraintError: + pass + if isinstance(self.toolchain, XilinxISEToolchain): + self.add_platform_command("CONFIG DCI_CASCADE = \"33 32 34\";") + else: + self.add_platform_command("set_property DCI_CASCADE {{32 34}} [get_iobanks 33]") diff --git a/mibuild/platforms/lx9_microboard.py b/mibuild/platforms/lx9_microboard.py index 077d0a0b..8ce9bea6 100644 --- a/mibuild/platforms/lx9_microboard.py +++ b/mibuild/platforms/lx9_microboard.py @@ -2,129 +2,129 @@ from mibuild.generic_platform import * from mibuild.xilinx import XilinxPlatform _io = [ - ("user_btn", 0, Pins("V4"), IOStandard("LVCMOS33"), - Misc("PULLDOWN"), Misc("TIG")), - - ("user_led", 0, Pins("P4"), Misc("SLEW=QUIETIO"), IOStandard("LVCMOS18")), - ("user_led", 1, Pins("L6"), Misc("SLEW=QUIETIO"), IOStandard("LVCMOS18")), - ("user_led", 2, Pins("F5"), Misc("SLEW=QUIETIO"), IOStandard("LVCMOS18")), - ("user_led", 3, Pins("C2"), Misc("SLEW=QUIETIO"), IOStandard("LVCMOS18")), - - ("user_dip", 0, Pins("B3"), Misc("PULLDOWN"), IOStandard("LVCMOS33")), - ("user_dip", 1, Pins("A3"), Misc("PULLDOWN"), IOStandard("LVCMOS33")), - ("user_dip", 2, Pins("B4"), Misc("PULLDOWN"), IOStandard("LVCMOS33")), - ("user_dip", 3, Pins("A4"), Misc("PULLDOWN"), IOStandard("LVCMOS33")), - - # TI CDCE913 programmable triple-output PLL - ("clk_y1", 0, Pins("V10"), IOStandard("LVCMOS33")), # default: 40 MHz - ("clk_y2", 0, Pins("K15"), IOStandard("LVCMOS33")), # default: 66 2/3 MHz - ("clk_y3", 0, Pins("C10"), IOStandard("LVCMOS33")), # default: 100 MHz - - # Maxim DS1088LU oscillator, not populated - ("clk_backup", 0, Pins("R8"), IOStandard("LVCMOS33")), - - # TI CDCE913 PLL I2C control - ("pll", 0, - Subsignal("scl", Pins("P12")), - Subsignal("sda", Pins("U13")), - Misc("PULLUP"), - IOStandard("LVCMOS33")), - - # Micron N25Q128 SPI Flash - ("spiflash", 0, - Subsignal("clk", Pins("R15")), - Subsignal("cs_n", Pins("V3")), - Subsignal("dq", Pins("T13 R13 T14 V14")), - IOStandard("LVCMOS33")), - - # PMOD extension connectors - ("pmod", 0, - Subsignal("d", Pins("F15 F16 C17 C18 F14 G14 D17 D18")), - IOStandard("LVCMOS33")), - ("pmod", 1, - Subsignal("d", Pins("H12 G13 E16 E18 K12 K13 F17 F18")), - IOStandard("LVCMOS33")), - - ("pmod_diff", 0, - Subsignal("io", Pins("F15 C17 F14 D17 H12 E16 K12 F17")), - Subsignal("iob", Pins("F16 C18 G14 D18 G13 E18 K13 F18")), - IOStandard("LVCMOS33")), - - ("serial", 0, - Subsignal("tx", Pins("T7"), Misc("SLEW=SLOW")), - Subsignal("rx", Pins("R7"), Misc("PULLUP")), - IOStandard("LVCMOS33")), - - ("ddram_clock", 0, - Subsignal("p", Pins("G3")), - Subsignal("n", Pins("G1")), - IOStandard("MOBILE_DDR")), # actually DIFF_ - - # Micron MT46H32M16LFBF-5 LPDDR - ("ddram", 0, - Subsignal("a", Pins("J7 J6 H5 L7 F3 H4 H3 H6 " - "D2 D1 F4 D3 G6")), - Subsignal("ba", Pins("F2 F1")), - Subsignal("dq", Pins("L2 L1 K2 K1 H2 H1 J3 J1 " - "M3 M1 N2 N1 T2 T1 U2 U1")), - Subsignal("cke", Pins("H7")), - Subsignal("we_n", Pins("E3")), - Subsignal("cs_n", Pins("K6")), # NC! - Subsignal("cas_n", Pins("K5")), - Subsignal("ras_n", Pins("L5")), - Subsignal("dm", Pins("K3", "K4")), - Subsignal("dqs", Pins("L4", "P2")), - Subsignal("rzq", Pins("N4")), - IOStandard("MOBILE_DDR")), - - # Nat Semi DP83848J 10/100 Ethernet PHY - # pull-ups on col and rx_data set phy addr to 11111b - # and prevent isolate mode (addr 00000b) - ("eth_clocks", 0, - Subsignal("rx", Pins("L15")), - Subsignal("tx", Pins("H17")), - IOStandard("LVCMOS33")), - - ("eth", 0, - Subsignal("col", Pins("M18"), Misc("PULLUP")), - Subsignal("crs", Pins("N17"), Misc("PULLDOWN")), - Subsignal("mdc", Pins("M16"), Misc("PULLDOWN")), - Subsignal("mdio", Pins("L18"), Misc("PULLUP")), # 1k5 ext PULLUP - Subsignal("rst_n", Pins("T18"), Misc("TIG")), - Subsignal("rx_data", Pins("T17 N16 N15 P18"), Misc("PULLUP")), - Subsignal("dv", Pins("P17"), Misc("PULLDOWN")), # MII - Subsignal("rx_er", Pins("N18"), Misc("PULLUP")), # auto MDIX - Subsignal("tx_data", Pins("K18 K17 J18 J16")), - Subsignal("tx_en", Pins("L17")), - Subsignal("tx_er", Pins("L16")), # NC! - IOStandard("LVCMOS33")), - ] + ("user_btn", 0, Pins("V4"), IOStandard("LVCMOS33"), + Misc("PULLDOWN"), Misc("TIG")), + + ("user_led", 0, Pins("P4"), Misc("SLEW=QUIETIO"), IOStandard("LVCMOS18")), + ("user_led", 1, Pins("L6"), Misc("SLEW=QUIETIO"), IOStandard("LVCMOS18")), + ("user_led", 2, Pins("F5"), Misc("SLEW=QUIETIO"), IOStandard("LVCMOS18")), + ("user_led", 3, Pins("C2"), Misc("SLEW=QUIETIO"), IOStandard("LVCMOS18")), + + ("user_dip", 0, Pins("B3"), Misc("PULLDOWN"), IOStandard("LVCMOS33")), + ("user_dip", 1, Pins("A3"), Misc("PULLDOWN"), IOStandard("LVCMOS33")), + ("user_dip", 2, Pins("B4"), Misc("PULLDOWN"), IOStandard("LVCMOS33")), + ("user_dip", 3, Pins("A4"), Misc("PULLDOWN"), IOStandard("LVCMOS33")), + + # TI CDCE913 programmable triple-output PLL + ("clk_y1", 0, Pins("V10"), IOStandard("LVCMOS33")), # default: 40 MHz + ("clk_y2", 0, Pins("K15"), IOStandard("LVCMOS33")), # default: 66 2/3 MHz + ("clk_y3", 0, Pins("C10"), IOStandard("LVCMOS33")), # default: 100 MHz + + # Maxim DS1088LU oscillator, not populated + ("clk_backup", 0, Pins("R8"), IOStandard("LVCMOS33")), + + # TI CDCE913 PLL I2C control + ("pll", 0, + Subsignal("scl", Pins("P12")), + Subsignal("sda", Pins("U13")), + Misc("PULLUP"), + IOStandard("LVCMOS33")), + + # Micron N25Q128 SPI Flash + ("spiflash", 0, + Subsignal("clk", Pins("R15")), + Subsignal("cs_n", Pins("V3")), + Subsignal("dq", Pins("T13 R13 T14 V14")), + IOStandard("LVCMOS33")), + + # PMOD extension connectors + ("pmod", 0, + Subsignal("d", Pins("F15 F16 C17 C18 F14 G14 D17 D18")), + IOStandard("LVCMOS33")), + ("pmod", 1, + Subsignal("d", Pins("H12 G13 E16 E18 K12 K13 F17 F18")), + IOStandard("LVCMOS33")), + + ("pmod_diff", 0, + Subsignal("io", Pins("F15 C17 F14 D17 H12 E16 K12 F17")), + Subsignal("iob", Pins("F16 C18 G14 D18 G13 E18 K13 F18")), + IOStandard("LVCMOS33")), + + ("serial", 0, + Subsignal("tx", Pins("T7"), Misc("SLEW=SLOW")), + Subsignal("rx", Pins("R7"), Misc("PULLUP")), + IOStandard("LVCMOS33")), + + ("ddram_clock", 0, + Subsignal("p", Pins("G3")), + Subsignal("n", Pins("G1")), + IOStandard("MOBILE_DDR")), # actually DIFF_ + + # Micron MT46H32M16LFBF-5 LPDDR + ("ddram", 0, + Subsignal("a", Pins("J7 J6 H5 L7 F3 H4 H3 H6 " + "D2 D1 F4 D3 G6")), + Subsignal("ba", Pins("F2 F1")), + Subsignal("dq", Pins("L2 L1 K2 K1 H2 H1 J3 J1 " + "M3 M1 N2 N1 T2 T1 U2 U1")), + Subsignal("cke", Pins("H7")), + Subsignal("we_n", Pins("E3")), + Subsignal("cs_n", Pins("K6")), # NC! + Subsignal("cas_n", Pins("K5")), + Subsignal("ras_n", Pins("L5")), + Subsignal("dm", Pins("K3", "K4")), + Subsignal("dqs", Pins("L4", "P2")), + Subsignal("rzq", Pins("N4")), + IOStandard("MOBILE_DDR")), + + # Nat Semi DP83848J 10/100 Ethernet PHY + # pull-ups on col and rx_data set phy addr to 11111b + # and prevent isolate mode (addr 00000b) + ("eth_clocks", 0, + Subsignal("rx", Pins("L15")), + Subsignal("tx", Pins("H17")), + IOStandard("LVCMOS33")), + + ("eth", 0, + Subsignal("col", Pins("M18"), Misc("PULLUP")), + Subsignal("crs", Pins("N17"), Misc("PULLDOWN")), + Subsignal("mdc", Pins("M16"), Misc("PULLDOWN")), + Subsignal("mdio", Pins("L18"), Misc("PULLUP")), # 1k5 ext PULLUP + Subsignal("rst_n", Pins("T18"), Misc("TIG")), + Subsignal("rx_data", Pins("T17 N16 N15 P18"), Misc("PULLUP")), + Subsignal("dv", Pins("P17"), Misc("PULLDOWN")), # MII + Subsignal("rx_er", Pins("N18"), Misc("PULLUP")), # auto MDIX + Subsignal("tx_data", Pins("K18 K17 J18 J16")), + Subsignal("tx_en", Pins("L17")), + Subsignal("tx_er", Pins("L16")), # NC! + IOStandard("LVCMOS33")), + ] class Platform(XilinxPlatform): - default_clk_name = "clk_y3" - default_clk_period = 10 - - def __init__(self): - XilinxPlatform.__init__(self, "xc6slx9-2csg324", _io) - self.add_platform_command(""" + default_clk_name = "clk_y3" + default_clk_period = 10 + + def __init__(self): + XilinxPlatform.__init__(self, "xc6slx9-2csg324", _io) + self.add_platform_command(""" CONFIG VCCAUX = "3.3"; """) - self.toolchain.bitgen_opt = "-g LCK_cycle:6 -g Binary:Yes -w -g SPI_buswidth:4" - self.toolchain.ise_commands = """ + self.toolchain.bitgen_opt = "-g LCK_cycle:6 -g Binary:Yes -w -g SPI_buswidth:4" + self.toolchain.ise_commands = """ promgen -w -spi -c FF -p mcs -o {build_name}.mcs -u 0 {build_name}.bit """ - def do_finalize(self, fragment): - XilinxPlatform.do_finalize(self, fragment) + def do_finalize(self, fragment): + XilinxPlatform.do_finalize(self, fragment) - try: - eth_clocks = self.lookup_request("eth_clocks") - self.add_period_constraint(eth_clocks.rx, 40) - self.add_period_constraint(eth_clocks.tx, 40) - self.add_platform_command(""" + try: + eth_clocks = self.lookup_request("eth_clocks") + self.add_period_constraint(eth_clocks.rx, 40) + self.add_period_constraint(eth_clocks.tx, 40) + self.add_platform_command(""" TIMESPEC "TS{phy_tx_clk}_io" = FROM "GRP{phy_tx_clk}" TO "PADS" 10 ns; TIMESPEC "TS{phy_rx_clk}_io" = FROM "PADS" TO "GRP{phy_rx_clk}" 10 ns; """, phy_rx_clk=eth_clocks.rx, phy_tx_clk=eth_clocks.tx) - except ConstraintError: - pass + except ConstraintError: + pass diff --git a/mibuild/platforms/m1.py b/mibuild/platforms/m1.py index 8cd7fb19..84a70d2e 100644 --- a/mibuild/platforms/m1.py +++ b/mibuild/platforms/m1.py @@ -3,148 +3,148 @@ from mibuild.xilinx import XilinxPlatform from mibuild.xilinx.programmer import UrJTAG _io = [ - ("user_led", 0, Pins("B16"), IOStandard("LVCMOS33"), Drive(24), Misc("SLEW=QUIETIO")), - ("user_led", 1, Pins("A16"), IOStandard("LVCMOS33"), Drive(24), Misc("SLEW=QUIETIO")), - - ("user_btn", 0, Pins("AB4"), IOStandard("LVCMOS33")), - ("user_btn", 1, Pins("AA4"), IOStandard("LVCMOS33")), - ("user_btn", 2, Pins("AB5"), IOStandard("LVCMOS33")), - - ("clk50", 0, Pins("AB11"), IOStandard("LVCMOS33")), - - # When executing softcore code in-place from the flash, we want - # the flash reset to be released before the system reset. - ("norflash_rst_n", 0, Pins("P22"), IOStandard("LVCMOS33"), Misc("SLEW=FAST"), Drive(8)), - ("norflash", 0, - Subsignal("adr", Pins("L22 L20 K22 K21 J19 H20 F22", - "F21 K17 J17 E22 E20 H18 H19 F20", - "G19 C22 C20 D22 D21 F19 F18 D20 D19")), - Subsignal("d", Pins("AA20 U14 U13 AA6 AB6 W4 Y4 Y7", - "AA2 AB2 V15 AA18 AB18 Y13 AA12 AB12"), Misc("PULLDOWN")), - Subsignal("oe_n", Pins("M22")), - Subsignal("we_n", Pins("N20")), - Subsignal("ce_n", Pins("M21")), - IOStandard("LVCMOS33"), Misc("SLEW=FAST"), Drive(8) - ), - - ("serial", 0, - Subsignal("tx", Pins("L17"), IOStandard("LVCMOS33"), Misc("SLEW=SLOW")), - Subsignal("rx", Pins("K18"), IOStandard("LVCMOS33"), Misc("PULLUP")) - ), - - ("ddram_clock", 0, - Subsignal("p", Pins("M3")), - Subsignal("n", Pins("L4")), - IOStandard("SSTL2_I") - ), - ("ddram", 0, - Subsignal("a", Pins("B1 B2 H8 J7 E4 D5 K7 F5 G6 C1 C3 D1 D2")), - Subsignal("ba", Pins("A2 E6")), - Subsignal("cs_n", Pins("F7")), - Subsignal("cke", Pins("G7")), - Subsignal("ras_n", Pins("E5")), - Subsignal("cas_n", Pins("C4")), - Subsignal("we_n", Pins("D3")), - Subsignal("dq", Pins("Y2 W3 W1 P8 P7 P6 P5 T4 T3", - "U4 V3 N6 N7 M7 M8 R4 P4 M6 L6 P3 N4", - "M5 V2 V1 U3 U1 T2 T1 R3 R1 P2 P1")), - Subsignal("dm", Pins("E1 E3 F3 G4")), - Subsignal("dqs", Pins("F1 F2 H5 H6")), - IOStandard("SSTL2_I") - ), - - ("eth_clocks", 0, - Subsignal("phy", Pins("M20")), - Subsignal("rx", Pins("H22")), - Subsignal("tx", Pins("H21")), - IOStandard("LVCMOS33") - ), - ("eth", 0, - Subsignal("rst_n", Pins("R22")), - Subsignal("dv", Pins("V21")), - Subsignal("rx_er", Pins("V22")), - Subsignal("rx_data", Pins("U22 U20 T22 T21")), - Subsignal("tx_en", Pins("N19")), - Subsignal("tx_er", Pins("M19")), - Subsignal("tx_data", Pins("M16 L15 P19 P20")), - Subsignal("col", Pins("W20")), - Subsignal("crs", Pins("W22")), - IOStandard("LVCMOS33") - ), - - ("vga_out", 0, - Subsignal("clk", Pins("A11")), - Subsignal("r", Pins("C6 B6 A6 C7 A7 B8 A8 D9")), - Subsignal("g", Pins("C8 C9 A9 D7 D8 D10 C10 B10")), - Subsignal("b", Pins("D11 C12 B12 A12 C13 A13 D14 C14")), - Subsignal("hsync_n", Pins("A14")), - Subsignal("vsync_n", Pins("C15")), - Subsignal("psave_n", Pins("B14")), - IOStandard("LVCMOS33") - ), - - ("mmc", 0, - Subsignal("clk", Pins("A10")), - Subsignal("cmd", Pins("B18")), - Subsignal("dat", Pins("A18 E16 C17 A17")), - IOStandard("LVCMOS33") - ), - - # Digital video mixer extension board - ("dvi_in", 0, - Subsignal("clk", Pins("A20")), - Subsignal("data0_n", Pins("A21")), - Subsignal("data1", Pins("B21")), - Subsignal("data2_n", Pins("B22")), - Subsignal("scl", Pins("G16")), - Subsignal("sda", Pins("G17")), - IOStandard("LVCMOS33") - ), - ("dvi_in", 1, - Subsignal("clk", Pins("H17")), - Subsignal("data0_n", Pins("H16")), - Subsignal("data1", Pins("F17")), - Subsignal("data2_n", Pins("F16")), - Subsignal("scl", Pins("J16")), - Subsignal("sda", Pins("K16")), - IOStandard("LVCMOS33") - ), - ("dvi_pots", 0, - Subsignal("charge", Pins("A18")), # SD_DAT0 - Subsignal("blackout", Pins("C17")), # SD_DAT2 - Subsignal("crossfade", Pins("A17")), # SD_DAT3 - IOStandard("LVCMOS33") - ) + ("user_led", 0, Pins("B16"), IOStandard("LVCMOS33"), Drive(24), Misc("SLEW=QUIETIO")), + ("user_led", 1, Pins("A16"), IOStandard("LVCMOS33"), Drive(24), Misc("SLEW=QUIETIO")), + + ("user_btn", 0, Pins("AB4"), IOStandard("LVCMOS33")), + ("user_btn", 1, Pins("AA4"), IOStandard("LVCMOS33")), + ("user_btn", 2, Pins("AB5"), IOStandard("LVCMOS33")), + + ("clk50", 0, Pins("AB11"), IOStandard("LVCMOS33")), + + # When executing softcore code in-place from the flash, we want + # the flash reset to be released before the system reset. + ("norflash_rst_n", 0, Pins("P22"), IOStandard("LVCMOS33"), Misc("SLEW=FAST"), Drive(8)), + ("norflash", 0, + Subsignal("adr", Pins("L22 L20 K22 K21 J19 H20 F22", + "F21 K17 J17 E22 E20 H18 H19 F20", + "G19 C22 C20 D22 D21 F19 F18 D20 D19")), + Subsignal("d", Pins("AA20 U14 U13 AA6 AB6 W4 Y4 Y7", + "AA2 AB2 V15 AA18 AB18 Y13 AA12 AB12"), Misc("PULLDOWN")), + Subsignal("oe_n", Pins("M22")), + Subsignal("we_n", Pins("N20")), + Subsignal("ce_n", Pins("M21")), + IOStandard("LVCMOS33"), Misc("SLEW=FAST"), Drive(8) + ), + + ("serial", 0, + Subsignal("tx", Pins("L17"), IOStandard("LVCMOS33"), Misc("SLEW=SLOW")), + Subsignal("rx", Pins("K18"), IOStandard("LVCMOS33"), Misc("PULLUP")) + ), + + ("ddram_clock", 0, + Subsignal("p", Pins("M3")), + Subsignal("n", Pins("L4")), + IOStandard("SSTL2_I") + ), + ("ddram", 0, + Subsignal("a", Pins("B1 B2 H8 J7 E4 D5 K7 F5 G6 C1 C3 D1 D2")), + Subsignal("ba", Pins("A2 E6")), + Subsignal("cs_n", Pins("F7")), + Subsignal("cke", Pins("G7")), + Subsignal("ras_n", Pins("E5")), + Subsignal("cas_n", Pins("C4")), + Subsignal("we_n", Pins("D3")), + Subsignal("dq", Pins("Y2 W3 W1 P8 P7 P6 P5 T4 T3", + "U4 V3 N6 N7 M7 M8 R4 P4 M6 L6 P3 N4", + "M5 V2 V1 U3 U1 T2 T1 R3 R1 P2 P1")), + Subsignal("dm", Pins("E1 E3 F3 G4")), + Subsignal("dqs", Pins("F1 F2 H5 H6")), + IOStandard("SSTL2_I") + ), + + ("eth_clocks", 0, + Subsignal("phy", Pins("M20")), + Subsignal("rx", Pins("H22")), + Subsignal("tx", Pins("H21")), + IOStandard("LVCMOS33") + ), + ("eth", 0, + Subsignal("rst_n", Pins("R22")), + Subsignal("dv", Pins("V21")), + Subsignal("rx_er", Pins("V22")), + Subsignal("rx_data", Pins("U22 U20 T22 T21")), + Subsignal("tx_en", Pins("N19")), + Subsignal("tx_er", Pins("M19")), + Subsignal("tx_data", Pins("M16 L15 P19 P20")), + Subsignal("col", Pins("W20")), + Subsignal("crs", Pins("W22")), + IOStandard("LVCMOS33") + ), + + ("vga_out", 0, + Subsignal("clk", Pins("A11")), + Subsignal("r", Pins("C6 B6 A6 C7 A7 B8 A8 D9")), + Subsignal("g", Pins("C8 C9 A9 D7 D8 D10 C10 B10")), + Subsignal("b", Pins("D11 C12 B12 A12 C13 A13 D14 C14")), + Subsignal("hsync_n", Pins("A14")), + Subsignal("vsync_n", Pins("C15")), + Subsignal("psave_n", Pins("B14")), + IOStandard("LVCMOS33") + ), + + ("mmc", 0, + Subsignal("clk", Pins("A10")), + Subsignal("cmd", Pins("B18")), + Subsignal("dat", Pins("A18 E16 C17 A17")), + IOStandard("LVCMOS33") + ), + + # Digital video mixer extension board + ("dvi_in", 0, + Subsignal("clk", Pins("A20")), + Subsignal("data0_n", Pins("A21")), + Subsignal("data1", Pins("B21")), + Subsignal("data2_n", Pins("B22")), + Subsignal("scl", Pins("G16")), + Subsignal("sda", Pins("G17")), + IOStandard("LVCMOS33") + ), + ("dvi_in", 1, + Subsignal("clk", Pins("H17")), + Subsignal("data0_n", Pins("H16")), + Subsignal("data1", Pins("F17")), + Subsignal("data2_n", Pins("F16")), + Subsignal("scl", Pins("J16")), + Subsignal("sda", Pins("K16")), + IOStandard("LVCMOS33") + ), + ("dvi_pots", 0, + Subsignal("charge", Pins("A18")), # SD_DAT0 + Subsignal("blackout", Pins("C17")), # SD_DAT2 + Subsignal("crossfade", Pins("A17")), # SD_DAT3 + IOStandard("LVCMOS33") + ) ] class Platform(XilinxPlatform): - identifier = 0x4D31 - default_clk_name = "clk50" - default_clk_period = 20 + identifier = 0x4D31 + default_clk_name = "clk50" + default_clk_period = 20 - def __init__(self): - XilinxPlatform.__init__(self, "xc6slx45-fgg484-2", _io) + def __init__(self): + XilinxPlatform.__init__(self, "xc6slx45-fgg484-2", _io) - def create_programmer(self): - return UrJTAG("fjmem-m1.bit") + def create_programmer(self): + return UrJTAG("fjmem-m1.bit") - def do_finalize(self, fragment): - XilinxPlatform.do_finalize(self, fragment) + def do_finalize(self, fragment): + XilinxPlatform.do_finalize(self, fragment) - try: - eth_clocks = self.lookup_request("eth_clocks") - self.add_period_constraint(eth_clocks.rx, 40) - self.add_period_constraint(eth_clocks.tx, 40) - self.add_platform_command(""" + try: + eth_clocks = self.lookup_request("eth_clocks") + self.add_period_constraint(eth_clocks.rx, 40) + self.add_period_constraint(eth_clocks.tx, 40) + self.add_platform_command(""" TIMESPEC "TS{phy_tx_clk}_io" = FROM "GRP{phy_tx_clk}" TO "PADS" 10 ns; TIMESPEC "TS{phy_rx_clk}_io" = FROM "PADS" TO "GRP{phy_rx_clk}" 10 ns; """, phy_rx_clk=eth_clocks.rx, phy_tx_clk=eth_clocks.tx) - except ConstraintError: - pass - - for i in range(2): - si = "dviclk"+str(i) - try: - self.add_period_constraint(self.lookup_request("dvi_in", i).clk, 26.7) - except ConstraintError: - pass + except ConstraintError: + pass + + for i in range(2): + si = "dviclk"+str(i) + try: + self.add_period_constraint(self.lookup_request("dvi_in", i).clk, 26.7) + except ConstraintError: + pass diff --git a/mibuild/platforms/minispartan6.py b/mibuild/platforms/minispartan6.py index 88987729..1db3d4db 100644 --- a/mibuild/platforms/minispartan6.py +++ b/mibuild/platforms/minispartan6.py @@ -6,119 +6,119 @@ from mibuild.xilinx import XilinxPlatform from mibuild.xilinx.programmer import XC3SProg, FpgaProg _io = [ - ("user_led", 0, Pins("P11"), IOStandard("LVCMOS33")), - ("user_led", 1, Pins("N9"), IOStandard("LVCMOS33")), - ("user_led", 2, Pins("M9"), IOStandard("LVCMOS33")), - ("user_led", 3, Pins("P9"), IOStandard("LVCMOS33")), - ("user_led", 4, Pins("T8"), IOStandard("LVCMOS33")), - ("user_led", 5, Pins("N8"), IOStandard("LVCMOS33")), - ("user_led", 6, Pins("P8"), IOStandard("LVCMOS33")), - ("user_led", 7, Pins("P7"), IOStandard("LVCMOS33")), - - ("user_sw", 0, Pins("L1"), IOStandard("LVCMOS33"), Misc("PULLUP")), - ("user_sw", 1, Pins("L3"), IOStandard("LVCMOS33"), Misc("PULLUP")), - ("user_sw", 2, Pins("L4"), IOStandard("LVCMOS33"), Misc("PULLUP")), - ("user_sw", 3, Pins("L5"), IOStandard("LVCMOS33"), Misc("PULLUP")), - - ("clk32", 0, Pins("J4"), IOStandard("LVCMOS33")), - ("clk50", 0, Pins("K3"), IOStandard("LVCMOS33")), - - ("spiflash", 0, - Subsignal("cs_n", Pins("T3"), IOStandard("LVCMOS33")), - Subsignal("clk", Pins("R11"), IOStandard("LVCMOS33")), - Subsignal("mosi", Pins("T10"), IOStandard("LVCMOS33")), - Subsignal("miso", Pins("P10"), IOStandard("LVCMOS33")) - ), - - ("adc", 0, - Subsignal("cs_n", Pins("F6"), IOStandard("LVCMOS33")), - Subsignal("clk", Pins("G6"), IOStandard("LVCMOS33")), - Subsignal("mosi", Pins("H4"), IOStandard("LVCMOS33")), - Subsignal("miso", Pins("H5"), IOStandard("LVCMOS33")) - ), - - ("serial", 0, - Subsignal("tx", Pins("N6"), IOStandard("LVCMOS33")), # FTDI D1 - Subsignal("rx", Pins("M7"), IOStandard("LVCMOS33")) # FTDI D0 - ), - - ("audio", 0, - Subsignal("a0", Pins("B8"), IOStandard("LVCMOS33")), - Subsignal("a1", Pins("A8"), IOStandard("LVCMOS33")) - ), - - ("sdram_clock", 0, Pins("G16"), IOStandard("LVCMOS33"), Misc("SLEW=FAST")), - ("sdram", 0, - Subsignal("a", Pins("T15 R16 P15 P16 N16 M15 M16 L16 K15 K16 R15 J16 H15")), - Subsignal("dq", Pins("T13 T12 R12 T9 R9 T7 R7 T6 F16 E15 E16 D16 B16 B15 C16 C15")), - Subsignal("we_n", Pins("R5")), - Subsignal("ras_n", Pins("R2")), - Subsignal("cas_n", Pins("T4")), - Subsignal("cs_n", Pins("R1")), - Subsignal("cke", Pins("H16")), - Subsignal("ba", Pins("R14 T14")), - Subsignal("dm", Pins("T5 F15")), - IOStandard("LVCMOS33"), Misc("SLEW=FAST") - ), - - ("ftdi_fifo", 0, - Subsignal("data", Pins("M7 N6 M6 P5 N5 P4 P2 P1")), - Subsignal("rxf_n", Pins("N3")), - Subsignal("txe_n", Pins("N1")), - Subsignal("rd_n", Pins("M2")), - Subsignal("wr_n", Pins("M1")), - Subsignal("siwua", Pins("M3")), - IOStandard("LVCMOS33"), Drive(8), Misc("SLEW=FAST") - ), - - ("sd", 0, - Subsignal("sck", Pins("L12")), - Subsignal("d3", Pins("K12")), - Subsignal("d", Pins("M10")), - Subsignal("d1", Pins("L10")), - Subsignal("d2", Pins("J11")), - Subsignal("cmd", Pins("K11")), - IOStandard("LVCMOS33") - ), - - ("dvi_in", 0, - Subsignal("clk_p", Pins("C9"), IOStandard("TMDS_33")), - Subsignal("clk_n", Pins("A9"), IOStandard("TMDS_33")), - Subsignal("data_p", Pins("C7 B6 B5"), IOStandard("TMDS_33")), - Subsignal("data_n", Pins("A7 A6 A5"), IOStandard("TMDS_33")), - Subsignal("scl", Pins("C1"), IOStandard("LVCMOS33")), - Subsignal("sda", Pins("B1"), IOStandard("LVCMOS33")) - ), - - ("dvi_out", 0, - Subsignal("clk_p", Pins("B14"), IOStandard("TMDS_33")), - Subsignal("clk_n", Pins("A14"), IOStandard("TMDS_33")), - Subsignal("data_p", Pins("C13 B12 C11"), IOStandard("TMDS_33")), - Subsignal("data_n", Pins("A13 A12 A11"), IOStandard("TMDS_33")), - ) + ("user_led", 0, Pins("P11"), IOStandard("LVCMOS33")), + ("user_led", 1, Pins("N9"), IOStandard("LVCMOS33")), + ("user_led", 2, Pins("M9"), IOStandard("LVCMOS33")), + ("user_led", 3, Pins("P9"), IOStandard("LVCMOS33")), + ("user_led", 4, Pins("T8"), IOStandard("LVCMOS33")), + ("user_led", 5, Pins("N8"), IOStandard("LVCMOS33")), + ("user_led", 6, Pins("P8"), IOStandard("LVCMOS33")), + ("user_led", 7, Pins("P7"), IOStandard("LVCMOS33")), + + ("user_sw", 0, Pins("L1"), IOStandard("LVCMOS33"), Misc("PULLUP")), + ("user_sw", 1, Pins("L3"), IOStandard("LVCMOS33"), Misc("PULLUP")), + ("user_sw", 2, Pins("L4"), IOStandard("LVCMOS33"), Misc("PULLUP")), + ("user_sw", 3, Pins("L5"), IOStandard("LVCMOS33"), Misc("PULLUP")), + + ("clk32", 0, Pins("J4"), IOStandard("LVCMOS33")), + ("clk50", 0, Pins("K3"), IOStandard("LVCMOS33")), + + ("spiflash", 0, + Subsignal("cs_n", Pins("T3"), IOStandard("LVCMOS33")), + Subsignal("clk", Pins("R11"), IOStandard("LVCMOS33")), + Subsignal("mosi", Pins("T10"), IOStandard("LVCMOS33")), + Subsignal("miso", Pins("P10"), IOStandard("LVCMOS33")) + ), + + ("adc", 0, + Subsignal("cs_n", Pins("F6"), IOStandard("LVCMOS33")), + Subsignal("clk", Pins("G6"), IOStandard("LVCMOS33")), + Subsignal("mosi", Pins("H4"), IOStandard("LVCMOS33")), + Subsignal("miso", Pins("H5"), IOStandard("LVCMOS33")) + ), + + ("serial", 0, + Subsignal("tx", Pins("N6"), IOStandard("LVCMOS33")), # FTDI D1 + Subsignal("rx", Pins("M7"), IOStandard("LVCMOS33")) # FTDI D0 + ), + + ("audio", 0, + Subsignal("a0", Pins("B8"), IOStandard("LVCMOS33")), + Subsignal("a1", Pins("A8"), IOStandard("LVCMOS33")) + ), + + ("sdram_clock", 0, Pins("G16"), IOStandard("LVCMOS33"), Misc("SLEW=FAST")), + ("sdram", 0, + Subsignal("a", Pins("T15 R16 P15 P16 N16 M15 M16 L16 K15 K16 R15 J16 H15")), + Subsignal("dq", Pins("T13 T12 R12 T9 R9 T7 R7 T6 F16 E15 E16 D16 B16 B15 C16 C15")), + Subsignal("we_n", Pins("R5")), + Subsignal("ras_n", Pins("R2")), + Subsignal("cas_n", Pins("T4")), + Subsignal("cs_n", Pins("R1")), + Subsignal("cke", Pins("H16")), + Subsignal("ba", Pins("R14 T14")), + Subsignal("dm", Pins("T5 F15")), + IOStandard("LVCMOS33"), Misc("SLEW=FAST") + ), + + ("ftdi_fifo", 0, + Subsignal("data", Pins("M7 N6 M6 P5 N5 P4 P2 P1")), + Subsignal("rxf_n", Pins("N3")), + Subsignal("txe_n", Pins("N1")), + Subsignal("rd_n", Pins("M2")), + Subsignal("wr_n", Pins("M1")), + Subsignal("siwua", Pins("M3")), + IOStandard("LVCMOS33"), Drive(8), Misc("SLEW=FAST") + ), + + ("sd", 0, + Subsignal("sck", Pins("L12")), + Subsignal("d3", Pins("K12")), + Subsignal("d", Pins("M10")), + Subsignal("d1", Pins("L10")), + Subsignal("d2", Pins("J11")), + Subsignal("cmd", Pins("K11")), + IOStandard("LVCMOS33") + ), + + ("dvi_in", 0, + Subsignal("clk_p", Pins("C9"), IOStandard("TMDS_33")), + Subsignal("clk_n", Pins("A9"), IOStandard("TMDS_33")), + Subsignal("data_p", Pins("C7 B6 B5"), IOStandard("TMDS_33")), + Subsignal("data_n", Pins("A7 A6 A5"), IOStandard("TMDS_33")), + Subsignal("scl", Pins("C1"), IOStandard("LVCMOS33")), + Subsignal("sda", Pins("B1"), IOStandard("LVCMOS33")) + ), + + ("dvi_out", 0, + Subsignal("clk_p", Pins("B14"), IOStandard("TMDS_33")), + Subsignal("clk_n", Pins("A14"), IOStandard("TMDS_33")), + Subsignal("data_p", Pins("C13 B12 C11"), IOStandard("TMDS_33")), + Subsignal("data_n", Pins("A13 A12 A11"), IOStandard("TMDS_33")), + ) ] _connectors = [ - ("A", "E7 C8 D8 E8 D9 A10 B10 C10 E10 F9 F10 D11"), - ("B", "E11 D14 D12 E12 E13 F13 F12 F14 G12 H14 J14"), - ("C", "J13 J12 K14 L14 L13 M14 M13 N14 M12 N12 P12 M11"), - ("D", "D6 C6 E6 C5"), - ("E", "D5 A4 G5 A3 B3 A2 B2 C3 C2 D3 D1 E3"), - ("F", "E2 E1 E4 F4 F5 G3 F3 G1 H3 H1 H2 J1") + ("A", "E7 C8 D8 E8 D9 A10 B10 C10 E10 F9 F10 D11"), + ("B", "E11 D14 D12 E12 E13 F13 F12 F14 G12 H14 J14"), + ("C", "J13 J12 K14 L14 L13 M14 M13 N14 M12 N12 P12 M11"), + ("D", "D6 C6 E6 C5"), + ("E", "D5 A4 G5 A3 B3 A2 B2 C3 C2 D3 D1 E3"), + ("F", "E2 E1 E4 F4 F5 G3 F3 G1 H3 H1 H2 J1") ] class Platform(XilinxPlatform): - default_clk_name = "clk32" - default_clk_period = 31.25 - - def __init__(self, device="xc6slx9", programmer="xc3sprog"): - self.programmer = programmer - XilinxPlatform.__init__(self, device+"-3-ftg256", _io, _connectors) - - def create_programmer(self): - if self.programmer == "xc3sprog": - return XC3SProg("minispartan6", "bscan_spi_minispartan6.bit") - elif self.programmer == "fpgaprog": - return FpgaProg() - else: - raise ValueError("{} programmer is not supported".format(programmer)) + default_clk_name = "clk32" + default_clk_period = 31.25 + + def __init__(self, device="xc6slx9", programmer="xc3sprog"): + self.programmer = programmer + XilinxPlatform.__init__(self, device+"-3-ftg256", _io, _connectors) + + def create_programmer(self): + if self.programmer == "xc3sprog": + return XC3SProg("minispartan6", "bscan_spi_minispartan6.bit") + elif self.programmer == "fpgaprog": + return FpgaProg() + else: + raise ValueError("{} programmer is not supported".format(programmer)) diff --git a/mibuild/platforms/mixxeo.py b/mibuild/platforms/mixxeo.py index 356f9883..217baf18 100644 --- a/mibuild/platforms/mixxeo.py +++ b/mibuild/platforms/mixxeo.py @@ -3,184 +3,184 @@ from mibuild.xilinx import XilinxPlatform from mibuild.xilinx.programmer import UrJTAG _io = [ - ("user_led", 0, Pins("V5"), IOStandard("LVCMOS33"), Drive(24), Misc("SLEW=QUIETIO")), + ("user_led", 0, Pins("V5"), IOStandard("LVCMOS33"), Drive(24), Misc("SLEW=QUIETIO")), - ("clk50", 0, Pins("AB13"), IOStandard("LVCMOS33")), + ("clk50", 0, Pins("AB13"), IOStandard("LVCMOS33")), - # When executing softcore code in-place from the flash, we want - # the flash reset to be released before the system reset. - ("norflash_rst_n", 0, Pins("P22"), IOStandard("LVCMOS33"), Misc("SLEW=FAST"), Drive(8)), - ("norflash", 0, - Subsignal("adr", Pins("L22 L20 K22 K21 J19 H20 F22", - "F21 K17 J17 E22 E20 H18 H19 F20", - "G19 C22 C20 D22 D21 F19 F18 D20 D19")), - Subsignal("d", Pins("AA20 U14 U13 AA6 AB6 W4 Y4 Y7", - "AA2 AB2 V15 AA18 AB18 Y13 AA12 AB12"), Misc("PULLDOWN")), - Subsignal("oe_n", Pins("M22")), - Subsignal("we_n", Pins("N20")), - Subsignal("ce_n", Pins("M21")), - IOStandard("LVCMOS33"), Misc("SLEW=FAST"), Drive(8) - ), + # When executing softcore code in-place from the flash, we want + # the flash reset to be released before the system reset. + ("norflash_rst_n", 0, Pins("P22"), IOStandard("LVCMOS33"), Misc("SLEW=FAST"), Drive(8)), + ("norflash", 0, + Subsignal("adr", Pins("L22 L20 K22 K21 J19 H20 F22", + "F21 K17 J17 E22 E20 H18 H19 F20", + "G19 C22 C20 D22 D21 F19 F18 D20 D19")), + Subsignal("d", Pins("AA20 U14 U13 AA6 AB6 W4 Y4 Y7", + "AA2 AB2 V15 AA18 AB18 Y13 AA12 AB12"), Misc("PULLDOWN")), + Subsignal("oe_n", Pins("M22")), + Subsignal("we_n", Pins("N20")), + Subsignal("ce_n", Pins("M21")), + IOStandard("LVCMOS33"), Misc("SLEW=FAST"), Drive(8) + ), - ("serial", 0, - Subsignal("tx", Pins("L17"), IOStandard("LVCMOS33"), Misc("SLEW=SLOW")), - Subsignal("rx", Pins("K18"), IOStandard("LVCMOS33"), Misc("PULLUP")) - ), + ("serial", 0, + Subsignal("tx", Pins("L17"), IOStandard("LVCMOS33"), Misc("SLEW=SLOW")), + Subsignal("rx", Pins("K18"), IOStandard("LVCMOS33"), Misc("PULLUP")) + ), - ("ddram_clock", 0, - Subsignal("p", Pins("M3")), - Subsignal("n", Pins("L4")), - IOStandard("SSTL2_I") - ), - ("ddram", 0, - Subsignal("a", Pins("B1 B2 H8 J7 E4 D5 K7 F5 G6 C1 C3 D1 D2")), - Subsignal("ba", Pins("A2 E6")), - Subsignal("cs_n", Pins("F7")), - Subsignal("cke", Pins("G7")), - Subsignal("ras_n", Pins("E5")), - Subsignal("cas_n", Pins("C4")), - Subsignal("we_n", Pins("D3")), - Subsignal("dq", Pins("Y2 W3 W1 P8 P7 P6 P5 T4 T3", - "U4 V3 N6 N7 M7 M8 R4 P4 M6 L6 P3 N4", - "M5 V2 V1 U3 U1 T2 T1 R3 R1 P2 P1")), - Subsignal("dm", Pins("E1 E3 F3 G4")), - Subsignal("dqs", Pins("F1 F2 H5 H6")), - IOStandard("SSTL2_I") - ), + ("ddram_clock", 0, + Subsignal("p", Pins("M3")), + Subsignal("n", Pins("L4")), + IOStandard("SSTL2_I") + ), + ("ddram", 0, + Subsignal("a", Pins("B1 B2 H8 J7 E4 D5 K7 F5 G6 C1 C3 D1 D2")), + Subsignal("ba", Pins("A2 E6")), + Subsignal("cs_n", Pins("F7")), + Subsignal("cke", Pins("G7")), + Subsignal("ras_n", Pins("E5")), + Subsignal("cas_n", Pins("C4")), + Subsignal("we_n", Pins("D3")), + Subsignal("dq", Pins("Y2 W3 W1 P8 P7 P6 P5 T4 T3", + "U4 V3 N6 N7 M7 M8 R4 P4 M6 L6 P3 N4", + "M5 V2 V1 U3 U1 T2 T1 R3 R1 P2 P1")), + Subsignal("dm", Pins("E1 E3 F3 G4")), + Subsignal("dqs", Pins("F1 F2 H5 H6")), + IOStandard("SSTL2_I") + ), - ("eth_clocks", 0, - Subsignal("phy", Pins("M20")), - Subsignal("rx", Pins("H22")), - Subsignal("tx", Pins("H21")), - IOStandard("LVCMOS33") - ), - ("eth", 0, - Subsignal("rst_n", Pins("R22")), - Subsignal("dv", Pins("V21")), - Subsignal("rx_er", Pins("V22")), - Subsignal("rx_data", Pins("U22 U20 T22 T21")), - Subsignal("tx_en", Pins("N19")), - Subsignal("tx_er", Pins("M19")), - Subsignal("tx_data", Pins("M16 L15 P19 P20")), - Subsignal("col", Pins("W20")), - Subsignal("crs", Pins("W22")), - IOStandard("LVCMOS33") - ), + ("eth_clocks", 0, + Subsignal("phy", Pins("M20")), + Subsignal("rx", Pins("H22")), + Subsignal("tx", Pins("H21")), + IOStandard("LVCMOS33") + ), + ("eth", 0, + Subsignal("rst_n", Pins("R22")), + Subsignal("dv", Pins("V21")), + Subsignal("rx_er", Pins("V22")), + Subsignal("rx_data", Pins("U22 U20 T22 T21")), + Subsignal("tx_en", Pins("N19")), + Subsignal("tx_er", Pins("M19")), + Subsignal("tx_data", Pins("M16 L15 P19 P20")), + Subsignal("col", Pins("W20")), + Subsignal("crs", Pins("W22")), + IOStandard("LVCMOS33") + ), - ("vga_out", 0, - Subsignal("clk", Pins("A10")), - Subsignal("r", Pins("C6 B6 A6 C7 A7 B8 A8 D9")), - Subsignal("g", Pins("C8 C9 A9 D7 D8 D10 C10 B10")), - Subsignal("b", Pins("D11 C12 B12 A12 C13 A13 D14 C14")), - Subsignal("hsync_n", Pins("A14")), - Subsignal("vsync_n", Pins("C15")), - Subsignal("psave_n", Pins("B14")), - IOStandard("LVCMOS33") - ), - ("dvi_out", 0, - Subsignal("clk_p", Pins("W12"), IOStandard("TMDS_33")), - Subsignal("clk_n", Pins("Y12"), IOStandard("TMDS_33")), - Subsignal("data0_p", Pins("Y16"), IOStandard("TMDS_33")), - Subsignal("data0_n", Pins("W15"), IOStandard("TMDS_33")), - Subsignal("data1_p", Pins("AA16"), IOStandard("TMDS_33")), - Subsignal("data1_n", Pins("AB16"), IOStandard("TMDS_33")), - Subsignal("data2_p", Pins("Y15"), IOStandard("TMDS_33")), - Subsignal("data2_n", Pins("AB15"), IOStandard("TMDS_33")), - ), + ("vga_out", 0, + Subsignal("clk", Pins("A10")), + Subsignal("r", Pins("C6 B6 A6 C7 A7 B8 A8 D9")), + Subsignal("g", Pins("C8 C9 A9 D7 D8 D10 C10 B10")), + Subsignal("b", Pins("D11 C12 B12 A12 C13 A13 D14 C14")), + Subsignal("hsync_n", Pins("A14")), + Subsignal("vsync_n", Pins("C15")), + Subsignal("psave_n", Pins("B14")), + IOStandard("LVCMOS33") + ), + ("dvi_out", 0, + Subsignal("clk_p", Pins("W12"), IOStandard("TMDS_33")), + Subsignal("clk_n", Pins("Y12"), IOStandard("TMDS_33")), + Subsignal("data0_p", Pins("Y16"), IOStandard("TMDS_33")), + Subsignal("data0_n", Pins("W15"), IOStandard("TMDS_33")), + Subsignal("data1_p", Pins("AA16"), IOStandard("TMDS_33")), + Subsignal("data1_n", Pins("AB16"), IOStandard("TMDS_33")), + Subsignal("data2_p", Pins("Y15"), IOStandard("TMDS_33")), + Subsignal("data2_n", Pins("AB15"), IOStandard("TMDS_33")), + ), - ("mmc", 0, - Subsignal("clk", Pins("J3")), - Subsignal("cmd", Pins("K1")), - Subsignal("dat", Pins("J6 K6 N1 K5")), - IOStandard("LVCMOS33") - ), + ("mmc", 0, + Subsignal("clk", Pins("J3")), + Subsignal("cmd", Pins("K1")), + Subsignal("dat", Pins("J6 K6 N1 K5")), + IOStandard("LVCMOS33") + ), - ("dvi_in", 0, - Subsignal("clk_p", Pins("K20"), IOStandard("TMDS_33")), - Subsignal("clk_n", Pins("K19"), IOStandard("TMDS_33")), - Subsignal("data0_p", Pins("B21"), IOStandard("TMDS_33")), - Subsignal("data0_n", Pins("B22"), IOStandard("TMDS_33")), - Subsignal("data1_p", Pins("A20"), IOStandard("TMDS_33")), - Subsignal("data1_n", Pins("A21"), IOStandard("TMDS_33")), - Subsignal("data2_p", Pins("K16"), IOStandard("TMDS_33")), - Subsignal("data2_n", Pins("J16"), IOStandard("TMDS_33")), - Subsignal("scl", Pins("G20"), IOStandard("LVCMOS33")), - Subsignal("sda", Pins("H16"), IOStandard("LVCMOS33")), - Subsignal("hpd_notif", Pins("G22"), IOStandard("LVCMOS33")), - Subsignal("hpd_en", Pins("G17"), IOStandard("LVCMOS33")) - ), - ("dvi_in", 1, - Subsignal("clk_p", Pins("C11"), IOStandard("TMDS_33")), - Subsignal("clk_n", Pins("A11"), IOStandard("TMDS_33")), - Subsignal("data0_p", Pins("B18"), IOStandard("TMDS_33")), - Subsignal("data0_n", Pins("A18"), IOStandard("TMDS_33")), - Subsignal("data1_p", Pins("C17"), IOStandard("TMDS_33")), - Subsignal("data1_n", Pins("A17"), IOStandard("TMDS_33")), - Subsignal("data2_p", Pins("E16"), IOStandard("TMDS_33")), - Subsignal("data2_n", Pins("D17"), IOStandard("TMDS_33")), - Subsignal("scl", Pins("F17"), IOStandard("LVCMOS33")), - Subsignal("sda", Pins("F16"), IOStandard("LVCMOS33")), - Subsignal("hpd_notif", Pins("G16"), IOStandard("LVCMOS33")), - Subsignal("hpd_en", Pins("B20"), IOStandard("LVCMOS33")) - ), - ("dvi_in", 2, - Subsignal("clk_p", Pins("Y11"), IOStandard("TMDS_33")), - Subsignal("clk_n", Pins("AB11"), IOStandard("TMDS_33")), - Subsignal("data0_p", Pins("V11"), IOStandard("TMDS_33")), - Subsignal("data0_n", Pins("W11"), IOStandard("TMDS_33")), - Subsignal("data1_p", Pins("AA10"), IOStandard("TMDS_33")), - Subsignal("data1_n", Pins("AB10"), IOStandard("TMDS_33")), - Subsignal("data2_p", Pins("R11"), IOStandard("TMDS_33")), - Subsignal("data2_n", Pins("T11"), IOStandard("TMDS_33")), - Subsignal("scl", Pins("C16"), IOStandard("LVCMOS33")), - Subsignal("sda", Pins("B16"), IOStandard("LVCMOS33")), - Subsignal("hpd_notif", Pins("D6"), IOStandard("LVCMOS33")), - Subsignal("hpd_en", Pins("A4"), IOStandard("LVCMOS33")) - ), - ("dvi_in", 3, - Subsignal("clk_p", Pins("J20"), IOStandard("TMDS_33")), - Subsignal("clk_n", Pins("J22"), IOStandard("TMDS_33")), - Subsignal("data0_p", Pins("P18"), IOStandard("TMDS_33")), - Subsignal("data0_n", Pins("R19"), IOStandard("TMDS_33")), - Subsignal("data1_p", Pins("P17"), IOStandard("TMDS_33")), - Subsignal("data1_n", Pins("N16"), IOStandard("TMDS_33")), - Subsignal("data2_p", Pins("M17"), IOStandard("TMDS_33")), - Subsignal("data2_n", Pins("M18"), IOStandard("TMDS_33")), - Subsignal("scl", Pins("P21"), IOStandard("LVCMOS33")), - Subsignal("sda", Pins("N22"), IOStandard("LVCMOS33")), - Subsignal("hpd_notif", Pins("H17"), IOStandard("LVCMOS33")), - Subsignal("hpd_en", Pins("C19"), IOStandard("LVCMOS33")) - ), + ("dvi_in", 0, + Subsignal("clk_p", Pins("K20"), IOStandard("TMDS_33")), + Subsignal("clk_n", Pins("K19"), IOStandard("TMDS_33")), + Subsignal("data0_p", Pins("B21"), IOStandard("TMDS_33")), + Subsignal("data0_n", Pins("B22"), IOStandard("TMDS_33")), + Subsignal("data1_p", Pins("A20"), IOStandard("TMDS_33")), + Subsignal("data1_n", Pins("A21"), IOStandard("TMDS_33")), + Subsignal("data2_p", Pins("K16"), IOStandard("TMDS_33")), + Subsignal("data2_n", Pins("J16"), IOStandard("TMDS_33")), + Subsignal("scl", Pins("G20"), IOStandard("LVCMOS33")), + Subsignal("sda", Pins("H16"), IOStandard("LVCMOS33")), + Subsignal("hpd_notif", Pins("G22"), IOStandard("LVCMOS33")), + Subsignal("hpd_en", Pins("G17"), IOStandard("LVCMOS33")) + ), + ("dvi_in", 1, + Subsignal("clk_p", Pins("C11"), IOStandard("TMDS_33")), + Subsignal("clk_n", Pins("A11"), IOStandard("TMDS_33")), + Subsignal("data0_p", Pins("B18"), IOStandard("TMDS_33")), + Subsignal("data0_n", Pins("A18"), IOStandard("TMDS_33")), + Subsignal("data1_p", Pins("C17"), IOStandard("TMDS_33")), + Subsignal("data1_n", Pins("A17"), IOStandard("TMDS_33")), + Subsignal("data2_p", Pins("E16"), IOStandard("TMDS_33")), + Subsignal("data2_n", Pins("D17"), IOStandard("TMDS_33")), + Subsignal("scl", Pins("F17"), IOStandard("LVCMOS33")), + Subsignal("sda", Pins("F16"), IOStandard("LVCMOS33")), + Subsignal("hpd_notif", Pins("G16"), IOStandard("LVCMOS33")), + Subsignal("hpd_en", Pins("B20"), IOStandard("LVCMOS33")) + ), + ("dvi_in", 2, + Subsignal("clk_p", Pins("Y11"), IOStandard("TMDS_33")), + Subsignal("clk_n", Pins("AB11"), IOStandard("TMDS_33")), + Subsignal("data0_p", Pins("V11"), IOStandard("TMDS_33")), + Subsignal("data0_n", Pins("W11"), IOStandard("TMDS_33")), + Subsignal("data1_p", Pins("AA10"), IOStandard("TMDS_33")), + Subsignal("data1_n", Pins("AB10"), IOStandard("TMDS_33")), + Subsignal("data2_p", Pins("R11"), IOStandard("TMDS_33")), + Subsignal("data2_n", Pins("T11"), IOStandard("TMDS_33")), + Subsignal("scl", Pins("C16"), IOStandard("LVCMOS33")), + Subsignal("sda", Pins("B16"), IOStandard("LVCMOS33")), + Subsignal("hpd_notif", Pins("D6"), IOStandard("LVCMOS33")), + Subsignal("hpd_en", Pins("A4"), IOStandard("LVCMOS33")) + ), + ("dvi_in", 3, + Subsignal("clk_p", Pins("J20"), IOStandard("TMDS_33")), + Subsignal("clk_n", Pins("J22"), IOStandard("TMDS_33")), + Subsignal("data0_p", Pins("P18"), IOStandard("TMDS_33")), + Subsignal("data0_n", Pins("R19"), IOStandard("TMDS_33")), + Subsignal("data1_p", Pins("P17"), IOStandard("TMDS_33")), + Subsignal("data1_n", Pins("N16"), IOStandard("TMDS_33")), + Subsignal("data2_p", Pins("M17"), IOStandard("TMDS_33")), + Subsignal("data2_n", Pins("M18"), IOStandard("TMDS_33")), + Subsignal("scl", Pins("P21"), IOStandard("LVCMOS33")), + Subsignal("sda", Pins("N22"), IOStandard("LVCMOS33")), + Subsignal("hpd_notif", Pins("H17"), IOStandard("LVCMOS33")), + Subsignal("hpd_en", Pins("C19"), IOStandard("LVCMOS33")) + ), ] class Platform(XilinxPlatform): - identifier = 0x4D58 - default_clk_name = "clk50" - default_clk_period = 20 + identifier = 0x4D58 + default_clk_name = "clk50" + default_clk_period = 20 - def __init__(self): - XilinxPlatform.__init__(self, "xc6slx45-fgg484-2", _io) - self.add_platform_command("CONFIG VCCAUX=\"3.3\";\n") + def __init__(self): + XilinxPlatform.__init__(self, "xc6slx45-fgg484-2", _io) + self.add_platform_command("CONFIG VCCAUX=\"3.3\";\n") - def create_programmer(self): - return UrJTAG("fjmem-mixxeo.bit") + def create_programmer(self): + return UrJTAG("fjmem-mixxeo.bit") - def do_finalize(self, fragment): - XilinxPlatform.do_finalize(self, fragment) + def do_finalize(self, fragment): + XilinxPlatform.do_finalize(self, fragment) - try: - eth_clocks = self.lookup_request("eth_clocks") - self.add_period_constraint(eth_clocks.rx, 40) - self.add_period_constraint(eth_clocks.tx, 40) - self.add_platform_command(""" + try: + eth_clocks = self.lookup_request("eth_clocks") + self.add_period_constraint(eth_clocks.rx, 40) + self.add_period_constraint(eth_clocks.tx, 40) + self.add_platform_command(""" TIMESPEC "TS{phy_tx_clk}_io" = FROM "GRP{phy_tx_clk}" TO "PADS" 10 ns; TIMESPEC "TS{phy_rx_clk}_io" = FROM "PADS" TO "GRP{phy_rx_clk}" 10 ns; """, phy_rx_clk=eth_clocks.rx, phy_tx_clk=eth_clocks.tx) - except ConstraintError: - pass + except ConstraintError: + pass - for i in range(4): - try: - self.add_period_constraint(self.lookup_request("dvi_in", i).clk_p, 12) - except ConstraintError: - pass + for i in range(4): + try: + self.add_period_constraint(self.lookup_request("dvi_in", i).clk_p, 12) + except ConstraintError: + pass diff --git a/mibuild/platforms/ml605.py b/mibuild/platforms/ml605.py index ac4cf9f9..ccec0eed 100644 --- a/mibuild/platforms/ml605.py +++ b/mibuild/platforms/ml605.py @@ -2,57 +2,57 @@ from mibuild.generic_platform import * from mibuild.xilinx import XilinxPlatform _io = [ - # System clock (Differential 200MHz) - ("clk200", 0, - Subsignal("p", Pins("J9"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE")), - Subsignal("n", Pins("H9"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE")) - ), - - # User clock (66MHz) - ("clk66", 0, Pins("U23"), IOStandard("LVCMOS25")), - - # CPU reset switch - ("cpu_reset", 0, Pins("H10"), IOStandard("SSTL15")), - - # LEDs - ("user_led", 0, Pins("AC22"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), - ("user_led", 1, Pins("AC24"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), - ("user_led", 2, Pins("AE22"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), - ("user_led", 3, Pins("AE23"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), - ("user_led", 4, Pins("AB23"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), - ("user_led", 5, Pins("AG23"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), - ("user_led", 6, Pins("AE24"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), - ("user_led", 7, Pins("AD24"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), - - # USB-to-UART - ("serial", 0, - Subsignal("tx", Pins("J25"), IOStandard("LVCMOS25")), - Subsignal("rx", Pins("J24"), IOStandard("LVCMOS25")) - ), - - # 10/100/1000 Tri-Speed Ethernet PHY - ("eth_clocks", 0, - Subsignal("rx", Pins("AP11")), - Subsignal("tx", Pins("AD12")), - IOStandard("LVCMOS25") - ), - ("eth", 0, - Subsignal("rst_n", Pins("AH13")), - Subsignal("dv", Pins("AM13")), - Subsignal("rx_er", Pins("AG12")), - Subsignal("rx_data", Pins("AN13 AF14 AE14 AN12 AM12 AD11 AC12 AC13")), - Subsignal("tx_en", Pins("AJ10")), - Subsignal("tx_er", Pins("AH10")), - Subsignal("tx_data", Pins("AM11 AL11 AG10 AG11 AL10 AM10 AE11 AF11")), - Subsignal("col", Pins("AK13")), - Subsignal("crs", Pins("AL13")), - IOStandard("LVCMOS25") - ) + # System clock (Differential 200MHz) + ("clk200", 0, + Subsignal("p", Pins("J9"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE")), + Subsignal("n", Pins("H9"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE")) + ), + + # User clock (66MHz) + ("clk66", 0, Pins("U23"), IOStandard("LVCMOS25")), + + # CPU reset switch + ("cpu_reset", 0, Pins("H10"), IOStandard("SSTL15")), + + # LEDs + ("user_led", 0, Pins("AC22"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), + ("user_led", 1, Pins("AC24"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), + ("user_led", 2, Pins("AE22"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), + ("user_led", 3, Pins("AE23"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), + ("user_led", 4, Pins("AB23"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), + ("user_led", 5, Pins("AG23"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), + ("user_led", 6, Pins("AE24"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), + ("user_led", 7, Pins("AD24"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), + + # USB-to-UART + ("serial", 0, + Subsignal("tx", Pins("J25"), IOStandard("LVCMOS25")), + Subsignal("rx", Pins("J24"), IOStandard("LVCMOS25")) + ), + + # 10/100/1000 Tri-Speed Ethernet PHY + ("eth_clocks", 0, + Subsignal("rx", Pins("AP11")), + Subsignal("tx", Pins("AD12")), + IOStandard("LVCMOS25") + ), + ("eth", 0, + Subsignal("rst_n", Pins("AH13")), + Subsignal("dv", Pins("AM13")), + Subsignal("rx_er", Pins("AG12")), + Subsignal("rx_data", Pins("AN13 AF14 AE14 AN12 AM12 AD11 AC12 AC13")), + Subsignal("tx_en", Pins("AJ10")), + Subsignal("tx_er", Pins("AH10")), + Subsignal("tx_data", Pins("AM11 AL11 AG10 AG11 AL10 AM10 AE11 AF11")), + Subsignal("col", Pins("AK13")), + Subsignal("crs", Pins("AL13")), + IOStandard("LVCMOS25") + ) ] class Platform(XilinxPlatform): - default_clk_name = "clk200" - default_clk_period = 5 + default_clk_name = "clk200" + default_clk_period = 5 - def __init__(self): - XilinxPlatform.__init__(self, "xc6vlx240t-ff1156-1", _io) + def __init__(self): + XilinxPlatform.__init__(self, "xc6vlx240t-ff1156-1", _io) diff --git a/mibuild/platforms/papilio_pro.py b/mibuild/platforms/papilio_pro.py index 2de08e94..741d7b0a 100644 --- a/mibuild/platforms/papilio_pro.py +++ b/mibuild/platforms/papilio_pro.py @@ -3,58 +3,58 @@ from mibuild.xilinx import XilinxPlatform from mibuild.xilinx.programmer import XC3SProg _io = [ - ("user_led", 0, Pins("P112"), IOStandard("LVCMOS33"), Drive(24), Misc("SLEW=QUIETIO")), - - ("clk32", 0, Pins("P94"), IOStandard("LVCMOS33")), - - ("serial", 0, - Subsignal("tx", Pins("P105"), IOStandard("LVCMOS33"), Misc("SLEW=SLOW")), - Subsignal("rx", Pins("P101"), IOStandard("LVCMOS33"), Misc("PULLUP")) - ), - - ("spiflash", 0, - Subsignal("cs_n", Pins("P38")), - Subsignal("clk", Pins("P70")), - Subsignal("mosi", Pins("P64")), - Subsignal("miso", Pins("P65"), Misc("PULLUP")), - IOStandard("LVCMOS33"), Misc("SLEW=FAST") - ), - ("spiflash2x", 0, - Subsignal("cs_n", Pins("P38")), - Subsignal("clk", Pins("P70")), - Subsignal("dq", Pins("P64", "P65")), - IOStandard("LVCMOS33"), Misc("SLEW=FAST") - ), - - ("sdram_clock", 0, Pins("P32"), IOStandard("LVCMOS33"), Misc("SLEW=FAST")), - ("sdram", 0, - Subsignal("a", Pins("P140 P139 P138 P137 P46 P45 P44", - "P43 P41 P40 P141 P35 P34")), - Subsignal("ba", Pins("P143 P142")), - Subsignal("cs_n", Pins("P1")), - Subsignal("cke", Pins("P33")), - Subsignal("ras_n", Pins("P2")), - Subsignal("cas_n", Pins("P5")), - Subsignal("we_n", Pins("P6")), - Subsignal("dq", Pins("P9 P10 P11 P12 P14 P15 P16 P8 P21 P22 P23 P24 P26 P27 P29 P30")), - Subsignal("dm", Pins("P7 P17")), - IOStandard("LVCMOS33"), Misc("SLEW=FAST") - ) + ("user_led", 0, Pins("P112"), IOStandard("LVCMOS33"), Drive(24), Misc("SLEW=QUIETIO")), + + ("clk32", 0, Pins("P94"), IOStandard("LVCMOS33")), + + ("serial", 0, + Subsignal("tx", Pins("P105"), IOStandard("LVCMOS33"), Misc("SLEW=SLOW")), + Subsignal("rx", Pins("P101"), IOStandard("LVCMOS33"), Misc("PULLUP")) + ), + + ("spiflash", 0, + Subsignal("cs_n", Pins("P38")), + Subsignal("clk", Pins("P70")), + Subsignal("mosi", Pins("P64")), + Subsignal("miso", Pins("P65"), Misc("PULLUP")), + IOStandard("LVCMOS33"), Misc("SLEW=FAST") + ), + ("spiflash2x", 0, + Subsignal("cs_n", Pins("P38")), + Subsignal("clk", Pins("P70")), + Subsignal("dq", Pins("P64", "P65")), + IOStandard("LVCMOS33"), Misc("SLEW=FAST") + ), + + ("sdram_clock", 0, Pins("P32"), IOStandard("LVCMOS33"), Misc("SLEW=FAST")), + ("sdram", 0, + Subsignal("a", Pins("P140 P139 P138 P137 P46 P45 P44", + "P43 P41 P40 P141 P35 P34")), + Subsignal("ba", Pins("P143 P142")), + Subsignal("cs_n", Pins("P1")), + Subsignal("cke", Pins("P33")), + Subsignal("ras_n", Pins("P2")), + Subsignal("cas_n", Pins("P5")), + Subsignal("we_n", Pins("P6")), + Subsignal("dq", Pins("P9 P10 P11 P12 P14 P15 P16 P8 P21 P22 P23 P24 P26 P27 P29 P30")), + Subsignal("dm", Pins("P7 P17")), + IOStandard("LVCMOS33"), Misc("SLEW=FAST") + ) ] _connectors = [ - ("A", "P48 P51 P56 P58 P61 P66 P67 P75 P79 P81 P83 P85 P88 P93 P98 P100"), - ("B", "P99 P97 P92 P87 P84 P82 P80 P78 P74 P95 P62 P59 P57 P55 P50 P47"), - ("C", "P114 P115 P116 P117 P118 P119 P120 P121 P123 P124 P126 P127 P131 P132 P133 P134") + ("A", "P48 P51 P56 P58 P61 P66 P67 P75 P79 P81 P83 P85 P88 P93 P98 P100"), + ("B", "P99 P97 P92 P87 P84 P82 P80 P78 P74 P95 P62 P59 P57 P55 P50 P47"), + ("C", "P114 P115 P116 P117 P118 P119 P120 P121 P123 P124 P126 P127 P131 P132 P133 P134") ] class Platform(XilinxPlatform): - identifier = 0x5050 - default_clk_name = "clk32" - default_clk_period = 31.25 + identifier = 0x5050 + default_clk_name = "clk32" + default_clk_period = 31.25 - def __init__(self): - XilinxPlatform.__init__(self, "xc6slx9-tqg144-2", _io, _connectors) + def __init__(self): + XilinxPlatform.__init__(self, "xc6slx9-tqg144-2", _io, _connectors) - def create_programmer(self): - return XC3SProg("papilio", "bscan_spi_lx9_papilio.bit") + def create_programmer(self): + return XC3SProg("papilio", "bscan_spi_lx9_papilio.bit") diff --git a/mibuild/platforms/pipistrello.py b/mibuild/platforms/pipistrello.py index 1776bc84..2b2c9cc6 100644 --- a/mibuild/platforms/pipistrello.py +++ b/mibuild/platforms/pipistrello.py @@ -3,134 +3,134 @@ from mibuild.xilinx import XilinxPlatform from mibuild.xilinx.programmer import XC3SProg _io = [ - ("user_led", 0, Pins("V16"), IOStandard("LVTTL"), Drive(8), Misc("SLEW=QUIETIO")), # green at hdmi - ("user_led", 1, Pins("U16"), IOStandard("LVTTL"), Drive(8), Misc("SLEW=QUIETIO")), # red at hdmi - ("user_led", 2, Pins("A16"), IOStandard("LVTTL"), Drive(8), Misc("SLEW=QUIETIO")), # green at msd - ("user_led", 3, Pins("A15"), IOStandard("LVTTL"), Drive(8), Misc("SLEW=QUIETIO")), # red at msd - ("user_led", 4, Pins("A12"), IOStandard("LVTTL"), Drive(8), Misc("SLEW=QUIETIO")), # red at usb - - ("user_btn", 0, Pins("N14"), IOStandard("LVTTL"), Misc("PULLDOWN")), - - ("clk50", 0, Pins("H17"), IOStandard("LVTTL")), - - ("serial", 0, - Subsignal("tx", Pins("A10")), - Subsignal("rx", Pins("A11"), Misc("PULLUP")), - Subsignal("rts", Pins("C10")), - Subsignal("cts", Pins("A9"), Misc("PULLUP")), - IOStandard("LVTTL"), - ), - - ("usb_fifo", 0, - Subsignal("data", Pins("A11 A10 C10 A9 B9 A8 B8 A7")), - Subsignal("rxf", Pins("C7")), - Subsignal("txe", Pins("A6")), - Subsignal("rd", Pins("B6")), - Subsignal("wr", Pins("A5")), - Subsignal("siwua", Pins("C5")), - IOStandard("LVTTL"), - ), - - ("hdmi", 0, - Subsignal("clk_p", Pins("U5"), IOStandard("TMDS_33")), - Subsignal("clk_n", Pins("V5"), IOStandard("TMDS_33")), - Subsignal("data0_p", Pins("T6"), IOStandard("TMDS_33")), - Subsignal("data0_n", Pins("V6"), IOStandard("TMDS_33")), - Subsignal("data1_p", Pins("U7"), IOStandard("TMDS_33")), - Subsignal("data1_n", Pins("V7"), IOStandard("TMDS_33")), - Subsignal("data2_p", Pins("U8"), IOStandard("TMDS_33")), - Subsignal("data2_n", Pins("V8"), IOStandard("TMDS_33")), - Subsignal("scl", Pins("V9"), IOStandard("I2C")), - Subsignal("sda", Pins("T9"), IOStandard("I2C")), - Subsignal("hpd_notif", Pins("R8"), IOStandard("LVTTL")), - ), - - ("spiflash", 0, - Subsignal("cs_n", Pins("V3")), - Subsignal("clk", Pins("R15")), - Subsignal("mosi", Pins("T13")), - Subsignal("miso", Pins("R13"), Misc("PULLUP")), - Subsignal("wp", Pins("T14")), - Subsignal("hold", Pins("V14")), - IOStandard("LVTTL"), Misc("SLEW=FAST") - ), - - ("spiflash2x", 0, - Subsignal("cs_n", Pins("V3")), - Subsignal("clk", Pins("R15")), - Subsignal("dq", Pins("T13 R13"), Misc("PULLUP")), - Subsignal("wp", Pins("T14")), - Subsignal("hold", Pins("V14")), - IOStandard("LVTTL"), Misc("SLEW=FAST") - ), - - ("spiflash4x", 0, - Subsignal("cs_n", Pins("V3")), - Subsignal("clk", Pins("R15")), - Subsignal("dq", Pins("T13 R13 T14 V14"), Misc("PULLUP")), - IOStandard("LVTTL"), Misc("SLEW=FAST") - ), - - ("mmc", 0, - Subsignal("clk", Pins("A3")), - Subsignal("cmd", Pins("B3"), Misc("PULLUP")), - Subsignal("dat", Pins("B4 A4 B2 A2"), Misc("PULLUP")), - IOStandard("SDIO") - ), - - ("mmc_spi", 0, - Subsignal("cs_n", Pins("A2"), Misc("PULLUP")), - Subsignal("clk", Pins("A3")), - Subsignal("mosi", Pins("B3")), - Subsignal("miso", Pins("B4"), Misc("PULLUP")), - IOStandard("SDIO") - ), - - ("audio", 0, - Subsignal("l", Pins("R7"), Misc("SLEW=SLOW")), - Subsignal("r", Pins("T7"), Misc("SLEW=SLOW")), - IOStandard("LVTTL"), - ), - - ("pmod", 0, - Subsignal("d", Pins("D9 C8 D6 C4 B11 C9 D8 C6")), - IOStandard("LVTTL") - ), - - ("ddram_clock", 0, - Subsignal("p", Pins("G3")), - Subsignal("n", Pins("G1")), - IOStandard("MOBILE_DDR") - ), - - ("ddram", 0, - Subsignal("a", Pins("J7 J6 H5 L7 F3 H4 H3 H6 D2 D1 F4 D3 G6")), - Subsignal("ba", Pins("F2 F1")), - Subsignal("cke", Pins("H7")), - Subsignal("ras_n", Pins("L5")), - Subsignal("cas_n", Pins("K5")), - Subsignal("we_n", Pins("E3")), - Subsignal("dq", Pins("L2 L1 K2 K1 H2 H1 J3 J1 M3 M1 N2 N1 T2 T1 U2 U1")), - Subsignal("dqs", Pins("L4 P2")), - Subsignal("dm", Pins("K3 K4")), - IOStandard("MOBILE_DDR") - ) + ("user_led", 0, Pins("V16"), IOStandard("LVTTL"), Drive(8), Misc("SLEW=QUIETIO")), # green at hdmi + ("user_led", 1, Pins("U16"), IOStandard("LVTTL"), Drive(8), Misc("SLEW=QUIETIO")), # red at hdmi + ("user_led", 2, Pins("A16"), IOStandard("LVTTL"), Drive(8), Misc("SLEW=QUIETIO")), # green at msd + ("user_led", 3, Pins("A15"), IOStandard("LVTTL"), Drive(8), Misc("SLEW=QUIETIO")), # red at msd + ("user_led", 4, Pins("A12"), IOStandard("LVTTL"), Drive(8), Misc("SLEW=QUIETIO")), # red at usb + + ("user_btn", 0, Pins("N14"), IOStandard("LVTTL"), Misc("PULLDOWN")), + + ("clk50", 0, Pins("H17"), IOStandard("LVTTL")), + + ("serial", 0, + Subsignal("tx", Pins("A10")), + Subsignal("rx", Pins("A11"), Misc("PULLUP")), + Subsignal("rts", Pins("C10")), + Subsignal("cts", Pins("A9"), Misc("PULLUP")), + IOStandard("LVTTL"), + ), + + ("usb_fifo", 0, + Subsignal("data", Pins("A11 A10 C10 A9 B9 A8 B8 A7")), + Subsignal("rxf", Pins("C7")), + Subsignal("txe", Pins("A6")), + Subsignal("rd", Pins("B6")), + Subsignal("wr", Pins("A5")), + Subsignal("siwua", Pins("C5")), + IOStandard("LVTTL"), + ), + + ("hdmi", 0, + Subsignal("clk_p", Pins("U5"), IOStandard("TMDS_33")), + Subsignal("clk_n", Pins("V5"), IOStandard("TMDS_33")), + Subsignal("data0_p", Pins("T6"), IOStandard("TMDS_33")), + Subsignal("data0_n", Pins("V6"), IOStandard("TMDS_33")), + Subsignal("data1_p", Pins("U7"), IOStandard("TMDS_33")), + Subsignal("data1_n", Pins("V7"), IOStandard("TMDS_33")), + Subsignal("data2_p", Pins("U8"), IOStandard("TMDS_33")), + Subsignal("data2_n", Pins("V8"), IOStandard("TMDS_33")), + Subsignal("scl", Pins("V9"), IOStandard("I2C")), + Subsignal("sda", Pins("T9"), IOStandard("I2C")), + Subsignal("hpd_notif", Pins("R8"), IOStandard("LVTTL")), + ), + + ("spiflash", 0, + Subsignal("cs_n", Pins("V3")), + Subsignal("clk", Pins("R15")), + Subsignal("mosi", Pins("T13")), + Subsignal("miso", Pins("R13"), Misc("PULLUP")), + Subsignal("wp", Pins("T14")), + Subsignal("hold", Pins("V14")), + IOStandard("LVTTL"), Misc("SLEW=FAST") + ), + + ("spiflash2x", 0, + Subsignal("cs_n", Pins("V3")), + Subsignal("clk", Pins("R15")), + Subsignal("dq", Pins("T13 R13"), Misc("PULLUP")), + Subsignal("wp", Pins("T14")), + Subsignal("hold", Pins("V14")), + IOStandard("LVTTL"), Misc("SLEW=FAST") + ), + + ("spiflash4x", 0, + Subsignal("cs_n", Pins("V3")), + Subsignal("clk", Pins("R15")), + Subsignal("dq", Pins("T13 R13 T14 V14"), Misc("PULLUP")), + IOStandard("LVTTL"), Misc("SLEW=FAST") + ), + + ("mmc", 0, + Subsignal("clk", Pins("A3")), + Subsignal("cmd", Pins("B3"), Misc("PULLUP")), + Subsignal("dat", Pins("B4 A4 B2 A2"), Misc("PULLUP")), + IOStandard("SDIO") + ), + + ("mmc_spi", 0, + Subsignal("cs_n", Pins("A2"), Misc("PULLUP")), + Subsignal("clk", Pins("A3")), + Subsignal("mosi", Pins("B3")), + Subsignal("miso", Pins("B4"), Misc("PULLUP")), + IOStandard("SDIO") + ), + + ("audio", 0, + Subsignal("l", Pins("R7"), Misc("SLEW=SLOW")), + Subsignal("r", Pins("T7"), Misc("SLEW=SLOW")), + IOStandard("LVTTL"), + ), + + ("pmod", 0, + Subsignal("d", Pins("D9 C8 D6 C4 B11 C9 D8 C6")), + IOStandard("LVTTL") + ), + + ("ddram_clock", 0, + Subsignal("p", Pins("G3")), + Subsignal("n", Pins("G1")), + IOStandard("MOBILE_DDR") + ), + + ("ddram", 0, + Subsignal("a", Pins("J7 J6 H5 L7 F3 H4 H3 H6 D2 D1 F4 D3 G6")), + Subsignal("ba", Pins("F2 F1")), + Subsignal("cke", Pins("H7")), + Subsignal("ras_n", Pins("L5")), + Subsignal("cas_n", Pins("K5")), + Subsignal("we_n", Pins("E3")), + Subsignal("dq", Pins("L2 L1 K2 K1 H2 H1 J3 J1 M3 M1 N2 N1 T2 T1 U2 U1")), + Subsignal("dqs", Pins("L4 P2")), + Subsignal("dm", Pins("K3 K4")), + IOStandard("MOBILE_DDR") + ) ] _connectors = [ - ("A", "U18 T17 P17 P16 N16 N17 M16 L15 L17 K15 K17 J16 H15 H18 F18 D18"), - ("B", "C18 E18 G18 H16 J18 K18 K16 L18 L16 M18 N18 N15 P15 P18 T18 U17"), - ("C", "F17 F16 E16 G16 F15 G14 F14 H14 H13 J13 G13 H12 K14 K13 K12 L12"), + ("A", "U18 T17 P17 P16 N16 N17 M16 L15 L17 K15 K17 J16 H15 H18 F18 D18"), + ("B", "C18 E18 G18 H16 J18 K18 K16 L18 L16 M18 N18 N15 P15 P18 T18 U17"), + ("C", "F17 F16 E16 G16 F15 G14 F14 H14 H13 J13 G13 H12 K14 K13 K12 L12"), ] class Platform(XilinxPlatform): - identifier = 0x5049 - default_clk_name = "clk50" - default_clk_period = 20 + identifier = 0x5049 + default_clk_name = "clk50" + default_clk_period = 20 - def __init__(self): - XilinxPlatform.__init__(self, "xc6slx45-csg324-2", _io, _connectors) - self.toolchain.bitgen_opt += " -g Compress -g ConfigRate:6" + def __init__(self): + XilinxPlatform.__init__(self, "xc6slx45-csg324-2", _io, _connectors) + self.toolchain.bitgen_opt += " -g Compress -g ConfigRate:6" - def create_programmer(self): - return XC3SProg("papilio", "bscan_spi_lx45_csg324.bit") + def create_programmer(self): + return XC3SProg("papilio", "bscan_spi_lx45_csg324.bit") diff --git a/mibuild/platforms/rhino.py b/mibuild/platforms/rhino.py index cb2f043f..feb4fa4a 100644 --- a/mibuild/platforms/rhino.py +++ b/mibuild/platforms/rhino.py @@ -2,139 +2,139 @@ from mibuild.generic_platform import * from mibuild.xilinx import XilinxPlatform _io = [ - ("user_led", 0, Pins("Y3")), - ("user_led", 1, Pins("Y1")), - ("user_led", 2, Pins("W2")), - ("user_led", 3, Pins("W1")), - ("user_led", 4, Pins("V3")), - ("user_led", 5, Pins("V1")), - ("user_led", 6, Pins("U2")), - ("user_led", 7, Pins("U1")), + ("user_led", 0, Pins("Y3")), + ("user_led", 1, Pins("Y1")), + ("user_led", 2, Pins("W2")), + ("user_led", 3, Pins("W1")), + ("user_led", 4, Pins("V3")), + ("user_led", 5, Pins("V1")), + ("user_led", 6, Pins("U2")), + ("user_led", 7, Pins("U1")), - ("clk100", 0, - Subsignal("p", Pins("B14"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE")), - Subsignal("n", Pins("A14"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE")) - ), + ("clk100", 0, + Subsignal("p", Pins("B14"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE")), + Subsignal("n", Pins("A14"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE")) + ), - ("gpio", 0, Pins("R8")), + ("gpio", 0, Pins("R8")), - ("gpmc", 0, - Subsignal("clk", Pins("R26")), - Subsignal("a", Pins("N17 N18 L23 L24 N19 N20 N21 N22 P17 P19")), - Subsignal("d", Pins("N23 N24 R18 R19 P21 P22 R20 R21 P24 P26 R23 R24 T22 T23 U23 R25")), - Subsignal("we_n", Pins("W26")), - Subsignal("oe_n", Pins("AA25")), - Subsignal("ale_n", Pins("AA26")), - Subsignal("wait", Pins("AD26")), # WAIT1/BUSY0 - IOStandard("LVCMOS33")), - # Warning: CS are numbered 1-7 on ARM side and 0-6 on FPGA side. - # Numbers here are given on the FPGA side. - ("gpmc_ce_n", 0, Pins("V23"), IOStandard("LVCMOS33")), # nCS0 - ("gpmc_ce_n", 1, Pins("U25"), IOStandard("LVCMOS33")), # nCS1 - ("gpmc_ce_n", 2, Pins("W25"), IOStandard("LVCMOS33")), # nCS6 - ("gpmc_dmareq_n", 0, Pins("T24"), IOStandard("LVCMOS33")), # nCS2 - ("gpmc_dmareq_n", 1, Pins("T26"), IOStandard("LVCMOS33")), # nCS3 - ("gpmc_dmareq_n", 2, Pins("V24"), IOStandard("LVCMOS33")), # nCS4 - ("gpmc_dmareq_n", 3, Pins("V26"), IOStandard("LVCMOS33")), # nCS5 + ("gpmc", 0, + Subsignal("clk", Pins("R26")), + Subsignal("a", Pins("N17 N18 L23 L24 N19 N20 N21 N22 P17 P19")), + Subsignal("d", Pins("N23 N24 R18 R19 P21 P22 R20 R21 P24 P26 R23 R24 T22 T23 U23 R25")), + Subsignal("we_n", Pins("W26")), + Subsignal("oe_n", Pins("AA25")), + Subsignal("ale_n", Pins("AA26")), + Subsignal("wait", Pins("AD26")), # WAIT1/BUSY0 + IOStandard("LVCMOS33")), + # Warning: CS are numbered 1-7 on ARM side and 0-6 on FPGA side. + # Numbers here are given on the FPGA side. + ("gpmc_ce_n", 0, Pins("V23"), IOStandard("LVCMOS33")), # nCS0 + ("gpmc_ce_n", 1, Pins("U25"), IOStandard("LVCMOS33")), # nCS1 + ("gpmc_ce_n", 2, Pins("W25"), IOStandard("LVCMOS33")), # nCS6 + ("gpmc_dmareq_n", 0, Pins("T24"), IOStandard("LVCMOS33")), # nCS2 + ("gpmc_dmareq_n", 1, Pins("T26"), IOStandard("LVCMOS33")), # nCS3 + ("gpmc_dmareq_n", 2, Pins("V24"), IOStandard("LVCMOS33")), # nCS4 + ("gpmc_dmareq_n", 3, Pins("V26"), IOStandard("LVCMOS33")), # nCS5 - # FMC150 - ("fmc150_ctrl", 0, - Subsignal("spi_sclk", Pins("AE5")), - Subsignal("spi_data", Pins("AF5")), + # FMC150 + ("fmc150_ctrl", 0, + Subsignal("spi_sclk", Pins("AE5")), + Subsignal("spi_data", Pins("AF5")), - Subsignal("adc_sdo", Pins("U13")), - Subsignal("adc_en_n", Pins("AA15")), - Subsignal("adc_reset", Pins("V13")), + Subsignal("adc_sdo", Pins("U13")), + Subsignal("adc_en_n", Pins("AA15")), + Subsignal("adc_reset", Pins("V13")), - Subsignal("cdce_sdo", Pins("AA8")), - Subsignal("cdce_en_n", Pins("Y9")), - Subsignal("cdce_reset_n", Pins("AB7")), - Subsignal("cdce_pd_n", Pins("AC6")), - Subsignal("cdce_pll_status", Pins("W7")), - Subsignal("cdce_ref_en", Pins("W8")), + Subsignal("cdce_sdo", Pins("AA8")), + Subsignal("cdce_en_n", Pins("Y9")), + Subsignal("cdce_reset_n", Pins("AB7")), + Subsignal("cdce_pd_n", Pins("AC6")), + Subsignal("cdce_pll_status", Pins("W7")), + Subsignal("cdce_ref_en", Pins("W8")), - Subsignal("dac_sdo", Pins("W9")), - Subsignal("dac_en_n", Pins("W10")), + Subsignal("dac_sdo", Pins("W9")), + Subsignal("dac_en_n", Pins("W10")), - Subsignal("mon_sdo", Pins("AC5")), - Subsignal("mon_en_n", Pins("AD6")), - Subsignal("mon_reset_n", Pins("AF6")), - Subsignal("mon_int_n", Pins("AD5")), + Subsignal("mon_sdo", Pins("AC5")), + Subsignal("mon_en_n", Pins("AD6")), + Subsignal("mon_reset_n", Pins("AF6")), + Subsignal("mon_int_n", Pins("AD5")), - Subsignal("pg_c2m", Pins("AA23"), IOStandard("LVCMOS33")) - ), - ("ti_dac", 0, # DAC3283 - Subsignal("dat_p", Pins("AA10 AA9 V11 Y11 W14 Y12 AD14 AE13"), IOStandard("LVDS_25")), - Subsignal("dat_n", Pins("AB11 AB9 V10 AA11 Y13 AA12 AF14 AF13"), IOStandard("LVDS_25")), - Subsignal("frame_p", Pins("AB13"), IOStandard("LVDS_25")), - Subsignal("frame_n", Pins("AA13"), IOStandard("LVDS_25")), - Subsignal("txenable", Pins("AB15"), IOStandard("LVCMOS25")) - ), - ("ti_adc", 0, # ADS62P49 - Subsignal("dat_a_p", Pins("AB14 Y21 W20 AB22 V18 W17 AA21")), - Subsignal("dat_a_n", Pins("AC14 AA22 Y20 AC22 W19 W18 AB21")), - Subsignal("dat_b_p", Pins("Y17 U15 AA19 W16 AA18 Y15 V14")), - Subsignal("dat_b_n", Pins("AA17 V16 AB19 Y16 AB17 AA16 V15")), - IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE") - ), - ("fmc150_clocks", 0, - Subsignal("dac_clk_p", Pins("V12"), IOStandard("LVDS_25")), - Subsignal("dac_clk_n", Pins("W12"), IOStandard("LVDS_25")), - Subsignal("adc_clk_p", Pins("AE15"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE")), - Subsignal("adc_clk_n", Pins("AF15"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE")), - Subsignal("clk_to_fpga", Pins("W24"), IOStandard("LVCMOS25")) - ), + Subsignal("pg_c2m", Pins("AA23"), IOStandard("LVCMOS33")) + ), + ("ti_dac", 0, # DAC3283 + Subsignal("dat_p", Pins("AA10 AA9 V11 Y11 W14 Y12 AD14 AE13"), IOStandard("LVDS_25")), + Subsignal("dat_n", Pins("AB11 AB9 V10 AA11 Y13 AA12 AF14 AF13"), IOStandard("LVDS_25")), + Subsignal("frame_p", Pins("AB13"), IOStandard("LVDS_25")), + Subsignal("frame_n", Pins("AA13"), IOStandard("LVDS_25")), + Subsignal("txenable", Pins("AB15"), IOStandard("LVCMOS25")) + ), + ("ti_adc", 0, # ADS62P49 + Subsignal("dat_a_p", Pins("AB14 Y21 W20 AB22 V18 W17 AA21")), + Subsignal("dat_a_n", Pins("AC14 AA22 Y20 AC22 W19 W18 AB21")), + Subsignal("dat_b_p", Pins("Y17 U15 AA19 W16 AA18 Y15 V14")), + Subsignal("dat_b_n", Pins("AA17 V16 AB19 Y16 AB17 AA16 V15")), + IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE") + ), + ("fmc150_clocks", 0, + Subsignal("dac_clk_p", Pins("V12"), IOStandard("LVDS_25")), + Subsignal("dac_clk_n", Pins("W12"), IOStandard("LVDS_25")), + Subsignal("adc_clk_p", Pins("AE15"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE")), + Subsignal("adc_clk_n", Pins("AF15"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE")), + Subsignal("clk_to_fpga", Pins("W24"), IOStandard("LVCMOS25")) + ), - ("fmc150_ext_trigger", 0, Pins("U26")), + ("fmc150_ext_trigger", 0, Pins("U26")), - # Vermeer radar testbed - # Switch controller - ("pca9555", 0, - Subsignal("sda", Pins("C13")), - Subsignal("scl", Pins("G8")), - IOStandard("LVCMOS33") - ), - # TX path - ("pe43602", 0, - Subsignal("d", Pins("H8")), - Subsignal("clk", Pins("B3")), - Subsignal("le", Pins("F7")), - IOStandard("LVCMOS33") - ), - ("rfmd2081", 0, - Subsignal("enx", Pins("E5")), - Subsignal("sclk", Pins("G6")), - Subsignal("sdata", Pins("F5")), - Subsignal("locked", Pins("E6")), - IOStandard("LVCMOS33") - ), - # RX path - ("lmh6521", 0, - Subsignal("scsb", Pins("C5")), - Subsignal("sclk", Pins("G10")), - Subsignal("sdi", Pins("D5")), - Subsignal("sdo", Pins("F9")), - IOStandard("LVCMOS33") - ), - ("lmh6521", 1, - Subsignal("scsb", Pins("E10")), - Subsignal("sclk", Pins("A4")), - Subsignal("sdi", Pins("B4")), - Subsignal("sdo", Pins("H10")), - IOStandard("LVCMOS33") - ), - ("rffc5071", 0, - Subsignal("enx", Pins("A2")), - Subsignal("sclk", Pins("G9")), - Subsignal("sdata", Pins("H9")), - Subsignal("locked", Pins("A3")), - IOStandard("LVCMOS33") - ) + # Vermeer radar testbed + # Switch controller + ("pca9555", 0, + Subsignal("sda", Pins("C13")), + Subsignal("scl", Pins("G8")), + IOStandard("LVCMOS33") + ), + # TX path + ("pe43602", 0, + Subsignal("d", Pins("H8")), + Subsignal("clk", Pins("B3")), + Subsignal("le", Pins("F7")), + IOStandard("LVCMOS33") + ), + ("rfmd2081", 0, + Subsignal("enx", Pins("E5")), + Subsignal("sclk", Pins("G6")), + Subsignal("sdata", Pins("F5")), + Subsignal("locked", Pins("E6")), + IOStandard("LVCMOS33") + ), + # RX path + ("lmh6521", 0, + Subsignal("scsb", Pins("C5")), + Subsignal("sclk", Pins("G10")), + Subsignal("sdi", Pins("D5")), + Subsignal("sdo", Pins("F9")), + IOStandard("LVCMOS33") + ), + ("lmh6521", 1, + Subsignal("scsb", Pins("E10")), + Subsignal("sclk", Pins("A4")), + Subsignal("sdi", Pins("B4")), + Subsignal("sdo", Pins("H10")), + IOStandard("LVCMOS33") + ), + ("rffc5071", 0, + Subsignal("enx", Pins("A2")), + Subsignal("sclk", Pins("G9")), + Subsignal("sdata", Pins("H9")), + Subsignal("locked", Pins("A3")), + IOStandard("LVCMOS33") + ) ] class Platform(XilinxPlatform): - default_clk_name = "clk100" - default_clk_period = 10 + default_clk_name = "clk100" + default_clk_period = 10 - def __init__(self): - XilinxPlatform.__init__(self, "xc6slx150t-fgg676-3", _io) + def __init__(self): + XilinxPlatform.__init__(self, "xc6slx150t-fgg676-3", _io) diff --git a/mibuild/platforms/roach.py b/mibuild/platforms/roach.py index 37e391f2..b2ca92f4 100644 --- a/mibuild/platforms/roach.py +++ b/mibuild/platforms/roach.py @@ -2,32 +2,32 @@ from mibuild.generic_platform import * from mibuild.xilinx import XilinxPlatform _io = [ - ("epb", 0, - Subsignal("cs_n", Pins("K13")), - Subsignal("r_w_n", Pins("AF20")), - Subsignal("be_n", Pins("AF14 AF18")), - Subsignal("oe_n", Pins("AF21")), - Subsignal("addr", Pins("AE23 AE22 AG18 AG12 AG15 AG23 AF19 AE12 AG16 AF13 AG20 AF23", - "AH17 AH15 L20 J22 H22 L15 L16 K22 K21 K16 J15")), - Subsignal("addr_gp", Pins("L21 G22 K23 K14 L14 J12")), - Subsignal("data", Pins("AF15 AE16 AE21 AD20 AF16 AE17 AE19 AD19 AG22 AH22 AH12 AG13", - "AH20 AH19 AH14 AH13")), - Subsignal("rdy", Pins("K12")), - IOStandard("LVCMOS33") - ), - ("roach_clocks", 0, - Subsignal("epb_clk", Pins("AH18"), IOStandard("LVCMOS33")), - Subsignal("sys_clk_n", Pins("H13")), - Subsignal("sys_clk_p", Pins("J14")), - Subsignal("aux0_clk_p", Pins("G15")), - Subsignal("aux0_clk_n", Pins("G16")), - Subsignal("aux1_clk_p", Pins("H14")), - Subsignal("aux1_clk_n", Pins("H15")), - Subsignal("dly_clk_n", Pins("J17")), - Subsignal("dly_clk_p", Pins("J16")), - ), + ("epb", 0, + Subsignal("cs_n", Pins("K13")), + Subsignal("r_w_n", Pins("AF20")), + Subsignal("be_n", Pins("AF14 AF18")), + Subsignal("oe_n", Pins("AF21")), + Subsignal("addr", Pins("AE23 AE22 AG18 AG12 AG15 AG23 AF19 AE12 AG16 AF13 AG20 AF23", + "AH17 AH15 L20 J22 H22 L15 L16 K22 K21 K16 J15")), + Subsignal("addr_gp", Pins("L21 G22 K23 K14 L14 J12")), + Subsignal("data", Pins("AF15 AE16 AE21 AD20 AF16 AE17 AE19 AD19 AG22 AH22 AH12 AG13", + "AH20 AH19 AH14 AH13")), + Subsignal("rdy", Pins("K12")), + IOStandard("LVCMOS33") + ), + ("roach_clocks", 0, + Subsignal("epb_clk", Pins("AH18"), IOStandard("LVCMOS33")), + Subsignal("sys_clk_n", Pins("H13")), + Subsignal("sys_clk_p", Pins("J14")), + Subsignal("aux0_clk_p", Pins("G15")), + Subsignal("aux0_clk_n", Pins("G16")), + Subsignal("aux1_clk_p", Pins("H14")), + Subsignal("aux1_clk_n", Pins("H15")), + Subsignal("dly_clk_n", Pins("J17")), + Subsignal("dly_clk_p", Pins("J16")), + ), ] class Platform(XilinxPlatform): - def __init__(self): - XilinxPlatform.__init__(self, "xc5vsx95t-ff1136-1", _io) + def __init__(self): + XilinxPlatform.__init__(self, "xc5vsx95t-ff1136-1", _io) diff --git a/mibuild/platforms/sim.py b/mibuild/platforms/sim.py index 3572872c..81d5106f 100644 --- a/mibuild/platforms/sim.py +++ b/mibuild/platforms/sim.py @@ -2,42 +2,42 @@ from mibuild.generic_platform import * from mibuild.sim import SimPlatform class SimPins(Pins): - def __init__(self, n): - Pins.__init__(self, "s "*n) + def __init__(self, n): + Pins.__init__(self, "s "*n) _io = [ - ("sys_clk", 0, SimPins(1)), - ("sys_rst", 0, SimPins(1)), - ("serial", 0, - Subsignal("source_stb", SimPins(1)), - Subsignal("source_ack", SimPins(1)), - Subsignal("source_data", SimPins(8)), + ("sys_clk", 0, SimPins(1)), + ("sys_rst", 0, SimPins(1)), + ("serial", 0, + Subsignal("source_stb", SimPins(1)), + Subsignal("source_ack", SimPins(1)), + Subsignal("source_data", SimPins(8)), - Subsignal("sink_stb", SimPins(1)), - Subsignal("sink_ack", SimPins(1)), - Subsignal("sink_data", SimPins(8)), - ), - ("eth_clocks", 0, - Subsignal("none", SimPins(1)), - ), - ("eth", 0, - Subsignal("source_stb", SimPins(1)), - Subsignal("source_ack", SimPins(1)), - Subsignal("source_data", SimPins(8)), + Subsignal("sink_stb", SimPins(1)), + Subsignal("sink_ack", SimPins(1)), + Subsignal("sink_data", SimPins(8)), + ), + ("eth_clocks", 0, + Subsignal("none", SimPins(1)), + ), + ("eth", 0, + Subsignal("source_stb", SimPins(1)), + Subsignal("source_ack", SimPins(1)), + Subsignal("source_data", SimPins(8)), - Subsignal("sink_stb", SimPins(1)), - Subsignal("sink_ack", SimPins(1)), - Subsignal("sink_data", SimPins(8)), - ), + Subsignal("sink_stb", SimPins(1)), + Subsignal("sink_ack", SimPins(1)), + Subsignal("sink_data", SimPins(8)), + ), ] class Platform(SimPlatform): - is_sim = True - default_clk_name = "sys_clk" - default_clk_period = 1000 # on modern computers simulate at ~ 1MHz + is_sim = True + default_clk_name = "sys_clk" + default_clk_period = 1000 # on modern computers simulate at ~ 1MHz - def __init__(self): - SimPlatform.__init__(self, "SIM", _io) + def __init__(self): + SimPlatform.__init__(self, "SIM", _io) - def do_finalize(self, fragment): - pass + def do_finalize(self, fragment): + pass diff --git a/mibuild/platforms/usrp_b100.py b/mibuild/platforms/usrp_b100.py index ff6413e0..6edfe77b 100644 --- a/mibuild/platforms/usrp_b100.py +++ b/mibuild/platforms/usrp_b100.py @@ -2,150 +2,150 @@ from mibuild.generic_platform import * from mibuild.xilinx import XilinxPlatform _io = [ - ("clk64", 0, - Subsignal("p", Pins("R7")), - Subsignal("n", Pins("T7")), - IOStandard("LVDS_33"), - Misc("DIFF_TERM=TRUE"), - ), - - ("pps", 0, Pins("M14"), Misc("TIG")), - ("reset_n", 0, Pins("D5"), Misc("TIG")), - ("codec_reset", 0, Pins("B14")), - # recycles fpga_cfg_cclk for reset from fw - ("ext_reset", 0, Pins("R14")), - - ("i2c", 0, - Subsignal("sda", Pins("T13")), - Subsignal("scl", Pins("R13")), - ), - - ("cgen", 0, - Subsignal("st_ld", Pins("M13")), - Subsignal("st_refmon", Pins("J14")), - Subsignal("st_status", Pins("P6")), - Subsignal("ref_sel", Pins("T2")), - Subsignal("sync_b", Pins("H15")), - ), - - ("fx2_ifclk", 0, Pins("T8")), - ("fx2_gpif", 0, - Subsignal("d", Pins("P8 P9 N9 T9 R9 P11 P13 N12 " - "T3 R3 P5 N6 T6 T5 N8 P7")), - Subsignal("ctl", Pins("M7 M9 M11 P12")), - Subsignal("slwr", Pins("T4")), # rdy0 - Subsignal("slrd", Pins("R5")), # rdy1 - #Subsignal("rdy2", Pins("T10")), - #Subsignal("rdy3", Pins("N11")), - #Subsignal("cs", Pins("P12")), - Subsignal("sloe", Pins("R11")), - Subsignal("pktend", Pins("P10")), - Subsignal("adr", Pins("T11 H16")), - ), - - ("user_led", 0, Pins("P4"), Misc("TIG")), - ("user_led", 1, Pins("N4"), Misc("TIG")), - ("user_led", 2, Pins("R2"), Misc("TIG")), - - ("debug_clk", 0, Pins("K15 K14")), - ("debug", 0, Pins( - "K16 J16 C16 C15 E13 D14 D16 D15 " - "E14 F13 G13 F14 E16 F15 H13 G14 " - "G16 F16 J12 J13 L14 L16 M15 M16 " - "L13 K13 P16 N16 R15 P15 N13 N14")), - - ("adc", 0, - Subsignal("sync", Pins("D10")), - Subsignal("d", Pins("A4 B3 A3 D9 C10 A9 C9 D8 " - "C8 B8 A8 B15")), - ), - ("dac", 0, - Subsignal("blank", Pins("K1")), - Subsignal("sync", Pins("J2")), - Subsignal("d", Pins("J1 H3 J3 G2 H1 N3 M4 R1 " - "P2 P1 M1 N1 M3 L4")), - ), - ("codec_spi", 0, - Subsignal("sclk", Pins("K3")), - Subsignal("sen", Pins("D13")), - Subsignal("mosi", Pins("C13")), - Subsignal("miso", Pins("G4")), - ), - - ("aux_spi", 0, - Subsignal("sen", Pins("C12")), - Subsignal("sclk", Pins("D12")), - Subsignal("miso", Pins("J5")), - ), - ("rx_io", 0, Pins("D7 C6 A6 B6 E9 A7 C7 B10 " - "A10 C11 A11 D11 B12 A12 A14 A13")), - ("tx_io", 0, Pins("K4 L3 L2 F1 F3 G3 E3 E2 " - "E4 F4 D1 E1 D4 D3 C2 C1")), - ("rx_spi", 0, - Subsignal("miso", Pins("E6")), - Subsignal("sen", Pins("B4")), - Subsignal("mosi", Pins("A5")), - Subsignal("sclk", Pins("C5")), - ), - ("tx_spi", 0, - Subsignal("miso", Pins("J4")), - Subsignal("sen", Pins("N2")), - Subsignal("mosi", Pins("L1")), - Subsignal("sclk", Pins("G1")), - ), - - # these are just for information. do not request. - ("mystery_bus", 0, Pins("C4 E7")), - ("fpga_cfg", - Subsignal("din", Pins("T14")), - Subsignal("cclk", Pins("R14")), - Subsignal("init_b", Pins("T12")), - Subsignal("prog_b", Pins("A2")), - Subsignal("done", Pins("T15")), - ), - ("jtag", - Subsignal("tms", Pins("B2")), - Subsignal("tdo", Pins("B16")), - Subsignal("tdi", Pins("B1")), - Subsignal("tck", Pins("A15")), - ), + ("clk64", 0, + Subsignal("p", Pins("R7")), + Subsignal("n", Pins("T7")), + IOStandard("LVDS_33"), + Misc("DIFF_TERM=TRUE"), + ), + + ("pps", 0, Pins("M14"), Misc("TIG")), + ("reset_n", 0, Pins("D5"), Misc("TIG")), + ("codec_reset", 0, Pins("B14")), + # recycles fpga_cfg_cclk for reset from fw + ("ext_reset", 0, Pins("R14")), + + ("i2c", 0, + Subsignal("sda", Pins("T13")), + Subsignal("scl", Pins("R13")), + ), + + ("cgen", 0, + Subsignal("st_ld", Pins("M13")), + Subsignal("st_refmon", Pins("J14")), + Subsignal("st_status", Pins("P6")), + Subsignal("ref_sel", Pins("T2")), + Subsignal("sync_b", Pins("H15")), + ), + + ("fx2_ifclk", 0, Pins("T8")), + ("fx2_gpif", 0, + Subsignal("d", Pins("P8 P9 N9 T9 R9 P11 P13 N12 " + "T3 R3 P5 N6 T6 T5 N8 P7")), + Subsignal("ctl", Pins("M7 M9 M11 P12")), + Subsignal("slwr", Pins("T4")), # rdy0 + Subsignal("slrd", Pins("R5")), # rdy1 + #Subsignal("rdy2", Pins("T10")), + #Subsignal("rdy3", Pins("N11")), + #Subsignal("cs", Pins("P12")), + Subsignal("sloe", Pins("R11")), + Subsignal("pktend", Pins("P10")), + Subsignal("adr", Pins("T11 H16")), + ), + + ("user_led", 0, Pins("P4"), Misc("TIG")), + ("user_led", 1, Pins("N4"), Misc("TIG")), + ("user_led", 2, Pins("R2"), Misc("TIG")), + + ("debug_clk", 0, Pins("K15 K14")), + ("debug", 0, Pins( + "K16 J16 C16 C15 E13 D14 D16 D15 " + "E14 F13 G13 F14 E16 F15 H13 G14 " + "G16 F16 J12 J13 L14 L16 M15 M16 " + "L13 K13 P16 N16 R15 P15 N13 N14")), + + ("adc", 0, + Subsignal("sync", Pins("D10")), + Subsignal("d", Pins("A4 B3 A3 D9 C10 A9 C9 D8 " + "C8 B8 A8 B15")), + ), + ("dac", 0, + Subsignal("blank", Pins("K1")), + Subsignal("sync", Pins("J2")), + Subsignal("d", Pins("J1 H3 J3 G2 H1 N3 M4 R1 " + "P2 P1 M1 N1 M3 L4")), + ), + ("codec_spi", 0, + Subsignal("sclk", Pins("K3")), + Subsignal("sen", Pins("D13")), + Subsignal("mosi", Pins("C13")), + Subsignal("miso", Pins("G4")), + ), + + ("aux_spi", 0, + Subsignal("sen", Pins("C12")), + Subsignal("sclk", Pins("D12")), + Subsignal("miso", Pins("J5")), + ), + ("rx_io", 0, Pins("D7 C6 A6 B6 E9 A7 C7 B10 " + "A10 C11 A11 D11 B12 A12 A14 A13")), + ("tx_io", 0, Pins("K4 L3 L2 F1 F3 G3 E3 E2 " + "E4 F4 D1 E1 D4 D3 C2 C1")), + ("rx_spi", 0, + Subsignal("miso", Pins("E6")), + Subsignal("sen", Pins("B4")), + Subsignal("mosi", Pins("A5")), + Subsignal("sclk", Pins("C5")), + ), + ("tx_spi", 0, + Subsignal("miso", Pins("J4")), + Subsignal("sen", Pins("N2")), + Subsignal("mosi", Pins("L1")), + Subsignal("sclk", Pins("G1")), + ), + + # these are just for information. do not request. + ("mystery_bus", 0, Pins("C4 E7")), + ("fpga_cfg", + Subsignal("din", Pins("T14")), + Subsignal("cclk", Pins("R14")), + Subsignal("init_b", Pins("T12")), + Subsignal("prog_b", Pins("A2")), + Subsignal("done", Pins("T15")), + ), + ("jtag", + Subsignal("tms", Pins("B2")), + Subsignal("tdo", Pins("B16")), + Subsignal("tdi", Pins("B1")), + Subsignal("tck", Pins("A15")), + ), ] class Platform(XilinxPlatform): - default_clk_name = "clk64" - default_clk_period = 15.625 + default_clk_name = "clk64" + default_clk_period = 15.625 - def __init__(self): - XilinxPlatform.__init__(self, "xc3s1400a-ft256-4", _io) - self.toolchain.bitgen_opt = "-g LCK_cycle:6 -g Binary:Yes -w -g UnusedPin:PullUp" + def __init__(self): + XilinxPlatform.__init__(self, "xc3s1400a-ft256-4", _io) + self.toolchain.bitgen_opt = "-g LCK_cycle:6 -g Binary:Yes -w -g UnusedPin:PullUp" - def do_finalize(self, fragment): - XilinxPlatform.do_finalize(self, fragment) + def do_finalize(self, fragment): + XilinxPlatform.do_finalize(self, fragment) - self.add_platform_command(""" + self.add_platform_command(""" TIMESPEC TS_Pad2Pad = FROM PADS TO PADS 7 ns; """) - try: - ifclk = self.lookup_request("fx2_ifclk") - gpif = self.lookup_request("fx2_gpif") - for i, d in [(gpif.d, "in"), (gpif.d, "out"), - (gpif.ctl, "in"), (gpif.adr, "out"), - (gpif.slwr, "out"), (gpif.sloe, "out"), - (gpif.slrd, "out"), (gpif.pktend, "out")]: - if flen(i) > 1: - q = "(*)" - else: - q = "" - self.add_platform_command(""" + try: + ifclk = self.lookup_request("fx2_ifclk") + gpif = self.lookup_request("fx2_gpif") + for i, d in [(gpif.d, "in"), (gpif.d, "out"), + (gpif.ctl, "in"), (gpif.adr, "out"), + (gpif.slwr, "out"), (gpif.sloe, "out"), + (gpif.slrd, "out"), (gpif.pktend, "out")]: + if flen(i) > 1: + q = "(*)" + else: + q = "" + self.add_platform_command(""" INST "{i}%s" TNM = gpif_net_%s; """ % (q, d), i=i) - self.add_platform_command(""" + self.add_platform_command(""" NET "{ifclk}" TNM_NET = "GRPifclk"; TIMESPEC "TSifclk" = PERIOD "GRPifclk" 20833 ps HIGH 50%; TIMEGRP "gpif_net_in" OFFSET = IN 5 ns VALID 10 ns BEFORE "{ifclk}" RISING; TIMEGRP "gpif_net_out" OFFSET = OUT 7 ns AFTER "{ifclk}" RISING; """, ifclk=ifclk) - except ConstraintError: - pass + except ConstraintError: + pass diff --git a/mibuild/platforms/versa.py b/mibuild/platforms/versa.py index b753ac7f..83b41a6d 100644 --- a/mibuild/platforms/versa.py +++ b/mibuild/platforms/versa.py @@ -6,89 +6,89 @@ from mibuild.lattice import LatticePlatform from mibuild.lattice.programmer import LatticeProgrammer _io = [ - ("clk100", 0, Pins("L5"), IOStandard("LVDS25")), - ("rst_n", 0, Pins("A21"), IOStandard("LVCMOS33")), + ("clk100", 0, Pins("L5"), IOStandard("LVDS25")), + ("rst_n", 0, Pins("A21"), IOStandard("LVCMOS33")), - ("user_led", 0, Pins("Y20"), IOStandard("LVCMOS33")), - ("user_led", 1, Pins("AA21"), IOStandard("LVCMOS33")), - ("user_led", 2, Pins("U18"), IOStandard("LVCMOS33")), - ("user_led", 3, Pins("U19"), IOStandard("LVCMOS33")), - ("user_led", 4, Pins("W19"), IOStandard("LVCMOS33")), - ("user_led", 5, Pins("V19"), IOStandard("LVCMOS33")), - ("user_led", 6, Pins("AB20"), IOStandard("LVCMOS33")), - ("user_led", 7, Pins("AA20"), IOStandard("LVCMOS33")), + ("user_led", 0, Pins("Y20"), IOStandard("LVCMOS33")), + ("user_led", 1, Pins("AA21"), IOStandard("LVCMOS33")), + ("user_led", 2, Pins("U18"), IOStandard("LVCMOS33")), + ("user_led", 3, Pins("U19"), IOStandard("LVCMOS33")), + ("user_led", 4, Pins("W19"), IOStandard("LVCMOS33")), + ("user_led", 5, Pins("V19"), IOStandard("LVCMOS33")), + ("user_led", 6, Pins("AB20"), IOStandard("LVCMOS33")), + ("user_led", 7, Pins("AA20"), IOStandard("LVCMOS33")), - ("user_dip_btn", 0, Pins("J7"), IOStandard("LVCMOS15")), - ("user_dip_btn", 1, Pins("J6"), IOStandard("LVCMOS15")), - ("user_dip_btn", 2, Pins("H2"), IOStandard("LVCMOS15")), - ("user_dip_btn", 3, Pins("H3"), IOStandard("LVCMOS15")), - ("user_dip_btn", 4, Pins("J3"), IOStandard("LVCMOS15")), - ("user_dip_btn", 5, Pins("K3"), IOStandard("LVCMOS15")), - ("user_dip_btn", 6, Pins("J2"), IOStandard("LVCMOS15")), - ("user_dip_btn", 7, Pins("J1"), IOStandard("LVCMOS15")), + ("user_dip_btn", 0, Pins("J7"), IOStandard("LVCMOS15")), + ("user_dip_btn", 1, Pins("J6"), IOStandard("LVCMOS15")), + ("user_dip_btn", 2, Pins("H2"), IOStandard("LVCMOS15")), + ("user_dip_btn", 3, Pins("H3"), IOStandard("LVCMOS15")), + ("user_dip_btn", 4, Pins("J3"), IOStandard("LVCMOS15")), + ("user_dip_btn", 5, Pins("K3"), IOStandard("LVCMOS15")), + ("user_dip_btn", 6, Pins("J2"), IOStandard("LVCMOS15")), + ("user_dip_btn", 7, Pins("J1"), IOStandard("LVCMOS15")), - ("serial", 0, - Subsignal("tx", Pins("B11"), IOStandard("LVCMOS33")), # X4 IO0 - Subsignal("rx", Pins("B12"), IOStandard("LVCMOS33")), # X4 IO1 - ), + ("serial", 0, + Subsignal("tx", Pins("B11"), IOStandard("LVCMOS33")), # X4 IO0 + Subsignal("rx", Pins("B12"), IOStandard("LVCMOS33")), # X4 IO1 + ), - ("eth_clocks", 0, - Subsignal("tx", Pins("C12")), - Subsignal("gtx", Pins("M2")), - Subsignal("rx", Pins("L4")), - IOStandard("LVCMOS33") - ), - ("eth", 0, - Subsignal("rst_n", Pins("L3")), - Subsignal("mdio", Pins("L2")), - Subsignal("mdc", Pins("V4")), - Subsignal("dv", Pins("M1")), - Subsignal("rx_er", Pins("M4")), - Subsignal("rx_data", Pins("M5 N1 N6 P6 T2 R2 P5 P3")), - Subsignal("tx_en", Pins("V3")), - Subsignal("tx_data", Pins("V1 U1 R3 P1 N5 N3 N4 N2")), - Subsignal("col", Pins("R1")), - Subsignal("crs", Pins("P4")), - IOStandard("LVCMOS33") - ), + ("eth_clocks", 0, + Subsignal("tx", Pins("C12")), + Subsignal("gtx", Pins("M2")), + Subsignal("rx", Pins("L4")), + IOStandard("LVCMOS33") + ), + ("eth", 0, + Subsignal("rst_n", Pins("L3")), + Subsignal("mdio", Pins("L2")), + Subsignal("mdc", Pins("V4")), + Subsignal("dv", Pins("M1")), + Subsignal("rx_er", Pins("M4")), + Subsignal("rx_data", Pins("M5 N1 N6 P6 T2 R2 P5 P3")), + Subsignal("tx_en", Pins("V3")), + Subsignal("tx_data", Pins("V1 U1 R3 P1 N5 N3 N4 N2")), + Subsignal("col", Pins("R1")), + Subsignal("crs", Pins("P4")), + IOStandard("LVCMOS33") + ), - ("eth_clocks", 1, - Subsignal("tx", Pins("M21")), - Subsignal("gtx", Pins("M19")), - Subsignal("rx", Pins("N19")), - IOStandard("LVCMOS33") - ), - ("eth", 1, - Subsignal("rst_n", Pins("R21")), - Subsignal("mdio", Pins("U16")), - Subsignal("mdc", Pins("Y18")), - Subsignal("dv", Pins("U15")), - Subsignal("rx_er", Pins("V20")), - Subsignal("rx_data", Pins("AB17 AA17 R19 V21 T17 R18 W21 Y21")), - Subsignal("tx_en", Pins("V22")), - Subsignal("tx_data", Pins("W22 R16 P17 Y22 T21 U22 P20 U20")), - Subsignal("col", Pins("N18")), - Subsignal("crs", Pins("P19")), - IOStandard("LVCMOS33") - ), + ("eth_clocks", 1, + Subsignal("tx", Pins("M21")), + Subsignal("gtx", Pins("M19")), + Subsignal("rx", Pins("N19")), + IOStandard("LVCMOS33") + ), + ("eth", 1, + Subsignal("rst_n", Pins("R21")), + Subsignal("mdio", Pins("U16")), + Subsignal("mdc", Pins("Y18")), + Subsignal("dv", Pins("U15")), + Subsignal("rx_er", Pins("V20")), + Subsignal("rx_data", Pins("AB17 AA17 R19 V21 T17 R18 W21 Y21")), + Subsignal("tx_en", Pins("V22")), + Subsignal("tx_data", Pins("W22 R16 P17 Y22 T21 U22 P20 U20")), + Subsignal("col", Pins("N18")), + Subsignal("crs", Pins("P19")), + IOStandard("LVCMOS33") + ), ] class Platform(LatticePlatform): - default_clk_name = "clk100" - default_clk_period = 10 + default_clk_name = "clk100" + default_clk_period = 10 - def __init__(self): - LatticePlatform.__init__(self, "LFE3-35EA-6FN484C", _io) + def __init__(self): + LatticePlatform.__init__(self, "LFE3-35EA-6FN484C", _io) - def do_finalize(self, fragment): - LatticePlatform.do_finalize(self, fragment) - try: - self.add_period_constraint(self.lookup_request("eth_clocks", 0).rx, 8.0) - except ConstraintError: - pass - try: - self.add_period_constraint(self.lookup_request("eth_clocks", 1).rx, 8.0) - except ConstraintError: - pass - def create_programmer(self): - return LatticeProgrammer() + def do_finalize(self, fragment): + LatticePlatform.do_finalize(self, fragment) + try: + self.add_period_constraint(self.lookup_request("eth_clocks", 0).rx, 8.0) + except ConstraintError: + pass + try: + self.add_period_constraint(self.lookup_request("eth_clocks", 1).rx, 8.0) + except ConstraintError: + pass + def create_programmer(self): + return LatticeProgrammer() diff --git a/mibuild/platforms/zedboard.py b/mibuild/platforms/zedboard.py index 7be76018..a5a26743 100644 --- a/mibuild/platforms/zedboard.py +++ b/mibuild/platforms/zedboard.py @@ -3,142 +3,142 @@ from mibuild.xilinx import XilinxPlatform # Bank 34 and 35 voltage depend on J18 jumper setting _io = [ - ("clk100", 0, Pins("Y9"), IOStandard("LVCMOS33")), - - ("user_btn", 0, Pins("P16"), IOStandard("LVCMOS18")), # center - ("user_btn", 1, Pins("R16"), IOStandard("LVCMOS18")), # down - ("user_btn", 2, Pins("N15"), IOStandard("LVCMOS18")), # left - ("user_btn", 3, Pins("R18"), IOStandard("LVCMOS18")), # right - ("user_btn", 4, Pins("T18"), IOStandard("LVCMOS18")), # up - - ("user_sw", 0, Pins("F22"), IOStandard("LVCMOS18")), - ("user_sw", 1, Pins("G22"), IOStandard("LVCMOS18")), - ("user_sw", 2, Pins("H22"), IOStandard("LVCMOS18")), - ("user_sw", 3, Pins("F21"), IOStandard("LVCMOS18")), - ("user_sw", 4, Pins("H19"), IOStandard("LVCMOS18")), - ("user_sw", 5, Pins("H18"), IOStandard("LVCMOS18")), - ("user_sw", 6, Pins("H17"), IOStandard("LVCMOS18")), - ("user_sw", 7, Pins("M15"), IOStandard("LVCMOS18")), - - ("user_led", 0, Pins("T22"), IOStandard("LVCMOS33")), - ("user_led", 1, Pins("T21"), IOStandard("LVCMOS33")), - ("user_led", 2, Pins("U22"), IOStandard("LVCMOS33")), - ("user_led", 3, Pins("U21"), IOStandard("LVCMOS33")), - ("user_led", 4, Pins("V22"), IOStandard("LVCMOS33")), - ("user_led", 5, Pins("W22"), IOStandard("LVCMOS33")), - ("user_led", 6, Pins("U19"), IOStandard("LVCMOS33")), - ("user_led", 7, Pins("U14"), IOStandard("LVCMOS33")), - - # A - ("pmod", 0, Pins("Y11 AA11 Y10 AA9 AB11 AB10 AB9 AA8"), - IOStandard("LVCMOS33")), - # B - ("pmod", 1, Pins("W12 W11 V10 W8 V12 W10 V9 V8"), - IOStandard("LVCMOS33")), - # C - ("pmod", 2, - Subsignal("n", Pins("AB6 AA4 T6 U4")), - Subsignal("p", Pins("AB7 Y4 R6 T4")), - IOStandard("LVCMOS33")), - # D - ("pmod", 3, - Subsignal("n", Pins("W7 V4 W5 U5")), - Subsignal("p", Pins("V7 V5 W6 U6")), - IOStandard("LVCMOS33")), - - ("audio", 0, - Subsignal("adr", Pins("AB1 Y5")), - Subsignal("gpio", Pins("Y8 AA7 AA6 Y6")), - Subsignal("mclk", Pins("AB2")), - Subsignal("sck", Pins("AB4")), - Subsignal("sda", Pins("AB5")), - IOStandard("LVCMOS33")), - - ("oled", 0, - Subsignal("dc", Pins("U10")), - Subsignal("res", Pins("U9")), - Subsignal("sclk", Pins("AB12")), - Subsignal("sdin", Pins("AA12")), - Subsignal("vbat", Pins("U11")), - Subsignal("vdd", Pins("U12")), - IOStandard("LVCMOS33")), - - ("hdmi", 0, - Subsignal("clk", Pins("W18")), - Subsignal("d", Pins( - "Y13 AA13 AA14 Y14 AB15 AB16 AA16 AB17 " - "AA17 Y15 W13 W15 V15 U17 V14 V13")), - Subsignal("de", Pins("U16")), - Subsignal("hsync", Pins("V17")), - Subsignal("vsync", Pins("W17")), - Subsignal("int", Pins("W16")), - Subsignal("scl", Pins("AA18")), - Subsignal("sda", Pins("Y16")), - Subsignal("spdif", Pins("U15")), - Subsignal("spdifo", Pins("Y18")), - IOStandard("LVCMOS33")), - - ("netic16", 0, - Subsignal("w20", Pins("W20")), - Subsignal("w21", Pins("W21")), - IOStandard("LVCMOS33")), - - ("vga", 0, - Subsignal("r", Pins("V20 U20 V19 V18")), - Subsignal("g", Pins("AB22 AA22 AB21 AA21")), - Subsignal("b", Pins("Y21 Y20 AB20 AB19")), - Subsignal("hsync_n", Pins("AA19")), - Subsignal("vsync_n", Pins("Y19")), - IOStandard("LVCMOS33")), - - ("usb_otg", 0, - Subsignal("vbusoc", Pins("L16")), - Subsignal("reset_n", Pins("G17")), - IOStandard("LVCMOS18")), - - ("pudc_b", 0, Pins("K16"), IOStandard("LVCMOS18")), - - ("xadc", 0, - Subsignal("gio", Pins("H15 R15 K15 J15")), - Subsignal("ad0_n", Pins("E16")), - Subsignal("ad0_p", Pins("F16")), - Subsignal("ad8_n", Pins("D17")), - Subsignal("ad8_p", Pins("D16")), - IOStandard("LVCMOS18")), - - ("fmc_clocks", 0, - Subsignal("clk0_n", Pins("L19")), - Subsignal("clk0_p", Pins("L18")), - Subsignal("clk1_n", Pins("C19")), - Subsignal("clk1_p", Pins("D18")), - IOStandard("LVCMOS18")), - - ("fmc", 0, - Subsignal("scl", Pins("R7")), - Subsignal("sda", Pins("U7")), - - Subsignal("prsnt", Pins("AB14")), - - # 0, 1, 17, 18 can be clock signals - Subsignal("la_n", Pins( - "M20 N20 P18 P22 M22 K18 L22 T17 " - "J22 R21 T19 N18 P21 M17 K20 J17 " - "K21 B20 C20 G16 G21 E20 F19 D15 " - "A19 C22 E18 D21 A17 C18 B15 B17 " - "A22 B22")), - Subsignal("la_p", Pins( - "M19 N19 P17 N22 M21 J18 L21 T16 " - "J21 R20 R19 N17 P20 L17 K19 J16 " - "J20 B19 D20 G15 G20 E19 G19 E15 " - "A18 D22 F18 E21 A16 C17 C15 B16 " - "A21 B21")), - IOStandard("LVCMOS18")), + ("clk100", 0, Pins("Y9"), IOStandard("LVCMOS33")), + + ("user_btn", 0, Pins("P16"), IOStandard("LVCMOS18")), # center + ("user_btn", 1, Pins("R16"), IOStandard("LVCMOS18")), # down + ("user_btn", 2, Pins("N15"), IOStandard("LVCMOS18")), # left + ("user_btn", 3, Pins("R18"), IOStandard("LVCMOS18")), # right + ("user_btn", 4, Pins("T18"), IOStandard("LVCMOS18")), # up + + ("user_sw", 0, Pins("F22"), IOStandard("LVCMOS18")), + ("user_sw", 1, Pins("G22"), IOStandard("LVCMOS18")), + ("user_sw", 2, Pins("H22"), IOStandard("LVCMOS18")), + ("user_sw", 3, Pins("F21"), IOStandard("LVCMOS18")), + ("user_sw", 4, Pins("H19"), IOStandard("LVCMOS18")), + ("user_sw", 5, Pins("H18"), IOStandard("LVCMOS18")), + ("user_sw", 6, Pins("H17"), IOStandard("LVCMOS18")), + ("user_sw", 7, Pins("M15"), IOStandard("LVCMOS18")), + + ("user_led", 0, Pins("T22"), IOStandard("LVCMOS33")), + ("user_led", 1, Pins("T21"), IOStandard("LVCMOS33")), + ("user_led", 2, Pins("U22"), IOStandard("LVCMOS33")), + ("user_led", 3, Pins("U21"), IOStandard("LVCMOS33")), + ("user_led", 4, Pins("V22"), IOStandard("LVCMOS33")), + ("user_led", 5, Pins("W22"), IOStandard("LVCMOS33")), + ("user_led", 6, Pins("U19"), IOStandard("LVCMOS33")), + ("user_led", 7, Pins("U14"), IOStandard("LVCMOS33")), + + # A + ("pmod", 0, Pins("Y11 AA11 Y10 AA9 AB11 AB10 AB9 AA8"), + IOStandard("LVCMOS33")), + # B + ("pmod", 1, Pins("W12 W11 V10 W8 V12 W10 V9 V8"), + IOStandard("LVCMOS33")), + # C + ("pmod", 2, + Subsignal("n", Pins("AB6 AA4 T6 U4")), + Subsignal("p", Pins("AB7 Y4 R6 T4")), + IOStandard("LVCMOS33")), + # D + ("pmod", 3, + Subsignal("n", Pins("W7 V4 W5 U5")), + Subsignal("p", Pins("V7 V5 W6 U6")), + IOStandard("LVCMOS33")), + + ("audio", 0, + Subsignal("adr", Pins("AB1 Y5")), + Subsignal("gpio", Pins("Y8 AA7 AA6 Y6")), + Subsignal("mclk", Pins("AB2")), + Subsignal("sck", Pins("AB4")), + Subsignal("sda", Pins("AB5")), + IOStandard("LVCMOS33")), + + ("oled", 0, + Subsignal("dc", Pins("U10")), + Subsignal("res", Pins("U9")), + Subsignal("sclk", Pins("AB12")), + Subsignal("sdin", Pins("AA12")), + Subsignal("vbat", Pins("U11")), + Subsignal("vdd", Pins("U12")), + IOStandard("LVCMOS33")), + + ("hdmi", 0, + Subsignal("clk", Pins("W18")), + Subsignal("d", Pins( + "Y13 AA13 AA14 Y14 AB15 AB16 AA16 AB17 " + "AA17 Y15 W13 W15 V15 U17 V14 V13")), + Subsignal("de", Pins("U16")), + Subsignal("hsync", Pins("V17")), + Subsignal("vsync", Pins("W17")), + Subsignal("int", Pins("W16")), + Subsignal("scl", Pins("AA18")), + Subsignal("sda", Pins("Y16")), + Subsignal("spdif", Pins("U15")), + Subsignal("spdifo", Pins("Y18")), + IOStandard("LVCMOS33")), + + ("netic16", 0, + Subsignal("w20", Pins("W20")), + Subsignal("w21", Pins("W21")), + IOStandard("LVCMOS33")), + + ("vga", 0, + Subsignal("r", Pins("V20 U20 V19 V18")), + Subsignal("g", Pins("AB22 AA22 AB21 AA21")), + Subsignal("b", Pins("Y21 Y20 AB20 AB19")), + Subsignal("hsync_n", Pins("AA19")), + Subsignal("vsync_n", Pins("Y19")), + IOStandard("LVCMOS33")), + + ("usb_otg", 0, + Subsignal("vbusoc", Pins("L16")), + Subsignal("reset_n", Pins("G17")), + IOStandard("LVCMOS18")), + + ("pudc_b", 0, Pins("K16"), IOStandard("LVCMOS18")), + + ("xadc", 0, + Subsignal("gio", Pins("H15 R15 K15 J15")), + Subsignal("ad0_n", Pins("E16")), + Subsignal("ad0_p", Pins("F16")), + Subsignal("ad8_n", Pins("D17")), + Subsignal("ad8_p", Pins("D16")), + IOStandard("LVCMOS18")), + + ("fmc_clocks", 0, + Subsignal("clk0_n", Pins("L19")), + Subsignal("clk0_p", Pins("L18")), + Subsignal("clk1_n", Pins("C19")), + Subsignal("clk1_p", Pins("D18")), + IOStandard("LVCMOS18")), + + ("fmc", 0, + Subsignal("scl", Pins("R7")), + Subsignal("sda", Pins("U7")), + + Subsignal("prsnt", Pins("AB14")), + + # 0, 1, 17, 18 can be clock signals + Subsignal("la_n", Pins( + "M20 N20 P18 P22 M22 K18 L22 T17 " + "J22 R21 T19 N18 P21 M17 K20 J17 " + "K21 B20 C20 G16 G21 E20 F19 D15 " + "A19 C22 E18 D21 A17 C18 B15 B17 " + "A22 B22")), + Subsignal("la_p", Pins( + "M19 N19 P17 N22 M21 J18 L21 T16 " + "J21 R20 R19 N17 P20 L17 K19 J16 " + "J20 B19 D20 G15 G20 E19 G19 E15 " + "A18 D22 F18 E21 A16 C17 C15 B16 " + "A21 B21")), + IOStandard("LVCMOS18")), ] class Platform(XilinxPlatform): - default_clk_name = "clk100" - default_clk_period = 10 + default_clk_name = "clk100" + default_clk_period = 10 - def __init__(self): - XilinxPlatform.__init__(self, "xc7z020-clg484-1", _io) + def __init__(self): + XilinxPlatform.__init__(self, "xc7z020-clg484-1", _io) diff --git a/mibuild/platforms/ztex_115d.py b/mibuild/platforms/ztex_115d.py index 7b0a601d..1b8f40df 100644 --- a/mibuild/platforms/ztex_115d.py +++ b/mibuild/platforms/ztex_115d.py @@ -2,101 +2,101 @@ from mibuild.generic_platform import * from mibuild.xilinx import XilinxPlatform _io = [ - ("clk_fx", 0, Pins("L22"), IOStandard("LVCMOS33")), - ("clk_if", 0, Pins("K20"), IOStandard("LVCMOS33")), - ("rst", 0, Pins("A18")), - # PROG_B and DONE: AA1 U16 + ("clk_fx", 0, Pins("L22"), IOStandard("LVCMOS33")), + ("clk_if", 0, Pins("K20"), IOStandard("LVCMOS33")), + ("rst", 0, Pins("A18")), + # PROG_B and DONE: AA1 U16 - ("fx2", 0, - Subsignal("sloe", Pins("U15"), Drive(12)), # M1 - Subsignal("slrd", Pins("N22"), Drive(12)), - Subsignal("slwr", Pins("M22"), Drive(12)), - Subsignal("pktend", Pins("AB5"), Drive(12)), # CSO - Subsignal("fifoadr", Pins("W17 Y18"), Drive(12)), # CCLK M0 - Subsignal("cont", Pins("G20")), - Subsignal("fd", Pins("Y17 V13 W13 AA8 AB8 W6 Y6 Y9 " - "V21 V22 U20 U22 R20 R22 P18 P19")), - Subsignal("flag", Pins("F20 F19 F18 AB17")), # - - - CSI/MOSI - Subsignal("rdy25", Pins("M21 K21 K22 J21")), - Subsignal("ctl35", Pins("D19 E20 N20")), - Subsignal("int45", Pins("C18 V17")), - Subsignal("pc", Pins("G20 T10 V5 AB9 G19 H20 H19 H18")), - # - DOUT/BUSY INIT_B RDWR_B DO CS CLK DI - IOStandard("LVCMOS33")), + ("fx2", 0, + Subsignal("sloe", Pins("U15"), Drive(12)), # M1 + Subsignal("slrd", Pins("N22"), Drive(12)), + Subsignal("slwr", Pins("M22"), Drive(12)), + Subsignal("pktend", Pins("AB5"), Drive(12)), # CSO + Subsignal("fifoadr", Pins("W17 Y18"), Drive(12)), # CCLK M0 + Subsignal("cont", Pins("G20")), + Subsignal("fd", Pins("Y17 V13 W13 AA8 AB8 W6 Y6 Y9 " + "V21 V22 U20 U22 R20 R22 P18 P19")), + Subsignal("flag", Pins("F20 F19 F18 AB17")), # - - - CSI/MOSI + Subsignal("rdy25", Pins("M21 K21 K22 J21")), + Subsignal("ctl35", Pins("D19 E20 N20")), + Subsignal("int45", Pins("C18 V17")), + Subsignal("pc", Pins("G20 T10 V5 AB9 G19 H20 H19 H18")), + # - DOUT/BUSY INIT_B RDWR_B DO CS CLK DI + IOStandard("LVCMOS33")), - ("mm", 0, - Subsignal("a", Pins("M20 M19 M18 N19 T19 T21 T22 R19 ", - "P20 P21 P22 J22 H21 H22 G22 F21")), - Subsignal("d", Pins("D20 C20 C19 B21 B20 J19 K19 L19"), Drive(2)), - Subsignal("wr_n", Pins("C22")), - Subsignal("rd_n", Pins("D21")), - Subsignal("psen_n", Pins("D22")), - IOStandard("LVCMOS33")), + ("mm", 0, + Subsignal("a", Pins("M20 M19 M18 N19 T19 T21 T22 R19 ", + "P20 P21 P22 J22 H21 H22 G22 F21")), + Subsignal("d", Pins("D20 C20 C19 B21 B20 J19 K19 L19"), Drive(2)), + Subsignal("wr_n", Pins("C22")), + Subsignal("rd_n", Pins("D21")), + Subsignal("psen_n", Pins("D22")), + IOStandard("LVCMOS33")), - ("serial", 0, - Subsignal("tx", Pins("B22"), Misc("SLEW=QUIETIO")), - Subsignal("rx", Pins("A21"), Misc("PULLDOWN")), - IOStandard("LVCMOS33")), + ("serial", 0, + Subsignal("tx", Pins("B22"), Misc("SLEW=QUIETIO")), + Subsignal("rx", Pins("A21"), Misc("PULLDOWN")), + IOStandard("LVCMOS33")), - ("ddram_clock", 0, - Subsignal("p", Pins("F2"), Misc("OUT_TERM=UNTUNED_50")), - Subsignal("n", Pins("F1"), Misc("OUT_TERM=UNTUNED_50")), - IOStandard("SSTL18_II")), + ("ddram_clock", 0, + Subsignal("p", Pins("F2"), Misc("OUT_TERM=UNTUNED_50")), + Subsignal("n", Pins("F1"), Misc("OUT_TERM=UNTUNED_50")), + IOStandard("SSTL18_II")), - ("ddram", 0, - Subsignal("dqs", Pins("L3 T2"), IOStandard("SSTL18_II"), # DIFF_ - Misc("IN_TERM=NONE")), - Subsignal("dqs_n", Pins("L1 T1"), IOStandard("SSTL18_II"), # DIFF_ - Misc("IN_TERM=NONE")), - Subsignal("dm", Pins("H1 H2"), Misc("OUT_TERM=UNTUNED_50")), - Subsignal("dq", Pins("M1 M2 J1 K2 J3 K1 N3 N1 " - "U1 U3 P1 R3 P2 R1 V2 V1"), Misc("IN_TERM=NONE")), - Subsignal("ras_n", Pins("N4"), Misc("OUT_TERM=UNTUNED_50")), - Subsignal("cas_n", Pins("P3"), Misc("OUT_TERM=UNTUNED_50")), - Subsignal("a", Pins("M5 K6 B1 J4 L4 K3 M4 K5 G3 G1 K4 C3 C1"), - Misc("OUT_TERM=UNTUNED_50")), - Subsignal("ba", Pins("E3 E1 D1"), Misc("OUT_TERM=UNTUNED_50")), - Subsignal("cke", Pins("J6"), Misc("OUT_TERM=UNTUNED_50")), - Subsignal("cs_n", Pins("H6")), # NC! - Subsignal("odt", Pins("M3"), Misc("OUT_TERM=UNTUNED_50")), - Subsignal("we_n", Pins("D2")), - Subsignal("rzq", Pins("AA2")), - Subsignal("zio", Pins("Y2")), - IOStandard("SSTL18_II")), + ("ddram", 0, + Subsignal("dqs", Pins("L3 T2"), IOStandard("SSTL18_II"), # DIFF_ + Misc("IN_TERM=NONE")), + Subsignal("dqs_n", Pins("L1 T1"), IOStandard("SSTL18_II"), # DIFF_ + Misc("IN_TERM=NONE")), + Subsignal("dm", Pins("H1 H2"), Misc("OUT_TERM=UNTUNED_50")), + Subsignal("dq", Pins("M1 M2 J1 K2 J3 K1 N3 N1 " + "U1 U3 P1 R3 P2 R1 V2 V1"), Misc("IN_TERM=NONE")), + Subsignal("ras_n", Pins("N4"), Misc("OUT_TERM=UNTUNED_50")), + Subsignal("cas_n", Pins("P3"), Misc("OUT_TERM=UNTUNED_50")), + Subsignal("a", Pins("M5 K6 B1 J4 L4 K3 M4 K5 G3 G1 K4 C3 C1"), + Misc("OUT_TERM=UNTUNED_50")), + Subsignal("ba", Pins("E3 E1 D1"), Misc("OUT_TERM=UNTUNED_50")), + Subsignal("cke", Pins("J6"), Misc("OUT_TERM=UNTUNED_50")), + Subsignal("cs_n", Pins("H6")), # NC! + Subsignal("odt", Pins("M3"), Misc("OUT_TERM=UNTUNED_50")), + Subsignal("we_n", Pins("D2")), + Subsignal("rzq", Pins("AA2")), + Subsignal("zio", Pins("Y2")), + IOStandard("SSTL18_II")), - ("i2c", 0, - Subsignal("scl", Pins("F22")), - Subsignal("sda", Pins("E22")), - IOStandard("LVCMOS33")), + ("i2c", 0, + Subsignal("scl", Pins("F22")), + Subsignal("sda", Pins("E22")), + IOStandard("LVCMOS33")), - ("sd", 0, - Subsignal("sck", Pins("H11")), - Subsignal("d3", Pins("H14")), - Subsignal("d", Pins("P10")), - Subsignal("d1", Pins("T18")), - Subsignal("d2", Pins("R17")), - Subsignal("cmd", Pins("H13")), - IOStandard("LVCMOS33")), + ("sd", 0, + Subsignal("sck", Pins("H11")), + Subsignal("d3", Pins("H14")), + Subsignal("d", Pins("P10")), + Subsignal("d1", Pins("T18")), + Subsignal("d2", Pins("R17")), + Subsignal("cmd", Pins("H13")), + IOStandard("LVCMOS33")), ] class Platform(XilinxPlatform): - default_clk_name = "clk_if" - default_clk_period = 20 + default_clk_name = "clk_if" + default_clk_period = 20 - def __init__(self): - XilinxPlatform.__init__(self, "xc6slx150-3csg484", _io) - self.add_platform_command(""" + def __init__(self): + XilinxPlatform.__init__(self, "xc6slx150-3csg484", _io) + self.add_platform_command(""" CONFIG VCCAUX = "2.5"; """) - def do_finalize(self, fragment): - XilinxPlatform.do_finalize(self, fragment) + def do_finalize(self, fragment): + XilinxPlatform.do_finalize(self, fragment) - try: - clk_if = self.lookup_request("clk_if") - clk_fx = self.lookup_request("clk_fx") - self.add_platform_command(""" + try: + clk_if = self.lookup_request("clk_if") + clk_fx = self.lookup_request("clk_fx") + self.add_platform_command(""" NET "{clk_if}" TNM_NET = "GRPclk_if"; NET "{clk_fx}" TNM_NET = "GRPclk_fx"; TIMESPEC "TSclk_fx" = PERIOD "GRPclk_fx" 20.83333 ns HIGH 50%; @@ -104,5 +104,5 @@ TIMESPEC "TSclk_if" = PERIOD "GRPclk_if" 20 ns HIGH 50%; TIMESPEC "TSclk_fx2if" = FROM "GRPclk_fx" TO "GRPclk_if" 3 ns DATAPATHONLY; TIMESPEC "TSclk_if2fx" = FROM "GRPclk_if" TO "GRPclk_fx" 3 ns DATAPATHONLY; """, clk_if=clk_if, clk_fx=clk_fx) - except ConstraintError: - pass + except ConstraintError: + pass diff --git a/mibuild/sim/platform.py b/mibuild/sim/platform.py index b781f3c3..830037bc 100644 --- a/mibuild/sim/platform.py +++ b/mibuild/sim/platform.py @@ -2,18 +2,18 @@ from mibuild.generic_platform import GenericPlatform from mibuild.sim import common, verilator class SimPlatform(GenericPlatform): - def __init__(self, *args, toolchain="verilator", **kwargs): - GenericPlatform.__init__(self, *args, **kwargs) - if toolchain == "verilator": - self.toolchain = verilator.SimVerilatorToolchain() - else: - raise ValueError("Unknown toolchain") + def __init__(self, *args, toolchain="verilator", **kwargs): + GenericPlatform.__init__(self, *args, **kwargs) + if toolchain == "verilator": + self.toolchain = verilator.SimVerilatorToolchain() + else: + raise ValueError("Unknown toolchain") - def get_verilog(self, *args, special_overrides=dict(), **kwargs): - so = dict(common.sim_special_overrides) - so.update(special_overrides) - return GenericPlatform.get_verilog(self, *args, special_overrides=so, **kwargs) + def get_verilog(self, *args, special_overrides=dict(), **kwargs): + so = dict(common.sim_special_overrides) + so.update(special_overrides) + return GenericPlatform.get_verilog(self, *args, special_overrides=so, **kwargs) - def build(self, *args, **kwargs): - return self.toolchain.build(self, *args, **kwargs) + def build(self, *args, **kwargs): + return self.toolchain.build(self, *args, **kwargs) diff --git a/mibuild/sim/verilator.py b/mibuild/sim/verilator.py index 5a4bd251..11b1b503 100644 --- a/mibuild/sim/verilator.py +++ b/mibuild/sim/verilator.py @@ -12,24 +12,24 @@ from mibuild.sim import common def _build_tb(platform, vns, serial, template): - def io_name(ressource, subsignal=None): - res = platform.lookup_request(ressource) - if subsignal is not None: - res = getattr(res, subsignal) - return vns.get_name(res) + def io_name(ressource, subsignal=None): + res = platform.lookup_request(ressource) + if subsignal is not None: + res = getattr(res, subsignal) + return vns.get_name(res) - ios = """ + ios = """ #define SYS_CLK dut->{sys_clk} """.format(sys_clk=io_name("sys_clk")) - if serial == "pty": - ios += "#define WITH_SERIAL_PTY" - elif serial == "console": - pass - else: - raise ValueError - try: - ios += """ + if serial == "pty": + ios += "#define WITH_SERIAL_PTY" + elif serial == "console": + pass + else: + raise ValueError + try: + ios += """ #define SERIAL_SOURCE_STB dut->{serial_source_stb} #define SERIAL_SOURCE_ACK dut->{serial_source_ack} #define SERIAL_SOURCE_DATA dut->{serial_source_data} @@ -38,110 +38,110 @@ def _build_tb(platform, vns, serial, template): #define SERIAL_SINK_ACK dut->{serial_sink_ack} #define SERIAL_SINK_DATA dut->{serial_sink_data} """.format( - serial_source_stb=io_name("serial", "source_stb"), - serial_source_ack=io_name("serial", "source_ack"), - serial_source_data=io_name("serial", "source_data"), - - serial_sink_stb=io_name("serial", "sink_stb"), - serial_sink_ack=io_name("serial", "sink_ack"), - serial_sink_data=io_name("serial", "sink_data"), - ) - except: - pass - - try: - ios += """ -#define ETH_SOURCE_STB dut->{eth_source_stb} -#define ETH_SOURCE_ACK dut->{eth_source_ack} -#define ETH_SOURCE_DATA dut->{eth_source_data} - -#define ETH_SINK_STB dut->{eth_sink_stb} -#define ETH_SINK_ACK dut->{eth_sink_ack} -#define ETH_SINK_DATA dut->{eth_sink_data} + serial_source_stb=io_name("serial", "source_stb"), + serial_source_ack=io_name("serial", "source_ack"), + serial_source_data=io_name("serial", "source_data"), + + serial_sink_stb=io_name("serial", "sink_stb"), + serial_sink_ack=io_name("serial", "sink_ack"), + serial_sink_data=io_name("serial", "sink_data"), + ) + except: + pass + + try: + ios += """ +#define ETH_SOURCE_STB dut->{eth_source_stb} +#define ETH_SOURCE_ACK dut->{eth_source_ack} +#define ETH_SOURCE_DATA dut->{eth_source_data} + +#define ETH_SINK_STB dut->{eth_sink_stb} +#define ETH_SINK_ACK dut->{eth_sink_ack} +#define ETH_SINK_DATA dut->{eth_sink_data} """.format( - eth_source_stb=io_name("eth", "source_stb"), - eth_source_ack=io_name("eth", "source_ack"), - eth_source_data=io_name("eth", "source_data"), - - eth_sink_stb=io_name("eth", "sink_stb"), - eth_sink_ack=io_name("eth", "sink_ack"), - eth_sink_data=io_name("eth", "sink_data"), - ) - except: - pass - - content = "" - f = open(template, "r") - done = False - for l in f: - content += l - if "/* ios */" in l and not done: - content += ios - done = True - - f.close() - tools.write_to_file("dut_tb.cpp", content) + eth_source_stb=io_name("eth", "source_stb"), + eth_source_ack=io_name("eth", "source_ack"), + eth_source_data=io_name("eth", "source_data"), + + eth_sink_stb=io_name("eth", "sink_stb"), + eth_sink_ack=io_name("eth", "sink_ack"), + eth_sink_data=io_name("eth", "sink_data"), + ) + except: + pass + + content = "" + f = open(template, "r") + done = False + for l in f: + content += l + if "/* ios */" in l and not done: + content += ios + done = True + + f.close() + tools.write_to_file("dut_tb.cpp", content) def _build_sim(platform, vns, build_name, include_paths, sim_path, serial, verbose): - include = "" - for path in include_paths: - include += "-I"+path+" " + include = "" + for path in include_paths: + include += "-I"+path+" " - build_script_contents = """# Autogenerated by mibuild - rm -rf obj_dir/ + build_script_contents = """# Autogenerated by mibuild + rm -rf obj_dir/ verilator {disable_warnings} -O3 --cc dut.v --exe dut_tb.cpp -LDFLAGS "-lpthread" -trace {include} make -j -C obj_dir/ -f Vdut.mk Vdut """.format( - disable_warnings="-Wno-fatal", - include=include) - build_script_file = "build_" + build_name + ".sh" - tools.write_to_file(build_script_file, build_script_contents, force_unix=True) - - _build_tb(platform, vns, serial, os.path.join("..", sim_path,"dut_tb.cpp")) - if verbose: - r = subprocess.call(["bash", build_script_file]) - else: - r = subprocess.call(["bash", build_script_file], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT) - if r != 0: - raise OSError("Subprocess failed") + disable_warnings="-Wno-fatal", + include=include) + build_script_file = "build_" + build_name + ".sh" + tools.write_to_file(build_script_file, build_script_contents, force_unix=True) + + _build_tb(platform, vns, serial, os.path.join("..", sim_path,"dut_tb.cpp")) + if verbose: + r = subprocess.call(["bash", build_script_file]) + else: + r = subprocess.call(["bash", build_script_file], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT) + if r != 0: + raise OSError("Subprocess failed") def _run_sim(build_name): - run_script_contents = """obj_dir/Vdut + run_script_contents = """obj_dir/Vdut """ - run_script_file = "run_" + build_name + ".sh" - tools.write_to_file(run_script_file, run_script_contents, force_unix=True) - r = subprocess.call(["bash", run_script_file]) - if r != 0: - raise OSError("Subprocess failed") + run_script_file = "run_" + build_name + ".sh" + tools.write_to_file(run_script_file, run_script_contents, force_unix=True) + r = subprocess.call(["bash", run_script_file]) + if r != 0: + raise OSError("Subprocess failed") class SimVerilatorToolchain: - # XXX fir sim_path - def build(self, platform, fragment, build_dir="build", build_name="top", - sim_path="../migen/mibuild/sim/", serial="console", - run=True, verbose=False): - tools.mkdir_noerror(build_dir) - os.chdir(build_dir) - - if not isinstance(fragment, _Fragment): - fragment = fragment.get_fragment() - platform.finalize(fragment) - - v_output = platform.get_verilog(fragment) - named_sc, named_pc = platform.resolve_signals(v_output.ns) - v_output.write("dut.v") - - include_paths = [] - for source in platform.sources: - path = os.path.dirname(source[0]).replace("\\", "\/") - if path not in include_paths: - include_paths.append(path) - include_paths += platform.verilog_include_paths - _build_sim(platform, v_output.ns, build_name, include_paths, sim_path, serial, verbose) - - if run: - _run_sim(build_name) - - os.chdir("..") - - return v_output.ns + # XXX fir sim_path + def build(self, platform, fragment, build_dir="build", build_name="top", + sim_path="../migen/mibuild/sim/", serial="console", + run=True, verbose=False): + tools.mkdir_noerror(build_dir) + os.chdir(build_dir) + + if not isinstance(fragment, _Fragment): + fragment = fragment.get_fragment() + platform.finalize(fragment) + + v_output = platform.get_verilog(fragment) + named_sc, named_pc = platform.resolve_signals(v_output.ns) + v_output.write("dut.v") + + include_paths = [] + for source in platform.sources: + path = os.path.dirname(source[0]).replace("\\", "\/") + if path not in include_paths: + include_paths.append(path) + include_paths += platform.verilog_include_paths + _build_sim(platform, v_output.ns, build_name, include_paths, sim_path, serial, verbose) + + if run: + _run_sim(build_name) + + os.chdir("..") + + return v_output.ns diff --git a/mibuild/tools.py b/mibuild/tools.py index ab690ed0..b330d933 100644 --- a/mibuild/tools.py +++ b/mibuild/tools.py @@ -2,35 +2,35 @@ import os, struct from distutils.version import StrictVersion def mkdir_noerror(d): - try: - os.mkdir(d) - except OSError: - pass + try: + os.mkdir(d) + except OSError: + pass def language_by_filename(name): - extension = name.rsplit(".")[-1] - if extension in ["v", "vh", "vo"]: - return "verilog" - if extension in ["vhd", "vhdl", "vho"]: - return "vhdl" - return None + extension = name.rsplit(".")[-1] + if extension in ["v", "vh", "vo"]: + return "verilog" + if extension in ["vhd", "vhdl", "vho"]: + return "vhdl" + return None def write_to_file(filename, contents, force_unix=False): - newline = None - if force_unix: - newline = "\n" - with open(filename, "w", newline=newline) as f: - f.write(contents) + newline = None + if force_unix: + newline = "\n" + with open(filename, "w", newline=newline) as f: + f.write(contents) def arch_bits(): - return struct.calcsize("P")*8 + return struct.calcsize("P")*8 def versions(path): - for n in os.listdir(path): - full = os.path.join(path, n) - if not os.path.isdir(full): - continue - try: - yield StrictVersion(n) - except ValueError: - continue + for n in os.listdir(path): + full = os.path.join(path, n) + if not os.path.isdir(full): + continue + try: + yield StrictVersion(n) + except ValueError: + continue diff --git a/mibuild/xilinx/common.py b/mibuild/xilinx/common.py index 255d592b..604c6451 100644 --- a/mibuild/xilinx/common.py +++ b/mibuild/xilinx/common.py @@ -9,99 +9,99 @@ from migen.genlib.io import * from mibuild import tools def settings(path, ver=None, sub=None): - vers = list(tools.versions(path)) - if ver is None: - ver = max(vers) - else: - ver = StrictVersion(ver) - assert ver in vers + vers = list(tools.versions(path)) + if ver is None: + ver = max(vers) + else: + ver = StrictVersion(ver) + assert ver in vers - full = os.path.join(path, str(ver)) - if sub: - full = os.path.join(full, sub) + full = os.path.join(path, str(ver)) + if sub: + full = os.path.join(full, sub) - search = [64, 32] - if tools.arch_bits() == 32: - search.reverse() + search = [64, 32] + if tools.arch_bits() == 32: + search.reverse() - for b in search: - settings = os.path.join(full, "settings{0}.sh".format(b)) - if os.path.exists(settings): - return settings + for b in search: + settings = os.path.join(full, "settings{0}.sh".format(b)) + if os.path.exists(settings): + return settings - raise OSError("no settings file found") + raise OSError("no settings file found") class XilinxNoRetimingImpl(Module): - def __init__(self, reg): - self.specials += SynthesisDirective("attribute register_balancing of {r} is no", r=reg) + def __init__(self, reg): + self.specials += SynthesisDirective("attribute register_balancing of {r} is no", r=reg) class XilinxNoRetiming: - @staticmethod - def lower(dr): - return XilinxNoRetimingImpl(dr.reg) + @staticmethod + def lower(dr): + return XilinxNoRetimingImpl(dr.reg) class XilinxMultiRegImpl(MultiRegImpl): - def __init__(self, *args, **kwargs): - MultiRegImpl.__init__(self, *args, **kwargs) - self.specials += [SynthesisDirective("attribute shreg_extract of {r} is no", r=r) - for r in self.regs] + def __init__(self, *args, **kwargs): + MultiRegImpl.__init__(self, *args, **kwargs) + self.specials += [SynthesisDirective("attribute shreg_extract of {r} is no", r=r) + for r in self.regs] class XilinxMultiReg: - @staticmethod - def lower(dr): - return XilinxMultiRegImpl(dr.i, dr.o, dr.odomain, dr.n) + @staticmethod + def lower(dr): + return XilinxMultiRegImpl(dr.i, dr.o, dr.odomain, dr.n) class XilinxAsyncResetSynchronizerImpl(Module): - def __init__(self, cd, async_reset): - rst1 = Signal() - self.specials += [ - Instance("FDPE", p_INIT=1, i_D=0, i_PRE=async_reset, - i_CE=1, i_C=cd.clk, o_Q=rst1), - Instance("FDPE", p_INIT=1, i_D=rst1, i_PRE=async_reset, - i_CE=1, i_C=cd.clk, o_Q=cd.rst) - ] + def __init__(self, cd, async_reset): + rst1 = Signal() + self.specials += [ + Instance("FDPE", p_INIT=1, i_D=0, i_PRE=async_reset, + i_CE=1, i_C=cd.clk, o_Q=rst1), + Instance("FDPE", p_INIT=1, i_D=rst1, i_PRE=async_reset, + i_CE=1, i_C=cd.clk, o_Q=cd.rst) + ] class XilinxAsyncResetSynchronizer: - @staticmethod - def lower(dr): - return XilinxAsyncResetSynchronizerImpl(dr.cd, dr.async_reset) + @staticmethod + def lower(dr): + return XilinxAsyncResetSynchronizerImpl(dr.cd, dr.async_reset) class XilinxDifferentialInputImpl(Module): - def __init__(self, i_p, i_n, o): - self.specials += Instance("IBUFDS", i_I=i_p, i_IB=i_n, o_O=o) + def __init__(self, i_p, i_n, o): + self.specials += Instance("IBUFDS", i_I=i_p, i_IB=i_n, o_O=o) class XilinxDifferentialInput: - @staticmethod - def lower(dr): - return XilinxDifferentialInputImpl(dr.i_p, dr.i_n, dr.o) + @staticmethod + def lower(dr): + return XilinxDifferentialInputImpl(dr.i_p, dr.i_n, dr.o) class XilinxDifferentialOutputImpl(Module): - def __init__(self, i, o_p, o_n): - self.specials += Instance("OBUFDS", i_I=i, o_O=o_p, o_OB=o_n) + def __init__(self, i, o_p, o_n): + self.specials += Instance("OBUFDS", i_I=i, o_O=o_p, o_OB=o_n) class XilinxDifferentialOutput: - @staticmethod - def lower(dr): - return XilinxDifferentialOutputImpl(dr.i, dr.o_p, dr.o_n) + @staticmethod + def lower(dr): + return XilinxDifferentialOutputImpl(dr.i, dr.o_p, dr.o_n) class XilinxDDROutputImpl(Module): - def __init__(self, i1, i2, o, clk): - self.specials += Instance("ODDR", - p_DDR_CLK_EDGE="SAME_EDGE", - i_C=clk, i_CE=1, i_S=0, i_R=0, - i_D1=i1, i_D2=i2, o_Q=o, - ) + def __init__(self, i1, i2, o, clk): + self.specials += Instance("ODDR", + p_DDR_CLK_EDGE="SAME_EDGE", + i_C=clk, i_CE=1, i_S=0, i_R=0, + i_D1=i1, i_D2=i2, o_Q=o, + ) class XilinxDDROutput: - @staticmethod - def lower(dr): - return XilinxDDROutputImpl(dr.i1, dr.i2, dr.o, dr.clk) + @staticmethod + def lower(dr): + return XilinxDDROutputImpl(dr.i1, dr.i2, dr.o, dr.clk) xilinx_special_overrides = { - NoRetiming: XilinxNoRetiming, - MultiReg: XilinxMultiReg, - AsyncResetSynchronizer: XilinxAsyncResetSynchronizer, - DifferentialInput: XilinxDifferentialInput, - DifferentialOutput: XilinxDifferentialOutput, - DDROutput: XilinxDDROutput + NoRetiming: XilinxNoRetiming, + MultiReg: XilinxMultiReg, + AsyncResetSynchronizer: XilinxAsyncResetSynchronizer, + DifferentialInput: XilinxDifferentialInput, + DifferentialOutput: XilinxDifferentialOutput, + DDROutput: XilinxDDROutput } diff --git a/mibuild/xilinx/ise.py b/mibuild/xilinx/ise.py index 1ab01b91..c578bab8 100644 --- a/mibuild/xilinx/ise.py +++ b/mibuild/xilinx/ise.py @@ -8,179 +8,179 @@ from mibuild import tools from mibuild.xilinx import common def _format_constraint(c): - if isinstance(c, Pins): - return "LOC=" + c.identifiers[0] - elif isinstance(c, IOStandard): - return "IOSTANDARD=" + c.name - elif isinstance(c, Drive): - return "DRIVE=" + str(c.strength) - elif isinstance(c, Misc): - return c.misc + if isinstance(c, Pins): + return "LOC=" + c.identifiers[0] + elif isinstance(c, IOStandard): + return "IOSTANDARD=" + c.name + elif isinstance(c, Drive): + return "DRIVE=" + str(c.strength) + elif isinstance(c, Misc): + return c.misc def _format_ucf(signame, pin, others, resname): - fmt_c = [] - for c in [Pins(pin)] + others: - fc = _format_constraint(c) - if fc is not None: - fmt_c.append(fc) - fmt_r = resname[0] + ":" + str(resname[1]) - if resname[2] is not None: - fmt_r += "." + resname[2] - return "NET \"" + signame + "\" " + " | ".join(fmt_c) + "; # " + fmt_r + "\n" + fmt_c = [] + for c in [Pins(pin)] + others: + fc = _format_constraint(c) + if fc is not None: + fmt_c.append(fc) + fmt_r = resname[0] + ":" + str(resname[1]) + if resname[2] is not None: + fmt_r += "." + resname[2] + return "NET \"" + signame + "\" " + " | ".join(fmt_c) + "; # " + fmt_r + "\n" def _build_ucf(named_sc, named_pc): - r = "" - for sig, pins, others, resname in named_sc: - if len(pins) > 1: - for i, p in enumerate(pins): - r += _format_ucf(sig + "(" + str(i) + ")", p, others, resname) - else: - r += _format_ucf(sig, pins[0], others, resname) - if named_pc: - r += "\n" + "\n\n".join(named_pc) - return r + r = "" + for sig, pins, others, resname in named_sc: + if len(pins) > 1: + for i, p in enumerate(pins): + r += _format_ucf(sig + "(" + str(i) + ")", p, others, resname) + else: + r += _format_ucf(sig, pins[0], others, resname) + if named_pc: + r += "\n" + "\n\n".join(named_pc) + return r def _build_xst_files(device, sources, vincpaths, build_name, xst_opt): - prj_contents = "" - for filename, language in sources: - prj_contents += language + " work " + filename + "\n" - tools.write_to_file(build_name + ".prj", prj_contents) + prj_contents = "" + for filename, language in sources: + prj_contents += language + " work " + filename + "\n" + tools.write_to_file(build_name + ".prj", prj_contents) - xst_contents = """run + xst_contents = """run -ifn {build_name}.prj -top top {xst_opt} -ofn {build_name}.ngc -p {device} """.format(build_name=build_name, xst_opt=xst_opt, device=device) - for path in vincpaths: - xst_contents += "-vlgincdir " + path + "\n" - tools.write_to_file(build_name + ".xst", xst_contents) + for path in vincpaths: + xst_contents += "-vlgincdir " + path + "\n" + tools.write_to_file(build_name + ".xst", xst_contents) def _run_yosys(device, sources, vincpaths, build_name): - ys_contents = "" - incflags = "" - for path in vincpaths: - incflags += " -I" + path - for filename, language in sources: - ys_contents += "read_{}{} {}\n".format(language, incflags, filename) - - if device[:2] == "xc": - archcode = device[2:4] - else: - archcode = device[0:2] - arch = { - "6s": "spartan6", - "7a": "artix7", - "7k": "kintex7", - "7v": "virtex7", - "7z": "zynq7000" - }[archcode] - - ys_contents += """hierarchy -check -top top + ys_contents = "" + incflags = "" + for path in vincpaths: + incflags += " -I" + path + for filename, language in sources: + ys_contents += "read_{}{} {}\n".format(language, incflags, filename) + + if device[:2] == "xc": + archcode = device[2:4] + else: + archcode = device[0:2] + arch = { + "6s": "spartan6", + "7a": "artix7", + "7k": "kintex7", + "7v": "virtex7", + "7z": "zynq7000" + }[archcode] + + ys_contents += """hierarchy -check -top top proc; memory; opt; fsm; opt synth_xilinx -arch {arch} -top top -edif {build_name}.edif""".format(arch=arch, build_name=build_name) - ys_name = build_name + ".ys" - tools.write_to_file(ys_name, ys_contents) - r = subprocess.call(["yosys", ys_name]) - if r != 0: - raise OSError("Subprocess failed") + ys_name = build_name + ".ys" + tools.write_to_file(ys_name, ys_contents) + r = subprocess.call(["yosys", ys_name]) + if r != 0: + raise OSError("Subprocess failed") def _run_ise(build_name, ise_path, source, mode, ngdbuild_opt, - bitgen_opt, ise_commands, map_opt, par_opt, ver=None): - if sys.platform == "win32" or sys.platform == "cygwin": - source = False - build_script_contents = "# Autogenerated by mibuild\nset -e\n" - if source: - settings = common.settings(ise_path, ver, "ISE_DS") - build_script_contents += "source " + settings + "\n" - if mode == "edif": - ext = "edif" - else: - ext = "ngc" - build_script_contents += """ + bitgen_opt, ise_commands, map_opt, par_opt, ver=None): + if sys.platform == "win32" or sys.platform == "cygwin": + source = False + build_script_contents = "# Autogenerated by mibuild\nset -e\n" + if source: + settings = common.settings(ise_path, ver, "ISE_DS") + build_script_contents += "source " + settings + "\n" + if mode == "edif": + ext = "edif" + else: + ext = "ngc" + build_script_contents += """ xst -ifn {build_name}.xst """ - build_script_contents += """ + build_script_contents += """ ngdbuild {ngdbuild_opt} -uc {build_name}.ucf {build_name}.{ext} {build_name}.ngd map {map_opt} -o {build_name}_map.ncd {build_name}.ngd {build_name}.pcf par {par_opt} {build_name}_map.ncd {build_name}.ncd {build_name}.pcf bitgen {bitgen_opt} {build_name}.ncd {build_name}.bit """ - build_script_contents = build_script_contents.format(build_name=build_name, - ngdbuild_opt=ngdbuild_opt, bitgen_opt=bitgen_opt, ext=ext, - par_opt=par_opt, map_opt=map_opt) - build_script_contents += ise_commands.format(build_name=build_name) - build_script_file = "build_" + build_name + ".sh" - tools.write_to_file(build_script_file, build_script_contents, force_unix=True) + build_script_contents = build_script_contents.format(build_name=build_name, + ngdbuild_opt=ngdbuild_opt, bitgen_opt=bitgen_opt, ext=ext, + par_opt=par_opt, map_opt=map_opt) + build_script_contents += ise_commands.format(build_name=build_name) + build_script_file = "build_" + build_name + ".sh" + tools.write_to_file(build_script_file, build_script_contents, force_unix=True) - r = subprocess.call(["bash", build_script_file]) - if r != 0: - raise OSError("Subprocess failed") + r = subprocess.call(["bash", build_script_file]) + if r != 0: + raise OSError("Subprocess failed") class XilinxISEToolchain: - def __init__(self): - self.xst_opt = """-ifmt MIXED + def __init__(self): + self.xst_opt = """-ifmt MIXED -opt_mode SPEED -register_balancing yes""" - self.map_opt = "-ol high -w" - self.par_opt = "-ol high -w" - self.ngdbuild_opt = "" - self.bitgen_opt = "-g LCK_cycle:6 -g Binary:Yes -w" - self.ise_commands = "" - - def build(self, platform, fragment, build_dir="build", build_name="top", - ise_path="/opt/Xilinx", source=True, run=True, mode="xst"): - tools.mkdir_noerror(build_dir) - os.chdir(build_dir) - - if not isinstance(fragment, _Fragment): - fragment = fragment.get_fragment() - platform.finalize(fragment) - - ngdbuild_opt = self.ngdbuild_opt - - vns = None - - if mode == "xst" or mode == "yosys": - v_output = platform.get_verilog(fragment) - vns = v_output.ns - named_sc, named_pc = platform.resolve_signals(vns) - v_file = build_name + ".v" - v_output.write(v_file) - sources = platform.sources | {(v_file, "verilog")} - if mode == "xst": - _build_xst_files(platform.device, sources, platform.verilog_include_paths, build_name, self.xst_opt) - isemode = "xst" - else: - _run_yosys(platform.device, sources, platform.verilog_include_paths, build_name) - isemode = "edif" - ngdbuild_opt += "-p " + platform.device - - if mode == "mist": - from mist import synthesize - synthesize(fragment, platform.constraint_manager.get_io_signals()) - - if mode == "edif" or mode == "mist": - e_output = platform.get_edif(fragment) - vns = e_output.ns - named_sc, named_pc = platform.resolve_signals(vns) - e_file = build_name + ".edif" - e_output.write(e_file) - isemode = "edif" - - tools.write_to_file(build_name + ".ucf", _build_ucf(named_sc, named_pc)) - if run: - _run_ise(build_name, ise_path, source, isemode, - ngdbuild_opt, self.bitgen_opt, self.ise_commands, - self.map_opt, self.par_opt) - - os.chdir("..") - - return vns - - def add_period_constraint(self, platform, clk, period): - platform.add_platform_command("""NET "{clk}" TNM_NET = "GRP{clk}"; + self.map_opt = "-ol high -w" + self.par_opt = "-ol high -w" + self.ngdbuild_opt = "" + self.bitgen_opt = "-g LCK_cycle:6 -g Binary:Yes -w" + self.ise_commands = "" + + def build(self, platform, fragment, build_dir="build", build_name="top", + ise_path="/opt/Xilinx", source=True, run=True, mode="xst"): + tools.mkdir_noerror(build_dir) + os.chdir(build_dir) + + if not isinstance(fragment, _Fragment): + fragment = fragment.get_fragment() + platform.finalize(fragment) + + ngdbuild_opt = self.ngdbuild_opt + + vns = None + + if mode == "xst" or mode == "yosys": + v_output = platform.get_verilog(fragment) + vns = v_output.ns + named_sc, named_pc = platform.resolve_signals(vns) + v_file = build_name + ".v" + v_output.write(v_file) + sources = platform.sources | {(v_file, "verilog")} + if mode == "xst": + _build_xst_files(platform.device, sources, platform.verilog_include_paths, build_name, self.xst_opt) + isemode = "xst" + else: + _run_yosys(platform.device, sources, platform.verilog_include_paths, build_name) + isemode = "edif" + ngdbuild_opt += "-p " + platform.device + + if mode == "mist": + from mist import synthesize + synthesize(fragment, platform.constraint_manager.get_io_signals()) + + if mode == "edif" or mode == "mist": + e_output = platform.get_edif(fragment) + vns = e_output.ns + named_sc, named_pc = platform.resolve_signals(vns) + e_file = build_name + ".edif" + e_output.write(e_file) + isemode = "edif" + + tools.write_to_file(build_name + ".ucf", _build_ucf(named_sc, named_pc)) + if run: + _run_ise(build_name, ise_path, source, isemode, + ngdbuild_opt, self.bitgen_opt, self.ise_commands, + self.map_opt, self.par_opt) + + os.chdir("..") + + return vns + + def add_period_constraint(self, platform, clk, period): + platform.add_platform_command("""NET "{clk}" TNM_NET = "GRP{clk}"; TIMESPEC "TS{clk}" = PERIOD "GRP{clk}" """+str(period)+""" ns HIGH 50%;""", clk=clk) diff --git a/mibuild/xilinx/platform.py b/mibuild/xilinx/platform.py index 50cecdcd..142c79f0 100644 --- a/mibuild/xilinx/platform.py +++ b/mibuild/xilinx/platform.py @@ -2,29 +2,29 @@ from mibuild.generic_platform import GenericPlatform from mibuild.xilinx import common, vivado, ise class XilinxPlatform(GenericPlatform): - bitstream_ext = ".bit" + bitstream_ext = ".bit" - def __init__(self, *args, toolchain="ise", **kwargs): - GenericPlatform.__init__(self, *args, **kwargs) - if toolchain == "ise": - self.toolchain = ise.XilinxISEToolchain() - elif toolchain == "vivado": - self.toolchain = vivado.XilinxVivadoToolchain() - else: - raise ValueError("Unknown toolchain") + def __init__(self, *args, toolchain="ise", **kwargs): + GenericPlatform.__init__(self, *args, **kwargs) + if toolchain == "ise": + self.toolchain = ise.XilinxISEToolchain() + elif toolchain == "vivado": + self.toolchain = vivado.XilinxVivadoToolchain() + else: + raise ValueError("Unknown toolchain") - def get_verilog(self, *args, special_overrides=dict(), **kwargs): - so = dict(common.xilinx_special_overrides) - so.update(special_overrides) - return GenericPlatform.get_verilog(self, *args, special_overrides=so, **kwargs) + def get_verilog(self, *args, special_overrides=dict(), **kwargs): + so = dict(common.xilinx_special_overrides) + so.update(special_overrides) + return GenericPlatform.get_verilog(self, *args, special_overrides=so, **kwargs) - def get_edif(self, fragment, **kwargs): - return GenericPlatform.get_edif(self, fragment, "UNISIMS", "Xilinx", self.device, **kwargs) + def get_edif(self, fragment, **kwargs): + return GenericPlatform.get_edif(self, fragment, "UNISIMS", "Xilinx", self.device, **kwargs) - def build(self, *args, **kwargs): - return self.toolchain.build(self, *args, **kwargs) + def build(self, *args, **kwargs): + return self.toolchain.build(self, *args, **kwargs) - def add_period_constraint(self, clk, period): - if hasattr(clk, "p"): - clk = clk.p - self.toolchain.add_period_constraint(self, clk, period) + def add_period_constraint(self, clk, period): + if hasattr(clk, "p"): + clk = clk.p + self.toolchain.add_period_constraint(self, clk, period) diff --git a/mibuild/xilinx/programmer.py b/mibuild/xilinx/programmer.py index 0a09efa3..ae26d42b 100644 --- a/mibuild/xilinx/programmer.py +++ b/mibuild/xilinx/programmer.py @@ -4,24 +4,24 @@ from mibuild.generic_programmer import GenericProgrammer from mibuild.xilinx import common def _run_urjtag(cmds): - with subprocess.Popen("jtag", stdin=subprocess.PIPE) as process: - process.stdin.write(cmds.encode("ASCII")) - process.communicate() + with subprocess.Popen("jtag", stdin=subprocess.PIPE) as process: + process.stdin.write(cmds.encode("ASCII")) + process.communicate() class UrJTAG(GenericProgrammer): - needs_bitreverse = True + needs_bitreverse = True - def load_bitstream(self, bitstream_file): - cmds = """cable milkymist + def load_bitstream(self, bitstream_file): + cmds = """cable milkymist detect pld load {bitstream} quit """.format(bitstream=bitstream_file) - _run_urjtag(cmds) + _run_urjtag(cmds) - def flash(self, address, data_file): - flash_proxy = self.find_flash_proxy() - cmds = """cable milkymist + def flash(self, address, data_file): + flash_proxy = self.find_flash_proxy() + cmds = """cable milkymist detect pld load "{flash_proxy}" initbus fjmem opcode=000010 @@ -30,75 +30,75 @@ detectflash 0 endian big flashmem "{address}" "{data_file}" noverify """.format(flash_proxy=flash_proxy, address=address, data_file=data_file) - _run_urjtag(cmds) + _run_urjtag(cmds) class XC3SProg(GenericProgrammer): - needs_bitreverse = False + needs_bitreverse = False - def __init__(self, cable, flash_proxy_basename=None): - GenericProgrammer.__init__(self, flash_proxy_basename) - self.cable = cable + def __init__(self, cable, flash_proxy_basename=None): + GenericProgrammer.__init__(self, flash_proxy_basename) + self.cable = cable - def load_bitstream(self, bitstream_file): - subprocess.call(["xc3sprog", "-v", "-c", self.cable, bitstream_file]) + def load_bitstream(self, bitstream_file): + subprocess.call(["xc3sprog", "-v", "-c", self.cable, bitstream_file]) - def flash(self, address, data_file): - flash_proxy = self.find_flash_proxy() - subprocess.call(["xc3sprog", "-v", "-c", self.cable, "-I"+flash_proxy, "{}:w:0x{:x}:BIN".format(data_file, address)]) + def flash(self, address, data_file): + flash_proxy = self.find_flash_proxy() + subprocess.call(["xc3sprog", "-v", "-c", self.cable, "-I"+flash_proxy, "{}:w:0x{:x}:BIN".format(data_file, address)]) class FpgaProg(GenericProgrammer): - needs_bitreverse = False + needs_bitreverse = False - def __init__(self, flash_proxy_basename=None): - GenericProgrammer.__init__(self, flash_proxy_basename) + def __init__(self, flash_proxy_basename=None): + GenericProgrammer.__init__(self, flash_proxy_basename) - def load_bitstream(self, bitstream_file): - subprocess.call(["fpgaprog", "-v", "-f", bitstream_file]) + def load_bitstream(self, bitstream_file): + subprocess.call(["fpgaprog", "-v", "-f", bitstream_file]) - def flash(self, address, data_file): - if address != 0: - raise ValueError("fpga prog needs a main bitstream at address 0") - flash_proxy = self.find_flash_proxy() - subprocess.call(["fpgaprog", "-v", "-sa", "-r", "-b", flash_proxy, - "-f", data_file]) + def flash(self, address, data_file): + if address != 0: + raise ValueError("fpga prog needs a main bitstream at address 0") + flash_proxy = self.find_flash_proxy() + subprocess.call(["fpgaprog", "-v", "-sa", "-r", "-b", flash_proxy, + "-f", data_file]) def _run_impact(cmds): - with subprocess.Popen("impact -batch", stdin=subprocess.PIPE) as process: - process.stdin.write(cmds.encode("ASCII")) - process.communicate() + with subprocess.Popen("impact -batch", stdin=subprocess.PIPE) as process: + process.stdin.write(cmds.encode("ASCII")) + process.communicate() class iMPACT(GenericProgrammer): - needs_bitreverse = False + needs_bitreverse = False - def load_bitstream(self, bitstream_file): - cmds = """setMode -bs + def load_bitstream(self, bitstream_file): + cmds = """setMode -bs setCable -p auto addDevice -p 1 -file {bitstream} program -p 1 quit """.format(bitstream=bitstream_file) - _run_impact(cmds) + _run_impact(cmds) def _run_vivado(path, ver, cmds): - if sys.platform == "win32" or sys.platform == "cygwin": - vivado_cmd = "vivado -mode tcl" - else: - settings = common.settings(path, ver) - vivado_cmd = "bash -c \"source " + settings + "&& vivado -mode tcl\"" - with subprocess.Popen(vivado_cmd, stdin=subprocess.PIPE, shell=True) as process: - process.stdin.write(cmds.encode("ASCII")) - process.communicate() + if sys.platform == "win32" or sys.platform == "cygwin": + vivado_cmd = "vivado -mode tcl" + else: + settings = common.settings(path, ver) + vivado_cmd = "bash -c \"source " + settings + "&& vivado -mode tcl\"" + with subprocess.Popen(vivado_cmd, stdin=subprocess.PIPE, shell=True) as process: + process.stdin.write(cmds.encode("ASCII")) + process.communicate() class VivadoProgrammer(GenericProgrammer): - needs_bitreverse = False - def __init__(self, vivado_path="/opt/Xilinx/Vivado", vivado_ver=None): - GenericProgrammer.__init__(self) - self.vivado_path = vivado_path - self.vivado_ver = vivado_ver - - def load_bitstream(self, bitstream_file): - cmds = """open_hw + needs_bitreverse = False + def __init__(self, vivado_path="/opt/Xilinx/Vivado", vivado_ver=None): + GenericProgrammer.__init__(self) + self.vivado_path = vivado_path + self.vivado_ver = vivado_ver + + def load_bitstream(self, bitstream_file): + cmds = """open_hw connect_hw_server open_hw_target [lindex [get_hw_targets -of_objects [get_hw_servers localhost]] 0] @@ -110,11 +110,11 @@ refresh_hw_device [lindex [get_hw_devices] 0] quit """.format(bitstream=bitstream_file) - _run_vivado(self.vivado_path, self.vivado_ver, cmds) + _run_vivado(self.vivado_path, self.vivado_ver, cmds) - # XXX works to flash bitstream, adapt it to flash bios - def flash(self, address, data_file): - cmds = """open_hw + # XXX works to flash bitstream, adapt it to flash bios + def flash(self, address, data_file): + cmds = """open_hw connect_hw_server open_hw_target [lindex [get_hw_targets -of_objects [get_hw_servers localhost]] 0] create_hw_cfgmem -hw_device [lindex [get_hw_devices] 0] -mem_dev [lindex [get_cfgmem_parts {{n25q256-3.3v-spi-x1_x2_x4}}] 0] @@ -140,4 +140,4 @@ endgroup quit """.format(data=data_file) - _run_vivado(self.vivado_path, self.vivado_ver, cmds) + _run_vivado(self.vivado_path, self.vivado_ver, cmds) diff --git a/mibuild/xilinx/vivado.py b/mibuild/xilinx/vivado.py index 5ef4c297..6077b2f8 100644 --- a/mibuild/xilinx/vivado.py +++ b/mibuild/xilinx/vivado.py @@ -11,120 +11,120 @@ from mibuild import tools from mibuild.xilinx import common def _format_constraint(c): - if isinstance(c, Pins): - return "set_property LOC " + c.identifiers[0] - elif isinstance(c, IOStandard): - return "set_property IOSTANDARD " + c.name - elif isinstance(c, Drive): - return "set_property DRIVE " + str(c.strength) - elif isinstance(c, Misc): - return "set_property " + c.misc.replace("=", " ") - else: - raise ValueError("unknown constraint %s" % c) + if isinstance(c, Pins): + return "set_property LOC " + c.identifiers[0] + elif isinstance(c, IOStandard): + return "set_property IOSTANDARD " + c.name + elif isinstance(c, Drive): + return "set_property DRIVE " + str(c.strength) + elif isinstance(c, Misc): + return "set_property " + c.misc.replace("=", " ") + else: + raise ValueError("unknown constraint %s" % c) def _format_xdc(signame, resname, *constraints): - fmt_c = [_format_constraint(c) for c in constraints] - fmt_r = resname[0] + ":" + str(resname[1]) - if resname[2] is not None: - fmt_r += "." + resname[2] - r = " ## %s\n" %fmt_r - for c in fmt_c: - r += c + " [get_ports " + signame + "]\n" - return r + fmt_c = [_format_constraint(c) for c in constraints] + fmt_r = resname[0] + ":" + str(resname[1]) + if resname[2] is not None: + fmt_r += "." + resname[2] + r = " ## %s\n" %fmt_r + for c in fmt_c: + r += c + " [get_ports " + signame + "]\n" + return r def _build_xdc(named_sc, named_pc): - r = "" - for sig, pins, others, resname in named_sc: - if len(pins) > 1: - for i, p in enumerate(pins): - r += _format_xdc(sig + "[" + str(i) + "]", resname, Pins(p), *others) - elif pins: - r += _format_xdc(sig, resname, Pins(pins[0]), *others) - else: - r += _format_xdc(sig, resname, *others) - if named_pc: - r += "\n" + "\n\n".join(named_pc) - return r + r = "" + for sig, pins, others, resname in named_sc: + if len(pins) > 1: + for i, p in enumerate(pins): + r += _format_xdc(sig + "[" + str(i) + "]", resname, Pins(p), *others) + elif pins: + r += _format_xdc(sig, resname, Pins(pins[0]), *others) + else: + r += _format_xdc(sig, resname, *others) + if named_pc: + r += "\n" + "\n\n".join(named_pc) + return r def _run_vivado(build_name, vivado_path, source, ver=None): - if sys.platform == "win32" or sys.platform == "cygwin": - build_script_contents = "REM Autogenerated by mibuild\n" - build_script_contents += "vivado -mode batch -source " + build_name + ".tcl\n" - build_script_file = "build_" + build_name + ".bat" - tools.write_to_file(build_script_file, build_script_contents) - r = subprocess.call([build_script_file]) - else: - build_script_contents = "# Autogenerated by mibuild\nset -e\n" - settings = common.settings(vivado_path, ver) - build_script_contents += "source " + settings + "\n" - build_script_contents += "vivado -mode batch -source " + build_name + ".tcl\n" - build_script_file = "build_" + build_name + ".sh" - tools.write_to_file(build_script_file, build_script_contents) - r = subprocess.call(["bash", build_script_file]) - - if r != 0: - raise OSError("Subprocess failed") + if sys.platform == "win32" or sys.platform == "cygwin": + build_script_contents = "REM Autogenerated by mibuild\n" + build_script_contents += "vivado -mode batch -source " + build_name + ".tcl\n" + build_script_file = "build_" + build_name + ".bat" + tools.write_to_file(build_script_file, build_script_contents) + r = subprocess.call([build_script_file]) + else: + build_script_contents = "# Autogenerated by mibuild\nset -e\n" + settings = common.settings(vivado_path, ver) + build_script_contents += "source " + settings + "\n" + build_script_contents += "vivado -mode batch -source " + build_name + ".tcl\n" + build_script_file = "build_" + build_name + ".sh" + tools.write_to_file(build_script_file, build_script_contents) + r = subprocess.call(["bash", build_script_file]) + + if r != 0: + raise OSError("Subprocess failed") class XilinxVivadoToolchain: - def __init__(self): - self.bitstream_commands = [] - self.additional_commands = [] - self.pre_synthesis_commands = [] - self.with_phys_opt = False - - def _build_batch(self, platform, sources, build_name): - tcl = [] - for filename, language in sources: - tcl.append("add_files " + filename.replace("\\", "/")) - - tcl.append("read_xdc %s.xdc" %build_name) - tcl.extend(c.format(build_name=build_name) for c in self.pre_synthesis_commands) - tcl.append("synth_design -top top -part %s -include_dirs {%s}" %(platform.device, " ".join(platform.verilog_include_paths))) - tcl.append("report_utilization -hierarchical -file %s_utilization_hierarchical_synth.rpt" %(build_name)) - tcl.append("report_utilization -file %s_utilization_synth.rpt" %(build_name)) - tcl.append("place_design") - if self.with_phys_opt: - tcl.append("phys_opt_design -directive AddRetime") - tcl.append("report_utilization -hierarchical -file %s_utilization_hierarchical_place.rpt" %(build_name)) - tcl.append("report_utilization -file %s_utilization_place.rpt" %(build_name)) - tcl.append("report_io -file %s_io.rpt" %(build_name)) - tcl.append("report_control_sets -verbose -file %s_control_sets.rpt" %(build_name)) - tcl.append("report_clock_utilization -file %s_clock_utilization.rpt" %(build_name)) - tcl.append("route_design") - tcl.append("report_route_status -file %s_route_status.rpt" %(build_name)) - tcl.append("report_drc -file %s_drc.rpt" %(build_name)) - tcl.append("report_timing_summary -max_paths 10 -file %s_timing.rpt" %(build_name)) - tcl.append("report_power -file %s_power.rpt" %(build_name)) - for bitstream_command in self.bitstream_commands: - tcl.append(bitstream_command.format(build_name=build_name)) - tcl.append("write_bitstream -force %s.bit " %build_name) - for additional_command in self.additional_commands: - tcl.append(additional_command.format(build_name=build_name)) - tcl.append("quit") - tools.write_to_file(build_name + ".tcl", "\n".join(tcl)) - - def build(self, platform, fragment, build_dir="build", build_name="top", - vivado_path="/opt/Xilinx/Vivado", source=True, run=True): - tools.mkdir_noerror(build_dir) - os.chdir(build_dir) - - if not isinstance(fragment, _Fragment): - fragment = fragment.get_fragment() - platform.finalize(fragment) - v_output = platform.get_verilog(fragment) - named_sc, named_pc = platform.resolve_signals(v_output.ns) - v_file = build_name + ".v" - v_output.write(v_file) - sources = platform.sources | {(v_file, "verilog")} - self._build_batch(platform, sources, build_name) - tools.write_to_file(build_name + ".xdc", _build_xdc(named_sc, named_pc)) - if run: - _run_vivado(build_name, vivado_path, source) - - os.chdir("..") - - return v_output.ns - - def add_period_constraint(self, platform, clk, period): - platform.add_platform_command("""create_clock -name {clk} -period """ + \ - str(period) + """ [get_ports {clk}]""", clk=clk) + def __init__(self): + self.bitstream_commands = [] + self.additional_commands = [] + self.pre_synthesis_commands = [] + self.with_phys_opt = False + + def _build_batch(self, platform, sources, build_name): + tcl = [] + for filename, language in sources: + tcl.append("add_files " + filename.replace("\\", "/")) + + tcl.append("read_xdc %s.xdc" %build_name) + tcl.extend(c.format(build_name=build_name) for c in self.pre_synthesis_commands) + tcl.append("synth_design -top top -part %s -include_dirs {%s}" %(platform.device, " ".join(platform.verilog_include_paths))) + tcl.append("report_utilization -hierarchical -file %s_utilization_hierarchical_synth.rpt" %(build_name)) + tcl.append("report_utilization -file %s_utilization_synth.rpt" %(build_name)) + tcl.append("place_design") + if self.with_phys_opt: + tcl.append("phys_opt_design -directive AddRetime") + tcl.append("report_utilization -hierarchical -file %s_utilization_hierarchical_place.rpt" %(build_name)) + tcl.append("report_utilization -file %s_utilization_place.rpt" %(build_name)) + tcl.append("report_io -file %s_io.rpt" %(build_name)) + tcl.append("report_control_sets -verbose -file %s_control_sets.rpt" %(build_name)) + tcl.append("report_clock_utilization -file %s_clock_utilization.rpt" %(build_name)) + tcl.append("route_design") + tcl.append("report_route_status -file %s_route_status.rpt" %(build_name)) + tcl.append("report_drc -file %s_drc.rpt" %(build_name)) + tcl.append("report_timing_summary -max_paths 10 -file %s_timing.rpt" %(build_name)) + tcl.append("report_power -file %s_power.rpt" %(build_name)) + for bitstream_command in self.bitstream_commands: + tcl.append(bitstream_command.format(build_name=build_name)) + tcl.append("write_bitstream -force %s.bit " %build_name) + for additional_command in self.additional_commands: + tcl.append(additional_command.format(build_name=build_name)) + tcl.append("quit") + tools.write_to_file(build_name + ".tcl", "\n".join(tcl)) + + def build(self, platform, fragment, build_dir="build", build_name="top", + vivado_path="/opt/Xilinx/Vivado", source=True, run=True): + tools.mkdir_noerror(build_dir) + os.chdir(build_dir) + + if not isinstance(fragment, _Fragment): + fragment = fragment.get_fragment() + platform.finalize(fragment) + v_output = platform.get_verilog(fragment) + named_sc, named_pc = platform.resolve_signals(v_output.ns) + v_file = build_name + ".v" + v_output.write(v_file) + sources = platform.sources | {(v_file, "verilog")} + self._build_batch(platform, sources, build_name) + tools.write_to_file(build_name + ".xdc", _build_xdc(named_sc, named_pc)) + if run: + _run_vivado(build_name, vivado_path, source) + + os.chdir("..") + + return v_output.ns + + def add_period_constraint(self, platform, clk, period): + platform.add_platform_command("""create_clock -name {clk} -period """ + \ + str(period) + """ [get_ports {clk}]""", clk=clk) diff --git a/migen/actorlib/dma_wishbone.py b/migen/actorlib/dma_wishbone.py index 66063627..b9076732 100644 --- a/migen/actorlib/dma_wishbone.py +++ b/migen/actorlib/dma_wishbone.py @@ -3,52 +3,52 @@ 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() + 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) + 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) - ) - ] + 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() + 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) - ] + 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 index 36312eb8..7029269e 100644 --- a/migen/actorlib/fifo.py +++ b/migen/actorlib/fifo.py @@ -3,52 +3,52 @@ 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) - ] + 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) + 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) + def __init__(self, layout, depth): + _FIFOActor.__init__(self, fifo.AsyncFIFO, layout, depth) diff --git a/migen/actorlib/misc.py b/migen/actorlib/misc.py index 302216c9..0800a421 100644 --- a/migen/actorlib/misc.py +++ b/migen/actorlib/misc.py @@ -5,60 +5,60 @@ from migen.flow.actor import * # 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)) + 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() + self.parameters = Sink(parameters_layout) + self.source = Source([("value", max(nbits, offsetbits))]) + self.busy = Signal() - ### + ### - load = Signal() - ce = Signal() - last = Signal() + load = Signal() + ce = Signal() + last = Signal() - maximum = Signal(nbits) - if offsetbits: - offset = Signal(offsetbits) - counter = Signal(nbits) + 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) + 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")) - ) - ) + 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")) + ) + ) diff --git a/migen/actorlib/sim.py b/migen/actorlib/sim.py index dcb9e5e7..87efb751 100644 --- a/migen/actorlib/sim.py +++ b/migen/actorlib/sim.py @@ -4,22 +4,22 @@ 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 + 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) + 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. @@ -28,89 +28,89 @@ def _sim_multiwrite(sim, obj, value): # 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 __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 _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 _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 _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 + 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 __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 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) + 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)) + 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 index df56abc5..175312df 100644 --- a/migen/actorlib/spi.py +++ b/migen/actorlib/spi.py @@ -12,167 +12,167 @@ from migen.actorlib import misc # - (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 + 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, "r_"+regname, reg) - self.sync += If(self.source.ack | ~self.source.stb, - getattr(target, name).eq(reg.storage)) + 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, "r_"+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) - ] + 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.r_busy = CSRStatus() - - self.length = self.generator.r_length.storage - self.base = self.generator.r_base.storage - if hasattr(self.generator, "trigger"): - self.trigger = self.generator.trigger - - def get_csrs(self): - return self.generator.get_csrs() + [self.r_busy] + 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.r_busy = CSRStatus() + + self.length = self.generator.r_length.storage + self.base = self.generator.r_base.storage + if hasattr(self.generator, "trigger"): + self.trigger = self.generator.trigger + + def get_csrs(self): + return self.generator.get_csrs() + [self.r_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.r_busy.status.eq(self.busy) + 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.r_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.r_busy.status.eq(self.busy) + 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.r_busy.status.eq(self.busy) diff --git a/migen/actorlib/structuring.py b/migen/actorlib/structuring.py index 1ad971c8..6a74b18e 100644 --- a/migen/actorlib/structuring.py +++ b/migen/actorlib/structuring.py @@ -5,256 +5,256 @@ from migen.genlib.record import * from migen.flow.actor import * def _rawbits_layout(l): - if isinstance(l, int): - return [("rawbits", l)] - else: - return 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 __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)] + 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) - ] + 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) - ) - ] + 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) + 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) + 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) + 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) + 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/bank.py b/migen/bank/bank.py index a989085f..b27d8cf5 100644 --- a/migen/bank/bank.py +++ b/migen/bank/bank.py @@ -2,22 +2,22 @@ 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 __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) + 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 index 2223394b..67a337e1 100644 --- a/migen/bank/csrgen.py +++ b/migen/bank/csrgen.py @@ -4,31 +4,31 @@ 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 + 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)) + GenericBank.__init__(self, description, flen(self.bus.dat_w)) - sel = Signal() - self.comb += sel.eq(self.bus.adr[9:] == address) + 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)) - ] + 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)) - ] + 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). @@ -37,44 +37,44 @@ class Bank(GenericBank): # 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 __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 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_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_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()] + 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 index e44cc56b..1f9fe38d 100644 --- a/migen/bank/description.py +++ b/migen/bank/description.py @@ -3,137 +3,137 @@ 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 + 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") + 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 __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 get_simple_csrs(self): + if not self.finalized: + raise FinalizeError + return self.simple_csrs - def do_finalize(self, busword): - raise NotImplementedError + 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 __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) + 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 __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 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) + 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) + 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_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) + 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 index d2a89d9e..ad2622f5 100644 --- a/migen/bank/eventmanager.py +++ b/migen/bank/eventmanager.py @@ -4,74 +4,74 @@ 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 + 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)) - ] + 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)) - ] + 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) - ] + 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 __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) + 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) - ] + 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)) + 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 + 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])) + 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 index 0047bc18..ad6b2e97 100644 --- a/migen/bank/wbgen.py +++ b/migen/bank/wbgen.py @@ -3,24 +3,24 @@ 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 + 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)) + 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)) - ] + 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)) - ] + 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/csr.py b/migen/bus/csr.py index 49dc5533..8530c0b8 100644 --- a/migen/bus/csr.py +++ b/migen/bus/csr.py @@ -5,126 +5,126 @@ 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) + ("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)) + 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) + 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 __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 + 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 + 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 + 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) + 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 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)) + 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] + 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 index bd0b93e9..621420c1 100644 --- a/migen/bus/memory.py +++ b/migen/bus/memory.py @@ -2,33 +2,33 @@ 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 + 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 __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 + 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 index b3550b75..fb3a0619 100644 --- a/migen/bus/transactions.py +++ b/migen/bus/transactions.py @@ -1,21 +1,21 @@ 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 __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) + ">" + def __str__(self): + return "<" + self.__class__.__name__ + " adr:" + hex(self.address) + " dat:" + hex(self.data) + ">" class TRead(Transaction): - pass + pass class TWrite(Transaction): - pass + pass diff --git a/migen/bus/wishbone.py b/migen/bus/wishbone.py index 11917ebd..ef06d25a 100644 --- a/migen/bus/wishbone.py +++ b/migen/bus/wishbone.py @@ -6,316 +6,316 @@ 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) + ("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)) + 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) + 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)) + 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)) + # 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) + 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) + 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 splits Wishbone accesses of N bits in M accesses of L bits where: - # N is the original data-width - # L is the target data-width - # M = N/L - def __init__(self, dw_i, dw_o): - self.wishbone_i = Interface(dw_i) - self.wishbone_o = Interface(dw_o) - self.ratio = dw_i//dw_o - - ### - - rst = Signal() - - # generate internal write and read ack - write_ack = Signal() - read_ack = Signal() - ack = Signal() - self.comb += [ - ack.eq(self.wishbone_o.cyc & self.wishbone_o.stb & self.wishbone_o.ack), - write_ack.eq(ack & self.wishbone_o.we), - read_ack.eq(ack & ~self.wishbone_o.we) - ] - - # accesses counter logic - cnt = Signal(max=self.ratio) - self.sync += If(rst, cnt.eq(0)).Elif(ack, cnt.eq(cnt + 1)) - - # read data path - dat_r = Signal(dw_i) - self.sync += If(ack, dat_r.eq(Cat(self.wishbone_o.dat_r, dat_r[:dw_i-dw_o]))) - - # write data path - dat_w = Signal(dw_i) - self.comb += dat_w.eq(self.wishbone_i.dat_w) - - # errors generation - err = Signal() - self.sync += If(ack, err.eq(self.wishbone_o.err)) - - # direct connection of wishbone_i --> wishbone_o signals - for name, size, direction in self.wishbone_i.layout: - if direction == DIR_M_TO_S and name not in ["adr", "dat_w", "sel"]: - self.comb += getattr(self.wishbone_o, name).eq(getattr(self.wishbone_i, name)) - - # adaptation of adr & dat signals - self.comb += [ - self.wishbone_o.adr[0:flen(cnt)].eq(cnt), - self.wishbone_o.adr[flen(cnt):].eq(self.wishbone_i.adr) - ] - - self.comb += chooser(dat_w, cnt, self.wishbone_o.dat_w, reverse=True) - self.comb += chooser(self.wishbone_i.sel, cnt, self.wishbone_o.sel, reverse=True) - - # fsm - fsm = FSM(reset_state="IDLE") - self.submodules += fsm - - fsm.act("IDLE", - If(write_ack, NextState("WRITE_ADAPT")), - If(read_ack, NextState("READ_ADAPT")) - ) - - fsm.act("WRITE_ADAPT", - If(write_ack & (cnt == self.ratio-1), - NextState("IDLE"), - rst.eq(1), - self.wishbone_i.err.eq(err | self.wishbone_o.err), - self.wishbone_i.ack.eq(1), - ) - ) - - master_i_dat_r = Signal(dw_i) - self.comb += master_i_dat_r.eq(Cat(self.wishbone_o.dat_r, dat_r[:dw_i-dw_o])) - - fsm.act("READ_ADAPT", - If(read_ack & (cnt == self.ratio-1), - NextState("IDLE"), - rst.eq(1), - self.wishbone_i.err.eq(err | self.wishbone_o.err), - self.wishbone_i.ack.eq(1), - self.wishbone_i.dat_r.eq(master_i_dat_r) - ) - ) + # DownConverter splits Wishbone accesses of N bits in M accesses of L bits where: + # N is the original data-width + # L is the target data-width + # M = N/L + def __init__(self, dw_i, dw_o): + self.wishbone_i = Interface(dw_i) + self.wishbone_o = Interface(dw_o) + self.ratio = dw_i//dw_o + + ### + + rst = Signal() + + # generate internal write and read ack + write_ack = Signal() + read_ack = Signal() + ack = Signal() + self.comb += [ + ack.eq(self.wishbone_o.cyc & self.wishbone_o.stb & self.wishbone_o.ack), + write_ack.eq(ack & self.wishbone_o.we), + read_ack.eq(ack & ~self.wishbone_o.we) + ] + + # accesses counter logic + cnt = Signal(max=self.ratio) + self.sync += If(rst, cnt.eq(0)).Elif(ack, cnt.eq(cnt + 1)) + + # read data path + dat_r = Signal(dw_i) + self.sync += If(ack, dat_r.eq(Cat(self.wishbone_o.dat_r, dat_r[:dw_i-dw_o]))) + + # write data path + dat_w = Signal(dw_i) + self.comb += dat_w.eq(self.wishbone_i.dat_w) + + # errors generation + err = Signal() + self.sync += If(ack, err.eq(self.wishbone_o.err)) + + # direct connection of wishbone_i --> wishbone_o signals + for name, size, direction in self.wishbone_i.layout: + if direction == DIR_M_TO_S and name not in ["adr", "dat_w", "sel"]: + self.comb += getattr(self.wishbone_o, name).eq(getattr(self.wishbone_i, name)) + + # adaptation of adr & dat signals + self.comb += [ + self.wishbone_o.adr[0:flen(cnt)].eq(cnt), + self.wishbone_o.adr[flen(cnt):].eq(self.wishbone_i.adr) + ] + + self.comb += chooser(dat_w, cnt, self.wishbone_o.dat_w, reverse=True) + self.comb += chooser(self.wishbone_i.sel, cnt, self.wishbone_o.sel, reverse=True) + + # fsm + fsm = FSM(reset_state="IDLE") + self.submodules += fsm + + fsm.act("IDLE", + If(write_ack, NextState("WRITE_ADAPT")), + If(read_ack, NextState("READ_ADAPT")) + ) + + fsm.act("WRITE_ADAPT", + If(write_ack & (cnt == self.ratio-1), + NextState("IDLE"), + rst.eq(1), + self.wishbone_i.err.eq(err | self.wishbone_o.err), + self.wishbone_i.ack.eq(1), + ) + ) + + master_i_dat_r = Signal(dw_i) + self.comb += master_i_dat_r.eq(Cat(self.wishbone_o.dat_r, dat_r[:dw_i-dw_o])) + + fsm.act("READ_ADAPT", + If(read_ack & (cnt == self.ratio-1), + NextState("IDLE"), + rst.eq(1), + self.wishbone_i.err.eq(err | self.wishbone_o.err), + self.wishbone_i.ack.eq(1), + self.wishbone_i.dat_r.eq(master_i_dat_r) + ) + ) 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 + 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 + 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 read(self, address): + return 0 - def write(self, address, data, sel): - pass + def write(self, address, data, sel): + pass - def can_ack(self, bus): - return True + 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 + 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)) - ] + 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 index 03f1d53b..9c81ebcf 100644 --- a/migen/bus/wishbone2csr.py +++ b/migen/bus/wishbone2csr.py @@ -4,24 +4,24 @@ 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 + 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)]) - ]) + 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/fhdl/bitcontainer.py b/migen/fhdl/bitcontainer.py index 5b105360..e05b8f45 100644 --- a/migen/fhdl/bitcontainer.py +++ b/migen/fhdl/bitcontainer.py @@ -1,202 +1,202 @@ from migen.fhdl import structure as f def log2_int(n, need_pow2=True): - l = 1 - r = 0 - while l < n: - l *= 2 - r += 1 - if need_pow2 and l != n: - raise ValueError("Not a power of 2") - return r + l = 1 + r = 0 + while l < n: + l *= 2 + r += 1 + if need_pow2 and l != n: + raise ValueError("Not a power of 2") + return r def bits_for(n, require_sign_bit=False): - if n > 0: - r = log2_int(n + 1, False) - else: - require_sign_bit = True - r = log2_int(-n, False) - if require_sign_bit: - r += 1 - return r + if n > 0: + r = log2_int(n + 1, False) + else: + require_sign_bit = True + r = log2_int(-n, False) + if require_sign_bit: + r += 1 + return r def value_bits_sign(v): - if isinstance(v, bool): - return 1, False - elif isinstance(v, int): - return bits_for(v), v < 0 - elif isinstance(v, f.Signal): - return v.nbits, v.signed - elif isinstance(v, (f.ClockSignal, f.ResetSignal)): - return 1, False - elif isinstance(v, f._Operator): - obs = list(map(value_bits_sign, v.operands)) - if v.op == "+" or v.op == "-": - if not obs[0][1] and not obs[1][1]: - # both operands unsigned - return max(obs[0][0], obs[1][0]) + 1, False - elif obs[0][1] and obs[1][1]: - # both operands signed - return max(obs[0][0], obs[1][0]) + 1, True - elif not obs[0][1] and obs[1][1]: - # first operand unsigned (add sign bit), second operand signed - return max(obs[0][0] + 1, obs[1][0]) + 1, True - else: - # first signed, second operand unsigned (add sign bit) - return max(obs[0][0], obs[1][0] + 1) + 1, True - elif v.op == "*": - if not obs[0][1] and not obs[1][1]: - # both operands unsigned - return obs[0][0] + obs[1][0] - elif obs[0][1] and obs[1][1]: - # both operands signed - return obs[0][0] + obs[1][0] - 1 - else: - # one operand signed, the other unsigned (add sign bit) - return obs[0][0] + obs[1][0] + 1 - 1 - elif v.op == "<<<": - if obs[1][1]: - extra = 2**(obs[1][0] - 1) - 1 - else: - extra = 2**obs[1][0] - 1 - return obs[0][0] + extra, obs[0][1] - elif v.op == ">>>": - if obs[1][1]: - extra = 2**(obs[1][0] - 1) - else: - extra = 0 - return obs[0][0] + extra, obs[0][1] - elif v.op == "&" or v.op == "^" or v.op == "|": - if not obs[0][1] and not obs[1][1]: - # both operands unsigned - return max(obs[0][0], obs[1][0]), False - elif obs[0][1] and obs[1][1]: - # both operands signed - return max(obs[0][0], obs[1][0]), True - elif not obs[0][1] and obs[1][1]: - # first operand unsigned (add sign bit), second operand signed - return max(obs[0][0] + 1, obs[1][0]), True - else: - # first signed, second operand unsigned (add sign bit) - return max(obs[0][0], obs[1][0] + 1), True - elif v.op == "<" or v.op == "<=" or v.op == "==" or v.op == "!=" \ - or v.op == ">" or v.op == ">=": - return 1, False - elif v.op == "~": - return obs[0] - else: - raise TypeError - elif isinstance(v, f._Slice): - return v.stop - v.start, value_bits_sign(v.value)[1] - elif isinstance(v, f.Cat): - return sum(value_bits_sign(sv)[0] for sv in v.l), False - elif isinstance(v, f.Replicate): - return (value_bits_sign(v.v)[0])*v.n, False - elif isinstance(v, f._ArrayProxy): - bsc = list(map(value_bits_sign, v.choices)) - return max(bs[0] for bs in bsc), any(bs[1] for bs in bsc) - else: - raise TypeError("Can not calculate bit length of {} {}".format( - type(v), v)) + if isinstance(v, bool): + return 1, False + elif isinstance(v, int): + return bits_for(v), v < 0 + elif isinstance(v, f.Signal): + return v.nbits, v.signed + elif isinstance(v, (f.ClockSignal, f.ResetSignal)): + return 1, False + elif isinstance(v, f._Operator): + obs = list(map(value_bits_sign, v.operands)) + if v.op == "+" or v.op == "-": + if not obs[0][1] and not obs[1][1]: + # both operands unsigned + return max(obs[0][0], obs[1][0]) + 1, False + elif obs[0][1] and obs[1][1]: + # both operands signed + return max(obs[0][0], obs[1][0]) + 1, True + elif not obs[0][1] and obs[1][1]: + # first operand unsigned (add sign bit), second operand signed + return max(obs[0][0] + 1, obs[1][0]) + 1, True + else: + # first signed, second operand unsigned (add sign bit) + return max(obs[0][0], obs[1][0] + 1) + 1, True + elif v.op == "*": + if not obs[0][1] and not obs[1][1]: + # both operands unsigned + return obs[0][0] + obs[1][0] + elif obs[0][1] and obs[1][1]: + # both operands signed + return obs[0][0] + obs[1][0] - 1 + else: + # one operand signed, the other unsigned (add sign bit) + return obs[0][0] + obs[1][0] + 1 - 1 + elif v.op == "<<<": + if obs[1][1]: + extra = 2**(obs[1][0] - 1) - 1 + else: + extra = 2**obs[1][0] - 1 + return obs[0][0] + extra, obs[0][1] + elif v.op == ">>>": + if obs[1][1]: + extra = 2**(obs[1][0] - 1) + else: + extra = 0 + return obs[0][0] + extra, obs[0][1] + elif v.op == "&" or v.op == "^" or v.op == "|": + if not obs[0][1] and not obs[1][1]: + # both operands unsigned + return max(obs[0][0], obs[1][0]), False + elif obs[0][1] and obs[1][1]: + # both operands signed + return max(obs[0][0], obs[1][0]), True + elif not obs[0][1] and obs[1][1]: + # first operand unsigned (add sign bit), second operand signed + return max(obs[0][0] + 1, obs[1][0]), True + else: + # first signed, second operand unsigned (add sign bit) + return max(obs[0][0], obs[1][0] + 1), True + elif v.op == "<" or v.op == "<=" or v.op == "==" or v.op == "!=" \ + or v.op == ">" or v.op == ">=": + return 1, False + elif v.op == "~": + return obs[0] + else: + raise TypeError + elif isinstance(v, f._Slice): + return v.stop - v.start, value_bits_sign(v.value)[1] + elif isinstance(v, f.Cat): + return sum(value_bits_sign(sv)[0] for sv in v.l), False + elif isinstance(v, f.Replicate): + return (value_bits_sign(v.v)[0])*v.n, False + elif isinstance(v, f._ArrayProxy): + bsc = list(map(value_bits_sign, v.choices)) + return max(bs[0] for bs in bsc), any(bs[1] for bs in bsc) + else: + raise TypeError("Can not calculate bit length of {} {}".format( + type(v), v)) def flen(v): - """Bit length of an expression - - Parameters - ---------- - v : int, bool or Value - - Returns - ------- - int - Number of bits required to store `v` or available in `v` - - Examples - -------- - >>> flen(f.Signal(8)) - 8 - >>> flen(0xaa) - 8 - """ - return value_bits_sign(v)[0] + """Bit length of an expression + + Parameters + ---------- + v : int, bool or Value + + Returns + ------- + int + Number of bits required to store `v` or available in `v` + + Examples + -------- + >>> flen(f.Signal(8)) + 8 + >>> flen(0xaa) + 8 + """ + return value_bits_sign(v)[0] def fiter(v): - """Bit iterator - - Parameters - ---------- - v : int, bool or Value - - Returns - ------- - iter - Iterator over the bits in `v` - - Examples - -------- - >>> list(fiter(f.Signal(2))) #doctest: +ELLIPSIS - [, ] - >>> list(fiter(4)) - [0, 0, 1] - """ - if isinstance(v, (bool, int)): - return ((v >> i) & 1 for i in range(bits_for(v))) - elif isinstance(v, f.Value): - return (v[i] for i in range(flen(v))) - else: - raise TypeError("Can not bit-iterate {} {}".format(type(v), v)) + """Bit iterator + + Parameters + ---------- + v : int, bool or Value + + Returns + ------- + iter + Iterator over the bits in `v` + + Examples + -------- + >>> list(fiter(f.Signal(2))) #doctest: +ELLIPSIS + [, ] + >>> list(fiter(4)) + [0, 0, 1] + """ + if isinstance(v, (bool, int)): + return ((v >> i) & 1 for i in range(bits_for(v))) + elif isinstance(v, f.Value): + return (v[i] for i in range(flen(v))) + else: + raise TypeError("Can not bit-iterate {} {}".format(type(v), v)) def fslice(v, s): - """Bit slice - - Parameters - ---------- - v : int, bool or Value - s : slice or int - - Returns - ------- - int or Value - Expression for the slice `s` of `v`. - - Examples - -------- - >>> fslice(f.Signal(2), 1) #doctest: +ELLIPSIS - - >>> bin(fslice(0b1101, slice(1, None, 2))) - '0b10' - >>> fslice(-1, slice(0, 4)) - 1 - >>> fslice(-7, slice(None)) - 9 - """ - if isinstance(v, (bool, int)): - if isinstance(s, int): - s = slice(s) - idx = range(*s.indices(bits_for(v))) - return sum(((v >> i) & 1) << j for j, i in enumerate(idx)) - elif isinstance(v, f.Value): - return v[s] - else: - raise TypeError("Can not bit-slice {} {}".format(type(v), v)) + """Bit slice + + Parameters + ---------- + v : int, bool or Value + s : slice or int + + Returns + ------- + int or Value + Expression for the slice `s` of `v`. + + Examples + -------- + >>> fslice(f.Signal(2), 1) #doctest: +ELLIPSIS + + >>> bin(fslice(0b1101, slice(1, None, 2))) + '0b10' + >>> fslice(-1, slice(0, 4)) + 1 + >>> fslice(-7, slice(None)) + 9 + """ + if isinstance(v, (bool, int)): + if isinstance(s, int): + s = slice(s) + idx = range(*s.indices(bits_for(v))) + return sum(((v >> i) & 1) << j for j, i in enumerate(idx)) + elif isinstance(v, f.Value): + return v[s] + else: + raise TypeError("Can not bit-slice {} {}".format(type(v), v)) def freversed(v): - """Bit reverse - - Parameters - ---------- - v : int, bool or Value - - Returns - ------- - int or Value - Expression containing the bit reversed input. - - Examples - -------- - >>> freversed(f.Signal(2)) #doctest: +ELLIPSIS - - >>> bin(freversed(0b1011)) - '0b1101' - """ - return fslice(v, slice(None, None, -1)) + """Bit reverse + + Parameters + ---------- + v : int, bool or Value + + Returns + ------- + int or Value + Expression containing the bit reversed input. + + Examples + -------- + >>> freversed(f.Signal(2)) #doctest: +ELLIPSIS + + >>> bin(freversed(0b1011)) + '0b1101' + """ + return fslice(v, slice(None, None, -1)) diff --git a/migen/fhdl/decorators.py b/migen/fhdl/decorators.py index ddd1a965..aaa5d56f 100644 --- a/migen/fhdl/decorators.py +++ b/migen/fhdl/decorators.py @@ -5,111 +5,111 @@ from migen.fhdl.module import Module from migen.fhdl.tools import insert_reset, rename_clock_domain class ModuleTransformer: - # overload this in derived classes - def transform_instance(self, i): - pass - - # overload this in derived classes - def transform_fragment(self, i, f): - pass - - def wrap_class(self, victim): - class Wrapped(victim): - def __init__(i, *args, **kwargs): - victim.__init__(i, *args, **kwargs) - self.transform_instance(i) - - def get_fragment(i): - f = victim.get_fragment(i) - self.transform_fragment(i, f) - return f - - Wrapped.__name__ = victim.__name__ - # "{}_{}".format(self.__class__.__name__, victim.__name__) - return Wrapped - - def wrap_instance(self, victim): - self.transform_instance(victim) - orig_get_fragment = victim.get_fragment - - def get_fragment(): - f = orig_get_fragment() - self.transform_fragment(victim, f) - return f - - victim.get_fragment = get_fragment - return victim - - def __call__(self, victim): - if isinstance(victim, Module): - return self.wrap_instance(victim) - else: - return self.wrap_class(victim) - - @classmethod - def adhoc(cls, i, *args, **kwargs): - warnings.warn("deprecated, use the plain transformer", DeprecationWarning, 2) - return cls(*args, **kwargs)(i) + # overload this in derived classes + def transform_instance(self, i): + pass + + # overload this in derived classes + def transform_fragment(self, i, f): + pass + + def wrap_class(self, victim): + class Wrapped(victim): + def __init__(i, *args, **kwargs): + victim.__init__(i, *args, **kwargs) + self.transform_instance(i) + + def get_fragment(i): + f = victim.get_fragment(i) + self.transform_fragment(i, f) + return f + + Wrapped.__name__ = victim.__name__ + # "{}_{}".format(self.__class__.__name__, victim.__name__) + return Wrapped + + def wrap_instance(self, victim): + self.transform_instance(victim) + orig_get_fragment = victim.get_fragment + + def get_fragment(): + f = orig_get_fragment() + self.transform_fragment(victim, f) + return f + + victim.get_fragment = get_fragment + return victim + + def __call__(self, victim): + if isinstance(victim, Module): + return self.wrap_instance(victim) + else: + return self.wrap_class(victim) + + @classmethod + def adhoc(cls, i, *args, **kwargs): + warnings.warn("deprecated, use the plain transformer", DeprecationWarning, 2) + return cls(*args, **kwargs)(i) def DecorateModule(transformer, *args, **kwargs): - warnings.warn("deprecated, use the plain transformer", DeprecationWarning, 2) - return transformer.__self__(*args, **kwargs) + warnings.warn("deprecated, use the plain transformer", DeprecationWarning, 2) + return transformer.__self__(*args, **kwargs) class ControlInserter(ModuleTransformer): - control_name = None # override this - - def __init__(self, clock_domains=None): - self.clock_domains = clock_domains - - def transform_instance(self, i): - if self.clock_domains is None: - ctl = Signal(name=self.control_name) - assert not hasattr(i, self.control_name) - setattr(i, self.control_name, ctl) - else: - for cd in self.clock_domains: - name = self.control_name + "_" + cd - ctl = Signal(name=name) - assert not hasattr(i, name) - setattr(i, name, ctl) - - def transform_fragment(self, i, f): - if self.clock_domains is None: - if len(f.sync) != 1: - raise ValueError("Control signal clock domains must be specified when module has more than one domain") - cdn = list(f.sync.keys())[0] - to_insert = [(getattr(i, self.control_name), cdn)] - else: - to_insert = [(getattr(i, self.control_name + "_" + cdn), cdn) - for cdn in self.clock_domains] - self.transform_fragment_insert(i, f, to_insert) + control_name = None # override this + + def __init__(self, clock_domains=None): + self.clock_domains = clock_domains + + def transform_instance(self, i): + if self.clock_domains is None: + ctl = Signal(name=self.control_name) + assert not hasattr(i, self.control_name) + setattr(i, self.control_name, ctl) + else: + for cd in self.clock_domains: + name = self.control_name + "_" + cd + ctl = Signal(name=name) + assert not hasattr(i, name) + setattr(i, name, ctl) + + def transform_fragment(self, i, f): + if self.clock_domains is None: + if len(f.sync) != 1: + raise ValueError("Control signal clock domains must be specified when module has more than one domain") + cdn = list(f.sync.keys())[0] + to_insert = [(getattr(i, self.control_name), cdn)] + else: + to_insert = [(getattr(i, self.control_name + "_" + cdn), cdn) + for cdn in self.clock_domains] + self.transform_fragment_insert(i, f, to_insert) class CEInserter(ControlInserter): - control_name = "ce" + control_name = "ce" - def transform_fragment_insert(self, i, f, to_insert): - for ce, cdn in to_insert: - f.sync[cdn] = [If(ce, *f.sync[cdn])] + def transform_fragment_insert(self, i, f, to_insert): + for ce, cdn in to_insert: + f.sync[cdn] = [If(ce, *f.sync[cdn])] InsertCE = CEInserter.adhoc class ResetInserter(ControlInserter): - control_name = "reset" + control_name = "reset" - def transform_fragment_insert(self, i, f, to_insert): - for reset, cdn in to_insert: - f.sync[cdn] = insert_reset(reset, f.sync[cdn]) + def transform_fragment_insert(self, i, f, to_insert): + for reset, cdn in to_insert: + f.sync[cdn] = insert_reset(reset, f.sync[cdn]) InsertReset = ResetInserter.adhoc class ClockDomainsRenamer(ModuleTransformer): - def __init__(self, cd_remapping): - if isinstance(cd_remapping, str): - cd_remapping = {"sys": cd_remapping} - self.cd_remapping = cd_remapping - - def transform_fragment(self, i, f): - for old, new in self.cd_remapping.items(): - rename_clock_domain(f, old, new) + def __init__(self, cd_remapping): + if isinstance(cd_remapping, str): + cd_remapping = {"sys": cd_remapping} + self.cd_remapping = cd_remapping + + def transform_fragment(self, i, f): + for old, new in self.cd_remapping.items(): + rename_clock_domain(f, old, new) RenameClockDomains = ClockDomainsRenamer.adhoc diff --git a/migen/fhdl/edif.py b/migen/fhdl/edif.py index a3acc466..ef6663dd 100644 --- a/migen/fhdl/edif.py +++ b/migen/fhdl/edif.py @@ -15,190 +15,190 @@ _Instance = namedtuple("_Instance", "name cell properties") _NetBranch = namedtuple("_NetBranch", "portname instancename") def _write_cells(cells): - r = "" - for cell in cells: - r += """ - (cell {0.name} - (cellType GENERIC) - (view view_1 - (viewType NETLIST) - (interface""".format(cell) - for port in cell.ports: - r += """ - (port {0.name} (direction {0.direction}))""".format(port) - r += """ - ) - ) - )""" - return r + r = "" + for cell in cells: + r += """ + (cell {0.name} + (cellType GENERIC) + (view view_1 + (viewType NETLIST) + (interface""".format(cell) + for port in cell.ports: + r += """ + (port {0.name} (direction {0.direction}))""".format(port) + r += """ + ) + ) + )""" + return r def _write_io(ios): - r = "" - for s in ios: - r += """ - (port {0.name} (direction {0.direction}))""".format(s) - return r + r = "" + for s in ios: + r += """ + (port {0.name} (direction {0.direction}))""".format(s) + return r def _write_instantiations(instances, cell_library): - instantiations = "" - for instance in instances: - instantiations += """ - (instance {0.name} - (viewRef view_1 (cellRef {0.cell} (libraryRef {1})))""".format(instance, cell_library) - for prop in instance.properties: - instantiations += """ - (property {0} (string "{1}"))""".format(prop.name, prop.value) - instantiations += """ - )""" - return instantiations + instantiations = "" + for instance in instances: + instantiations += """ + (instance {0.name} + (viewRef view_1 (cellRef {0.cell} (libraryRef {1})))""".format(instance, cell_library) + for prop in instance.properties: + instantiations += """ + (property {0} (string "{1}"))""".format(prop.name, prop.value) + instantiations += """ + )""" + return instantiations def _write_connections(connections): - r = "" - for netname, branches in connections.items(): - r += """ - (net {0} - (joined""".format(netname) - for branch in branches: - r += """ - (portRef {0}{1})""".format(branch.portname, "" if branch.instancename == "" else " (instanceRef {})".format(branch.instancename)) - r += """ - ) - )""" - return r + r = "" + for netname, branches in connections.items(): + r += """ + (net {0} + (joined""".format(netname) + for branch in branches: + r += """ + (portRef {0}{1})""".format(branch.portname, "" if branch.instancename == "" else " (instanceRef {})".format(branch.instancename)) + r += """ + ) + )""" + return r def _write_edif(cells, ios, instances, connections, cell_library, design_name, part, vendor): - r = """(edif {0} - (edifVersion 2 0 0) - (edifLevel 0) - (keywordMap (keywordLevel 0)) - (external {1} - (edifLevel 0) - (technology (numberDefinition))""".format(design_name, cell_library) - r += _write_cells(cells) - r += """ - ) - (library {0}_lib - (edifLevel 0) - (technology (numberDefinition)) - (cell {0} - (cellType GENERIC) - (view view_1 - (viewType NETLIST) - (interface""".format(design_name) - r += _write_io(ios) - r += """ - (designator "{0}") - ) - (contents""".format(part) - r += _write_instantiations(instances, cell_library) - r += _write_connections(connections) - r += """ - ) - ) - ) - ) - (design {0} - (cellRef {0} (libraryRef {0}_lib)) - (property PART (string "{1}") (owner "{2}")) - ) + r = """(edif {0} + (edifVersion 2 0 0) + (edifLevel 0) + (keywordMap (keywordLevel 0)) + (external {1} + (edifLevel 0) + (technology (numberDefinition))""".format(design_name, cell_library) + r += _write_cells(cells) + r += """ + ) + (library {0}_lib + (edifLevel 0) + (technology (numberDefinition)) + (cell {0} + (cellType GENERIC) + (view view_1 + (viewType NETLIST) + (interface""".format(design_name) + r += _write_io(ios) + r += """ + (designator "{0}") + ) + (contents""".format(part) + r += _write_instantiations(instances, cell_library) + r += _write_connections(connections) + r += """ + ) + ) + ) + ) + (design {0} + (cellRef {0} (libraryRef {0}_lib)) + (property PART (string "{1}") (owner "{2}")) + ) )""".format(design_name, part, vendor) - return r + return r def _generate_cells(f): - cell_dict = OrderedDict() - for special in f.specials: - if isinstance(special, Instance): - port_list = [] - for port in special.items: - if isinstance(port, Instance.Input): - port_list.append(_Port(port.name, "INPUT")) - elif isinstance(port, Instance.Output): - port_list.append(_Port(port.name, "OUTPUT")) - elif isinstance(port, Instance.InOut): - port_list.append(_Port(port.name, "INOUT")) - elif isinstance(port, Instance.Parameter): - pass - else: - raise NotImplementedError("Unsupported instance item") - if special.of in cell_dict: - if set(port_list) != set(cell_dict[special.of]): - raise ValueError("All instances must have the same ports for EDIF conversion") - else: - cell_dict[special.of] = port_list - else: - raise ValueError("EDIF conversion can only handle synthesized fragments") - return [_Cell(k, v) for k, v in cell_dict.items()] + cell_dict = OrderedDict() + for special in f.specials: + if isinstance(special, Instance): + port_list = [] + for port in special.items: + if isinstance(port, Instance.Input): + port_list.append(_Port(port.name, "INPUT")) + elif isinstance(port, Instance.Output): + port_list.append(_Port(port.name, "OUTPUT")) + elif isinstance(port, Instance.InOut): + port_list.append(_Port(port.name, "INOUT")) + elif isinstance(port, Instance.Parameter): + pass + else: + raise NotImplementedError("Unsupported instance item") + if special.of in cell_dict: + if set(port_list) != set(cell_dict[special.of]): + raise ValueError("All instances must have the same ports for EDIF conversion") + else: + cell_dict[special.of] = port_list + else: + raise ValueError("EDIF conversion can only handle synthesized fragments") + return [_Cell(k, v) for k, v in cell_dict.items()] def _generate_instances(f,ns): - instances = [] - for special in f.specials: - if isinstance(special, Instance): - props = [] - for prop in special.items: - if isinstance(prop, Instance.Input): - pass - elif isinstance(prop, Instance.Output): - pass - elif isinstance(prop, Instance.InOut): - pass - elif isinstance(prop, Instance.Parameter): - props.append(_Property(name=prop.name, value=prop.value)) - else: - raise NotImplementedError("Unsupported instance item") - instances.append(_Instance(name=ns.get_name(special), cell=special.of, properties=props)) - else: - raise ValueError("EDIF conversion can only handle synthesized fragments") - return instances + instances = [] + for special in f.specials: + if isinstance(special, Instance): + props = [] + for prop in special.items: + if isinstance(prop, Instance.Input): + pass + elif isinstance(prop, Instance.Output): + pass + elif isinstance(prop, Instance.InOut): + pass + elif isinstance(prop, Instance.Parameter): + props.append(_Property(name=prop.name, value=prop.value)) + else: + raise NotImplementedError("Unsupported instance item") + instances.append(_Instance(name=ns.get_name(special), cell=special.of, properties=props)) + else: + raise ValueError("EDIF conversion can only handle synthesized fragments") + return instances def _generate_ios(f, ios, ns): - outs = list_special_ios(f, False, True, False) - inouts = list_special_ios(f, False, False, True) - r = [] - for io in ios: - direction = "OUTPUT" if io in outs else "INOUT" if io in inouts else "INPUT" - r.append(_Port(name=ns.get_name(io), direction=direction)) - return r + outs = list_special_ios(f, False, True, False) + inouts = list_special_ios(f, False, False, True) + r = [] + for io in ios: + direction = "OUTPUT" if io in outs else "INOUT" if io in inouts else "INPUT" + r.append(_Port(name=ns.get_name(io), direction=direction)) + return r def _generate_connections(f, ios, ns): - r = OrderedDict() - for special in f.specials: - if isinstance(special, Instance): - instname = ns.get_name(special) - for port in special.items: - if isinstance(port, Instance._IO): - s = ns.get_name(port.expr) - if s not in r: - r[s] = [] - r[s].append(_NetBranch(portname=port.name, instancename=instname)) - elif isinstance(port, Instance.Parameter): - pass - else: - raise NotImplementedError("Unsupported instance item") - else: - raise ValueError("EDIF conversion can only handle synthesized fragments") - for s in ios: - io = ns.get_name(s) - if io not in r: - r[io] = [] - r[io].append(_NetBranch(portname=io, instancename="")) - return r + r = OrderedDict() + for special in f.specials: + if isinstance(special, Instance): + instname = ns.get_name(special) + for port in special.items: + if isinstance(port, Instance._IO): + s = ns.get_name(port.expr) + if s not in r: + r[s] = [] + r[s].append(_NetBranch(portname=port.name, instancename=instname)) + elif isinstance(port, Instance.Parameter): + pass + else: + raise NotImplementedError("Unsupported instance item") + else: + raise ValueError("EDIF conversion can only handle synthesized fragments") + for s in ios: + io = ns.get_name(s) + if io not in r: + r[io] = [] + r[io].append(_NetBranch(portname=io, instancename="")) + return r def convert(f, ios, cell_library, vendor, device, name="top"): - if not isinstance(f, _Fragment): - f = f.get_fragment() - if f.comb != [] or f.sync != {}: - raise ValueError("EDIF conversion can only handle synthesized fragments") - if ios is None: - ios = set() - cells = _generate_cells(f) - ns = build_namespace(list_special_ios(f, True, True, True)) - instances = _generate_instances(f, ns) - inouts = _generate_ios(f, ios, ns) - connections = _generate_connections(f, ios, ns) - src = _write_edif(cells, inouts, instances, connections, cell_library, name, device, vendor) + if not isinstance(f, _Fragment): + f = f.get_fragment() + if f.comb != [] or f.sync != {}: + raise ValueError("EDIF conversion can only handle synthesized fragments") + if ios is None: + ios = set() + cells = _generate_cells(f) + ns = build_namespace(list_special_ios(f, True, True, True)) + instances = _generate_instances(f, ns) + inouts = _generate_ios(f, ios, ns) + connections = _generate_connections(f, ios, ns) + src = _write_edif(cells, inouts, instances, connections, cell_library, name, device, vendor) - r = ConvOutput() - r.set_main_source(src) - r.ns = ns - return r + r = ConvOutput() + r.set_main_source(src) + r.ns = ns + return r diff --git a/migen/fhdl/module.py b/migen/fhdl/module.py index 1d83abe9..a08bc680 100644 --- a/migen/fhdl/module.py +++ b/migen/fhdl/module.py @@ -8,177 +8,177 @@ from migen.fhdl.tools import rename_clock_domain from migen.sim.upper import gen_sim, proxy_sim class FinalizeError(Exception): - pass + pass def _flat_list(e): - if isinstance(e, collections.Iterable): - return flat_iteration(e) - else: - return [e] + if isinstance(e, collections.Iterable): + return flat_iteration(e) + else: + return [e] class _ModuleProxy: - def __init__(self, fm): - object.__setattr__(self, "_fm", fm) + def __init__(self, fm): + object.__setattr__(self, "_fm", fm) class _ModuleComb(_ModuleProxy): - def __iadd__(self, other): - self._fm._fragment.comb += _flat_list(other) - return self + def __iadd__(self, other): + self._fm._fragment.comb += _flat_list(other) + return self def _cd_append(d, key, statements): - try: - l = d[key] - except KeyError: - l = [] - d[key] = l - l += _flat_list(statements) + try: + l = d[key] + except KeyError: + l = [] + d[key] = l + l += _flat_list(statements) class _ModuleSyncCD: - def __init__(self, fm, cd): - self._fm = fm - self._cd = cd + def __init__(self, fm, cd): + self._fm = fm + self._cd = cd - def __iadd__(self, other): - _cd_append(self._fm._fragment.sync, self._cd, other) - return self + def __iadd__(self, other): + _cd_append(self._fm._fragment.sync, self._cd, other) + return self class _ModuleSync(_ModuleProxy): - def __iadd__(self, other): - _cd_append(self._fm._fragment.sync, "sys", other) - return self + def __iadd__(self, other): + _cd_append(self._fm._fragment.sync, "sys", other) + return self - def __getattr__(self, name): - return _ModuleSyncCD(self._fm, name) + def __getattr__(self, name): + return _ModuleSyncCD(self._fm, name) - def __setattr__(self, name, value): - if not isinstance(value, _ModuleSyncCD): - raise AttributeError("Attempted to assign sync property - use += instead") + def __setattr__(self, name, value): + if not isinstance(value, _ModuleSyncCD): + raise AttributeError("Attempted to assign sync property - use += instead") # _ModuleForwardAttr enables user classes to do e.g.: # self.subm.foobar = SomeModule() # and then access the submodule with self.foobar. class _ModuleForwardAttr: - def __setattr__(self, name, value): - self.__iadd__(value) - setattr(self._fm, name, value) + def __setattr__(self, name, value): + self.__iadd__(value) + setattr(self._fm, name, value) class _ModuleSpecials(_ModuleProxy, _ModuleForwardAttr): - def __iadd__(self, other): - self._fm._fragment.specials |= set(_flat_list(other)) - return self + def __iadd__(self, other): + self._fm._fragment.specials |= set(_flat_list(other)) + return self class _ModuleSubmodules(_ModuleProxy): - def __setattr__(self, name, value): - self._fm._submodules += [(name, e) for e in _flat_list(value)] - setattr(self._fm, name, value) + def __setattr__(self, name, value): + self._fm._submodules += [(name, e) for e in _flat_list(value)] + setattr(self._fm, name, value) - def __iadd__(self, other): - self._fm._submodules += [(None, e) for e in _flat_list(other)] - return self + def __iadd__(self, other): + self._fm._submodules += [(None, e) for e in _flat_list(other)] + return self class _ModuleClockDomains(_ModuleProxy, _ModuleForwardAttr): - def __iadd__(self, other): - self._fm._fragment.clock_domains += _flat_list(other) - return self + def __iadd__(self, other): + self._fm._fragment.clock_domains += _flat_list(other) + return self class Module: - def get_fragment(self): - assert(not self.get_fragment_called) - self.get_fragment_called = True - self.finalize() - return self._fragment - - def __getattr__(self, name): - if name == "comb": - return _ModuleComb(self) - elif name == "sync": - return _ModuleSync(self) - elif name == "specials": - return _ModuleSpecials(self) - elif name == "submodules": - return _ModuleSubmodules(self) - elif name == "clock_domains": - return _ModuleClockDomains(self) - - # hack to have initialized regular attributes without using __init__ - # (which would require derived classes to call it) - elif name == "finalized": - self.finalized = False - return self.finalized - elif name == "_fragment": - simf = None - try: - simf = self.do_simulation - except AttributeError: - try: - simg = self.gen_simulation - except AttributeError: - pass - else: - simf = gen_sim(simg) - if simf is not None: - simf = proxy_sim(self, simf) - sim = [] if simf is None else [simf] - self._fragment = _Fragment(sim=sim) - return self._fragment - elif name == "_submodules": - self._submodules = [] - return self._submodules - elif name == "_clock_domains": - self._clock_domains = [] - return self._clock_domains - elif name == "get_fragment_called": - self.get_fragment_called = False - return self.get_fragment_called - - else: - raise AttributeError("'"+self.__class__.__name__+"' object has no attribute '"+name+"'") - - def __setattr__(self, name, value): - if name in ["comb", "sync", "specials", "submodules", "clock_domains"]: - if not isinstance(value, _ModuleProxy): - raise AttributeError("Attempted to assign special Module property - use += instead") - else: - object.__setattr__(self, name, value) - - def _collect_submodules(self): - r = [] - for name, submodule in self._submodules: - if not submodule.get_fragment_called: - r.append((name, submodule.get_fragment())) - return r - - def finalize(self, *args, **kwargs): - if not self.finalized: - self.finalized = True - # finalize existing submodules before finalizing us - subfragments = self._collect_submodules() - self.do_finalize(*args, **kwargs) - # finalize submodules created by do_finalize - subfragments += self._collect_submodules() - # resolve clock domain name conflicts - needs_renaming = set() - for (mod_name1, f1), (mod_name2, f2) in combinations(subfragments, 2): - f1_names = set(cd.name for cd in f1.clock_domains) - f2_names = set(cd.name for cd in f2.clock_domains) - common_names = f1_names & f2_names - if common_names: - if mod_name1 is None or mod_name2 is None: - raise ValueError("Multiple submodules with local clock domains cannot be anonymous") - if mod_name1 == mod_name2: - raise ValueError("Multiple submodules with local clock domains cannot have the same name") - needs_renaming |= common_names - for mod_name, f in subfragments: - for cd in f.clock_domains: - if cd.name in needs_renaming: - rename_clock_domain(f, cd.name, mod_name + "_" + cd.name) - # sum subfragments - for mod_name, f in subfragments: - self._fragment += f - - def do_finalize(self): - pass - - def do_exit(self, *args, **kwargs): - for name, submodule in self._submodules: - submodule.do_exit(*args, **kwargs) + def get_fragment(self): + assert(not self.get_fragment_called) + self.get_fragment_called = True + self.finalize() + return self._fragment + + def __getattr__(self, name): + if name == "comb": + return _ModuleComb(self) + elif name == "sync": + return _ModuleSync(self) + elif name == "specials": + return _ModuleSpecials(self) + elif name == "submodules": + return _ModuleSubmodules(self) + elif name == "clock_domains": + return _ModuleClockDomains(self) + + # hack to have initialized regular attributes without using __init__ + # (which would require derived classes to call it) + elif name == "finalized": + self.finalized = False + return self.finalized + elif name == "_fragment": + simf = None + try: + simf = self.do_simulation + except AttributeError: + try: + simg = self.gen_simulation + except AttributeError: + pass + else: + simf = gen_sim(simg) + if simf is not None: + simf = proxy_sim(self, simf) + sim = [] if simf is None else [simf] + self._fragment = _Fragment(sim=sim) + return self._fragment + elif name == "_submodules": + self._submodules = [] + return self._submodules + elif name == "_clock_domains": + self._clock_domains = [] + return self._clock_domains + elif name == "get_fragment_called": + self.get_fragment_called = False + return self.get_fragment_called + + else: + raise AttributeError("'"+self.__class__.__name__+"' object has no attribute '"+name+"'") + + def __setattr__(self, name, value): + if name in ["comb", "sync", "specials", "submodules", "clock_domains"]: + if not isinstance(value, _ModuleProxy): + raise AttributeError("Attempted to assign special Module property - use += instead") + else: + object.__setattr__(self, name, value) + + def _collect_submodules(self): + r = [] + for name, submodule in self._submodules: + if not submodule.get_fragment_called: + r.append((name, submodule.get_fragment())) + return r + + def finalize(self, *args, **kwargs): + if not self.finalized: + self.finalized = True + # finalize existing submodules before finalizing us + subfragments = self._collect_submodules() + self.do_finalize(*args, **kwargs) + # finalize submodules created by do_finalize + subfragments += self._collect_submodules() + # resolve clock domain name conflicts + needs_renaming = set() + for (mod_name1, f1), (mod_name2, f2) in combinations(subfragments, 2): + f1_names = set(cd.name for cd in f1.clock_domains) + f2_names = set(cd.name for cd in f2.clock_domains) + common_names = f1_names & f2_names + if common_names: + if mod_name1 is None or mod_name2 is None: + raise ValueError("Multiple submodules with local clock domains cannot be anonymous") + if mod_name1 == mod_name2: + raise ValueError("Multiple submodules with local clock domains cannot have the same name") + needs_renaming |= common_names + for mod_name, f in subfragments: + for cd in f.clock_domains: + if cd.name in needs_renaming: + rename_clock_domain(f, cd.name, mod_name + "_" + cd.name) + # sum subfragments + for mod_name, f in subfragments: + self._fragment += f + + def do_finalize(self): + pass + + def do_exit(self, *args, **kwargs): + for name, submodule in self._submodules: + submodule.do_exit(*args, **kwargs) diff --git a/migen/fhdl/namer.py b/migen/fhdl/namer.py index 8a30c6e7..ea9d5ff9 100644 --- a/migen/fhdl/namer.py +++ b/migen/fhdl/namer.py @@ -4,231 +4,231 @@ from itertools import combinations from migen.fhdl.structure import * class _Node: - def __init__(self): - self.signal_count = 0 - self.numbers = set() - self.use_name = False - self.use_number = False - self.children = OrderedDict() + def __init__(self): + self.signal_count = 0 + self.numbers = set() + self.use_name = False + self.use_number = False + self.children = OrderedDict() def _display_tree(filename, tree): - from migen.util.treeviz import RenderNode - - def _to_render_node(name, node): - children = [_to_render_node(k, v) for k, v in node.children.items()] - if node.use_name: - if node.use_number: - color = (0.5, 0.9, 0.8) - else: - color = (0.8, 0.5, 0.9) - else: - if node.use_number: - color = (0.9, 0.8, 0.5) - else: - color = (0.8, 0.8, 0.8) - label = "{0}\n{1} signals\n{2}".format(name, node.signal_count, node.numbers) - return RenderNode(label, children, color=color) - - top = _to_render_node("top", tree) - top.to_svg(filename) + from migen.util.treeviz import RenderNode + + def _to_render_node(name, node): + children = [_to_render_node(k, v) for k, v in node.children.items()] + if node.use_name: + if node.use_number: + color = (0.5, 0.9, 0.8) + else: + color = (0.8, 0.5, 0.9) + else: + if node.use_number: + color = (0.9, 0.8, 0.5) + else: + color = (0.8, 0.8, 0.8) + label = "{0}\n{1} signals\n{2}".format(name, node.signal_count, node.numbers) + return RenderNode(label, children, color=color) + + top = _to_render_node("top", tree) + top.to_svg(filename) def _build_tree(signals, basic_tree=None): - root = _Node() - for signal in signals: - current_b = basic_tree - current = root - current.signal_count += 1 - for name, number in signal.backtrace: - if basic_tree is None: - use_number = False - else: - current_b = current_b.children[name] - use_number = current_b.use_number - if use_number: - key = (name, number) - else: - key = name - try: - current = current.children[key] - except KeyError: - new = _Node() - current.children[key] = new - current = new - current.numbers.add(number) - if use_number: - current.all_numbers = sorted(current_b.numbers) - current.signal_count += 1 - return root + root = _Node() + for signal in signals: + current_b = basic_tree + current = root + current.signal_count += 1 + for name, number in signal.backtrace: + if basic_tree is None: + use_number = False + else: + current_b = current_b.children[name] + use_number = current_b.use_number + if use_number: + key = (name, number) + else: + key = name + try: + current = current.children[key] + except KeyError: + new = _Node() + current.children[key] = new + current = new + current.numbers.add(number) + if use_number: + current.all_numbers = sorted(current_b.numbers) + current.signal_count += 1 + return root def _set_use_name(node, node_name=""): - cnames = [(k, _set_use_name(v, k)) for k, v in node.children.items()] - for (c1_prefix, c1_names), (c2_prefix, c2_names) in combinations(cnames, 2): - if not c1_names.isdisjoint(c2_names): - node.children[c1_prefix].use_name = True - node.children[c2_prefix].use_name = True - r = set() - for c_prefix, c_names in cnames: - if node.children[c_prefix].use_name: - for c_name in c_names: - r.add((c_prefix, ) + c_name) - else: - r |= c_names - - if node.signal_count > sum(c.signal_count for c in node.children.values()): - node.use_name = True - r.add((node_name, )) - - return r + cnames = [(k, _set_use_name(v, k)) for k, v in node.children.items()] + for (c1_prefix, c1_names), (c2_prefix, c2_names) in combinations(cnames, 2): + if not c1_names.isdisjoint(c2_names): + node.children[c1_prefix].use_name = True + node.children[c2_prefix].use_name = True + r = set() + for c_prefix, c_names in cnames: + if node.children[c_prefix].use_name: + for c_name in c_names: + r.add((c_prefix, ) + c_name) + else: + r |= c_names + + if node.signal_count > sum(c.signal_count for c in node.children.values()): + node.use_name = True + r.add((node_name, )) + + return r def _name_signal(tree, signal): - elements = [] - treepos = tree - for step_name, step_n in signal.backtrace: - try: - treepos = treepos.children[(step_name, step_n)] - use_number = True - except KeyError: - treepos = treepos.children[step_name] - use_number = False - if treepos.use_name: - elname = step_name - if use_number: - elname += str(treepos.all_numbers.index(step_n)) - elements.append(elname) - return "_".join(elements) + elements = [] + treepos = tree + for step_name, step_n in signal.backtrace: + try: + treepos = treepos.children[(step_name, step_n)] + use_number = True + except KeyError: + treepos = treepos.children[step_name] + use_number = False + if treepos.use_name: + elname = step_name + if use_number: + elname += str(treepos.all_numbers.index(step_n)) + elements.append(elname) + return "_".join(elements) def _build_pnd_from_tree(tree, signals): - return dict((signal, _name_signal(tree, signal)) for signal in signals) + return dict((signal, _name_signal(tree, signal)) for signal in signals) def _invert_pnd(pnd): - inv_pnd = dict() - for k, v in pnd.items(): - inv_pnd[v] = inv_pnd.get(v, []) - inv_pnd[v].append(k) - return inv_pnd + inv_pnd = dict() + for k, v in pnd.items(): + inv_pnd[v] = inv_pnd.get(v, []) + inv_pnd[v].append(k) + return inv_pnd def _list_conflicting_signals(pnd): - inv_pnd = _invert_pnd(pnd) - r = set() - for k, v in inv_pnd.items(): - if len(v) > 1: - r.update(v) - return r + inv_pnd = _invert_pnd(pnd) + r = set() + for k, v in inv_pnd.items(): + if len(v) > 1: + r.update(v) + return r def _set_use_number(tree, signals): - for signal in signals: - current = tree - for step_name, step_n in signal.backtrace: - current = current.children[step_name] - current.use_number = current.signal_count > len(current.numbers) and len(current.numbers) > 1 + for signal in signals: + current = tree + for step_name, step_n in signal.backtrace: + current = current.children[step_name] + current.use_number = current.signal_count > len(current.numbers) and len(current.numbers) > 1 _debug = False def _build_pnd_for_group(group_n, signals): - basic_tree = _build_tree(signals) - _set_use_name(basic_tree) - if _debug: - _display_tree("tree{0}_basic.svg".format(group_n), basic_tree) - pnd = _build_pnd_from_tree(basic_tree, signals) - - # If there are conflicts, try splitting the tree by numbers - # on paths taken by conflicting signals. - conflicting_signals = _list_conflicting_signals(pnd) - if conflicting_signals: - _set_use_number(basic_tree, conflicting_signals) - if _debug: - print("namer: using split-by-number strategy (group {0})".format(group_n)) - _display_tree("tree{0}_marked.svg".format(group_n), basic_tree) - numbered_tree = _build_tree(signals, basic_tree) - _set_use_name(numbered_tree) - if _debug: - _display_tree("tree{0}_numbered.svg".format(group_n), numbered_tree) - pnd = _build_pnd_from_tree(numbered_tree, signals) - else: - if _debug: - print("namer: using basic strategy (group {0})".format(group_n)) - - # ...then add number suffixes by HUID - inv_pnd = _invert_pnd(pnd) - huid_suffixed = False - for name, signals in inv_pnd.items(): - if len(signals) > 1: - huid_suffixed = True - for n, signal in enumerate(sorted(signals, key=lambda x: x.huid)): - pnd[signal] += str(n) - if _debug and huid_suffixed: - print("namer: using HUID suffixes (group {0})".format(group_n)) - - return pnd + basic_tree = _build_tree(signals) + _set_use_name(basic_tree) + if _debug: + _display_tree("tree{0}_basic.svg".format(group_n), basic_tree) + pnd = _build_pnd_from_tree(basic_tree, signals) + + # If there are conflicts, try splitting the tree by numbers + # on paths taken by conflicting signals. + conflicting_signals = _list_conflicting_signals(pnd) + if conflicting_signals: + _set_use_number(basic_tree, conflicting_signals) + if _debug: + print("namer: using split-by-number strategy (group {0})".format(group_n)) + _display_tree("tree{0}_marked.svg".format(group_n), basic_tree) + numbered_tree = _build_tree(signals, basic_tree) + _set_use_name(numbered_tree) + if _debug: + _display_tree("tree{0}_numbered.svg".format(group_n), numbered_tree) + pnd = _build_pnd_from_tree(numbered_tree, signals) + else: + if _debug: + print("namer: using basic strategy (group {0})".format(group_n)) + + # ...then add number suffixes by HUID + inv_pnd = _invert_pnd(pnd) + huid_suffixed = False + for name, signals in inv_pnd.items(): + if len(signals) > 1: + huid_suffixed = True + for n, signal in enumerate(sorted(signals, key=lambda x: x.huid)): + pnd[signal] += str(n) + if _debug and huid_suffixed: + print("namer: using HUID suffixes (group {0})".format(group_n)) + + return pnd def _build_signal_groups(signals): - r = [] - for signal in signals: - # build chain of related signals - related_list = [] - cur_signal = signal - while cur_signal is not None: - related_list.insert(0, cur_signal) - cur_signal = cur_signal.related - # add to groups - r += [set()]*(len(related_list) - len(r)) - for target_set, source_set in zip(r, related_list): - target_set.add(source_set) - # with the algorithm above and a list of all signals, - # a signal appears in all groups of a lower number than its. - # make signals appear only in their group of highest number. - for s1, s2 in zip(r, r[1:]): - s1 -= s2 - return r + r = [] + for signal in signals: + # build chain of related signals + related_list = [] + cur_signal = signal + while cur_signal is not None: + related_list.insert(0, cur_signal) + cur_signal = cur_signal.related + # add to groups + r += [set()]*(len(related_list) - len(r)) + for target_set, source_set in zip(r, related_list): + target_set.add(source_set) + # with the algorithm above and a list of all signals, + # a signal appears in all groups of a lower number than its. + # make signals appear only in their group of highest number. + for s1, s2 in zip(r, r[1:]): + s1 -= s2 + return r def _build_pnd(signals): - groups = _build_signal_groups(signals) - gpnds = [_build_pnd_for_group(n, gsignals) for n, gsignals in enumerate(groups)] - - pnd = dict() - for gn, gpnd in enumerate(gpnds): - for signal, name in gpnd.items(): - result = name - cur_gn = gn - cur_signal = signal - while cur_signal.related is not None: - cur_signal = cur_signal.related - cur_gn -= 1 - result = gpnds[cur_gn][cur_signal] + "_" + result - pnd[signal] = result - - return pnd + groups = _build_signal_groups(signals) + gpnds = [_build_pnd_for_group(n, gsignals) for n, gsignals in enumerate(groups)] + + pnd = dict() + for gn, gpnd in enumerate(gpnds): + for signal, name in gpnd.items(): + result = name + cur_gn = gn + cur_signal = signal + while cur_signal.related is not None: + cur_signal = cur_signal.related + cur_gn -= 1 + result = gpnds[cur_gn][cur_signal] + "_" + result + pnd[signal] = result + + return pnd def build_namespace(signals): - pnd = _build_pnd(signals) - ns = Namespace(pnd) - # register signals with name_override - for signal in signals: - if signal.name_override is not None: - ns.get_name(signal) - return ns + pnd = _build_pnd(signals) + ns = Namespace(pnd) + # register signals with name_override + for signal in signals: + if signal.name_override is not None: + ns.get_name(signal) + return ns class Namespace: - def __init__(self, pnd): - self.counts = {} - self.sigs = {} - self.pnd = pnd - - def get_name(self, sig): - if sig.name_override is not None: - sig_name = sig.name_override - else: - sig_name = self.pnd[sig] - try: - n = self.sigs[sig] - except KeyError: - try: - n = self.counts[sig_name] - except KeyError: - n = 0 - self.sigs[sig] = n - self.counts[sig_name] = n + 1 - if n: - return sig_name + "_" + str(n) - else: - return sig_name + def __init__(self, pnd): + self.counts = {} + self.sigs = {} + self.pnd = pnd + + def get_name(self, sig): + if sig.name_override is not None: + sig_name = sig.name_override + else: + sig_name = self.pnd[sig] + try: + n = self.sigs[sig] + except KeyError: + try: + n = self.counts[sig_name] + except KeyError: + n = 0 + self.sigs[sig] = n + self.counts[sig_name] = n + 1 + if n: + return sig_name + "_" + str(n) + else: + return sig_name diff --git a/migen/fhdl/simplify.py b/migen/fhdl/simplify.py index 1bc2eeca..3719a178 100644 --- a/migen/fhdl/simplify.py +++ b/migen/fhdl/simplify.py @@ -4,38 +4,38 @@ from migen.fhdl.decorators import ModuleTransformer from migen.util.misc import gcd_multiple class FullMemoryWE(ModuleTransformer): - def transform_fragment(self, i, f): - newspecials = set() + def transform_fragment(self, i, f): + newspecials = set() - for orig in f.specials: - if not isinstance(orig, Memory): - newspecials.add(orig) - continue - global_granularity = gcd_multiple([p.we_granularity if p.we_granularity else orig.width for p in orig.ports]) - if global_granularity == orig.width: - newspecials.add(orig) # nothing to do - else: - for i in range(orig.width//global_granularity): - if orig.init is None: - newinit = None - else: - newinit = [(v >> i*global_granularity) & (2**global_granularity - 1) for v in orig.init] - newmem = Memory(global_granularity, orig.depth, newinit, orig.name_override + "_grain" + str(i)) - newspecials.add(newmem) - for port in orig.ports: - port_granularity = port.we_granularity if port.we_granularity else orig.width - newport = _MemoryPort(adr=port.adr, + for orig in f.specials: + if not isinstance(orig, Memory): + newspecials.add(orig) + continue + global_granularity = gcd_multiple([p.we_granularity if p.we_granularity else orig.width for p in orig.ports]) + if global_granularity == orig.width: + newspecials.add(orig) # nothing to do + else: + for i in range(orig.width//global_granularity): + if orig.init is None: + newinit = None + else: + newinit = [(v >> i*global_granularity) & (2**global_granularity - 1) for v in orig.init] + newmem = Memory(global_granularity, orig.depth, newinit, orig.name_override + "_grain" + str(i)) + newspecials.add(newmem) + for port in orig.ports: + port_granularity = port.we_granularity if port.we_granularity else orig.width + newport = _MemoryPort(adr=port.adr, - dat_r=port.dat_r[i*global_granularity:(i+1)*global_granularity] if port.dat_r is not None else None, - we=port.we[i*global_granularity//port_granularity] if port.we is not None else None, - dat_w=port.dat_w[i*global_granularity:(i+1)*global_granularity] if port.dat_w is not None else None, + dat_r=port.dat_r[i*global_granularity:(i+1)*global_granularity] if port.dat_r is not None else None, + we=port.we[i*global_granularity//port_granularity] if port.we is not None else None, + dat_w=port.dat_w[i*global_granularity:(i+1)*global_granularity] if port.dat_w is not None else None, - async_read=port.async_read, - re=port.re, - we_granularity=0, - mode=port.mode, - clock_domain=port.clock) - newmem.ports.append(newport) - newspecials.add(newport) + async_read=port.async_read, + re=port.re, + we_granularity=0, + mode=port.mode, + clock_domain=port.clock) + newmem.ports.append(newport) + newspecials.add(newport) - f.specials = newspecials + f.specials = newspecials diff --git a/migen/fhdl/specials.py b/migen/fhdl/specials.py index 764fa791..8554067a 100644 --- a/migen/fhdl/specials.py +++ b/migen/fhdl/specials.py @@ -7,326 +7,326 @@ from migen.fhdl.tracer import get_obj_var_name from migen.fhdl.verilog import _printexpr as verilog_printexpr class Special(HUID): - def iter_expressions(self): - for x in []: - yield x - - def rename_clock_domain(self, old, new): - for obj, attr, direction in self.iter_expressions(): - rename_clock_domain_expr(getattr(obj, attr), old, new) - - def list_clock_domains(self): - r = set() - for obj, attr, direction in self.iter_expressions(): - r |= list_clock_domains_expr(getattr(obj, attr)) - return r - - def list_ios(self, ins, outs, inouts): - r = set() - for obj, attr, direction in self.iter_expressions(): - if (direction == SPECIAL_INPUT and ins) \ - or (direction == SPECIAL_OUTPUT and outs) \ - or (direction == SPECIAL_INOUT and inouts): - signals = list_signals(getattr(obj, attr)) - r.update(signals) - return r + def iter_expressions(self): + for x in []: + yield x + + def rename_clock_domain(self, old, new): + for obj, attr, direction in self.iter_expressions(): + rename_clock_domain_expr(getattr(obj, attr), old, new) + + def list_clock_domains(self): + r = set() + for obj, attr, direction in self.iter_expressions(): + r |= list_clock_domains_expr(getattr(obj, attr)) + return r + + def list_ios(self, ins, outs, inouts): + r = set() + for obj, attr, direction in self.iter_expressions(): + if (direction == SPECIAL_INPUT and ins) \ + or (direction == SPECIAL_OUTPUT and outs) \ + or (direction == SPECIAL_INOUT and inouts): + signals = list_signals(getattr(obj, attr)) + r.update(signals) + return r class Tristate(Special): - def __init__(self, target, o, oe, i=None): - Special.__init__(self) - self.target = target - self.o = o - self.oe = oe - self.i = i - - def iter_expressions(self): - for attr, target_context in [ - ("target", SPECIAL_INOUT), - ("o", SPECIAL_INPUT), - ("oe", SPECIAL_INPUT), - ("i", SPECIAL_OUTPUT)]: - yield self, attr, target_context - - @staticmethod - def emit_verilog(tristate, ns, add_data_file): - def pe(e): - return verilog_printexpr(ns, e)[0] - w, s = value_bits_sign(tristate.target) - r = "assign " + pe(tristate.target) + " = " \ - + pe(tristate.oe) + " ? " + pe(tristate.o) \ - + " : " + str(w) + "'bz;\n" - if tristate.i is not None: - r += "assign " + pe(tristate.i) + " = " + pe(tristate.target) + ";\n" - r += "\n" - return r + def __init__(self, target, o, oe, i=None): + Special.__init__(self) + self.target = target + self.o = o + self.oe = oe + self.i = i + + def iter_expressions(self): + for attr, target_context in [ + ("target", SPECIAL_INOUT), + ("o", SPECIAL_INPUT), + ("oe", SPECIAL_INPUT), + ("i", SPECIAL_OUTPUT)]: + yield self, attr, target_context + + @staticmethod + def emit_verilog(tristate, ns, add_data_file): + def pe(e): + return verilog_printexpr(ns, e)[0] + w, s = value_bits_sign(tristate.target) + r = "assign " + pe(tristate.target) + " = " \ + + pe(tristate.oe) + " ? " + pe(tristate.o) \ + + " : " + str(w) + "'bz;\n" + if tristate.i is not None: + r += "assign " + pe(tristate.i) + " = " + pe(tristate.target) + ";\n" + r += "\n" + return r class TSTriple: - def __init__(self, bits_sign=None, min=None, max=None, reset_o=0, reset_oe=0): - self.o = Signal(bits_sign, min=min, max=max, reset=reset_o) - self.oe = Signal(reset=reset_oe) - self.i = Signal(bits_sign, min=min, max=max) + def __init__(self, bits_sign=None, min=None, max=None, reset_o=0, reset_oe=0): + self.o = Signal(bits_sign, min=min, max=max, reset=reset_o) + self.oe = Signal(reset=reset_oe) + self.i = Signal(bits_sign, min=min, max=max) - def get_tristate(self, target): - return Tristate(target, self.o, self.oe, self.i) + def get_tristate(self, target): + return Tristate(target, self.o, self.oe, self.i) class Instance(Special): - class _IO: - def __init__(self, name, expr=None): - self.name = name - if expr is None: - expr = Signal() - self.expr = expr - class Input(_IO): - pass - class Output(_IO): - pass - class InOut(_IO): - pass - class Parameter: - def __init__(self, name, value): - self.name = name - self.value = value - class PreformattedParam(str): - pass - - def __init__(self, of, *items, name="", synthesis_directive=None, **kwargs): - Special.__init__(self) - self.of = of - if name: - self.name_override = name - else: - self.name_override = of - self.items = list(items) - self.synthesis_directive = synthesis_directive - for k, v in sorted(kwargs.items(), key=itemgetter(0)): - item_type, item_name = k.split("_", maxsplit=1) - item_class = { - "i": Instance.Input, - "o": Instance.Output, - "io": Instance.InOut, - "p": Instance.Parameter - }[item_type] - self.items.append(item_class(item_name, v)) - - def get_io(self, name): - for item in self.items: - if isinstance(item, Instance._IO) and item.name == name: - return item.expr - - def iter_expressions(self): - for item in self.items: - if isinstance(item, Instance.Input): - yield item, "expr", SPECIAL_INPUT - elif isinstance(item, Instance.Output): - yield item, "expr", SPECIAL_OUTPUT - elif isinstance(item, Instance.InOut): - yield item, "expr", SPECIAL_INOUT - - @staticmethod - def emit_verilog(instance, ns, add_data_file): - r = instance.of + " " - parameters = list(filter(lambda i: isinstance(i, Instance.Parameter), instance.items)) - if parameters: - r += "#(\n" - firstp = True - for p in parameters: - if not firstp: - r += ",\n" - firstp = False - r += "\t." + p.name + "(" - if isinstance(p.value, (int, bool)): - r += verilog_printexpr(ns, p.value)[0] - elif isinstance(p.value, float): - r += str(p.value) - elif isinstance(p.value, Instance.PreformattedParam): - r += p.value - elif isinstance(p.value, str): - r += "\"" + p.value + "\"" - else: - raise TypeError - r += ")" - r += "\n) " - r += ns.get_name(instance) - if parameters: r += " " - r += "(\n" - firstp = True - for p in instance.items: - if isinstance(p, Instance._IO): - name_inst = p.name - name_design = verilog_printexpr(ns, p.expr)[0] - if not firstp: - r += ",\n" - firstp = False - r += "\t." + name_inst + "(" + name_design + ")" - if not firstp: - r += "\n" - if instance.synthesis_directive is not None: - synthesis_directive = "/* synthesis {} */".format(instance.synthesis_directive) - r += ")" + synthesis_directive + ";\n\n" - else: - r += ");\n\n" - return r + class _IO: + def __init__(self, name, expr=None): + self.name = name + if expr is None: + expr = Signal() + self.expr = expr + class Input(_IO): + pass + class Output(_IO): + pass + class InOut(_IO): + pass + class Parameter: + def __init__(self, name, value): + self.name = name + self.value = value + class PreformattedParam(str): + pass + + def __init__(self, of, *items, name="", synthesis_directive=None, **kwargs): + Special.__init__(self) + self.of = of + if name: + self.name_override = name + else: + self.name_override = of + self.items = list(items) + self.synthesis_directive = synthesis_directive + for k, v in sorted(kwargs.items(), key=itemgetter(0)): + item_type, item_name = k.split("_", maxsplit=1) + item_class = { + "i": Instance.Input, + "o": Instance.Output, + "io": Instance.InOut, + "p": Instance.Parameter + }[item_type] + self.items.append(item_class(item_name, v)) + + def get_io(self, name): + for item in self.items: + if isinstance(item, Instance._IO) and item.name == name: + return item.expr + + def iter_expressions(self): + for item in self.items: + if isinstance(item, Instance.Input): + yield item, "expr", SPECIAL_INPUT + elif isinstance(item, Instance.Output): + yield item, "expr", SPECIAL_OUTPUT + elif isinstance(item, Instance.InOut): + yield item, "expr", SPECIAL_INOUT + + @staticmethod + def emit_verilog(instance, ns, add_data_file): + r = instance.of + " " + parameters = list(filter(lambda i: isinstance(i, Instance.Parameter), instance.items)) + if parameters: + r += "#(\n" + firstp = True + for p in parameters: + if not firstp: + r += ",\n" + firstp = False + r += "\t." + p.name + "(" + if isinstance(p.value, (int, bool)): + r += verilog_printexpr(ns, p.value)[0] + elif isinstance(p.value, float): + r += str(p.value) + elif isinstance(p.value, Instance.PreformattedParam): + r += p.value + elif isinstance(p.value, str): + r += "\"" + p.value + "\"" + else: + raise TypeError + r += ")" + r += "\n) " + r += ns.get_name(instance) + if parameters: r += " " + r += "(\n" + firstp = True + for p in instance.items: + if isinstance(p, Instance._IO): + name_inst = p.name + name_design = verilog_printexpr(ns, p.expr)[0] + if not firstp: + r += ",\n" + firstp = False + r += "\t." + name_inst + "(" + name_design + ")" + if not firstp: + r += "\n" + if instance.synthesis_directive is not None: + synthesis_directive = "/* synthesis {} */".format(instance.synthesis_directive) + r += ")" + synthesis_directive + ";\n\n" + else: + r += ");\n\n" + return r (READ_FIRST, WRITE_FIRST, NO_CHANGE) = range(3) class _MemoryPort(Special): - def __init__(self, adr, dat_r, we=None, dat_w=None, - async_read=False, re=None, we_granularity=0, mode=WRITE_FIRST, - clock_domain="sys"): - Special.__init__(self) - self.adr = adr - self.dat_r = dat_r - self.we = we - self.dat_w = dat_w - self.async_read = async_read - self.re = re - self.we_granularity = we_granularity - self.mode = mode - if isinstance(clock_domain, str): - self.clock = ClockSignal(clock_domain) - else: - self.clock = clock_domain - - def iter_expressions(self): - for attr, target_context in [ - ("adr", SPECIAL_INPUT), - ("we", SPECIAL_INPUT), - ("dat_w", SPECIAL_INPUT), - ("re", SPECIAL_INPUT), - ("dat_r", SPECIAL_OUTPUT), - ("clock", SPECIAL_INPUT)]: - yield self, attr, target_context - - @staticmethod - def emit_verilog(port, ns, add_data_file): - return "" # done by parent Memory object + def __init__(self, adr, dat_r, we=None, dat_w=None, + async_read=False, re=None, we_granularity=0, mode=WRITE_FIRST, + clock_domain="sys"): + Special.__init__(self) + self.adr = adr + self.dat_r = dat_r + self.we = we + self.dat_w = dat_w + self.async_read = async_read + self.re = re + self.we_granularity = we_granularity + self.mode = mode + if isinstance(clock_domain, str): + self.clock = ClockSignal(clock_domain) + else: + self.clock = clock_domain + + def iter_expressions(self): + for attr, target_context in [ + ("adr", SPECIAL_INPUT), + ("we", SPECIAL_INPUT), + ("dat_w", SPECIAL_INPUT), + ("re", SPECIAL_INPUT), + ("dat_r", SPECIAL_OUTPUT), + ("clock", SPECIAL_INPUT)]: + yield self, attr, target_context + + @staticmethod + def emit_verilog(port, ns, add_data_file): + return "" # done by parent Memory object class Memory(Special): - def __init__(self, width, depth, init=None, name=None): - Special.__init__(self) - self.width = width - self.depth = depth - self.ports = [] - self.init = init - self.name_override = get_obj_var_name(name, "mem") - - def get_port(self, write_capable=False, async_read=False, - has_re=False, we_granularity=0, mode=WRITE_FIRST, - clock_domain="sys"): - if we_granularity >= self.width: - we_granularity = 0 - adr = Signal(max=self.depth) - dat_r = Signal(self.width) - if write_capable: - if we_granularity: - we = Signal(self.width//we_granularity) - else: - we = Signal() - dat_w = Signal(self.width) - else: - we = None - dat_w = None - if has_re: - re = Signal() - else: - re = None - mp = _MemoryPort(adr, dat_r, we, dat_w, - async_read, re, we_granularity, mode, - clock_domain) - self.ports.append(mp) - return mp - - @staticmethod - def emit_verilog(memory, ns, add_data_file): - r = "" - def gn(e): - if isinstance(e, Memory): - return ns.get_name(e) - else: - return verilog_printexpr(ns, e)[0] - adrbits = bits_for(memory.depth-1) - - r += "reg [" + str(memory.width-1) + ":0] " \ - + gn(memory) \ - + "[0:" + str(memory.depth-1) + "];\n" - - adr_regs = {} - data_regs = {} - for port in memory.ports: - if not port.async_read: - if port.mode == WRITE_FIRST and port.we is not None: - adr_reg = Signal(name_override="memadr") - r += "reg [" + str(adrbits-1) + ":0] " \ - + gn(adr_reg) + ";\n" - adr_regs[id(port)] = adr_reg - else: - data_reg = Signal(name_override="memdat") - r += "reg [" + str(memory.width-1) + ":0] " \ - + gn(data_reg) + ";\n" - data_regs[id(port)] = data_reg - - for port in memory.ports: - r += "always @(posedge " + gn(port.clock) + ") begin\n" - if port.we is not None: - if port.we_granularity: - n = memory.width//port.we_granularity - for i in range(n): - m = i*port.we_granularity - M = (i+1)*port.we_granularity-1 - sl = "[" + str(M) + ":" + str(m) + "]" - r += "\tif (" + gn(port.we) + "[" + str(i) + "])\n" - r += "\t\t" + gn(memory) + "[" + gn(port.adr) + "]" + sl + " <= " + gn(port.dat_w) + sl + ";\n" - else: - r += "\tif (" + gn(port.we) + ")\n" - r += "\t\t" + gn(memory) + "[" + gn(port.adr) + "] <= " + gn(port.dat_w) + ";\n" - if not port.async_read: - if port.mode == WRITE_FIRST and port.we is not None: - rd = "\t" + gn(adr_regs[id(port)]) + " <= " + gn(port.adr) + ";\n" - else: - bassign = gn(data_regs[id(port)]) + " <= " + gn(memory) + "[" + gn(port.adr) + "];\n" - if port.mode == READ_FIRST or port.we is None: - rd = "\t" + bassign - elif port.mode == NO_CHANGE: - rd = "\tif (!" + gn(port.we) + ")\n" \ - + "\t\t" + bassign - if port.re is None: - r += rd - else: - r += "\tif (" + gn(port.re) + ")\n" - r += "\t" + rd.replace("\n\t", "\n\t\t") - r += "end\n\n" - - for port in memory.ports: - if port.async_read: - r += "assign " + gn(port.dat_r) + " = " + gn(memory) + "[" + gn(port.adr) + "];\n" - else: - if port.mode == WRITE_FIRST and port.we is not None: - r += "assign " + gn(port.dat_r) + " = " + gn(memory) + "[" + gn(adr_regs[id(port)]) + "];\n" - else: - r += "assign " + gn(port.dat_r) + " = " + gn(data_regs[id(port)]) + ";\n" - r += "\n" - - if memory.init is not None: - content = "" - for d in memory.init: - content += "{:x}\n".format(d) - memory_filename = add_data_file(gn(memory) + ".init", content) - - r += "initial begin\n" - r += "$readmemh(\"" + memory_filename + "\", " + gn(memory) + ");\n" - r += "end\n\n" - - - return r + def __init__(self, width, depth, init=None, name=None): + Special.__init__(self) + self.width = width + self.depth = depth + self.ports = [] + self.init = init + self.name_override = get_obj_var_name(name, "mem") + + def get_port(self, write_capable=False, async_read=False, + has_re=False, we_granularity=0, mode=WRITE_FIRST, + clock_domain="sys"): + if we_granularity >= self.width: + we_granularity = 0 + adr = Signal(max=self.depth) + dat_r = Signal(self.width) + if write_capable: + if we_granularity: + we = Signal(self.width//we_granularity) + else: + we = Signal() + dat_w = Signal(self.width) + else: + we = None + dat_w = None + if has_re: + re = Signal() + else: + re = None + mp = _MemoryPort(adr, dat_r, we, dat_w, + async_read, re, we_granularity, mode, + clock_domain) + self.ports.append(mp) + return mp + + @staticmethod + def emit_verilog(memory, ns, add_data_file): + r = "" + def gn(e): + if isinstance(e, Memory): + return ns.get_name(e) + else: + return verilog_printexpr(ns, e)[0] + adrbits = bits_for(memory.depth-1) + + r += "reg [" + str(memory.width-1) + ":0] " \ + + gn(memory) \ + + "[0:" + str(memory.depth-1) + "];\n" + + adr_regs = {} + data_regs = {} + for port in memory.ports: + if not port.async_read: + if port.mode == WRITE_FIRST and port.we is not None: + adr_reg = Signal(name_override="memadr") + r += "reg [" + str(adrbits-1) + ":0] " \ + + gn(adr_reg) + ";\n" + adr_regs[id(port)] = adr_reg + else: + data_reg = Signal(name_override="memdat") + r += "reg [" + str(memory.width-1) + ":0] " \ + + gn(data_reg) + ";\n" + data_regs[id(port)] = data_reg + + for port in memory.ports: + r += "always @(posedge " + gn(port.clock) + ") begin\n" + if port.we is not None: + if port.we_granularity: + n = memory.width//port.we_granularity + for i in range(n): + m = i*port.we_granularity + M = (i+1)*port.we_granularity-1 + sl = "[" + str(M) + ":" + str(m) + "]" + r += "\tif (" + gn(port.we) + "[" + str(i) + "])\n" + r += "\t\t" + gn(memory) + "[" + gn(port.adr) + "]" + sl + " <= " + gn(port.dat_w) + sl + ";\n" + else: + r += "\tif (" + gn(port.we) + ")\n" + r += "\t\t" + gn(memory) + "[" + gn(port.adr) + "] <= " + gn(port.dat_w) + ";\n" + if not port.async_read: + if port.mode == WRITE_FIRST and port.we is not None: + rd = "\t" + gn(adr_regs[id(port)]) + " <= " + gn(port.adr) + ";\n" + else: + bassign = gn(data_regs[id(port)]) + " <= " + gn(memory) + "[" + gn(port.adr) + "];\n" + if port.mode == READ_FIRST or port.we is None: + rd = "\t" + bassign + elif port.mode == NO_CHANGE: + rd = "\tif (!" + gn(port.we) + ")\n" \ + + "\t\t" + bassign + if port.re is None: + r += rd + else: + r += "\tif (" + gn(port.re) + ")\n" + r += "\t" + rd.replace("\n\t", "\n\t\t") + r += "end\n\n" + + for port in memory.ports: + if port.async_read: + r += "assign " + gn(port.dat_r) + " = " + gn(memory) + "[" + gn(port.adr) + "];\n" + else: + if port.mode == WRITE_FIRST and port.we is not None: + r += "assign " + gn(port.dat_r) + " = " + gn(memory) + "[" + gn(adr_regs[id(port)]) + "];\n" + else: + r += "assign " + gn(port.dat_r) + " = " + gn(data_regs[id(port)]) + ";\n" + r += "\n" + + if memory.init is not None: + content = "" + for d in memory.init: + content += "{:x}\n".format(d) + memory_filename = add_data_file(gn(memory) + ".init", content) + + r += "initial begin\n" + r += "$readmemh(\"" + memory_filename + "\", " + gn(memory) + ");\n" + r += "end\n\n" + + + return r class SynthesisDirective(Special): - def __init__(self, template, **signals): - Special.__init__(self) - self.template = template - self.signals = signals - - @staticmethod - def emit_verilog(directive, ns, add_data_file): - name_dict = dict((k, ns.get_name(sig)) for k, sig in directive.signals.items()) - formatted = directive.template.format(**name_dict) - return "// synthesis " + formatted + "\n" + def __init__(self, template, **signals): + Special.__init__(self) + self.template = template + self.signals = signals + + @staticmethod + def emit_verilog(directive, ns, add_data_file): + name_dict = dict((k, ns.get_name(sig)) for k, sig in directive.signals.items()) + formatted = directive.template.format(**name_dict) + return "// synthesis " + formatted + "\n" diff --git a/migen/fhdl/std.py b/migen/fhdl/std.py index a9ac658d..76b1b378 100644 --- a/migen/fhdl/std.py +++ b/migen/fhdl/std.py @@ -4,4 +4,4 @@ from migen.fhdl.specials import TSTriple, Instance, Memory from migen.fhdl.bitcontainer import log2_int, bits_for, flen, fiter, fslice, freversed from migen.fhdl.decorators import DecorateModule, InsertCE, InsertReset, RenameClockDomains from migen.fhdl.decorators import (CEInserter, ResetInserter, - ClockDomainsRenamer, ModuleTransformer) + ClockDomainsRenamer, ModuleTransformer) diff --git a/migen/fhdl/structure.py b/migen/fhdl/structure.py index 071ae23c..868a743f 100644 --- a/migen/fhdl/structure.py +++ b/migen/fhdl/structure.py @@ -5,587 +5,587 @@ from migen.fhdl import tracer from migen.util.misc import flat_iteration class HUID: - __next_uid = 0 - def __init__(self): - self.huid = HUID.__next_uid - HUID.__next_uid += 1 + __next_uid = 0 + def __init__(self): + self.huid = HUID.__next_uid + HUID.__next_uid += 1 - def __hash__(self): - return self.huid + def __hash__(self): + return self.huid class Value(HUID): - """Base class for operands - - Instances of `Value` or its subclasses can be operands to - arithmetic, comparison, bitwise, and logic operators. - They can be assigned (:meth:`eq`) or indexed/sliced (using the usual - Python indexing and slicing notation). - - Values created from integers have the minimum bit width to necessary to - represent the integer. - """ - def __bool__(self): - raise NotImplementedError("For boolean operations between expressions: use '&'/'|' instead of 'and'/'or'") - - def __invert__(self): - return _Operator("~", [self]) - def __neg__(self): - return _Operator("-", [self]) - - def __add__(self, other): - return _Operator("+", [self, other]) - def __radd__(self, other): - return _Operator("+", [other, self]) - def __sub__(self, other): - return _Operator("-", [self, other]) - def __rsub__(self, other): - return _Operator("-", [other, self]) - def __mul__(self, other): - return _Operator("*", [self, other]) - def __rmul__(self, other): - return _Operator("*", [other, self]) - def __lshift__(self, other): - return _Operator("<<<", [self, other]) - def __rlshift__(self, other): - return _Operator("<<<", [other, self]) - def __rshift__(self, other): - return _Operator(">>>", [self, other]) - def __rrshift__(self, other): - return _Operator(">>>", [other, self]) - def __and__(self, other): - return _Operator("&", [self, other]) - def __rand__(self, other): - return _Operator("&", [other, self]) - def __xor__(self, other): - return _Operator("^", [self, other]) - def __rxor__(self, other): - return _Operator("^", [other, self]) - def __or__(self, other): - return _Operator("|", [self, other]) - def __ror__(self, other): - return _Operator("|", [other, self]) - - def __lt__(self, other): - return _Operator("<", [self, other]) - def __le__(self, other): - return _Operator("<=", [self, other]) - def __eq__(self, other): - return _Operator("==", [self, other]) - def __ne__(self, other): - return _Operator("!=", [self, other]) - def __gt__(self, other): - return _Operator(">", [self, other]) - def __ge__(self, other): - return _Operator(">=", [self, other]) - - - def __getitem__(self, key): - from migen.fhdl.bitcontainer import flen - - n = flen(self) - if isinstance(key, int): - if key >= n: - raise IndexError - if key < 0: - key += n - return _Slice(self, key, key+1) - elif isinstance(key, slice): - start, stop, step = key.indices(n) - if step != 1: - return Cat(self[i] for i in range(start, stop, step)) - return _Slice(self, start, stop) - else: - raise TypeError - - def eq(self, r): - """Assignment - - Parameters - ---------- - r : Value, in - Value to be assigned. - - Returns - ------- - _Assign - Assignment statement that can be used in combinatorial or - synchronous context. - """ - return _Assign(self, r) - - def __hash__(self): - return HUID.__hash__(self) + """Base class for operands + + Instances of `Value` or its subclasses can be operands to + arithmetic, comparison, bitwise, and logic operators. + They can be assigned (:meth:`eq`) or indexed/sliced (using the usual + Python indexing and slicing notation). + + Values created from integers have the minimum bit width to necessary to + represent the integer. + """ + def __bool__(self): + raise NotImplementedError("For boolean operations between expressions: use '&'/'|' instead of 'and'/'or'") + + def __invert__(self): + return _Operator("~", [self]) + def __neg__(self): + return _Operator("-", [self]) + + def __add__(self, other): + return _Operator("+", [self, other]) + def __radd__(self, other): + return _Operator("+", [other, self]) + def __sub__(self, other): + return _Operator("-", [self, other]) + def __rsub__(self, other): + return _Operator("-", [other, self]) + def __mul__(self, other): + return _Operator("*", [self, other]) + def __rmul__(self, other): + return _Operator("*", [other, self]) + def __lshift__(self, other): + return _Operator("<<<", [self, other]) + def __rlshift__(self, other): + return _Operator("<<<", [other, self]) + def __rshift__(self, other): + return _Operator(">>>", [self, other]) + def __rrshift__(self, other): + return _Operator(">>>", [other, self]) + def __and__(self, other): + return _Operator("&", [self, other]) + def __rand__(self, other): + return _Operator("&", [other, self]) + def __xor__(self, other): + return _Operator("^", [self, other]) + def __rxor__(self, other): + return _Operator("^", [other, self]) + def __or__(self, other): + return _Operator("|", [self, other]) + def __ror__(self, other): + return _Operator("|", [other, self]) + + def __lt__(self, other): + return _Operator("<", [self, other]) + def __le__(self, other): + return _Operator("<=", [self, other]) + def __eq__(self, other): + return _Operator("==", [self, other]) + def __ne__(self, other): + return _Operator("!=", [self, other]) + def __gt__(self, other): + return _Operator(">", [self, other]) + def __ge__(self, other): + return _Operator(">=", [self, other]) + + + def __getitem__(self, key): + from migen.fhdl.bitcontainer import flen + + n = flen(self) + if isinstance(key, int): + if key >= n: + raise IndexError + if key < 0: + key += n + return _Slice(self, key, key+1) + elif isinstance(key, slice): + start, stop, step = key.indices(n) + if step != 1: + return Cat(self[i] for i in range(start, stop, step)) + return _Slice(self, start, stop) + else: + raise TypeError + + def eq(self, r): + """Assignment + + Parameters + ---------- + r : Value, in + Value to be assigned. + + Returns + ------- + _Assign + Assignment statement that can be used in combinatorial or + synchronous context. + """ + return _Assign(self, r) + + def __hash__(self): + return HUID.__hash__(self) class _Operator(Value): - def __init__(self, op, operands): - Value.__init__(self) - self.op = op - self.operands = operands + def __init__(self, op, operands): + Value.__init__(self) + self.op = op + self.operands = operands def Mux(sel, val1, val0): - """Multiplex between two values - - Parameters - ---------- - sel : Value(1), in - Selector. - val1 : Value(N), in - val0 : Value(N), in - Input values. - - Returns - ------- - Value(N), out - Output `Value`. If `sel` is asserted, the Mux returns - `val1`, else `val0`. - """ - return _Operator("m", [sel, val1, val0]) + """Multiplex between two values + + Parameters + ---------- + sel : Value(1), in + Selector. + val1 : Value(N), in + val0 : Value(N), in + Input values. + + Returns + ------- + Value(N), out + Output `Value`. If `sel` is asserted, the Mux returns + `val1`, else `val0`. + """ + return _Operator("m", [sel, val1, val0]) class _Slice(Value): - def __init__(self, value, start, stop): - Value.__init__(self) - self.value = value - self.start = start - self.stop = stop + def __init__(self, value, start, stop): + Value.__init__(self) + self.value = value + self.start = start + self.stop = stop class Cat(Value): - """Concatenate values - - Form a compound `Value` from several smaller ones by concatenation. - The first argument occupies the lower bits of the result. - The return value can be used on either side of an assignment, that - is, the concatenated value can be used as an argument on the RHS or - as a target on the LHS. If it is used on the LHS, it must solely - consist of `Signal` s, slices of `Signal` s, and other concatenations - meeting these properties. The bit length of the return value is the sum of - the bit lengths of the arguments:: - - flen(Cat(args)) == sum(flen(arg) for arg in args) - - Parameters - ---------- - *args : Values or iterables of Values, inout - `Value` s to be concatenated. - - Returns - ------- - Cat, inout - Resulting `Value` obtained by concatentation. - """ - def __init__(self, *args): - Value.__init__(self) - self.l = list(flat_iteration(args)) + """Concatenate values + + Form a compound `Value` from several smaller ones by concatenation. + The first argument occupies the lower bits of the result. + The return value can be used on either side of an assignment, that + is, the concatenated value can be used as an argument on the RHS or + as a target on the LHS. If it is used on the LHS, it must solely + consist of `Signal` s, slices of `Signal` s, and other concatenations + meeting these properties. The bit length of the return value is the sum of + the bit lengths of the arguments:: + + flen(Cat(args)) == sum(flen(arg) for arg in args) + + Parameters + ---------- + *args : Values or iterables of Values, inout + `Value` s to be concatenated. + + Returns + ------- + Cat, inout + Resulting `Value` obtained by concatentation. + """ + def __init__(self, *args): + Value.__init__(self) + self.l = list(flat_iteration(args)) class Replicate(Value): - """Replicate a value - - An input value is replicated (repeated) several times - to be used on the RHS of assignments:: - - flen(Replicate(s, n)) == flen(s)*n - - Parameters - ---------- - v : Value, in - Input value to be replicated. - n : int - Number of replications. - - Returns - ------- - Replicate, out - Replicated value. - """ - def __init__(self, v, n): - Value.__init__(self) - self.v = v - self.n = n + """Replicate a value + + An input value is replicated (repeated) several times + to be used on the RHS of assignments:: + + flen(Replicate(s, n)) == flen(s)*n + + Parameters + ---------- + v : Value, in + Input value to be replicated. + n : int + Number of replications. + + Returns + ------- + Replicate, out + Replicated value. + """ + def __init__(self, v, n): + Value.__init__(self) + self.v = v + self.n = n class Signal(Value): - """A `Value` that can change - - The `Signal` object represents a value that is expected to change - in the circuit. It does exactly what Verilog's `wire` and - `reg` and VHDL's `signal` do. - - A `Signal` can be indexed to access a subset of its bits. Negative - indices (`signal[-1]`) and the extended Python slicing notation - (`signal[start:stop:step]`) are supported. - The indeces 0 and -1 are the least and most significant bits - respectively. - - Parameters - ---------- - bits_sign : int or tuple - Either an integer `bits` or a tuple `(bits, signed)` - specifying the number of bits in this `Signal` and whether it is - signed (can represent negative values). `signed` defaults to - `False`. - name : str or None - Name hint for this signal. If `None` (default) the name is - inferred from the variable name this `Signal` is assigned to. - Name collisions are automatically resolved by prepending - names of objects that contain this `Signal` and by - appending integer sequences. - variable : bool - Deprecated. - reset : int - Reset (synchronous) or default (combinatorial) value. - When this `Signal` is assigned to in synchronous context and the - corresponding clock domain is reset, the `Signal` assumes the - given value. When this `Signal` is unassigned in combinatorial - context (due to conditional assignments not being taken), - the `Signal` assumes its `reset` value. Defaults to 0. - name_override : str or None - Do not use the inferred name but the given one. - min : int or None - max : int or None - If `bits_sign` is `None`, the signal bit width and signedness are - determined by the integer range given by `min` (inclusive, - defaults to 0) and `max` (exclusive, defaults to 2). - related : Signal or None - """ - def __init__(self, bits_sign=None, name=None, variable=False, reset=0, name_override=None, min=None, max=None, related=None): - from migen.fhdl.bitcontainer import bits_for - - Value.__init__(self) - - # determine number of bits and signedness - if bits_sign is None: - if min is None: - min = 0 - if max is None: - max = 2 - max -= 1 # make both bounds inclusive - assert(min < max) - self.signed = min < 0 or max < 0 - self.nbits = builtins.max(bits_for(min, self.signed), bits_for(max, self.signed)) - else: - assert(min is None and max is None) - if isinstance(bits_sign, tuple): - self.nbits, self.signed = bits_sign - else: - self.nbits, self.signed = bits_sign, False - if not isinstance(self.nbits, int) or self.nbits <= 0: - raise ValueError("Signal width must be a strictly positive integer") - - self.variable = variable # deprecated - self.reset = reset - self.name_override = name_override - self.backtrace = tracer.trace_back(name) - self.related = related - - def __repr__(self): - return "" - - @classmethod - def like(cls, other, **kwargs): - """Create Signal based on another. - - Parameters - ---------- - other : Value - Object to base this Signal on. - - See `migen.fhdl.bitcontainer.value_bits_sign`() for details. - """ - from migen.fhdl.bitcontainer import value_bits_sign - return cls(bits_sign=value_bits_sign(other), **kwargs) + """A `Value` that can change + + The `Signal` object represents a value that is expected to change + in the circuit. It does exactly what Verilog's `wire` and + `reg` and VHDL's `signal` do. + + A `Signal` can be indexed to access a subset of its bits. Negative + indices (`signal[-1]`) and the extended Python slicing notation + (`signal[start:stop:step]`) are supported. + The indeces 0 and -1 are the least and most significant bits + respectively. + + Parameters + ---------- + bits_sign : int or tuple + Either an integer `bits` or a tuple `(bits, signed)` + specifying the number of bits in this `Signal` and whether it is + signed (can represent negative values). `signed` defaults to + `False`. + name : str or None + Name hint for this signal. If `None` (default) the name is + inferred from the variable name this `Signal` is assigned to. + Name collisions are automatically resolved by prepending + names of objects that contain this `Signal` and by + appending integer sequences. + variable : bool + Deprecated. + reset : int + Reset (synchronous) or default (combinatorial) value. + When this `Signal` is assigned to in synchronous context and the + corresponding clock domain is reset, the `Signal` assumes the + given value. When this `Signal` is unassigned in combinatorial + context (due to conditional assignments not being taken), + the `Signal` assumes its `reset` value. Defaults to 0. + name_override : str or None + Do not use the inferred name but the given one. + min : int or None + max : int or None + If `bits_sign` is `None`, the signal bit width and signedness are + determined by the integer range given by `min` (inclusive, + defaults to 0) and `max` (exclusive, defaults to 2). + related : Signal or None + """ + def __init__(self, bits_sign=None, name=None, variable=False, reset=0, name_override=None, min=None, max=None, related=None): + from migen.fhdl.bitcontainer import bits_for + + Value.__init__(self) + + # determine number of bits and signedness + if bits_sign is None: + if min is None: + min = 0 + if max is None: + max = 2 + max -= 1 # make both bounds inclusive + assert(min < max) + self.signed = min < 0 or max < 0 + self.nbits = builtins.max(bits_for(min, self.signed), bits_for(max, self.signed)) + else: + assert(min is None and max is None) + if isinstance(bits_sign, tuple): + self.nbits, self.signed = bits_sign + else: + self.nbits, self.signed = bits_sign, False + if not isinstance(self.nbits, int) or self.nbits <= 0: + raise ValueError("Signal width must be a strictly positive integer") + + self.variable = variable # deprecated + self.reset = reset + self.name_override = name_override + self.backtrace = tracer.trace_back(name) + self.related = related + + def __repr__(self): + return "" + + @classmethod + def like(cls, other, **kwargs): + """Create Signal based on another. + + Parameters + ---------- + other : Value + Object to base this Signal on. + + See `migen.fhdl.bitcontainer.value_bits_sign`() for details. + """ + from migen.fhdl.bitcontainer import value_bits_sign + return cls(bits_sign=value_bits_sign(other), **kwargs) class ClockSignal(Value): - """Clock signal for a given clock domain + """Clock signal for a given clock domain - `ClockSignal` s for a given clock domain can be retrieved multiple - times. They all ultimately refer to the same signal. + `ClockSignal` s for a given clock domain can be retrieved multiple + times. They all ultimately refer to the same signal. - Parameters - ---------- - cd : str - Clock domain to obtain a clock signal for. Defaults to `"sys"`. - """ - def __init__(self, cd="sys"): - Value.__init__(self) - self.cd = cd + Parameters + ---------- + cd : str + Clock domain to obtain a clock signal for. Defaults to `"sys"`. + """ + def __init__(self, cd="sys"): + Value.__init__(self) + self.cd = cd class ResetSignal(Value): - """Reset signal for a given clock domain + """Reset signal for a given clock domain - `ResetSignal` s for a given clock domain can be retrieved multiple - times. They all ultimately refer to the same signal. + `ResetSignal` s for a given clock domain can be retrieved multiple + times. They all ultimately refer to the same signal. - Parameters - ---------- - cd : str - Clock domain to obtain a reset signal for. Defaults to `"sys"`. - """ - def __init__(self, cd="sys"): - Value.__init__(self) - self.cd = cd + Parameters + ---------- + cd : str + Clock domain to obtain a reset signal for. Defaults to `"sys"`. + """ + def __init__(self, cd="sys"): + Value.__init__(self) + self.cd = cd # statements class _Assign: - def __init__(self, l, r): - self.l = l - self.r = r + def __init__(self, l, r): + self.l = l + self.r = r class If: - """Conditional execution of statements - - Parameters - ---------- - cond : Value(1), in - Condition - *t : Statements - Statements to execute if `cond` is asserted. - - Examples - -------- - >>> a = Signal() - >>> b = Signal() - >>> c = Signal() - >>> d = Signal() - >>> If(a, - ... b.eq(1) - ... ).Elif(c, - ... b.eq(0) - ... ).Else( - ... b.eq(d) - ... ) - """ - def __init__(self, cond, *t): - self.cond = cond - self.t = list(t) - self.f = [] - - def Else(self, *f): - """Add an `else` conditional block - - Parameters - ---------- - *f : Statements - Statements to execute if all previous conditions fail. - """ - _insert_else(self, list(f)) - return self - - def Elif(self, cond, *t): - """Add an `else if` conditional block - - Parameters - ---------- - cond : Value(1), in - Condition - *t : Statements - Statements to execute if previous conditions fail and `cond` - is asserted. - """ - _insert_else(self, [If(cond, *t)]) - return self + """Conditional execution of statements + + Parameters + ---------- + cond : Value(1), in + Condition + *t : Statements + Statements to execute if `cond` is asserted. + + Examples + -------- + >>> a = Signal() + >>> b = Signal() + >>> c = Signal() + >>> d = Signal() + >>> If(a, + ... b.eq(1) + ... ).Elif(c, + ... b.eq(0) + ... ).Else( + ... b.eq(d) + ... ) + """ + def __init__(self, cond, *t): + self.cond = cond + self.t = list(t) + self.f = [] + + def Else(self, *f): + """Add an `else` conditional block + + Parameters + ---------- + *f : Statements + Statements to execute if all previous conditions fail. + """ + _insert_else(self, list(f)) + return self + + def Elif(self, cond, *t): + """Add an `else if` conditional block + + Parameters + ---------- + cond : Value(1), in + Condition + *t : Statements + Statements to execute if previous conditions fail and `cond` + is asserted. + """ + _insert_else(self, [If(cond, *t)]) + return self def _insert_else(obj, clause): - o = obj - while o.f: - assert(len(o.f) == 1) - assert(isinstance(o.f[0], If)) - o = o.f[0] - o.f = clause + o = obj + while o.f: + assert(len(o.f) == 1) + assert(isinstance(o.f[0], If)) + o = o.f[0] + o.f = clause class Case: - """Case/Switch statement - - Parameters - ---------- - test : Value, in - Selector value used to decide which block to execute - cases : dict - Dictionary of cases. The keys are numeric constants to compare - with `test`. The values are statements to be executed the - corresponding key matches `test`. The dictionary may contain a - string key `"default"` to mark a fall-through case that is - executed if no other key matches. - - Examples - -------- - >>> a = Signal() - >>> b = Signal() - >>> Case(a, { - ... 0: b.eq(1), - ... 1: b.eq(0), - ... "default": b.eq(0), - ... }) - """ - def __init__(self, test, cases): - self.test = test - self.cases = cases - - def makedefault(self, key=None): - """Mark a key as the default case - - Deletes/Substitutes any previously existing default case. - - Parameters - ---------- - key : int or None - Key to use as default case if no other key matches. - By default, the largest key is the default key. - """ - if key is None: - for choice in self.cases.keys(): - if key is None or choice > key: - key = choice - self.cases["default"] = self.cases[key] - del self.cases[key] - return self + """Case/Switch statement + + Parameters + ---------- + test : Value, in + Selector value used to decide which block to execute + cases : dict + Dictionary of cases. The keys are numeric constants to compare + with `test`. The values are statements to be executed the + corresponding key matches `test`. The dictionary may contain a + string key `"default"` to mark a fall-through case that is + executed if no other key matches. + + Examples + -------- + >>> a = Signal() + >>> b = Signal() + >>> Case(a, { + ... 0: b.eq(1), + ... 1: b.eq(0), + ... "default": b.eq(0), + ... }) + """ + def __init__(self, test, cases): + self.test = test + self.cases = cases + + def makedefault(self, key=None): + """Mark a key as the default case + + Deletes/Substitutes any previously existing default case. + + Parameters + ---------- + key : int or None + Key to use as default case if no other key matches. + By default, the largest key is the default key. + """ + if key is None: + for choice in self.cases.keys(): + if key is None or choice > key: + key = choice + self.cases["default"] = self.cases[key] + del self.cases[key] + return self # arrays class _ArrayProxy(Value): - def __init__(self, choices, key): - self.choices = choices - self.key = key + def __init__(self, choices, key): + self.choices = choices + self.key = key - def __getattr__(self, attr): - return _ArrayProxy([getattr(choice, attr) for choice in self.choices], - self.key) + def __getattr__(self, attr): + return _ArrayProxy([getattr(choice, attr) for choice in self.choices], + self.key) - def __getitem__(self, key): - return _ArrayProxy([choice.__getitem__(key) for choice in self.choices], - self.key) + def __getitem__(self, key): + return _ArrayProxy([choice.__getitem__(key) for choice in self.choices], + self.key) class Array(list): - """Addressable multiplexer - - An array is created from an iterable of values and indexed using the - usual Python simple indexing notation (no negative indices or - slices). It can be indexed by numeric constants, `Value` s, or - `Signal` s. - - The result of indexing the array is a proxy for the entry at the - given index that can be used on either RHS or LHS of assignments. - - An array can be indexed multiple times. - - Multidimensional arrays are supported by packing inner arrays into - outer arrays. - - Parameters - ---------- - values : iterable of ints, Values, Signals - Entries of the array. Each entry can be a numeric constant, a - `Signal` or a `Record`. - - Examples - -------- - >>> a = Array(range(10)) - >>> b = Signal(max=10) - >>> c = Signal(max=10) - >>> b.eq(a[9 - c]) - """ - def __getitem__(self, key): - if isinstance(key, Value): - return _ArrayProxy(self, key) - else: - return list.__getitem__(self, key) + """Addressable multiplexer + + An array is created from an iterable of values and indexed using the + usual Python simple indexing notation (no negative indices or + slices). It can be indexed by numeric constants, `Value` s, or + `Signal` s. + + The result of indexing the array is a proxy for the entry at the + given index that can be used on either RHS or LHS of assignments. + + An array can be indexed multiple times. + + Multidimensional arrays are supported by packing inner arrays into + outer arrays. + + Parameters + ---------- + values : iterable of ints, Values, Signals + Entries of the array. Each entry can be a numeric constant, a + `Signal` or a `Record`. + + Examples + -------- + >>> a = Array(range(10)) + >>> b = Signal(max=10) + >>> c = Signal(max=10) + >>> b.eq(a[9 - c]) + """ + def __getitem__(self, key): + if isinstance(key, Value): + return _ArrayProxy(self, key) + else: + return list.__getitem__(self, key) class ClockDomain: - """Synchronous domain - - Parameters - ---------- - name : str or None - Domain name. If None (the default) the name is inferred from the - variable name this `ClockDomain` is assigned to (stripping any - `"cd_"` prefix). - reset_less : bool - The domain does not use a reset signal. Registers within this - domain are still all initialized to their reset state once, e.g. - through Verilog `"initial"` statements. - - Attributes - ---------- - clk : Signal, inout - The clock for this domain. Can be driven or used to drive other - signals (preferably in combinatorial context). - rst : Signal or None, inout - Reset signal for this domain. Can be driven or used to drive. - """ - def __init__(self, name=None, reset_less=False): - self.name = tracer.get_obj_var_name(name) - if self.name is None: - raise ValueError("Cannot extract clock domain name from code, need to specify.") - if self.name.startswith("cd_"): - self.name = self.name[3:] - if self.name[0].isdigit(): - raise ValueError("Clock domain name cannot start with a number.") - self.clk = Signal(name_override=self.name + "_clk") - if reset_less: - self.rst = None - else: - self.rst = Signal(name_override=self.name + "_rst") - - def rename(self, new_name): - """Rename the clock domain - - Parameters - ---------- - new_name : str - New name - """ - self.name = new_name - self.clk.name_override = new_name + "_clk" - if self.rst is not None: - self.rst.name_override = new_name + "_rst" + """Synchronous domain + + Parameters + ---------- + name : str or None + Domain name. If None (the default) the name is inferred from the + variable name this `ClockDomain` is assigned to (stripping any + `"cd_"` prefix). + reset_less : bool + The domain does not use a reset signal. Registers within this + domain are still all initialized to their reset state once, e.g. + through Verilog `"initial"` statements. + + Attributes + ---------- + clk : Signal, inout + The clock for this domain. Can be driven or used to drive other + signals (preferably in combinatorial context). + rst : Signal or None, inout + Reset signal for this domain. Can be driven or used to drive. + """ + def __init__(self, name=None, reset_less=False): + self.name = tracer.get_obj_var_name(name) + if self.name is None: + raise ValueError("Cannot extract clock domain name from code, need to specify.") + if self.name.startswith("cd_"): + self.name = self.name[3:] + if self.name[0].isdigit(): + raise ValueError("Clock domain name cannot start with a number.") + self.clk = Signal(name_override=self.name + "_clk") + if reset_less: + self.rst = None + else: + self.rst = Signal(name_override=self.name + "_rst") + + def rename(self, new_name): + """Rename the clock domain + + Parameters + ---------- + new_name : str + New name + """ + self.name = new_name + self.clk.name_override = new_name + "_clk" + if self.rst is not None: + self.rst.name_override = new_name + "_rst" class _ClockDomainList(list): - def __getitem__(self, key): - if isinstance(key, str): - for cd in self: - if cd.name == key: - return cd - raise KeyError(key) - else: - return list.__getitem__(self, key) + def __getitem__(self, key): + if isinstance(key, str): + for cd in self: + if cd.name == key: + return cd + raise KeyError(key) + else: + return list.__getitem__(self, key) (SPECIAL_INPUT, SPECIAL_OUTPUT, SPECIAL_INOUT) = range(3) class StopSimulation(Exception): - pass + pass class _Fragment: - def __init__(self, comb=None, sync=None, specials=None, clock_domains=None, sim=None): - if comb is None: comb = [] - if sync is None: sync = dict() - if specials is None: specials = set() - if clock_domains is None: clock_domains = _ClockDomainList() - if sim is None: sim = [] - - self.comb = comb - self.sync = sync - self.specials = specials - self.clock_domains = _ClockDomainList(clock_domains) - self.sim = sim - - def __add__(self, other): - newsync = defaultdict(list) - for k, v in self.sync.items(): - newsync[k] = v[:] - for k, v in other.sync.items(): - newsync[k].extend(v) - return _Fragment(self.comb + other.comb, newsync, - self.specials | other.specials, - self.clock_domains + other.clock_domains, - self.sim + other.sim) - - def __iadd__(self, other): - newsync = defaultdict(list) - for k, v in self.sync.items(): - newsync[k] = v[:] - for k, v in other.sync.items(): - newsync[k].extend(v) - self.comb += other.comb - self.sync = newsync - self.specials |= other.specials - self.clock_domains += other.clock_domains - self.sim += other.sim - return self + def __init__(self, comb=None, sync=None, specials=None, clock_domains=None, sim=None): + if comb is None: comb = [] + if sync is None: sync = dict() + if specials is None: specials = set() + if clock_domains is None: clock_domains = _ClockDomainList() + if sim is None: sim = [] + + self.comb = comb + self.sync = sync + self.specials = specials + self.clock_domains = _ClockDomainList(clock_domains) + self.sim = sim + + def __add__(self, other): + newsync = defaultdict(list) + for k, v in self.sync.items(): + newsync[k] = v[:] + for k, v in other.sync.items(): + newsync[k].extend(v) + return _Fragment(self.comb + other.comb, newsync, + self.specials | other.specials, + self.clock_domains + other.clock_domains, + self.sim + other.sim) + + def __iadd__(self, other): + newsync = defaultdict(list) + for k, v in self.sync.items(): + newsync[k] = v[:] + for k, v in other.sync.items(): + newsync[k].extend(v) + self.comb += other.comb + self.sync = newsync + self.specials |= other.specials + self.clock_domains += other.clock_domains + self.sim += other.sim + return self diff --git a/migen/fhdl/tools.py b/migen/fhdl/tools.py index ed74ab0e..233c0eba 100644 --- a/migen/fhdl/tools.py +++ b/migen/fhdl/tools.py @@ -5,245 +5,245 @@ from migen.fhdl.bitcontainer import value_bits_sign from migen.util.misc import flat_iteration class _SignalLister(NodeVisitor): - def __init__(self): - self.output_list = set() + def __init__(self): + self.output_list = set() - def visit_Signal(self, node): - self.output_list.add(node) + def visit_Signal(self, node): + self.output_list.add(node) class _TargetLister(NodeVisitor): - def __init__(self): - self.output_list = set() - self.target_context = False + def __init__(self): + self.output_list = set() + self.target_context = False - def visit_Signal(self, node): - if self.target_context: - self.output_list.add(node) + def visit_Signal(self, node): + if self.target_context: + self.output_list.add(node) - def visit_Assign(self, node): - self.target_context = True - self.visit(node.l) - self.target_context = False + def visit_Assign(self, node): + self.target_context = True + self.visit(node.l) + self.target_context = False - def visit_ArrayProxy(self, node): - for choice in node.choices: - self.visit(choice) + def visit_ArrayProxy(self, node): + for choice in node.choices: + self.visit(choice) def list_signals(node): - lister = _SignalLister() - lister.visit(node) - return lister.output_list + lister = _SignalLister() + lister.visit(node) + return lister.output_list def list_targets(node): - lister = _TargetLister() - lister.visit(node) - return lister.output_list + lister = _TargetLister() + lister.visit(node) + return lister.output_list def _resort_statements(ol): - return [statement for i, statement in - sorted(ol, key=lambda x: x[0])] + return [statement for i, statement in + sorted(ol, key=lambda x: x[0])] def group_by_targets(sl): - groups = [] - seen = set() - for order, stmt in enumerate(flat_iteration(sl)): - targets = set(list_targets(stmt)) - group = [(order, stmt)] - disjoint = targets.isdisjoint(seen) - seen |= targets - if not disjoint: - groups, old_groups = [], groups - for old_targets, old_group in old_groups: - if targets.isdisjoint(old_targets): - groups.append((old_targets, old_group)) - else: - targets |= old_targets - group += old_group - groups.append((targets, group)) - return [(targets, _resort_statements(stmts)) - for targets, stmts in groups] + groups = [] + seen = set() + for order, stmt in enumerate(flat_iteration(sl)): + targets = set(list_targets(stmt)) + group = [(order, stmt)] + disjoint = targets.isdisjoint(seen) + seen |= targets + if not disjoint: + groups, old_groups = [], groups + for old_targets, old_group in old_groups: + if targets.isdisjoint(old_targets): + groups.append((old_targets, old_group)) + else: + targets |= old_targets + group += old_group + groups.append((targets, group)) + return [(targets, _resort_statements(stmts)) + for targets, stmts in groups] def list_special_ios(f, ins, outs, inouts): - r = set() - for special in f.specials: - r |= special.list_ios(ins, outs, inouts) - return r + r = set() + for special in f.specials: + r |= special.list_ios(ins, outs, inouts) + return r class _ClockDomainLister(NodeVisitor): - def __init__(self): - self.clock_domains = set() + def __init__(self): + self.clock_domains = set() - def visit_ClockSignal(self, node): - self.clock_domains.add(node.cd) + def visit_ClockSignal(self, node): + self.clock_domains.add(node.cd) - def visit_ResetSignal(self, node): - self.clock_domains.add(node.cd) + def visit_ResetSignal(self, node): + self.clock_domains.add(node.cd) - def visit_clock_domains(self, node): - for clockname, statements in node.items(): - self.clock_domains.add(clockname) - self.visit(statements) + def visit_clock_domains(self, node): + for clockname, statements in node.items(): + self.clock_domains.add(clockname) + self.visit(statements) def list_clock_domains_expr(f): - cdl = _ClockDomainLister() - cdl.visit(f) - return cdl.clock_domains + cdl = _ClockDomainLister() + cdl.visit(f) + return cdl.clock_domains def list_clock_domains(f): - r = list_clock_domains_expr(f) - for special in f.specials: - r |= special.list_clock_domains() - for cd in f.clock_domains: - r.add(cd.name) - return r + r = list_clock_domains_expr(f) + for special in f.specials: + r |= special.list_clock_domains() + for cd in f.clock_domains: + r.add(cd.name) + return r def is_variable(node): - if isinstance(node, Signal): - return node.variable - elif isinstance(node, _Slice): - return is_variable(node.value) - elif isinstance(node, Cat): - arevars = list(map(is_variable, node.l)) - r = arevars[0] - for x in arevars: - if x != r: - raise TypeError - return r - else: - raise TypeError + if isinstance(node, Signal): + return node.variable + elif isinstance(node, _Slice): + return is_variable(node.value) + elif isinstance(node, Cat): + arevars = list(map(is_variable, node.l)) + r = arevars[0] + for x in arevars: + if x != r: + raise TypeError + return r + else: + raise TypeError def generate_reset(rst, sl): - targets = list_targets(sl) - return [t.eq(t.reset) for t in sorted(targets, key=lambda x: x.huid)] + targets = list_targets(sl) + return [t.eq(t.reset) for t in sorted(targets, key=lambda x: x.huid)] def insert_reset(rst, sl): - return [If(rst, *generate_reset(rst, sl)).Else(*sl)] + return [If(rst, *generate_reset(rst, sl)).Else(*sl)] def insert_resets(f): - newsync = dict() - for k, v in f.sync.items(): - if f.clock_domains[k].rst is not None: - newsync[k] = insert_reset(ResetSignal(k), v) - else: - newsync[k] = v - f.sync = newsync + newsync = dict() + for k, v in f.sync.items(): + if f.clock_domains[k].rst is not None: + newsync[k] = insert_reset(ResetSignal(k), v) + else: + newsync[k] = v + f.sync = newsync class _Lowerer(NodeTransformer): - def __init__(self): - self.target_context = False - self.extra_stmts = [] - self.comb = [] - - def visit_Assign(self, node): - old_target_context, old_extra_stmts = self.target_context, self.extra_stmts - self.extra_stmts = [] - - self.target_context = True - lhs = self.visit(node.l) - self.target_context = False - rhs = self.visit(node.r) - r = _Assign(lhs, rhs) - if self.extra_stmts: - r = [r] + self.extra_stmts - - self.target_context, self.extra_stmts = old_target_context, old_extra_stmts - return r + def __init__(self): + self.target_context = False + self.extra_stmts = [] + self.comb = [] + + def visit_Assign(self, node): + old_target_context, old_extra_stmts = self.target_context, self.extra_stmts + self.extra_stmts = [] + + self.target_context = True + lhs = self.visit(node.l) + self.target_context = False + rhs = self.visit(node.r) + r = _Assign(lhs, rhs) + if self.extra_stmts: + r = [r] + self.extra_stmts + + self.target_context, self.extra_stmts = old_target_context, old_extra_stmts + return r # Basics are FHDL structure elements that back-ends are not required to support # but can be expressed in terms of other elements (lowered) before conversion. class _BasicLowerer(_Lowerer): - def __init__(self, clock_domains): - self.clock_domains = clock_domains - _Lowerer.__init__(self) - - def visit_ArrayProxy(self, node): - # TODO: rewrite without variables - array_muxed = Signal(value_bits_sign(node), variable=True) - if self.target_context: - k = self.visit(node.key) - cases = {} - for n, choice in enumerate(node.choices): - cases[n] = [self.visit_Assign(_Assign(choice, array_muxed))] - self.extra_stmts.append(Case(k, cases).makedefault()) - else: - cases = dict((n, _Assign(array_muxed, self.visit(choice))) - for n, choice in enumerate(node.choices)) - self.comb.append(Case(self.visit(node.key), cases).makedefault()) - return array_muxed - - def visit_ClockSignal(self, node): - return self.clock_domains[node.cd].clk - - def visit_ResetSignal(self, node): - return self.clock_domains[node.cd].rst + def __init__(self, clock_domains): + self.clock_domains = clock_domains + _Lowerer.__init__(self) + + def visit_ArrayProxy(self, node): + # TODO: rewrite without variables + array_muxed = Signal(value_bits_sign(node), variable=True) + if self.target_context: + k = self.visit(node.key) + cases = {} + for n, choice in enumerate(node.choices): + cases[n] = [self.visit_Assign(_Assign(choice, array_muxed))] + self.extra_stmts.append(Case(k, cases).makedefault()) + else: + cases = dict((n, _Assign(array_muxed, self.visit(choice))) + for n, choice in enumerate(node.choices)) + self.comb.append(Case(self.visit(node.key), cases).makedefault()) + return array_muxed + + def visit_ClockSignal(self, node): + return self.clock_domains[node.cd].clk + + def visit_ResetSignal(self, node): + return self.clock_domains[node.cd].rst class _ComplexSliceLowerer(_Lowerer): - def visit_Slice(self, node): - if not isinstance(node.value, Signal): - slice_proxy = Signal(value_bits_sign(node.value)) - if self.target_context: - a = _Assign(node.value, slice_proxy) - else: - a = _Assign(slice_proxy, node.value) - self.comb.append(self.visit_Assign(a)) - node = _Slice(slice_proxy, node.start, node.stop) - return NodeTransformer.visit_Slice(self, node) + def visit_Slice(self, node): + if not isinstance(node.value, Signal): + slice_proxy = Signal(value_bits_sign(node.value)) + if self.target_context: + a = _Assign(node.value, slice_proxy) + else: + a = _Assign(slice_proxy, node.value) + self.comb.append(self.visit_Assign(a)) + node = _Slice(slice_proxy, node.start, node.stop) + return NodeTransformer.visit_Slice(self, node) def _apply_lowerer(l, f): - f = l.visit(f) - f.comb += l.comb - - for special in f.specials: - for obj, attr, direction in special.iter_expressions(): - if direction != SPECIAL_INOUT: - # inouts are only supported by Migen when connected directly to top-level - # in this case, they are Signal and never need lowering - l.comb = [] - l.target_context = direction != SPECIAL_INPUT - l.extra_stmts = [] - expr = getattr(obj, attr) - expr = l.visit(expr) - setattr(obj, attr, expr) - f.comb += l.comb + l.extra_stmts - - return f + f = l.visit(f) + f.comb += l.comb + + for special in f.specials: + for obj, attr, direction in special.iter_expressions(): + if direction != SPECIAL_INOUT: + # inouts are only supported by Migen when connected directly to top-level + # in this case, they are Signal and never need lowering + l.comb = [] + l.target_context = direction != SPECIAL_INPUT + l.extra_stmts = [] + expr = getattr(obj, attr) + expr = l.visit(expr) + setattr(obj, attr, expr) + f.comb += l.comb + l.extra_stmts + + return f def lower_basics(f): - return _apply_lowerer(_BasicLowerer(f.clock_domains), f) + return _apply_lowerer(_BasicLowerer(f.clock_domains), f) def lower_complex_slices(f): - return _apply_lowerer(_ComplexSliceLowerer(), f) + return _apply_lowerer(_ComplexSliceLowerer(), f) class _ClockDomainRenamer(NodeVisitor): - def __init__(self, old, new): - self.old = old - self.new = new + def __init__(self, old, new): + self.old = old + self.new = new - def visit_ClockSignal(self, node): - if node.cd == self.old: - node.cd = self.new + def visit_ClockSignal(self, node): + if node.cd == self.old: + node.cd = self.new - def visit_ResetSignal(self, node): - if node.cd == self.old: - node.cd = self.new + def visit_ResetSignal(self, node): + if node.cd == self.old: + node.cd = self.new def rename_clock_domain_expr(f, old, new): - cdr = _ClockDomainRenamer(old, new) - cdr.visit(f) + cdr = _ClockDomainRenamer(old, new) + cdr.visit(f) def rename_clock_domain(f, old, new): - rename_clock_domain_expr(f, old, new) - if old in f.sync: - if new in f.sync: - f.sync[new].extend(f.sync[old]) - else: - f.sync[new] = f.sync[old] - del f.sync[old] - for special in f.specials: - special.rename_clock_domain(old, new) - try: - cd = f.clock_domains[old] - except KeyError: - pass - else: - cd.rename(new) + rename_clock_domain_expr(f, old, new) + if old in f.sync: + if new in f.sync: + f.sync[new].extend(f.sync[old]) + else: + f.sync[new] = f.sync[old] + del f.sync[old] + for special in f.specials: + special.rename_clock_domain(old, new) + try: + cd = f.clock_domains[old] + except KeyError: + pass + else: + cd.rename(new) diff --git a/migen/fhdl/tracer.py b/migen/fhdl/tracer.py index 73a47a31..ad696608 100644 --- a/migen/fhdl/tracer.py +++ b/migen/fhdl/tracer.py @@ -3,108 +3,108 @@ from opcode import opname from collections import defaultdict def get_var_name(frame): - code = frame.f_code - call_index = frame.f_lasti - call_opc = opname[code.co_code[call_index]] - if call_opc != "CALL_FUNCTION" and call_opc != "CALL_FUNCTION_VAR": - return None - index = call_index+3 - while True: - opc = opname[code.co_code[index]] - if opc == "STORE_NAME" or opc == "STORE_ATTR": - name_index = int(code.co_code[index+1]) - return code.co_names[name_index] - elif opc == "STORE_FAST": - name_index = int(code.co_code[index+1]) - return code.co_varnames[name_index] - elif opc == "STORE_DEREF": - name_index = int(code.co_code[index+1]) - return code.co_cellvars[name_index] - elif opc == "LOAD_GLOBAL" or opc == "LOAD_ATTR" or opc == "LOAD_FAST" or opc == "LOAD_DEREF": - index += 3 - elif opc == "DUP_TOP": - index += 1 - elif opc == "BUILD_LIST": - index += 3 - else: - return None + code = frame.f_code + call_index = frame.f_lasti + call_opc = opname[code.co_code[call_index]] + if call_opc != "CALL_FUNCTION" and call_opc != "CALL_FUNCTION_VAR": + return None + index = call_index+3 + while True: + opc = opname[code.co_code[index]] + if opc == "STORE_NAME" or opc == "STORE_ATTR": + name_index = int(code.co_code[index+1]) + return code.co_names[name_index] + elif opc == "STORE_FAST": + name_index = int(code.co_code[index+1]) + return code.co_varnames[name_index] + elif opc == "STORE_DEREF": + name_index = int(code.co_code[index+1]) + return code.co_cellvars[name_index] + elif opc == "LOAD_GLOBAL" or opc == "LOAD_ATTR" or opc == "LOAD_FAST" or opc == "LOAD_DEREF": + index += 3 + elif opc == "DUP_TOP": + index += 1 + elif opc == "BUILD_LIST": + index += 3 + else: + return None def remove_underscore(s): - if len(s) > 2 and s[0] == "_" and s[1] != "_": - s = s[1:] - return s + if len(s) > 2 and s[0] == "_" and s[1] != "_": + s = s[1:] + return s def get_obj_var_name(override=None, default=None): - if override: - return override + if override: + return override - frame = inspect.currentframe().f_back - # We can be called via derived classes. Go back the stack frames - # until we reach the first class that does not inherit from us. - ourclass = frame.f_locals["self"].__class__ - while "self" in frame.f_locals and isinstance(frame.f_locals["self"], ourclass): - frame = frame.f_back + frame = inspect.currentframe().f_back + # We can be called via derived classes. Go back the stack frames + # until we reach the first class that does not inherit from us. + ourclass = frame.f_locals["self"].__class__ + while "self" in frame.f_locals and isinstance(frame.f_locals["self"], ourclass): + frame = frame.f_back - vn = get_var_name(frame) - if vn is None: - vn = default - else: - vn = remove_underscore(vn) - return vn + vn = get_var_name(frame) + if vn is None: + vn = default + else: + vn = remove_underscore(vn) + return vn name_to_idx = defaultdict(int) classname_to_objs = dict() def index_id(l, obj): - for n, e in enumerate(l): - if id(e) == id(obj): - return n - raise ValueError + for n, e in enumerate(l): + if id(e) == id(obj): + return n + raise ValueError def trace_back(varname=None): - l = [] - frame = inspect.currentframe().f_back.f_back - while frame is not None: - if varname is None: - varname = get_var_name(frame) - if varname is not None: - varname = remove_underscore(varname) - l.insert(0, (varname, name_to_idx[varname])) - name_to_idx[varname] += 1 + l = [] + frame = inspect.currentframe().f_back.f_back + while frame is not None: + if varname is None: + varname = get_var_name(frame) + if varname is not None: + varname = remove_underscore(varname) + l.insert(0, (varname, name_to_idx[varname])) + name_to_idx[varname] += 1 - try: - obj = frame.f_locals["self"] - except KeyError: - obj = None - if hasattr(obj, "__del__"): - obj = None + try: + obj = frame.f_locals["self"] + except KeyError: + obj = None + if hasattr(obj, "__del__"): + obj = None - if obj is None: - if varname is not None: - coname = frame.f_code.co_name - if coname == "": - modules = frame.f_globals["__name__"] - modules = modules.split(".") - coname = modules[len(modules)-1] - coname = remove_underscore(coname) - l.insert(0, (coname, name_to_idx[coname])) - name_to_idx[coname] += 1 - else: - classname = obj.__class__.__name__.lower() - try: - objs = classname_to_objs[classname] - except KeyError: - classname_to_objs[classname] = [obj] - idx = 0 - else: - try: - idx = index_id(objs, obj) - except ValueError: - idx = len(objs) - objs.append(obj) - classname = remove_underscore(classname) - l.insert(0, (classname, idx)) + if obj is None: + if varname is not None: + coname = frame.f_code.co_name + if coname == "": + modules = frame.f_globals["__name__"] + modules = modules.split(".") + coname = modules[len(modules)-1] + coname = remove_underscore(coname) + l.insert(0, (coname, name_to_idx[coname])) + name_to_idx[coname] += 1 + else: + classname = obj.__class__.__name__.lower() + try: + objs = classname_to_objs[classname] + except KeyError: + classname_to_objs[classname] = [obj] + idx = 0 + else: + try: + idx = index_id(objs, obj) + except ValueError: + idx = len(objs) + objs.append(obj) + classname = remove_underscore(classname) + l.insert(0, (classname, idx)) - varname = None - frame = frame.f_back - return l + varname = None + frame = frame.f_back + return l diff --git a/migen/fhdl/verilog.py b/migen/fhdl/verilog.py index eac214c6..46edfd43 100644 --- a/migen/fhdl/verilog.py +++ b/migen/fhdl/verilog.py @@ -9,306 +9,306 @@ from migen.fhdl.namer import Namespace, build_namespace from migen.fhdl.conv_output import ConvOutput def _printsig(ns, s): - if s.signed: - n = "signed " - else: - n = "" - if flen(s) > 1: - n += "[" + str(flen(s)-1) + ":0] " - n += ns.get_name(s) - return n + if s.signed: + n = "signed " + else: + n = "" + if flen(s) > 1: + n += "[" + str(flen(s)-1) + ":0] " + n += ns.get_name(s) + return n def _printintbool(node): - if isinstance(node, bool): - if node: - return "1'd1", False - else: - return "1'd0", False - elif isinstance(node, int): - if node >= 0: - return str(bits_for(node)) + "'d" + str(node), False - else: - nbits = bits_for(node) - return str(nbits) + "'sd" + str(2**nbits + node), True - else: - raise TypeError + if isinstance(node, bool): + if node: + return "1'd1", False + else: + return "1'd0", False + elif isinstance(node, int): + if node >= 0: + return str(bits_for(node)) + "'d" + str(node), False + else: + nbits = bits_for(node) + return str(nbits) + "'sd" + str(2**nbits + node), True + else: + raise TypeError def _printexpr(ns, node): - if isinstance(node, (int, bool)): - return _printintbool(node) - elif isinstance(node, Signal): - return ns.get_name(node), node.signed - elif isinstance(node, _Operator): - arity = len(node.operands) - r1, s1 = _printexpr(ns, node.operands[0]) - if arity == 1: - if node.op == "-": - if s1: - r = node.op + r1 - else: - r = "-$signed({1'd0, " + r1 + "})" - s = True - else: - r = node.op + r1 - s = s1 - elif arity == 2: - r2, s2 = _printexpr(ns, node.operands[1]) - if node.op not in ["<<<", ">>>"]: - if s2 and not s1: - r1 = "$signed({1'd0, " + r1 + "})" - if s1 and not s2: - r2 = "$signed({1'd0, " + r2 + "})" - r = r1 + " " + node.op + " " + r2 - s = s1 or s2 - elif arity == 3: - assert node.op == "m" - r2, s2 = _printexpr(ns, node.operands[1]) - r3, s3 = _printexpr(ns, node.operands[2]) - if s2 and not s3: - r3 = "$signed({1'd0, " + r3 + "})" - if s3 and not s2: - r2 = "$signed({1'd0, " + r2 + "})" - r = r1 + " ? " + r2 + " : " + r3 - s = s2 or s3 - else: - raise TypeError - return "(" + r + ")", s - elif isinstance(node, _Slice): - # Verilog does not like us slicing non-array signals... - if isinstance(node.value, Signal) \ - and flen(node.value) == 1 \ - and node.start == 0 and node.stop == 1: - return _printexpr(ns, node.value) + if isinstance(node, (int, bool)): + return _printintbool(node) + elif isinstance(node, Signal): + return ns.get_name(node), node.signed + elif isinstance(node, _Operator): + arity = len(node.operands) + r1, s1 = _printexpr(ns, node.operands[0]) + if arity == 1: + if node.op == "-": + if s1: + r = node.op + r1 + else: + r = "-$signed({1'd0, " + r1 + "})" + s = True + else: + r = node.op + r1 + s = s1 + elif arity == 2: + r2, s2 = _printexpr(ns, node.operands[1]) + if node.op not in ["<<<", ">>>"]: + if s2 and not s1: + r1 = "$signed({1'd0, " + r1 + "})" + if s1 and not s2: + r2 = "$signed({1'd0, " + r2 + "})" + r = r1 + " " + node.op + " " + r2 + s = s1 or s2 + elif arity == 3: + assert node.op == "m" + r2, s2 = _printexpr(ns, node.operands[1]) + r3, s3 = _printexpr(ns, node.operands[2]) + if s2 and not s3: + r3 = "$signed({1'd0, " + r3 + "})" + if s3 and not s2: + r2 = "$signed({1'd0, " + r2 + "})" + r = r1 + " ? " + r2 + " : " + r3 + s = s2 or s3 + else: + raise TypeError + return "(" + r + ")", s + elif isinstance(node, _Slice): + # Verilog does not like us slicing non-array signals... + if isinstance(node.value, Signal) \ + and flen(node.value) == 1 \ + and node.start == 0 and node.stop == 1: + return _printexpr(ns, node.value) - if node.start + 1 == node.stop: - sr = "[" + str(node.start) + "]" - else: - sr = "[" + str(node.stop-1) + ":" + str(node.start) + "]" - r, s = _printexpr(ns, node.value) - return r + sr, s - elif isinstance(node, Cat): - l = [_printexpr(ns, v)[0] for v in reversed(node.l)] - return "{" + ", ".join(l) + "}", False - elif isinstance(node, Replicate): - return "{" + str(node.n) + "{" + _printexpr(ns, node.v)[0] + "}}", False - else: - raise TypeError("Expression of unrecognized type: "+str(type(node))) + if node.start + 1 == node.stop: + sr = "[" + str(node.start) + "]" + else: + sr = "[" + str(node.stop-1) + ":" + str(node.start) + "]" + r, s = _printexpr(ns, node.value) + return r + sr, s + elif isinstance(node, Cat): + l = [_printexpr(ns, v)[0] for v in reversed(node.l)] + return "{" + ", ".join(l) + "}", False + elif isinstance(node, Replicate): + return "{" + str(node.n) + "{" + _printexpr(ns, node.v)[0] + "}}", False + else: + raise TypeError("Expression of unrecognized type: "+str(type(node))) (_AT_BLOCKING, _AT_NONBLOCKING, _AT_SIGNAL) = range(3) def _printnode(ns, at, level, node): - if node is None: - return "" - elif isinstance(node, _Assign): - if at == _AT_BLOCKING: - assignment = " = " - elif at == _AT_NONBLOCKING: - assignment = " <= " - elif is_variable(node.l): - assignment = " = " - else: - assignment = " <= " - return "\t"*level + _printexpr(ns, node.l)[0] + assignment + _printexpr(ns, node.r)[0] + ";\n" - elif isinstance(node, (list, tuple)): - return "".join(list(map(partial(_printnode, ns, at, level), node))) - elif isinstance(node, If): - r = "\t"*level + "if (" + _printexpr(ns, node.cond)[0] + ") begin\n" - r += _printnode(ns, at, level + 1, node.t) - if node.f: - r += "\t"*level + "end else begin\n" - r += _printnode(ns, at, level + 1, node.f) - r += "\t"*level + "end\n" - return r - elif isinstance(node, Case): - if node.cases: - r = "\t"*level + "case (" + _printexpr(ns, node.test)[0] + ")\n" - css = sorted([(k, v) for (k, v) in node.cases.items() if k != "default"], key=itemgetter(0)) - for choice, statements in css: - r += "\t"*(level + 1) + _printexpr(ns, choice)[0] + ": begin\n" - r += _printnode(ns, at, level + 2, statements) - r += "\t"*(level + 1) + "end\n" - if "default" in node.cases: - r += "\t"*(level + 1) + "default: begin\n" - r += _printnode(ns, at, level + 2, node.cases["default"]) - r += "\t"*(level + 1) + "end\n" - r += "\t"*level + "endcase\n" - return r - else: - return "" - else: - raise TypeError("Node of unrecognized type: "+str(type(node))) + if node is None: + return "" + elif isinstance(node, _Assign): + if at == _AT_BLOCKING: + assignment = " = " + elif at == _AT_NONBLOCKING: + assignment = " <= " + elif is_variable(node.l): + assignment = " = " + else: + assignment = " <= " + return "\t"*level + _printexpr(ns, node.l)[0] + assignment + _printexpr(ns, node.r)[0] + ";\n" + elif isinstance(node, (list, tuple)): + return "".join(list(map(partial(_printnode, ns, at, level), node))) + elif isinstance(node, If): + r = "\t"*level + "if (" + _printexpr(ns, node.cond)[0] + ") begin\n" + r += _printnode(ns, at, level + 1, node.t) + if node.f: + r += "\t"*level + "end else begin\n" + r += _printnode(ns, at, level + 1, node.f) + r += "\t"*level + "end\n" + return r + elif isinstance(node, Case): + if node.cases: + r = "\t"*level + "case (" + _printexpr(ns, node.test)[0] + ")\n" + css = sorted([(k, v) for (k, v) in node.cases.items() if k != "default"], key=itemgetter(0)) + for choice, statements in css: + r += "\t"*(level + 1) + _printexpr(ns, choice)[0] + ": begin\n" + r += _printnode(ns, at, level + 2, statements) + r += "\t"*(level + 1) + "end\n" + if "default" in node.cases: + r += "\t"*(level + 1) + "default: begin\n" + r += _printnode(ns, at, level + 2, node.cases["default"]) + r += "\t"*(level + 1) + "end\n" + r += "\t"*level + "endcase\n" + return r + else: + return "" + else: + raise TypeError("Node of unrecognized type: "+str(type(node))) def _list_comb_wires(f): - r = set() - groups = group_by_targets(f.comb) - for g in groups: - if len(g[1]) == 1 and isinstance(g[1][0], _Assign): - r |= g[0] - return r + r = set() + groups = group_by_targets(f.comb) + for g in groups: + if len(g[1]) == 1 and isinstance(g[1][0], _Assign): + r |= g[0] + return r def _printheader(f, ios, name, ns): - sigs = list_signals(f) | list_special_ios(f, True, True, True) - special_outs = list_special_ios(f, False, True, True) - inouts = list_special_ios(f, False, False, True) - targets = list_targets(f) | special_outs - wires = _list_comb_wires(f) | special_outs - r = "module " + name + "(\n" - firstp = True - for sig in sorted(ios, key=lambda x: x.huid): - if not firstp: - r += ",\n" - firstp = False - if sig in inouts: - r += "\tinout " + _printsig(ns, sig) - elif sig in targets: - if sig in wires: - r += "\toutput " + _printsig(ns, sig) - else: - r += "\toutput reg " + _printsig(ns, sig) - else: - r += "\tinput " + _printsig(ns, sig) - r += "\n);\n\n" - for sig in sorted(sigs - ios, key=lambda x: x.huid): - if sig in wires: - r += "wire " + _printsig(ns, sig) + ";\n" - else: - if isinstance(sig.reset, int): - resetexpr = " = " + _printexpr(ns, sig.reset)[0] - else: - resetexpr = "" - r += "reg " + _printsig(ns, sig) + resetexpr + ";\n" - r += "\n" - return r + sigs = list_signals(f) | list_special_ios(f, True, True, True) + special_outs = list_special_ios(f, False, True, True) + inouts = list_special_ios(f, False, False, True) + targets = list_targets(f) | special_outs + wires = _list_comb_wires(f) | special_outs + r = "module " + name + "(\n" + firstp = True + for sig in sorted(ios, key=lambda x: x.huid): + if not firstp: + r += ",\n" + firstp = False + if sig in inouts: + r += "\tinout " + _printsig(ns, sig) + elif sig in targets: + if sig in wires: + r += "\toutput " + _printsig(ns, sig) + else: + r += "\toutput reg " + _printsig(ns, sig) + else: + r += "\tinput " + _printsig(ns, sig) + r += "\n);\n\n" + for sig in sorted(sigs - ios, key=lambda x: x.huid): + if sig in wires: + r += "wire " + _printsig(ns, sig) + ";\n" + else: + if isinstance(sig.reset, int): + resetexpr = " = " + _printexpr(ns, sig.reset)[0] + else: + resetexpr = "" + r += "reg " + _printsig(ns, sig) + resetexpr + ";\n" + r += "\n" + return r def _printcomb(f, ns, display_run): - r = "" - if f.comb: - # Generate a dummy event to get the simulator - # to run the combinatorial process once at the beginning. - syn_off = "// synthesis translate_off\n" - syn_on = "// synthesis translate_on\n" - dummy_s = Signal(name_override="dummy_s") - r += syn_off - r += "reg " + _printsig(ns, dummy_s) + ";\n" - r += "initial " + ns.get_name(dummy_s) + " <= 1'd0;\n" - r += syn_on + r = "" + if f.comb: + # Generate a dummy event to get the simulator + # to run the combinatorial process once at the beginning. + syn_off = "// synthesis translate_off\n" + syn_on = "// synthesis translate_on\n" + dummy_s = Signal(name_override="dummy_s") + r += syn_off + r += "reg " + _printsig(ns, dummy_s) + ";\n" + r += "initial " + ns.get_name(dummy_s) + " <= 1'd0;\n" + r += syn_on - groups = group_by_targets(f.comb) + groups = group_by_targets(f.comb) - for n, g in enumerate(groups): - if len(g[1]) == 1 and isinstance(g[1][0], _Assign): - r += "assign " + _printnode(ns, _AT_BLOCKING, 0, g[1][0]) - else: - dummy_d = Signal(name_override="dummy_d") - r += "\n" + syn_off - r += "reg " + _printsig(ns, dummy_d) + ";\n" - r += syn_on + for n, g in enumerate(groups): + if len(g[1]) == 1 and isinstance(g[1][0], _Assign): + r += "assign " + _printnode(ns, _AT_BLOCKING, 0, g[1][0]) + else: + dummy_d = Signal(name_override="dummy_d") + r += "\n" + syn_off + r += "reg " + _printsig(ns, dummy_d) + ";\n" + r += syn_on - r += "always @(*) begin\n" - if display_run: - r += "\t$display(\"Running comb block #" + str(n) + "\");\n" - for t in g[0]: - r += "\t" + ns.get_name(t) + " <= " + _printexpr(ns, t.reset)[0] + ";\n" - r += _printnode(ns, _AT_NONBLOCKING, 1, g[1]) - r += syn_off - r += "\t" + ns.get_name(dummy_d) + " <= " + ns.get_name(dummy_s) + ";\n" - r += syn_on - r += "end\n" - r += "\n" - return r + r += "always @(*) begin\n" + if display_run: + r += "\t$display(\"Running comb block #" + str(n) + "\");\n" + for t in g[0]: + r += "\t" + ns.get_name(t) + " <= " + _printexpr(ns, t.reset)[0] + ";\n" + r += _printnode(ns, _AT_NONBLOCKING, 1, g[1]) + r += syn_off + r += "\t" + ns.get_name(dummy_d) + " <= " + ns.get_name(dummy_s) + ";\n" + r += syn_on + r += "end\n" + r += "\n" + return r def _printsync(f, ns): - r = "" - for k, v in sorted(f.sync.items(), key=itemgetter(0)): - r += "always @(posedge " + ns.get_name(f.clock_domains[k].clk) + ") begin\n" - r += _printnode(ns, _AT_SIGNAL, 1, v) - r += "end\n\n" - return r + r = "" + for k, v in sorted(f.sync.items(), key=itemgetter(0)): + r += "always @(posedge " + ns.get_name(f.clock_domains[k].clk) + ") begin\n" + r += _printnode(ns, _AT_SIGNAL, 1, v) + r += "end\n\n" + return r def _call_special_classmethod(overrides, obj, method, *args, **kwargs): - cl = obj.__class__ - if cl in overrides: - cl = overrides[cl] - if hasattr(cl, method): - return getattr(cl, method)(obj, *args, **kwargs) - else: - return None + cl = obj.__class__ + if cl in overrides: + cl = overrides[cl] + if hasattr(cl, method): + return getattr(cl, method)(obj, *args, **kwargs) + else: + return None def _lower_specials_step(overrides, specials): - f = _Fragment() - lowered_specials = set() - for special in sorted(specials, key=lambda x: x.huid): - impl = _call_special_classmethod(overrides, special, "lower") - if impl is not None: - f += impl.get_fragment() - lowered_specials.add(special) - return f, lowered_specials + f = _Fragment() + lowered_specials = set() + for special in sorted(specials, key=lambda x: x.huid): + impl = _call_special_classmethod(overrides, special, "lower") + if impl is not None: + f += impl.get_fragment() + lowered_specials.add(special) + return f, lowered_specials def _can_lower(overrides, specials): - for special in specials: - cl = special.__class__ - if cl in overrides: - cl = overrides[cl] - if hasattr(cl, "lower"): - return True - return False + for special in specials: + cl = special.__class__ + if cl in overrides: + cl = overrides[cl] + if hasattr(cl, "lower"): + return True + return False def _lower_specials(overrides, specials): - f, lowered_specials = _lower_specials_step(overrides, specials) - while _can_lower(overrides, f.specials): - f2, lowered_specials2 = _lower_specials_step(overrides, f.specials) - f += f2 - lowered_specials |= lowered_specials2 - f.specials -= lowered_specials2 - return f, lowered_specials + f, lowered_specials = _lower_specials_step(overrides, specials) + while _can_lower(overrides, f.specials): + f2, lowered_specials2 = _lower_specials_step(overrides, f.specials) + f += f2 + lowered_specials |= lowered_specials2 + f.specials -= lowered_specials2 + return f, lowered_specials def _printspecials(overrides, specials, ns, add_data_file): - r = "" - for special in sorted(specials, key=lambda x: x.huid): - pr = _call_special_classmethod(overrides, special, "emit_verilog", ns, add_data_file) - if pr is None: - raise NotImplementedError("Special " + str(special) + " failed to implement emit_verilog") - r += pr - return r + r = "" + for special in sorted(specials, key=lambda x: x.huid): + pr = _call_special_classmethod(overrides, special, "emit_verilog", ns, add_data_file) + if pr is None: + raise NotImplementedError("Special " + str(special) + " failed to implement emit_verilog") + r += pr + return r def convert(f, ios=None, name="top", special_overrides=dict(), create_clock_domains=True, display_run=False): - r = ConvOutput() - if not isinstance(f, _Fragment): - f = f.get_fragment() - if ios is None: - ios = set() + r = ConvOutput() + if not isinstance(f, _Fragment): + f = f.get_fragment() + if ios is None: + ios = set() - for cd_name in list_clock_domains(f): - try: - f.clock_domains[cd_name] - except KeyError: - if create_clock_domains: - cd = ClockDomain(cd_name) - f.clock_domains.append(cd) - ios |= {cd.clk, cd.rst} - else: - raise KeyError("Unresolved clock domain: '"+cd_name+"'") + for cd_name in list_clock_domains(f): + try: + f.clock_domains[cd_name] + except KeyError: + if create_clock_domains: + cd = ClockDomain(cd_name) + f.clock_domains.append(cd) + ios |= {cd.clk, cd.rst} + else: + raise KeyError("Unresolved clock domain: '"+cd_name+"'") - f = lower_complex_slices(f) - insert_resets(f) - f = lower_basics(f) - fs, lowered_specials = _lower_specials(special_overrides, f.specials) - f += lower_basics(fs) + f = lower_complex_slices(f) + insert_resets(f) + f = lower_basics(f) + fs, lowered_specials = _lower_specials(special_overrides, f.specials) + f += lower_basics(fs) - ns = build_namespace(list_signals(f) \ - | list_special_ios(f, True, True, True) \ - | ios) - r.ns = ns + ns = build_namespace(list_signals(f) \ + | list_special_ios(f, True, True, True) \ + | ios) + r.ns = ns - src = "/* Machine-generated using Migen */\n" - src += _printheader(f, ios, name, ns) - src += _printcomb(f, ns, display_run) - src += _printsync(f, ns) - src += _printspecials(special_overrides, f.specials - lowered_specials, ns, r.add_data_file) - src += "endmodule\n" - r.set_main_source(src) + src = "/* Machine-generated using Migen */\n" + src += _printheader(f, ios, name, ns) + src += _printcomb(f, ns, display_run) + src += _printsync(f, ns) + src += _printspecials(special_overrides, f.specials - lowered_specials, ns, r.add_data_file) + src += "endmodule\n" + r.set_main_source(src) - return r + return r diff --git a/migen/fhdl/visit.py b/migen/fhdl/visit.py index 386c038b..3a6d7e1c 100644 --- a/migen/fhdl/visit.py +++ b/migen/fhdl/visit.py @@ -4,99 +4,99 @@ from migen.fhdl.structure import * from migen.fhdl.structure import _Operator, _Slice, _Assign, _ArrayProxy, _Fragment class NodeVisitor: - def visit(self, node): - if isinstance(node, (int, bool)): - self.visit_constant(node) - elif isinstance(node, Signal): - self.visit_Signal(node) - elif isinstance(node, ClockSignal): - self.visit_ClockSignal(node) - elif isinstance(node, ResetSignal): - self.visit_ResetSignal(node) - elif isinstance(node, _Operator): - self.visit_Operator(node) - elif isinstance(node, _Slice): - self.visit_Slice(node) - elif isinstance(node, Cat): - self.visit_Cat(node) - elif isinstance(node, Replicate): - self.visit_Replicate(node) - elif isinstance(node, _Assign): - self.visit_Assign(node) - elif isinstance(node, If): - self.visit_If(node) - elif isinstance(node, Case): - self.visit_Case(node) - elif isinstance(node, _Fragment): - self.visit_Fragment(node) - elif isinstance(node, (list, tuple)): - self.visit_statements(node) - elif isinstance(node, dict): - self.visit_clock_domains(node) - elif isinstance(node, _ArrayProxy): - self.visit_ArrayProxy(node) - elif node is not None: - self.visit_unknown(node) - - def visit_constant(self, node): - pass - - def visit_Signal(self, node): - pass - - def visit_ClockSignal(self, node): - pass - - def visit_ResetSignal(self, node): - pass - - def visit_Operator(self, node): - for o in node.operands: - self.visit(o) - - def visit_Slice(self, node): - self.visit(node.value) - - def visit_Cat(self, node): - for e in node.l: - self.visit(e) - - def visit_Replicate(self, node): - self.visit(node.v) - - def visit_Assign(self, node): - self.visit(node.l) - self.visit(node.r) - - def visit_If(self, node): - self.visit(node.cond) - self.visit(node.t) - self.visit(node.f) - - def visit_Case(self, node): - self.visit(node.test) - for v, statements in node.cases.items(): - self.visit(statements) - - def visit_Fragment(self, node): - self.visit(node.comb) - self.visit(node.sync) - - def visit_statements(self, node): - for statement in node: - self.visit(statement) - - def visit_clock_domains(self, node): - for clockname, statements in node.items(): - self.visit(statements) - - def visit_ArrayProxy(self, node): - for choice in node.choices: - self.visit(choice) - self.visit(node.key) - - def visit_unknown(self, node): - pass + def visit(self, node): + if isinstance(node, (int, bool)): + self.visit_constant(node) + elif isinstance(node, Signal): + self.visit_Signal(node) + elif isinstance(node, ClockSignal): + self.visit_ClockSignal(node) + elif isinstance(node, ResetSignal): + self.visit_ResetSignal(node) + elif isinstance(node, _Operator): + self.visit_Operator(node) + elif isinstance(node, _Slice): + self.visit_Slice(node) + elif isinstance(node, Cat): + self.visit_Cat(node) + elif isinstance(node, Replicate): + self.visit_Replicate(node) + elif isinstance(node, _Assign): + self.visit_Assign(node) + elif isinstance(node, If): + self.visit_If(node) + elif isinstance(node, Case): + self.visit_Case(node) + elif isinstance(node, _Fragment): + self.visit_Fragment(node) + elif isinstance(node, (list, tuple)): + self.visit_statements(node) + elif isinstance(node, dict): + self.visit_clock_domains(node) + elif isinstance(node, _ArrayProxy): + self.visit_ArrayProxy(node) + elif node is not None: + self.visit_unknown(node) + + def visit_constant(self, node): + pass + + def visit_Signal(self, node): + pass + + def visit_ClockSignal(self, node): + pass + + def visit_ResetSignal(self, node): + pass + + def visit_Operator(self, node): + for o in node.operands: + self.visit(o) + + def visit_Slice(self, node): + self.visit(node.value) + + def visit_Cat(self, node): + for e in node.l: + self.visit(e) + + def visit_Replicate(self, node): + self.visit(node.v) + + def visit_Assign(self, node): + self.visit(node.l) + self.visit(node.r) + + def visit_If(self, node): + self.visit(node.cond) + self.visit(node.t) + self.visit(node.f) + + def visit_Case(self, node): + self.visit(node.test) + for v, statements in node.cases.items(): + self.visit(statements) + + def visit_Fragment(self, node): + self.visit(node.comb) + self.visit(node.sync) + + def visit_statements(self, node): + for statement in node: + self.visit(statement) + + def visit_clock_domains(self, node): + for clockname, statements in node.items(): + self.visit(statements) + + def visit_ArrayProxy(self, node): + for choice in node.choices: + self.visit(choice) + self.visit(node.key) + + def visit_unknown(self, node): + pass # Default methods always copy the node, except for: # - Signals, ClockSignals and ResetSignals @@ -104,96 +104,96 @@ class NodeVisitor: # - All fragment fields except comb and sync # In those cases, the original node is returned unchanged. class NodeTransformer: - def visit(self, node): - if isinstance(node, (int, bool)): - return self.visit_constant(node) - elif isinstance(node, Signal): - return self.visit_Signal(node) - elif isinstance(node, ClockSignal): - return self.visit_ClockSignal(node) - elif isinstance(node, ResetSignal): - return self.visit_ResetSignal(node) - elif isinstance(node, _Operator): - return self.visit_Operator(node) - elif isinstance(node, _Slice): - return self.visit_Slice(node) - elif isinstance(node, Cat): - return self.visit_Cat(node) - elif isinstance(node, Replicate): - return self.visit_Replicate(node) - elif isinstance(node, _Assign): - return self.visit_Assign(node) - elif isinstance(node, If): - return self.visit_If(node) - elif isinstance(node, Case): - return self.visit_Case(node) - elif isinstance(node, _Fragment): - return self.visit_Fragment(node) - elif isinstance(node, (list, tuple)): - return self.visit_statements(node) - elif isinstance(node, dict): - return self.visit_clock_domains(node) - elif isinstance(node, _ArrayProxy): - return self.visit_ArrayProxy(node) - elif node is not None: - return self.visit_unknown(node) - else: - return None - - def visit_constant(self, node): - return node - - def visit_Signal(self, node): - return node - - def visit_ClockSignal(self, node): - return node - - def visit_ResetSignal(self, node): - return node - - def visit_Operator(self, node): - return _Operator(node.op, [self.visit(o) for o in node.operands]) - - def visit_Slice(self, node): - return _Slice(self.visit(node.value), node.start, node.stop) - - def visit_Cat(self, node): - return Cat(*[self.visit(e) for e in node.l]) - - def visit_Replicate(self, node): - return Replicate(self.visit(node.v), node.n) - - def visit_Assign(self, node): - return _Assign(self.visit(node.l), self.visit(node.r)) - - def visit_If(self, node): - r = If(self.visit(node.cond)) - r.t = self.visit(node.t) - r.f = self.visit(node.f) - return r - - def visit_Case(self, node): - cases = dict((v, self.visit(statements)) for v, statements in node.cases.items()) - r = Case(self.visit(node.test), cases) - return r - - def visit_Fragment(self, node): - r = copy(node) - r.comb = self.visit(node.comb) - r.sync = self.visit(node.sync) - return r - - # NOTE: this will always return a list, even if node is a tuple - def visit_statements(self, node): - return [self.visit(statement) for statement in node] - - def visit_clock_domains(self, node): - return dict((clockname, self.visit(statements)) for clockname, statements in node.items()) - - def visit_ArrayProxy(self, node): - return _ArrayProxy([self.visit(choice) for choice in node.choices], - self.visit(node.key)) - - def visit_unknown(self, node): - return node + def visit(self, node): + if isinstance(node, (int, bool)): + return self.visit_constant(node) + elif isinstance(node, Signal): + return self.visit_Signal(node) + elif isinstance(node, ClockSignal): + return self.visit_ClockSignal(node) + elif isinstance(node, ResetSignal): + return self.visit_ResetSignal(node) + elif isinstance(node, _Operator): + return self.visit_Operator(node) + elif isinstance(node, _Slice): + return self.visit_Slice(node) + elif isinstance(node, Cat): + return self.visit_Cat(node) + elif isinstance(node, Replicate): + return self.visit_Replicate(node) + elif isinstance(node, _Assign): + return self.visit_Assign(node) + elif isinstance(node, If): + return self.visit_If(node) + elif isinstance(node, Case): + return self.visit_Case(node) + elif isinstance(node, _Fragment): + return self.visit_Fragment(node) + elif isinstance(node, (list, tuple)): + return self.visit_statements(node) + elif isinstance(node, dict): + return self.visit_clock_domains(node) + elif isinstance(node, _ArrayProxy): + return self.visit_ArrayProxy(node) + elif node is not None: + return self.visit_unknown(node) + else: + return None + + def visit_constant(self, node): + return node + + def visit_Signal(self, node): + return node + + def visit_ClockSignal(self, node): + return node + + def visit_ResetSignal(self, node): + return node + + def visit_Operator(self, node): + return _Operator(node.op, [self.visit(o) for o in node.operands]) + + def visit_Slice(self, node): + return _Slice(self.visit(node.value), node.start, node.stop) + + def visit_Cat(self, node): + return Cat(*[self.visit(e) for e in node.l]) + + def visit_Replicate(self, node): + return Replicate(self.visit(node.v), node.n) + + def visit_Assign(self, node): + return _Assign(self.visit(node.l), self.visit(node.r)) + + def visit_If(self, node): + r = If(self.visit(node.cond)) + r.t = self.visit(node.t) + r.f = self.visit(node.f) + return r + + def visit_Case(self, node): + cases = dict((v, self.visit(statements)) for v, statements in node.cases.items()) + r = Case(self.visit(node.test), cases) + return r + + def visit_Fragment(self, node): + r = copy(node) + r.comb = self.visit(node.comb) + r.sync = self.visit(node.sync) + return r + + # NOTE: this will always return a list, even if node is a tuple + def visit_statements(self, node): + return [self.visit(statement) for statement in node] + + def visit_clock_domains(self, node): + return dict((clockname, self.visit(statements)) for clockname, statements in node.items()) + + def visit_ArrayProxy(self, node): + return _ArrayProxy([self.visit(choice) for choice in node.choices], + self.visit(node.key)) + + def visit_unknown(self, node): + return node diff --git a/migen/flow/actor.py b/migen/flow/actor.py index 58ddcb40..a92d1aa9 100644 --- a/migen/flow/actor.py +++ b/migen/flow/actor.py @@ -4,171 +4,171 @@ 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 + 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 + 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) + 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) + def connect(self, sink): + return Record.connect(self, sink) class Sink(_Endpoint): - def connect(self, source): - return source.connect(self) + 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 + 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] + 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 __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") + 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) - ] + 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) - ] + 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.sop - eop = 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) - ] + 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.sop + eop = 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 index 2e90b9a9..d92afb41 100644 --- a/migen/flow/hooks.py +++ b/migen/flow/hooks.py @@ -4,39 +4,39 @@ from migen.fhdl.std import * from migen.flow.actor import * class EndpointSimHook(Module): - def __init__(self, endpoint): - self.endpoint = endpoint + def __init__(self, endpoint): + self.endpoint = endpoint - def on_ack(self): - pass + def on_ack(self): + pass - def on_nack(self): - pass + def on_nack(self): + pass - def on_inactive(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() + 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 + 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 index f657e9e4..2936aca5 100644 --- a/migen/flow/isd.py +++ b/migen/flow/isd.py @@ -5,65 +5,65 @@ from migen.flow.hooks import DFGHook ISD_MAGIC = 0x6ab4 class EndpointReporter(Module, AutoCSR): - def __init__(self, endpoint, nbits): - self.reset = Signal() - self.freeze = Signal() + 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) + 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) - ) - ] + 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() + 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()) + 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) - ] + 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 index 703475a6..9d02e470 100644 --- a/migen/flow/network.py +++ b/migen/flow/network.py @@ -10,317 +10,317 @@ from migen.flow import plumbing # 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() + def __init__(self): + MultiDiGraph.__init__(self) + self.elaborated = False + self.abstract_busy_signals = dict() + + def add_connection(self, source_node, sink_node, + source_ep=None, sink_ep=None, # default: assume nodes have 1 source/sink and use that one + source_subr=None, sink_subr=None): # default: use whole record + self.add_edge(source_node, sink_node, + source=source_ep, sink=sink_ep, + source_subr=source_subr, sink_subr=sink_subr) + + def add_buffered_connection(self, source_node, sink_node, + source_ep=None, sink_ep=None, + source_subr=None, sink_subr=None): + buf = AbstractActor(plumbing.Buffer) + self.add_connection(source_node, buf, source_ep=source_ep, source_subr=source_subr) + self.add_connection(buf, sink_node, sink_ep=sink_ep, sink_subr=sink_subr) + + def add_pipeline(self, *nodes): + for n1, n2 in zip(nodes, nodes[1:]): + self.add_connection(n1, n2) + + def del_connections(self, source_node, sink_node, data_requirements): + edges_to_delete = [] + edge_data = self.get_edge_data(source_node, sink_node) + if edge_data is None: + # the two nodes are already completely disconnected + return + for key, data in edge_data.items(): + if all(k not in data_requirements or data_requirements[k] == v + for k, v in data.items()): + edges_to_delete.append(key) + for key in edges_to_delete: + self.remove_edge(source_node, sink_node, key) + + def replace_actor(self, old, new): + self.add_node(new) + for xold, v, data in self.out_edges(old, data=True): + self.add_edge(new, v, **data) + for u, xold, data in self.in_edges(old, data=True): + self.add_edge(u, new, **data) + self.remove_node(old) + + def instantiate(self, actor): + inst = actor.create_instance() + self.abstract_busy_signals[id(inst)] = actor.busy + self.replace_actor(actor, inst) + + # Returns a dictionary + # source -> [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) + 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 index 6a7023e0..2132c2a0 100644 --- a/migen/flow/perftools.py +++ b/migen/flow/perftools.py @@ -1,52 +1,52 @@ from migen.flow.hooks import * class EndpointReporter(EndpointSimHook): - def __init__(self, endpoint): - EndpointSimHook.__init__(self, endpoint) - self.reset() + def __init__(self, endpoint): + EndpointSimHook.__init__(self, endpoint) + self.reset() - def reset(self): - self.inactive = 0 - self.ack = 0 - self.nack = 0 + 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 + # 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 + # 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 + # 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 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_ack(self): + self.ack += 1 - def on_nack(self): - self.nack += 1 + def on_nack(self): + self.nack += 1 - def on_inactive(self): - self.inactive += 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 + 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 index 6e4f81aa..5bfb4935 100644 --- a/migen/flow/plumbing.py +++ b/migen/flow/plumbing.py @@ -4,95 +4,95 @@ 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) - ) + 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() + 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] + 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() + 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]) + 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) + 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) + 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) + 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) + 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} diff --git a/migen/flow/transactions.py b/migen/flow/transactions.py index b9c1bc1d..342cad87 100644 --- a/migen/flow/transactions.py +++ b/migen/flow/transactions.py @@ -1,5 +1,5 @@ class Token: - def __init__(self, endpoint, value=None, idle_wait=False): - self.endpoint = endpoint - self.value = value - self.idle_wait = idle_wait + 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/cdc.py b/migen/genlib/cdc.py index dd5e6273..1b2dceb5 100644 --- a/migen/genlib/cdc.py +++ b/migen/genlib/cdc.py @@ -4,98 +4,98 @@ from migen.fhdl.specials import Special from migen.fhdl.tools import list_signals class NoRetiming(Special): - def __init__(self, reg): - Special.__init__(self) - self.reg = reg + def __init__(self, reg): + Special.__init__(self) + self.reg = reg - # do nothing - @staticmethod - def lower(dr): - return Module() + # do nothing + @staticmethod + def lower(dr): + return Module() class MultiRegImpl(Module): - def __init__(self, i, o, odomain, n): - self.i = i - self.o = o - self.odomain = odomain + def __init__(self, i, o, odomain, n): + self.i = i + self.o = o + self.odomain = odomain - w, signed = value_bits_sign(self.i) - self.regs = [Signal((w, signed)) for i in range(n)] + w, signed = value_bits_sign(self.i) + self.regs = [Signal((w, signed)) for i in range(n)] - ### + ### - src = self.i - for reg in self.regs: - sd = getattr(self.sync, self.odomain) - sd += reg.eq(src) - src = reg - self.comb += self.o.eq(src) - self.specials += [NoRetiming(reg) for reg in self.regs] + src = self.i + for reg in self.regs: + sd = getattr(self.sync, self.odomain) + sd += reg.eq(src) + src = reg + self.comb += self.o.eq(src) + self.specials += [NoRetiming(reg) for reg in self.regs] class MultiReg(Special): - def __init__(self, i, o, odomain="sys", n=2): - Special.__init__(self) - self.i = i - self.o = o - self.odomain = odomain - self.n = n - - def iter_expressions(self): - yield self, "i", SPECIAL_INPUT - yield self, "o", SPECIAL_OUTPUT - - def rename_clock_domain(self, old, new): - Special.rename_clock_domain(self, old, new) - if self.odomain == old: - self.odomain = new - - def list_clock_domains(self): - r = Special.list_clock_domains(self) - r.add(self.odomain) - return r - - @staticmethod - def lower(dr): - return MultiRegImpl(dr.i, dr.o, dr.odomain, dr.n) + def __init__(self, i, o, odomain="sys", n=2): + Special.__init__(self) + self.i = i + self.o = o + self.odomain = odomain + self.n = n + + def iter_expressions(self): + yield self, "i", SPECIAL_INPUT + yield self, "o", SPECIAL_OUTPUT + + def rename_clock_domain(self, old, new): + Special.rename_clock_domain(self, old, new) + if self.odomain == old: + self.odomain = new + + def list_clock_domains(self): + r = Special.list_clock_domains(self) + r.add(self.odomain) + return r + + @staticmethod + def lower(dr): + return MultiRegImpl(dr.i, dr.o, dr.odomain, dr.n) class PulseSynchronizer(Module): - def __init__(self, idomain, odomain): - self.i = Signal() - self.o = Signal() + def __init__(self, idomain, odomain): + self.i = Signal() + self.o = Signal() - ### + ### - toggle_i = Signal() - toggle_o = Signal() - toggle_o_r = Signal() + toggle_i = Signal() + toggle_o = Signal() + toggle_o_r = Signal() - sync_i = getattr(self.sync, idomain) - sync_o = getattr(self.sync, odomain) + sync_i = getattr(self.sync, idomain) + sync_o = getattr(self.sync, odomain) - sync_i += If(self.i, toggle_i.eq(~toggle_i)) - self.specials += MultiReg(toggle_i, toggle_o, odomain) - sync_o += toggle_o_r.eq(toggle_o) - self.comb += self.o.eq(toggle_o ^ toggle_o_r) + sync_i += If(self.i, toggle_i.eq(~toggle_i)) + self.specials += MultiReg(toggle_i, toggle_o, odomain) + sync_o += toggle_o_r.eq(toggle_o) + self.comb += self.o.eq(toggle_o ^ toggle_o_r) class GrayCounter(Module): - def __init__(self, width): - self.ce = Signal() - self.q = Signal(width) - self.q_next = Signal(width) - self.q_binary = Signal(width) - self.q_next_binary = Signal(width) - - ### - - self.comb += [ - If(self.ce, - self.q_next_binary.eq(self.q_binary + 1) - ).Else( - self.q_next_binary.eq(self.q_binary) - ), - self.q_next.eq(self.q_next_binary ^ self.q_next_binary[1:]) - ] - self.sync += [ - self.q_binary.eq(self.q_next_binary), - self.q.eq(self.q_next) - ] + def __init__(self, width): + self.ce = Signal() + self.q = Signal(width) + self.q_next = Signal(width) + self.q_binary = Signal(width) + self.q_next_binary = Signal(width) + + ### + + self.comb += [ + If(self.ce, + self.q_next_binary.eq(self.q_binary + 1) + ).Else( + self.q_next_binary.eq(self.q_binary) + ), + self.q_next.eq(self.q_next_binary ^ self.q_next_binary[1:]) + ] + self.sync += [ + self.q_binary.eq(self.q_next_binary), + self.q.eq(self.q_next) + ] diff --git a/migen/genlib/coding.py b/migen/genlib/coding.py index df89f6cc..c12b4066 100644 --- a/migen/genlib/coding.py +++ b/migen/genlib/coding.py @@ -5,89 +5,89 @@ Encoders and decoders between binary and one-hot representation """ class Encoder(Module): - """Encode one-hot to binary + """Encode one-hot to binary - If `n` is low, the `o` th bit in `i` is asserted, else none or - multiple bits are asserted. + If `n` is low, the `o` th bit in `i` is asserted, else none or + multiple bits are asserted. - Parameters - ---------- - width : int - Bit width of the input + Parameters + ---------- + width : int + Bit width of the input - Attributes - ---------- - i : Signal(width), in - One-hot input - o : Signal(max=width), out - Encoded binary - n : Signal(1), out - Invalid, either none or multiple input bits are asserted - """ - def __init__(self, width): - self.i = Signal(width) # one-hot - self.o = Signal(max=max(2, width)) # binary - self.n = Signal() # invalid: none or multiple - act = dict((1<> other, self.imag >> other) + 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 __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 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) + real = Signal(*args, **kwargs) + imag = Signal(*args, **kwargs) + return Complex(real, imag) diff --git a/migen/genlib/divider.py b/migen/genlib/divider.py index 12fcf53c..575cc4a4 100644 --- a/migen/genlib/divider.py +++ b/migen/genlib/divider.py @@ -1,38 +1,38 @@ from migen.fhdl.std import * class Divider(Module): - def __init__(self, w): - self.start_i = Signal() - self.dividend_i = Signal(w) - self.divisor_i = Signal(w) - self.ready_o = Signal() - self.quotient_o = Signal(w) - self.remainder_o = Signal(w) + def __init__(self, w): + self.start_i = Signal() + self.dividend_i = Signal(w) + self.divisor_i = Signal(w) + self.ready_o = Signal() + self.quotient_o = Signal(w) + self.remainder_o = Signal(w) - ### + ### - qr = Signal(2*w) - counter = Signal(max=w+1) - divisor_r = Signal(w) - diff = Signal(w+1) + qr = Signal(2*w) + counter = Signal(max=w+1) + divisor_r = Signal(w) + diff = Signal(w+1) - self.comb += [ - self.quotient_o.eq(qr[:w]), - self.remainder_o.eq(qr[w:]), - self.ready_o.eq(counter == 0), - diff.eq(qr[w-1:] - divisor_r) - ] - self.sync += [ - If(self.start_i, - counter.eq(w), - qr.eq(self.dividend_i), - divisor_r.eq(self.divisor_i) - ).Elif(~self.ready_o, - If(diff[w], - qr.eq(Cat(0, qr[:2*w-1])) - ).Else( - qr.eq(Cat(1, qr[:w-1], diff[:w])) - ), - counter.eq(counter - 1) - ) - ] + self.comb += [ + self.quotient_o.eq(qr[:w]), + self.remainder_o.eq(qr[w:]), + self.ready_o.eq(counter == 0), + diff.eq(qr[w-1:] - divisor_r) + ] + self.sync += [ + If(self.start_i, + counter.eq(w), + qr.eq(self.dividend_i), + divisor_r.eq(self.divisor_i) + ).Elif(~self.ready_o, + If(diff[w], + qr.eq(Cat(0, qr[:2*w-1])) + ).Else( + qr.eq(Cat(1, qr[:w-1], diff[:w])) + ), + counter.eq(counter - 1) + ) + ] diff --git a/migen/genlib/fifo.py b/migen/genlib/fifo.py index 548c3add..f976cdfe 100644 --- a/migen/genlib/fifo.py +++ b/migen/genlib/fifo.py @@ -3,216 +3,216 @@ from migen.genlib.cdc import NoRetiming, MultiReg, GrayCounter from migen.genlib.record import layout_len, Record def _inc(signal, modulo): - if modulo == 2**flen(signal): - return signal.eq(signal + 1) - else: - return If(signal == (modulo - 1), - signal.eq(0) - ).Else( - signal.eq(signal + 1) - ) + if modulo == 2**flen(signal): + return signal.eq(signal + 1) + else: + return If(signal == (modulo - 1), + signal.eq(0) + ).Else( + signal.eq(signal + 1) + ) class _FIFOInterface: - """ - Data written to the input interface (`din`, `we`, `writable`) is - buffered and can be read at the output interface (`dout`, `re`, - `readable`). The data entry written first to the input - also appears first on the output. - - Parameters - ---------- - width_or_layout : int, layout - Bit width or `Record` layout for the data. - depth : int - Depth of the FIFO. - - Attributes - ---------- - din : in, width_or_layout - Input data either flat or Record structured. - writable : out - There is space in the FIFO and `we` can be asserted to load new data. - we : in - Write enable signal to latch `din` into the FIFO. Does nothing if - `writable` is not asserted. - dout : out, width_or_layout - Output data, same type as `din`. Only valid if `readable` is - asserted. - readable : out - Output data `dout` valid, FIFO not empty. - re : in - Acknowledge `dout`. If asserted, the next entry will be - available on the next cycle (if `readable` is high then). - """ - def __init__(self, width_or_layout, depth): - self.we = Signal() - self.writable = Signal() # not full - self.re = Signal() - self.readable = Signal() # not empty - - if isinstance(width_or_layout, list): - self.din = Record(width_or_layout) - self.dout = Record(width_or_layout) - self.din_bits = self.din.raw_bits() - self.dout_bits = self.dout.raw_bits() - self.width = layout_len(width_or_layout) - else: - self.din = Signal(width_or_layout) - self.dout = Signal(width_or_layout) - self.din_bits = self.din - self.dout_bits = self.dout - self.width = width_or_layout + """ + Data written to the input interface (`din`, `we`, `writable`) is + buffered and can be read at the output interface (`dout`, `re`, + `readable`). The data entry written first to the input + also appears first on the output. + + Parameters + ---------- + width_or_layout : int, layout + Bit width or `Record` layout for the data. + depth : int + Depth of the FIFO. + + Attributes + ---------- + din : in, width_or_layout + Input data either flat or Record structured. + writable : out + There is space in the FIFO and `we` can be asserted to load new data. + we : in + Write enable signal to latch `din` into the FIFO. Does nothing if + `writable` is not asserted. + dout : out, width_or_layout + Output data, same type as `din`. Only valid if `readable` is + asserted. + readable : out + Output data `dout` valid, FIFO not empty. + re : in + Acknowledge `dout`. If asserted, the next entry will be + available on the next cycle (if `readable` is high then). + """ + def __init__(self, width_or_layout, depth): + self.we = Signal() + self.writable = Signal() # not full + self.re = Signal() + self.readable = Signal() # not empty + + if isinstance(width_or_layout, list): + self.din = Record(width_or_layout) + self.dout = Record(width_or_layout) + self.din_bits = self.din.raw_bits() + self.dout_bits = self.dout.raw_bits() + self.width = layout_len(width_or_layout) + else: + self.din = Signal(width_or_layout) + self.dout = Signal(width_or_layout) + self.din_bits = self.din + self.dout_bits = self.dout + self.width = width_or_layout class SyncFIFO(Module, _FIFOInterface): - """Synchronous FIFO (first in, first out) - - Read and write interfaces are accessed from the same clock domain. - If different clock domains are needed, use :class:`AsyncFIFO`. - - {interface} - level : out - Number of unread entries. - replace : in - Replaces the last entry written into the FIFO with `din`. Does nothing - if that entry has already been read (i.e. the FIFO is empty). - Assert in conjunction with `we`. - """ - __doc__ = __doc__.format(interface=_FIFOInterface.__doc__) - - def __init__(self, width_or_layout, depth, fwft=True): - _FIFOInterface.__init__(self, width_or_layout, depth) - - self.level = Signal(max=depth+1) - self.replace = Signal() - - ### - - produce = Signal(max=depth) - consume = Signal(max=depth) - storage = Memory(self.width, depth) - self.specials += storage - - wrport = storage.get_port(write_capable=True) - self.specials += wrport - self.comb += [ - If(self.replace, - wrport.adr.eq(produce-1) - ).Else( - wrport.adr.eq(produce) - ), - wrport.dat_w.eq(self.din_bits), - wrport.we.eq(self.we & (self.writable | self.replace)) - ] - self.sync += If(self.we & self.writable & ~self.replace, - _inc(produce, depth)) - - do_read = Signal() - self.comb += do_read.eq(self.readable & self.re) - - rdport = storage.get_port(async_read=fwft, has_re=not fwft) - self.specials += rdport - self.comb += [ - rdport.adr.eq(consume), - self.dout_bits.eq(rdport.dat_r) - ] - if not fwft: - self.comb += rdport.re.eq(do_read) - self.sync += If(do_read, _inc(consume, depth)) - - self.sync += \ - If(self.we & self.writable & ~self.replace, - If(~do_read, self.level.eq(self.level + 1)) - ).Elif(do_read, - self.level.eq(self.level - 1) - ) - self.comb += [ - self.writable.eq(self.level != depth), - self.readable.eq(self.level != 0) - ] + """Synchronous FIFO (first in, first out) + + Read and write interfaces are accessed from the same clock domain. + If different clock domains are needed, use :class:`AsyncFIFO`. + + {interface} + level : out + Number of unread entries. + replace : in + Replaces the last entry written into the FIFO with `din`. Does nothing + if that entry has already been read (i.e. the FIFO is empty). + Assert in conjunction with `we`. + """ + __doc__ = __doc__.format(interface=_FIFOInterface.__doc__) + + def __init__(self, width_or_layout, depth, fwft=True): + _FIFOInterface.__init__(self, width_or_layout, depth) + + self.level = Signal(max=depth+1) + self.replace = Signal() + + ### + + produce = Signal(max=depth) + consume = Signal(max=depth) + storage = Memory(self.width, depth) + self.specials += storage + + wrport = storage.get_port(write_capable=True) + self.specials += wrport + self.comb += [ + If(self.replace, + wrport.adr.eq(produce-1) + ).Else( + wrport.adr.eq(produce) + ), + wrport.dat_w.eq(self.din_bits), + wrport.we.eq(self.we & (self.writable | self.replace)) + ] + self.sync += If(self.we & self.writable & ~self.replace, + _inc(produce, depth)) + + do_read = Signal() + self.comb += do_read.eq(self.readable & self.re) + + rdport = storage.get_port(async_read=fwft, has_re=not fwft) + self.specials += rdport + self.comb += [ + rdport.adr.eq(consume), + self.dout_bits.eq(rdport.dat_r) + ] + if not fwft: + self.comb += rdport.re.eq(do_read) + self.sync += If(do_read, _inc(consume, depth)) + + self.sync += \ + If(self.we & self.writable & ~self.replace, + If(~do_read, self.level.eq(self.level + 1)) + ).Elif(do_read, + self.level.eq(self.level - 1) + ) + self.comb += [ + self.writable.eq(self.level != depth), + self.readable.eq(self.level != 0) + ] class SyncFIFOBuffered(Module, _FIFOInterface): - def __init__(self, width_or_layout, depth): - _FIFOInterface.__init__(self, width_or_layout, depth) - self.submodules.fifo = fifo = SyncFIFO(width_or_layout, depth, False) - - self.writable = fifo.writable - self.din_bits = fifo.din_bits - self.din = fifo.din - self.we = fifo.we - self.dout_bits = fifo.dout_bits - self.dout = fifo.dout - self.level = Signal(max=depth+2) - - ### - - self.comb += fifo.re.eq(fifo.readable & (~self.readable | self.re)) - self.sync += \ - If(fifo.re, - self.readable.eq(1), - ).Elif(self.re, - self.readable.eq(0), - ) - self.comb += self.level.eq(fifo.level + self.readable) + def __init__(self, width_or_layout, depth): + _FIFOInterface.__init__(self, width_or_layout, depth) + self.submodules.fifo = fifo = SyncFIFO(width_or_layout, depth, False) + + self.writable = fifo.writable + self.din_bits = fifo.din_bits + self.din = fifo.din + self.we = fifo.we + self.dout_bits = fifo.dout_bits + self.dout = fifo.dout + self.level = Signal(max=depth+2) + + ### + + self.comb += fifo.re.eq(fifo.readable & (~self.readable | self.re)) + self.sync += \ + If(fifo.re, + self.readable.eq(1), + ).Elif(self.re, + self.readable.eq(0), + ) + self.comb += self.level.eq(fifo.level + self.readable) class AsyncFIFO(Module, _FIFOInterface): - """Asynchronous FIFO (first in, first out) - - Read and write interfaces are accessed from different clock domains, - named `read` and `write`. Use `ClockDomainsRenamer` to rename to - other names. - - {interface} - """ - __doc__ = __doc__.format(interface=_FIFOInterface.__doc__) - - def __init__(self, width_or_layout, depth): - _FIFOInterface.__init__(self, width_or_layout, depth) - - ### - - depth_bits = log2_int(depth, True) - - produce = ClockDomainsRenamer("write")(GrayCounter(depth_bits+1)) - consume = ClockDomainsRenamer("read")(GrayCounter(depth_bits+1)) - self.submodules += produce, consume - self.comb += [ - produce.ce.eq(self.writable & self.we), - consume.ce.eq(self.readable & self.re) - ] - - produce_rdomain = Signal(depth_bits+1) - self.specials += [ - NoRetiming(produce.q), - MultiReg(produce.q, produce_rdomain, "read") - ] - consume_wdomain = Signal(depth_bits+1) - self.specials += [ - NoRetiming(consume.q), - MultiReg(consume.q, consume_wdomain, "write") - ] - if depth_bits == 1: - self.comb += self.writable.eq((produce.q[-1] == consume_wdomain[-1]) - | (produce.q[-2] == consume_wdomain[-2])) - else: - self.comb += [ - self.writable.eq((produce.q[-1] == consume_wdomain[-1]) - | (produce.q[-2] == consume_wdomain[-2]) - | (produce.q[:-2] != consume_wdomain[:-2])) - ] - self.comb += self.readable.eq(consume.q != produce_rdomain) - - storage = Memory(self.width, depth) - self.specials += storage - wrport = storage.get_port(write_capable=True, clock_domain="write") - self.specials += wrport - self.comb += [ - wrport.adr.eq(produce.q_binary[:-1]), - wrport.dat_w.eq(self.din_bits), - wrport.we.eq(produce.ce) - ] - rdport = storage.get_port(clock_domain="read") - self.specials += rdport - self.comb += [ - rdport.adr.eq(consume.q_next_binary[:-1]), - self.dout_bits.eq(rdport.dat_r) - ] + """Asynchronous FIFO (first in, first out) + + Read and write interfaces are accessed from different clock domains, + named `read` and `write`. Use `ClockDomainsRenamer` to rename to + other names. + + {interface} + """ + __doc__ = __doc__.format(interface=_FIFOInterface.__doc__) + + def __init__(self, width_or_layout, depth): + _FIFOInterface.__init__(self, width_or_layout, depth) + + ### + + depth_bits = log2_int(depth, True) + + produce = ClockDomainsRenamer("write")(GrayCounter(depth_bits+1)) + consume = ClockDomainsRenamer("read")(GrayCounter(depth_bits+1)) + self.submodules += produce, consume + self.comb += [ + produce.ce.eq(self.writable & self.we), + consume.ce.eq(self.readable & self.re) + ] + + produce_rdomain = Signal(depth_bits+1) + self.specials += [ + NoRetiming(produce.q), + MultiReg(produce.q, produce_rdomain, "read") + ] + consume_wdomain = Signal(depth_bits+1) + self.specials += [ + NoRetiming(consume.q), + MultiReg(consume.q, consume_wdomain, "write") + ] + if depth_bits == 1: + self.comb += self.writable.eq((produce.q[-1] == consume_wdomain[-1]) + | (produce.q[-2] == consume_wdomain[-2])) + else: + self.comb += [ + self.writable.eq((produce.q[-1] == consume_wdomain[-1]) + | (produce.q[-2] == consume_wdomain[-2]) + | (produce.q[:-2] != consume_wdomain[:-2])) + ] + self.comb += self.readable.eq(consume.q != produce_rdomain) + + storage = Memory(self.width, depth) + self.specials += storage + wrport = storage.get_port(write_capable=True, clock_domain="write") + self.specials += wrport + self.comb += [ + wrport.adr.eq(produce.q_binary[:-1]), + wrport.dat_w.eq(self.din_bits), + wrport.we.eq(produce.ce) + ] + rdport = storage.get_port(clock_domain="read") + self.specials += rdport + self.comb += [ + rdport.adr.eq(consume.q_next_binary[:-1]), + self.dout_bits.eq(rdport.dat_r) + ] diff --git a/migen/genlib/fsm.py b/migen/genlib/fsm.py index 44a1be39..dbadfd70 100644 --- a/migen/genlib/fsm.py +++ b/migen/genlib/fsm.py @@ -6,134 +6,134 @@ from migen.fhdl.visit import NodeTransformer from migen.fhdl.bitcontainer import value_bits_sign class AnonymousState: - pass + pass # do not use namedtuple here as it inherits tuple # and the latter is used elsewhere in FHDL class NextState: - def __init__(self, state): - self.state = state + def __init__(self, state): + self.state = state class NextValue: - def __init__(self, register, value): - self.register = register - self.value = value + def __init__(self, register, value): + self.register = register + self.value = value class _LowerNext(NodeTransformer): - def __init__(self, next_state_signal, encoding, aliases): - self.next_state_signal = next_state_signal - self.encoding = encoding - self.aliases = aliases - # register -> next_value_ce, next_value - self.registers = OrderedDict() - - def visit_unknown(self, node): - if isinstance(node, NextState): - try: - actual_state = self.aliases[node.state] - except KeyError: - actual_state = node.state - return self.next_state_signal.eq(self.encoding[actual_state]) - elif isinstance(node, NextValue): - try: - next_value_ce, next_value = self.registers[node.register] - except KeyError: - related = node.register if isinstance(node.register, Signal) else None - next_value = Signal(bits_sign=value_bits_sign(node.register), related=related) - next_value_ce = Signal(related=related) - self.registers[node.register] = next_value_ce, next_value - return next_value.eq(node.value), next_value_ce.eq(1) - else: - return node + def __init__(self, next_state_signal, encoding, aliases): + self.next_state_signal = next_state_signal + self.encoding = encoding + self.aliases = aliases + # register -> next_value_ce, next_value + self.registers = OrderedDict() + + def visit_unknown(self, node): + if isinstance(node, NextState): + try: + actual_state = self.aliases[node.state] + except KeyError: + actual_state = node.state + return self.next_state_signal.eq(self.encoding[actual_state]) + elif isinstance(node, NextValue): + try: + next_value_ce, next_value = self.registers[node.register] + except KeyError: + related = node.register if isinstance(node.register, Signal) else None + next_value = Signal(bits_sign=value_bits_sign(node.register), related=related) + next_value_ce = Signal(related=related) + self.registers[node.register] = next_value_ce, next_value + return next_value.eq(node.value), next_value_ce.eq(1) + else: + return node class FSM(Module): - def __init__(self, reset_state=None): - self.actions = OrderedDict() - self.state_aliases = dict() - self.reset_state = reset_state - - self.before_entering_signals = OrderedDict() - self.before_leaving_signals = OrderedDict() - self.after_entering_signals = OrderedDict() - self.after_leaving_signals = OrderedDict() - - def act(self, state, *statements): - if self.finalized: - raise FinalizeError - if self.reset_state is None: - self.reset_state = state - if state not in self.actions: - self.actions[state] = [] - self.actions[state] += statements - - def delayed_enter(self, name, target, delay): - if self.finalized: - raise FinalizeError - if delay: - state = name - for i in range(delay): - if i == delay - 1: - next_state = target - else: - next_state = AnonymousState() - self.act(state, NextState(next_state)) - state = next_state - else: - self.state_aliases[name] = target - - def ongoing(self, state): - is_ongoing = Signal() - self.act(state, is_ongoing.eq(1)) - return is_ongoing - - def _get_signal(self, d, state): - if state not in self.actions: - self.actions[state] = [] - try: - return d[state] - except KeyError: - is_el = Signal() - d[state] = is_el - return is_el - - def before_entering(self, state): - return self._get_signal(self.before_entering_signals, state) - - def before_leaving(self, state): - return self._get_signal(self.before_leaving_signals, state) - - def after_entering(self, state): - signal = self._get_signal(self.after_entering_signals, state) - self.sync += signal.eq(self.before_entering(state)) - return signal - - def after_leaving(self, state): - signal = self._get_signal(self.after_leaving_signals, state) - self.sync += signal.eq(self.before_leaving(state)) - return signal - - def do_finalize(self): - nstates = len(self.actions) - self.encoding = dict((s, n) for n, s in enumerate(self.actions.keys())) - self.state = Signal(max=nstates, reset=self.encoding[self.reset_state]) - self.next_state = Signal(max=nstates) - - ln = _LowerNext(self.next_state, self.encoding, self.state_aliases) - cases = dict((self.encoding[k], ln.visit(v)) for k, v in self.actions.items() if v) - self.comb += [ - self.next_state.eq(self.state), - Case(self.state, cases).makedefault(self.encoding[self.reset_state]) - ] - self.sync += self.state.eq(self.next_state) - for register, (next_value_ce, next_value) in ln.registers.items(): - self.sync += If(next_value_ce, register.eq(next_value)) - - # drive entering/leaving signals - for state, signal in self.before_leaving_signals.items(): - encoded = self.encoding[state] - self.comb += signal.eq((self.state == encoded) & ~(self.next_state == encoded)) - if self.reset_state in self.after_entering_signals: - self.after_entering_signals[self.reset_state].reset = 1 - for state, signal in self.before_entering_signals.items(): - encoded = self.encoding[state] - self.comb += signal.eq(~(self.state == encoded) & (self.next_state == encoded)) + def __init__(self, reset_state=None): + self.actions = OrderedDict() + self.state_aliases = dict() + self.reset_state = reset_state + + self.before_entering_signals = OrderedDict() + self.before_leaving_signals = OrderedDict() + self.after_entering_signals = OrderedDict() + self.after_leaving_signals = OrderedDict() + + def act(self, state, *statements): + if self.finalized: + raise FinalizeError + if self.reset_state is None: + self.reset_state = state + if state not in self.actions: + self.actions[state] = [] + self.actions[state] += statements + + def delayed_enter(self, name, target, delay): + if self.finalized: + raise FinalizeError + if delay: + state = name + for i in range(delay): + if i == delay - 1: + next_state = target + else: + next_state = AnonymousState() + self.act(state, NextState(next_state)) + state = next_state + else: + self.state_aliases[name] = target + + def ongoing(self, state): + is_ongoing = Signal() + self.act(state, is_ongoing.eq(1)) + return is_ongoing + + def _get_signal(self, d, state): + if state not in self.actions: + self.actions[state] = [] + try: + return d[state] + except KeyError: + is_el = Signal() + d[state] = is_el + return is_el + + def before_entering(self, state): + return self._get_signal(self.before_entering_signals, state) + + def before_leaving(self, state): + return self._get_signal(self.before_leaving_signals, state) + + def after_entering(self, state): + signal = self._get_signal(self.after_entering_signals, state) + self.sync += signal.eq(self.before_entering(state)) + return signal + + def after_leaving(self, state): + signal = self._get_signal(self.after_leaving_signals, state) + self.sync += signal.eq(self.before_leaving(state)) + return signal + + def do_finalize(self): + nstates = len(self.actions) + self.encoding = dict((s, n) for n, s in enumerate(self.actions.keys())) + self.state = Signal(max=nstates, reset=self.encoding[self.reset_state]) + self.next_state = Signal(max=nstates) + + ln = _LowerNext(self.next_state, self.encoding, self.state_aliases) + cases = dict((self.encoding[k], ln.visit(v)) for k, v in self.actions.items() if v) + self.comb += [ + self.next_state.eq(self.state), + Case(self.state, cases).makedefault(self.encoding[self.reset_state]) + ] + self.sync += self.state.eq(self.next_state) + for register, (next_value_ce, next_value) in ln.registers.items(): + self.sync += If(next_value_ce, register.eq(next_value)) + + # drive entering/leaving signals + for state, signal in self.before_leaving_signals.items(): + encoded = self.encoding[state] + self.comb += signal.eq((self.state == encoded) & ~(self.next_state == encoded)) + if self.reset_state in self.after_entering_signals: + self.after_entering_signals[self.reset_state].reset = 1 + for state, signal in self.before_entering_signals.items(): + encoded = self.encoding[state] + self.comb += signal.eq(~(self.state == encoded) & (self.next_state == encoded)) diff --git a/migen/genlib/io.py b/migen/genlib/io.py index ab8cc9bf..da0b1cd5 100644 --- a/migen/genlib/io.py +++ b/migen/genlib/io.py @@ -3,89 +3,89 @@ from migen.fhdl.specials import Special from migen.fhdl.tools import list_signals class DifferentialInput(Special): - def __init__(self, i_p, i_n, o): - Special.__init__(self) - self.i_p = i_p - self.i_n = i_n - self.o = o + def __init__(self, i_p, i_n, o): + Special.__init__(self) + self.i_p = i_p + self.i_n = i_n + self.o = o - def iter_expressions(self): - yield self, "i_p", SPECIAL_INPUT - yield self, "i_n", SPECIAL_INPUT - yield self, "o", SPECIAL_OUTPUT + def iter_expressions(self): + yield self, "i_p", SPECIAL_INPUT + yield self, "i_n", SPECIAL_INPUT + yield self, "o", SPECIAL_OUTPUT - @staticmethod - def lower(dr): - raise NotImplementedError("Attempted to use a differential input, but platform does not support them") + @staticmethod + def lower(dr): + raise NotImplementedError("Attempted to use a differential input, but platform does not support them") class DifferentialOutput(Special): - def __init__(self, i, o_p, o_n): - Special.__init__(self) - self.i = i - self.o_p = o_p - self.o_n = o_n + def __init__(self, i, o_p, o_n): + Special.__init__(self) + self.i = i + self.o_p = o_p + self.o_n = o_n - def iter_expressions(self): - yield self, "i", SPECIAL_INPUT - yield self, "o_p", SPECIAL_OUTPUT - yield self, "o_n", SPECIAL_OUTPUT + def iter_expressions(self): + yield self, "i", SPECIAL_INPUT + yield self, "o_p", SPECIAL_OUTPUT + yield self, "o_n", SPECIAL_OUTPUT - @staticmethod - def lower(dr): - raise NotImplementedError("Attempted to use a differential output, but platform does not support them") + @staticmethod + def lower(dr): + raise NotImplementedError("Attempted to use a differential output, but platform does not support them") class CRG(Module): - def __init__(self, clk, rst=0): - self.clock_domains.cd_sys = ClockDomain() - self.clock_domains.cd_por = ClockDomain(reset_less=True) - - if hasattr(clk, "p"): - clk_se = Signal() - self.specials += DifferentialInput(clk.p, clk.n, clk_se) - clk = clk_se - - # Power on Reset (vendor agnostic) - rst_n = Signal() - self.sync.por += rst_n.eq(1 & ~rst) - self.comb += [ - self.cd_sys.clk.eq(clk), - self.cd_por.clk.eq(clk), - self.cd_sys.rst.eq(~rst_n) - ] + def __init__(self, clk, rst=0): + self.clock_domains.cd_sys = ClockDomain() + self.clock_domains.cd_por = ClockDomain(reset_less=True) + + if hasattr(clk, "p"): + clk_se = Signal() + self.specials += DifferentialInput(clk.p, clk.n, clk_se) + clk = clk_se + + # Power on Reset (vendor agnostic) + rst_n = Signal() + self.sync.por += rst_n.eq(1 & ~rst) + self.comb += [ + self.cd_sys.clk.eq(clk), + self.cd_por.clk.eq(clk), + self.cd_sys.rst.eq(~rst_n) + ] class DDRInput(Special): - def __init__(self, i, o1, o2, clk=ClockSignal()): - Special.__init__(self) - self.i = i - self.o1 = o1 - self.o2 = o2 - self.clk = clk - - def iter_expressions(self): - yield self, "i", SPECIAL_INPUT - yield self, "o1", SPECIAL_OUTPUT - yield self, "o2", SPECIAL_OUTPUT - yield self, "clk", SPECIAL_INPUT - - @staticmethod - def lower(dr): - raise NotImplementedError("Attempted to use a DDR input, but platform does not support them") + def __init__(self, i, o1, o2, clk=ClockSignal()): + Special.__init__(self) + self.i = i + self.o1 = o1 + self.o2 = o2 + self.clk = clk + + def iter_expressions(self): + yield self, "i", SPECIAL_INPUT + yield self, "o1", SPECIAL_OUTPUT + yield self, "o2", SPECIAL_OUTPUT + yield self, "clk", SPECIAL_INPUT + + @staticmethod + def lower(dr): + raise NotImplementedError("Attempted to use a DDR input, but platform does not support them") class DDROutput(Special): - def __init__(self, i1, i2, o, clk=ClockSignal()): - Special.__init__(self) - self.i1 = i1 - self.i2 = i2 - self.o = o - self.clk = clk - - def iter_expressions(self): - yield self, "i1", SPECIAL_INPUT - yield self, "i2", SPECIAL_INPUT - yield self, "o", SPECIAL_OUTPUT - yield self, "clk", SPECIAL_INPUT - - @staticmethod - def lower(dr): - raise NotImplementedError("Attempted to use a DDR output, but platform does not support them") + def __init__(self, i1, i2, o, clk=ClockSignal()): + Special.__init__(self) + self.i1 = i1 + self.i2 = i2 + self.o = o + self.clk = clk + + def iter_expressions(self): + yield self, "i1", SPECIAL_INPUT + yield self, "i2", SPECIAL_INPUT + yield self, "o", SPECIAL_OUTPUT + yield self, "clk", SPECIAL_INPUT + + @staticmethod + def lower(dr): + raise NotImplementedError("Attempted to use a DDR output, but platform does not support them") diff --git a/migen/genlib/mhamgen.py b/migen/genlib/mhamgen.py index 6f38ba97..958851b9 100644 --- a/migen/genlib/mhamgen.py +++ b/migen/genlib/mhamgen.py @@ -30,114 +30,114 @@ 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 + 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)) + 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 + m = 1 + c = 0 - while c < data_bits: - m += 1 - c = 2**m - m - 1 - return m + 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 + 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 + 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:]) + 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. @@ -156,14 +156,14 @@ def xor_tree(in_signal, in_bits): # 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) + 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])) + 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 @@ -183,50 +183,50 @@ class HammingGenerator(Module): # 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)) + 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/misc.py b/migen/genlib/misc.py index b505032e..89ea0380 100644 --- a/migen/genlib/misc.py +++ b/migen/genlib/misc.py @@ -2,112 +2,112 @@ from migen.fhdl.std import * from migen.fhdl.structure import _Operator def optree(op, operands, lb=None, ub=None, default=None): - if lb is None: - lb = 0 - if ub is None: - ub = len(operands) - l = ub - lb - if l == 0: - if default is None: - raise AttributeError - else: - return default - elif l == 1: - return operands[lb] - else: - s = lb + l//2 - return _Operator(op, - [optree(op, operands, lb, s, default), - optree(op, operands, s, ub, default)]) + if lb is None: + lb = 0 + if ub is None: + ub = len(operands) + l = ub - lb + if l == 0: + if default is None: + raise AttributeError + else: + return default + elif l == 1: + return operands[lb] + else: + s = lb + l//2 + return _Operator(op, + [optree(op, operands, lb, s, default), + optree(op, operands, s, ub, default)]) def split(v, *counts): - r = [] - offset = 0 - for n in counts: - if n != 0: - r.append(v[offset:offset+n]) - else: - r.append(None) - offset += n - return tuple(r) + r = [] + offset = 0 + for n in counts: + if n != 0: + r.append(v[offset:offset+n]) + else: + r.append(None) + offset += n + return tuple(r) def displacer(signal, shift, output, n=None, reverse=False): - if shift is None: - return output.eq(signal) - if n is None: - n = 2**flen(shift) - w = flen(signal) - if reverse: - r = reversed(range(n)) - else: - r = range(n) - l = [Replicate(shift == i, w) & signal for i in r] - return output.eq(Cat(*l)) + if shift is None: + return output.eq(signal) + if n is None: + n = 2**flen(shift) + w = flen(signal) + if reverse: + r = reversed(range(n)) + else: + r = range(n) + l = [Replicate(shift == i, w) & signal for i in r] + return output.eq(Cat(*l)) def chooser(signal, shift, output, n=None, reverse=False): - if shift is None: - return output.eq(signal) - if n is None: - n = 2**flen(shift) - w = flen(output) - cases = {} - for i in range(n): - if reverse: - s = n - i - 1 - else: - s = i - cases[i] = [output.eq(signal[s*w:(s+1)*w])] - return Case(shift, cases).makedefault() + if shift is None: + return output.eq(signal) + if n is None: + n = 2**flen(shift) + w = flen(output) + cases = {} + for i in range(n): + if reverse: + s = n - i - 1 + else: + s = i + cases[i] = [output.eq(signal[s*w:(s+1)*w])] + return Case(shift, cases).makedefault() def timeline(trigger, events): - lastevent = max([e[0] for e in events]) - counter = Signal(max=lastevent+1) + lastevent = max([e[0] for e in events]) + counter = Signal(max=lastevent+1) - counterlogic = If(counter != 0, - counter.eq(counter + 1) - ).Elif(trigger, - counter.eq(1) - ) - # insert counter reset if it doesn't naturally overflow - # (test if lastevent+1 is a power of 2) - if (lastevent & (lastevent + 1)) != 0: - counterlogic = If(counter == lastevent, - counter.eq(0) - ).Else( - counterlogic - ) + counterlogic = If(counter != 0, + counter.eq(counter + 1) + ).Elif(trigger, + counter.eq(1) + ) + # insert counter reset if it doesn't naturally overflow + # (test if lastevent+1 is a power of 2) + if (lastevent & (lastevent + 1)) != 0: + counterlogic = If(counter == lastevent, + counter.eq(0) + ).Else( + counterlogic + ) - def get_cond(e): - if e[0] == 0: - return trigger & (counter == 0) - else: - return counter == e[0] - sync = [If(get_cond(e), *e[1]) for e in events] - sync.append(counterlogic) - return sync + def get_cond(e): + if e[0] == 0: + return trigger & (counter == 0) + else: + return counter == e[0] + sync = [If(get_cond(e), *e[1]) for e in events] + sync.append(counterlogic) + return sync @ResetInserter() @CEInserter() class FlipFlop(Module): - def __init__(self, *args, **kwargs): - self.d = Signal(*args, **kwargs) - self.q = Signal(*args, **kwargs) - self.sync += self.q.eq(self.d) + def __init__(self, *args, **kwargs): + self.d = Signal(*args, **kwargs) + self.q = Signal(*args, **kwargs) + self.sync += self.q.eq(self.d) @ResetInserter() @CEInserter() class Counter(Module): - def __init__(self, *args, increment=1, **kwargs): - self.value = Signal(*args, **kwargs) - self.width = flen(self.value) - self.sync += self.value.eq(self.value+increment) + def __init__(self, *args, increment=1, **kwargs): + self.value = Signal(*args, **kwargs) + self.width = flen(self.value) + self.sync += self.value.eq(self.value+increment) @ResetInserter() @CEInserter() class Timeout(Module): - def __init__(self, length): - self.reached = Signal() - ### - value = Signal(max=length) - self.sync += If(~self.reached, value.eq(value+1)) - self.comb += self.reached.eq(value == (length-1)) + def __init__(self, length): + self.reached = Signal() + ### + value = Signal(max=length) + self.sync += If(~self.reached, value.eq(value+1)) + self.comb += self.reached.eq(value == (length-1)) diff --git a/migen/genlib/record.py b/migen/genlib/record.py index 48b5c019..084ba9ce 100644 --- a/migen/genlib/record.py +++ b/migen/genlib/record.py @@ -12,157 +12,157 @@ from migen.genlib.misc import optree # sublayout must be a list def set_layout_parameters(layout, **layout_dict): - def resolve(p): - if isinstance(p, str): - try: - return layout_dict[p] - except KeyError: - return p - else: - return p - - r = [] - for f in layout: - if isinstance(f[1], (int, tuple, str)): # cases 1/2 - if len(f) == 3: - r.append((f[0], resolve(f[1]), f[2])) - else: - r.append((f[0], resolve(f[1]))) - elif isinstance(f[1], list): # case 3 - r.append((f[0], set_layout_parameters(f[1], **layout_dict))) - else: - raise TypeError - return r + def resolve(p): + if isinstance(p, str): + try: + return layout_dict[p] + except KeyError: + return p + else: + return p + + r = [] + for f in layout: + if isinstance(f[1], (int, tuple, str)): # cases 1/2 + if len(f) == 3: + r.append((f[0], resolve(f[1]), f[2])) + else: + r.append((f[0], resolve(f[1]))) + elif isinstance(f[1], list): # case 3 + r.append((f[0], set_layout_parameters(f[1], **layout_dict))) + else: + raise TypeError + return r def layout_len(layout): - r = 0 - for f in layout: - if isinstance(f[1], (int, tuple)): # cases 1/2 - if len(f) == 3: - fname, fsize, fdirection = f - else: - fname, fsize = f - elif isinstance(f[1], list): # case 3 - fname, fsublayout = f - fsize = layout_len(fsublayout) - else: - raise TypeError - if isinstance(fsize, tuple): - r += fsize[0] - else: - r += fsize - return r + r = 0 + for f in layout: + if isinstance(f[1], (int, tuple)): # cases 1/2 + if len(f) == 3: + fname, fsize, fdirection = f + else: + fname, fsize = f + elif isinstance(f[1], list): # case 3 + fname, fsublayout = f + fsize = layout_len(fsublayout) + else: + raise TypeError + if isinstance(fsize, tuple): + r += fsize[0] + else: + r += fsize + return r def layout_get(layout, name): - for f in layout: - if f[0] == name: - return f - raise KeyError(name) + for f in layout: + if f[0] == name: + return f + raise KeyError(name) def layout_partial(layout, *elements): - r = [] - for path in elements: - path_s = path.split("/") - last = path_s.pop() - copy_ref = layout - insert_ref = r - for hop in path_s: - name, copy_ref = layout_get(copy_ref, hop) - try: - name, insert_ref = layout_get(insert_ref, hop) - except KeyError: - new_insert_ref = [] - insert_ref.append((hop, new_insert_ref)) - insert_ref = new_insert_ref - insert_ref.append(layout_get(copy_ref, last)) - return r + r = [] + for path in elements: + path_s = path.split("/") + last = path_s.pop() + copy_ref = layout + insert_ref = r + for hop in path_s: + name, copy_ref = layout_get(copy_ref, hop) + try: + name, insert_ref = layout_get(insert_ref, hop) + except KeyError: + new_insert_ref = [] + insert_ref.append((hop, new_insert_ref)) + insert_ref = new_insert_ref + insert_ref.append(layout_get(copy_ref, last)) + return r class Record: - def __init__(self, layout, name=None): - self.name = get_obj_var_name(name, "") - self.layout = layout - - if self.name: - prefix = self.name + "_" - else: - prefix = "" - for f in self.layout: - if isinstance(f[1], (int, tuple)): # cases 1/2 - if(len(f) == 3): - fname, fsize, fdirection = f - else: - fname, fsize = f - finst = Signal(fsize, name=prefix + fname) - elif isinstance(f[1], list): # case 3 - fname, fsublayout = f - finst = Record(fsublayout, prefix + fname) - else: - raise TypeError - setattr(self, fname, finst) - - def eq(self, other): - return [getattr(self, f[0]).eq(getattr(other, f[0])) - for f in self.layout if hasattr(other, f[0])] - - def iter_flat(self): - for f in self.layout: - e = getattr(self, f[0]) - if isinstance(e, Signal): - if len(f) == 3: - yield e, f[2] - else: - yield e, DIR_NONE - elif isinstance(e, Record): - yield from e.iter_flat() - else: - raise TypeError - - def flatten(self): - return [signal for signal, direction in self.iter_flat()] - - def raw_bits(self): - return Cat(*self.flatten()) - - def connect(self, *slaves): - r = [] - for f in self.layout: - field = f[0] - self_e = getattr(self, field) - if isinstance(self_e, Signal): - direction = f[2] - if direction == DIR_M_TO_S: - r += [getattr(slave, field).eq(self_e) for slave in slaves] - elif direction == DIR_S_TO_M: - r.append(self_e.eq(optree("|", [getattr(slave, field) for slave in slaves]))) - else: - raise TypeError - else: - for slave in slaves: - r += self_e.connect(getattr(slave, field)) - return r - - def connect_flat(self, *slaves): - r = [] - iter_slaves = [slave.iter_flat() for slave in slaves] - for m_signal, m_direction in self.iter_flat(): - if m_direction == DIR_M_TO_S: - for iter_slave in iter_slaves: - s_signal, s_direction = next(iter_slave) - assert(s_direction == DIR_M_TO_S) - r.append(s_signal.eq(m_signal)) - elif m_direction == DIR_S_TO_M: - s_signals = [] - for iter_slave in iter_slaves: - s_signal, s_direction = next(iter_slave) - assert(s_direction == DIR_S_TO_M) - s_signals.append(s_signal) - r.append(m_signal.eq(optree("|", s_signals))) - else: - raise TypeError - return r - - def __len__(self): - return layout_len(self.layout) - - def __repr__(self): - return "" + def __init__(self, layout, name=None): + self.name = get_obj_var_name(name, "") + self.layout = layout + + if self.name: + prefix = self.name + "_" + else: + prefix = "" + for f in self.layout: + if isinstance(f[1], (int, tuple)): # cases 1/2 + if(len(f) == 3): + fname, fsize, fdirection = f + else: + fname, fsize = f + finst = Signal(fsize, name=prefix + fname) + elif isinstance(f[1], list): # case 3 + fname, fsublayout = f + finst = Record(fsublayout, prefix + fname) + else: + raise TypeError + setattr(self, fname, finst) + + def eq(self, other): + return [getattr(self, f[0]).eq(getattr(other, f[0])) + for f in self.layout if hasattr(other, f[0])] + + def iter_flat(self): + for f in self.layout: + e = getattr(self, f[0]) + if isinstance(e, Signal): + if len(f) == 3: + yield e, f[2] + else: + yield e, DIR_NONE + elif isinstance(e, Record): + yield from e.iter_flat() + else: + raise TypeError + + def flatten(self): + return [signal for signal, direction in self.iter_flat()] + + def raw_bits(self): + return Cat(*self.flatten()) + + def connect(self, *slaves): + r = [] + for f in self.layout: + field = f[0] + self_e = getattr(self, field) + if isinstance(self_e, Signal): + direction = f[2] + if direction == DIR_M_TO_S: + r += [getattr(slave, field).eq(self_e) for slave in slaves] + elif direction == DIR_S_TO_M: + r.append(self_e.eq(optree("|", [getattr(slave, field) for slave in slaves]))) + else: + raise TypeError + else: + for slave in slaves: + r += self_e.connect(getattr(slave, field)) + return r + + def connect_flat(self, *slaves): + r = [] + iter_slaves = [slave.iter_flat() for slave in slaves] + for m_signal, m_direction in self.iter_flat(): + if m_direction == DIR_M_TO_S: + for iter_slave in iter_slaves: + s_signal, s_direction = next(iter_slave) + assert(s_direction == DIR_M_TO_S) + r.append(s_signal.eq(m_signal)) + elif m_direction == DIR_S_TO_M: + s_signals = [] + for iter_slave in iter_slaves: + s_signal, s_direction = next(iter_slave) + assert(s_direction == DIR_S_TO_M) + s_signals.append(s_signal) + r.append(m_signal.eq(optree("|", s_signals))) + else: + raise TypeError + return r + + def __len__(self): + return layout_len(self.layout) + + def __repr__(self): + return "" diff --git a/migen/genlib/resetsync.py b/migen/genlib/resetsync.py index 6182ead6..456c68b1 100644 --- a/migen/genlib/resetsync.py +++ b/migen/genlib/resetsync.py @@ -3,16 +3,16 @@ from migen.fhdl.specials import Special from migen.fhdl.tools import list_signals class AsyncResetSynchronizer(Special): - def __init__(self, cd, async_reset): - Special.__init__(self) - self.cd = cd - self.async_reset = async_reset + def __init__(self, cd, async_reset): + Special.__init__(self) + self.cd = cd + self.async_reset = async_reset - def iter_expressions(self): - yield self.cd, "clk", SPECIAL_INPUT - yield self.cd, "rst", SPECIAL_OUTPUT - yield self, "async_reset", SPECIAL_INPUT + def iter_expressions(self): + yield self.cd, "clk", SPECIAL_INPUT + yield self.cd, "rst", SPECIAL_OUTPUT + yield self, "async_reset", SPECIAL_INPUT - @staticmethod - def lower(dr): - raise NotImplementedError("Attempted to use a reset synchronizer, but platform does not support them") + @staticmethod + def lower(dr): + raise NotImplementedError("Attempted to use a reset synchronizer, but platform does not support them") diff --git a/migen/genlib/rob.py b/migen/genlib/rob.py index d944eafb..dbbea870 100644 --- a/migen/genlib/rob.py +++ b/migen/genlib/rob.py @@ -1,76 +1,76 @@ 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) + 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) + 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) + # 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) + # 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)) + 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) - ) + # 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) - ) + # 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) - ) - ] + # 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) - ) + # 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/genlib/roundrobin.py b/migen/genlib/roundrobin.py index 45febb3c..d0f34d6b 100644 --- a/migen/genlib/roundrobin.py +++ b/migen/genlib/roundrobin.py @@ -3,36 +3,36 @@ from migen.fhdl.std import * (SP_WITHDRAW, SP_CE) = range(2) class RoundRobin(Module): - def __init__(self, n, switch_policy=SP_WITHDRAW): - self.request = Signal(n) - self.grant = Signal(max=max(2, n)) - self.switch_policy = switch_policy - if self.switch_policy == SP_CE: - self.ce = Signal() + def __init__(self, n, switch_policy=SP_WITHDRAW): + self.request = Signal(n) + self.grant = Signal(max=max(2, n)) + self.switch_policy = switch_policy + if self.switch_policy == SP_CE: + self.ce = Signal() - ### + ### - if n > 1: - cases = {} - for i in range(n): - switch = [] - for j in reversed(range(i+1,i+n)): - t = j % n - switch = [ - If(self.request[t], - self.grant.eq(t) - ).Else( - *switch - ) - ] - if self.switch_policy == SP_WITHDRAW: - case = [If(~self.request[i], *switch)] - else: - case = switch - cases[i] = case - statement = Case(self.grant, cases) - if self.switch_policy == SP_CE: - statement = If(self.ce, statement) - self.sync += statement - else: - self.comb += self.grant.eq(0) + if n > 1: + cases = {} + for i in range(n): + switch = [] + for j in reversed(range(i+1,i+n)): + t = j % n + switch = [ + If(self.request[t], + self.grant.eq(t) + ).Else( + *switch + ) + ] + if self.switch_policy == SP_WITHDRAW: + case = [If(~self.request[i], *switch)] + else: + case = switch + cases[i] = case + statement = Case(self.grant, cases) + if self.switch_policy == SP_CE: + statement = If(self.ce, statement) + self.sync += statement + else: + self.comb += self.grant.eq(0) diff --git a/migen/genlib/sort.py b/migen/genlib/sort.py index 1bc82ef1..5c73097e 100644 --- a/migen/genlib/sort.py +++ b/migen/genlib/sort.py @@ -2,69 +2,69 @@ from migen.fhdl.std import * from migen.fhdl import verilog class BitonicSort(Module): - """Combinatorial sorting network + """Combinatorial sorting network - The Bitonic sort is implemented as a combinatorial sort using - comparators and multiplexers. Its asymptotic complexity (in terms of - number of comparators/muxes) is O(n log(n)**2), like mergesort or - shellsort. + The Bitonic sort is implemented as a combinatorial sort using + comparators and multiplexers. Its asymptotic complexity (in terms of + number of comparators/muxes) is O(n log(n)**2), like mergesort or + shellsort. - http://www.dps.uibk.ac.at/~cosenza/teaching/gpu/sort-batcher.pdf + http://www.dps.uibk.ac.at/~cosenza/teaching/gpu/sort-batcher.pdf - http://www.inf.fh-flensburg.de/lang/algorithmen/sortieren/bitonic/bitonicen.htm + http://www.inf.fh-flensburg.de/lang/algorithmen/sortieren/bitonic/bitonicen.htm - http://www.myhdl.org/doku.php/cookbook:bitonic + http://www.myhdl.org/doku.php/cookbook:bitonic - Parameters - ---------- - n : int - Number of inputs and output signals. - m : int - Bit width of inputs and outputs. Or a tuple of `(m, signed)`. - ascending : bool - Sort direction. `True` if input is to be sorted ascending, - `False` for descending. Defaults to ascending. + Parameters + ---------- + n : int + Number of inputs and output signals. + m : int + Bit width of inputs and outputs. Or a tuple of `(m, signed)`. + ascending : bool + Sort direction. `True` if input is to be sorted ascending, + `False` for descending. Defaults to ascending. - Attributes - ---------- - i : list of Signals, in - Input values, each `m` wide. - o : list of Signals, out - Output values, sorted, each `m` bits wide. - """ - def __init__(self, n, m, ascending=True): - self.i = [Signal(m) for i in range(n)] - self.o = [Signal(m) for i in range(n)] - self._sort(self.i, self.o, int(ascending), m) + Attributes + ---------- + i : list of Signals, in + Input values, each `m` wide. + o : list of Signals, out + Output values, sorted, each `m` bits wide. + """ + def __init__(self, n, m, ascending=True): + self.i = [Signal(m) for i in range(n)] + self.o = [Signal(m) for i in range(n)] + self._sort(self.i, self.o, int(ascending), m) - def _sort_two(self, i0, i1, o0, o1, dir): - self.comb += [ - o0.eq(i0), - o1.eq(i1), - If(dir == (i0 > i1), - o0.eq(i1), - o1.eq(i0), - )] + def _sort_two(self, i0, i1, o0, o1, dir): + self.comb += [ + o0.eq(i0), + o1.eq(i1), + If(dir == (i0 > i1), + o0.eq(i1), + o1.eq(i0), + )] - def _merge(self, i, o, dir, m): - n = len(i) - k = n//2 - if n > 1: - t = [Signal(m) for j in range(n)] - for j in range(k): - self._sort_two(i[j], i[j + k], t[j], t[j + k], dir) - self._merge(t[:k], o[:k], dir, m) - self._merge(t[k:], o[k:], dir, m) - else: - self.comb += o[0].eq(i[0]) + def _merge(self, i, o, dir, m): + n = len(i) + k = n//2 + if n > 1: + t = [Signal(m) for j in range(n)] + for j in range(k): + self._sort_two(i[j], i[j + k], t[j], t[j + k], dir) + self._merge(t[:k], o[:k], dir, m) + self._merge(t[k:], o[k:], dir, m) + else: + self.comb += o[0].eq(i[0]) - def _sort(self, i, o, dir, m): - n = len(i) - k = n//2 - if n > 1: - t = [Signal(m) for j in range(n)] - self._sort(i[:k], t[:k], 1, m) # ascending - self._sort(i[k:], t[k:], 0, m) # descending - self._merge(t, o, dir, m) - else: - self.comb += o[0].eq(i[0]) + def _sort(self, i, o, dir, m): + n = len(i) + k = n//2 + if n > 1: + t = [Signal(m) for j in range(n)] + self._sort(i[:k], t[:k], 1, m) # ascending + self._sort(i[k:], t[k:], 0, m) # descending + self._merge(t, o, dir, m) + else: + self.comb += o[0].eq(i[0]) diff --git a/migen/sim/generic.py b/migen/sim/generic.py index 8377e00d..e9dd52ca 100644 --- a/migen/sim/generic.py +++ b/migen/sim/generic.py @@ -7,24 +7,24 @@ from migen.sim.ipc import * from migen.sim import icarus class TopLevel: - def __init__(self, vcd_name=None, vcd_level=1, - top_name="top", dut_type="dut", dut_name="dut", - cd_name="sys", clk_period=10): - self.vcd_name = vcd_name - self.vcd_level = vcd_level - self.top_name = top_name - self.dut_type = dut_type - self.dut_name = dut_name + def __init__(self, vcd_name=None, vcd_level=1, + top_name="top", dut_type="dut", dut_name="dut", + cd_name="sys", clk_period=10): + self.vcd_name = vcd_name + self.vcd_level = vcd_level + self.top_name = top_name + self.dut_type = dut_type + self.dut_name = dut_name - self._cd_name = cd_name - self._clk_period = clk_period + self._cd_name = cd_name + self._clk_period = clk_period - cd = ClockDomain(self._cd_name) - self.clock_domains = [cd] - self.ios = {cd.clk, cd.rst} + cd = ClockDomain(self._cd_name) + self.clock_domains = [cd] + self.ios = {cd.clk, cd.rst} - def get(self, sockaddr): - template1 = """`timescale 1ns / 1ps + def get(self, sockaddr): + template1 = """`timescale 1ns / 1ps module {top_name}(); @@ -32,185 +32,185 @@ reg {clk_name}; reg {rst_name}; initial begin - {rst_name} <= 1'b1; - @(posedge {clk_name}); - {rst_name} <= 1'b0; + {rst_name} <= 1'b1; + @(posedge {clk_name}); + {rst_name} <= 1'b0; end always begin - {clk_name} <= 1'b0; - #{hclk_period}; - {clk_name} <= 1'b1; - #{hclk_period}; + {clk_name} <= 1'b0; + #{hclk_period}; + {clk_name} <= 1'b1; + #{hclk_period}; end {dut_type} {dut_name}( - .{rst_name}({rst_name}), - .{clk_name}({clk_name}) + .{rst_name}({rst_name}), + .{clk_name}({clk_name}) ); initial $migensim_connect("{sockaddr}"); always @(posedge {clk_name}) $migensim_tick; """ - template2 = """ + template2 = """ initial begin - $dumpfile("{vcd_name}"); - $dumpvars({vcd_level}, {dut_name}); + $dumpfile("{vcd_name}"); + $dumpvars({vcd_level}, {dut_name}); end """ - r = template1.format(top_name=self.top_name, - dut_type=self.dut_type, - dut_name=self.dut_name, - clk_name=self._cd_name + "_clk", - rst_name=self._cd_name + "_rst", - hclk_period=str(self._clk_period/2), - sockaddr=sockaddr) - if self.vcd_name is not None: - r += template2.format(vcd_name=self.vcd_name, - vcd_level=str(self.vcd_level), - dut_name=self.dut_name) - r += "\nendmodule" - return r + r = template1.format(top_name=self.top_name, + dut_type=self.dut_type, + dut_name=self.dut_name, + clk_name=self._cd_name + "_clk", + rst_name=self._cd_name + "_rst", + hclk_period=str(self._clk_period/2), + sockaddr=sockaddr) + if self.vcd_name is not None: + r += template2.format(vcd_name=self.vcd_name, + vcd_level=str(self.vcd_level), + dut_name=self.dut_name) + r += "\nendmodule" + return r class Simulator: - def __init__(self, fragment, top_level=None, sim_runner=None, sockaddr="simsocket", **vopts): - if not isinstance(fragment, _Fragment): - fragment = fragment.get_fragment() - if top_level is None: - top_level = TopLevel() - if sim_runner is None: - sim_runner = icarus.Runner() - self.top_level = top_level - self.ipc = Initiator(sockaddr) - self.sim_runner = sim_runner - - c_top = self.top_level.get(sockaddr) - - fragment = fragment + _Fragment(clock_domains=top_level.clock_domains) - c_fragment = verilog.convert(fragment, - ios=self.top_level.ios, - name=self.top_level.dut_type, - **vopts) - self.namespace = c_fragment.ns - - self.cycle_counter = -1 - - self.sim_runner = sim_runner - self.sim_runner.start(c_top, c_fragment) - self.ipc.accept() - reply = self.ipc.recv() - assert(isinstance(reply, MessageTick)) - - self.sim_functions = fragment.sim - self.active_sim_functions = set(f for f in fragment.sim if not hasattr(f, "passive") or not f.passive) - self.unreferenced = {} - - def run(self, ncycles=None): - counter = 0 - - if self.active_sim_functions: - if ncycles is None: - def continue_simulation(): - return bool(self.active_sim_functions) - else: - def continue_simulation(): - return self.active_sim_functions and counter < ncycles - else: - if ncycles is None: - raise ValueError("No active simulation function present - must specify ncycles to end simulation") - def continue_simulation(): - return counter < ncycles - - while continue_simulation(): - self.cycle_counter += 1 - counter += 1 - self.ipc.send(MessageGo()) - reply = self.ipc.recv() - assert(isinstance(reply, MessageTick)) - - del_list = [] - for s in self.sim_functions: - try: - s(self) - except StopSimulation: - del_list.append(s) - for s in del_list: - self.sim_functions.remove(s) - try: - self.active_sim_functions.remove(s) - except KeyError: - pass - - def get_unreferenced(self, item, index): - try: - return self.unreferenced[(item, index)] - except KeyError: - if isinstance(item, Memory): - try: - init = item.init[index] - except (TypeError, IndexError): - init = 0 - else: - init = item.reset - self.unreferenced[(item, index)] = init - return init - - def rd(self, item, index=0): - try: - name = self.top_level.top_name + "." \ - + self.top_level.dut_name + "." \ - + self.namespace.get_name(item) - self.ipc.send(MessageRead(name, Int32(index))) - reply = self.ipc.recv() - assert(isinstance(reply, MessageReadReply)) - value = reply.value - except KeyError: - value = self.get_unreferenced(item, index) - if isinstance(item, Memory): - signed = False - nbits = item.width - else: - signed = item.signed - nbits = flen(item) - value = value & (2**nbits - 1) - if signed and (value & 2**(nbits - 1)): - value -= 2**nbits - return value - - def wr(self, item, value, index=0): - if isinstance(item, Memory): - nbits = item.width - else: - nbits = flen(item) - if value < 0: - value += 2**nbits - assert(value >= 0 and value < 2**nbits) - try: - name = self.top_level.top_name + "." \ - + self.top_level.dut_name + "." \ - + self.namespace.get_name(item) - self.ipc.send(MessageWrite(name, Int32(index), value)) - except KeyError: - self.unreferenced[(item, index)] = value - - def __del__(self): - if hasattr(self, "ipc"): - warnings.warn("call Simulator.close() to clean up " - "or use it as a contextmanager", DeprecationWarning) - self.close() - - def close(self): - self.ipc.close() - self.sim_runner.close() - del self.ipc - del self.sim_runner - - def __enter__(self): - return self - - def __exit__(self, type, value, traceback): - self.close() + def __init__(self, fragment, top_level=None, sim_runner=None, sockaddr="simsocket", **vopts): + if not isinstance(fragment, _Fragment): + fragment = fragment.get_fragment() + if top_level is None: + top_level = TopLevel() + if sim_runner is None: + sim_runner = icarus.Runner() + self.top_level = top_level + self.ipc = Initiator(sockaddr) + self.sim_runner = sim_runner + + c_top = self.top_level.get(sockaddr) + + fragment = fragment + _Fragment(clock_domains=top_level.clock_domains) + c_fragment = verilog.convert(fragment, + ios=self.top_level.ios, + name=self.top_level.dut_type, + **vopts) + self.namespace = c_fragment.ns + + self.cycle_counter = -1 + + self.sim_runner = sim_runner + self.sim_runner.start(c_top, c_fragment) + self.ipc.accept() + reply = self.ipc.recv() + assert(isinstance(reply, MessageTick)) + + self.sim_functions = fragment.sim + self.active_sim_functions = set(f for f in fragment.sim if not hasattr(f, "passive") or not f.passive) + self.unreferenced = {} + + def run(self, ncycles=None): + counter = 0 + + if self.active_sim_functions: + if ncycles is None: + def continue_simulation(): + return bool(self.active_sim_functions) + else: + def continue_simulation(): + return self.active_sim_functions and counter < ncycles + else: + if ncycles is None: + raise ValueError("No active simulation function present - must specify ncycles to end simulation") + def continue_simulation(): + return counter < ncycles + + while continue_simulation(): + self.cycle_counter += 1 + counter += 1 + self.ipc.send(MessageGo()) + reply = self.ipc.recv() + assert(isinstance(reply, MessageTick)) + + del_list = [] + for s in self.sim_functions: + try: + s(self) + except StopSimulation: + del_list.append(s) + for s in del_list: + self.sim_functions.remove(s) + try: + self.active_sim_functions.remove(s) + except KeyError: + pass + + def get_unreferenced(self, item, index): + try: + return self.unreferenced[(item, index)] + except KeyError: + if isinstance(item, Memory): + try: + init = item.init[index] + except (TypeError, IndexError): + init = 0 + else: + init = item.reset + self.unreferenced[(item, index)] = init + return init + + def rd(self, item, index=0): + try: + name = self.top_level.top_name + "." \ + + self.top_level.dut_name + "." \ + + self.namespace.get_name(item) + self.ipc.send(MessageRead(name, Int32(index))) + reply = self.ipc.recv() + assert(isinstance(reply, MessageReadReply)) + value = reply.value + except KeyError: + value = self.get_unreferenced(item, index) + if isinstance(item, Memory): + signed = False + nbits = item.width + else: + signed = item.signed + nbits = flen(item) + value = value & (2**nbits - 1) + if signed and (value & 2**(nbits - 1)): + value -= 2**nbits + return value + + def wr(self, item, value, index=0): + if isinstance(item, Memory): + nbits = item.width + else: + nbits = flen(item) + if value < 0: + value += 2**nbits + assert(value >= 0 and value < 2**nbits) + try: + name = self.top_level.top_name + "." \ + + self.top_level.dut_name + "." \ + + self.namespace.get_name(item) + self.ipc.send(MessageWrite(name, Int32(index), value)) + except KeyError: + self.unreferenced[(item, index)] = value + + def __del__(self): + if hasattr(self, "ipc"): + warnings.warn("call Simulator.close() to clean up " + "or use it as a contextmanager", DeprecationWarning) + self.close() + + def close(self): + self.ipc.close() + self.sim_runner.close() + del self.ipc + del self.sim_runner + + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + self.close() def run_simulation(fragment, ncycles=None, vcd_name=None, **kwargs): - with Simulator(fragment, TopLevel(vcd_name), icarus.Runner(**kwargs)) as s: - s.run(ncycles) + with Simulator(fragment, TopLevel(vcd_name), icarus.Runner(**kwargs)) as s: + s.run(ncycles) diff --git a/migen/sim/icarus.py b/migen/sim/icarus.py index 7f8c30c7..59dc2b7d 100644 --- a/migen/sim/icarus.py +++ b/migen/sim/icarus.py @@ -7,37 +7,37 @@ import time class Runner: - def __init__(self, options=None, extra_files=None, top_file="migensim_top.v", dut_file="migensim_dut.v", vvp_file=None, keep_files=False): - if extra_files is None: extra_files = [] - if vvp_file is None: vvp_file = dut_file + "vp" - if options is None: options = [] - self.options = options - self.extra_files = extra_files - self.top_file = top_file - self.dut_file = dut_file - self.vvp_file = vvp_file - self.data_files = [] - self.keep_files = keep_files + def __init__(self, options=None, extra_files=None, top_file="migensim_top.v", dut_file="migensim_dut.v", vvp_file=None, keep_files=False): + if extra_files is None: extra_files = [] + if vvp_file is None: vvp_file = dut_file + "vp" + if options is None: options = [] + self.options = options + self.extra_files = extra_files + self.top_file = top_file + self.dut_file = dut_file + self.vvp_file = vvp_file + self.data_files = [] + self.keep_files = keep_files - def start(self, c_top, c_dut): - with open(self.top_file, "w") as f: - f.write(c_top) - c_dut.write(self.dut_file) - self.data_files += c_dut.data_files.keys() - subprocess.check_call(["iverilog", "-o", self.vvp_file] + self.options + [self.top_file, self.dut_file] + self.extra_files) - self.process = subprocess.Popen(["vvp", "-mmigensim", "-Mvpi", self.vvp_file]) + def start(self, c_top, c_dut): + with open(self.top_file, "w") as f: + f.write(c_top) + c_dut.write(self.dut_file) + self.data_files += c_dut.data_files.keys() + subprocess.check_call(["iverilog", "-o", self.vvp_file] + self.options + [self.top_file, self.dut_file] + self.extra_files) + self.process = subprocess.Popen(["vvp", "-mmigensim", "-Mvpi", self.vvp_file]) - def close(self): - if hasattr(self, "process"): - self.process.terminate() - if self.process.poll() is None: - time.sleep(.1) - self.process.kill() - self.process.wait() - if not self.keep_files: - for f in [self.top_file, self.dut_file, self.vvp_file] + self.data_files: - try: - os.remove(f) - except OSError: - pass - self.data_files.clear() + def close(self): + if hasattr(self, "process"): + self.process.terminate() + if self.process.poll() is None: + time.sleep(.1) + self.process.kill() + self.process.wait() + if not self.keep_files: + for f in [self.top_file, self.dut_file, self.vvp_file] + self.data_files: + try: + os.remove(f) + except OSError: + pass + self.data_files.clear() diff --git a/migen/sim/ipc.py b/migen/sim/ipc.py index f7aaf9de..b0266aec 100644 --- a/migen/sim/ipc.py +++ b/migen/sim/ipc.py @@ -9,42 +9,42 @@ import os # class Int32(int): - pass + pass class Message: - def __init__(self, *pvalues): - for parameter, value in zip(self.parameters, pvalues): - setattr(self, parameter[1], parameter[0](value)) - - def __str__(self): - p = [] - for parameter in self.parameters: - p.append(parameter[1] + "=" + str(getattr(self, parameter[1]))) - if p: - pf = " " + " ".join(p) - else: - pf = "" - return "<" + self.__class__.__name__ + pf + ">" + def __init__(self, *pvalues): + for parameter, value in zip(self.parameters, pvalues): + setattr(self, parameter[1], parameter[0](value)) + + def __str__(self): + p = [] + for parameter in self.parameters: + p.append(parameter[1] + "=" + str(getattr(self, parameter[1]))) + if p: + pf = " " + " ".join(p) + else: + pf = "" + return "<" + self.__class__.__name__ + pf + ">" class MessageTick(Message): - code = 0 - parameters = [] + code = 0 + parameters = [] class MessageGo(Message): - code = 1 - parameters = [] + code = 1 + parameters = [] class MessageWrite(Message): - code = 2 - parameters = [(str, "name"), (Int32, "index"), (int, "value")] + code = 2 + parameters = [(str, "name"), (Int32, "index"), (int, "value")] class MessageRead(Message): - code = 3 - parameters = [(str, "name"), (Int32, "index")] + code = 3 + parameters = [(str, "name"), (Int32, "index")] class MessageReadReply(Message): - code = 4 - parameters = [(int, "value")] + code = 4 + parameters = [(int, "value")] message_classes = [MessageTick, MessageGo, MessageWrite, MessageRead, MessageReadReply] @@ -53,124 +53,124 @@ message_classes = [MessageTick, MessageGo, MessageWrite, MessageRead, MessageRea # def _pack_int(v): - if v == 0: - p = [1, 0] - else: - p = [] - while v != 0: - p.append(v & 0xff) - v >>= 8 - p.insert(0, len(p)) - return p + if v == 0: + p = [1, 0] + else: + p = [] + while v != 0: + p.append(v & 0xff) + v >>= 8 + p.insert(0, len(p)) + return p def _pack_str(v): - p = [ord(c) for c in v] - p.append(0) - return p + p = [ord(c) for c in v] + p.append(0) + return p def _pack_int32(v): - return [ - v & 0xff, - (v & 0xff00) >> 8, - (v & 0xff0000) >> 16, - (v & 0xff000000) >> 24 - ] + return [ + v & 0xff, + (v & 0xff00) >> 8, + (v & 0xff0000) >> 16, + (v & 0xff000000) >> 24 + ] def _pack(message): - r = [message.code] - for t, p in message.parameters: - value = getattr(message, p) - assert(isinstance(value, t)) - if t == int: - r += _pack_int(value) - elif t == str: - r += _pack_str(value) - elif t == Int32: - r += _pack_int32(value) - else: - raise TypeError - return bytes(r) + r = [message.code] + for t, p in message.parameters: + value = getattr(message, p) + assert(isinstance(value, t)) + if t == int: + r += _pack_int(value) + elif t == str: + r += _pack_str(value) + elif t == Int32: + r += _pack_int32(value) + else: + raise TypeError + return bytes(r) # # Unpacking # def _unpack_int(i, nchunks=None): - v = 0 - power = 1 - if nchunks is None: - nchunks = next(i) - for j in range(nchunks): - v += power*next(i) - power *= 256 - return v + v = 0 + power = 1 + if nchunks is None: + nchunks = next(i) + for j in range(nchunks): + v += power*next(i) + power *= 256 + return v def _unpack_str(i): - v = "" - c = next(i) - while c: - v += chr(c) - c = next(i) - return v + v = "" + c = next(i) + while c: + v += chr(c) + c = next(i) + return v def _unpack(message): - i = iter(message) - code = next(i) - msgclass = next(filter(lambda x: x.code == code, message_classes)) - pvalues = [] - for t, p in msgclass.parameters: - if t == int: - v = _unpack_int(i) - elif t == str: - v = _unpack_str(i) - elif t == Int32: - v = _unpack_int(i, 4) - else: - raise TypeError - pvalues.append(v) - return msgclass(*pvalues) + i = iter(message) + code = next(i) + msgclass = next(filter(lambda x: x.code == code, message_classes)) + pvalues = [] + for t, p in msgclass.parameters: + if t == int: + v = _unpack_int(i) + elif t == str: + v = _unpack_str(i) + elif t == Int32: + v = _unpack_int(i, 4) + else: + raise TypeError + pvalues.append(v) + return msgclass(*pvalues) # # I/O # class PacketTooLarge(Exception): - pass + pass class Initiator: - def __init__(self, sockaddr): - self.sockaddr = sockaddr - self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET) - self._cleanup_file() - self.socket.bind(self.sockaddr) - self.socket.listen(1) - - def _cleanup_file(self): - try: - os.remove(self.sockaddr) - except OSError: - pass - - def accept(self): - self.conn, addr = self.socket.accept() - - def send(self, message): - self.conn.send(_pack(message)) - - def recv(self): - maxlen = 2048 - packet = self.conn.recv(maxlen) - if len(packet) < 1: - return None - if len(packet) >= maxlen: - raise PacketTooLarge - return _unpack(packet) - - def close(self): - if hasattr(self, "conn"): - self.conn.shutdown(socket.SHUT_RDWR) - self.conn.close() - if hasattr(self, "socket"): - self.socket.shutdown(socket.SHUT_RDWR) - self.socket.close() - self._cleanup_file() + def __init__(self, sockaddr): + self.sockaddr = sockaddr + self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET) + self._cleanup_file() + self.socket.bind(self.sockaddr) + self.socket.listen(1) + + def _cleanup_file(self): + try: + os.remove(self.sockaddr) + except OSError: + pass + + def accept(self): + self.conn, addr = self.socket.accept() + + def send(self, message): + self.conn.send(_pack(message)) + + def recv(self): + maxlen = 2048 + packet = self.conn.recv(maxlen) + if len(packet) < 1: + return None + if len(packet) >= maxlen: + raise PacketTooLarge + return _unpack(packet) + + def close(self): + if hasattr(self, "conn"): + self.conn.shutdown(socket.SHUT_RDWR) + self.conn.close() + if hasattr(self, "socket"): + self.socket.shutdown(socket.SHUT_RDWR) + self.socket.close() + self._cleanup_file() diff --git a/migen/sim/upper.py b/migen/sim/upper.py index 4035234e..0c8789dc 100644 --- a/migen/sim/upper.py +++ b/migen/sim/upper.py @@ -2,108 +2,108 @@ from migen.fhdl.structure import Signal, StopSimulation from migen.fhdl.specials import Memory class MemoryProxy: - def __init__(self, simulator, obj): - self.simulator = simulator - self._simproxy_obj = obj - - def __getitem__(self, key): - if isinstance(key, int): - return self.simulator.rd(self._simproxy_obj, key) - else: - start, stop, step = key.indices(self._simproxy_obj.depth) - return [self.simulator.rd(self._simproxy_obj, i) for i in range(start, stop, step)] - - def __setitem__(self, key, value): - if isinstance(key, int): - self.simulator.wr(self._simproxy_obj, key, value) - else: - start, stop, step = key.indices(self.__obj.depth) - if len(value) != (stop - start)//step: - raise ValueError - for i, v in zip(range(start, stop, step), value): - self.simulator.wr(self._simproxy_obj, i, v) + def __init__(self, simulator, obj): + self.simulator = simulator + self._simproxy_obj = obj + + def __getitem__(self, key): + if isinstance(key, int): + return self.simulator.rd(self._simproxy_obj, key) + else: + start, stop, step = key.indices(self._simproxy_obj.depth) + return [self.simulator.rd(self._simproxy_obj, i) for i in range(start, stop, step)] + + def __setitem__(self, key, value): + if isinstance(key, int): + self.simulator.wr(self._simproxy_obj, key, value) + else: + start, stop, step = key.indices(self.__obj.depth) + if len(value) != (stop - start)//step: + raise ValueError + for i, v in zip(range(start, stop, step), value): + self.simulator.wr(self._simproxy_obj, i, v) class Proxy: - def __init__(self, simulator, obj): - object.__setattr__(self, "simulator", simulator) - object.__setattr__(self, "_simproxy_obj", obj) - - def __process_get(self, item): - if isinstance(item, Signal): - return self.simulator.rd(item) - elif isinstance(item, Memory): - return MemoryProxy(self.simulator, item) - else: - return Proxy(self.simulator, item) - - def __getattr__(self, name): - return self.__process_get(getattr(self._simproxy_obj, name)) - - def __setattr__(self, name, value): - item = getattr(self._simproxy_obj, name) - assert(isinstance(item, Signal)) - self.simulator.wr(item, value) - - def __getitem__(self, key): - return self.__process_get(self._simproxy_obj[key]) - - def __setitem__(self, key, value): - item = self._simproxy_obj[key] - assert(isinstance(item, Signal)) - self.simulator.wr(item, value) + def __init__(self, simulator, obj): + object.__setattr__(self, "simulator", simulator) + object.__setattr__(self, "_simproxy_obj", obj) + + def __process_get(self, item): + if isinstance(item, Signal): + return self.simulator.rd(item) + elif isinstance(item, Memory): + return MemoryProxy(self.simulator, item) + else: + return Proxy(self.simulator, item) + + def __getattr__(self, name): + return self.__process_get(getattr(self._simproxy_obj, name)) + + def __setattr__(self, name, value): + item = getattr(self._simproxy_obj, name) + assert(isinstance(item, Signal)) + self.simulator.wr(item, value) + + def __getitem__(self, key): + return self.__process_get(self._simproxy_obj[key]) + + def __setitem__(self, key, value): + item = self._simproxy_obj[key] + assert(isinstance(item, Signal)) + self.simulator.wr(item, value) def gen_sim(simg): - gens = dict() - resume_cycle = 0 - - def do_simulation(s): - nonlocal resume_cycle, gens - - if isinstance(s, Proxy): - simulator = s.simulator - else: - simulator = s - - if simulator.cycle_counter >= resume_cycle: - try: - gen = gens[simulator] - except KeyError: - gen = simg(s) - gens[simulator] = gen - try: - n = next(gen) - except StopIteration: - del gens[simulator] - raise StopSimulation - else: - if n is None: - n = 1 - resume_cycle = simulator.cycle_counter + n - - if hasattr(simg, "passive"): - do_simulation.passive = simg.passive - - return do_simulation + gens = dict() + resume_cycle = 0 + + def do_simulation(s): + nonlocal resume_cycle, gens + + if isinstance(s, Proxy): + simulator = s.simulator + else: + simulator = s + + if simulator.cycle_counter >= resume_cycle: + try: + gen = gens[simulator] + except KeyError: + gen = simg(s) + gens[simulator] = gen + try: + n = next(gen) + except StopIteration: + del gens[simulator] + raise StopSimulation + else: + if n is None: + n = 1 + resume_cycle = simulator.cycle_counter + n + + if hasattr(simg, "passive"): + do_simulation.passive = simg.passive + + return do_simulation def proxy_sim(target, simf): - proxies = dict() - - def do_simulation(simulator): - nonlocal proxies - - try: - proxy = proxies[simulator] - except KeyError: - proxy = Proxy(simulator, target) - proxies[simulator] = proxy - try: - simf(proxy) - except StopSimulation: - del proxies[simulator] - raise - - if hasattr(simf, "passive"): - do_simulation.passive = simf.passive - - return do_simulation + proxies = dict() + + def do_simulation(simulator): + nonlocal proxies + + try: + proxy = proxies[simulator] + except KeyError: + proxy = Proxy(simulator, target) + proxies[simulator] = proxy + try: + simf(proxy) + except StopSimulation: + del proxies[simulator] + raise + + if hasattr(simf, "passive"): + do_simulation.passive = simf.passive + + return do_simulation diff --git a/migen/test/support.py b/migen/test/support.py index 51a89707..f0dc77ae 100644 --- a/migen/test/support.py +++ b/migen/test/support.py @@ -3,20 +3,20 @@ from migen.sim.generic import run_simulation from migen.fhdl import verilog class SimBench(Module): - callback = None - def do_simulation(self, selfp): - if self.callback is not None: - return self.callback(self, selfp) + callback = None + def do_simulation(self, selfp): + if self.callback is not None: + return self.callback(self, selfp) class SimCase: - TestBench = SimBench + TestBench = SimBench - def setUp(self, *args, **kwargs): - self.tb = self.TestBench(*args, **kwargs) + def setUp(self, *args, **kwargs): + self.tb = self.TestBench(*args, **kwargs) - def test_to_verilog(self): - verilog.convert(self.tb) + def test_to_verilog(self): + verilog.convert(self.tb) - def run_with(self, cb, ncycles=None): - self.tb.callback = cb - run_simulation(self.tb, ncycles=ncycles) + def run_with(self, cb, ncycles=None): + self.tb.callback = cb + run_simulation(self.tb, ncycles=ncycles) diff --git a/migen/test/test_actor.py b/migen/test/test_actor.py index d3856a04..9bd65ac2 100644 --- a/migen/test/test_actor.py +++ b/migen/test/test_actor.py @@ -9,57 +9,57 @@ 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) + 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 __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"]) + 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)) + 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) + 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 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) + 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) + 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 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) + def test_equal(self): + self.run_with(lambda tb, tbp: None) + self.assertEqual(self.tb.source.sent, self.tb.sink.received) diff --git a/migen/test/test_coding.py b/migen/test/test_coding.py index c21d726f..d8aabe2b 100644 --- a/migen/test/test_coding.py +++ b/migen/test/test_coding.py @@ -6,97 +6,97 @@ from migen.genlib.coding import * from migen.test.support import SimCase, SimBench class EncCase(SimCase, unittest.TestCase): - class TestBench(SimBench): - def __init__(self): - self.submodules.dut = Encoder(8) + class TestBench(SimBench): + def __init__(self): + self.submodules.dut = Encoder(8) - def test_sizes(self): - self.assertEqual(flen(self.tb.dut.i), 8) - self.assertEqual(flen(self.tb.dut.o), 3) - self.assertEqual(flen(self.tb.dut.n), 1) + def test_sizes(self): + self.assertEqual(flen(self.tb.dut.i), 8) + self.assertEqual(flen(self.tb.dut.o), 3) + self.assertEqual(flen(self.tb.dut.n), 1) - def test_run_sequence(self): - seq = list(range(1<<8)) - def cb(tb, tbp): - if seq: - tbp.dut.i = seq.pop(0) - if tbp.dut.n: - self.assertNotIn(tbp.dut.i, [1< 0: - self.assertEqual(i & 1<<(o - 1), 0) - self.assertGreaterEqual(i, 1< 0: + self.assertEqual(i & 1<<(o - 1), 0) + self.assertGreaterEqual(i, 1< 0: - self.assertEqual(i & 1<<(o - 1), 0) - self.assertGreaterEqual(i, 1< 0: + self.assertEqual(i & 1<<(o - 1), 0) + self.assertGreaterEqual(i, 1< q, - lambda p, q: p >= q, - lambda p, q: p < q, - lambda p, q: p <= q, - lambda p, q: p == q, - lambda p, q: p != q, - ] - self.vals = [] - for asign in 1, -1: - for bsign in 1, -1: - for f in comps: - r = Signal() - r0 = f(asign*self.a, bsign*self.b) - self.comb += r.eq(r0) - self.vals.append((asign, bsign, f, r, r0.op)) + class TestBench(SimBench): + def __init__(self): + self.a = Signal((3, True)) + self.b = Signal((4, True)) + comps = [ + lambda p, q: p > q, + lambda p, q: p >= q, + lambda p, q: p < q, + lambda p, q: p <= q, + lambda p, q: p == q, + lambda p, q: p != q, + ] + self.vals = [] + for asign in 1, -1: + for bsign in 1, -1: + for f in comps: + r = Signal() + r0 = f(asign*self.a, bsign*self.b) + self.comb += r.eq(r0) + self.vals.append((asign, bsign, f, r, r0.op)) - def test_comparisons(self): - values = range(-4, 4) - agen = iter(values) - bgen = iter(values) - def cb(tb, tbp): - try: - tbp.a = next(agen) - tbp.b = next(bgen) - except StopIteration: - raise StopSimulation - a = tbp.a - b = tbp.b - for asign, bsign, f, r, op in self.tb.vals: - r, r0 = tbp.simulator.rd(r), f(asign*a, bsign*b) - self.assertEqual(r, int(r0), - "got {}, want {}*{} {} {}*{} = {}".format( - r, asign, a, op, bsign, b, r0)) - self.run_with(cb) + def test_comparisons(self): + values = range(-4, 4) + agen = iter(values) + bgen = iter(values) + def cb(tb, tbp): + try: + tbp.a = next(agen) + tbp.b = next(bgen) + except StopIteration: + raise StopSimulation + a = tbp.a + b = tbp.b + for asign, bsign, f, r, op in self.tb.vals: + r, r0 = tbp.simulator.rd(r), f(asign*a, bsign*b) + self.assertEqual(r, int(r0), + "got {}, want {}*{} {} {}*{} = {}".format( + r, asign, a, op, bsign, b, r0)) + self.run_with(cb) diff --git a/migen/test/test_size.py b/migen/test/test_size.py index 5c222732..7bc63f70 100644 --- a/migen/test/test_size.py +++ b/migen/test/test_size.py @@ -3,49 +3,49 @@ import unittest from migen.fhdl.std import * def _same_slices(a, b): - return a.value is b.value and a.start == b.start and a.stop == b.stop + return a.value is b.value and a.start == b.start and a.stop == b.stop class SignalSizeCase(unittest.TestCase): - def setUp(self): - self.i = 0xaa - self.j = -127 - self.s = Signal((13, True)) - - def test_flen(self): - self.assertEqual(flen(self.s), 13) - self.assertEqual(flen(self.i), 8) - self.assertEqual(flen(self.j), 8) - - def test_flen_type(self): - self.assertRaises(TypeError, flen, []) - - def test_fiter(self): - for i, si in enumerate(fiter(self.s)): - self.assertTrue(_same_slices(si, self.s[i])) - self.assertEqual(list(fiter(self.i)), - [(self.i >> i) & 1 for i in range(8)]) - self.assertEqual(list(fiter(self.j)), - [(self.j >> i) & 1 for i in range(8)]) - - def test_fiter_type(self): - self.assertRaises(TypeError, fiter, []) - - def test_fslice(self): - sl = slice(1, None, 2) - fslice(self.s, sl) - self.assertEqual(fslice(self.i, sl), 15) - self.assertEqual(fslice(self.j, sl), 8) - self.assertEqual(fslice(-1, 9), 1) - self.assertEqual(fslice(-1, slice(0, 4)), 0b1) - self.assertEqual(fslice(-7, slice(0, None, 1)), 0b1001) - - def test_fslice_type(self): - self.assertRaises(TypeError, fslice, [], 3) - - def test_freversed(self): - freversed(self.s) - freversed(self.i) - freversed(self.j) - - def test_freveseed_type(self): - self.assertRaises(TypeError, freversed, []) + def setUp(self): + self.i = 0xaa + self.j = -127 + self.s = Signal((13, True)) + + def test_flen(self): + self.assertEqual(flen(self.s), 13) + self.assertEqual(flen(self.i), 8) + self.assertEqual(flen(self.j), 8) + + def test_flen_type(self): + self.assertRaises(TypeError, flen, []) + + def test_fiter(self): + for i, si in enumerate(fiter(self.s)): + self.assertTrue(_same_slices(si, self.s[i])) + self.assertEqual(list(fiter(self.i)), + [(self.i >> i) & 1 for i in range(8)]) + self.assertEqual(list(fiter(self.j)), + [(self.j >> i) & 1 for i in range(8)]) + + def test_fiter_type(self): + self.assertRaises(TypeError, fiter, []) + + def test_fslice(self): + sl = slice(1, None, 2) + fslice(self.s, sl) + self.assertEqual(fslice(self.i, sl), 15) + self.assertEqual(fslice(self.j, sl), 8) + self.assertEqual(fslice(-1, 9), 1) + self.assertEqual(fslice(-1, slice(0, 4)), 0b1) + self.assertEqual(fslice(-7, slice(0, None, 1)), 0b1001) + + def test_fslice_type(self): + self.assertRaises(TypeError, fslice, [], 3) + + def test_freversed(self): + freversed(self.s) + freversed(self.i) + freversed(self.j) + + def test_freveseed_type(self): + self.assertRaises(TypeError, freversed, []) diff --git a/migen/test/test_sort.py b/migen/test/test_sort.py index 163be8c2..a0c6f37d 100644 --- a/migen/test/test_sort.py +++ b/migen/test/test_sort.py @@ -7,20 +7,20 @@ from migen.genlib.sort import * from migen.test.support import SimCase, SimBench class BitonicCase(SimCase, unittest.TestCase): - class TestBench(SimBench): - def __init__(self): - self.submodules.dut = BitonicSort(8, 4, ascending=True) + class TestBench(SimBench): + def __init__(self): + self.submodules.dut = BitonicSort(8, 4, ascending=True) - def test_sizes(self): - self.assertEqual(len(self.tb.dut.i), 8) - self.assertEqual(len(self.tb.dut.o), 8) - for i in range(8): - self.assertEqual(flen(self.tb.dut.i[i]), 4) - self.assertEqual(flen(self.tb.dut.o[i]), 4) + def test_sizes(self): + self.assertEqual(len(self.tb.dut.i), 8) + self.assertEqual(len(self.tb.dut.o), 8) + for i in range(8): + self.assertEqual(flen(self.tb.dut.i[i]), 4) + self.assertEqual(flen(self.tb.dut.o[i]), 4) - def test_sort(self): - def cb(tb, tbp): - for i in tb.dut.i: - tbp.simulator.wr(i, randrange(1<