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.

78 lines
2.3 KiB
Python

from collections import OrderedDict
from amaranth import *
from amaranth.asserts import *
from ... import PowerFVCheck
from .... import pfv, tb
__all__ = ["SPRSpec", "SPRCheck"]
class StorageSPRSpec(Elaboratable):
"""Storage SPR specification.
Checks that reads from supported SPRs return the last value that was written to them.
"""
def __init__(self, spr_name, spr_reset, post):
self.spr_name = spr_name
self.spr_reset = spr_reset
self.pfv = pfv.Interface()
self.post = tb.Trigger(cycle=post)
def triggers(self):
yield self.post
@property
def pfv_spr(self):
return getattr(self.pfv, self.spr_name)
def elaborate(self, platform):
m = Module()
spr = Record([
("written", 1),
("shadow", self.pfv_spr.r_data.width),
], name=self.spr_name)
spec_order = AnyConst(self.pfv.order.width)
with m.If(Initial()):
m.d.sync += Assume(spr.shadow == self.spr_reset)
with m.If(self.pfv.stb & (self.pfv.order <= spec_order)):
with m.If(self.pfv_spr.w_mask.any()):
m.d.sync += [
spr.written.eq(1),
spr.shadow .eq((spr.shadow & ~self.pfv_spr.w_mask) | (self.pfv_spr.w_data & self.pfv_spr.w_mask)),
]
with m.If(self.post.stb):
m.d.sync += [
Assume(Past(self.pfv.stb)),
Assume(Past(self.pfv.order) == spec_order),
]
with m.If(spr.written):
p_spr_r_mask = Past(self.pfv_spr.r_mask)
p_spr_r_data = Past(self.pfv_spr.r_data)
p_spr_shadow = Past(spr.shadow)
m.d.sync += Assert((p_spr_r_data & p_spr_r_mask) == (p_spr_shadow & p_spr_r_mask))
m.d.sync += Assume(spr.written & Past(self.pfv_spr.r_mask).any()) # FIXME rm
return m
class StorageSPRCheck(PowerFVCheck, name="_cons_spr_storage"):
def __init_subclass__(cls, name, spr_name):
super().__init_subclass__(name)
cls.spr_name = spr_name
def get_testbench(self, dut, post, spr_reset=0):
tb_spec = StorageSPRSpec(self.spr_name, spr_reset, post)
tb_top = tb.Testbench(tb_spec, dut)
return tb_top