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.

86 lines
3.1 KiB
Python

from amaranth import *
from amaranth.asserts import *
from .. import PowerFVCheck
from ... import pfv, tb
__all__ = ["GPRSpec", "GPRCheck"]
class GPRSpec(Elaboratable):
"""GPR consistency specification.
Checks that:
* reads from a GPR return the last value that was written to it;
* writes to multiple GPRs by a single instruction (e.g. load with update) do not target the
same register.
"""
def __init__(self, post):
self.pfv = pfv.Interface()
self.post = tb.Trigger(cycle=post)
def triggers(self):
yield self.post
def elaborate(self, platform):
m = Module()
spec_order = AnyConst(self.pfv.order.width)
spec_gpr_index = AnyConst(5)
gpr_ra_read = Signal()
gpr_ra_write = Signal()
gpr_rb_read = Signal()
gpr_rs_read = Signal()
gpr_rt_read = Signal()
gpr_rt_write = Signal()
gpr_conflict = Signal()
gpr_written = Signal()
gpr_shadow = Signal(64)
m.d.comb += [
gpr_ra_read .eq(self.pfv.ra.r_stb & (self.pfv.ra.index == spec_gpr_index)),
gpr_ra_write.eq(self.pfv.ra.w_stb & (self.pfv.ra.index == spec_gpr_index)),
gpr_rb_read .eq(self.pfv.rb.r_stb & (self.pfv.rb.index == spec_gpr_index)),
gpr_rs_read .eq(self.pfv.rs.r_stb & (self.pfv.rs.index == spec_gpr_index)),
gpr_rt_read .eq(self.pfv.rt.r_stb & (self.pfv.rt.index == spec_gpr_index)),
gpr_rt_write.eq(self.pfv.rt.w_stb & (self.pfv.rt.index == spec_gpr_index)),
]
with m.If(self.pfv.stb & ~self.pfv.intr & (self.pfv.order <= spec_order)):
with m.If(gpr_ra_write & gpr_rt_write):
m.d.sync += gpr_conflict.eq(1)
with m.If(gpr_ra_write | gpr_rt_write):
m.d.sync += gpr_written.eq(1)
with m.If(gpr_ra_write):
m.d.sync += gpr_shadow.eq(self.pfv.ra.w_data)
with m.Else():
m.d.sync += gpr_shadow.eq(self.pfv.rt.w_data)
with m.If(self.post.stb):
m.d.sync += [
Assume(Past(self.pfv.stb)),
Assume(Past(self.pfv.order) == spec_order),
]
with m.If(~Past(self.pfv.intr)):
m.d.sync += Assert(gpr_written.implies(~gpr_conflict))
with m.If(gpr_written & Past(gpr_ra_read)):
m.d.sync += Assert(Past(gpr_shadow) == Past(self.pfv.ra.r_data))
with m.If(gpr_written & Past(gpr_rb_read)):
m.d.sync += Assert(Past(gpr_shadow) == Past(self.pfv.rb.r_data))
with m.If(gpr_written & Past(gpr_rs_read)):
m.d.sync += Assert(Past(gpr_shadow) == Past(self.pfv.rs.r_data))
with m.If(gpr_written & Past(gpr_rt_read)):
m.d.sync += Assert(Past(gpr_shadow) == Past(self.pfv.rt.r_data))
return m
class GPRCheck(PowerFVCheck, name="cons_gpr"):
def get_testbench(self, dut, post):
tb_spec = GPRSpec(post)
tb_top = tb.Testbench(tb_spec, dut)
return tb_top