Before this commit, there was no way to do so besides creating and
assigning an intermediate signal, which could not be extracted into
a helper function due to Module statefulness.
Fixes#292.
Before this commit, doing something like:
with m.FSM():
with m.State("FOO"):
m.next = "bAR"
with m.State("BAR"):
m.next = "FOO"
would silently create an empty state `bAR` and get stuck in it until
the module is reset. This was done intentionally (in Migen, this code
would in fact miscompile), but in retrospect was clearly a bad idea;
it turns typos into bugs, while in the rare case that branching to
a completely empty state is desired, it is trivial to define one.
Fixes#315.
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.
`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.
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.
The redesign introduces no fundamental incompatibilities, but it does
involve minor breaking changes:
* The simulator commands were moved from hdl.ast to back.pysim
(instead of only being reexported from back.pysim).
* back.pysim.DeadlineError was removed.
Summary of changes:
* The new simulator compiles HDL to Python code and is >6x faster.
(The old one compiled HDL to lots of Python lambdas.)
* The new simulator is a straightforward, rigorous implementation
of the Synchronous Reactive Programming paradigm, instead of
a pile of ad-hoc code with no particular design driving it.
* The new simulator never raises DeadlineError, and there is no
limit on the amount of delta cycles.
* The new simulator robustly handles multiclock designs.
* The new simulator can be reset, such that the compiled design
can be reused, which can save significant runtime with large
designs.
* Generators can no longer be added as processes, since that would
break reset(); only generator functions may be. If necessary,
they may be added by wrapping them into a generator function;
a deprecated fallback does just that. This workaround will raise
an exception if the simulator is reset and restarted.
* The new simulator does not depend on Python extensions.
(The old one required bitarray, which did not provide wheels.)
Fixes#28.
Fixes#34.
Fixes#160.
Fixes#161.
Fixes#215.
Fixes#242.
Fixes#262.
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.
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.
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.
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.
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.
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.