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.
74 lines
2.4 KiB
Python
74 lines
2.4 KiB
Python
2 years ago
|
from abc import ABCMeta, abstractmethod
|
||
|
from pathlib import Path
|
||
|
|
||
|
from power_fv.build import sby
|
||
|
|
||
|
|
||
|
__all__ = ["PowerFVCheck"]
|
||
|
|
||
|
|
||
|
class PowerFVCheckMeta(ABCMeta):
|
||
|
all_checks = {}
|
||
|
|
||
|
def __new__(metacls, clsname, bases, namespace, name=None, **kwargs):
|
||
|
if name is not None:
|
||
|
if name in metacls.all_checks:
|
||
|
raise NameError("Check {!r} already exists".format(name))
|
||
|
namespace["name"] = name
|
||
|
|
||
|
cls = ABCMeta.__new__(metacls, clsname, bases, namespace, **kwargs)
|
||
|
if name is not None:
|
||
|
metacls.all_checks[name] = cls
|
||
|
cls.name = name
|
||
|
return cls
|
||
|
|
||
|
@classmethod
|
||
|
def find(cls, *name):
|
||
|
for check_name, check_cls in cls.all_checks.items():
|
||
|
assert isinstance(check_name, tuple)
|
||
|
if len(name) > len(check_name):
|
||
|
continue
|
||
|
if name == check_name[:len(name)]:
|
||
|
yield check_name, check_cls
|
||
|
|
||
|
|
||
|
class PowerFVCheck(metaclass=PowerFVCheckMeta):
|
||
|
@classmethod
|
||
|
def add_check_arguments(cls, parser):
|
||
|
parser.add_argument(
|
||
|
"name", metavar="NAME", type=str, help="name of the check")
|
||
|
parser.add_argument(
|
||
|
"--depth", type=int, default=15,
|
||
|
help="depth of the BMC, in clock cycles (default: %(default)s)")
|
||
|
parser.add_argument(
|
||
|
"--skip", type=int, default=None,
|
||
|
help="skip the specified number of clock cycles (default: DEPTH-1))")
|
||
|
|
||
|
@classmethod
|
||
|
def add_build_arguments(cls, parser):
|
||
|
parser.add_argument(
|
||
|
"--build-dir", type=Path, default=Path("./build"),
|
||
|
help="output directory (default: %(default)s)")
|
||
|
|
||
|
def __init__(self, *, depth, skip, core, **kwargs):
|
||
|
self.depth = depth
|
||
|
self.skip = skip if skip is not None else depth - 1
|
||
|
self.core = core
|
||
|
self.dut = core.wrapper(**kwargs)
|
||
|
|
||
|
@abstractmethod
|
||
|
def testbench(self):
|
||
|
raise NotImplementedError
|
||
|
|
||
|
def build(self, *, build_dir, **kwargs):
|
||
|
platform = sby.SymbiYosysPlatform()
|
||
|
self.core.add_files(platform, self.dut, **kwargs)
|
||
|
|
||
|
top = self.testbench()
|
||
|
build_dir = build_dir / top.name
|
||
|
overrides = {key: str(value) for key, value in kwargs.items()}
|
||
|
overrides["depth"] = str(self.depth)
|
||
|
overrides["skip"] = str(self.skip)
|
||
|
|
||
|
return platform.build(top, name=top.name, build_dir=build_dir, **overrides)
|