Commit graph

270 commits

Author SHA1 Message Date
whitequark a295e3599c hdl.ast: update documentation for Signal.
Fixes #288.
2020-02-01 23:15:18 +00:00
whitequark 49758a3a0c hdl.ast: prohibit shifts by signed value.
These are not desirable in a HDL, and currently elaborate to broken
RTLIL (after YosysHQ/yosys#1551); prohibit them completely, like
we already do for division and modulo.

Fixes #302.
2020-02-01 23:04:25 +00:00
whitequark cce6b8687b build.plat: align pipeline with Fragment.prepare().
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.
2020-02-01 03:26:04 +00:00
whitequark 6fd7cbad0d hdl.dsl: don't allow inheriting from Module.
`Module` is an object with a lot of complex and sometimes fragile
behavior that overrides Python attribute accessors and so on.
To prevent user designs from breaking when it is changed, it is not
supposed to be inherited from (unlike in Migen), but rather returned
from the elaborate() method. This commit makes sure it will not be
inherited from by accident (most likely by users familiar with
Migen).

Fixes #286.
2020-02-01 02:15:45 +00:00
whitequark afece15001 hdl.ast: warn on unused property statements (Assert, Assume, etc).
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.
2020-02-01 02:03:23 +00:00
whitequark 9fb4a4f09e _unused: extract must-use logic from hdl.ir. 2020-02-01 01:35:05 +00:00
whitequark 687d3a3df7 hdl.dsl: add missing case width check for Enum values.
Fixes #305.
2020-01-31 23:14:16 +00:00
whitequark 9964fc6b57 hdl.dsl: make if m.{If,Elif,Else}(...) a syntax error.
A common typo, and hard to notice when it's silently ignored.

Fixes #284.
2020-01-31 06:37:45 +00:00
whitequark a7be3b480a hdl.ir: resolve hierarchy conflicts before creating missing domains.
Otherwise, code such as:

    m.submodules.a = (something with cd_sync)
    m.submodules.b = (something with cd_sync)
    m.d.b_sync += x.eq(y)

causes an assertion failure.

Fixes #304 (again).
2020-01-18 10:30:36 +00:00
whitequark 7cb3095334 hdl.xfrm: transform drivers as well in DomainRenamer.
This is necessary because drivers may be late bound.

Fixes #304.
2020-01-17 02:13:46 +00:00
whitequark e18385b613 Remove everything deprecated in nmigen 0.1.
Closes #275.
2020-01-12 13:59:26 +00:00
Staf Verhaegen e4e26717be Signal: allow to use integral Enum for reset value. 2020-01-11 09:03:20 +00:00
whitequark 318274d5a0 hdl.mem: fix src_loc_at in ReadPort, WritePort. 2019-12-15 11:46:26 +00:00
Marcin Kościelnicki 67650214b7 hdl.ast: Fix width for unary minus operator on signed argument.
To properly represent a negation of a signed X-bit quantity we may, in
general, need a signed (X+1)-bit signal — for example, negation of
3-bit -4 is 4, which is not representable in signed 3 bits.
2019-12-04 06:55:35 +00:00
whitequark d048f069f8 hdl.ast: actually remove simulator commands.
These were supposed to be removed in 7df70059, but I forgot.
2019-12-02 02:24:24 +00:00
whitequark 56bb42aff2 hdl.ir: for instance ports, prioritize defs over uses.
Fixes #274.
2019-11-26 21:19:03 +00:00
whitequark f8f7d83127 hdl.rec: fix Record.like() being called through a subclass.
The subclass does not necessarily take layout as the first argument.
2019-11-09 17:45:07 +00:00
Staf Verhaegen dc2a09b8b9 hdl.rec: make Record(name=) keyword-only.
Everywhere else, the name argument is already keyword-only, so
change it here too for consistency.
2019-11-09 16:10:36 +00:00
whitequark 9749c70730 hdl.ir: lower domains before resolving hierarchy conflicts.
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.
2019-11-07 08:20:27 +00:00
whitequark 75d0fcd639 test: use #nmigen: magic comment instead of monkey patch.
Also, fix missing and incorrect src_loc_at arguments where
appropriate so the testsuite passes without warnings.
2019-10-26 06:37:08 +00:00
whitequark 9786d0c0e3 hdl.ir: allow disabling UnusedElaboratable warning in file scope.
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.
2019-10-26 06:17:14 +00:00
whitequark 51269ad4a0 hdl.ast: simplify {bit,word}_select with constant offset.
We don't have any other convenient shortcut for x[off*w:(off+1)*w],
but using word_select to extract a single static range would result
in severe bloat of emitted code through expansion to dead branches.
Recognize and simplify this pattern.
2019-10-26 00:09:53 +00:00
whitequark 61e6267daf Explicitly restrict prelude imports.
It turns out that while Python does not import _private identifiers
when using * imports, it does nevertheless import all submodules.

Avoid polluting the namespace in the prelude by explicitly listing
all exported identifiers.
2019-10-21 10:39:21 +00:00
whitequark 2f9dab361f {,_}tools→{,_}utils
In context of nMigen, "tools" means "parts of toolchain", so it is
confusing to have a completely unrelated module also called "tools".
2019-10-13 18:53:38 +00:00
whitequark 29253295ee hdl.ir: allow ClockSignal and ResetSignal in ports.
Fixes #248.
2019-10-13 03:39:56 +00:00
whitequark 722b3879f4 hdl.ir: cast instance port connections to Values.
Fixes #249.
2019-10-13 03:19:17 +00:00
whitequark a7e3b80409 hdl.ast: rename Slice.end back to Slice.stop.
It used to be called .stop in oMigen, and it's also called .stop in
Python range and slice objects, so keep that.
2019-10-12 22:40:48 +00:00
whitequark da48c05bdf _tools: extract most utility methods to a private package.
We don't want to guarantee backwards compatibility for most of them.
2019-10-12 22:40:48 +00:00
whitequark b90687c988 Rename remaining wrap methods to cast.
Following commit d72d4a55.
2019-10-11 13:28:26 +00:00
whitequark a658cb2bbf hdl.ast: deprecate shapes like (1, True) in favor of signed(1).
This is a great improvement in clarity.
2019-10-11 13:22:08 +00:00
whitequark 706bfaf5e1 hdl.ast: deprecate Signal.{range,enum}.
Although constructor methods can improve clarity, there are many
contexts in which it is useful to use range() as a shape: notably
Layout, but also Const and AnyConst/AnyValue. Instead of duplicating
these constructor methods everywhere (which is not even easily
possible for Layout), use casting to Shape, introduced in 6aabdc0a.

Fixes #225.
2019-10-11 13:07:42 +00:00
whitequark 6aabdc0a73 hdl.ast: add an explicit Shape class, included in prelude.
Shapes have long been a part of nMigen, but represented using tuples.
This commit adds a Shape class (using namedtuple for backwards
compatibility), and accepts anything castable to Shape (including
enums, ranges, etc) anywhere a tuple was accepted previously.

In addition, `signed(n)` and `unsigned(n)` are added as aliases for
`Shape(n, signed=True)` and `Shape(n, signed=False)`, transforming
code such as `Signal((8, True))` to `Signal(signed(8))`.
These aliases are also included in prelude.

Preparation for #225.
2019-10-11 12:52:41 +00:00
whitequark db960e7c30 Consistently use {!r}, not '{!r}' in diagnostics.
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.
2019-10-11 11:47:42 +00:00
whitequark fa1e466a65 hdl.ast: Operator.{op→operator}
Both "operator" and "operand" were shortened to "op" in different
places in code, which caused confusion.
2019-10-11 11:37:26 +00:00
whitequark 7ff4c6ce43 hdl.ast: simplify enum handling. 2019-10-11 11:16:00 +00:00
whitequark d72d4a55fd hdl.ast: Value.{wrap→cast}
Preparation for #225.
2019-10-11 10:49:34 +00:00
whitequark 7257c20a6a build.plat: elaborate result of create_missing_domain() against platform.
Before this commit, the result was elaborated without platform, which
caused generic implementation of e.g. ResetSynchronizer to be used.
2019-10-09 21:16:20 +00:00
whitequark de34728bf8 hdl.ast: prohibit signed divisors.
See #238.
2019-10-04 07:49:24 +00:00
whitequark 9458de2079 hdl.ast: don't crash on Mux(<bool>, ...).
Fixes #240.
2019-10-02 08:30:15 +00:00
whitequark 1621ceb65a hdl.ast: actually implement the // operator. 2019-09-28 19:33:24 +00:00
whitequark 450d7efdf2 hdl.dsl: add a diagnostic for m.d.submodules += .... 2019-09-28 17:50:24 +00:00
whitequark a02e3750bf hdl.mem: remove WritePort(priority=) argument.
The write port priority in Yosys is derived directly from the order
in which the ports are declared in the Verilog frontend. It is being
removed for several reasons:
  1. It is not clear if it works correctly for all cases (FFRAM,
     LUTRAM, BRAM).
  2. Although it is roundtripped via Verilog with correct simulation
     semantics, the resulting code has a high chance of being
     interpreted incorrectly by Xilinx tools.
  3. It cannot be roundtripped via FIRRTL, which is an alternative
     backend that is an interesting future option. (FIRRTL leaves
     write collision completely undefined.)
  3. It is a niche feature that, if it is needed, can be completely
     replaced using an explicit comparator, priority encoder, and
     write enable gating circuit. (This is what Xilinx recommends
     for handling this case.)

In the future we should extend nMigen's formal verification to assert
that a write collision does not happen.
2019-09-28 01:29:56 +00:00
whitequark b227352258 hdl.ast: cast Mux() selector to bool if it is not a 1-bit value.
Fixes #232.
2019-09-23 13:39:31 +00:00
whitequark bc53bbf564 hdl.mem,lib.fifo: use keyword-only arguments for memory geometry.
Fixes #230.
2019-09-23 12:15:06 +00:00
whitequark 1aeb11d7e3 hdl.mem: simplify. NFC. 2019-09-23 11:16:29 +00:00
whitequark 649444449d hdl.ast: make Signal(name=) a keyword-only argument.
Almost no code would specify Signal(_, name) as a positional argument
on purpose, but forgetting parens and accidentally placing signedness
into the name position is so common that we had a test for it.
2019-09-23 11:08:43 +00:00
whitequark 1976310bf0 hdl.rec: fix using Enum subclass as shape if direction is specified.
Also improves error messages.

Fixes #224.
2019-09-22 17:23:32 +00:00
whitequark 4c582ef609 hdl.rec: allow using Enum subclass as shape.
Fixes #223.
2019-09-22 15:17:40 +00:00
whitequark a13a21cbd6 hdl.ast: update docs. NFC. 2019-09-21 06:53:13 +00:00
whitequark 4b3a068b15 hdl.mem: use 1 as reset value for ReadPort.en.
This is necessary for consistency, since for transparent read ports,
we currently do not support .en at all (it is fixed at 1) due to
YosysHQ/yosys#760. Before this commit, changing port transparency
would require adding or removing an assignment to .en, which is
confusing and error-prone.

Also, most read ports are always enabled, so this behavior is also
convenient.
2019-09-20 19:51:13 +00:00
whitequark 378e924280 hdl.ast: rename nbits to width.
Also, replace `bits, sign = x.shape()` with more idiomatic
`width, signed = x.shape()`.

This unifies all properties corresponding to `len(x)` to `x.width`.
(Not all values have a `width` property.)

Fixes #210.
2019-09-20 15:36:25 +00:00
whitequark 4777a7b3a2 hdl.{ast,dsl}: add Signal.enum; coerce Enum to Value; accept Enum patterns.
Fixes #207.
2019-09-16 19:22:12 +00:00
whitequark e8f79c5539 hdl.ast: add Value.matches(), accepting same language as Case().
Fixes #202.
2019-09-14 21:06:12 +00:00
whitequark f292a1977c hdl.dsl: improve error messages for Case(). 2019-09-14 20:58:19 +00:00
whitequark 32310aecad hdl.ast: add Value.xor, mapping to $reduce_xor.
Fixes #147.
2019-09-13 14:29:46 +00:00
whitequark b23a9794a4 hdl.ast: add Value.{any,all}, mapping to $reduce_{or,and}.
Refs #147.
2019-09-13 13:14:52 +00:00
whitequark 42805ad959 hdl.mem: use keyword-only arguments as appropriate. 2019-09-12 20:03:48 +00:00
whitequark 7342662bee hdl.ast: warn if reset value is truncated.
Fixes #183.
2019-09-10 07:26:34 +00:00
whitequark 9b398b502e hdl.ast: check type of Sample(domain=...).
Fixes #199.
2019-09-08 23:55:05 +00:00
whitequark 3f6abc0b7a hdl.dsl: add Default(), an alias for Case() with no arguments.
Fixes #197.
2019-09-08 12:24:18 +00:00
whitequark eb04a2509e hdl.mem,lib,examples: use Signal.range(). 2019-09-08 12:19:13 +00:00
whitequark ccfbccc044 hdl.ast: add Signal.range(...), to replace Signal(min=..., max=...).
Fixes #196.
2019-09-08 12:10:31 +00:00
whitequark 943ce317af hdl.ast,back.rtlil: implement Cover.
Fixes #194.
2019-09-03 01:32:24 +00:00
whitequark 2e20622046 hdl.cd: add negedge clock domains.
Fixes #185.
2019-08-31 22:05:48 +00:00
whitequark 13316053e3 build.plat, hdl.ir: coordinate missing domain creation.
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.
2019-08-19 22:52:01 +00:00
whitequark 003ba3b45f hdl.cd: implement local clock domains.
Closes #175.
2019-08-19 21:44:33 +00:00
whitequark 69d36dc139 hdl.xfrm: lower resets in DomainLowerer as well.
Changed in preparation for introducing local clock domains.

Also makes elaboration about 15% faster.
2019-08-19 21:44:30 +00:00
whitequark 404f99f022 hdl.xfrm: consider fragment's own domains in DomainLowerer.
Changed in preparation for introducing local clock domains.
2019-08-19 21:07:02 +00:00
whitequark 32bfbb11cb formal→asserts
Closes #171.
2019-08-19 20:23:24 +00:00
whitequark d44ea4e9fe hdl.xfrm: make deprecated CEInserter more well-behaved. 2019-08-18 16:26:45 +00:00
whitequark ed7e07c6c1 hdl.ast: implement Initial.
This is the last remaining part for first-class formal support.
2019-08-15 02:53:07 +00:00
whitequark 40abaef858 hdl.xfrm: sample cache should be per-fragment. 2019-08-15 02:45:31 +00:00
whitequark fa0fa056ba hdl.xfrm: CEInserter→EnableInserter.
Fixes #166.
2019-08-12 13:39:26 +00:00
whitequark 9d2cbbabb8 hdl.ast: hash-cons ValueKey.
This speeds up elaboration by ~10%.
2019-08-08 10:56:53 +00:00
whitequark 99d205494a hdl.dsl: reword m.If(~True) warning to be more clear.
Before this commit, it only suggested one thing (silencing it) and
that's wrong almost all of the time, so suggest the right thing
instead.
2019-08-03 18:52:24 +00:00
whitequark e0b54b417e hdl.ir: allow adding more than one domain in missing domain callback.
This is useful for injecting complex power-on reset logic.
2019-08-03 18:19:40 +00:00
whitequark 9c28b61d9f hdl.ir: don't expose as ports missing domains added via elaboratables.
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.
2019-08-03 16:39:21 +00:00
whitequark cea92e9531 hdl.ir: allow returning elaboratables from missing domain callback.
This allows e.g. injecting a clock/reset generator in platform build
code on demand (i.e. if the domain is not instantiated manually).

See #57.
2019-08-03 15:44:02 +00:00
whitequark fc846532c7 hdl.ir: raise DomainError if a domain is used but not defined.
Before this commit, a KeyError would be raised elsewhere in guts of
hdl.ir, which is not helpful.
2019-08-03 15:31:24 +00:00
whitequark fdb0c5a6bc hdl.ir: call back from Fragment.prepare if a clock domain is missing.
See #57.
2019-08-03 14:54:20 +00:00
whitequark ace2b5ff0a hdl.dsl: warn on suspicious statements like m.If(~True):.
This pattern usually produces an extremely hard to notice bug that
will usually break a design when it is triggered, but will also be
hidden unless the pathological value of a boolean switch is used.

Fixes #159.
2019-08-03 14:00:29 +00:00
whitequark 0a603b3844 hdl.ast: fix typo. 2019-08-03 13:21:09 +00:00
whitequark 94e13effad hdl.ast: deprecate Value.part, add Value.{bit,word}_select.
Fixes #148.
2019-08-03 13:07:06 +00:00
whitequark bcdc280a87 hdl.ast, back.rtlil: add source locations to anonymous wires.
This might help with propagation of locations through optimizer
passes, since not all of them take care to preserve cells at all,
but usually wires stay intact when possible.

Also fixes incorrect source location on value.part().
2019-08-03 12:51:57 +00:00
whitequark 29fee01f86 hdl.ir: warn if .elaborate() returns None.
Fixes #164.
2019-08-03 12:30:39 +00:00
whitequark 995e4adb8c hdl.xfrm: handle mem.{Read,Write}Port in CEInserter.
Fixes #154.
2019-07-31 05:20:05 +00:00
N. Engelhardt 698b005182 hdl.dsl: add getters to m.submodules. 2019-07-19 12:39:47 +00:00
whitequark 2fa858b003 hdl.ir: make UnusedElaboratable a real warning.
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.
2019-07-10 12:46:54 +00:00
whitequark 00c5209a47 hdl.{ast,dsl},back.rtlil: track source locations for switch cases.
This is a very new Yosys feature, and will require a Yosys build
newer than YosysHQ/yosys@93bc5aff.
2019-07-09 19:26:47 +00:00
whitequark 0ab0a74ec1 hdl.rec: respect modifications to signals in Record.like().
Fixes #126.
2019-07-08 10:59:15 +00:00
whitequark a7fbff94d8 hdl.{ast,cd,dsl,xfrm}: reject inappropriately used comb domain.
Fixes #125.
2019-07-08 10:26:49 +00:00
whitequark ec7fcd3697 hdl.xfrm: don't overwrite source locations on ClockDomain signals.
On the sample of examples/basic/*.py, there are no remaining
incorrectly inferred locations.
2019-07-08 09:58:12 +00:00
whitequark 8c9fdf907f hdl.{dsl,mem,xfrm}: inject appropriate source locations.
This primarily fixes the problem with source location precision in
Module (which used to trace locations from __exit__ of the context
managers, by which point everything interesting has been lost), but
also improves memory port and control inserter source locations.

On the sample of examples/basic/*.py, the only incorrectly inferred
remaining location is clk pointing to hdl/mem.py:166.
2019-07-08 09:58:12 +00:00
whitequark dac6275493 hdl.ast: use keyword-only arguments as appropriate.
As a motivation/related refactor, make sure each AST node exposes
src_loc_at in the constructor.
2019-07-08 09:58:12 +00:00
whitequark da1f58b7ae hdl.dsl: further clarify error message for incorrect nesting.
Fixes #133.
2019-07-07 01:03:59 +00:00
whitequark cb8be4a1b0 hdl.dsl: clarify error message for incorrect nesting.
Refs #133.
2019-07-07 00:59:57 +00:00
whitequark 3388b5b085 hdl.dsl: gracefully handle FSM with no states. 2019-07-07 00:59:34 +00:00
whitequark 2e4cc47fcb hdl.dsl: fix src_loc_at for FSM state signal. 2019-07-03 16:34:31 +00:00
whitequark 82903e493a back.rtlil: emit \src attributes for processes via Switch and Assign.
The locations are unfortunately not very precise, but they provide
some improvement over status quo.
2019-07-03 16:27:54 +00:00
whitequark e351e27206 hdl.ast: fix src_loc_at for Mux(). 2019-07-03 15:25:14 +00:00