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.
70 lines
1.9 KiB
Python
70 lines
1.9 KiB
Python
2 years ago
|
from abc import ABCMeta, abstractmethod
|
||
|
|
||
|
from amaranth import *
|
||
|
from amaranth.asserts import *
|
||
|
|
||
|
from power_fv.check import PowerFVCheck
|
||
|
|
||
|
|
||
|
__all__ = ["DataStorageCheck", "DataStorageModel", "DataStorageTestbench"]
|
||
|
|
||
|
|
||
|
# TODO: add support for restricting addresses to non-cachable/write-through regions.
|
||
|
|
||
|
|
||
|
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.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
|