You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
3.6 KiB
Python

from abc import ABCMeta, abstractmethod
from amaranth import *
from amaranth.asserts import *
from power_fv.check import PowerFVCheck
__all__ = [
"InsnStorageCheck", "InsnStorageModel", "InsnStorageTestbench",
"DataStorageCheck", "DataStorageModel", "DataStorageTestbench",
]
# TODO: add support for restricting addresses to non-cachable/write-through regions.
class InsnStorageCheck(PowerFVCheck):
pass
class InsnStorageModel(metaclass=ABCMeta):
@abstractmethod
def connect(self, dut):
raise NotImplementedError
@abstractmethod
def elaborate(self, platform):
raise NotImplementedError
class InsnStorageTestbench(Elaboratable, metaclass=ABCMeta):
def __init__(self, check):
if not isinstance(check, InsnStorageCheck):
raise TypeError("Check must be an instance of InsnStorageCheck, not {!r}"
.format(check))
self.check = check
self.name = "storage_insn_tb"
@abstractmethod
def storage(self):
raise NotImplementedError
def elaborate(self, platform):
m = Module()
m.submodules.dut = dut = self.check.dut
m.submodules.storage = storage = self.storage()
insn_po = Signal(6)
prefixed = Signal()
m.d.comb += [
storage.connect(dut),
insn_po .eq(dut.pfv.insn[63-5:64-0]),
prefixed.eq(insn_po == 1),
]
with m.If(dut.pfv.stb & ~dut.pfv.intr):
with m.If(dut.pfv.cia == storage.addr):
m.d.comb += Assert(dut.pfv.insn[32:] == storage.data)
with m.If(prefixed & (dut.pfv.cia + 4 == storage.addr)):
m.d.comb += Assert(dut.pfv.insn[:32] == storage.data)
return m
class DataStorageCheck(PowerFVCheck):
pass
class DataStorageModel(metaclass=ABCMeta):
@abstractmethod
def connect(self, dut):
raise NotImplementedError
@abstractmethod
def elaborate(self, platform):
raise NotImplementedError
class DataStorageTestbench(Elaboratable, metaclass=ABCMeta):
def __init__(self, check):
if not isinstance(check, DataStorageCheck):
raise TypeError("Check must be an instance of DataStorageCheck, not {!r}"
.format(check))
self.check = check
self.name = "storage_data_tb"
@abstractmethod
def storage(self):
raise NotImplementedError
def elaborate(self, platform):
m = Module()
m.submodules.dut = dut = self.check.dut
m.submodules.storage = storage = self.storage()
written = Signal(64 // 8)
shadow = Signal(64)
m.d.comb += storage.connect(dut)
with m.If(dut.pfv.stb & dut.pfv.skip):
m.d.comb += [
Assert(~dut.pfv.mem.r_mask.any()),
Assert(~dut.pfv.mem.w_mask.any()),
]
with m.If(dut.pfv.stb & (dut.pfv.mem.addr == storage.addr)):
for i, byte_written in enumerate(written):
byte_shadow = shadow[i*8:i*8+8]
byte_w_stb = dut.pfv.mem.w_mask[i]
byte_w_data = dut.pfv.mem.w_data[i*8:i*8+8]
byte_r_stb = dut.pfv.mem.r_mask[i]
byte_r_data = dut.pfv.mem.r_data[i*8:i*8+8]
with m.If(byte_w_stb):
m.d.sync += [
byte_written.eq(1),
byte_shadow .eq(byte_w_data),
]
with m.If(byte_r_stb & byte_written):
m.d.comb += Assert(byte_r_data == byte_shadow)
return m