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.9 KiB
Python

from amaranth import *
from amaranth.asserts import *
from .. import pfv
__all__ = ["Check"]
class Check(Elaboratable):
"""General Purpose Registers check.
Checks that:
* reads from a GPR are consistent with 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):
self.pfv = pfv.Interface()
self.trig = Record([
("pre", 1),
("post", 1),
])
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.trig.post):
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