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 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_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_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 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()
def simulate(self, m): adder = self dump_inputs(adder, m) sim = Simulator(m) def timings(): yield adder.x.eq(0x1) yield adder.y.eq(0x2) yield Delay(1 * muS) sim.add_process(timings) os.chdir("waves") with sim.write_vcd("test.vcd", "test.gtkw", traces = adder.ports()): sim.run() fix_gtkw_win("test.gtkw")
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()
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 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()
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 simulate(): from nmigen.back.pysim import Simulator, Delay, Settle uart_baud = 9600 sim_clock_freq = uart_baud * 32 m = Module() uart_tx = Signal() uart_rx = Signal() m.submodules.uart_high_speed = uart_high_speed = LowHighSpeedLoopback( divisor=int(sim_clock_freq / uart_baud)) m.d.comb += uart_tx.eq(uart_high_speed.uart_tx) m.d.comb += uart_high_speed.uart_rx.eq(uart_rx) sim = Simulator(m) sim.add_clock(1 / sim_clock_freq, domain="sync") uart_tick = Delay(1 / uart_baud) def process(): rx = uart_rx yield rx.eq(1) yield uart_tick for i in range(4): # start bit yield rx.eq(0) yield uart_tick # 8 data bits for i in range(1, 9): yield rx.eq(i % 2 == 1) yield uart_tick # one stop bit yield rx.eq(1) yield uart_tick # pause for i in range(30): yield uart_tick sim.add_process(process) # or sim.add_sync_process(process), see below # with sim.write_vcd("test.vcd", "test.gtkw", traces=[uart_tx, uart_rx]): with sim.write_vcd("test.vcd", "test.gtkw", traces=uart_high_speed.ports()): sim.run()
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 simulate(self, m: Module): uut = self dump_inputs(uut, m) sim = Simulator(m) def timings(): yield uut.a.eq(0x3) yield Delay(1 * muS) yield uut.a.eq(0x4) yield Delay(1 * muS) yield uut.a.eq(0x5) yield Delay(1 * muS) yield uut.a.eq(0x7) yield Delay(1 * muS) sim.add_process(timings) os.chdir("waves") with sim.write_vcd("test.vcd", "test.gtkw", traces=uut.ports()): sim.run() fix_gtkw_win("test.gtkw")
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_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()
m.d.comb += adder.x.eq(x) m.d.comb += adder.y.eq(y) sim = Simulator(m) def timings(): yield adder.x.eq(0x00) yield adder.y.eq(0x00) yield Delay(muS) yield adder.x.eq(0xFF) yield adder.y.eq(0xFF) yield Delay(muS) yield adder.x.eq(0x00) yield Delay(muS) sim.add_process(timings) with sim.write_vcd("test.vcd", "test.gtkw", traces=[x, y] + adder.ports()): sim.run() fix_gtkw_win("test.gtkw") #main_runner(parser, args, m, ports=[]+adder.ports()) #if __name__ == "__main__": # parser = main_parser() # args = parser.parse_args() # m = Module() # m.submodules.adder = adder = Adder() # # main_runner(parser, args, m, ports=[]+adder.ports())
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()
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) assert (yield uart.rx_rdy) assert not (yield uart.rx_err) assert (yield uart.rx_data) == 0x5A yield uart.rx_ack.eq(1) yield sim.add_sync_process(transmit_proc) with sim.write_vcd("uart.vcd", "uart.gtkw"): sim.run() if args.action == "generate": from nmigen.back import verilog print(verilog.convert(uart, ports=ports))
def print_leds(leds): line_top = [" ", " _ "] line_mid = [" ", " │", " _ ", " _│", "│ ", "│ │", "│_ ", "│_│"] line_bot = line_mid a = leds & 1 fgb = ((leds >> 1) & 1) | ((leds >> 5) & 2) | ((leds >> 3) & 4) edc = ((leds >> 2) & 1) | ((leds >> 2) & 2) | ((leds >> 2) & 4) print(line_top[a]) print(line_mid[fgb]) print(line_bot[edc]) if __name__ == '__main__': # seg = SevenSegment() seg = SevenSegController() sim = Simulator(seg) def process(): for i in range(16): yield seg.val.eq(i) yield Delay() result = yield seg.leds print_leds(result) sim.add_process(process) with sim.write_vcd('output.vcd'): sim.run()
#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()
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)