def run_sim(dut, data, n): sim = Simulator(dut, engine=os.getenv('NMIGEN_SIM', 'pysim')) sim.add_clock(10e-9, domain='sync') sim.add_sync_process(dut.input.send_driver(data)) sim.add_sync_process(dut.output.recv_driver(n)) with sim.write_vcd('bla.vcd'): sim.run()
def sim(cls): """A quick simulation of the transparent latch.""" m = Module() m.submodules.latch = latch = TransparentLatch(32) sim = Simulator(m) def process(): yield latch.n_oe.eq(1) yield latch.le.eq(1) yield Delay(1e-6) yield latch.data_in.eq(0xAAAA1111) yield Delay(1e-6) yield latch.data_in.eq(0x1111AAAA) yield Delay(1e-6) yield latch.le.eq(0) yield Delay(1e-6) yield latch.data_in.eq(0xAAAA1111) yield Delay(1e-6) yield latch.le.eq(1) yield Delay(1e-6) sim.add_process(process) with sim.write_vcd("latch.vcd"): sim.run_until(10e-6)
def fxfilter(self, stimulus): """ Calculate the fixpoint filter response in float format for a frame of stimulus data (float). Parameters ---------- stimulus : ndarray of float One frame of stimuli data (float) scaled as WI.WF Returns ------- output : ndarray of float One frame of response data (float) scaled as WI.WF """ def process(): # convert stimulus to int by multiplying with 2 ^ WF input = np.round(stimulus * (1 << self.fx_filt.p['QI']['WF'])).astype(int) self.output = [] for i in input: yield self.fx_filt.i.eq(int(i)) yield Tick() self.output.append((yield self.fx_filt.o)) sim = Simulator(self.fx_filt) sim.add_clock(1 / 48000) sim.add_process(process) sim.run() # convert output to ndarray of float by dividing the integer response by 2 ^ WF return np.array(self.output, dtype='f') / (1 << self.fx_filt.p['QO']['WF'])
def sim(self, dut, testbench=None, traces=(), engine="pysim"): dut = self.prepare(dut) self.fragment = dut simulator = Simulator(dut, engine=engine) for name, (frequency, phase) in self.clocks.items(): simulator.add_clock(1 / frequency, domain=name, phase=phase) if isinstance(testbench, tuple): generator, domain = testbench self.add_process(generator, domain) elif inspect.isgeneratorfunction(testbench): self.add_process(testbench, "sync") elif testbench is None: pass else: raise TypeError("unknown type for testbench") for generator, domain in self.processes: simulator.add_sync_process(generator, domain=domain) print("\nwriting vcd to '{}.vcd'".format(self.output_filename_base)) with simulator.write_vcd("{}.vcd".format(self.output_filename_base), "{}.gtkw".format(self.output_filename_base), traces=traces): simulator.run()
def sim(cls): """A quick simulation of the async memory.""" m = Module() m.submodules.mem = mem = AsyncMemory(width=32, addr_lines=5) sim = Simulator(m) def process(): yield mem.n_oe.eq(0) yield mem.n_wr.eq(1) yield mem.data_in.eq(0xFFFFFFFF) yield Delay(1e-6) yield mem.addr.eq(1) yield mem.n_oe.eq(0) yield Delay(1e-6) yield mem.n_oe.eq(1) yield Delay(1e-6) yield mem.data_in.eq(0xAAAA1111) yield Delay(1e-6) yield mem.n_wr.eq(0) yield Delay(0.2e-6) yield mem.n_wr.eq(1) yield Delay(0.2e-6) yield mem.data_in.eq(0xFFFFFFFF) yield mem.n_oe.eq(0) yield Delay(1e-6) yield mem.addr.eq(0) yield Delay(1e-6) sim.add_process(process) with sim.write_vcd("async_memory.vcd"): sim.run_until(10e-6)
def sim(self, dut, testbench=None, traces=(), filename=None): dut = self.prepare(dut) simulator = Simulator(dut) for name, frequency in self.clocks.items(): simulator.add_clock(1 / frequency, domain=name) if not filename: stack = inspect.stack() filename = stack[1].function assert isinstance(filename, str) if isinstance(testbench, tuple): generator, domain = testbench self.add_process(generator, domain) elif inspect.isgeneratorfunction(testbench): self.add_process(testbench, "sync") elif testbench is None: pass else: raise TypeError("unknown type for testbench") for generator, domain in self.processes: simulator.add_sync_process(generator, domain=domain) Path(".sim_results/").mkdir(exist_ok=True) with simulator.write_vcd(".sim_results/{}.vcd".format(filename), ".sim_results/{}.gtkw".format(filename), traces=traces): simulator.run()
def setUp(self): # Ensure IS_SIM_RUN set global _IS_SIM_RUN _IS_SIM_RUN = True # Create DUT and add to simulator self.m = Module() self.dut = self.create_dut() self.m.submodules['dut'] = self.dut self.m.submodules['dummy'] = _DummySyncModule() self.sim = Simulator(self.m)
def setUp(self): self.dut = self.instantiate_dut() self.sim = Simulator(self.dut) if self.USB_CLOCK_FREQUENCY: self.sim.add_clock(1 / self.USB_CLOCK_FREQUENCY, domain="usb") if self.SYNC_CLOCK_FREQUENCY: self.sim.add_clock(1 / self.SYNC_CLOCK_FREQUENCY, domain="sync") if self.FAST_CLOCK_FREQUENCY: self.sim.add_clock(1 / self.FAST_CLOCK_FREQUENCY, domain="fast") if self.SS_CLOCK_FREQUENCY: self.sim.add_clock(1 / self.SS_CLOCK_FREQUENCY, domain="ss")
def test_h100_sync(): from nmigen.sim import Simulator, Delay bus = HighSpeedTransmitBus() m = Module() m.submodules.sync = sync = H100Sync() m.submodules.dut = dut = HighSpeedTransmit(bus=bus, sync=sync) frame_data_0 = [ord(c) for c in '0_TESTING_T1_DATA_STUFF\xff'] frame_data_1 = [ord(c) for c in '1_TESTING_T1_DATA_STUFF\x00'] frame_data_2 = [ord(c) for c in '2_TESTING_T1_DATA_STUFF\xff'] frame_data_3 = [ord(c) for c in '3_TESTING_T1_DATA_STUFF\x00'] def process_test(): yield Delay(100e-9) yield sync.enable.eq(1) yield dut.enable.eq(1) yield dut.data[0].eq(0xaa) yield dut.data[1].eq(0x55) yield dut.data[2].eq(0xff) yield dut.data[3].eq(0x00) for _ in range(2500): slot_t1 = yield sync.slot_t1 yield yield dut.data[0].eq(frame_data_0[slot_t1]) yield dut.data[1].eq(frame_data_1[slot_t1]) yield dut.data[2].eq(frame_data_2[slot_t1]) yield dut.data[3].eq(frame_data_3[slot_t1]) sim = Simulator(m) sim.add_clock(1.0 / 16.384e6) # sim.add_sync_process(process_inclk) sim.add_sync_process(process_test) traces = [ # sync.inclk, # sync.outclk, dut.enable, bus.ser.o, bus.ser.oe, bus.msync.o, bus.msync.oe, bus.sync.o, bus.sync.oe, ] with sim.write_vcd("test_h100_sync.vcd", "test_h100_sync.gtkw", traces=traces): sim.run()
def resolve(expr): """Resolves a nMigen expression that can be constantly evaluated to an integer""" sim = Simulator(Module()) a = [] def testbench(): a.append((yield expr)) sim.add_process(testbench) sim.run() return a[0]
def test_ram_banks(self): sim = Simulator(self.mbc) def proc(): yield from self.reset() yield from self.write(0x4000, 0x1F) assert (yield self.mbc.ram_bank) == 0xF yield from self.write(0x4000, 0x7A) assert (yield self.mbc.ram_bank) == 0xA sim.add_process(proc) sim.reset() sim.run()
def test_ram_en(self): sim = Simulator(self.mbc) def proc(): yield from self.reset() assert (yield self.mbc.ram_en) == 0 yield from self.write(0x0000, 0x0A) assert (yield self.mbc.ram_en) == 1 yield from self.write(0x0000, 0x1A) assert (yield self.mbc.ram_en) == 0 sim.add_process(proc) sim.reset() sim.run()
def gen(): sim = Simulator(m) has_clock = True try: sim.add_clock(1e-6, domain="sync") except ValueError: has_clock = False next_inputs = [0] * len(inputs) next_outputs = [0] * len(outputs) iteration = [0] def input_receiver(): next_input = yield yield next_input def process(): while True: for i in range(len(inputs)): yield inputs[i].eq(next_inputs[i]) if has_clock: yield Tick() for i in range(len(outputs)): next_outputs[i] = (yield outputs[i]) iteration[0] += 1 yield Settle() sim.add_process(process) last_iter = 0 while True: # Receive the input received = yield for i in range(len(received)): next_inputs[i] = received[i] # Iterate until outputs are updated after a clock cycle while last_iter == iteration[0]: sim.advance() last_iter = iteration[0] if len(next_outputs) == 1: yield next_outputs[0] else: yield next_outputs.copy()
def test_rom_banks(self): sim = Simulator(self.mbc) def proc(): yield from self.reset() yield from self.assert_rom_banks(0x000, 0x001) yield from self.write(0x2000, 0x42) yield from self.assert_rom_banks(0x000, 0x042) yield from self.write(0x3000, 0x01) yield from self.assert_rom_banks(0x000, 0x142) yield from self.write(0x2000, 0x00) yield from self.assert_rom_banks(0x000, 0x100) yield from self.write(0x3000, 0x00) yield from self.assert_rom_banks(0x000, 0x000) sim.add_process(proc) sim.reset() sim.run()
def test_pattern_matching(): m = Matcher(pattern=[0, 1, 1, 0], interval=1) sim = Simulator(m) sim.add_clock(1e-6, domain="sync") haystack = [0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0] def process(): matchcount = 0 for i in range(len(haystack)): yield yield m.input.eq(haystack[i]) matchcount += yield m.match assert (matchcount == 1) sim.add_sync_process(process) with sim.write_vcd("matching.vcd"): sim.run()
def test_crc(): m = GaloisCRC() sim = Simulator(m) sim.add_clock(1e-6, domain="sync") data = [0, 1, 0, 0, 1, 0, 1, 1, 1, 0] def process(): for bit in data: yield m.input.eq(bit) yield m.en.eq(1) yield yield crc = yield m.crc assert (crc == py_crc(np.array(data))) sim.add_sync_process(process) with sim.write_vcd("crc.vcd"): sim.run()
def test_sim_async_fifo(self): m = Module() fifo = m.submodules.fifo = AsyncFIFO(width=32, depth=8, r_domain="sync", w_domain="sync") def testbench(): for i in range(20): yield fifo.w_data.eq(i) yield fifo.w_en.eq(1) yield yield fifo.w_en.eq(0) yield yield yield yield assert (yield fifo.r_level) == 8 simulator = Simulator(m) simulator.add_clock(1 / 100e6, domain="sync") simulator.add_sync_process(testbench, domain="sync") simulator.run()
def test_sim_asnyc_stream_fifo(self): m = Module() input = StreamEndpoint(32, is_sink=False, has_last=False) fifo = m.submodules.fifo = AsyncStreamFifo(input, 1024, r_domain="sync", w_domain="sync", buffered=False) def testbench(): for i in range(10): yield from write_to_stream(input, i) # async fifos need some time yield yield assert (yield fifo.r_level) == 10 for i in range(10): assert (yield from read_from_stream(fifo.output)) == i simulator = Simulator(m) simulator.add_clock(1 / 100e6, domain="sync") simulator.add_sync_process(testbench, domain="sync") simulator.run()
def check(self, instruction: int, expected: Dict[str, int]): decoder = CPUDecoder() sim = Simulator(decoder) def input_process(): yield decoder.instruction_in.eq(instruction) def check_process(): yield Delay(1e-6) for k, expected_value in expected.items(): value = yield getattr(decoder, k) if isinstance(expected_value, enum.Enum): value = expected_value.__class__(value) else: value = hex(value) expected_value = hex(expected_value) with self.subTest(f"decoder.{k}"): self.assertEqual(value, expected_value) with sim.write_vcd(f"test_decode_{hex(instruction)}.vcd"): sim.add_process(input_process) sim.add_process(check_process) sim.run()
def assertStatement(self, stmt, inputs, output, reset=0): inputs = [Value.cast(i) for i in inputs] output = Value.cast(output) isigs = [Signal(i.shape(), name=n) for i, n in zip(inputs, "abcd")] osig = Signal(output.shape(), name="y", reset=reset) stmt = stmt(osig, *isigs) frag = Fragment() frag.add_statements(stmt) for signal in flatten(s._lhs_signals() for s in Statement.cast(stmt)): frag.add_driver(signal) sim = Simulator(frag) def process(): for isig, input in zip(isigs, inputs): yield isig.eq(input) yield Settle() self.assertEqual((yield osig), output.value) sim.add_process(process) with sim.write_vcd("test.vcd", "test.gtkw", traces=[*isigs, osig]): sim.run()
def test_frequency_generation(): """This creates an oscillator with a frequency error that meets a given spec and then verifies that it actually loops through everything. Note that below a certain error level, we start to get assorted floating point differences that mean that this test fails against even the "realized frequency" reference""" freq = 2.4*1e9 sample_rate = 5*1e9 error = 0.0001*1e6 # 50ppm allowable frequency error, not m = OneBitFixedOscillator(sample_rate=sample_rate, frequency=freq, max_error=error, width=20, domain='sync') sim = Simulator(m) sim.add_clock(1e-6, domain="sync") assert np.abs(m.realized_frequency - freq) < error samples = m.pattern_words*10 ref = binarize(make_carrier(sample_rate=sample_rate, freq=m.realized_frequency, samples=samples*20)) ref = pack_mem(ref, 20) output = np.zeros((samples,), dtype=np.uint32) def process(): for i in range(samples): yield result = yield m.output counter = yield m.counter output[i] = result if bin(result) != bin(ref[i]): raise Exception("At {} got {} but expected {}".format(i, bin(result), bin(ref[i]))) print(json.dumps(list(map(int, output)))) sim.add_sync_process(process) with sim.write_vcd("nco.vcd"): sim.run()
def test_serializer(self): clk = 60e6 m = Serializer(w_width=32, r_width=8) sim = Simulator(m) sim.add_clock(1 / clk) def process(): data = 0xDDCCBBAA yield m.w_data.eq(data) yield m.w_en.eq(1) yield m.r_en.eq(1) yield for i in range(10): for j in range(4): yield shift = (j * 8) mask = (0xff << shift) expected_r_data = (data & mask) >> shift self.assertEqual((yield m.r_data), expected_r_data) sim.add_sync_process(process) with sim.write_vcd("serializer.vcd", "serializer.gtkw", traces=[]): sim.run()
def main(): # parser = main_parser() # args = parser.parse_args() m = Module() m.submodules.ft = ft = FT600() m.submodules.wfifo = wfifo = AsyncFIFOBuffered( width=16, depth=1024, r_domain="sync", w_domain="sync") m.submodules.rfifo = rfifo = AsyncFIFOBuffered( width=16, depth=1024, r_domain="sync", w_domain="sync") ft_oe = Signal() ft_be = Signal() ft_txe = Signal() # FT control m.d.comb += ft_oe.eq(ft.ft_oe) m.d.comb += ft_be.eq(ft.ft_be) m.d.comb += ft_txe.eq(ft.ft_txe) # FT to Write FIFO m.d.comb += ft.input_payload.eq(wfifo.r_data) m.d.comb += wfifo.r_en.eq(ft.input_ready) m.d.comb += ft.input_valid.eq(wfifo.r_rdy) # FT to Read FIFO m.d.comb += rfifo.w_data.eq(ft.output_payload) m.d.comb += rfifo.w_en.eq(ft.output_valid) m.d.comb += ft.output_ready.eq(rfifo.w_rdy) sim = Simulator(m) sim.add_clock(1e-7, domain="sync") # 10 MHz FPGA clock def process(): yield wfifo.w_en.eq(1) yield wfifo.w_data.eq(1) yield Tick(domain="sync") yield wfifo.w_data.eq(2) yield Tick(domain="sync") yield wfifo.w_data.eq(3) yield Tick(domain="sync") yield wfifo.w_data.eq(4) yield Tick(domain="sync") yield wfifo.w_data.eq(5) yield Tick(domain="sync") yield wfifo.w_data.eq(6) yield Tick(domain="sync") yield wfifo.w_data.eq(7) yield Tick(domain="sync") yield wfifo.w_en.eq(0) yield Tick(domain="sync") yield Tick(domain="sync") yield ft.ft_txe.eq(1) yield Tick(domain="sync") yield Tick(domain="sync") yield Tick(domain="sync") yield Tick(domain="sync") yield ft.ft_txe.eq(0) yield Tick(domain="sync") yield Tick(domain="sync") yield ft.ft_txe.eq(1) yield Tick(domain="sync") yield Tick(domain="sync") yield Tick(domain="sync") yield Tick(domain="sync") yield Tick(domain="sync") yield Tick(domain="sync") yield Tick(domain="sync") yield ft.ft_rxf.eq(1) yield Tick(domain="sync") yield ft.ft_override.eq(1) yield Tick(domain="sync") yield ft.ft_override.eq(2) yield Tick(domain="sync") yield ft.ft_override.eq(3) yield Tick(domain="sync") yield ft.ft_rxf.eq(0) yield Tick(domain="sync") yield Tick(domain="sync") yield Tick(domain="sync") yield Tick(domain="sync") sim.add_sync_process(process) with sim.write_vcd("test.vcd", "test.gtkw", traces=[]): sim.run()
spimem.sclk.eq(timer[0]), #spimem.copi.eq((timer == 0x30) | (timer == 0x10)), # read address 1 spimem.copi.eq((timer == 0x30) | (timer == 0x40)), # write address 1, dout = 1 spimem.csn.eq(timer == 0), spimem.din.eq(0x55) ] return m if __name__ == "__main__": m = Module() m.submodules.test = test = TestSPI() sim = Simulator(m) sim.add_clock(1e-6) def process(): for i in range(67): yield addr = yield test.spimem.addr print("addr:", addr) dout = yield test.spimem.dout print("dout:", dout) sim.add_sync_process(process) with sim.write_vcd("test.vcd", "test.gtkw"): sim.run()
parser.add_argument("-g", "--generate", action="store_true") args = parser.parse_args() fw = FIRM # use this firmware if args.simulate: spork = build(fw, mem_size=1024) from nmigen.sim import Simulator from sim_data import test_rx, str_data st = "sphinx of black quartz judge my vow" # print(hex(_crc(st.encode("utf-8")))) data = str_data(st) dut = spork.cpu.pc.devices[0]._phy dut.divisor_val = spork.divisor sim = Simulator(spork) sim.add_clock(1e-3) sim.add_sync_process(test_rx(data, dut)) with sim.write_vcd("sim.vcd"): sim.run() if args.list: spork = build(fw, detail=True) if args.program: spork = build(fw, detail=True) spork.platform.build(spork, do_program=True) if args.generate: spork = build(fw, mem_size=1024, sim=True) from nmigen.back import cxxrtl
def test_base_rate_sync(): from nmigen.sim import Simulator, Delay clock_sclk = 1.544e6 clock_sync = 16.384e6 m = Module() m.submodules.dut = dut = BaseRateSync() sclk = Signal() serclk = Signal() ser = Signal() SERCLK_SKEW = 10e-9 SER_SKEW = 10e-9 def process_framer(): frequency = clock_sclk period = 1.0 / frequency data = 'THIS_IS_A_TEST_' * 40 data_bits = ''.join(['{:08b}'.format(ord(v)) for v in data]) for bit in data_bits: yield sclk.eq(1) yield Delay(SERCLK_SKEW) yield serclk.eq(1) yield Delay(SER_SKEW) yield ser.eq(int(bit)) yield Delay(period * 0.5 - SERCLK_SKEW - SER_SKEW) yield sclk.eq(0) yield Delay(SERCLK_SKEW) yield serclk.eq(0) yield Delay(period * 0.5 - SERCLK_SKEW) def process_strobe(): last = 0 for _ in range(int(round(4700 * clock_sync / clock_sclk))): serclk_value = yield serclk if serclk_value == 0 and last == 1: yield dut.strobe_in.eq(1) else: yield dut.strobe_in.eq(0) last = serclk_value yield def process_test(): yield Delay(100e-9) for _ in range(4700): yield sim = Simulator(m) sim.add_clock(1.0 / clock_sync) sim.add_process(process_framer) sim.add_sync_process(process_strobe) sim.add_sync_process(process_test) traces = [ sclk, serclk, ser, ] with sim.write_vcd("test_base_rate_sync.vcd", "test_base_rate_sync.gtkw", traces=traces): sim.run()
m.next = "FETCH" with m.Case(3): with m.If(bus.done): m.d.sync += [ self.pc.eq(self.wx), bus.addr.eq(self.sp), bus.data_in.eq(self.pc[:8]), bus.en.eq(1), cycle.eq(4) ] with m.Case(4): with m.If(bus.done): m.next = "FETCH" with m.Default(): # NOP m.d.comb += op.eq(OpBlock.NOP) m.next = "FETCH" with m.State("HALT"): pass return m if __name__ == "__main__": import sys, os from nmigen.sim import Simulator sys.setrecursionlimit(8192) sim = Simulator(I8080()) sim.add_clock(1e-4) with sim.write_vcd("trace.vcd"): sim.run_until(1, run_passive=True)
uart.tx_data, uart.tx_rdy, uart.tx_ack, uart.rx_data, uart.rx_rdy, uart.rx_err, uart.rx_ovf, uart.rx_ack ] import argparse parser = argparse.ArgumentParser() p_action = parser.add_subparsers(dest="action") p_action.add_parser("simulate") p_action.add_parser("generate") args = parser.parse_args() if args.action == "simulate": from nmigen.sim import Simulator, Passive sim = Simulator(uart) sim.add_clock(1e-6) def loopback_proc(): yield Passive() while True: yield uart.rx_i.eq((yield uart.tx_o)) yield sim.add_sync_process(loopback_proc) def transmit_proc(): assert (yield uart.tx_ack) assert not (yield uart.rx_rdy) yield uart.tx_data.eq(0x5A) yield uart.tx_rdy.eq(1)
def setUp(self): self.m = Module() self.dut = self.create_dut() self.m.submodules['dut'] = self.dut self.m.submodules['dummy'] = _DummySyncModule() self.sim = Simulator(self.m)
# with m.If(self.enable): m.d.sync += phase_acc.eq(phase_acc + self.phase_step) return m @staticmethod def calculate_phase_step(clk_frequency: float, frequency: float): return int(round((2 ** 32) * frequency / clk_frequency)) if __name__ == "__main__": # from nmigen_boards.tinyfpga_bx import TinyFPGABXPlatform # platform = TinyFPGABXPlatform() # products = platform.build(Top(), do_program=True) from nmigen.sim import Simulator, Tick dut = NCO(width=8, samples=1024) sim = Simulator(dut) sim.add_clock(1 / 1e6) def proc(): yield dut.phase_step.eq(NCO.calculate_phase_step(clk_frequency=1e6, frequency=440)) for i in range(3000): yield Tick() sim.add_process(proc) with sim.write_vcd("dds.vcd"): sim.run()