-"""ConfigureableLoadStoreUnit
+"""ConfigureableLoadStoreUnit and ConfigMemoryPortInterface
allows the type of LoadStoreUnit to be run-time selectable
+this allows the same code to be used for both small unit tests
+as well as larger ones and so on, without needing large amounts
+of unnecessarily-duplicated code
"""
from soc.experiment.lsmem import TestMemLoadStoreUnit
from soc.bus.test.test_minerva import TestSRAMBareLoadStoreUnit
-
+from soc.experiment.pi2ls import Pi2LSUI
+from soc.experiment.pimem import TestMemoryPortInterface
class ConfigLoadStoreUnit:
def __init__(self, pspec):
mask_wid=pspec.mask_wid, # cache line range
data_wid=pspec.reg_wid) # data bus width
+
+class ConfigMemoryPortInterface:
+ def __init__(self, pspec):
+ if pspec.ldst_ifacetype == 'testpi':
+ self.pi = TestMemoryPortInterface(addrwid=pspec.addr_wid, # adr bus
+ regwid=pspec.reg_wid) # data bus
+ return
+ self.lsmem = ConfigLoadStoreUnit(pspec)
+ self.pi = Pi2LSUI("mem", lsui=self.lsmem.lsi,
+ addr_wid=pspec.addr_wid, # address range
+ mask_wid=pspec.mask_wid, # cache line range
+ data_wid=pspec.reg_wid) # data bus width
from collections import namedtuple
from nmigen.cli import rtlil
+TestMemPspec = namedtuple('TestMemPspec', ['ldst_ifacetype',
+ 'addr_wid', 'mask_wid', 'reg_wid'])
def write_to_addr(dut, addr, value):
yield dut.x_addr_i.eq(addr)
def tst_lsmemtype(ifacetype):
m = Module()
- Pspec = namedtuple('Pspec', ['ldst_ifacetype',
- 'addr_wid', 'mask_wid', 'reg_wid'])
- pspec = Pspec(ldst_ifacetype=ifacetype, addr_wid=64, mask_wid=4, reg_wid=32)
+ pspec = TestMemPspec(ldst_ifacetype=ifacetype, addr_wid=64,
+ mask_wid=4,
+ reg_wid=32)
dut = ConfigLoadStoreUnit(pspec).lsi
vl = rtlil.convert(dut, ports=[]) # TODOdut.ports())
with open("test_loadstore_%s.il" % ifacetype, "w") as f:
class Pi2LSUI(Elaboratable):
def __init__(self, name, pi=None, lsui=None,
- regwid=64, mask_wid=8, addrwid=48):
- print ("pi2lsui reg mask addr", regwid, mask_wid, addrwid)
+ data_wid=64, mask_wid=8, addr_wid=48):
+ print ("pi2lsui reg mask addr", data_wid, mask_wid, addr_wid)
self.addrbits = mask_wid
if pi is None:
piname = "%s_pi" % name
- pi = PortInterface(piname, regwid=regwid, addrwid=addrwid)
+ pi = PortInterface(piname, regwid=data_wid, addrwid=addr_wid)
self.pi = pi
if lsui is None:
- lsui = LoadStoreUnitInterface(addrwid, self.addrbits, regwid)
+ lsui = LoadStoreUnitInterface(addr_wid, self.addrbits, data_wid)
self.lsui = lsui
def splitaddr(self, addr):
from nmutil.formaltest import FHDLTestCase
from nmigen.cli import rtlil
import unittest
-from soc.experiment.pi2ls import Pi2LSUI
-from soc.experiment.lsmem import TestMemLoadStoreUnit
-from soc.experiment.pimem import TestMemoryPortInterface
+from soc.config.test.test_loadstore import TestMemPspec
+from soc.config.loadstore import ConfigMemoryPortInterface
+
def wait_busy(port, no=False):
while True:
def l0_cache_ldst(arg, dut):
- yield
+
+ # do two half-word stores at consecutive addresses, then two loads
addr1 = 0x04
addr2 = addr1 + 0x2
data = 0xbeef
arg.assertEqual(data, result, "data %x != %x" % (result, data))
arg.assertEqual(data2, result2, "data2 %x != %x" % (result2, data2))
- # now load both
+ # now load both in a 32-bit load to make sure they're really consecutive
data3 = data | (data2 << 16)
result3 = yield from l0_cache_ld(dut, addr1, 4)
arg.assertEqual(data3, result3, "data3 %x != %x" % (result3, data3))
-class TestPIMem(unittest.TestCase):
+def tst_config_pi(testcls, ifacetype):
+ """set up a configureable memory test of type ifacetype
+ """
+ dut = Module()
+ pspec = TestMemPspec(ldst_ifacetype=ifacetype,
+ addr_wid=48,
+ mask_wid=8,
+ reg_wid=64)
+ cmpi = ConfigMemoryPortInterface(pspec)
+ dut.submodules.pi = cmpi.pi
+ if hasattr(cmpi, 'lsmem'): # hmmm not happy about this
+ dut.submodules.lsmem = cmpi.lsmem.lsi
+ vl = rtlil.convert(dut, ports=[])#dut.ports())
+ with open("test_pi_%s.il" % ifacetype, "w") as f:
+ f.write(vl)
- def test_pi_mem(self):
+ run_simulation(dut, {"sync": l0_cache_ldst(testcls, cmpi.pi)},
+ vcd_name='test_pi_%s.vcd' % ifacetype)
- dut = TestMemoryPortInterface(regwid=64)
- #vl = rtlil.convert(dut, ports=dut.ports())
- #with open("test_basic_l0_cache.il", "w") as f:
- # f.write(vl)
- run_simulation(dut, {"sync": l0_cache_ldst(self, dut)},
- vcd_name='test_pi_mem_basic.vcd')
+class TestPIMem(unittest.TestCase):
+
+ def test_pi_mem(self):
+ tst_config_pi(self, 'testpi')
def test_pi2ls(self):
- m = Module()
- regwid = 64
- addrwid = 48
- m.submodules.lsmem = lsmem = TestMemLoadStoreUnit(addr_wid=addrwid,
- mask_wid=8,
- data_wid=regwid)
- m.submodules.dut = dut = Pi2LSUI("mem", lsui=lsmem,
- regwid=regwid, addrwid=addrwid)
-
- """ passing in lsmem to Pi2LSUI means this isn't needed
- # Connect inputs
- m.d.comb += [lsmem.x_addr_i.eq(dut.lsui.x_addr_i),
- lsmem.x_mask_i.eq(dut.lsui.x_mask_i),
- lsmem.x_ld_i.eq(dut.lsui.x_ld_i),
- lsmem.x_st_i.eq(dut.lsui.x_st_i),
- lsmem.x_st_data_i.eq(dut.lsui.x_st_data_i),
- lsmem.x_stall_i.eq(dut.lsui.x_stall_i),
- lsmem.x_valid_i.eq(dut.lsui.x_valid_i),
- lsmem.m_stall_i.eq(dut.lsui.m_stall_i),
- lsmem.m_valid_i.eq(dut.lsui.m_valid_i)]
-
- # connect outputs
- m.d.comb += [dut.lsui.x_busy_o.eq(lsmem.x_busy_o),
- dut.lsui.m_busy_o.eq(lsmem.m_busy_o),
- dut.lsui.m_ld_data_o.eq(lsmem.m_ld_data_o),
- dut.lsui.m_load_err_o.eq(lsmem.m_load_err_o),
- dut.lsui.m_store_err_o.eq(lsmem.m_store_err_o),
- dut.lsui.m_badaddr_o.eq(lsmem.m_badaddr_o)]
- """
- run_simulation(m, {"sync": l0_cache_ldst(self, dut)},
- vcd_name='test_pi2ls.vcd')
+ tst_config_pi(self, 'testmem')
+
if __name__ == '__main__':
unittest.main(exit=False)
+