diff --git a/test/test_mem_core_sim.py b/test/test_mem_core_sim.py index dd8d430..9618687 100644 --- a/test/test_mem_core_sim.py +++ b/test/test_mem_core_sim.py @@ -2,148 +2,109 @@ from manta.memory_core import MemoryCore from manta.utils import * from random import randint, sample, choice -width = 18 -depth = 512 -base_addr = 0 +class MemoryCoreTests(): + def __init__(self, mem_core): + self.mem_core = mem_core + self.base_addr = mem_core._base_addr + self.max_addr = mem_core.get_max_addr() + self.width = self.mem_core._width + self.depth = self.mem_core._depth + + self.bus_addrs = list(range(self.base_addr, self.max_addr)) # include the endpoint! + self.user_addrs = list(range(self.mem_core._depth)) + self.model = {} + + def check_each_address_on_bus_side_contains_zero(self): + for addr in self.bus_addrs: + yield from self.verify_bus_side(addr, 0) + + def check_each_address_on_user_side_contains_zero(self): + for addr in self.user_addrs: + yield from self.verify_user_side(addr, 0) + + def check_write_then_immediately_read_bus_side(self): + for addr in self.bus_addrs: + # this part is a little hard to check since we might have a + # memory at the end of the address space that's less than + # 16-bits wide. so we'll have to calculate how wide our + # memory is + + data_width = self.get_data_width(addr) + data = randint(0, (2**data_width) - 1) + + yield from self.write_bus_side(addr, data) + yield from self.verify_bus_side(addr, data) + + def check_multiple_writes_then_multiple_reads(self): + # write-write-write then read-read-read + for addr in sample(self.bus_addrs, len(self.bus_addrs)): + data_width = self.get_data_width(addr) + data = randint(0, (2**data_width) - 1) + + self.model[addr] = data + yield from self.write_bus_side(addr, data) + + for addr in sample(self.bus_addrs, len(self.bus_addrs)): + yield from self.verify_bus_side(addr, self.model[addr]) + + def check_random_reads_random_writes_random_orders(self): + # random reads and writes in random orders + for _ in range(5): + for addr in sample(self.bus_addrs, len(self.bus_addrs)): + + operation = choice(["read", "write"]) + if operation == "read": + yield from self.verify_bus_side(addr, self.model[addr]) + + elif operation == "write": + data_width = self.get_data_width(addr) + data = randint(0, (2**data_width) - 1) + self.model[addr] = data + yield from self.write_bus_side(addr, data) + + def get_data_width(self, addr): + n_full = self.width // 16 + if addr < self.base_addr + (n_full * self.depth): + return 16 + else: + return self.width % 16 + + def verify_bus_side(self, addr, expected_data): + yield from verify_register(self.mem_core, addr, expected_data) + for _ in range(4): + yield + + def write_bus_side(self, addr, data): + yield from write_register(self.mem_core, addr, data) + for _ in range(4): + yield + + def verify_user_side(self, addr, expected_data): + yield self.mem_core.user_addr.eq(addr) + yield self.mem_core.user_write_enable.eq(0) + yield + + data = yield (self.mem_core.user_data_out) + if data != expected_data: + raise ValueError(f"Read from {addr} yielded {data} instead of {expected_data}") + mem_core = MemoryCore( - mode="bidirectional", width=width, depth=depth, base_addr=base_addr, interface=None + mode="bidirectional", + width=23, + depth=512, + base_addr=0, + interface=None, ) -max_addr = mem_core.get_max_addr() -bus_addrs = list(range(base_addr, max_addr)) # include the endpoint! -user_addrs = list(range(depth)) - +tests = MemoryCoreTests(mem_core) @simulate(mem_core) -def test_bidirectional(): - # make sure each address on the bus side contains zero - for addr in bus_addrs: - yield from verify_register(mem_core, addr, 0) - - # make sure each address on the user side contains zero - for addr in user_addrs: - yield from verify_user_side(mem_core, addr, 0) - - # write then immediately read - for addr in bus_addrs: - # this part is a little hard to check since we might have a - # memory at the end of the address space that's less than - # 16-bits wide. so we'll have to calculate how wide our - # memory is - - n_full = width // 16 - if addr < base_addr + (n_full * depth): - data_width = 16 - else: - data_width = width % 16 - - data = randint(0, (2**data_width) - 1) - yield from write_register(mem_core, addr, data) - yield - yield - yield - yield - yield from verify_register(mem_core, addr, data) - yield - yield - yield - yield - yield - - # write-write-write then read-read-read - model = {} - for addr in sample(bus_addrs, len(bus_addrs)): - n_full = width // 16 - if addr < base_addr + (n_full * depth): - data_width = 16 - else: - data_width = width % 16 - - data = randint(0, (2**data_width) - 1) - model[addr] = data - yield from write_register(mem_core, addr, data) - yield - yield - yield - yield - - for addr in sample(bus_addrs, len(bus_addrs)): - yield from verify_register(mem_core, addr, model[addr]) - yield - yield - yield - yield - - # random reads and writes in random orders - for _ in range(5): - for addr in sample(bus_addrs, len(bus_addrs)): - - operation = choice(["read", "write"]) - if operation == "read": - yield from verify_register(mem_core, addr, model[addr]) - yield - yield - yield - yield - yield - yield - - elif operation == "write": - n_full = width // 16 - - if addr < base_addr + (n_full * depth): - data_width = 16 - else: - data_width = width % 16 - - data = randint(0, (2**data_width) - 1) - model[addr] = data - - yield from write_register(mem_core, addr, data) - yield - yield - yield - yield - yield - yield - - -def verify_user_side(mem_core, addr, expected_data): - yield mem_core.user_addr.eq(addr) - yield mem_core.user_write_enable.eq(0) - yield - - data = yield (mem_core.user_data_out) - if data != expected_data: - raise ValueError(f"Read from {addr} yielded {data} instead of {expected_data}") - - -# def fill_mem_from_user_port(mem_core, depth): -# for i in range(depth): -# yield mem_core.user_addr.eq(i) -# yield mem_core.user_data_in.eq(i) -# yield mem_core.user_write_enable.eq(1) -# yield - -# yield mem_core.user_write_enable.eq(0) -# yield - - -# def verify_mem_core(width, depth, base_addr): -# mem_core = MemoryCore("bidirectional", width, depth, base_addr, interface=None) - -# def testbench(): -# yield from fill_mem_from_user_port(mem_core, depth) - -# # Read from address sequentially -# for i in range(depth): -# yield from verify_register(mem_core, i + base_addr, i % (2**width)) - -# # Read from addresses randomly -# for i in sample(range(depth), k=depth): -# yield from verify_register(mem_core, i + base_addr, i % (2**width)) - -# simulate(mem_core, testbench) +def test_bidirectional_testbench(): + yield from tests.check_each_address_on_bus_side_contains_zero() + yield from tests.check_each_address_on_user_side_contains_zero() + yield from tests.check_write_then_immediately_read_bus_side() + yield from tests.check_multiple_writes_then_multiple_reads() + yield from tests.check_random_reads_random_writes_random_orders() # def test_sweep_core_widths(): # for i in range(1, 64):