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