Skip to content

Commit

Permalink
Dewishbonized tests (#770)
Browse files Browse the repository at this point in the history
  • Loading branch information
tilk authored Dec 17, 2024
1 parent 08e43d9 commit b4a84bd
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 84 deletions.
43 changes: 17 additions & 26 deletions test/cache/test_icache.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,14 @@
from coreblocks.cache.icache import ICache, ICacheBypass, CacheRefillerInterface
from coreblocks.params import GenParams
from coreblocks.interface.layouts import ICacheLayouts
from coreblocks.peripherals.wishbone import WishboneMaster, WishboneParameters
from coreblocks.peripherals.bus_adapter import WishboneMasterAdapter
from coreblocks.params.configurations import test_core_config
from coreblocks.cache.refiller import SimpleCommonBusCacheRefiller

from transactron.testing import TestCaseWithSimulator, TestbenchIO, def_method_mock, TestbenchContext
from transactron.testing.functions import MethodData
from transactron.testing.method_mock import MethodMock
from transactron.testing.testbenchio import CallTrigger
from ..peripherals.test_wishbone import WishboneInterfaceWrapper
from ..peripherals.bus_mock import BusMockParameters, MockMasterAdapter


class SimpleCommonBusCacheRefillerTestCircuit(Elaboratable):
Expand All @@ -29,12 +27,11 @@ def __init__(self, gen_params: GenParams):
def elaborate(self, platform):
m = Module()

wb_params = WishboneParameters(
bus_mock_params = BusMockParameters(
data_width=self.gen_params.isa.xlen,
addr_width=self.gen_params.isa.xlen,
)
self.wb_master = WishboneMaster(wb_params)
self.bus_master_adapter = WishboneMasterAdapter(self.wb_master)
self.bus_master_adapter = MockMasterAdapter(bus_mock_params)

self.refiller = SimpleCommonBusCacheRefiller(
self.gen_params.get(ICacheLayouts), self.cp, self.bus_master_adapter
Expand All @@ -43,14 +40,11 @@ def elaborate(self, platform):
self.start_refill = TestbenchIO(AdapterTrans(self.refiller.start_refill))
self.accept_refill = TestbenchIO(AdapterTrans(self.refiller.accept_refill))

m.submodules.wb_master = self.wb_master
m.submodules.bus_master_adapter = self.bus_master_adapter
m.submodules.refiller = self.refiller
m.submodules.start_refill = self.start_refill
m.submodules.accept_refill = self.accept_refill

self.wb_ctrl = WishboneInterfaceWrapper(self.wb_master.wb_master)

return m


Expand Down Expand Up @@ -100,12 +94,12 @@ def setup_method(self) -> None:
self.bad_addresses.add(bad_addr)
self.bad_fetch_blocks.add(bad_addr & ~(self.cp.fetch_block_bytes - 1))

async def wishbone_slave(self, sim: TestbenchContext):
async def bus_mock(self, sim: TestbenchContext):
while True:
adr, *_ = await self.test_module.wb_ctrl.slave_wait(sim)
req = await self.test_module.bus_master_adapter.request_read_mock.call(sim)

# Wishbone is addressing words, so we need to shift it a bit to get the real address.
addr = adr << exact_log2(self.cp.word_width_bytes)
# Bus model is addressing words, so we need to shift it a bit to get the real address.
addr = req.addr << exact_log2(self.cp.word_width_bytes)

await self.random_wait_geom(sim, 0.5)

Expand All @@ -114,7 +108,7 @@ async def wishbone_slave(self, sim: TestbenchContext):
data = random.randrange(2**self.gen_params.isa.xlen)
self.mem[addr] = data

await self.test_module.wb_ctrl.slave_respond(sim, data, err=err)
await self.test_module.bus_master_adapter.get_read_response_mock.call(sim, data=data, err=err)

async def refiller_process(self, sim: TestbenchContext):
while self.requests:
Expand Down Expand Up @@ -145,7 +139,7 @@ async def refiller_process(self, sim: TestbenchContext):

def test(self):
with self.run_simulation(self.test_module) as sim:
sim.add_testbench(self.wishbone_slave, background=True)
sim.add_testbench(self.bus_mock, background=True)
sim.add_testbench(self.refiller_process)


Expand All @@ -157,21 +151,18 @@ def __init__(self, gen_params: GenParams):
def elaborate(self, platform):
m = Module()

wb_params = WishboneParameters(
bus_mock_params = BusMockParameters(
data_width=self.gen_params.isa.xlen,
addr_width=self.gen_params.isa.xlen,
)

m.submodules.wb_master = self.wb_master = WishboneMaster(wb_params)
m.submodules.bus_master_adapter = self.bus_master_adapter = WishboneMasterAdapter(self.wb_master)
m.submodules.bus_master_adapter = self.bus_master_adapter = MockMasterAdapter(bus_mock_params)
m.submodules.bypass = self.bypass = ICacheBypass(
self.gen_params.get(ICacheLayouts), self.cp, self.bus_master_adapter
)
m.submodules.issue_req = self.issue_req = TestbenchIO(AdapterTrans(self.bypass.issue_req))
m.submodules.accept_res = self.accept_res = TestbenchIO(AdapterTrans(self.bypass.accept_res))

self.wb_ctrl = WishboneInterfaceWrapper(self.wb_master.wb_master)

return m


Expand Down Expand Up @@ -216,12 +207,12 @@ def load_or_gen_mem(self, addr: int):
self.mem[addr] = random.randrange(2**self.gen_params.isa.ilen)
return self.mem[addr]

async def wishbone_slave(self, sim: TestbenchContext):
async def bus_mock(self, sim: TestbenchContext):
while True:
adr, *_ = await self.m.wb_ctrl.slave_wait(sim)
req = await self.m.bus_master_adapter.request_read_mock.call(sim)

# Wishbone is addressing words, so we need to shift it a bit to get the real address.
addr = adr << exact_log2(self.cp.word_width_bytes)
# Bus model is addressing words, so we need to shift it a bit to get the real address.
addr = req.addr << exact_log2(self.cp.word_width_bytes)

await self.random_wait_geom(sim, 0.5)

Expand All @@ -231,7 +222,7 @@ async def wishbone_slave(self, sim: TestbenchContext):
if self.gen_params.isa.xlen == 64:
data = self.load_or_gen_mem(addr + 4) << 32 | data

await self.m.wb_ctrl.slave_respond(sim, data, err=err)
await self.m.bus_master_adapter.get_read_response_mock.call(sim, data=data, err=err)

async def user_process(self, sim: TestbenchContext):
while self.requests:
Expand All @@ -256,7 +247,7 @@ async def user_process(self, sim: TestbenchContext):

def test(self):
with self.run_simulation(self.m) as sim:
sim.add_testbench(self.wishbone_slave, background=True)
sim.add_testbench(self.bus_mock, background=True)
sim.add_testbench(self.user_process)


Expand Down
90 changes: 55 additions & 35 deletions test/func_blocks/lsu/test_dummylsu.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import random
from collections import deque
from amaranth import *

from transactron.lib import Adapter
from transactron.testing.method_mock import MethodMock
from transactron.lib import Adapter, AdapterTrans
from transactron.utils import int_to_signed, signed_to_int
from transactron.utils.dependencies import DependencyContext
from transactron.testing.method_mock import MethodMock
from transactron.testing import CallTrigger, TestbenchIO, TestCaseWithSimulator, def_method_mock, TestbenchContext
from coreblocks.params import GenParams
from coreblocks.func_blocks.fu.lsu.dummyLsu import LSUDummy
from coreblocks.params.configurations import test_core_config
from coreblocks.arch import *
from coreblocks.interface.keys import CoreStateKey, ExceptionReportKey, InstructionPrecommitKey
from transactron.utils.dependencies import DependencyContext
from coreblocks.interface.layouts import ExceptionRegisterLayouts, RetirementLayouts
from coreblocks.peripherals.wishbone import *
from transactron.testing import TestbenchIO, TestCaseWithSimulator, def_method_mock, TestbenchContext
from coreblocks.peripherals.bus_adapter import WishboneMasterAdapter
from test.peripherals.test_wishbone import WishboneInterfaceWrapper
from ...peripherals.bus_mock import BusMockParameters, MockMasterAdapter


def generate_aligned_addr(max_reg_val: int) -> int:
Expand Down Expand Up @@ -69,13 +68,9 @@ def __init__(self, gen: GenParams):
def elaborate(self, platform):
m = Module()

wb_params = WishboneParameters(
data_width=self.gen.isa.ilen,
addr_width=32,
)
bus_mock_params = BusMockParameters(data_width=self.gen.isa.ilen, addr_width=32)

self.bus = WishboneMaster(wb_params)
self.bus_master_adapter = WishboneMasterAdapter(self.bus)
self.bus_master_adapter = MockMasterAdapter(bus_mock_params)

m.submodules.exception_report = self.exception_report = TestbenchIO(
Adapter(i=self.gen.get(ExceptionRegisterLayouts).report)
Expand All @@ -101,9 +96,7 @@ def elaborate(self, platform):

m.submodules.issue_mock = self.issue = TestbenchIO(AdapterTrans(func_unit.issue))
m.submodules.accept_mock = self.accept = TestbenchIO(AdapterTrans(func_unit.accept))
self.io_in = WishboneInterfaceWrapper(self.bus.wb_master)
m.submodules.bus_master_adapter = self.bus_master_adapter
m.submodules.bus = self.bus
return m


Expand Down Expand Up @@ -198,7 +191,7 @@ def setup_method(self) -> None:
self.generate_instr(2**7, 2**7)
self.max_wait = 10

async def wishbone_slave(self, sim: TestbenchContext):
async def bus_mock(self, sim: TestbenchContext):
while self.mem_data_queue:
generated_data = self.mem_data_queue.pop()

Expand All @@ -207,7 +200,9 @@ async def wishbone_slave(self, sim: TestbenchContext):

mask = generated_data["mask"]
sign = generated_data["sign"]
await self.test_module.io_in.slave_wait_and_verify(sim, generated_data["addr"], 0, 0, mask)
req = await self.test_module.bus_master_adapter.request_read_mock.call(sim)
assert req.addr == generated_data["addr"]
assert req.sel == mask
await self.random_wait(sim, self.max_wait)

resp_data = int((generated_data["rnd_bytes"][:4]).hex(), 16)
Expand All @@ -221,7 +216,9 @@ async def wishbone_slave(self, sim: TestbenchContext):
data = int_to_signed(signed_to_int(data, size), 32)
if not generated_data["err"]:
self.returned_data.appendleft(data)
await self.test_module.io_in.slave_respond(sim, resp_data, err=generated_data["err"])
await self.test_module.bus_master_adapter.get_read_response_mock.call(
sim, data=resp_data, err=generated_data["err"]
)

async def inserter(self, sim: TestbenchContext):
for i in range(self.tests_number):
Expand Down Expand Up @@ -263,7 +260,7 @@ def core_state_process():
return {"flushing": 0}

with self.run_simulation(self.test_module) as sim:
sim.add_testbench(self.wishbone_slave, background=True)
sim.add_testbench(self.bus_mock, background=True)
sim.add_testbench(self.inserter)
sim.add_testbench(self.consumer)

Expand All @@ -286,30 +283,35 @@ def generate_instr(self, max_reg_val, max_imm_val):
"pc": 0,
}

wish_data = {
data = {
"addr": (s1_val + imm) >> 2,
"mask": 0xF,
"rnd_bytes": bytes.fromhex(f"{random.randint(0, 2**32-1):08x}"),
}
return instr, wish_data
return instr, data

def setup_method(self) -> None:
random.seed(14)
self.gen_params = GenParams(test_core_config.replace(phys_regs_bits=3, rob_entries_bits=3))
self.test_module = DummyLSUTestCircuit(self.gen_params)

async def one_instr_test(self, sim: TestbenchContext):
instr, wish_data = self.generate_instr(2**7, 2**7)
instr, data = self.generate_instr(2**7, 2**7)

await self.test_module.issue.call(sim, instr)

mask = wish_data["mask"]
await self.test_module.io_in.slave_wait_and_verify(sim, wish_data["addr"], 0, 0, mask)
data = wish_data["rnd_bytes"][:4]
mask = data["mask"]
req = await self.test_module.bus_master_adapter.request_read_mock.call(sim)
assert req.addr == data["addr"]
assert req.sel == mask
data = data["rnd_bytes"][:4]
data = int(data.hex(), 16)
await self.test_module.io_in.slave_respond(sim, data)

v = await self.test_module.accept.call(sim)
r, v = (
await CallTrigger(sim)
.call(self.test_module.bus_master_adapter.get_read_response_mock, data=data, err=0)
.call(self.test_module.accept)
)
assert r is not None and v is not None
assert v["result"] == data

def test(self):
Expand Down Expand Up @@ -378,7 +380,7 @@ def setup_method(self) -> None:
self.generate_instr(2**7, 2**7)
self.max_wait = 8

async def wishbone_slave(self, sim: TestbenchContext):
async def bus_mock(self, sim: TestbenchContext):
for i in range(self.tests_number):
generated_data = self.mem_data_queue.pop()

Expand All @@ -391,10 +393,13 @@ async def wishbone_slave(self, sim: TestbenchContext):
data = (int(generated_data["data"][-2:].hex(), 16) & 0xFFFF) << h_dict[mask]
else:
data = int(generated_data["data"][-4:].hex(), 16)
await self.test_module.io_in.slave_wait_and_verify(sim, generated_data["addr"], data, 1, mask)
req = await self.test_module.bus_master_adapter.request_write_mock.call(sim)
assert req.addr == generated_data["addr"]
assert req.data == data
assert req.sel == generated_data["mask"]
await self.random_wait(sim, self.max_wait)

await self.test_module.io_in.slave_respond(sim, 0)
await self.test_module.bus_master_adapter.get_write_response_mock.call(sim, err=0)

async def inserter(self, sim: TestbenchContext):
for i in range(self.tests_number):
Expand Down Expand Up @@ -428,7 +433,7 @@ def eff():
assert False

with self.run_simulation(self.test_module) as sim:
sim.add_testbench(self.wishbone_slave)
sim.add_testbench(self.bus_mock)
sim.add_testbench(self.inserter)
sim.add_testbench(self.get_resulter)

Expand All @@ -440,9 +445,6 @@ def get_instr(self, exec_fn):
async def push_one_instr(self, sim: TestbenchContext, instr):
await self.test_module.issue.call(sim, instr)

if instr["exec_fn"]["op_type"] == OpType.LOAD:
await self.test_module.io_in.slave_wait(sim)
await self.test_module.io_in.slave_respond(sim, 1)
v = await self.test_module.accept.call(sim)
if instr["exec_fn"]["op_type"] == OpType.LOAD:
assert v.result == 1
Expand All @@ -469,5 +471,23 @@ def eff():
def precommiter(rob_id):
return {"side_fx": 1}

pending_req = False

@def_method_mock(lambda: self.test_module.bus_master_adapter.request_read_mock, enable=lambda: not pending_req)
def request_read(addr, sel):
@MethodMock.effect
def eff():
nonlocal pending_req
pending_req = True

@def_method_mock(lambda: self.test_module.bus_master_adapter.get_read_response_mock, enable=lambda: pending_req)
def read_response():
@MethodMock.effect
def eff():
nonlocal pending_req
pending_req = False

return {"data": 1, "err": 0}

with self.run_simulation(self.test_module) as sim:
sim.add_testbench(self.process)
Loading

0 comments on commit b4a84bd

Please sign in to comment.