Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/nmigen
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 85ae99c1b479
Choose a base ref
...
head repository: m-labs/nmigen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: aed2062101af
Choose a head ref
  • 2 commits
  • 23 files changed
  • 1 contributor

Commits on Apr 21, 2019

  1. hdl.ir: detect elaboratables that are created but not used.

    Requres every elaboratable to inherit from Elaboratable, but still
    accepts ones that do not, with a warning.
    
    Fixes #3.
    whitequark committed Apr 21, 2019
    Copy the full SHA
    44711b7 View commit details
  2. Remove examples/tbuf.py.

    This example predates the plans for nmigen.build, and indeed
    get_tristate and TSTriple no longer exist.
    whitequark committed Apr 21, 2019
    Copy the full SHA
    aed2062 View commit details
2 changes: 1 addition & 1 deletion examples/alu.py
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
from nmigen.cli import main


class ALU:
class ALU(Elaboratable):
def __init__(self, width):
self.sel = Signal(2)
self.a = Signal(width)
6 changes: 3 additions & 3 deletions examples/alu_hier.py
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
from nmigen.cli import main


class Adder:
class Adder(Elaboratable):
def __init__(self, width):
self.a = Signal(width)
self.b = Signal(width)
@@ -14,7 +14,7 @@ def elaborate(self, platform):
return m


class Subtractor:
class Subtractor(Elaboratable):
def __init__(self, width):
self.a = Signal(width)
self.b = Signal(width)
@@ -26,7 +26,7 @@ def elaborate(self, platform):
return m


class ALU:
class ALU(Elaboratable):
def __init__(self, width):
self.op = Signal()
self.a = Signal(width)
2 changes: 1 addition & 1 deletion examples/arst.py
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
from nmigen.cli import main


class ClockDivisor:
class ClockDivisor(Elaboratable):
def __init__(self, factor):
self.v = Signal(factor)
self.o = Signal()
2 changes: 1 addition & 1 deletion examples/ctr.py
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
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()
2 changes: 1 addition & 1 deletion examples/ctr_ce.py
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
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()
2 changes: 1 addition & 1 deletion examples/fsm.py
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
from nmigen.cli import main


class UARTReceiver:
class UARTReceiver(Elaboratable):
def __init__(self, divisor):
self.divisor = divisor

2 changes: 1 addition & 1 deletion examples/gpio.py
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
from nmigen.cli import main


class GPIO:
class GPIO(Elaboratable):
def __init__(self, pins, bus):
self.pins = pins
self.bus = bus
2 changes: 1 addition & 1 deletion examples/inst.py
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
from nmigen.cli import main


class System:
class System(Elaboratable):
def __init__(self):
self.adr = Signal(16)
self.dat_r = Signal(8)
2 changes: 1 addition & 1 deletion examples/mem.py
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
from nmigen.cli import main


class RegisterFile:
class RegisterFile(Elaboratable):
def __init__(self):
self.adr = Signal(4)
self.dat_r = Signal(8)
2 changes: 1 addition & 1 deletion examples/pmux.py
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
from nmigen.cli import main


class ParMux:
class ParMux(Elaboratable):
def __init__(self, width):
self.s = Signal(3)
self.a = Signal(width)
12 changes: 0 additions & 12 deletions examples/tbuf.py

This file was deleted.

2 changes: 1 addition & 1 deletion nmigen/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
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
4 changes: 2 additions & 2 deletions nmigen/hdl/dsl.py
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@
from .xfrm import *


__all__ = ["Module", "SyntaxError", "SyntaxWarning"]
__all__ = ["SyntaxError", "SyntaxWarning", "Module"]


class SyntaxError(Exception):
@@ -109,7 +109,7 @@ def ongoing(self, name):
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)
45 changes: 36 additions & 9 deletions nmigen/hdl/ir.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,30 @@
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):
@@ -16,13 +34,22 @@ 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()
6 changes: 3 additions & 3 deletions nmigen/hdl/mem.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .. import tracer
from .ast import *
from .ir import Instance
from .ir import Elaboratable, Instance


