Refactor to facilitate integration with CLIs and config files.
* Checks are now split in two modules: checks.cons for consistency checks, checks.insn for instructions. * Checks are derived from PowerFVCheck and have a shorthand (e.g. "insn_b"). PowerFVCheck holds a mapping between its subclasses and their shorthands. * Instruction checks definitions have been simplified to one-liners, and grouped into a single file. * A Trigger class has been added to define testbench triggers.main
							parent
							
								
									5c097b9474
								
							
						
					
					
						commit
						9ea58a47a9
					
				@ -1,5 +1,12 @@
 | 
			
		||||
from .cr     import *
 | 
			
		||||
from .gpr    import *
 | 
			
		||||
from .ia_fwd import *
 | 
			
		||||
from .spr    import *
 | 
			
		||||
from .unique import *
 | 
			
		||||
class PowerFVCheck:
 | 
			
		||||
    registry = {}
 | 
			
		||||
    name     = None
 | 
			
		||||
 | 
			
		||||
    def __init_subclass__(cls, name):
 | 
			
		||||
        if name in cls.registry:
 | 
			
		||||
            raise ValueError("Check name {!r} is already registered".format(name))
 | 
			
		||||
        cls.registry[name] = cls
 | 
			
		||||
        cls.name = name
 | 
			
		||||
 | 
			
		||||
    def get_testbench(self, dut, *args, **kwargs):
 | 
			
		||||
        raise NotImplementedError
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,2 @@
 | 
			
		||||
from .cons.all import *
 | 
			
		||||
from .insn.all import *
 | 
			
		||||
@ -0,0 +1,5 @@
 | 
			
		||||
from .unique import *
 | 
			
		||||
from .ia_fwd import *
 | 
			
		||||
from .gpr    import *
 | 
			
		||||
from .cr     import *
 | 
			
		||||
from .spr    import *
 | 
			
		||||
@ -0,0 +1,49 @@
 | 
			
		||||
from amaranth import *
 | 
			
		||||
from amaranth.asserts import *
 | 
			
		||||
 | 
			
		||||
from .. import PowerFVCheck
 | 
			
		||||
