_unused: extract must-use logic from hdl.ir.
This commit is contained in:
parent
687d3a3df7
commit
9fb4a4f09e
45
nmigen/_unused.py
Normal file
45
nmigen/_unused.py
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import sys
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
from ._utils import get_linter_option
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ["UnusedMustUse", "MustUse"]
|
||||||
|
|
||||||
|
|
||||||
|
class UnusedMustUse(Warning):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MustUse:
|
||||||
|
_MustUse__silence = False
|
||||||
|
_MustUse__warning = UnusedMustUse
|
||||||
|
|
||||||
|
def __new__(cls, *args, src_loc_at=0, **kwargs):
|
||||||
|
frame = sys._getframe(1 + src_loc_at)
|
||||||
|
self = super().__new__(cls)
|
||||||
|
self._MustUse__used = False
|
||||||
|
self._MustUse__context = dict(
|
||||||
|
filename=frame.f_code.co_filename,
|
||||||
|
lineno=frame.f_lineno,
|
||||||
|
source=self)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
if self._MustUse__silence:
|
||||||
|
return
|
||||||
|
if hasattr(self, "_MustUse__used") and not self._MustUse__used:
|
||||||
|
if get_linter_option(self._MustUse__context["filename"],
|
||||||
|
self._MustUse__warning.__name__, bool, True):
|
||||||
|
warnings.warn_explicit(
|
||||||
|
"{!r} created but never used".format(self), self._MustUse__warning,
|
||||||
|
**self._MustUse__context)
|
||||||
|
|
||||||
|
|
||||||
|
_old_excepthook = sys.excepthook
|
||||||
|
def _silence_elaboratable(type, value, traceback):
|
||||||
|
# Don't show anything if the interpreter crashed; that'd just obscure the exception
|
||||||
|
# traceback instead of helping.
|
||||||
|
MustUse._MustUse__silence = True
|
||||||
|
_old_excepthook(type, value, traceback)
|
||||||
|
sys.excepthook = _silence_elaboratable
|
|
@ -95,7 +95,7 @@ class _CompatModuleClockDomains(_CompatModuleProxy):
|
||||||
|
|
||||||
|
|
||||||
class CompatModule(ir.Elaboratable):
|
class CompatModule(ir.Elaboratable):
|
||||||
_Elaboratable__silence = True
|
_MustUse__silence = True
|
||||||
|
|
||||||
# Actually returns another nMigen Elaboratable (nmigen.dsl.Module), not a Fragment.
|
# Actually returns another nMigen Elaboratable (nmigen.dsl.Module), not a Fragment.
|
||||||
def get_fragment(self):
|
def get_fragment(self):
|
||||||
|
|
|
@ -6,6 +6,7 @@ import traceback
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from .._utils import *
|
from .._utils import *
|
||||||
|
from .._unused import *
|
||||||
from .ast import *
|
from .ast import *
|
||||||
from .cd import *
|
from .cd import *
|
||||||
|
|
||||||
|
@ -13,41 +14,12 @@ from .cd import *
|
||||||
__all__ = ["UnusedElaboratable", "Elaboratable", "DriverConflict", "Fragment", "Instance"]
|
__all__ = ["UnusedElaboratable", "Elaboratable", "DriverConflict", "Fragment", "Instance"]
|
||||||
|
|
||||||
|
|
||||||
class UnusedElaboratable(Warning):
|
class UnusedElaboratable(UnusedMustUse):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Elaboratable(metaclass=ABCMeta):
|
class Elaboratable(MustUse, metaclass=ABCMeta):
|
||||||
_Elaboratable__silence = False
|
_MustUse__warning = UnusedElaboratable
|
||||||
|
|
||||||
def __new__(cls, *args, src_loc_at=0, **kwargs):
|
|
||||||
frame = sys._getframe(1 + src_loc_at)
|
|
||||||
self = super().__new__(cls)
|
|
||||||
self._Elaboratable__used = False
|
|
||||||
self._Elaboratable__context = dict(
|
|
||||||
filename=frame.f_code.co_filename,
|
|
||||||
lineno=frame.f_lineno,
|
|
||||||
source=self)
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
if self._Elaboratable__silence:
|
|
||||||
return
|
|
||||||
if hasattr(self, "_Elaboratable__used") and not self._Elaboratable__used:
|
|
||||||
if get_linter_option(self._Elaboratable__context["filename"],
|
|
||||||
"UnusedElaboratable", bool, True):
|
|
||||||
warnings.warn_explicit(
|
|
||||||
"{!r} created but never used".format(self), UnusedElaboratable,
|
|
||||||
**self._Elaboratable__context)
|
|
||||||
|
|
||||||
|
|
||||||
_old_excepthook = sys.excepthook
|
|
||||||
def _silence_elaboratable(type, value, traceback):
|
|
||||||
# Don't show anything if the interpreter crashed; that'd just obscure the exception
|
|
||||||
# traceback instead of helping.
|
|
||||||
Elaboratable._Elaboratable__silence = True
|
|
||||||
_old_excepthook(type, value, traceback)
|
|
||||||
sys.excepthook = _silence_elaboratable
|
|
||||||
|
|
||||||
|
|
||||||
class DriverConflict(UserWarning):
|
class DriverConflict(UserWarning):
|
||||||
|
@ -63,7 +35,7 @@ class Fragment:
|
||||||
return obj
|
return obj
|
||||||
elif isinstance(obj, Elaboratable):
|
elif isinstance(obj, Elaboratable):
|
||||||
code = obj.elaborate.__code__
|
code = obj.elaborate.__code__
|
||||||
obj._Elaboratable__used = True
|
obj._MustUse__used = True
|
||||||
obj = obj.elaborate(platform)
|
obj = obj.elaborate(platform)
|
||||||
elif hasattr(obj, "elaborate"):
|
elif hasattr(obj, "elaborate"):
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
|
|
Loading…
Reference in a new issue