# 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']
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()))
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()))
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}))
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)
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}))
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))
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()))
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})
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))
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()))
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)
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}))
@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}))
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()
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)
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()
# 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 (<TRead...>/<TWrite...>).
- 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 (<TRead...>/<TWrite...>).
+ 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:
# <TWrite adr:0x0 dat:0x0>
# 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)
# 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
# ...
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)
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())
# 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}))
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())
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)
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])
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}
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)
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
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
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
}
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)
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)
# XXX Lattice programmer need an .xcf file, will need clean up and support for more parameters
_xcf_template = """
<?xml version='1.0' encoding='utf-8' ?>
-<!DOCTYPE ispXCF SYSTEM "IspXCF.dtd" >
+<!DOCTYPE ispXCF SYSTEM "IspXCF.dtd" >
<ispXCF version="3.4.1">
- <Comment></Comment>
- <Chain>
- <Comm>JTAG</Comm>
- <Device>
- <SelectedProg value="TRUE"/>
- <Pos>1</Pos>
- <Vendor>Lattice</Vendor>
- <Family>LatticeECP3</Family>
- <Name>LFE3-35EA</Name>
- <File>{bitstream_file}</File>
- <Operation>Fast Program</Operation>
- </Device>
- </Chain>
- <ProjectOptions>
- <Program>SEQUENTIAL</Program>
- <Process>ENTIRED CHAIN</Process>
- <OperationOverride>No Override</OperationOverride>
- <StartTAP>TLR</StartTAP>
- <EndTAP>TLR</EndTAP>
- <VerifyUsercode value="FALSE"/>
- </ProjectOptions>
- <CableOptions>
- <CableName>USB2</CableName>
- <PortAdd>FTUSB-0</PortAdd>
- <USBID>Dual RS232-HS A Location 0000 Serial A</USBID>
- <JTAGPinSetting>
- TRST ABSENT;
- ISPEN ABSENT;
- </JTAGPinSetting>
- </CableOptions>
+ <Comment></Comment>
+ <Chain>
+ <Comm>JTAG</Comm>
+ <Device>
+ <SelectedProg value="TRUE"/>
+ <Pos>1</Pos>
+ <Vendor>Lattice</Vendor>
+ <Family>LatticeECP3</Family>
+ <Name>LFE3-35EA</Name>
+ <File>{bitstream_file}</File>
+ <Operation>Fast Program</Operation>
+ </Device>
+ </Chain>
+ <ProjectOptions>
+ <Program>SEQUENTIAL</Program>
+ <Process>ENTIRED CHAIN</Process>
+ <OperationOverride>No Override</OperationOverride>
+ <StartTAP>TLR</StartTAP>
+ <EndTAP>TLR</EndTAP>
+ <VerifyUsercode value="FALSE"/>
+ </ProjectOptions>
+ <CableOptions>
+ <CableName>USB2</CableName>
+ <PortAdd>FTUSB-0</PortAdd>
+ <USBID>Dual RS232-HS A Location 0000 Serial A</USBID>
+ <JTAGPinSetting>
+ TRST ABSENT;
+ ISPEN ABSENT;
+ </JTAGPinSetting>
+ </CableOptions>
</ispXCF>
"""
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])
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)
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)
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()
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]")
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
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
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))
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
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)
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")
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")
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)
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)
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
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
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()
# 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)
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%;
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
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)
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}
#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
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
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
}
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)
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)
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
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]
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]
quit
""".format(data=data_file)
- _run_vivado(self.vivado_path, self.vivado_ver, cmds)
+ _run_vivado(self.vivado_path, self.vivado_ver, cmds)
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)
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)
+ ]
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)
# 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"))
+ )
+ )
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.
# 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))
# - (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)
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)
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)
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).
# 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()]
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)
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]))
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))
+ ]
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]
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
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
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))
+ ]
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)])
+ ])
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
- [<migen.fhdl.structure._Slice object at 0x...>, <migen.fhdl.structure._Slice object at 0x...>]
- >>> 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
+ [<migen.fhdl.structure._Slice object at 0x...>, <migen.fhdl.structure._Slice object at 0x...>]
+ >>> 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
- <migen.fhdl.structure._Slice object at 0x...>
- >>> 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
+ <migen.fhdl.structure._Slice object at 0x...>
+ >>> 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
- <migen.fhdl.structure.Cat object at 0x...>
- >>> 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
+ <migen.fhdl.structure.Cat object at 0x...>
+ >>> bin(freversed(0b1011))
+ '0b1101'
+ """
+ return fslice(v, slice(None, None, -1))
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
_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
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)
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
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
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"
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)
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 "<Signal " + (self.backtrace[-1][0] or "anonymous") + " at " + hex(id(self)) + ">"
-
- @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 "<Signal " + (self.backtrace[-1][0] or "anonymous") + " at " + hex(id(self)) + ">"
+
+ @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
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)
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 == "<module>":
- 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 == "<module>":
+ 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
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
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
# - 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
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)
+ ]
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
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)
+ ]
# 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 = "<abstract " + self.actor_class.__name__
- if self.name is not None:
- r += ": " + self.name
- r += ">"
- return r
+ 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 = "<abstract " + self.actor_class.__name__
+ if self.name is not None:
+ r += ": " + self.name
+ r += ">"
+ return r
class MultiDiGraph:
- def __init__(self):
- self.edges = defaultdict(list)
- self.incoming = defaultdict(set)
- self.outgoing = defaultdict(set)
- self.nodes = set()
-
- def add_edge(self, a, b, **edge):
- self.edges[(a, b)].append(edge)
- self.incoming[b].add(a)
- self.outgoing[a].add(b)
- self.nodes |= {a, b}
-
- def __iter__(self):
- return iter(self.nodes)
-
- def __len__(self):
- return len(self.nodes)
-
- def edges_iter(self, data=True):
- assert data
- for (a, b), edges in self.edges.items():
- for edge in edges:
- yield a, b, edge
-
- def get_edge_data(self, a, b):
- return dict(enumerate(self.edges[(a, b)]))
-
- def add_node(self, node):
- self.nodes.add(node)
-
- def remove_node(self, node):
- for i in self.incoming.pop(node):
- del self.edges[(i, node)]
- self.outgoing[i].remove(node)
- for i in self.outgoing.pop(node):
- del self.edges[(node, i)]
- self.incoming[i].remove(node)
- self.nodes.remove(node)
-
- def remove_edge(self, a, b, key):
- e = self.edges[(a, b)]
- del e[key]
- if not e:
- self.incoming[b].remove(a)
- self.outgoing[a].remove(b)
-
- def in_edges(self, sink, data=True):
- assert data
- e = []
- for source in self.incoming[sink]:
- for edge in self.edges[(source, sink)]:
- e.append((source, sink, edge))
- return e
-
- def out_edges(self, source, data=True):
- assert data
- e = []
- for sink in self.outgoing[source]:
- for edge in self.edges[(source, sink)]:
- e.append((source, sink, edge))
- return e
+ def __init__(self):
+ self.edges = defaultdict(list)
+ self.incoming = defaultdict(set)
+ self.outgoing = defaultdict(set)
+ self.nodes = set()
+
+ def add_edge(self, a, b, **edge):
+ self.edges[(a, b)].append(edge)
+ self.incoming[b].add(a)
+ self.outgoing[a].add(b)
+ self.nodes |= {a, b}
+
+ def __iter__(self):
+ return iter(self.nodes)
+
+ def __len__(self):
+ return len(self.nodes)
+
+ def edges_iter(self, data=True):
+ assert data
+ for (a, b), edges in self.edges.items():
+ for edge in edges:
+ yield a, b, edge
+
+ def get_edge_data(self, a, b):
+ return dict(enumerate(self.edges[(a, b)]))
+
+ def add_node(self, node):
+ self.nodes.add(node)
+
+ def remove_node(self, node):
+ for i in self.incoming.pop(node):
+ del self.edges[(i, node)]
+ self.outgoing[i].remove(node)
+ for i in self.outgoing.pop(node):
+ del self.edges[(node, i)]
+ self.incoming[i].remove(node)
+ self.nodes.remove(node)
+
+ def remove_edge(self, a, b, key):
+ e = self.edges[(a, b)]
+ del e[key]
+ if not e:
+ self.incoming[b].remove(a)
+ self.outgoing[a].remove(b)
+
+ def in_edges(self, sink, data=True):
+ assert data
+ e = []
+ for source in self.incoming[sink]:
+ for edge in self.edges[(source, sink)]:
+ e.append((source, sink, edge))
+ return e
+
+ def out_edges(self, source, data=True):
+ assert data
+ e = []
+ for sink in self.outgoing[source]:
+ for edge in self.edges[(source, sink)]:
+ e.append((source, sink, edge))
+ return e
# TODO: rewrite this without non-determinism
class DataFlowGraph(MultiDiGraph):
- 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()
+ 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)
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
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}
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
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)
+ ]
"""
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<<j, self.o.eq(j)) for j in range(width))
- act["default"] = self.n.eq(1)
- self.comb += Case(self.i, act)
+ 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<<j, self.o.eq(j)) for j in range(width))
+ act["default"] = self.n.eq(1)
+ self.comb += Case(self.i, act)
class PriorityEncoder(Module):
- """Priority encode requests to binary
+ """Priority encode requests to binary
- If `n` is low, the `o` th bit in `i` is asserted and the bits below
- `o` are unasserted, else `o == 0`. The LSB has priority.
+ If `n` is low, the `o` th bit in `i` is asserted and the bits below
+ `o` are unasserted, else `o == 0`. The LSB has priority.
- Parameters
- ----------
- width : int
- Bit width of the input
+ Parameters
+ ----------
+ width : int
+ Bit width of the input
- Attributes
- ----------
- i : Signal(width), in
- Input requests
- o : Signal(max=width), out
- Encoded binary
- n : Signal(1), out
- Invalid, no input bits are asserted
- """
- def __init__(self, width):
- self.i = Signal(width) # one-hot, lsb has priority
- self.o = Signal(max=max(2, width)) # binary
- self.n = Signal() # none
- for j in range(width)[::-1]: # last has priority
- self.comb += If(self.i[j], self.o.eq(j))
- self.comb += self.n.eq(self.i == 0)
+ Attributes
+ ----------
+ i : Signal(width), in
+ Input requests
+ o : Signal(max=width), out
+ Encoded binary
+ n : Signal(1), out
+ Invalid, no input bits are asserted
+ """
+ def __init__(self, width):
+ self.i = Signal(width) # one-hot, lsb has priority
+ self.o = Signal(max=max(2, width)) # binary
+ self.n = Signal() # none
+ for j in range(width)[::-1]: # last has priority
+ self.comb += If(self.i[j], self.o.eq(j))
+ self.comb += self.n.eq(self.i == 0)
class Decoder(Module):
- """Decode binary to one-hot
+ """Decode binary to one-hot
- If `n` is low, the `i` th bit in `o` is asserted, the others are
- not, else `o == 0`.
+ If `n` is low, the `i` th bit in `o` is asserted, the others are
+ not, else `o == 0`.
- Parameters
- ----------
- width : int
- Bit width of the output
+ Parameters
+ ----------
+ width : int
+ Bit width of the output
- Attributes
- ----------
- i : Signal(max=width), in
- Input binary
- o : Signal(width), out
- Decoded one-hot
- n : Signal(1), in
- Invalid, no output bits are to be asserted
- """
+ Attributes
+ ----------
+ i : Signal(max=width), in
+ Input binary
+ o : Signal(width), out
+ Decoded one-hot
+ n : Signal(1), in
+ Invalid, no output bits are to be asserted
+ """
- def __init__(self, width):
- self.i = Signal(max=max(2, width)) # binary
- self.n = Signal() # none/invalid
- self.o = Signal(width) # one-hot
- act = dict((j, self.o.eq(1<<j)) for j in range(width))
- self.comb += Case(self.i, act)
- self.comb += If(self.n, self.o.eq(0))
+ def __init__(self, width):
+ self.i = Signal(max=max(2, width)) # binary
+ self.n = Signal() # none/invalid
+ self.o = Signal(width) # one-hot
+ act = dict((j, self.o.eq(1<<j)) for j in range(width))
+ self.comb += Case(self.i, act)
+ self.comb += If(self.n, self.o.eq(0))
class PriorityDecoder(Decoder):
- pass # same
+ pass # same
from migen.fhdl.std import *
class Complex:
- def __init__(self, real, imag):
- self.real = real
- self.imag = imag
+ def __init__(self, real, imag):
+ self.real = real
+ self.imag = imag
- def __neg__(self):
- return Complex(-self.real, -self.imag)
+ def __neg__(self):
+ return Complex(-self.real, -self.imag)
- def __add__(self, other):
- if isinstance(other, Complex):
- return Complex(self.real + other.real, self.imag + other.imag)
- else:
- return Complex(self.real + other, self.imag)
- __radd__ = __add__
- def __sub__(self, other):
- if isinstance(other, Complex):
- return Complex(self.real - other.real, self.imag - other.imag)
- else:
- return Complex(self.real - other, self.imag)
- def __rsub__(self, other):
- if isinstance(other, Complex):
- return Complex(other.real - self.real, other.imag - self.imag)
- else:
- return Complex(other - self.real, -self.imag)
- def __mul__(self, other):
- if isinstance(other, Complex):
- return Complex(self.real*other.real - self.imag*other.imag,
- self.real*other.imag + self.imag*other.real)
- else:
- return Complex(self.real*other, self.imag*other)
- __rmul__ = __mul__
+ def __add__(self, other):
+ if isinstance(other, Complex):
+ return Complex(self.real + other.real, self.imag + other.imag)
+ else:
+ return Complex(self.real + other, self.imag)
+ __radd__ = __add__
+ def __sub__(self, other):
+ if isinstance(other, Complex):
+ return Complex(self.real - other.real, self.imag - other.imag)
+ else:
+ return Complex(self.real - other, self.imag)
+ def __rsub__(self, other):
+ if isinstance(other, Complex):
+ return Complex(other.real - self.real, other.imag - self.imag)
+ else:
+ return Complex(other - self.real, -self.imag)
+ def __mul__(self, other):
+ if isinstance(other, Complex):
+ return Complex(self.real*other.real - self.imag*other.imag,
+ self.real*other.imag + self.imag*other.real)
+ else:
+ return Complex(self.real*other, self.imag*other)
+ __rmul__ = __mul__
- def __lshift__(self, other):
- return Complex(self.real << other, self.imag << other)
- def __rshift__(self, other):
- return Complex(self.real >> other, self.imag >> other)
+ def __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)
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)
+ )
+ ]
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)
+ ]
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))
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")
# 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.
# 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
# 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))
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))
# 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 "<Record " + ":".join(f[0] for f in self.layout) + " at " + hex(id(self)) + ">"
+ 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 "<Record " + ":".join(f[0] for f in self.layout) + " at " + hex(id(self)) + ">"
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")
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)
+ )
(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)
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])
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}();
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)
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()
#
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]
#
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()
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
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)
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)
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<<i for i in range(8)])
- else:
- self.assertEqual(tbp.dut.i, 1<<tbp.dut.o)
- self.run_with(cb, 256)
+ 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<<i for i in range(8)])
+ else:
+ self.assertEqual(tbp.dut.i, 1<<tbp.dut.o)
+ self.run_with(cb, 256)
class PrioEncCase(SimCase, unittest.TestCase):
- class TestBench(SimBench):
- def __init__(self):
- self.submodules.dut = PriorityEncoder(8)
+ class TestBench(SimBench):
+ def __init__(self):
+ self.submodules.dut = PriorityEncoder(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)
- i = tbp.dut.i
- if tbp.dut.n:
- self.assertEqual(i, 0)
- else:
- o = tbp.dut.o
- if o > 0:
- self.assertEqual(i & 1<<(o - 1), 0)
- self.assertGreaterEqual(i, 1<<o)
- self.run_with(cb, 256)
+ def test_run_sequence(self):
+ seq = list(range(1<<8))
+ def cb(tb, tbp):
+ if seq:
+ tbp.dut.i = seq.pop(0)
+ i = tbp.dut.i
+ if tbp.dut.n:
+ self.assertEqual(i, 0)
+ else:
+ o = tbp.dut.o
+ if o > 0:
+ self.assertEqual(i & 1<<(o - 1), 0)
+ self.assertGreaterEqual(i, 1<<o)
+ self.run_with(cb, 256)
class DecCase(SimCase, unittest.TestCase):
- class TestBench(SimBench):
- def __init__(self):
- self.submodules.dut = Decoder(8)
+ class TestBench(SimBench):
+ def __init__(self):
+ self.submodules.dut = Decoder(8)
- def test_sizes(self):
- self.assertEqual(flen(self.tb.dut.i), 3)
- self.assertEqual(flen(self.tb.dut.o), 8)
- self.assertEqual(flen(self.tb.dut.n), 1)
+ def test_sizes(self):
+ self.assertEqual(flen(self.tb.dut.i), 3)
+ self.assertEqual(flen(self.tb.dut.o), 8)
+ self.assertEqual(flen(self.tb.dut.n), 1)
- def test_run_sequence(self):
- seq = list(range(8*2))
- def cb(tb, tbp):
- if seq:
- i = seq.pop()
- tbp.dut.i = i//2
- tbp.dut.n = i%2
- i = tbp.dut.i
- o = tbp.dut.o
- if tbp.dut.n:
- self.assertEqual(o, 0)
- else:
- self.assertEqual(o, 1<<i)
- self.run_with(cb, 256)
+ def test_run_sequence(self):
+ seq = list(range(8*2))
+ def cb(tb, tbp):
+ if seq:
+ i = seq.pop()
+ tbp.dut.i = i//2
+ tbp.dut.n = i%2
+ i = tbp.dut.i
+ o = tbp.dut.o
+ if tbp.dut.n:
+ self.assertEqual(o, 0)
+ else:
+ self.assertEqual(o, 1<<i)
+ self.run_with(cb, 256)
class SmallPrioEncCase(SimCase, unittest.TestCase):
- class TestBench(SimBench):
- def __init__(self):
- self.submodules.dut = PriorityEncoder(1)
+ class TestBench(SimBench):
+ def __init__(self):
+ self.submodules.dut = PriorityEncoder(1)
- def test_sizes(self):
- self.assertEqual(flen(self.tb.dut.i), 1)
- self.assertEqual(flen(self.tb.dut.o), 1)
- self.assertEqual(flen(self.tb.dut.n), 1)
+ def test_sizes(self):
+ self.assertEqual(flen(self.tb.dut.i), 1)
+ self.assertEqual(flen(self.tb.dut.o), 1)
+ self.assertEqual(flen(self.tb.dut.n), 1)
- def test_run_sequence(self):
- seq = list(range(1))
- def cb(tb, tbp):
- if seq:
- tbp.dut.i = seq.pop(0)
- i = tbp.dut.i
- if tbp.dut.n:
- self.assertEqual(i, 0)
- else:
- o = tbp.dut.o
- if o > 0:
- self.assertEqual(i & 1<<(o - 1), 0)
- self.assertGreaterEqual(i, 1<<o)
- self.run_with(cb, 5)
+ def test_run_sequence(self):
+ seq = list(range(1))
+ def cb(tb, tbp):
+ if seq:
+ tbp.dut.i = seq.pop(0)
+ i = tbp.dut.i
+ if tbp.dut.n:
+ self.assertEqual(i, 0)
+ else:
+ o = tbp.dut.o
+ if o > 0:
+ self.assertEqual(i & 1<<(o - 1), 0)
+ self.assertGreaterEqual(i, 1<<o)
+ self.run_with(cb, 5)
from migen.test.support import SimCase, SimBench
class SyncFIFOCase(SimCase, unittest.TestCase):
- class TestBench(SimBench):
- def __init__(self):
- self.submodules.dut = SyncFIFO([("a", 32), ("b", 32)], 2)
+ class TestBench(SimBench):
+ def __init__(self):
+ self.submodules.dut = SyncFIFO([("a", 32), ("b", 32)], 2)
- self.sync += [
- If(self.dut.we & self.dut.writable,
- self.dut.din.a.eq(self.dut.din.a + 1),
- self.dut.din.b.eq(self.dut.din.b + 2)
- )
- ]
+ self.sync += [
+ If(self.dut.we & self.dut.writable,
+ self.dut.din.a.eq(self.dut.din.a + 1),
+ self.dut.din.b.eq(self.dut.din.b + 2)
+ )
+ ]
- def test_sizes(self):
- self.assertEqual(flen(self.tb.dut.din_bits), 64)
- self.assertEqual(flen(self.tb.dut.dout_bits), 64)
+ def test_sizes(self):
+ self.assertEqual(flen(self.tb.dut.din_bits), 64)
+ self.assertEqual(flen(self.tb.dut.dout_bits), 64)
- def test_run_sequence(self):
- seq = list(range(20))
- def cb(tb, tbp):
- # fire re and we at "random"
- tbp.dut.we = tbp.simulator.cycle_counter % 2 == 0
- tbp.dut.re = tbp.simulator.cycle_counter % 3 == 0
- # the output if valid must be correct
- if tbp.dut.readable and tbp.dut.re:
- try:
- i = seq.pop(0)
- except IndexError:
- raise StopSimulation
- self.assertEqual(tbp.dut.dout.a, i)
- self.assertEqual(tbp.dut.dout.b, i*2)
- self.run_with(cb)
+ def test_run_sequence(self):
+ seq = list(range(20))
+ def cb(tb, tbp):
+ # fire re and we at "random"
+ tbp.dut.we = tbp.simulator.cycle_counter % 2 == 0
+ tbp.dut.re = tbp.simulator.cycle_counter % 3 == 0
+ # the output if valid must be correct
+ if tbp.dut.readable and tbp.dut.re:
+ try:
+ i = seq.pop(0)
+ except IndexError:
+ raise StopSimulation
+ self.assertEqual(tbp.dut.dout.a, i)
+ self.assertEqual(tbp.dut.dout.b, i*2)
+ self.run_with(cb)
- def test_replace(self):
- seq = [x for x in range(20) if x % 5]
- def cb(tb, tbp):
- tbp.dut.we = tbp.simulator.cycle_counter % 2 == 0
- tbp.dut.re = tbp.simulator.cycle_counter % 3 == 0
- tbp.dut.replace = tbp.dut.din.a % 5 == 1
- if tbp.dut.readable and tbp.dut.re:
- try:
- i = seq.pop(0)
- except IndexError:
- raise StopSimulation
- self.assertEqual(tbp.dut.dout.a, i)
- self.assertEqual(tbp.dut.dout.b, i*2)
- self.run_with(cb)
+ def test_replace(self):
+ seq = [x for x in range(20) if x % 5]
+ def cb(tb, tbp):
+ tbp.dut.we = tbp.simulator.cycle_counter % 2 == 0
+ tbp.dut.re = tbp.simulator.cycle_counter % 3 == 0
+ tbp.dut.replace = tbp.dut.din.a % 5 == 1
+ if tbp.dut.readable and tbp.dut.re:
+ try:
+ i = seq.pop(0)
+ except IndexError:
+ raise StopSimulation
+ self.assertEqual(tbp.dut.dout.a, i)
+ self.assertEqual(tbp.dut.dout.b, i*2)
+ self.run_with(cb)
from migen.test.support import SimCase, SimBench
class SignedCase(SimCase, unittest.TestCase):
- 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))
+ 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)
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, [])
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<<flen(i)))
- self.assertEqual(sorted(list(tbp.dut.i)), list(tbp.dut.o))
- self.run_with(cb, 20)
+ def test_sort(self):
+ def cb(tb, tbp):
+ for i in tb.dut.i:
+ tbp.simulator.wr(i, randrange(1<<flen(i)))
+ self.assertEqual(sorted(list(tbp.dut.i)), list(tbp.dut.o))
+ self.run_with(cb, 20)
import collections
def flat_iteration(l):
- for element in l:
- if isinstance(element, collections.Iterable):
- for element2 in flat_iteration(element):
- yield element2
- else:
- yield element
+ for element in l:
+ if isinstance(element, collections.Iterable):
+ for element2 in flat_iteration(element):
+ yield element2
+ else:
+ yield element
def xdir(obj, return_values=False):
- for attr in dir(obj):
- if attr[:2] != "__" and attr[-2:] != "__":
- if return_values:
- yield attr, getattr(obj, attr)
- else:
- yield attr
+ for attr in dir(obj):
+ if attr[:2] != "__" and attr[-2:] != "__":
+ if return_values:
+ yield attr, getattr(obj, attr)
+ else:
+ yield attr
def autotype(s):
- if s == "True":
- return True
- elif s == "False":
- return False
- try:
- return int(s, 0)
- except ValueError:
- pass
- return s
+ if s == "True":
+ return True
+ elif s == "False":
+ return False
+ try:
+ return int(s, 0)
+ except ValueError:
+ pass
+ return s
def gcd_multiple(numbers):
- l = len(numbers)
- if l == 1:
- return numbers[0]
- else:
- s = l//2
- return gcd(gcd_multiple(numbers[:s]), gcd_multiple(numbers[s:]))
+ l = len(numbers)
+ if l == 1:
+ return numbers[0]
+ else:
+ s = l//2
+ return gcd(gcd_multiple(numbers[:s]), gcd_multiple(numbers[s:]))
import math
def _cairo_draw_node(ctx, dx, radius, color, outer_color, s):
- ctx.save()
+ ctx.save()
- ctx.translate(dx, 0)
+ ctx.translate(dx, 0)
- ctx.set_line_width(0.0)
- gradient_color = cairo.RadialGradient(0, 0, 0, 0, 0, radius)
- gradient_color.add_color_stop_rgb(0, *color)
- gradient_color.add_color_stop_rgb(1, *outer_color)
- ctx.set_source(gradient_color)
- ctx.arc(0, 0, radius, 0, 2*math.pi)
- ctx.fill()
+ ctx.set_line_width(0.0)
+ gradient_color = cairo.RadialGradient(0, 0, 0, 0, 0, radius)
+ gradient_color.add_color_stop_rgb(0, *color)
+ gradient_color.add_color_stop_rgb(1, *outer_color)
+ ctx.set_source(gradient_color)
+ ctx.arc(0, 0, radius, 0, 2*math.pi)
+ ctx.fill()
- lines = s.split("\n")
- textws = []
- texths = []
- for line in lines:
- x_bearing, y_bearing, w, h, x_advance, y_advance = ctx.text_extents(line)
- textws.append(w)
- texths.append(h + 2)
- ctx.translate(0, -sum(texths[1:])/2)
- for line, w, h in zip(lines, textws, texths):
- ctx.translate(-w/2, h/2)
- ctx.move_to(0, 0)
- ctx.set_source_rgb(0, 0, 0)
- ctx.show_text(line)
- ctx.translate(w/2, h/2)
+ lines = s.split("\n")
+ textws = []
+ texths = []
+ for line in lines:
+ x_bearing, y_bearing, w, h, x_advance, y_advance = ctx.text_extents(line)
+ textws.append(w)
+ texths.append(h + 2)
+ ctx.translate(0, -sum(texths[1:])/2)
+ for line, w, h in zip(lines, textws, texths):
+ ctx.translate(-w/2, h/2)
+ ctx.move_to(0, 0)
+ ctx.set_source_rgb(0, 0, 0)
+ ctx.show_text(line)
+ ctx.translate(w/2, h/2)
- ctx.restore()
+ ctx.restore()
def _cairo_draw_connection(ctx, x0, y0, color0, x1, y1, color1):
- ctx.move_to(x0, y0)
- ctx.curve_to(x0, y0+20, x1, y1-20, x1, y1)
- ctx.set_line_width(1.2)
- gradient_color = cairo.LinearGradient(x0, y0, x1, y1)
- gradient_color.add_color_stop_rgb(0, *color0)
- gradient_color.add_color_stop_rgb(1, *color1)
- ctx.set_source(gradient_color)
- ctx.stroke()
+ ctx.move_to(x0, y0)
+ ctx.curve_to(x0, y0+20, x1, y1-20, x1, y1)
+ ctx.set_line_width(1.2)
+ gradient_color = cairo.LinearGradient(x0, y0, x1, y1)
+ gradient_color.add_color_stop_rgb(0, *color0)
+ gradient_color.add_color_stop_rgb(1, *color1)
+ ctx.set_source(gradient_color)
+ ctx.stroke()
class RenderNode:
- def __init__(self, label, children=None, color=(0.8, 0.8, 0.8), radius=40):
- self.label = label
- if children is None:
- children = []
- self.children = children
- self.color = color
- self.outer_color = (color[0]*3/5, color[1]*3/5, color[2]*3/5)
- self.radius = radius
- self.pitch = self.radius*3
+ def __init__(self, label, children=None, color=(0.8, 0.8, 0.8), radius=40):
+ self.label = label
+ if children is None:
+ children = []
+ self.children = children
+ self.color = color
+ self.outer_color = (color[0]*3/5, color[1]*3/5, color[2]*3/5)
+ self.radius = radius
+ self.pitch = self.radius*3
- def get_dimensions(self):
- if self.children:
- cws, chs, cdxs = zip(*[c.get_dimensions() for c in self.children])
- w = sum(cws)
- h = self.pitch + max(chs)
- dx = cws[0]/4 - cws[-1]/4
- else:
- w = h = self.pitch
- dx = 0
- return w, h, dx
+ def get_dimensions(self):
+ if self.children:
+ cws, chs, cdxs = zip(*[c.get_dimensions() for c in self.children])
+ w = sum(cws)
+ h = self.pitch + max(chs)
+ dx = cws[0]/4 - cws[-1]/4
+ else:
+ w = h = self.pitch
+ dx = 0
+ return w, h, dx
- def render(self, ctx):
- if self.children:
- cws, chs, cdxs = zip(*[c.get_dimensions() for c in self.children])
- first_child_x = -sum(cws)/2
+ def render(self, ctx):
+ if self.children:
+ cws, chs, cdxs = zip(*[c.get_dimensions() for c in self.children])
+ first_child_x = -sum(cws)/2
- ctx.save()
- ctx.translate(first_child_x, self.pitch)
- for c, w in zip(self.children, cws):
- ctx.translate(w/2, 0)
- c.render(ctx)
- ctx.translate(w/2, 0)
- ctx.restore()
+ ctx.save()
+ ctx.translate(first_child_x, self.pitch)
+ for c, w in zip(self.children, cws):
+ ctx.translate(w/2, 0)
+ c.render(ctx)
+ ctx.translate(w/2, 0)
+ ctx.restore()
- dx = cws[0]/4 - cws[-1]/4
+ dx = cws[0]/4 - cws[-1]/4
- current_x = first_child_x
- for c, w, cdx in zip(self.children, cws, cdxs):
- current_y = self.pitch - c.radius
- current_x += w/2
- _cairo_draw_connection(ctx, dx, self.radius, self.outer_color, current_x+cdx, current_y, c.outer_color)
- current_x += w/2
- else:
- dx = 0
- _cairo_draw_node(ctx, dx, self.radius, self.color, self.outer_color, self.label)
+ current_x = first_child_x
+ for c, w, cdx in zip(self.children, cws, cdxs):
+ current_y = self.pitch - c.radius
+ current_x += w/2
+ _cairo_draw_connection(ctx, dx, self.radius, self.outer_color, current_x+cdx, current_y, c.outer_color)
+ current_x += w/2
+ else:
+ dx = 0
+ _cairo_draw_node(ctx, dx, self.radius, self.color, self.outer_color, self.label)
- def to_svg(self, name):
- w, h, dx = self.get_dimensions()
- surface = cairo.SVGSurface(name, w, h)
- ctx = cairo.Context(surface)
- ctx.translate(w/2, self.pitch/2)
- self.render(ctx)
- surface.finish()
+ def to_svg(self, name):
+ w, h, dx = self.get_dimensions()
+ surface = cairo.SVGSurface(name, w, h)
+ ctx = cairo.Context(surface)
+ ctx.translate(w/2, self.pitch/2)
+ self.render(ctx)
+ surface.finish()
def _test():
- xns = [RenderNode("X"+str(n)) for n in range(5)]
- yns = [RenderNode("Y"+str(n), [RenderNode("foo", color=(0.1*n, 0.5+0.2*n, 1.0-0.3*n))]) for n in range(3)]
- n1 = RenderNode("n1", yns)
- n2 = RenderNode("n2", xns, color=(0.8, 0.5, 0.9))
- top = RenderNode("top", [n1, n2])
- top.to_svg("test.svg")
+ xns = [RenderNode("X"+str(n)) for n in range(5)]
+ yns = [RenderNode("Y"+str(n), [RenderNode("foo", color=(0.1*n, 0.5+0.2*n, 1.0-0.3*n))]) for n in range(3)]
+ n1 = RenderNode("n1", yns)
+ n2 = RenderNode("n2", xns, color=(0.8, 0.5, 0.9))
+ top = RenderNode("top", [n1, n2])
+ top.to_svg("test.svg")
if __name__ == "__main__":
- _test()
+ _test()
required_version = (3, 3)
if sys.version_info < required_version:
- raise SystemExit("Migen requires python {0} or greater".format(
- ".".join(map(str, required_version))))
+ raise SystemExit("Migen requires python {0} or greater".format(
+ ".".join(map(str, required_version))))
setup(
- name="migen",
- version="unknown",
- description="Python toolbox for building complex digital hardware",
- long_description=README,
- author="Sebastien Bourdeauducq",
- author_email="sb@m-labs.hk",
- url="http://m-labs.hk",
- download_url="https://github.com/m-labs/migen",
- packages=find_packages(here),
- test_suite="migen.test",
- license="BSD",
- platforms=["Any"],
- keywords="HDL ASIC FPGA hardware design",
- classifiers=[
- "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)",
- "Environment :: Console",
- "Development Status :: Alpha",
- "Intended Audience :: Developers",
- "License :: OSI Approved :: BSD License",
- "Operating System :: OS Independent",
- "Programming Language :: Python",
- ],
+ name="migen",
+ version="unknown",
+ description="Python toolbox for building complex digital hardware",
+ long_description=README,
+ author="Sebastien Bourdeauducq",
+ author_email="sb@m-labs.hk",
+ url="http://m-labs.hk",
+ download_url="https://github.com/m-labs/migen",
+ packages=find_packages(here),
+ test_suite="migen.test",
+ license="BSD",
+ platforms=["Any"],
+ keywords="HDL ASIC FPGA hardware design",
+ classifiers=[
+ "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)",
+ "Environment :: Console",
+ "Development Status :: Alpha",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: BSD License",
+ "Operating System :: OS Independent",
+ "Programming Language :: Python",
+ ],
)