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(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()
class TestBase(unittest.TestCase): """Base class for testing an nMigen module. The module can use sync, comb or both. """ 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) def create_dut(self): """Returns an instance of the device under test""" raise NotImplementedError def add_process(self, process): """Add main test process to the simulator""" self.sim.add_sync_process(process) def add_sim_clocks(self): """Add clocks as required by sim. """ self.sim.add_clock(1, domain='sync') def run_sim(self, process, write_trace=False): self.add_process(process) self.add_sim_clocks() if write_trace: with self.sim.write_vcd("zz.vcd", "zz.gtkw"): self.sim.run() else: self.sim.run()
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 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 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 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()
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 from nmigen.hdl import ir
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()
from axi_stream_top import AxiStreamTop dut = AxiStreamTop() def bench(): tvalid_last = 0 tvalid_can_fall = 0 for i in range(2000): yield # Check that TVALID never goes low until the transmission completes. tvalid = (yield dut.tx.m_axis.tvalid) tx_done = (yield dut.tx.m_axis.tx_done()) # Don't care about no change in tvalid. # Don't care if tvalid is high. # Only allow tvalid to fall the cycle after a tx_done. assert ((tvalid == tvalid_last) or (tvalid) or (tvalid_can_fall)) tvalid_can_fall = tx_done tvalid_last = tvalid sim = Simulator(dut) sim.add_clock(1e-6) sim.add_sync_process(bench) with sim.write_vcd("axi_stream_top.vcd"): sim.run() with open("axi_stream_top.v", "w") as f: f.write(verilog.convert(dut))
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) yield yield uart.tx_rdy.eq(0) yield assert not (yield uart.tx_ack) for _ in range(uart.divisor * 12): yield assert (yield uart.tx_ack)
#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()
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()
yield from jtagPDI((0x4C, 1), (0xEB, 1)) yield yield from jtagPDI((0xCA, 0), (0xEB, 1)) yield yield from jtagPDI((0x01, 1), (0xEB, 1)) yield yield from jtagPDI((0x00, 0), (0xEB, 1)) yield yield from jtagPDI((0x01, 1), (0xEB, 1)) yield yield from jtagPDI((0x00, 0), (0xEB, 1)) yield yield yield yield sim = Simulator(subtarget) # Define the JTAG clock to have a period of 1/4MHz #sim.add_clock(250e-9, domain = 'jtag') sim.add_clock(2e-6, domain='jtag') # Define the system clock to have a period of 1/48MHz sim.add_clock(20.8e-9) sim.add_sync_process(benchSync, domain='sync') sim.add_sync_process(benchJTAG, domain='jtag') with sim.write_vcd('jtag_pdi-sniffer.vcd'): sim.reset() sim.run()
for addr, data in mem.items(): with m.Case(addr): m.d.comb += core.dout.eq(data) with m.Default(): m.d.comb += core.dout.eq(0xFF) sim = Simulator(m) sim.add_clock(1e-6, domain="sync") def process(): yield yield yield yield yield yield yield yield yield yield yield yield yield yield yield yield sim.add_sync_process(process, domain="sync") with sim.write_vcd("test.vcd", "test.gtkw", traces=core.ports()): sim.run()
def generic_chacha20(self, implementation): print("") # Encrypt a test message with a known good implementation import json from base64 import b64encode from Crypto.Cipher import ChaCha20 from Crypto.Random import get_random_bytes from struct import pack, unpack from binascii import hexlify def byte_xor(ba1, ba2): """ XOR two byte strings """ return bytes([_a ^ _b for _a, _b in zip(ba1, ba2)]) plaintext = b'A' * 64 # key = get_random_bytes(32) key = bytes([i for i in range(32)]) # nonce = get_random_bytes(12) nonce = bytes([(i * 16 + i) for i in range(12)]) cipher = ChaCha20.new(key=key, nonce=nonce) ciphertext = cipher.encrypt(plaintext) nonceb64 = b64encode(cipher.nonce).decode('utf-8') ciphertextb64 = b64encode(ciphertext).decode('utf-8') keystream = byte_xor(plaintext, ciphertext) keystream_hex = hexlify(keystream).decode('utf8') result = json.dumps({ 'nonce': nonceb64, 'ciphertext': ciphertextb64, 'keystream': keystream_hex }) # print(result) # cipher = ChaCha20.new(key=key, nonce=nonce) # cipher.seek(0) # print(cipher.decrypt(ciphertext)) m = Module() m.submodules.chacha20 = chacha20 = ChaCha20Cipher(implementation) key_words = unpack("<8I", key) m.d.comb += [ chacha20.i_key[i].eq(key_words[i]) for i in range(len(key_words)) ] nonce_words = unpack("<3I", nonce) m.d.comb += [ chacha20.i_nonce[i].eq(nonce_words[i]) for i in range(len(nonce_words)) ] sim = Simulator(m) sim.add_clock(1e-6, domain="sync") def process(): ks = [] iterations = 0 yield chacha20.i_en.eq(1) yield for i in range(30 * 4): # Simulate until it'd finished iterations += 1 if (yield chacha20.o_ready) != 0: yield yield yield break yield for i in range(16): ks.append((yield chacha20.o_stream[i])) keystream_hdl = pack("<16I", *ks) print(f"Took {iterations} iterations") print("Keystream generated by simulation: ", hexlify(keystream_hdl)) print("Decryption using simulation: ", byte_xor(keystream_hdl, ciphertext)) self.assertEqual(keystream_hdl, keystream) self.assertEqual(plaintext, byte_xor(keystream_hdl, ciphertext)) sim.add_sync_process(process) with sim.write_vcd("test.vcd", "test.gtkw"): sim.run()