from ... import pfv, tb
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ["UniquenessSpec", "UniquenessCheck"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UniquenessSpec(Elaboratable):
 | 
			
		||||
    """Uniqueness specification.
 | 
			
		||||
 | 
			
		||||
    A core cannot retire two instructions that share the same `pfv.order` identifier.
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, pre, post):
 | 
			
		||||
        self.pfv  = pfv.Interface()
 | 
			
		||||
        self.pre  = tb.Trigger(cycle=pre)
 | 
			
		||||
        self.post = tb.Trigger(cycle=post)
 | 
			
		||||
 | 
			
		||||
    def triggers(self):
 | 
			
		||||
        yield from (self.pre, self.post)
 | 
			
		||||
 | 
			
		||||
    def elaborate(self, platform):
 | 
			
		||||
        m = Module()
 | 
			
		||||
 | 
			
		||||
        spec_order = AnyConst(self.pfv.order.shape())
 | 
			
		||||
        duplicate  = Signal()
 | 
			
		||||
 | 
			
		||||
        with m.If(self.pre.stb):
 | 
			
		||||
            m.d.sync += [
 | 
			
		||||
                Assume(self.pfv.stb),
 | 
			
		||||
                Assume(spec_order == self.pfv.order),
 | 
			
		||||
                Assume(~duplicate),
 | 
			
		||||
            ]
 | 
			
		||||
        with m.Elif(self.pfv.stb & (self.pfv.order == spec_order)):
 | 
			
		||||
            m.d.sync += duplicate.eq(1)
 | 
			
		||||
 | 
			
		||||
        with m.If(self.post.stb):
 | 
			
		||||
            m.d.sync += Assert(~duplicate)
 | 
			
		||||
 | 
			
		||||
        return m
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UniquenessCheck(PowerFVCheck, name="cons_unique"):
 | 
			
		||||
    def get_testbench(self, dut, pre, post):
 | 
			
		||||
        tb_spec = UniquenessSpec(pre, post)
 | 
			
		||||
        tb_top  = tb.Testbench(tb_spec, dut)
 | 
			
		||||
        return tb_top
 | 
			
		||||
@ -0,0 +1,20 @@
 | 
			
		||||
from . import _fmt
 | 
			
		||||
 | 
			
		||||
# Branches
 | 
			
		||||
 | 
			
		||||
class B      (_fmt.Instruction_I, po=18, aa=0, lk=0): pass
 | 
			
		||||
class BA     (_fmt.Instruction_I, po=18, aa=1, lk=0): pass
 | 
			
		||||
class BL     (_fmt.Instruction_I, po=18, aa=0, lk=1): pass
 | 
			
		||||
class BLA    (_fmt.Instruction_I, po=18, aa=1, lk=1): pass
 | 
			
		||||
 | 
			
		||||
class BC     (_fmt.Instruction_B, po=16, aa=0, lk=0): pass
 | 
			
		||||
class BCA    (_fmt.Instruction_B, po=16, aa=1, lk=0): pass
 | 
			
		||||
class BCL    (_fmt.Instruction_B, po=16, aa=0, lk=1): pass
 | 
			
		||||
class BCLA   (_fmt.Instruction_B, po=16, aa=1, lk=1): pass
 | 
			
		||||
 | 
			
		||||
class BCLR   (_fmt.Instruction_XL_bc, po=19, xo= 16, lk=0): pass
 | 
			
		||||
class BCLRL  (_fmt.Instruction_XL_bc, po=19, xo= 16, lk=1): pass
 | 
			
		||||
class BCCTR  (_fmt.Instruction_XL_bc, po=19, xo=528, lk=0): pass
 | 
			
		||||
class BCCTRL (_fmt.Instruction_XL_bc, po=19, xo=528, lk=1): pass
 | 
			
		||||
class BCTAR  (_fmt.Instruction_XL_bc, po=19, xo=560, lk=0): pass
 | 
			
		||||
class BCTARL (_fmt.Instruction_XL_bc, po=19, xo=560, lk=1): pass
 | 
			
		||||
@ -0,0 +1,21 @@
 | 
			
		||||
from . import _insn
 | 
			
		||||
from ._branch import BranchCheck
 | 
			
		||||
 | 
			
		||||
# Branches
 | 
			
		||||
 | 
			
		||||
class B      (BranchCheck, name="insn_b",      insn_cls=_insn.B,    ): pass
 | 
			
		||||
class BA     (BranchCheck, name="insn_ba",     insn_cls=_insn.BA    ): pass
 | 
			
		||||
class BL     (BranchCheck, name="insn_bl",     insn_cls=_insn.BL    ): pass
 | 
			
		||||
class BLA    (BranchCheck, name="insn_bla",    insn_cls=_insn.BLA   ): pass
 | 
			
		||||
 | 
			
		||||
class BC     (BranchCheck, name="insn_bc",     insn_cls=_insn.BC    ): pass
 | 
			
		||||
class BCA    (BranchCheck, name="insn_bca",    insn_cls=_insn.BCA   ): pass
 | 
			
		||||
class BCL    (BranchCheck, name="insn_bcl",    insn_cls=_insn.BCL   ): pass
 | 
			
		||||
class BCLA   (BranchCheck, name="insn_bcla",   insn_cls=_insn.BCLA  ): pass
 | 
			
		||||
 | 
			
		||||
class BCLR   (BranchCheck, name="insn_bclr",   insn_cls=_insn.BCLR  ): pass
 | 
			
		||||
class BCLRL  (BranchCheck, name="insn_bclrl",  insn_cls=_insn.BCLRL ): pass
 | 
			
		||||
class BCCTR  (BranchCheck, name="insn_bcctr",  insn_cls=_insn.BCCTR ): pass
 | 
			
		||||
class BCCTRL (BranchCheck, name="insn_bcctrl", insn_cls=_insn.BCCTRL): pass
 | 
			
		||||
class BCTAR  (BranchCheck, name="insn_bctar",  insn_cls=_insn.BCTAR ): pass
 | 
			
		||||
class BCTARL (BranchCheck, name="insn_bctarl", insn_cls=_insn.BCTARL): pass
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
from . import _branch
 | 
			
		||||
from .. import insn
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ["Check"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Check(_branch.Check, insn_cls=insn.B):
 | 
			
		||||
    pass
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
from . import _branch
 | 
			
		||||
from .. import insn
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ["Check"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Check(_branch.Check, insn_cls=insn.BA):
 | 
			
		||||
    pass
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
from . import _branch
 | 
			
		||||
from .. import insn
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ["Check"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Check(_branch.Check, insn_cls=insn.BC):
 | 
			
		||||
    pass
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
from . import _branch
 | 
			
		||||
from .. import insn
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ["Check"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Check(_branch.Check, insn_cls=insn.BCA):
 | 
			
		||||
    pass
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
from . import _branch
 | 
			
		||||
from .. import insn
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ["Check"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Check(_branch.Check, insn_cls=insn.BCCTR):
 | 
			
		||||
    pass
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
from . import _branch
 | 
			
		||||
from .. import insn
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ["Check"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Check(_branch.Check, insn_cls=insn.BCCTRL):
 | 
			
		||||
    pass
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
from . import _branch
 | 
			
		||||
from .. import insn
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ["Check"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Check(_branch.Check, insn_cls=insn.BCL):
 | 
			
		||||
    pass
 | 
			
		||||
@ -1,10 +0,0 @@
 | 
			
		||||
from . import _branch
 | 
			
		||||
 | 
			
		||||
from .. import insn
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ["Check"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Check(_branch.Check, insn_cls=insn.BCLA):
 | 
			
		||||
    pass
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
from . import _branch
 | 
			
		||||
from .. import insn
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ["Check"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Check(_branch.Check, insn_cls=insn.BCLR):
 | 
			
		||||
    pass
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
from . import _branch
 | 
			
		||||
from .. import insn
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ["Check"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Check(_branch.Check, insn_cls=insn.BCLRL):
 | 
			
		||||
    pass
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
from . import _branch
 | 
			
		||||
from .. import insn
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ["Check"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Check(_branch.Check, insn_cls=insn.BCTAR):
 | 
			
		||||
    pass
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
from . import _branch
 | 
			
		||||
from .. import insn
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ["Check"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Check(_branch.Check, insn_cls=insn.BCTARL):
 | 
			
		||||
    pass
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
from . import _branch
 | 
			
		||||
from .. import insn
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ["Check"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Check(_branch.Check, insn_cls=insn.BL):
 | 
			
		||||
    pass
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
from . import _branch
 | 
			
		||||
from .. import insn
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ["Check"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Check(_branch.Check, insn_cls=insn.BLA):
 | 
			
		||||
    pass
 | 
			
		||||
@ -1,40 +0,0 @@
 | 
			
		||||
from amaranth import *
 | 
			
		||||
from amaranth.asserts import *
 | 
			
		||||
 | 
			
		||||
from .. import pfv
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ["Check"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Check(Elaboratable):
 | 
			
		||||
    """Uniqueness check.
 | 
			
		||||
 | 
			
		||||
    Check that the core cannot retire two instructions with the same `pfv.order` identifier.
 | 
			
		||||
    """
 | 
			
		||||
    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.shape())
 | 
			
		||||
        duplicate  = Signal()
 | 
			
		||||
 | 
			
		||||
        with m.If(self.trig.pre):
 | 
			
		||||
            m.d.sync += [
 | 
			
		||||
                Assume(self.pfv.stb),
 | 
			
		||||
                Assume(spec_order == self.pfv.order),
 | 
			
		||||
                Assume(~duplicate),
 | 
			
		||||
            ]
 | 
			
		||||
        with m.Elif(self.pfv.stb & (self.pfv.order == spec_order)):
 | 
			
		||||
            m.d.sync += duplicate.eq(1)
 | 
			
		||||
 | 
			
		||||
        with m.If(self.trig.post):
 | 
			
		||||
            m.d.sync += Assert(~duplicate)
 | 
			
		||||
 | 
			
		||||
        return m
 | 
			
		||||
					Loading…
					
					
				
		Reference in New Issue