cores/dinofly: add insn and data storage checks.

dinofly
Jean-François Nguyen 11 months ago
parent 96878c73da
commit a3dd57ac46

@ -2,6 +2,7 @@ from pathlib import PurePath
from power_fv.session import PowerFVSession

from .core import DinoflyCore
from .check.storage import *


class DinoflySession(PowerFVSession, core_cls=DinoflyCore):

@ -0,0 +1,166 @@
from amaranth import *
from amaranth.asserts import *
from amaranth.utils import log2_int

from amaranth_soc import wishbone

from power_fv.check.storage import *

from ..core import *


__all__ = [
"InsnStorageCheck_Dinofly", "InsnStorageTestbench_Dinofly", "InsnStorageModel_Dinofly",
"DataStorageCheck_Dinofly", "DataStorageTestbench_Dinofly", "DataStorageModel_Dinofly",
]


class InsnStorageCheck_Dinofly(InsnStorageCheck, name=("dinofly", "storage", "insn")):
def __init__(self, *, depth, skip, core, **kwargs):
if not isinstance(core, DinoflyCore):
raise TypeError("Core must be an instance of DinoflyCore, not {!r}"
.format(core))
super().__init__(depth=depth, skip=skip, core=core, **kwargs)

def testbench(self):
return InsnStorageTestbench_Dinofly(self)


class InsnStorageTestbench_Dinofly(InsnStorageTestbench):
def __init__(self, check):
if not isinstance(check, InsnStorageCheck_Dinofly):
raise TypeError("Check must be an instance of InsnStorageCheck_Dinofly, not {!r}"
.format(check))
super().__init__(check)

def storage(self):
return InsnStorageModel_Dinofly(
ibus_addr_width=self.check.dut.ibus.addr_width,
ibus_data_width=self.check.dut.ibus.data_width,
ibus_granularity=self.check.dut.ibus.granularity,
)


class InsnStorageModel_Dinofly(InsnStorageModel, Elaboratable):
def __init__(self, *, ibus_addr_width=30, ibus_data_width=32, ibus_granularity=8):
self.addr = Signal(64)
self.data = Signal(32)
self._ibus = wishbone.Interface(addr_width=ibus_addr_width, data_width=ibus_data_width,
granularity=ibus_granularity)

def connect(self, dut):
assert isinstance(dut, DinoflyWrapper)
assert dut.ibus.addr_width == self._ibus.addr_width
assert dut.ibus.data_width == self._ibus.data_width
assert dut.ibus.granularity == self._ibus.granularity

return self._ibus.eq(dut.ibus)

def elaborate(self, platform):
m = Module()

with m.If(self._ibus.ack):
m.d.comb += [
Assume(self._ibus.cyc & Past(self._ibus.cyc)),
Assume(self._ibus.stb & Past(self._ibus.stb)),
Assume(~Past(self._ibus.ack)),
]

gran_bits = log2_int(self._ibus.data_width // self._ibus.granularity)

m.d.comb += [
self.addr.eq(AnyConst(self._ibus.addr_width + gran_bits)),
self.data.eq(AnyConst(32)),
]

with m.If(self._ibus.cyc & self._ibus.stb & self._ibus.ack & ~ResetSignal("sync")):
if self._ibus.data_width == 32:
with m.If(self.addr == Cat(Const(0b00, 2), self._ibus.adr)):
m.d.comb += Assume(self._ibus.dat_r == self.data)
elif self._ibus.data_width == 64:
with m.If(self.addr == Cat(Const(0b000, 3), self._ibus.adr)):
m.d.comb += Assume(self._ibus.dat_r[:32] == self.data)
with m.If(self.addr == Cat(Const(0b100, 3), self._ibus.adr)):
m.d.comb += Assume(self._ibus.dat_r[32:] == self.data)
else:
assert False

return m


class DataStorageCheck_Dinofly(DataStorageCheck, name=("dinofly", "storage", "data")):
def __init__(self, *, depth, skip, core, **kwargs):
if not isinstance(core, DinoflyCore):
raise TypeError("Core must be an instance of DinoflyCore, not {!r}"
.format(core))
super().__init__(depth=depth, skip=skip, core=core, **kwargs)

def testbench(self):
return DataStorageTestbench_Dinofly(self)


class DataStorageTestbench_Dinofly(DataStorageTestbench):
def __init__(self, check):
if not isinstance(check, DataStorageCheck_Dinofly):
raise TypeError("Check must be an instance of DataStorageCheck_Dinofly, not {!r}"
.format(check))
super().__init__(check)

def storage(self):
return DataStorageModel_Dinofly(
dbus_addr_width=self.check.dut.dbus.addr_width,
dbus_data_width=self.check.dut.dbus.data_width,
dbus_granularity=self.check.dut.dbus.granularity,
)


class DataStorageModel_Dinofly(DataStorageModel, Elaboratable):
def __init__(self, *, dbus_addr_width=30, dbus_data_width=32, dbus_granularity=8):
self.addr = Signal(64)
self._dbus = wishbone.Interface(addr_width=dbus_addr_width, data_width=dbus_data_width,
granularity=dbus_granularity)

def connect(self, dut):
assert isinstance(dut, DinoflyWrapper)
assert dut.dbus.addr_width == self._dbus.addr_width
assert dut.dbus.data_width == self._dbus.data_width
assert dut.dbus.granularity == self._dbus.granularity

return self._dbus.eq(dut.dbus)

def elaborate(self, platform):
m = Module()

dbus_read = Signal()
dbus_write = Signal()

m.d.comb += [
dbus_read .eq(self._dbus.cyc & self._dbus.stb & self._dbus.ack),
dbus_write.eq(self._dbus.cyc & self._dbus.stb & self._dbus.ack & self._dbus.we),
]

with m.If(self._dbus.ack):
m.d.comb += [
Assume(self._dbus.cyc & Past(self._dbus.cyc)),
Assume(self._dbus.stb & Past(self._dbus.stb)),
Assume(~Past(self._dbus.ack)),
]

gran_bits = log2_int(self._dbus.data_width // self._dbus.granularity)
addr_hit = Signal()
value = Signal(self._dbus.data_width)

m.d.comb += [
self.addr.eq(AnyConst(self._dbus.addr_width + gran_bits)),
addr_hit .eq(self._dbus.adr == self.addr[gran_bits:]),
]

with m.If(dbus_read & addr_hit & ~ResetSignal("sync")):
m.d.comb += Assume(self._dbus.dat_r == value)

with m.If(dbus_write & addr_hit):
for i, sel_bit in enumerate(self._dbus.sel):
with m.If(sel_bit):
m.d.sync += value[i*8:i*8+8].eq(self._dbus.dat_w[i*8:i*8+8])

return m
Loading…
Cancel
Save