The `ports` argument to the `convert` functions is a frequent hotspot of
beginner issues. Check to make sure it is either a list or a tuple, and
give an appropriately helpful error message if not.
Fixes#362.
Since commit 7257c20a, platform code calls create_missing_domains()
before _propagate_domains_up() (as a part of prepare() call). Since
commit a7be3b48, without a platform, create_missing_domains() is
calle after _propagate_domains_up(); because of that, it adds
the missing domain to the fragment. When platform code then calls
prepare() again, this causes an assertion failure.
The true intent behind the platform code being written this way is
that it *overrides* a part of prepare()'s mechanism. Because it was
not changed when prepare() was modified in 7257c20a, the override,
which happened to work by coincidence, stopped working. This is
now fixed by inlining the relevant parts of Fragment.prepare() into
Platform.prepare().
This is not a great solution, but given the amount of breakage this
causes (no platform-using code works), it is acceptable for now.
Fixes#307.
A property statement that is created but not added to a module is
virtually always a serious bug, since it can make formal verification
pass when it should not. Therefore, add a warning to it, similar to
UnusedElaboratable.
Doing this to all statements is possible, but many temporary ones are
created internally by nMigen, and the extensive changes required to
remove false positives are likely not worth the true positives.
We can revisit this in the future.
Fixes#303.
Otherwise, two subfragments with the same local clock domain would
not be able to drive its clock or reset signals. This can be easily
hit if using two ResetSynchronizers in one module.
Fixes#265.
This warning is usually quite handy, but is problematic in tests:
although it can be suppressed by using Fragment.get on elaboratable,
that is not always possible, in particular when writing tests for
exceptions raised by __init__, e.g.:
def test_wrong_csr_bus(self):
with self.assertRaisesRegex(ValueError, r"blah blah"):
WishboneCSRBridge(csr_bus=object())
In theory, it should be possible to suppress warnings per-module
and even per-line using code such as:
import re, warnings
from nmigen.hdl.ir import UnusedElaboratable
warnings.filterwarnings("ignore", category=UnusedElaboratable,
module=re.escape(__name__))
Unfortunately, not only is this code quite convoluted, but it also
does not actually work; we are using warnings.warn_explicit() because
we collect source locations on our own, but it requires the caller
to extract the __warningregistry__ dictionary from module globals,
or warning suppression would not work. Not only is this not feasible
in most diagnostic sites in nMigen, but also I never got it to work
anyway, even when passing all of module, registry, and module_globals
to warn_explicit().
Instead, use a magic comment at the start of a file to do this job,
which might not be elegant but is simple and practical. For now,
only UnusedElaboratable can be suppressed with it, but in future,
other linter parameters may become tweakable this way.
This can cause confusion:
* If the erroneous object is None, it is printed as 'None', which
appears as a string (and could be the result of converting None
to a string.)
* If the erroneous object is a string, it is printed as ''<val>'',
which is a rather strange combination of quotes.
Platform.prepare() was completely broken after addition of local
clock domains, and only really worked before by a series of
accidents because there was a circular dependency between creation
of missing domains, fragment preparation, and insertion of pin
subfragments.
This commit untangles the dependency by adding a separate public
method Fragment.create_missing_domains(), used in build.plat.
It also makes DomainCollector consider both used and defined domains,
such that it will work on fragments before domain propagation, since
create_missing_domains() can be called by user code before prepare().
The fragment driving missing clock domain is not flattened anymore,
because flattening does not work well combined with local domains.
The elaboratable is already likely driving the clk/rst signals in
some way appropriate for the platform; if we expose them as ports
nevertheless it will cause problems downstream.
Before this commit, it was a print statement, and therefore, command
interpreter options like -Wignore did not affect it. There is no API
to access the warning filter list, so it was turned into a real
warning; and further, since Python 3.6, tracemalloc can be used
as a standard method to display traceback to allocation site instead
of the ad-hoc traceback logic that was used in Elaboratable before.
The main purpose of this rework is cleanup, to avoid specifying
the direction of input ports in an implicit, ad-hoc way using
the named ports and ports dictionaries.
While working on this I realized that output ports can be connected
to anything that is valid on LHS, so this is now supported too.