from nmigen.cli import main
-class ALU:
+class ALU(Elaboratable):
def __init__(self, width):
self.sel = Signal(2)
self.a = Signal(width)
from nmigen.cli import main
-class Adder:
+class Adder(Elaboratable):
def __init__(self, width):
self.a = Signal(width)
self.b = Signal(width)
return m
-class Subtractor:
+class Subtractor(Elaboratable):
def __init__(self, width):
self.a = Signal(width)
self.b = Signal(width)
return m
-class ALU:
+class ALU(Elaboratable):
def __init__(self, width):
self.op = Signal()
self.a = Signal(width)
from nmigen.cli import main
-class ClockDivisor:
+class ClockDivisor(Elaboratable):
def __init__(self, factor):
self.v = Signal(factor)
self.o = Signal()
from nmigen.cli import main, pysim
-class Counter:
+class Counter(Elaboratable):
def __init__(self, width):
self.v = Signal(width, reset=2**width-1)
self.o = Signal()
from nmigen.back import rtlil, verilog, pysim
-class Counter:
+class Counter(Elaboratable):
def __init__(self, width):
self.v = Signal(width, reset=2**width-1)
self.o = Signal()
from nmigen.cli import main
-class UARTReceiver:
+class UARTReceiver(Elaboratable):
def __init__(self, divisor):
self.divisor = divisor
from nmigen.cli import main
-class GPIO:
+class GPIO(Elaboratable):
def __init__(self, pins, bus):
self.pins = pins
self.bus = bus
from nmigen.cli import main
-class System:
+class System(Elaboratable):
def __init__(self):
self.adr = Signal(16)
self.dat_r = Signal(8)
from nmigen.cli import main
-class RegisterFile:
+class RegisterFile(Elaboratable):
def __init__(self):
self.adr = Signal(4)
self.dat_r = Signal(8)
from nmigen.cli import main
-class ParMux:
+class ParMux(Elaboratable):
def __init__(self, width):
self.s = Signal(3)
self.a = Signal(width)
from .hdl.ast import Value, Const, C, Mux, Cat, Repl, Array, Signal, ClockSignal, ResetSignal
from .hdl.dsl import Module
from .hdl.cd import ClockDomain
-from .hdl.ir import Fragment, Instance
+from .hdl.ir import Elaboratable, Fragment, Instance
from .hdl.mem import Memory
from .hdl.rec import Record
from .hdl.xfrm import ResetInserter, CEInserter
from .xfrm import *
-__all__ = ["Module", "SyntaxError", "SyntaxWarning"]
+__all__ = ["SyntaxError", "SyntaxWarning", "Module"]
class SyntaxError(Exception):
return self.state == self.encoding[name]
-class Module(_ModuleBuilderRoot):
+class Module(_ModuleBuilderRoot, Elaboratable):
def __init__(self):
_ModuleBuilderRoot.__init__(self, self, depth=0)
self.submodules = _ModuleBuilderSubmodules(self)
-import warnings
+from abc import ABCMeta, abstractmethod
from collections import defaultdict, OrderedDict
+import warnings
+import traceback
+import sys
from ..tools import *
from .ast import *
from .cd import *
-__all__ = ["Fragment", "Instance", "DriverConflict"]
+__all__ = ["Elaboratable", "DriverConflict", "Fragment", "Instance"]
+
+
+class Elaboratable(metaclass=ABCMeta):
+ def __new__(cls, *args, **kwargs):
+ self = super().__new__(cls)
+ self._Elaboratable__traceback = traceback.extract_stack()[:-1]
+ self._Elaboratable__used = False
+ return self
+
+ def __del__(self):
+ if hasattr(self, "_Elaboratable__used") and not self._Elaboratable__used:
+ print("Elaboratable created but never used\n",
+ "Traceback (most recent call last):\n",
+ *traceback.format_list(self._Elaboratable__traceback),
+ file=sys.stderr, sep="")
class DriverConflict(UserWarning):
class Fragment:
@staticmethod
def get(obj, platform):
- if isinstance(obj, Fragment):
- return obj
- elif hasattr(obj, "elaborate"):
- frag = obj.elaborate(platform)
- else:
- raise AttributeError("Object '{!r}' cannot be elaborated".format(obj))
- return Fragment.get(frag, platform)
+ while True:
+ if isinstance(obj, Fragment):
+ return obj
+ elif isinstance(obj, Elaboratable):
+ obj._Elaboratable__used = True
+ obj = obj.elaborate(platform)
+ elif hasattr(obj, "elaborate"):
+ warnings.warn(
+ message="Class {!r} is an elaboratable that does not explicitly inherit from "
+ "Elaboratable; doing so would improve diagnostics"
+ .format(type(obj)),
+ category=RuntimeWarning,
+ stacklevel=2)
+ obj = obj.elaborate(platform)
+ else:
+ raise AttributeError("Object '{!r}' cannot be elaborated".format(obj))
def __init__(self):
self.ports = SignalDict()
from .. import tracer
from .ast import *
-from .ir import Instance
+from .ir import Elaboratable, Instance
__all__ = ["Memory", "ReadPort", "WritePort", "DummyPort"]
return self._array[index]
-class ReadPort:
+class ReadPort(Elaboratable):
def __init__(self, memory, domain, synchronous, transparent):
self.memory = memory
self.domain = domain
return f
-class WritePort:
+class WritePort(Elaboratable):
def __init__(self, memory, domain, priority, granularity):
self.memory = memory
self.domain = domain
raise AttributeError("Object '{!r}' cannot be elaborated".format(value))
-class TransformedElaboratable:
+class TransformedElaboratable(Elaboratable):
def __init__(self, elaboratable):
assert hasattr(elaboratable, "elaborate")
__all__ = ["MultiReg", "ResetSynchronizer"]
-class MultiReg:
+class MultiReg(Elaboratable):
"""Resynchronise a signal to a different clock domain.
Consists of a chain of flip-flops. Eliminates metastabilities at the output, but provides
return m
-class ResetSynchronizer:
+class ResetSynchronizer(Elaboratable):
def __init__(self, arst, domain="sync", n=2):
self.arst = arst
self.domain = domain
]
-class Encoder:
+class Encoder(Elaboratable):
"""Encode one-hot to binary.
If one bit in ``i`` is asserted, ``n`` is low and ``o`` indicates the asserted bit.
return m
-class PriorityEncoder:
+class PriorityEncoder(Elaboratable):
"""Priority encode requests to binary.
If any bit in ``i`` is asserted, ``n`` is low and ``o`` indicates the least significant
return m
-class Decoder:
+class Decoder(Elaboratable):
"""Decode binary to one-hot.
If ``n`` is low, only the ``i``th bit in ``o`` is asserted.
"""
-class GrayEncoder:
+class GrayEncoder(Elaboratable):
"""Encode binary to Gray code.
Parameters
return m
-class GrayDecoder:
+class GrayDecoder(Elaboratable):
"""Decode Gray code to binary.
Parameters
return Mux(signal == 0, modulo - 1, signal - 1)
-class SyncFIFO(FIFOInterface):
+class SyncFIFO(Elaboratable, FIFOInterface):
__doc__ = FIFOInterface._doc_template.format(
description="""
Synchronous first in, first out queue.
return m
-class SyncFIFOBuffered(FIFOInterface):
+class SyncFIFOBuffered(Elaboratable, FIFOInterface):
__doc__ = FIFOInterface._doc_template.format(
description="""
Buffered synchronous first in, first out queue.
return m
-class AsyncFIFO(FIFOInterface):
+class AsyncFIFO(Elaboratable, FIFOInterface):
__doc__ = FIFOInterface._doc_template.format(
description="""
Asynchronous first in, first out queue.
return m
-class AsyncFIFOBuffered(FIFOInterface):
+class AsyncFIFOBuffered(Elaboratable, FIFOInterface):
__doc__ = FIFOInterface._doc_template.format(
description="""
Buffered asynchronous first in, first out queue.
+from ..hdl.ir import Elaboratable
+
+
+# The nMigen testsuite creates a lot of elaboratables that are intentionally unused.
+# Disable the unused elaboratable check, as in our case it provides nothing but noise.
+del Elaboratable.__del__
""")
-class _MockElaboratable:
+class _MockElaboratable(Elaboratable):
def __init__(self):
self.s1 = Signal()
from .tools import *
from ..hdl.ast import *
from ..hdl.dsl import *
+from ..hdl.ir import *
from ..back.pysim import *
from ..lib.coding import *
sim.run()
-class ReversibleSpec:
+class ReversibleSpec(Elaboratable):
def __init__(self, encoder_cls, decoder_cls, args):
self.encoder_cls = encoder_cls
self.decoder_cls = decoder_cls
return m
-class HammingDistanceSpec:
+class HammingDistanceSpec(Elaboratable):
def __init__(self, distance, encoder_cls, args):
self.distance = distance
self.encoder_cls = encoder_cls
self.assertAsyncFIFOWorks(AsyncFIFOBuffered(width=8, depth=3))
-class FIFOModel(FIFOInterface):
+class FIFOModel(Elaboratable, FIFOInterface):
"""
Non-synthesizable first-in first-out queue, implemented naively as a chain of registers.
"""
return m
-class FIFOModelEquivalenceSpec:
+class FIFOModelEquivalenceSpec(Elaboratable):
"""
The first-in first-out queue model equivalence specification: for any inputs and control
signals, the behavior of the implementation under test exactly matches the ideal model,
return m
-class FIFOContractSpec:
+class FIFOContractSpec(Elaboratable):
"""
The first-in first-out queue contract specification: if two elements are written to the queue
consecutively, they must be read out consecutively at some later point, no matter all other