def crossbar_stress_test(self, dut, ports, n_banks, n_ops, clocks=None): # Runs simulation with multiple masters writing and reading to multiple banks controller = ControllerStub( dut.interface, write_latency=dut.settings.phy.write_latency, read_latency=dut.settings.phy.read_latency) # Store data produced per master produced = defaultdict(list) prng = random.Random(42) def master(dut, driver, num): # Choose operation types based on port mode ops_choice = { "both": ["w", "r"], "write": ["w"], "read": ["r"], }[driver.port.mode] for i in range(n_ops): bank = prng.randrange(n_banks) # We will later distinguish data by its row address row = num col = 0x20 * num + i addr = dut.addr_port(bank=bank, row=row, col=col) addr_iface = dut.addr_iface(row=row, col=col) if prng.choice(ops_choice) == "w": yield from driver.write(addr, data=i) produced[num].append( self.W(bank, addr_iface, data=i, we=0xff)) else: yield from driver.read(addr) produced[num].append(self.R(bank, addr_iface, data=None)) yield from driver.wait_all() generators = defaultdict(list) for i, port in enumerate(ports): driver = NativePortDriver(port) generators[port.clock_domain].append(master(dut, driver, i)) generators[port.clock_domain].extend(driver.generators()) generators["sys"] += controller.generators() generators["sys"].append(timeout_generator(80 * n_ops)) sim_kwargs = {} if clocks is not None: sim_kwargs["clocks"] = clocks run_simulation(dut, generators, **sim_kwargs) # Split controller data by master, as this is what we want to compare consumed = defaultdict(list) for data in controller.data: master = data.addr >> (dut.settings.geom.colbits - dut.address_align) if isinstance(data, self.R): # Master couldn't know the data when it was sending data = data._replace(data=None) consumed[master].append(data) return produced, consumed, controller.data
def test_address_mappings(self): # Verify that address is translated correctly. reads = [] def producer(dut, driver): for t in transfers: addr = dut.addr_port(bank=t["bank"], row=t["row"], col=t["col"]) if t["rw"] == self.W: yield from driver.write(addr, data=t["data"], we=t.get("we", None)) elif t["rw"] == self.R: data = (yield from driver.read(addr)) reads.append(data) else: raise TypeError(t["rw"]) geom_settings = dict(colbits=10, rowbits=13, bankbits=2) dut = CrossbarDUT(geom_settings=geom_settings) port = dut.crossbar.get_port() driver = NativePortDriver(port) transfers = [ dict(rw=self.W, bank=2, row=0x30, col=0x03, data=0x20), dict(rw=self.W, bank=3, row=0x30, col=0x03, data=0x21), dict(rw=self.W, bank=2, row=0xab, col=0x03, data=0x22), dict(rw=self.W, bank=2, row=0x30, col=0x13, data=0x23), dict(rw=self.R, bank=1, row=0x10, col=0x99), dict(rw=self.R, bank=0, row=0x10, col=0x99), dict(rw=self.R, bank=1, row=0xcd, col=0x99), dict(rw=self.R, bank=1, row=0x10, col=0x77), ] expected = [] read_data = ControllerStub.read_data_counter() for i, t in enumerate(transfers): cls = t["rw"] addr = dut.addr_iface(row=t["row"], col=t["col"]) if cls == self.W: kwargs = dict(data=t["data"], we=0xff) elif cls == self.R: kwargs = dict(data=next(read_data)) expected.append(cls(bank=t["bank"], addr=addr, **kwargs)) data = self.crossbar_test(dut, [producer(dut, driver)] + driver.generators()) self.assertEqual(data, expected)