Previously `extract` on a `SigSpec` would always unpack it. Since a
significant amount of `SigSpec`s have one or few chunks, it's worth
having a dedicated implementation.
This is especially true, since the RTLIL frontend calls into this for
every `wire [lhs:rhs]` slice, making this `extract` take up 40% when
profiling `read_rtlil` with one of the largest coarse grained RTLIL
designs I had on hand.
With this change the `read_rtlil` profile looks like I would expect it
to look like, but I noticed that a lot of the other core RTLIL methods
also are a bit too eager with unpacking or implementing
`SigChunk`/`Const` overloads that just convert to a single chunk
`SigSpec` and forward to the implementation for that, when a direct
implementation would avoid temporary std::vector allocations. While not
relevant for `read_rtlil`, to me it looks like there might be a few easy
overall performance gains to be had by addressing this more generally.
This adjusts the way the headers kernel/{yosys,rtlil,register,log}.h
include each other to avoid the need of including headers outside of
include guards as well as avoiding the inclusion of rtlil.h in the
middle of yosys.h with rtlil.h depending on the prefix of yosys.h, and
the suffix of yosys.h depending on rtlil.h.
To do this I moved some of the declaration in yosys.h into a new header
yosys_common.h. I'm not sure if that is strictly necessary.
Including any of these files still results in the declarations of all
these headers being included, so this shouldn't be a breaking change for
any passes or external plugins.
My main motivation for this is that ccls's (clang based language server)
include guard handling gets confused by the previous way the includes
were done. It often ends up treating the include guard as a generic
disabled preprocessor conditional, breaking navigation and highlighting
for the core RTLIL data structures.
Additionally I think avoiding cyclic includes in the middle of header
files that depend on includes being outside of include guards will also
be less confusing for developers reading the code, not only for tools
like ccls.
Before this commit, the combination of `_` and `0` format characters
would produce a result like `000000001010_1010`.
After this commit, it would be `0000_0000_1010_1010`.
This has a slight quirk where a format like `{:020_b}` results in
the output `0_0000_0000_1010_1010`, which is one character longer than
requested. Python has the same behavior, and it's not clear what would
be strictly speaking correct, so Python behavior is implemented.
The option is serialized to RTLIL as `_` (to match Python's option with
the same symbol), and sets the `group` flag. This flag inserts an `_`
symbol between each group of 3 digits (for decimal) or four digits (for
binary, hex, and octal).
The option is serialized to RTLIL as `#` (to match Python's and Rust's
option with the same symbol), and sets the `show_base` flag. Because
the flag is called `show_base` and not e.g. `alternate_format` (which
is what Python and Rust call it), in addition to the prefixes `0x`,
`0X`, `0o`, `0b`, the RTLIL option also prints the `0d` prefix.
This format type is used to print an Unicode character (code point) as
its UTF-8 serialization. To this end, two UTF-8 decoders (one for fmt,
one for cxxrtl) are added for rendering. When converted to a Verilog
format specifier, `UNICHAR` degrades to `%c` with the low 7 bits of
the code point, which has equivalent behavior for inputs not exceeding
ASCII. (SystemVerilog leaves source and display encodings completely
undefined.)
Before this commit, the existing alignments were `LEFT` and `RIGHT`,
which added the `padding` character to the right and left just before
finishing formatting. However, if `padding == '0'` and the alignment is
to the right, then the padding character (digit zero) was added after
the sign, if one is present.
After this commit, the special case for `padding == '0'` is removed,
and the new justification `NUMERIC` adds the padding character like
the justification `RIGHT`, except after the sign, if one is present.
(Space, for the `SPACE_MINUS` sign mode, counts as the sign.)
The first two were already supported with the `plus` boolean flag.
The third one is a new specifier, which is allocated the ` ` character.
In addition, `MINUS` is now allocated the `-` character, but old format
where there is no `+`, `-`, or `-` in the respective position is also
accepted for compatibility.
Before this commit, the `STRING` variant inserted a literal string;
the `CHARACTER` variant inserted a string. This commit renames them
to `LITERAL` and `STRING` respectively.
The behavior of these format specifiers is highly specific to Verilog
(`$time` and `$realtime` are only defined relative to `$timescale`)
and may not fit other languages well, if at all. If they choose to use
it, it is now clear what they are opting into.
This commit also simplifies the CXXRTL code generation for these format
specifiers.
This commit achieves three roughly equally important goals:
1. To bring the rendering code in kernel/fmt.cc and in cxxrtl.h as close
together as possible, with an ideal of only having the bigint library
as the difference between the render functions.
2. To make the treatment of `$time` and `$realtime` in CXXRTL closer to
the Verilog semantics, at least in the formatting code.
3. To change the code generator so that all of the `$print`-to-`string`
conversion code is contained inside of a closure.
There are two reasons to aim for goal (3):
a. Because output redirection through definition of a global ostream
object is neither convenient nor useful for environments where
the output is consumed by other code rather than being printed on
a terminal.
b. Because it may be desirable to, in some cases, ignore the `$print`
cells that are present in the netlist based on a runtime decision.
This is doubly true for an upcoming `$check` cell implementing
assertions, since failing a `$check` would by default cause a crash.
When we are iterating over a `SigSpec`, the visited values will be of
type `SigBit` (as is the return type of `operator*()`). Account for that
in the publicly declared types.
`std::iterator` has been deprecated in C++17. Yosys is being compiled
against the C++11 standard but plugins can opt to compile against a
newer one. To silence some deprecation warnings when those plugins are
being compiled, replace the `std::iterator` inheritance with the
equivalent type declarations.
* Keep the previous behavior when no tcl script is used
* Do not treat "-" as a flag but as a positional argument
* Keep including <unistd.h> as it's also used for other functions (at
least for the emscripten build)
* Move the custom getopt implementation into the Yosys namespace to
avoid potential collisions
The main speedup is accomplished by avoiding a heap allocation in the common case where the final string length is less than 128. Inlining stringf & vstringf adds an additional improvement.
The main speedup comes from swithing from using a SHA1 hash to std::hash<std::string>. There is no need to use an expensive cryptographic hash for fingerprinting in this context.
This PR speeds up by roughly 17% across a wide spectrum of designs
tested at Google. Particularly for the mux generation pass.
Co-authored-by: Rasmus Larsen <rmlarsen@google.com>
Signed-off-by: Ethan Mahintorabi <ethanmoon@google.com>
This does not correctly handle an `$overwrite_tag` on a module output,
but since we currently require the user to flatten the design for
cross-module dft, this cannot be observed from within the design, only
by manually inspecting the signals in the design.
Fix mistaking the read-port and write-port indices for each other when
we are adding the partial transparency emulation to be able to merge two
write ports.
Remove superfluous curly braces in call to IdString::in to address
a compilation error (reproduced below) under GCC 9 and earlier.
kernel/cellaigs.cc:395:18: error: call to member function 'in' is ambiguous
if (cell->type.in({ID($gt), ID($ge)}))
~~~~~~~~~~~^~
./kernel/rtlil.h:383:8: note: candidate function
bool in(const std::string &rhs) const { return *this == rhs; }
^
./kernel/rtlil.h:384:8: note: candidate function
bool in(const pool &rhs) const { return rhs.co...
^
Removing some signed checks and logic where we've already guaranteed the
values to be positive. Indeed, in these cases, if a negative value got
through (per my realisation in the signed fuzz harness), it would cause
an infinite loop due to flooring division.
e.g. `$displayh(8'ha)` won't have a padding set, because it just gets
`lzero` set instead by `compute_required_decimal_places`.
It also doesn't have a width. In this case, we can just fill in a dummy
(unused) padding. Either space or zero would work, but space is a bit
more distinct given the width field follows.
Also omit writing the width if it's zero. This makes the emitted ilang
a little cleaner in places; `{8:> h0u}` is the output for this example,
now. The other possible extreme would be `{8:>00h0u}`.
For input like "{", "{1", etc., we would exit the loop due to
`i < fmt.size()` no longer being the case, and then check if
`++i == fmt.size()`. That would increment i to `fmt.size() + 1`,
and so execution continues.
The intention is to move i beyond the ':', so we do it only in that
case instead.
The guard is optimised out on some compilers under certain conditions (eg: LTO on GCC) as constant under C++ lifetime rules.
This is because the guard type's member is invalid to access (UB) after the type has been destroyed, resulting in
`destruct_guard.ok` being unable to be `false` according to the optimiser, based on the lifetime rules.
This patch still invokes UB (all accesses to the destroyed IdString instance are), but at least the optimiser
can't reason that destruct_guard_ok cannot be false and therefore it's safe to optimise out from its guard role.
It's a repeating pattern to print an error message tied to an AST
node. Start using an 'input_error' helper for that. Among other
things this is beneficial in shortening the print lines, which tend
to be long.
Later in the check() code we check the bottom wide_log2 bits on the
address port are zeroed out. If the address port is too narrow, we crash
due to out of bounds access. Explicitly assert the address port is wide
enough, so we don't crash on input such as
read_rtlil <<EOF
module \top
wire input 1 \clk
memory width 8 size 2 \mem
cell $memwr $auto$:1:$8
parameter \PRIORITY 1'0
parameter \CLK_POLARITY 1'1
parameter \CLK_ENABLE 1'1
parameter \MEMID "\\mem"
parameter \ABITS 1'0
parameter \WIDTH 6'010000
connect \DATA 16'0000000000000000
connect \ADDR { }
connect \EN 16'0000000000000000
connect \CLK \clk
end
end
EOF
memory
The return value of the min(...) call is never used.
Looks like some leftover from some previous implementation.
Signed-off-by: Henner Zeller <h.zeller@acm.org>
Avoids errors in trailing comma handling, broken indentation and
improper escaping that is common when building JSON by manually
concatenating strings.
This contains parsing code as well as generic routines to associate the
hierarchical signals paths within a Yosys witness file to a loaded RTLIL
design, including support for memories.
This adds the xprop_decoder attribute to bwmuxes that drive the original
unencoded signals. Setundef is changed to ignore the x inputs of these
bwmuxes, so that they survive the prep script of SBY's formal flow. This
is required to make simulation (via sim) using the prep model show the
decoded x signals instead of 0/1 values made up by the solver.
This makes it possible for yosys commands to return values when invoked
as tcl commands. Right now no commands natively support this, but the
tee command can be used with json output like this:
```tcl
set stat [yosys tee -q -s result.json stat -json -top top]
dict get $stat modules \\top num_cells_by_type \$pmux
```
Or with newline separated lists like this:
```tcl
split [yosys tee -q -s result.string select -list top] "\n"
```
The new bitwise case equality (`$bweqx`) and bitwise mux (`$bwmux`)
cells enable compact encoding and decoding of 3-valued logic signals
using multiple 2-valued signals.
When writing VCDs smtbmc replaces square brackets with angle brackets to
avoid the issues with VCD readers misinterpreting such signal names.
For memory addresses it also uses angle brackets and hexadecimal
addresses, while other tools will use square brackets and decimal
addresses.
Previously the code handled both forms of memory addresses, assuming
that any signal that looks like a memory address is a memory address.
This is not the case when the user uses regular signals whose names
include square brackets _or_ when the verific frontend generates such
names to represent various constructs.
With this change all angular brackets are turned into square brackets
when reading the trace _and_ when performing a signal lookup. This means
no matter which kind of brackets are used in the design or in the VCD
signals will be matched. This will not handle multiple signals that are
the same apart from replacing square/angle brackets, but this will cause
issues during the VCD writing of smtbmc already.
It still uses the distinction between square and angle brackets for
memories to decide whether the address is hex or decimal, but even if
something looks like a memory and is added to the `memory_to_handle`
data, the plain signal added to `name_to_handle` is used as-is, without
rewriting the address.
This last change is needed to successfully match verific generated
signal names that look like memory addresses while keeping memories
working at the same time. It may cause regressions when VCD generation
was done with a design that had memories but simulation is done with a
design where the memories were mapped to registers. This seems like an
unusual setup, but could be worked around with some further changes
should this be required.
* Change simlib's $mux cell to use the ternary operator as $_MUX_
already does
* Stop opt_expr -keepdc from changing S=x to S=0
* Change const eval of $mux and $pmux to match the updated simlib
(fixes sim)
* The sat behavior of $mux already matches the updated simlib
The verilog frontend uses $mux for the ternary operators and this
changes all interpreations of the $mux cell (that I found) to match the
verilog simulation behavior for the ternary operator. For 'if' and
'case' expressions the frontend may also use $mux but uses $eqx if the
verilog simulation behavior is requested with the '-ifx' option.
For $pmux there is a remaining mismatch between the sat behavior and the
simlib behavior. Resolving this requires more discussion, as the $pmux
cell does not directly correspond to a specific verilog construct.
This attribute can be used by formal backends to indicate which clocks
were mapped to the global clock. Update the btor and smt2 backend which
already handle clock inputs to understand this attribute.
These can be used to protect undefined flip-flop initialization values
from optimizations that are not sound for formal verification and can
help mapping all solver-provided values in witness traces for flows that
use different backends simultaneously.
This pull request is to address YosysHQ/yosys#2980.
The documentation, as originally written, does not make it clear that yosys commands, when used within a tcl script, do not return any value to the tcl script.
This pull request notes this and offers a workaround via tee as noted in the issue.