refactor Memory Core simulation into test class
This commit is contained in:
parent
e2d52a6e2d
commit
11022f474d
|
|
@ -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):
|
||||
|
|
|
|||
Loading…
Reference in New Issue