def test_activity(self): m = Module() r = runfiles.Create() m.submodules.cpu = cpu = core.Minerva(with_debug=True) m.submodules.periph = periph = peripheral.Peripherals( r.Rlocation( 'nmigen_nexys/board/nexysa7100t/riscv_demo/deadbeef.bin')) m.d.comb += cpu.ibus.connect(periph.ibus) m.d.comb += cpu.dbus.connect(periph.dbus) # TODO: enable timeout m.submodules.timer = timer = test_util.Timer(self, timeout_s=1e-6) sim = Simulator(m) sim.add_clock(1.0 / util.SIMULATION_CLOCK_FREQUENCY) events = event.EventSeries(timer.cycle_counter) wmon = WishboneMonitor(periph.dbus) wmon.attach(sim, events) test_dir = test_util.BazelTestOutput(self.id()) os.makedirs(test_dir, exist_ok=True) traces = sum([ self._wishbone_traces(periph.ibus), self._wishbone_traces(periph.dbus), ], []) with sim.write_vcd(os.path.join(test_dir, "test.vcd"), os.path.join(test_dir, "test.gtkw"), traces=traces): sim.run_until(1e-6, run_passive=True) events.ShowEvents() events.ValidateConstraints(self, [ Write(adr=0x2000 >> 2, sel=0b1111, dat_w=0xdeadbeef), WriteAck(), ])
def test_multiple(self): """Test the end-to-end conversion pipeline and output a waveform.""" m = Module() m.submodules.conv = conv = manual_brightness.ConversionPipeline( Signal(8), Signal(8)) rdisp_flat = util.Flatten(m, conv.rdisp) ldisp_flat = util.Flatten(m, conv.ldisp) sim = Simulator(m) sim.add_clock(1.0 / util.SIMULATION_CLOCK_FREQUENCY) def convert_one(rval: int, expected_rdisp: List[int], expected_ldisp: List[int]): yield conv.rval.eq(rval) yield conv.lval.eq(2 * rval) yield # Let conv automatically detect the update yield from test_util.WaitSync(conv.done) actual_rdisp = yield from test_util.YieldList(conv.rdisp) actual_ldisp = yield from test_util.YieldList(conv.ldisp) print(f'Input: {rval}') print(f'Expected: {expected_rdisp}, {expected_ldisp}') print(f'Actual: {actual_rdisp}, {actual_ldisp}') self.assertEqual(expected_rdisp, actual_rdisp) self.assertEqual(expected_ldisp, actual_ldisp) def convert(): test_cases = [ [0, [ZERO, BLANK, BLANK, BLANK], [ZERO, BLANK, BLANK, BLANK]], [1, [ONE, BLANK, BLANK, BLANK], [TWO, BLANK, BLANK, BLANK]], [2, [TWO, BLANK, BLANK, BLANK], [FOUR, BLANK, BLANK, BLANK]], [3, [THREE, BLANK, BLANK, BLANK], [SIX, BLANK, BLANK, BLANK]], [10, [ZERO, ONE, BLANK, BLANK], [ZERO, TWO, BLANK, BLANK]], [127, [SEVEN, TWO, ONE, BLANK], [FOUR, FIVE, TWO, BLANK]], ] for rval, rdisp, ldisp in test_cases: yield from convert_one(rval, rdisp, ldisp) def timeout(): yield Passive() yield Delay(10_000e-8) self.fail('Timed out after 10 kcycles') sim.add_process(timeout) sim.add_sync_process(convert) with sim.write_vcd(vcd_file=test_util.BazelTestOutput("test.vcd"), gtkw_file=test_util.BazelTestOutput("test.gtkw"), traces=[conv.rval, rdisp_flat, ldisp_flat]): sim.run()
def test_speed(self): m = Module() bus = spi.Bus(cs_n=Signal(name='cs'), clk=Signal(name='spi_clk'), mosi=Signal(name='mosi'), miso=Signal(name='miso'), freq_Hz=10_000_000) m.submodules.clk_eng = clk_eng = spi.ClockEngine( bus, polarity=Signal(reset=0)) m.submodules.clk_edge = clk_edge = edge.Detector(bus.clk) timestamp = Signal(range(100), reset=0) m.d.sync += timestamp.eq(timestamp + 1) sim = Simulator(m) sim.add_clock(1.0 / util.SIMULATION_CLOCK_FREQUENCY) def clock_driver(): yield clk_eng.enable.eq(1) yield Delay(1e-6) def clock_monitor(): yield Passive() last_edge = None while True: yield from test_util.WaitSync(clk_edge.rose) now = yield timestamp if last_edge is not None: self.assertEqual(now - last_edge, 10) last_edge = now yield def timeout(): yield Passive() while True: now = yield timestamp if now == util.ShapeMax(timestamp): self.fail(f'Timed out after {now} cycles') yield sim.add_sync_process(clock_driver) sim.add_sync_process(clock_monitor) sim.add_sync_process(timeout) test_dir = test_util.BazelTestOutput(self.id()) os.makedirs(test_dir, exist_ok=True) with sim.write_vcd(os.path.join(test_dir, "test.vcd"), os.path.join(test_dir, "test.gtkw"), traces=list(bus.fields.values())): sim.run()
"""Simulation waveform generator for nmigen_nexys.display.seven_segment.""" from nmigen import * from nmigen.sim import * from nmigen_nexys.core import util from nmigen_nexys.display import seven_segment from nmigen_nexys.test import test_util if __name__ == "__main__": m = Module() segments = Signal(8) anodes = Signal(8) m.submodules.demo = seven_segment.DisplayMultiplexerDemo(segments, anodes) sim = Simulator(m) sim.add_clock(1.0 / util.SIMULATION_CLOCK_FREQUENCY) with sim.write_vcd(test_util.BazelTestOutput("test.vcd"), test_util.BazelTestOutput("test.gtkw"), traces=[segments, anodes]): sim.run_until(100e-6, run_passive=True)
def test_sim(self): test = rf"""self._run_test('a', b"'a' = 0x61\r\n", runs={FLAGS.runs})""" test_dir = test_util.BazelTestOutput(self.id()) perf_file = os.path.join(test_dir, 'test.perf') cProfile.runctx(test, globals(), locals(), perf_file)
def _run_test(self, c: str, expected: bytes, runs: int = 1): m = Module() pins = Record( Layout([ ('rx', 1, Direction.FANIN), ('tx', 1, Direction.FANOUT), ('rts', 1, Direction.FANOUT), ('cts', 1, Direction.FANIN), ])) m.submodules.tx = tx = uart.Transmit(12_000_000) m.submodules.rx = rx = uart.Receive(12_000_000) m.submodules.demo = uart_demo.UARTDemo(pins) m.d.comb += pins.rx.eq(tx.output) m.d.comb += rx.input.eq(pins.tx) tx_done = Signal(range(runs + 1)) rx_done = Signal(range(runs + 1)) sim = Simulator(m) sim.add_clock(1.0 / util.SIMULATION_CLOCK_FREQUENCY) def transmit(): yield Passive() for i in range(runs): yield from test_util.WaitSync(rx_done >= i) yield tx.data.eq(ord(c)) yield tx.start.eq(1) yield yield tx.start.eq(0) yield from test_util.WaitSync(tx.done) yield tx_done.eq(tx_done + 1) def receive(): yield Passive() for _ in range(runs): data = bytearray() for _ in range(len(expected)): yield from test_util.WaitSync(rx.start) yield from test_util.WaitSync(rx.done) data.append((yield rx.data)) self.assertEqual(data, expected) yield rx_done.eq(rx_done + 1) def wait_done(): yield from test_util.WaitSync((tx_done == runs) & (rx_done == runs)) def timeout(): yield Passive() us = 12 * runs yield Delay(us * 1e-6) self.fail(f'Timed out after {us} us') sim.add_sync_process(transmit) sim.add_sync_process(receive) sim.add_sync_process(wait_done) sim.add_process(timeout) test_dir = test_util.BazelTestOutput(self.id()) os.makedirs(test_dir, exist_ok=True) with contextlib.ExitStack() as stack: if FLAGS.vcd: stack.enter_context( sim.write_vcd(os.path.join(test_dir, "test.vcd"), os.path.join(test_dir, "test.gtkw"), traces=[tx.output, rx.input])) sim.run()
def test_multiplexer(self): m = Module() bus = spi.Bus(cs_n=Signal(name='cs'), clk=Signal(name='spi_clk'), mosi=Signal(name='mosi'), miso=Signal(name='miso'), freq_Hz=10_000_000) m.submodules.master = master = spi.ShiftMaster(bus, shift_register.Up(16)) m.submodules.slave = slave = spi.ShiftSlave(bus, shift_register.Up(16)) m.submodules.mux = mux = master.Multiplexer(len(EXAMPLES), master.interface) master_finish = [Signal(reset=0) for _ in range(mux.n)] slave_finish = Signal(reset=0) finish = Signal() m.d.comb += finish.eq(Cat(*master_finish, slave_finish).all()) sim = Simulator(m) sim.add_clock(1.0 / util.SIMULATION_CLOCK_FREQUENCY) def master_proc(n: int): def process(): yield Passive() example = EXAMPLES[n] yield from test_util.WaitSync(mux.select == n) actual = yield from MasterDoOne(mux.interfaces[n], example.mosi_data, example.size) self.assertEqual(actual, example.miso_data) yield master_finish[n].eq(1) yield mux.select.eq(mux.select + 1) return process def slave_proc(): yield Passive() for example in EXAMPLES: yield from SlaveDoOne(slave, example.miso_data, example.size) overrun = yield slave.overrun actual_size = yield slave.transfer_size actual = yield slave.register.word_out[:example.size] self.assertFalse(overrun) self.assertEqual(actual_size, example.size) self.assertEqual(actual, example.mosi_data) yield slave_finish.eq(1) def wait_finish(): yield from test_util.WaitSync(finish) def timeout(): yield Passive() yield Delay(100e-6) self.fail('Timed out after 100 us') sim.add_process(timeout) for n in range(mux.n): sim.add_sync_process(master_proc(n)) sim.add_sync_process(slave_proc) sim.add_sync_process(wait_finish) test_dir = test_util.BazelTestOutput(self.id()) os.makedirs(test_dir, exist_ok=True) with sim.write_vcd(os.path.join(test_dir, "test.vcd"), os.path.join(test_dir, "test.gtkw"), traces=list(bus.fields.values())): sim.run()
def test_no_slave_activity(self): m = Module() master_bus = spi.Bus(cs_n=Signal(name='master_cs'), clk=Signal(name='spi_clk'), mosi=Signal(name='mosi'), miso=Signal(name='miso'), freq_Hz=10_000_000) slave_bus = spi.Bus(cs_n=Signal(name='slave_cs', reset=1), clk=master_bus.clk, mosi=master_bus.mosi, miso=master_bus.miso, freq_Hz=10_000_000) m.submodules.master = master = spi.ShiftMaster(master_bus, shift_register.Up(16)) m.submodules.slave = slave = spi.ShiftSlave(slave_bus, shift_register.Up(16)) sim = Simulator(m) sim.add_clock(1.0 / util.SIMULATION_CLOCK_FREQUENCY) def master_proc(): for example in EXAMPLES: self.assertNotEqual(example.miso_data, 0) actual = yield from MasterDoOne(master.interface, example.mosi_data, example.size) self.assertEqual(actual, 0) def slave_proc(): yield Passive() for example in EXAMPLES: yield from SlaveDoOne(slave, example.miso_data, example.size) self.fail('Slave transfer should not have completed!') def always_monitor(signal: Signal, expected: int): def monitor(): yield Passive() while True: actual = yield signal if actual != expected: self.fail( f'Signal {signal.name}: {actual} != {expected}') yield return monitor def timeout(): yield Passive() yield Delay(100e-6) self.fail('Timed out after 100 us') sim.add_process(timeout) sim.add_sync_process(master_proc) sim.add_sync_process(slave_proc) sim.add_sync_process(always_monitor(slave.start, 0)) sim.add_sync_process(always_monitor(slave.done, 0)) sim.add_sync_process(always_monitor(slave.register.shift, 0)) sim.add_sync_process(always_monitor(master_bus.miso, 0)) test_dir = test_util.BazelTestOutput(self.id()) os.makedirs(test_dir, exist_ok=True) traces = [ master_bus.cs_n, slave_bus.cs_n, master_bus.clk, master_bus.mosi, master_bus.miso, ] with sim.write_vcd(os.path.join(test_dir, "test.vcd"), os.path.join(test_dir, "test.gtkw"), traces=traces): sim.run()
def _run_test(self, examples: [Example], polarity: int = 0, phase: int = 0): m = Module() bus = spi.Bus(cs_n=Signal(name='cs'), clk=Signal(name='spi_clk'), mosi=Signal(name='mosi'), miso=Signal(name='miso'), freq_Hz=10_000_000) m.submodules.master = master = spi.ShiftMaster(bus, shift_register.Up(16)) m.submodules.slave = slave = spi.ShiftSlave(bus, shift_register.Up(16)) m.d.comb += master.polarity.eq(polarity) m.d.comb += master.phase.eq(phase) m.d.comb += slave.polarity.eq(polarity) m.d.comb += slave.phase.eq(phase) master_finish = Signal(reset=0) slave_finish = Signal(reset=0) finish = Signal() m.d.comb += finish.eq(master_finish & slave_finish) sim = Simulator(m) sim.add_clock(1.0 / util.SIMULATION_CLOCK_FREQUENCY) def master_proc(): yield Passive() for example in examples: actual = yield from MasterDoOne(master.interface, example.mosi_data, example.size) self.assertEqual(actual, example.miso_data) yield master_finish.eq(1) def slave_proc(): yield Passive() for example in examples: yield from SlaveDoOne(slave, example.miso_data, example.size) overrun = yield slave.overrun actual_size = yield slave.transfer_size actual = yield slave.register.word_out[:example.size] self.assertFalse(overrun) self.assertEqual(actual_size, example.size) self.assertEqual(actual, example.mosi_data) yield slave_finish.eq(1) def wait_finish(): yield from test_util.WaitSync(finish) def timeout(): yield Passive() yield Delay(100e-6) self.fail('Timed out after 100 us') sim.add_process(timeout) sim.add_sync_process(master_proc) sim.add_sync_process(slave_proc) sim.add_sync_process(wait_finish) test_dir = test_util.BazelTestOutput(self.id()) os.makedirs(test_dir, exist_ok=True) with sim.write_vcd(os.path.join(test_dir, "test.vcd"), os.path.join(test_dir, "test.gtkw"), traces=list(bus.fields.values())): sim.run()
def test_up_down(self): m = Module() pins = pmod_oled.PmodPins() m.submodules.controller = controller = ssd1306.Controller( pins.ControllerBus(), max_data_bytes=0) m.submodules.sequencer = sequencer = pmod_oled.PowerSequencer( pins, controller.interface, sim_logic_wait_us=0.1, sim_vcc_wait_us=20) m.submodules.decoder = decoder = spi.BusDecoder( controller.bus.SPIBus(), polarity=C(0, 1), phase=C(0, 1)) m.submodules.reset_edge = reset_edge = edge.Detector(pins.reset) m.submodules.vbatc_edge = vbatc_edge = edge.Detector(pins.vbatc) m.submodules.vddc_edge = vddc_edge = edge.Detector(pins.vddc) m.submodules.timer = timer = test_util.Timer(self, self.TIMEOUT_S) sim = Simulator(m) sim.add_clock(1.0 / util.SIMULATION_CLOCK_FREQUENCY) events = event.EventSeries(timer.cycle_counter) edge_monitor = event.EdgeMonitor([reset_edge, vbatc_edge, vddc_edge]) spi_monitor = SPIMonitor(self, pins, decoder) def sequencer_process(): yield sequencer.enable.eq(1) yield yield from test_util.WaitSync( sequencer.status == pmod_oled.PowerStatus.READY) yield sequencer.enable.eq(0) yield yield from test_util.WaitSync( sequencer.status == pmod_oled.PowerStatus.OFF) sim.add_sync_process(sequencer_process) spi_monitor.attach(sim, events) edge_monitor.attach(sim, events) sim.add_sync_process(timer.timeout_process) test_dir = test_util.BazelTestOutput(self.id()) os.makedirs(test_dir, exist_ok=True) with sim.write_vcd(os.path.join(test_dir, "test.vcd"), os.path.join(test_dir, "test.gtkw"), traces=list(pins.fields.values())): sim.run() events.ShowEvents() expected: event.EventConstraints = [ # Power on event.EdgeEvent(pins.vddc, 'fell'), event.MinDelay(seconds=0.1e-6), CommandEvent(0xAE), event.MinDelay(seconds=0.1e-6), event.EdgeEvent(pins.reset, 'rose'), CommandEvent(0x8D), CommandEvent(0x14), CommandEvent(0xD9), CommandEvent(0xF1), event.EdgeEvent(pins.vbatc, 'fell'), event.MinDelay(seconds=20.0e-6), CommandEvent(0xAF), # Power off CommandEvent(0xAE), event.EdgeEvent(pins.vbatc, 'rose'), event.MinDelay(seconds=20.0e-6), event.EdgeEvent(pins.vddc, 'rose'), ] events.ValidateConstraints(self, expected)