checks.insn: add checks for compare instructions.
							parent
							
								
									a413025fcb
								
							
						
					
					
						commit
						692e8ec7c4
					
				@ -0,0 +1,152 @@
 | 
			
		||||
from amaranth import *
 | 
			
		||||
from amaranth.asserts import *
 | 
			
		||||
 | 
			
		||||
from .. import PowerFVCheck
 | 
			
		||||
from ... import pfv, tb
 | 
			
		||||
 | 
			
		||||
from ._fmt  import *
 | 
			
		||||
from ._insn import *
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ["CompareSpec", "CompareCheck"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CompareSpec(Elaboratable):
 | 
			
		||||
    def __init__(self, insn_cls, post):
 | 
			
		||||
        self.insn_cls = insn_cls
 | 
			
		||||
        self.pfv      = pfv.Interface()
 | 
			
		||||
        self.post     = tb.Trigger(cycle=post)
 | 
			
		||||
 | 
			
		||||
    def triggers(self):
 | 
			
		||||
        yield self.post
 | 
			
		||||
 | 
			
		||||
    def elaborate(self, platform):
 | 
			
		||||
        m = Module()
 | 
			
		||||
 | 
			
		||||
        spec_insn = self.insn_cls()
 | 
			
		||||
 | 
			
		||||
        with m.If(self.post.stb):
 | 
			
		||||
            m.d.sync += [
 | 
			
		||||
                Assume(self.pfv.stb),
 | 
			
		||||
                Assume(self.pfv.insn[32:] == spec_insn),
 | 
			
		||||
            ]
 | 
			
		||||
 | 
			
		||||
        # GPRs
 | 
			
		||||
 | 
			
		||||
        spec_ra_r_stb = Signal()
 | 
			
		||||
        spec_rb_r_stb = Signal()
 | 
			
		||||
 | 
			
		||||
        if isinstance(spec_insn, (CMPI, CMPLI, CMP, CMPL)):
 | 
			
		||||
            m.d.comb += spec_ra_r_stb.eq(1)
 | 
			
		||||
        else:
 | 
			
		||||
            assert False
 | 
			
		||||
 | 
			
		||||
        if isinstance(spec_insn, (CMPI, CMPLI)):
 | 
			
		||||
            m.d.comb += spec_rb_r_stb.eq(0)
 | 
			
		||||
        elif isinstance(spec_insn, (CMP, CMPL)):
 | 
			
		||||
            m.d.comb += spec_rb_r_stb.eq(1)
 | 
			
		||||
        else:
 | 
			
		||||
            assert False
 | 
			
		||||
 | 
			
		||||
        with m.If(self.post.stb & ~self.pfv.intr):
 | 
			
		||||
            m.d.sync += [
 | 
			
		||||
                Assert(self.pfv.ra.r_stb == spec_ra_r_stb),
 | 
			
		||||
                Assert(self.pfv.rb.r_stb == spec_rb_r_stb),
 | 
			
		||||
            ]
 | 
			
		||||
 | 
			
		||||
        # CR
 | 
			
		||||
 | 
			
		||||
        spec_cr_w_stb  = Signal(8)
 | 
			
		||||
        spec_cr_w_data = Signal(32)
 | 
			
		||||
 | 
			
		||||
        a = Signal(signed(64))
 | 
			
		||||
        b = Signal(signed(64))
 | 
			
		||||
        c = Record([("lt", 1), ("gt", 1), ("eq_", 1), ("so", 1)])
 | 
			
		||||
 | 
			
		||||
        if isinstance(spec_insn, (CMPI, CMP)):
 | 
			
		||||
            with m.If(spec_insn.l):
 | 
			
		||||
                m.d.comb += a.eq(self.pfv.ra.r_data)
 | 
			
		||||
            with m.Else():
 | 
			
		||||
                m.d.comb += a.eq(self.pfv.ra.r_data[:32].as_signed())
 | 
			
		||||
        elif isinstance(spec_insn, (CMPL, CMPLI)):
 | 
			
		||||
            with m.If(spec_insn.l):
 | 
			
		||||
                m.d.comb += a.eq(self.pfv.ra.r_data)
 | 
			
		||||
            with m.Else():
 | 
			
		||||
                m.d.comb += a.eq(self.pfv.ra.r_data[:32].as_unsigned())
 | 
			
		||||
        else:
 | 
			
		||||
            assert False
 | 
			
		||||
 | 
			
		||||
        if isinstance(spec_insn, CMPI):
 | 
			
		||||
            m.d.comb += b.eq(spec_insn.si)
 | 
			
		||||
        elif isinstance(spec_insn, CMPLI):
 | 
			
		||||
            m.d.comb += b.eq(spec_insn.ui)
 | 
			
		||||
        elif isinstance(spec_insn, CMP):
 | 
			
		||||
            with m.If(spec_insn.l):
 | 
			
		||||
                m.d.comb += b.eq(self.pfv.rb.r_data)
 | 
			
		||||
            with m.Else():
 | 
			
		||||
                m.d.comb += b.eq(self.pfv.rb.r_data[:32].as_signed())
 | 
			
		||||
        elif isinstance(spec_insn, CMPL):
 | 
			
		||||
            with m.If(spec_insn.l):
 | 
			
		||||
                m.d.comb += b.eq(self.pfv.rb.r_data)
 | 
			
		||||
            with m.Else():
 | 
			
		||||
                m.d.comb += b.eq(self.pfv.rb.r_data[:32].as_unsigned())
 | 
			
		||||
        else:
 | 
			
		||||
            assert False
 | 
			
		||||
 | 
			
		||||
        if isinstance(spec_insn, (CMPI, CMP)):
 | 
			
		||||
            m.d.comb += [
 | 
			
		||||
                c.lt.eq(a.as_signed() < b.as_signed()),
 | 
			
		||||
                c.gt.eq(a.as_signed() > b.as_signed()),
 | 
			
		||||
            ]
 | 
			
		||||
        elif isinstance(spec_insn, (CMPLI, CMPL)):
 | 
			
		||||
            m.d.comb += [
 | 
			
		||||
                c.lt.eq(a.as_unsigned() < b.as_unsigned()),
 | 
			
		||||
                c.gt.eq(a.as_unsigned() > b.as_unsigned()),
 | 
			
		||||
            ]
 | 
			
		||||
        else:
 | 
			
		||||
            assert False
 | 
			
		||||
 | 
			
		||||
        m.d.comb += [
 | 
			
		||||
            c.eq_.eq(a == b),
 | 
			
		||||
            c.so .eq(self.pfv.xer.r_data[63 - 32]), # XER.SO
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
        m.d.comb += [
 | 
			
		||||
            spec_cr_w_stb[::-1].bit_select(spec_insn.bf, width=1).eq(1),
 | 
			
		||||
            spec_cr_w_data[::-1].eq(Repl(c, 8)),
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
        with m.If(self.post.stb & ~self.pfv.intr):
 | 
			
		||||
            for i in range(8):
 | 
			
		||||
                spec_cr_w_field = spec_cr_w_data    .word_select(i, width=4)
 | 
			
		||||
                pfv_cr_w_field  = self.pfv.cr.w_data.word_select(i, width=4)
 | 
			
		||||
 | 
			
		||||
                m.d.sync += [
 | 
			
		||||
                    Assert(self.pfv.cr.w_stb[i] == spec_cr_w_stb[i]),
 | 
			
		||||
                    Assert(spec_cr_w_stb[i].implies(pfv_cr_w_field == spec_cr_w_field)),
 | 
			
		||||
                ]
 | 
			
		||||
 | 
			
		||||
        # XER
 | 
			
		||||
 | 
			
		||||
        spec_xer_r_mask = Signal(64)
 | 
			
		||||
 | 
			
		||||
        if isinstance(spec_insn, (CMPI, CMPLI, CMP, CMPL)):
 | 
			
		||||
            m.d.comb += spec_xer_r_mask[63 - 32].eq(1) # XER.SO
 | 
			
		||||
        else:
 | 
			
		||||
            assert False
 | 
			
		||||
 | 
			
		||||
        with m.If(self.post.stb & ~self.pfv.intr):
 | 
			
		||||
            m.d.sync += Assert((self.pfv.xer.r_mask & spec_xer_r_mask) == spec_xer_r_mask)
 | 
			
		||||
 | 
			
		||||
        return m
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CompareCheck(PowerFVCheck, name="_insn_compare"):
 | 
			
		||||
    def __init_subclass__(cls, name, insn_cls):
 | 
			
		||||
        super().__init_subclass__(name)
 | 
			
		||||
        cls.insn_cls = insn_cls
 | 
			
		||||
 | 
			
		||||
    def get_testbench(self, dut, post):
 | 
			
		||||
        tb_spec = CompareSpec(self.insn_cls, post)
 | 
			
		||||
        tb_top  = tb.Testbench(tb_spec, dut)
 | 
			
		||||
        return tb_top
 | 
			
		||||
					Loading…
					
					
				
		Reference in New Issue