class LineShifterTest(unittest.TestCase): def setUp(self): self.num_words = 10 self.num_rounds = 5 self.shifter = LineShifter() # Make a list of random numbers. self.data = [ random.randrange(65536) for _ in range(self.num_words * self.num_rounds + 5) ] self.sim = Simulator(self.shifter) self.sim.add_clock(1) # 1Hz for simplicity of counting def double_buffer(self): yield Passive() d = self.data[:] while True: yield self.shifter.r_last.eq(0) for _ in range(self.num_words): while not (yield self.shifter.r_next): yield yield # One extra cycle wait while LFSR updates and memory read occurs yield self.shifter.r_data.eq(d.pop(0)) yield while not (yield self.shifter.r_next): yield yield self.shifter.r_data.eq(0) yield self.shifter.r_last.eq(1) yield def toggle(self, sig): yield sig.eq(1) yield yield sig.eq(0) yield def shift_line(self, n): # Start takes a bit to get going - two syncs yield from self.toggle(self.shifter.start) for i in range(self.num_words): expected_bits = to_bit_list(self.data[n * self.num_words + i]) for j, eb in enumerate(expected_bits): self.assertEqual((yield self.shifter.output), eb) self.assertFalse((yield self.shifter.done)) yield self.assertTrue((yield self.shifter.done)) yield def test_shifter(self): def process(): yield from self.toggle(self.shifter.r_next) for n in range(self.num_rounds): yield from self.shift_line(n) yield from self.toggle( self.shifter.r_next) # Throw away one word yield Delay(100) self.sim.add_sync_process(self.double_buffer) self.sim.add_sync_process(process) self.sim.run()
def test_tmds_simulation(self): m = Module() data = Signal(8, reset=0x3) c = Signal(2) blank = Signal() encoded = Signal(10) m.submodules.tmds_encoder = TMDSEncoder(data, c, blank, encoded) data_out = Signal(8) c_out = Signal(2) active_out = Signal() m.submodules.tmds_decoder = TMDSDecoder(encoded, data_out, c_out, active_out) sim = Simulator(m) sim.add_clock(1 / 25e6, domain="sync") def process(): for i in range(0x20 * 256): yield data.eq(i // 10) yield sim.add_sync_process(process) with sim.write_vcd("tmds.vcd"): sim.run()
def test_framer_sim(): from nmigen.back.pysim import Simulator, Passive input = i = StreamSource(Layout([("data", 8, DIR_FANOUT)]), name="input") framer = f = SLIPFramer(input) sim = Simulator(framer) sim.add_clock(1e-6) def transmit_proc(): yield g = 0 d = "hello world\xdb" m = len(d) while g < m: c = d[g] yield i.data.eq(ord(c)) yield i.sop.eq(0) yield i.eop.eq(0) if c == 'h': yield i.sop.eq(1) elif c == ' ': yield i.eop.eq(1) elif c == 'w': yield i.sop.eq(1) elif c == '\xdb': yield i.eop.eq(1) yield i.valid.eq(1) yield if (yield f.sink.ready) == 1: g += 1 for g in range(0, 16): yield i.valid.eq(0) yield def receive_proc(): for g in range(0, 16): yield data = [] yield f.source.ready.eq(1) yield #for g in range(0, 128): #while not (yield f.source.valid) == 0: counter = 0 while counter < 3: if (yield f.source.valid) == 1: data.append((yield f.source.data)) if (yield f.source.data) == 0xC0: counter += 1 yield assert list(map(hex, data)) == list(map(hex, b"hello \xc0world\xdb\xdd\xc0")) sim.add_sync_process(transmit_proc) sim.add_sync_process(receive_proc) with sim.write_vcd("slip.vcd", "slip.gtkw"): sim.run()
def test_gearbox(self): m = Module() m.submodules.gearbox = gearbox = Gearbox( width_in=3, width_out=2, domain_in="slow", domain_out="fast", depth=3, ) m.d.comb += gearbox.data_in.eq(0b101) sim = Simulator(m) sim.add_clock(1/2e6, domain="slow") sim.add_clock(1/3e6, domain="fast") def process_slow(): yield Active() for i in range(100): # yield gearbox.data_in.eq(i) yield # sim.add_sync_process(process, domain="fast") sim.add_sync_process(process_slow, domain="slow") with sim.write_vcd("gearbox.vcd"): sim.run()
def test_depacketizer_sim(): from nmigen.back.pysim import Simulator, Passive from udptherbone.slip import SLIPUnframer, SLIPFramer, slip_encode, slip_decode input = i = StreamSource(Layout([("data", 8, DIR_FANOUT)])) depacketizer = d = UDPDepacketizer(input, ipaddress.IPv4Address("127.0.0.2"), port = 2574) sim = Simulator(depacketizer) sim.add_clock(1e-6) input_pkt = IP(src='127.0.0.1', dst='127.0.0.2', flags='DF')/UDP(dport=2574, sport=7777)/"hello world" input_data = raw(input_pkt) input_pkt = IP(input_data) input_encoded = slip_encode(input_data) def de_input_proc(): yield g = 0 while g < len(input_encoded): b = input_encoded[g] if b == 'E': yield i.sop.eq(1) elif b == 'd': yield i.eop.eq(1) else: yield i.sop.eq(1) yield i.eop.eq(1) yield i.data.eq(b) yield i.valid.eq(1) yield if (yield i.ready) == 1: g += 1 for g in range(0, 16): yield i.sop.eq(0) yield i.eop.eq(0) yield i.valid.eq(0) yield def de_output_proc(): data = [] yield yield d.source.ready.eq(1) yield #for g in range(0, 512): # yield while True: if (yield d.source.valid) == 1: data.append((yield d.source.data)) if (yield d.source.eop) == 1: break yield assert "".join(list(map(chr, data))) == "hello world" sim.add_sync_process(de_input_proc) sim.add_sync_process(de_output_proc) with sim.write_vcd("udp_de.vcd", "udp_de.gtkw"): sim.run()
class SimulationTestCase(unittest.TestCase): def __init__(self, *args): super().__init__(*args) self.m = Module() self.extra_processes = [] def toggle(self, signal): """Set signal high, then low""" yield signal.eq(1) yield yield signal.eq(0) yield def add(self, submodule, name=None): if name: self.m.submodules[name] = submodule else: self.m.submodules += submodule def run_sim(self, *processes, write_trace=False): self.sim = Simulator(self.m) for p in processes: self.sim.add_sync_process(p) for p in self.extra_processes: self.sim.add_sync_process(p) self.sim.add_clock(1) # 1Hz for simplicity of counting if write_trace: with self.sim.write_vcd("zz.vcd", "zz.gtkw"): self.sim.run() else: self.sim.run()
def run_sim(self, process, record=False): sim = Simulator(self.m) sim.add_clock(1) # 1Hz for simplicity of counting sim.add_sync_process(process) if record: with sim.write_vcd("zz.vcd", "zz.gtkw"): sim.run() else: sim.run()
def test_packetizer_sim(): from nmigen.back.pysim import Simulator, Passive input = i = StreamSource(Layout([("data", 8, DIR_FANOUT)])) packetizer = p = UDPPacketizer(input, ipaddress.IPv4Address("127.0.0.1"), ipaddress.IPv4Address("127.0.0.2"), source_port = 2574, dest_port = 7777) sim = Simulator(packetizer) sim.add_clock(1e-6) def transmit_proc(): yield for c in "hello world": if c == "h": yield i.sop.eq(1) elif c == "d": yield i.eop.eq(1) else: yield i.sop.eq(0) yield i.eop.eq(0) yield i.data.eq(ord(c)) yield i.valid.eq(1) yield for g in range(0, 16): yield i.eop.eq(0) yield i.valid.eq(0) yield def receive_proc(): for g in range(0, 16): yield data = [] #for g in range(0, 128): yield p.source.ready.eq(1) yield while not (yield p.source.valid) == 0: if (yield p.source.valid) == 1: data.append((yield p.source.data)) yield r = IP(data) assert r.load == b"hello world" i = IP(data) del i.chksum i = IP(raw(i)) assert r.chksum == i.chksum sim.add_sync_process(transmit_proc) sim.add_sync_process(receive_proc) with sim.write_vcd("udp_pa.vcd", "udp_pa.gtkw"): sim.run()
def test_dvid(self): sync = ClockDomain() pixel = ClockDomain() m = Module() m.domains += sync, pixel dvid_config = dvid_configs["640x480p60"] dvid_out = Signal(3) dvid_out_clk = Signal(1) pdm_out = Signal(1) m.submodules.gfxdemo = gfxdemo = GFXDemo( dvid_out=dvid_out, dvid_out_clk=dvid_out_clk, pdm_out=pdm_out, vga_parameters=dvid_config.vga_parameters, xdr=2, emulate_ddr=True) m.submodules.buscontroller = buscontroller = BusController( bus=gfxdemo.wb, irq=gfxdemo.irq, program=[ # Draw stuff in the first 32 bits Asm.MOV_R0(0x3000_0100), Asm.WRITE_IMM(0b01010101_01010101_01010101_01010101), # Reset VGA Asm.MOV_R0(0x3000_0004), Asm.WRITE_IMM(0x1), Asm.NOP(), Asm.NOP(), Asm.NOP(), Asm.WRITE_IMM(0x0), # Wait for vsync Asm.WFI(0b10), ] ) sim = Simulator(m) sim.add_clock(period=1/25e6, domain="sync") sim.add_clock(period=1/250e6, phase=0, domain="pixel") def process(): for _ in range(640 * 480 * 4): yield sim.add_sync_process(process) with sim.write_vcd("dvid.vcd"): sim.run()
def test_unframer_sim(): from nmigen.back.pysim import Simulator, Passive input = i = StreamSource(Layout([("data", 8, DIR_FANOUT)]), name="input", sop=False, eop=False) framer = f = SLIPUnframer(input) sim = Simulator(framer) sim.add_clock(1e-6) def transmit_proc(): yield g = 0 d = "hello, \xdb\xdc world\xc0" m = len(d) while g < m: c = d[g] yield i.data.eq(ord(c)) yield i.valid.eq(1) yield if (yield f.sink.ready) == 1: g += 1 for g in range(0, 16): yield i.valid.eq(0) yield def receive_proc(): yield f.source.ready.eq(0) for g in range(0, 16): yield data = [] yield f.source.ready.eq(1) yield packets = 0 while packets < 1: #for g in range(512): if (yield f.source.valid) == 1: data.append((yield f.source.data)) if ((yield f.source.eop) == 1) and ((yield f.source.valid == 1)): packets += 1 yield assert list(map(hex, data)) == list(map(hex, b"hello, \xc0 world")) sim.add_sync_process(transmit_proc) sim.add_sync_process(receive_proc) with sim.write_vcd("slip_unframe.vcd", "slip_unframe.gtkw"): sim.run()
class WordShifterTest(unittest.TestCase): def setUp(self): self.shifter = WordShifter() # Make a list of random numbers. Turn that into a list of bits self.test_words = [0xffff, 0xaaaa ] + [random.randrange(65536) for _ in range(500)] self.test_bits = all_bits_list(self.test_words) self.bit_counter = 0 self.sim = Simulator(self.shifter) self.sim.add_clock(1) # 1Hz for simplicity of counting def load_next_word(self): yield self.shifter.input.eq(self.test_words[0]) self.test_words = self.test_words[1:] def assert_next_bit(self): out = yield self.shifter.output self.assertEqual(self.test_bits[self.bit_counter], out, f"testing bit: {self.bit_counter}") self.bit_counter += 1 def assert_next_word(self): """Tests word is shifted out over 16 cycles""" for i in range(16): yield from self.assert_next_bit() self.assertEqual(i == 14, (yield self.shifter.nearly_done)) self.assertEqual(i == 15, (yield self.shifter.done)) yield def test_shifter(self): def process(): yield from self.load_next_word() yield self.shifter.start.eq(1) yield # Output 3 words for i in range(3): yield from self.load_next_word() yield from self.assert_next_word() # Turn off start, do not load next word yield self.shifter.start.eq(0) # Pump out fourth word yield from self.assert_next_word() # Done and output should remain low for i in range(100): self.assertEqual(0, (yield self.shifter.output)) self.assertEqual(0, (yield self.shifter.nearly_done)) self.assertEqual(0, (yield self.shifter.done)) yield self.sim.add_sync_process(process) self.sim.run()
def test_blinky(self): btn = Signal() led = Record([('a', 7), ('c', 3)]) #m = Module() m = blinky = Blinky(led, btn) sim = Simulator(m) sim.add_clock(1e-6) def process(): yield Active() for _ in range(32): yield sim.add_sync_process(process) with sim.write_vcd("blinky.vcd"): sim.run()
def test_vga2dvid(self): sync = ClockDomain() pixel = ClockDomain() m = Module() m.domains += sync, pixel r = Signal(8) g = Signal(8) b = Signal(8) blank = Signal() hs = Signal() vs = Signal() pixel_r = Signal() pixel_g = Signal() pixel_b = Signal() pixel_clk = Signal() m.submodules.vga2dvid = VGA2DVID( in_r = r, in_g = g, in_b = b, in_blank = blank, in_hsync = hs, in_vsync = vs, out_r = pixel_r, out_g = pixel_g, out_b = pixel_b, out_clock = pixel_clk, ) sim = Simulator(m) sim.add_clock(1/25e6, domain="sync") sim.add_clock(1/250e6, domain="shift", phase=0) def process(): for _ in range(1000): yield sim.add_sync_process(process) with sim.write_vcd("dvid_vga2dvid.vcd"): sim.run()
class SquareWriterTest(unittest.TestCase): def setUp(self): self.res = RESOLUTIONS['TESTBIG'] self.fixture = SquareIntegrationFixture(self.res) self.sim = Simulator(self.fixture) self.sim.add_clock(1, domain='sync') self.sim.add_clock(2.54, domain='app') def frame_bits(self): # returns the bits for a TESTBIG resolution frame where # the SquareWriter has size=0 result = [] for row in range(44): pat0 = [0x0000, 0xffff, 0x0000, 0xffff] pat1 = [0xffff, 0x0000, 0xffff, 0x0000] pat = pat1 if (row & 0x10) else pat0 result += all_bits_list(pat) return result def test_reader(self): def process(): # Skip to after first vertical sync while not (yield self.fixture.vertical_sync): yield while (yield self.fixture.vertical_sync): yield pix = 0 bits = self.frame_bits() # Look for active pixels before next vertical sync while not (yield self.fixture.vertical_sync): if (yield self.fixture.active): out = yield self.fixture.out if out != bits[pix]: breakpoint() self.assertEqual(bits[pix], out) pix += 1 yield self.assertEqual( pix, self.res.horizontal.active * self.res.vertical.active) self.sim.add_sync_process(process, domain='sync') with self.sim.write_vcd("zz.vcd", "zz.gtkw"): self.sim.run()
def wrapper(self): if hasattr(self, "configure"): self.configure(self.tb, **kwargs) def setup_wrapper(): if hasattr(self, "simulationSetUp"): yield from self.simulationSetUp(self.tb) yield from case(self, self.tb) if isinstance(self.tb, CompatModule): compat_run_simulation(self.tb, setup_wrapper(), vcd_name="test.vcd") if isinstance(self.tb, Elaboratable): sim = Simulator(self.tb) with sim.write_vcd(vcd_file=open("test.vcd", "w")): sim.add_clock(1e-8) sim.add_sync_process(setup_wrapper) sim.run()
class FakeRamBankTest(unittest.TestCase): def setUp(self): m = Module() m.submodules.ram = self.ram = RamBank(True) self.sim = Simulator(m) self.sim.add_clock(1) # 1Hz for simplicity of counting def run_sim(self, p): self.sim.add_sync_process(p) #self.sim.run() with self.sim.write_vcd("zz.vcd", "zz.gtkw"): self.sim.run() def test(self): r = self.ram def read(addr): yield r.addr.eq(addr) yield r.wren.eq(0) yield yield def write(addr, val): yield r.addr.eq(addr) yield r.data_in.eq(val) yield r.wren.eq(1) yield yield def process(): yield from write(0x0010, 0x1111) yield from read(0x0010) self.assertEqual(0x1111, (yield r.data_out)) yield from write(0x4010, 0x2222) yield from read(0x4010) self.assertEqual(0x2222, (yield r.data_out)) yield from write(0xc010, 0xffff) yield from read(0xc010) self.assertEqual(0xffff, (yield r.data_out)) yield from read(0x0010) self.assertEqual(0x1111, (yield r.data_out)) self.run_sim(process)
def test_mem_port_unit(): # m = MtkCpu(reg_init=reg_init) arbiter = MemoryArbiter() port0 = arbiter.port(priority=0) port1 = arbiter.port(priority=1) sim = Simulator(arbiter) sim.add_clock(1e-6) def MAIN(): yield port0.cyc.eq(1) for _ in range(10): ack = yield port0.ack print(ack) yield sim.add_sync_process(MAIN) with sim.write_vcd("cpu.vcd"): sim.run()
def test_clock_divider_external_clock(): two_div = ClockDivider(divisor=2, use_external_clock=True) sim = Simulator(two_div) sim.add_clock(1e-6) def process(): # confirm the right initial state for our clocks assert (yield two_div.in_clock) == 0 assert (yield two_div.out_clock) == 0 assert (yield two_div.prev_clock_state) == 0 # now let's cycle the in clock. yield two_div.in_clock.eq(1); yield # after the first tick the prev clock state hasn't updated to the new value yet assert (yield two_div.prev_clock_state) == 0 # then after that we're good though yield assert (yield two_div.prev_clock_state) == 1 yield two_div.in_clock.eq(0); yield; yield; assert (yield two_div.prev_clock_state) == 0 # at this point we should have gotten the out clock to 1 assert (yield two_div.in_clock) == 0 assert (yield two_div.out_clock) == 1 # now let's yield twice without touching the two_div clock yield; yield; yield; yield; # still, out clock didn't move (because in_clock hasn't) assert (yield two_div.in_clock) == 0 assert (yield two_div.out_clock) == 1 # trigger in clock once... yield two_div.in_clock.eq(1); yield; yield; # still, nothing assert (yield two_div.in_clock) == 1 assert (yield two_div.out_clock) == 1 # but one more trigger gets us there yield two_div.in_clock.eq(0); yield; yield; assert (yield two_div.in_clock) == 0 assert (yield two_div.out_clock) == 0 sim.add_sync_process(process) sim.run()
def test_one_rule(self): n_bits = 4 rwg = RandomWordGenerator(n_bits) expected = 2000 def process(): counter = Counter() trials = (2**n_bits) * expected for _ in range(trials): counter.update([(yield rwg.output)]) yield # Test counts counts = [x[1] / expected for x in counter.most_common()] self.assertTrue(counts[0] < 1.1) self.assertTrue(counts[-1] > 0.9) self.assertTrue(pstdev(counts) < 0.06) sim = Simulator(rwg) sim.add_clock(1) # 1Hz for simplicity of counting sim.add_sync_process(process) sim.run()
def test_radiospi(self): clk = 60e6 m = RadioSPI(clk_freq=clk) sim = Simulator(m) sim.add_clock(1/clk) def process(): yield m.address.eq(0x3EAB) yield m.write.eq(1) yield m.write_value.eq(0x3) yield m.start.eq(1) while (not (yield m.busy)): yield yield m.start.eq(0) while (yield m.busy): yield sim.add_sync_process(process) with sim.write_vcd("radiospi.vcd", "radiospi.gtkw", traces=[]): sim.run()
def test_overlay_simulation(self): m = Module() data = Signal(8, reset=0x3) c = Signal(2) blank = Signal() encoded = Signal(10) m.submodules.tmds_encoder = TMDSEncoder(data, c, blank, encoded) encoded_shift = Signal(10) re_encoded = Signal(3) re_encoded_clk = Signal() ctr = Signal(16, reset=9) with m.If(ctr == 0): m.d.shift += encoded_shift.eq(encoded) m.d.shift += ctr.eq(9) with m.Else(): m.d.shift += ctr.eq(ctr - 1) m.d.shift += encoded_shift.eq(Cat(encoded_shift[1:], 0)) m.submodules.overlay = DVIDOverlay(Cat(encoded_shift[0], 0, 0), re_encoded, re_encoded_clk) sim = Simulator(m) sim.add_clock(1 / 25e6, domain="sync") sim.add_clock(1 / 250e6, domain="shift") def process(): for i in range(0x20 * 10): yield data.eq(i // 10) yield c.eq(11) yield blank.eq((i // 10) % 5 == 0) yield sim.add_sync_process(process) with sim.write_vcd("dvid-overlay.vcd"): sim.run()
def test_blinky(self): btn = Signal() led = Signal() m = Module() blinky = m.submodules.blinky = Blinky(led, btn) sim = Simulator(m) sim.add_clock(1e-6) def process(): yield Active() assert (yield blinky.timer) == 0 yield assert (yield blinky.timer) == 1 yield assert (yield blinky.timer) == 2 yield assert (yield blinky.timer) == 3 yield sim.add_sync_process(process) with sim.write_vcd("blinky.vcd"): sim.run()
def test_clock_divider(divisor): four_div = ClockDivider(divisor=divisor, use_external_clock=False) sim = Simulator(four_div) sim.add_clock(1e-6) def process(): # go through 4 cycles checking the results cycle_count = divisor * 6 trace = [] for i in range(cycle_count): # store trace trace.append((yield four_div.out_clock)) yield # move forward one frame # check that the trace would be right expected_trace = [ 0 if (i // divisor) % 2 == 0 else 1 for i in range(cycle_count) ] assert expected_trace == trace sim.add_sync_process(process) 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 = 0xAABBCCDD 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 = 24 - (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 simulate(self, top: Module, clk: ClockInfo, mem: Dict[int, int], n=30, filename_prefix="waves/test"): rst = clk.rst self.make_fakemem(top, mem) dump_inputs(self, top) def timings(): yield rst.eq(1) yield yield rst.eq(0) for _ in range(n): yield sim = Simulator(top) sim.add_clock(muS, domain="i") sim.add_sync_process(timings, domain="i") with sim.write_vcd(f"{filename_prefix}.vcd", f"{filename_prefix}.gtkw", traces=self.ports()): sim.run()
for addr, data in mem.items(): with m.Case(addr): m.d.comb += core.Din.eq(data) with m.Default(): m.d.comb += core.Din.eq(0xFF) sim = Simulator(m) sim.add_clock(1e-6, domain="ph1") def process(): yield yield yield yield yield yield yield yield yield yield yield yield yield yield yield yield sim.add_sync_process(process, domain="ph1") with sim.write_vcd("test.vcd", "test.gtkw", traces=core.ports()): sim.run()
yield sram.bus.stb.eq(1) yield # see sync_behaviors.py # for why we need Settle() yield Settle() yield from print_sig(sram.bus.adr) yield from print_sig(sram.bus.dat_r, "h") # set necessary signal to read bus # at address 4 yield sram.bus.we.eq(0) yield sram.bus.adr.eq(0x4) yield sram.bus.cyc.eq(1) yield sram.bus.stb.eq(1) yield yield Settle() yield from print_sig(sram.bus.adr) yield from print_sig(sram.bus.dat_r, "h") # disable signals yield sram.bus.cyc.eq(0) yield sram.bus.stb.eq(0) yield sim_writer = sim.write_vcd(f"{__file__[:-3]}.vcd") with sim_writer: sim.add_sync_process(process) sim.run()
p_action.add_parser("generate") args = parser.parse_args() if args.action == "simulate": from nmigen.back.pysim 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
def reg_test(name, timeout_cycles, reg_num, expected_val, expected_mem, reg_init, mem_dict, verbose=False): from nmigen.back.pysim import Simulator, Active, Passive, Tick, Settle LOG = lambda x: print(x) if verbose else True cpu = MtkCpu(reg_init=reg_init) sim = Simulator(cpu) sim.add_clock(1e-6) assert ((reg_num is None and expected_val is None) or (reg_num is not None and expected_val is not None)) check_reg = reg_num is not None check_mem = expected_mem is not None def TEST_MEM(): yield Passive() # yield Tick() # yield Settle() p = .4 # .5 # probability of mem access in current cycle from enum import Enum class MemState(Enum): FREE = 0 BUSY_READ = 1 BUSY_WRITE = 2 # TODO legacy - not used for now. # cursed - if we use state == MemState.FREE instead of list, 'timeout_range' generator wouldn't work. # param need to be passed by reference not by value, for actual binding to be visible in each loop iter. state = [MemState.FREE] arbiter = cpu.arbiter while (True): # that's ok, I'm passive. import numpy.random as random rdy = random.choice((0, 1), p=[1 - p, p]) ctr = yield cpu.DEBUG_CTR if state[0] == MemState.FREE: ack = yield arbiter.bus.ack if ack: yield arbiter.bus.ack.eq(0) # print(f"DEBUG_CTR: {ctr}, state: {state[0]}") yield continue cyc = yield arbiter.bus.cyc we = yield arbiter.bus.we write = cyc and we read = cyc and not we mem_addr = yield arbiter.bus.adr if read and write: raise ValueError( "ERROR (TODO handle): simultaneous 'read' and 'write' detected." ) if read: state[0] = MemState.BUSY_READ elif write: state[0] = MemState.BUSY_WRITE data = yield arbiter.bus.dat_w else: if rdy: # random indicated transaction done in current cycle yield arbiter.bus.ack.eq(1) sel = yield arbiter.bus.sel sel = format(sel, '04b') # '1111' string for full mask f = lambda x: 0xFF if int(x) == 1 else 0x00 g = lambda val, el: (val << 8) + el from functools import reduce mask = reduce(g, map(f, sel)) read_val = 0x0 if mem_addr not in mem_dict else mem_dict[ mem_addr] if state[0] == MemState.BUSY_WRITE: mem_dict[mem_addr] = (read_val & ~mask) | (data & mask) elif state[0] == MemState.BUSY_READ: read_val &= mask yield arbiter.bus.dat_r.eq(read_val) # print(f"cyc {ctr}: fetched {read_val} (from {mem_dict})...") state[0] = MemState.FREE yield def TEST_REG(timeout=25 + timeout_cycles): yield Active() yield Tick() yield Settle() for _ in range(timeout): en = yield cpu.reg_write_port.en if en == 1: addr = yield cpu.reg_write_port.addr if addr == reg_num: val = yield cpu.reg_write_port.data if check_reg and (val != expected_val): # TODO that mechanism for now allows for only one write to reg, extend it if neccessary. print( f"== ERROR: Expected data write to reg x{addr} of value {expected_val}," f" got value {val}.. \n== fail test: {name}\n") print( f"{format(expected_val, '32b')} vs {format(val, '32b')}" ) exit(1) return yield Tick() if check_reg: print( f"== ERROR: Test timeouted! No register write observed. Test: {name}\n" ) exit(1) sim.add_sync_process(TEST_MEM) sim.add_sync_process(TEST_REG) with sim.write_vcd("cpu.vcd"): sim.run() if check_mem: print(">>> MEM CHECKING: exp. vs val:", expected_mem, mem_dict) for k, v in expected_mem.items(): if not k in mem_dict: print( f"Error! Wrong memory state. Expected {v} value in {k} addr, got nothing here!" ) exit(1) if mem_dict[k] != v: print( f"Error! Wrong memory state. Expected {v} value in {k} addr, got {mem_dict[k]}" ) exit(1)
#Instantiate the LDPC_Decoder Module with the generator matrix, input codeword size and output data size as parameters m.submodules.LDPC_Decoder = LDPC_Decoder = LDPC_Decoder( parityCheckMatrix, 9, 4) #Simulation #[SIGNAL] - data_input - A top level signal which connects the 'data_input' signal on the LDPC Decoder data_input = Signal(9) #[SIGNAL] - start - A top level signal which connects the 'start' signal on the LDPC Decoder start = Signal(1) #Link the local data_input and start signals to the LDPC Input Ports m.d.comb += LDPC_Decoder.data_input.eq(data_input) m.d.comb += LDPC_Decoder.start.eq(start) #Create a simulator instance with the local nMigen module which contains the LDPC Decoder sim = Simulator(m) #Add a synchronous testbench process to the simulator sim.add_sync_process(testbench_process) #Add a clock to the simulator sim.add_clock(1e-6) #Run the simulation with all input and output ports from the LDPC_Decoder and write out the results with sim.write_vcd("test_9_4.vcd", "test_9_4.gtkw", traces=[data_input, start] + LDPC_Decoder.ports()): sim.run()