__all__ = ["Memory", "ReadPort", "WritePort", "DummyPort"]
@@ -70,7 +70,7 @@ def __getitem__(self, index):
return self._array[index]


class ReadPort:
class ReadPort(Elaboratable):
def __init__(self, memory, domain, synchronous, transparent):
self.memory = memory
self.domain = domain
@@ -135,7 +135,7 @@ def elaborate(self, platform):
return f


class WritePort:
class WritePort(Elaboratable):
def __init__(self, memory, domain, priority, granularity):
self.memory = memory
self.domain = domain
2 changes: 1 addition & 1 deletion nmigen/hdl/xfrm.py
Original file line number Diff line number Diff line change
@@ -292,7 +292,7 @@ def __call__(self, value):
raise AttributeError("Object '{!r}' cannot be elaborated".format(value))


class TransformedElaboratable:
class TransformedElaboratable(Elaboratable):
def __init__(self, elaboratable):
assert hasattr(elaboratable, "elaborate")

4 changes: 2 additions & 2 deletions nmigen/lib/cdc.py
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@
__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
@@ -69,7 +69,7 @@ def elaborate(self, platform):
return m


class ResetSynchronizer:
class ResetSynchronizer(Elaboratable):
def __init__(self, arst, domain="sync", n=2):
self.arst = arst
self.domain = domain
10 changes: 5 additions & 5 deletions nmigen/lib/coding.py
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@
]


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.
@@ -48,7 +48,7 @@ def elaborate(self, platform):
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
@@ -85,7 +85,7 @@ def elaborate(self, platform):
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.
@@ -130,7 +130,7 @@ class PriorityDecoder(Decoder):
"""


class GrayEncoder:
class GrayEncoder(Elaboratable):
"""Encode binary to Gray code.
Parameters
@@ -157,7 +157,7 @@ def elaborate(self, platform):
return m


class GrayDecoder:
class GrayDecoder(Elaboratable):
"""Decode Gray code to binary.
Parameters
8 changes: 4 additions & 4 deletions nmigen/lib/fifo.py
Original file line number Diff line number Diff line change
@@ -102,7 +102,7 @@ def _decr(signal, modulo):
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.
@@ -209,7 +209,7 @@ def elaborate(self, platform):
return m


class SyncFIFOBuffered(FIFOInterface):
class SyncFIFOBuffered(Elaboratable, FIFOInterface):
__doc__ = FIFOInterface._doc_template.format(
description="""
Buffered synchronous first in, first out queue.
@@ -265,7 +265,7 @@ def elaborate(self, platform):
return m


class AsyncFIFO(FIFOInterface):
class AsyncFIFO(Elaboratable, FIFOInterface):
__doc__ = FIFOInterface._doc_template.format(
description="""
Asynchronous first in, first out queue.
@@ -361,7 +361,7 @@ def elaborate(self, platform):
return m


class AsyncFIFOBuffered(FIFOInterface):
class AsyncFIFOBuffered(Elaboratable, FIFOInterface):
__doc__ = FIFOInterface._doc_template.format(
description="""
Buffered asynchronous first in, first out queue.
6 changes: 6 additions & 0 deletions nmigen/test/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
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__
2 changes: 1 addition & 1 deletion nmigen/test/test_hdl_xfrm.py
Original file line number Diff line number Diff line change
@@ -488,7 +488,7 @@ def test_ce_subfragment(self):
""")


class _MockElaboratable:
class _MockElaboratable(Elaboratable):
def __init__(self):
self.s1 = Signal()

5 changes: 3 additions & 2 deletions nmigen/test/test_lib_coding.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from .tools import *
from ..hdl.ast import *
from ..hdl.dsl import *
from ..hdl.ir import *
from ..back.pysim import *
from ..lib.coding import *

@@ -82,7 +83,7 @@ def process():
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
@@ -99,7 +100,7 @@ def elaborate(self, platform):
return m


class HammingDistanceSpec:
class HammingDistanceSpec(Elaboratable):
def __init__(self, distance, encoder_cls, args):
self.distance = distance
self.encoder_cls = encoder_cls
Loading