checks.gpr: add GPRCheck.
							parent
							
								
									6b5536eb0f
								
							
						
					
					
						commit
						b84a23877a
					
				@ -1,2 +1,3 @@
 | 
			
		||||
from .unique import *
 | 
			
		||||
from .gpr    import *
 | 
			
		||||
from .ia_fwd import *
 | 
			
		||||
from .unique import *
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,73 @@
 | 
			
		||||
from amaranth import *
 | 
			
		||||
from amaranth.asserts import *
 | 
			
		||||
 | 
			
		||||
from .. import pfv
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ["GPRCheck"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GPRCheck(Elaboratable):
 | 
			
		||||
    """General Purpose Registers check.
 | 
			
		||||
 | 
			
		||||
    Checks that reads from GPRs are consistent with the last value that was written to them.
 | 
			
		||||
    Also checks that simultaneous writes to multiple GPRs by the same instruction (e.g. a load
 | 
			
		||||
    with update) do not target the same register.
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.pre  = Signal()
 | 
			
		||||
        self.post = Signal()
 | 
			
		||||
        self.pfv  = pfv.Interface()
 | 
			
		||||
 | 
			
		||||
    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.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):
 | 
			
		||||
            m.d.sync += [
 | 
			
		||||
                Assume(Past(self.pfv.stb)),
 | 
			
		||||
                Assume(Past(self.pfv.order) == spec_order),
 | 
			
		||||
                Assert(gpr_written.implies(~gpr_conflict)),
 | 
			
		||||
            ]
 | 
			
		||||
            with m.If(Past(gpr_ra_read)):
 | 
			
		||||
                m.d.sync += Assert(Past(gpr_shadow) == Past(self.pfv.ra.r_data))
 | 
			
		||||
            with m.If(Past(gpr_rb_read)):
 | 
			
		||||
                m.d.sync += Assert(Past(gpr_shadow) == Past(self.pfv.rb.r_data))
 | 
			
		||||
            with m.If(Past(gpr_rs_read)):
 | 
			
		||||
                m.d.sync += Assert(Past(gpr_shadow) == Past(self.pfv.rs.r_data))
 | 
			
		||||
            with m.If(Past(gpr_rt_read)):
 | 
			
		||||
                m.d.sync += Assert(Past(gpr_shadow) == Past(self.pfv.rt.r_data))
 | 
			
		||||
 | 
			
		||||
        return m
 | 
			
		||||
					Loading…
					
					
				
		Reference in New Issue