From: Sebastien Bourdeauducq Date: Tue, 12 Jun 2012 15:49:50 +0000 (+0200) Subject: Reorganize examples folder X-Git-Tag: 24jan2021_ls180~2099^2~923 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=973c00938d8701df595e1504c89c6279d7b72bb6;p=litex.git Reorganize examples folder --- diff --git a/doc/index.rst b/doc/index.rst index 4aa17977..0e3e8eef 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -572,25 +572,30 @@ Simulation examples Most basic ========== -.. include:: ../examples/basic_sim.py +.. include:: ../examples/sim/basic1.py :code: python A few more features =================== -.. include:: ../examples/basic2_sim.py +.. include:: ../examples/sim/basic2.py :code: python Memory access ============= -.. include:: ../examples/memory_sim.py +.. include:: ../examples/sim/memory.py :code: python A FIR filter ============ -.. include:: ../examples/fir.py +.. include:: ../examples/sim/fir.py :code: python Abstract bus transactions ========================= -.. include:: ../examples/abstract_transactions.py +.. include:: ../examples/sim/abstract_transactions.py + :code: python + +Dataflow simulation actors +========================== +.. include:: ../examples/sim/dataflow.py :code: python diff --git a/examples/abstract_transactions.py b/examples/abstract_transactions.py deleted file mode 100644 index 09a5dfe7..00000000 --- a/examples/abstract_transactions.py +++ /dev/null @@ -1,116 +0,0 @@ -# Copyright (C) 2012 Vermeer Manufacturing Co. -# License: GPLv3 with additional permissions (see README). - -from random import Random - -from migen.fhdl.structure import * -from migen.fhdl import autofragment -from migen.bus.transactions import * -from migen.bus import wishbone, asmibus -from migen.sim.generic import Simulator -from migen.sim.icarus import Runner - -# Our bus master. -# Python generators let us program bus transactions in an elegant sequential style. -def my_generator(): - 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 - - # 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 MyModel: - def read(self, address): - return address + 4 - -class MyModelWB(MyModel, wishbone.TargetModel): - def __init__(self): - self.prng = Random(763627) - - def can_ack(self, bus): - # Simulate variable latency. - return self.prng.randrange(0, 2) - -class MyModelASMI(MyModel, asmibus.TargetModel): - pass - -def test_wishbone(): - print("*** Wishbone test") - - # The "wishbone.Initiator" library component runs our generator - # and manipulates the bus signals accordingly. - master = wishbone.Initiator(my_generator()) - # The "wishbone.Target" library component examines the bus signals - # and calls into our model object. - slave = wishbone.Target(MyModelWB()) - # The "wishbone.Tap" library component examines the bus at the slave port - # and displays the transactions on the console (/). - tap = wishbone.Tap(slave.bus) - # Connect the master to the slave. - intercon = wishbone.InterconnectPointToPoint(master.bus, slave.bus) - # A small extra simulation function to terminate the process when - # the initiator is done (i.e. our generator is exhausted). - def end_simulation(s): - s.interrupt = master.done - fragment = autofragment.from_local() + Fragment(sim=[end_simulation]) - sim = Simulator(fragment, Runner()) - sim.run() - -def test_asmi(): - print("*** ASMI test") - - # Create a hub with one port for our initiator. - hub = asmibus.Hub(32, 32) - port = hub.get_port() - hub.finalize() - # Create the initiator, target and tap (similar to the Wishbone case). - master = asmibus.Initiator(port, my_generator()) - slave = asmibus.Target(hub, MyModelASMI()) - tap = asmibus.Tap(hub) - # Run the simulation (same as the Wishbone case). - def end_simulation(s): - s.interrupt = master.done - fragment = autofragment.from_local() + Fragment(sim=[end_simulation]) - sim = Simulator(fragment, Runner()) - sim.run() - -test_wishbone() -test_asmi() - -# Output: -# -# Wrote in 0 cycle(s) -# -# Wrote in 0 cycle(s) -# -# Wrote in 0 cycle(s) -# -# Wrote in 1 cycle(s) -# -# Wrote in 1 cycle(s) -# -# Wrote in 2 cycle(s) -# ... -# -# Read 4 in 2 cycle(s) -# -# Read 5 in 2 cycle(s) -# -# Read 6 in 1 cycle(s) -# -# Read 7 in 1 cycle(s) -# ... diff --git a/examples/basic/fsm.py b/examples/basic/fsm.py new file mode 100644 index 00000000..f1716aea --- /dev/null +++ b/examples/basic/fsm.py @@ -0,0 +1,9 @@ +from migen.fhdl.structure import * +from migen.fhdl import verilog +from migen.corelogic.fsm import FSM + +s = Signal() +myfsm = FSM("FOO", "BAR") +myfsm.act(myfsm.FOO, s.eq(1), myfsm.next_state(myfsm.BAR)) +myfsm.act(myfsm.BAR, s.eq(0), myfsm.next_state(myfsm.FOO)) +print(verilog.convert(myfsm.get_fragment(), {s})) diff --git a/examples/basic/lm32_inst.py b/examples/basic/lm32_inst.py new file mode 100644 index 00000000..678dca55 --- /dev/null +++ b/examples/basic/lm32_inst.py @@ -0,0 +1,46 @@ +from migen.fhdl.structure import * +from migen.fhdl import verilog + +class LM32: + def __init__(self): + self.inst = Instance("lm32_top", + [("I_ADR_O", BV(32)), + ("I_DAT_O", BV(32)), + ("I_SEL_O", BV(4)), + ("I_CYC_O", BV(1)), + ("I_STB_O", BV(1)), + ("I_WE_O", BV(1)), + ("I_CTI_O", BV(3)), + ("I_LOCK_O", BV(1)), + ("I_BTE_O", BV(1)), + ("D_ADR_O", BV(32)), + ("D_DAT_O", BV(32)), + ("D_SEL_O", BV(4)), + ("D_CYC_O", BV(1)), + ("D_STB_O", BV(1)), + ("D_WE_O", BV(1)), + ("D_CTI_O", BV(3)), + ("D_LOCK_O", BV(1)), + ("D_BTE_O", BV(1))], + [("interrupt", BV(32)), + ("ext_break", BV(1)), + ("I_DAT_I", BV(32)), + ("I_ACK_I", BV(1)), + ("I_ERR_I", BV(1)), + ("I_RTY_I", BV(1)), + ("D_DAT_I", BV(32)), + ("D_ACK_I", BV(1)), + ("D_ERR_I", BV(1)), + ("D_RTY_I", BV(1))], + clkport="clk_i", + rstport="rst_i", + name="lm32") + + def get_fragment(self): + return Fragment(instances=[self.inst]) + +cpus = [LM32() for i in range(4)] +frag = Fragment() +for cpu in cpus: + frag += cpu.get_fragment() +print(verilog.convert(frag, set([cpus[0].inst.ins["interrupt"], cpus[0].inst.outs["I_WE_O"]]))) diff --git a/examples/basic/memory.py b/examples/basic/memory.py new file mode 100644 index 00000000..ec61c83a --- /dev/null +++ b/examples/basic/memory.py @@ -0,0 +1,23 @@ +from migen.fhdl.structure import * +from migen.fhdl import verilog + +d = 100 +d_b = bits_for(d-1) +w = 32 + +a1 = Signal(BV(d_b)) +d1 = Signal(BV(w)) +we1 = Signal(BV(4)) +dw1 = Signal(BV(w)) +re = Signal() +p1 = MemoryPort(a1, d1, we1, dw1, we_granularity=8) + +a2 = Signal(BV(d_b)) +d2 = Signal(BV(w)) +re2 = Signal() +p2 = MemoryPort(a2, d2, re=re2) + +mem = Memory(w, d, p1, p2, init=[5, 18, 32]) +f = Fragment(memories=[mem]) +v = verilog.convert(f, ios={a1, d1, we1, dw1, a2, d2, re2}) +print(v) diff --git a/examples/basic/simple_gpio.py b/examples/basic/simple_gpio.py new file mode 100644 index 00000000..1a738791 --- /dev/null +++ b/examples/basic/simple_gpio.py @@ -0,0 +1,23 @@ +from migen.fhdl.structure import * +from migen.fhdl import verilog +from migen.bank import description, csrgen +from migen.bank.description import READ_ONLY, WRITE_ONLY + +ninputs = 32 +noutputs = 32 + +oreg = description.RegisterField("o", noutputs) +ireg = description.RegisterField("i", ninputs, READ_ONLY, WRITE_ONLY) + +# input path +gpio_in = Signal(BV(ninputs)) +gpio_in_s = Signal(BV(ninputs)) # synchronizer +insync = [gpio_in_s.eq(gpio_in), ireg.field.w.eq(gpio_in_s)] +inf = Fragment(sync=insync) + +bank = csrgen.Bank([oreg, ireg]) +f = bank.get_fragment() + inf +oreg.field.r.name_override = "gpio_out" +i = bank.interface +v = verilog.convert(f, {i.dat_r, oreg.field.r, i.adr, i.we, i.dat_w, gpio_in}) +print(v) diff --git a/examples/basic/two_dividers.py b/examples/basic/two_dividers.py new file mode 100644 index 00000000..d82f8af1 --- /dev/null +++ b/examples/basic/two_dividers.py @@ -0,0 +1,10 @@ +from migen.fhdl import verilog +from migen.corelogic import divider + +d1 = divider.Divider(16) +d2 = divider.Divider(16) +frag = d1.get_fragment() + d2.get_fragment() +o = verilog.convert(frag, { + 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}) +print(o) diff --git a/examples/basic/using_record.py b/examples/basic/using_record.py new file mode 100644 index 00000000..7c757aa4 --- /dev/null +++ b/examples/basic/using_record.py @@ -0,0 +1,20 @@ +from migen.fhdl.structure import * +from migen.corelogic.record import * + +L = [ + ("x", BV(10), 8), + ("y", BV(10), 8), + ("level2", [ + ("a", BV(5), 32), + ("b", BV(5), 16) + ]) +] + +myrec = Record(L) +print(myrec.flatten()) +print(myrec.flatten(True)) +s = myrec.subrecord("level2/a", "x") +print(s.flatten()) +print(s.level2.layout()) +myrec2 = myrec.copy() +print(myrec2.flatten()) diff --git a/examples/basic2_sim.py b/examples/basic2_sim.py deleted file mode 100644 index a4387f76..00000000 --- a/examples/basic2_sim.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright (C) 2012 Vermeer Manufacturing Co. -# License: GPLv3 with additional permissions (see README). - -from migen.fhdl.structure import * -from migen.sim.generic import Simulator, TopLevel -from migen.sim.icarus import Runner - -# A slightly improved counter. -# Has a clock enable (CE) signal, counts on more bits -# and resets with a negative number. -class Counter: - def __init__(self): - self.ce = Signal() - # Demonstrate negative numbers and signals larger than 32 bits. - self.count = Signal(BV(37, True), reset=-5) - - def do_simulation(self, s): - # Only assert CE every second cycle. - # => each counter value is held for two cycles. - if s.cycle_counter % 2: - s.wr(self.ce, 0) # This is how you write to a signal. - else: - s.wr(self.ce, 1) - print("Cycle: " + str(s.cycle_counter) + " Count: " + \ - str(s.rd(self.count))) - # Set the "initialize" property on our simulation function. - # The simulator will call it during the reset cycle, - # with s.cycle_counter == -1. - do_simulation.initialize = True - - # Output is: - # Cycle: -1 Count: 0 - # Cycle: 0 Count: -5 - # Cycle: 1 Count: -5 - # Cycle: 2 Count: -4 - # Cycle: 3 Count: -4 - # Cycle: 4 Count: -3 - # ... - - def get_fragment(self): - sync = [If(self.ce, self.count.eq(self.count + 1))] - sim = [self.do_simulation] - return Fragment(sync=sync, sim=sim) - -def main(): - dut = Counter() - # Instantiating the generic top-level ourselves lets us - # specify a VCD output file. - sim = Simulator(dut.get_fragment(), Runner(), TopLevel("my.vcd")) - sim.run(20) - -main() diff --git a/examples/basic_sim.py b/examples/basic_sim.py deleted file mode 100644 index af00d0df..00000000 --- a/examples/basic_sim.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (C) 2012 Vermeer Manufacturing Co. -# License: GPLv3 with additional permissions (see README). - -from migen.fhdl.structure import * -from migen.sim.generic import Simulator -from migen.sim.icarus import Runner - -# Our simple counter, which increments at every cycle -# and prints its current value in simulation. -class Counter: - def __init__(self): - self.count = Signal(BV(4)) - - # This function will be called at every cycle. - def do_simulation(self, s): - # Simply read the count signal and print it. - # The output is: - # Count: 0 - # Count: 1 - # Count: 2 - # ... - print("Count: " + str(s.rd(self.count))) - - def get_fragment(self): - # At each cycle, increase the value of the count signal. - # We do it with convertible/synthesizable FHDL code. - sync = [self.count.eq(self.count + 1)] - # List our simulation function in the fragment. - sim = [self.do_simulation] - return Fragment(sync=sync, sim=sim) - -def main(): - dut = Counter() - # Use the Icarus Verilog runner. - # We do not specify a top-level object, and use the default. - sim = Simulator(dut.get_fragment(), Runner()) - # Since we do not use sim.interrupt, limit the simulation - # to some number of cycles. - sim.run(20) - -main() diff --git a/examples/corelogic_conv.py b/examples/corelogic_conv.py deleted file mode 100644 index d82f8af1..00000000 --- a/examples/corelogic_conv.py +++ /dev/null @@ -1,10 +0,0 @@ -from migen.fhdl import verilog -from migen.corelogic import divider - -d1 = divider.Divider(16) -d2 = divider.Divider(16) -frag = d1.get_fragment() + d2.get_fragment() -o = verilog.convert(frag, { - 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}) -print(o) diff --git a/examples/dataflow.py b/examples/dataflow.py deleted file mode 100644 index f6e78677..00000000 --- a/examples/dataflow.py +++ /dev/null @@ -1,23 +0,0 @@ -import sys - -from migen.fhdl import verilog -from migen.flow.ala import * -from migen.flow.network import * -from migen.flow.composer import * - -g = DataFlowGraph() -a1 = make_composable(g, Add(BV(16))) -a2 = make_composable(g, Add(BV(16))) -a3 = make_composable(g, Add(BV(16))) -c3 = (a1 + a2)*a3 -c = CompositeActor(g) - -frag = c.get_fragment() - -print(verilog.convert(frag)) - -if len(sys.argv) > 1 and sys.argv[1] == "draw": - import matplotlib.pyplot as plt - import networkx as nx - nx.draw(g) - plt.show() diff --git a/examples/dataflow/arithmetic.py b/examples/dataflow/arithmetic.py new file mode 100644 index 00000000..f6e78677 --- /dev/null +++ b/examples/dataflow/arithmetic.py @@ -0,0 +1,23 @@ +import sys + +from migen.fhdl import verilog +from migen.flow.ala import * +from migen.flow.network import * +from migen.flow.composer import * + +g = DataFlowGraph() +a1 = make_composable(g, Add(BV(16))) +a2 = make_composable(g, Add(BV(16))) +a3 = make_composable(g, Add(BV(16))) +c3 = (a1 + a2)*a3 +c = CompositeActor(g) + +frag = c.get_fragment() + +print(verilog.convert(frag)) + +if len(sys.argv) > 1 and sys.argv[1] == "draw": + import matplotlib.pyplot as plt + import networkx as nx + nx.draw(g) + plt.show() diff --git a/examples/dataflow/dma.py b/examples/dataflow/dma.py new file mode 100644 index 00000000..9b2491ec --- /dev/null +++ b/examples/dataflow/dma.py @@ -0,0 +1,89 @@ +from random import Random + +from migen.fhdl import verilog +from migen.flow.ala import * +from migen.flow.network import * +from migen.actorlib import dma_wishbone +from migen.actorlib.sim import * +from migen.bus import wishbone +from migen.sim.generic import Simulator +from migen.sim.icarus import Runner + +class MyModel(wishbone.TargetModel): + def __init__(self): + self.prng = Random(763627) + + def read(self, address): + return address + 4 + + def can_ack(self, bus): + return self.prng.randrange(0, 2) + +def adrgen_gen(): + for i in range(10): + print("Address: " + str(i)) + yield Token("address", {"a": i}) + +def dumper_gen(): + while True: + t = Token("data") + yield t + print("Received: " + str(t.value["d"])) + +def test_reader(): + print("*** Testing reader") + adrgen = SimActor(adrgen_gen(), ("address", Source, [("a", BV(30))])) + reader = dma_wishbone.Reader() + dumper = SimActor(dumper_gen(), ("data", Sink, [("d", BV(32))])) + g = DataFlowGraph() + g.add_connection(adrgen, reader) + g.add_connection(reader, dumper) + comp = CompositeActor(g) + + peripheral = wishbone.Target(MyModel()) + interconnect = wishbone.InterconnectPointToPoint(reader.bus, peripheral.bus) + + def end_simulation(s): + s.interrupt = adrgen.done and not s.rd(comp.busy) + + fragment = comp.get_fragment() \ + + peripheral.get_fragment() \ + + interconnect.get_fragment() \ + + Fragment(sim=[end_simulation]) + + sim = Simulator(fragment, Runner()) + sim.run() + +def trgen_gen(): + for i in range(10): + a = i + d = i+10 + print("Address: " + str(a) + " Data: " + str(d)) + yield Token("address_data", {"a": a, "d": d}) + +def test_writer(): + print("*** Testing writer") + trgen = SimActor(trgen_gen(), ("address_data", Source, [("a", BV(30)), ("d", BV(32))])) + writer = dma_wishbone.Writer() + g = DataFlowGraph() + g.add_connection(trgen, writer) + comp = CompositeActor(g) + + peripheral = wishbone.Target(MyModel()) + tap = wishbone.Tap(peripheral.bus) + interconnect = wishbone.InterconnectPointToPoint(writer.bus, peripheral.bus) + + def end_simulation(s): + s.interrupt = trgen.done and not s.rd(comp.busy) + + fragment = comp.get_fragment() \ + + peripheral.get_fragment() \ + + tap.get_fragment() \ + + interconnect.get_fragment() \ + + Fragment(sim=[end_simulation]) + + sim = Simulator(fragment, Runner()) + sim.run() + +test_reader() +test_writer() diff --git a/examples/dataflow_dma.py b/examples/dataflow_dma.py deleted file mode 100644 index 9b2491ec..00000000 --- a/examples/dataflow_dma.py +++ /dev/null @@ -1,89 +0,0 @@ -from random import Random - -from migen.fhdl import verilog -from migen.flow.ala import * -from migen.flow.network import * -from migen.actorlib import dma_wishbone -from migen.actorlib.sim import * -from migen.bus import wishbone -from migen.sim.generic import Simulator -from migen.sim.icarus import Runner - -class MyModel(wishbone.TargetModel): - def __init__(self): - self.prng = Random(763627) - - def read(self, address): - return address + 4 - - def can_ack(self, bus): - return self.prng.randrange(0, 2) - -def adrgen_gen(): - for i in range(10): - print("Address: " + str(i)) - yield Token("address", {"a": i}) - -def dumper_gen(): - while True: - t = Token("data") - yield t - print("Received: " + str(t.value["d"])) - -def test_reader(): - print("*** Testing reader") - adrgen = SimActor(adrgen_gen(), ("address", Source, [("a", BV(30))])) - reader = dma_wishbone.Reader() - dumper = SimActor(dumper_gen(), ("data", Sink, [("d", BV(32))])) - g = DataFlowGraph() - g.add_connection(adrgen, reader) - g.add_connection(reader, dumper) - comp = CompositeActor(g) - - peripheral = wishbone.Target(MyModel()) - interconnect = wishbone.InterconnectPointToPoint(reader.bus, peripheral.bus) - - def end_simulation(s): - s.interrupt = adrgen.done and not s.rd(comp.busy) - - fragment = comp.get_fragment() \ - + peripheral.get_fragment() \ - + interconnect.get_fragment() \ - + Fragment(sim=[end_simulation]) - - sim = Simulator(fragment, Runner()) - sim.run() - -def trgen_gen(): - for i in range(10): - a = i - d = i+10 - print("Address: " + str(a) + " Data: " + str(d)) - yield Token("address_data", {"a": a, "d": d}) - -def test_writer(): - print("*** Testing writer") - trgen = SimActor(trgen_gen(), ("address_data", Source, [("a", BV(30)), ("d", BV(32))])) - writer = dma_wishbone.Writer() - g = DataFlowGraph() - g.add_connection(trgen, writer) - comp = CompositeActor(g) - - peripheral = wishbone.Target(MyModel()) - tap = wishbone.Tap(peripheral.bus) - interconnect = wishbone.InterconnectPointToPoint(writer.bus, peripheral.bus) - - def end_simulation(s): - s.interrupt = trgen.done and not s.rd(comp.busy) - - fragment = comp.get_fragment() \ - + peripheral.get_fragment() \ - + tap.get_fragment() \ - + interconnect.get_fragment() \ - + Fragment(sim=[end_simulation]) - - sim = Simulator(fragment, Runner()) - sim.run() - -test_reader() -test_writer() diff --git a/examples/dataflow_sim.py b/examples/dataflow_sim.py deleted file mode 100644 index 98d79652..00000000 --- a/examples/dataflow_sim.py +++ /dev/null @@ -1,31 +0,0 @@ -from migen.fhdl.structure import * -from migen.flow.actor import * -from migen.flow.network import * -from migen.actorlib.sim import * -from migen.sim.generic import Simulator -from migen.sim.icarus import Runner - -def source_gen(): - for i in range(10): - print("Sending: " + str(i)) - yield Token("source", {"value": i}) - -def sink_gen(): - while True: - t = Token("sink") - yield t - print("Received: " + str(t.value["value"])) - -def main(): - source = SimActor(source_gen(), ("source", Source, [("value", BV(32))])) - sink = SimActor(sink_gen(), ("sink", Sink, [("value", BV(32))])) - g = DataFlowGraph() - g.add_connection(source, sink) - comp = CompositeActor(g) - def end_simulation(s): - s.interrupt = source.done - fragment = comp.get_fragment() + Fragment(sim=[end_simulation]) - sim = Simulator(fragment, Runner()) - sim.run() - -main() diff --git a/examples/fir.py b/examples/fir.py deleted file mode 100644 index 3b4b8d8a..00000000 --- a/examples/fir.py +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright (C) 2012 Vermeer Manufacturing Co. -# License: GPLv3 with additional permissions (see README). - -from math import cos, pi -from scipy import signal -import matplotlib.pyplot as plt - -from migen.fhdl.structure import * -from migen.fhdl import verilog -from migen.corelogic.misc import optree -from migen.fhdl import autofragment -from migen.sim.generic import Simulator, PureSimulable -from migen.sim.icarus import Runner - -# A synthesizable FIR filter. -class FIR: - def __init__(self, coef, wsize=16): - self.coef = coef - self.wsize = wsize - self.i = Signal(BV(self.wsize, True)) - self.o = Signal(BV(self.wsize, True)) - - def get_fragment(self): - muls = [] - sync = [] - src = self.i - for c in self.coef: - sreg = Signal(BV(self.wsize, True)) - sync.append(sreg.eq(src)) - src = sreg - c_fp = int(c*2**(self.wsize - 1)) - c_e = Constant(c_fp, BV(bits_for(c_fp), True)) - muls.append(c_e*sreg) - sum_full = Signal(BV(2*self.wsize-1, True)) - sync.append(sum_full.eq(optree("+", muls))) - comb = [self.o.eq(sum_full[self.wsize-1:])] - return Fragment(comb, sync) - -# A test bench for our FIR filter. -# Generates a sine wave at the input and records the output. -class TB(PureSimulable): - def __init__(self, fir, frequency): - self.fir = fir - self.frequency = frequency - self.inputs = [] - self.outputs = [] - - def do_simulation(self, s): - f = 2**(self.fir.wsize - 1) - v = 0.1*cos(2*pi*self.frequency*s.cycle_counter) - s.wr(self.fir.i, int(f*v)) - self.inputs.append(v) - self.outputs.append(s.rd(self.fir.o)/f) - -def main(): - # Compute filter coefficients with SciPy. - coef = signal.remez(80, [0, 0.1, 0.1, 0.5], [1, 0]) - fir = FIR(coef) - - # Simulate for different frequencies and concatenate - # the results. - in_signals = [] - out_signals = [] - for frequency in [0.05, 0.07, 0.1, 0.15, 0.2]: - tb = TB(fir, frequency) - fragment = autofragment.from_local() - sim = Simulator(fragment, Runner()) - sim.run(100) - 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() - - # Print the Verilog source for the filter. - print(verilog.convert(fir.get_fragment(), - ios={fir.i, fir.o})) - -main() diff --git a/examples/fsm.py b/examples/fsm.py deleted file mode 100644 index f1716aea..00000000 --- a/examples/fsm.py +++ /dev/null @@ -1,9 +0,0 @@ -from migen.fhdl.structure import * -from migen.fhdl import verilog -from migen.corelogic.fsm import FSM - -s = Signal() -myfsm = FSM("FOO", "BAR") -myfsm.act(myfsm.FOO, s.eq(1), myfsm.next_state(myfsm.BAR)) -myfsm.act(myfsm.BAR, s.eq(0), myfsm.next_state(myfsm.FOO)) -print(verilog.convert(myfsm.get_fragment(), {s})) diff --git a/examples/lm32_inst.py b/examples/lm32_inst.py deleted file mode 100644 index 678dca55..00000000 --- a/examples/lm32_inst.py +++ /dev/null @@ -1,46 +0,0 @@ -from migen.fhdl.structure import * -from migen.fhdl import verilog - -class LM32: - def __init__(self): - self.inst = Instance("lm32_top", - [("I_ADR_O", BV(32)), - ("I_DAT_O", BV(32)), - ("I_SEL_O", BV(4)), - ("I_CYC_O", BV(1)), - ("I_STB_O", BV(1)), - ("I_WE_O", BV(1)), - ("I_CTI_O", BV(3)), - ("I_LOCK_O", BV(1)), - ("I_BTE_O", BV(1)), - ("D_ADR_O", BV(32)), - ("D_DAT_O", BV(32)), - ("D_SEL_O", BV(4)), - ("D_CYC_O", BV(1)), - ("D_STB_O", BV(1)), - ("D_WE_O", BV(1)), - ("D_CTI_O", BV(3)), - ("D_LOCK_O", BV(1)), - ("D_BTE_O", BV(1))], - [("interrupt", BV(32)), - ("ext_break", BV(1)), - ("I_DAT_I", BV(32)), - ("I_ACK_I", BV(1)), - ("I_ERR_I", BV(1)), - ("I_RTY_I", BV(1)), - ("D_DAT_I", BV(32)), - ("D_ACK_I", BV(1)), - ("D_ERR_I", BV(1)), - ("D_RTY_I", BV(1))], - clkport="clk_i", - rstport="rst_i", - name="lm32") - - def get_fragment(self): - return Fragment(instances=[self.inst]) - -cpus = [LM32() for i in range(4)] -frag = Fragment() -for cpu in cpus: - frag += cpu.get_fragment() -print(verilog.convert(frag, set([cpus[0].inst.ins["interrupt"], cpus[0].inst.outs["I_WE_O"]]))) diff --git a/examples/memory.py b/examples/memory.py deleted file mode 100644 index ec61c83a..00000000 --- a/examples/memory.py +++ /dev/null @@ -1,23 +0,0 @@ -from migen.fhdl.structure import * -from migen.fhdl import verilog - -d = 100 -d_b = bits_for(d-1) -w = 32 - -a1 = Signal(BV(d_b)) -d1 = Signal(BV(w)) -we1 = Signal(BV(4)) -dw1 = Signal(BV(w)) -re = Signal() -p1 = MemoryPort(a1, d1, we1, dw1, we_granularity=8) - -a2 = Signal(BV(d_b)) -d2 = Signal(BV(w)) -re2 = Signal() -p2 = MemoryPort(a2, d2, re=re2) - -mem = Memory(w, d, p1, p2, init=[5, 18, 32]) -f = Fragment(memories=[mem]) -v = verilog.convert(f, ios={a1, d1, we1, dw1, a2, d2, re2}) -print(v) diff --git a/examples/memory_sim.py b/examples/memory_sim.py deleted file mode 100644 index 34ae1126..00000000 --- a/examples/memory_sim.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (C) 2012 Vermeer Manufacturing Co. -# License: GPLv3 with additional permissions (see README). - -from migen.fhdl.structure import * -from migen.sim.generic import Simulator -from migen.sim.icarus import Runner - -class Mem: - def __init__(self): - self.a = Signal(BV(12)) - self.d = Signal(BV(16)) - p = MemoryPort(self.a, self.d) - # Initialize the beginning of the memory with integers - # from 0 to 19. - self.mem = Memory(16, 2**12, p, init=list(range(20))) - - def do_simulation(self, s): - # Read the memory. Use the cycle counter as address. - value = s.rd(self.mem, s.cycle_counter) - # Print the result. Output is: - # 0 - # 1 - # 2 - # ... - print(value) - # Demonstrate how to interrupt the simulator. - if value == 10: - s.interrupt = True - - def get_fragment(self): - return Fragment(memories=[self.mem], sim=[self.do_simulation]) - -def main(): - dut = Mem() - sim = Simulator(dut.get_fragment(), Runner()) - # No need for a cycle limit here, we use sim.interrupt instead. - sim.run() - -main() diff --git a/examples/sim/abstract_transactions.py b/examples/sim/abstract_transactions.py new file mode 100644 index 00000000..09a5dfe7 --- /dev/null +++ b/examples/sim/abstract_transactions.py @@ -0,0 +1,116 @@ +# Copyright (C) 2012 Vermeer Manufacturing Co. +# License: GPLv3 with additional permissions (see README). + +from random import Random + +from migen.fhdl.structure import * +from migen.fhdl import autofragment +from migen.bus.transactions import * +from migen.bus import wishbone, asmibus +from migen.sim.generic import Simulator +from migen.sim.icarus import Runner + +# Our bus master. +# Python generators let us program bus transactions in an elegant sequential style. +def my_generator(): + 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 + + # 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 MyModel: + def read(self, address): + return address + 4 + +class MyModelWB(MyModel, wishbone.TargetModel): + def __init__(self): + self.prng = Random(763627) + + def can_ack(self, bus): + # Simulate variable latency. + return self.prng.randrange(0, 2) + +class MyModelASMI(MyModel, asmibus.TargetModel): + pass + +def test_wishbone(): + print("*** Wishbone test") + + # The "wishbone.Initiator" library component runs our generator + # and manipulates the bus signals accordingly. + master = wishbone.Initiator(my_generator()) + # The "wishbone.Target" library component examines the bus signals + # and calls into our model object. + slave = wishbone.Target(MyModelWB()) + # The "wishbone.Tap" library component examines the bus at the slave port + # and displays the transactions on the console (/). + tap = wishbone.Tap(slave.bus) + # Connect the master to the slave. + intercon = wishbone.InterconnectPointToPoint(master.bus, slave.bus) + # A small extra simulation function to terminate the process when + # the initiator is done (i.e. our generator is exhausted). + def end_simulation(s): + s.interrupt = master.done + fragment = autofragment.from_local() + Fragment(sim=[end_simulation]) + sim = Simulator(fragment, Runner()) + sim.run() + +def test_asmi(): + print("*** ASMI test") + + # Create a hub with one port for our initiator. + hub = asmibus.Hub(32, 32) + port = hub.get_port() + hub.finalize() + # Create the initiator, target and tap (similar to the Wishbone case). + master = asmibus.Initiator(port, my_generator()) + slave = asmibus.Target(hub, MyModelASMI()) + tap = asmibus.Tap(hub) + # Run the simulation (same as the Wishbone case). + def end_simulation(s): + s.interrupt = master.done + fragment = autofragment.from_local() + Fragment(sim=[end_simulation]) + sim = Simulator(fragment, Runner()) + sim.run() + +test_wishbone() +test_asmi() + +# Output: +# +# Wrote in 0 cycle(s) +# +# Wrote in 0 cycle(s) +# +# Wrote in 0 cycle(s) +# +# Wrote in 1 cycle(s) +# +# Wrote in 1 cycle(s) +# +# Wrote in 2 cycle(s) +# ... +# +# Read 4 in 2 cycle(s) +# +# Read 5 in 2 cycle(s) +# +# Read 6 in 1 cycle(s) +# +# Read 7 in 1 cycle(s) +# ... diff --git a/examples/sim/basic1.py b/examples/sim/basic1.py new file mode 100644 index 00000000..af00d0df --- /dev/null +++ b/examples/sim/basic1.py @@ -0,0 +1,41 @@ +# Copyright (C) 2012 Vermeer Manufacturing Co. +# License: GPLv3 with additional permissions (see README). + +from migen.fhdl.structure import * +from migen.sim.generic import Simulator +from migen.sim.icarus import Runner + +# Our simple counter, which increments at every cycle +# and prints its current value in simulation. +class Counter: + def __init__(self): + self.count = Signal(BV(4)) + + # This function will be called at every cycle. + def do_simulation(self, s): + # Simply read the count signal and print it. + # The output is: + # Count: 0 + # Count: 1 + # Count: 2 + # ... + print("Count: " + str(s.rd(self.count))) + + def get_fragment(self): + # At each cycle, increase the value of the count signal. + # We do it with convertible/synthesizable FHDL code. + sync = [self.count.eq(self.count + 1)] + # List our simulation function in the fragment. + sim = [self.do_simulation] + return Fragment(sync=sync, sim=sim) + +def main(): + dut = Counter() + # Use the Icarus Verilog runner. + # We do not specify a top-level object, and use the default. + sim = Simulator(dut.get_fragment(), Runner()) + # Since we do not use sim.interrupt, limit the simulation + # to some number of cycles. + sim.run(20) + +main() diff --git a/examples/sim/basic2.py b/examples/sim/basic2.py new file mode 100644 index 00000000..a4387f76 --- /dev/null +++ b/examples/sim/basic2.py @@ -0,0 +1,52 @@ +# Copyright (C) 2012 Vermeer Manufacturing Co. +# License: GPLv3 with additional permissions (see README). + +from migen.fhdl.structure import * +from migen.sim.generic import Simulator, TopLevel +from migen.sim.icarus import Runner + +# A slightly improved counter. +# Has a clock enable (CE) signal, counts on more bits +# and resets with a negative number. +class Counter: + def __init__(self): + self.ce = Signal() + # Demonstrate negative numbers and signals larger than 32 bits. + self.count = Signal(BV(37, True), reset=-5) + + def do_simulation(self, s): + # Only assert CE every second cycle. + # => each counter value is held for two cycles. + if s.cycle_counter % 2: + s.wr(self.ce, 0) # This is how you write to a signal. + else: + s.wr(self.ce, 1) + print("Cycle: " + str(s.cycle_counter) + " Count: " + \ + str(s.rd(self.count))) + # Set the "initialize" property on our simulation function. + # The simulator will call it during the reset cycle, + # with s.cycle_counter == -1. + do_simulation.initialize = True + + # Output is: + # Cycle: -1 Count: 0 + # Cycle: 0 Count: -5 + # Cycle: 1 Count: -5 + # Cycle: 2 Count: -4 + # Cycle: 3 Count: -4 + # Cycle: 4 Count: -3 + # ... + + def get_fragment(self): + sync = [If(self.ce, self.count.eq(self.count + 1))] + sim = [self.do_simulation] + return Fragment(sync=sync, sim=sim) + +def main(): + dut = Counter() + # Instantiating the generic top-level ourselves lets us + # specify a VCD output file. + sim = Simulator(dut.get_fragment(), Runner(), TopLevel("my.vcd")) + sim.run(20) + +main() diff --git a/examples/sim/dataflow.py b/examples/sim/dataflow.py new file mode 100644 index 00000000..98d79652 --- /dev/null +++ b/examples/sim/dataflow.py @@ -0,0 +1,31 @@ +from migen.fhdl.structure import * +from migen.flow.actor import * +from migen.flow.network import * +from migen.actorlib.sim import * +from migen.sim.generic import Simulator +from migen.sim.icarus import Runner + +def source_gen(): + for i in range(10): + print("Sending: " + str(i)) + yield Token("source", {"value": i}) + +def sink_gen(): + while True: + t = Token("sink") + yield t + print("Received: " + str(t.value["value"])) + +def main(): + source = SimActor(source_gen(), ("source", Source, [("value", BV(32))])) + sink = SimActor(sink_gen(), ("sink", Sink, [("value", BV(32))])) + g = DataFlowGraph() + g.add_connection(source, sink) + comp = CompositeActor(g) + def end_simulation(s): + s.interrupt = source.done + fragment = comp.get_fragment() + Fragment(sim=[end_simulation]) + sim = Simulator(fragment, Runner()) + sim.run() + +main() diff --git a/examples/sim/fir.py b/examples/sim/fir.py new file mode 100644 index 00000000..3b4b8d8a --- /dev/null +++ b/examples/sim/fir.py @@ -0,0 +1,81 @@ +# Copyright (C) 2012 Vermeer Manufacturing Co. +# License: GPLv3 with additional permissions (see README). + +from math import cos, pi +from scipy import signal +import matplotlib.pyplot as plt + +from migen.fhdl.structure import * +from migen.fhdl import verilog +from migen.corelogic.misc import optree +from migen.fhdl import autofragment +from migen.sim.generic import Simulator, PureSimulable +from migen.sim.icarus import Runner + +# A synthesizable FIR filter. +class FIR: + def __init__(self, coef, wsize=16): + self.coef = coef + self.wsize = wsize + self.i = Signal(BV(self.wsize, True)) + self.o = Signal(BV(self.wsize, True)) + + def get_fragment(self): + muls = [] + sync = [] + src = self.i + for c in self.coef: + sreg = Signal(BV(self.wsize, True)) + sync.append(sreg.eq(src)) + src = sreg + c_fp = int(c*2**(self.wsize - 1)) + c_e = Constant(c_fp, BV(bits_for(c_fp), True)) + muls.append(c_e*sreg) + sum_full = Signal(BV(2*self.wsize-1, True)) + sync.append(sum_full.eq(optree("+", muls))) + comb = [self.o.eq(sum_full[self.wsize-1:])] + return Fragment(comb, sync) + +# A test bench for our FIR filter. +# Generates a sine wave at the input and records the output. +class TB(PureSimulable): + def __init__(self, fir, frequency): + self.fir = fir + self.frequency = frequency + self.inputs = [] + self.outputs = [] + + def do_simulation(self, s): + f = 2**(self.fir.wsize - 1) + v = 0.1*cos(2*pi*self.frequency*s.cycle_counter) + s.wr(self.fir.i, int(f*v)) + self.inputs.append(v) + self.outputs.append(s.rd(self.fir.o)/f) + +def main(): + # Compute filter coefficients with SciPy. + coef = signal.remez(80, [0, 0.1, 0.1, 0.5], [1, 0]) + fir = FIR(coef) + + # Simulate for different frequencies and concatenate + # the results. + in_signals = [] + out_signals = [] + for frequency in [0.05, 0.07, 0.1, 0.15, 0.2]: + tb = TB(fir, frequency) + fragment = autofragment.from_local() + sim = Simulator(fragment, Runner()) + sim.run(100) + 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() + + # Print the Verilog source for the filter. + print(verilog.convert(fir.get_fragment(), + ios={fir.i, fir.o})) + +main() diff --git a/examples/sim/memory.py b/examples/sim/memory.py new file mode 100644 index 00000000..34ae1126 --- /dev/null +++ b/examples/sim/memory.py @@ -0,0 +1,39 @@ +# Copyright (C) 2012 Vermeer Manufacturing Co. +# License: GPLv3 with additional permissions (see README). + +from migen.fhdl.structure import * +from migen.sim.generic import Simulator +from migen.sim.icarus import Runner + +class Mem: + def __init__(self): + self.a = Signal(BV(12)) + self.d = Signal(BV(16)) + p = MemoryPort(self.a, self.d) + # Initialize the beginning of the memory with integers + # from 0 to 19. + self.mem = Memory(16, 2**12, p, init=list(range(20))) + + def do_simulation(self, s): + # Read the memory. Use the cycle counter as address. + value = s.rd(self.mem, s.cycle_counter) + # Print the result. Output is: + # 0 + # 1 + # 2 + # ... + print(value) + # Demonstrate how to interrupt the simulator. + if value == 10: + s.interrupt = True + + def get_fragment(self): + return Fragment(memories=[self.mem], sim=[self.do_simulation]) + +def main(): + dut = Mem() + sim = Simulator(dut.get_fragment(), Runner()) + # No need for a cycle limit here, we use sim.interrupt instead. + sim.run() + +main() diff --git a/examples/simple_gpio.py b/examples/simple_gpio.py deleted file mode 100644 index 1a738791..00000000 --- a/examples/simple_gpio.py +++ /dev/null @@ -1,23 +0,0 @@ -from migen.fhdl.structure import * -from migen.fhdl import verilog -from migen.bank import description, csrgen -from migen.bank.description import READ_ONLY, WRITE_ONLY - -ninputs = 32 -noutputs = 32 - -oreg = description.RegisterField("o", noutputs) -ireg = description.RegisterField("i", ninputs, READ_ONLY, WRITE_ONLY) - -# input path -gpio_in = Signal(BV(ninputs)) -gpio_in_s = Signal(BV(ninputs)) # synchronizer -insync = [gpio_in_s.eq(gpio_in), ireg.field.w.eq(gpio_in_s)] -inf = Fragment(sync=insync) - -bank = csrgen.Bank([oreg, ireg]) -f = bank.get_fragment() + inf -oreg.field.r.name_override = "gpio_out" -i = bank.interface -v = verilog.convert(f, {i.dat_r, oreg.field.r, i.adr, i.we, i.dat_w, gpio_in}) -print(v) diff --git a/examples/using_record.py b/examples/using_record.py deleted file mode 100644 index 7c757aa4..00000000 --- a/examples/using_record.py +++ /dev/null @@ -1,20 +0,0 @@ -from migen.fhdl.structure import * -from migen.corelogic.record import * - -L = [ - ("x", BV(10), 8), - ("y", BV(10), 8), - ("level2", [ - ("a", BV(5), 32), - ("b", BV(5), 16) - ]) -] - -myrec = Record(L) -print(myrec.flatten()) -print(myrec.flatten(True)) -s = myrec.subrecord("level2/a", "x") -print(s.flatten()) -print(s.level2.layout()) -myrec2 = myrec.copy() -print(myrec2.flatten())