There are two elements involved:
1) Apply the relevant full_case and/or parallel_case attribute(s) to
the generated AST_CASE node(s), so that the existing AST frontend and
subsequent passes will generate RTLIL with appropriate behaviour.
(This is handled in the parser "if_attr" non-terminal.)
2) Rearrange the AST_CASE structure when necessary. For "priority if"
(i.e., full_case), this requires only ensuring that directly nested
"else if" branches also inherit the full_case attribute. For
"unique if" and "unique0 if" (i.e., parallel_case+full_case and
parallel_case alone), there are two steps:
a) Flatten the AST_CASE structure such that any direct "else if"
branches are mapped to additional AST_CONDs in the parent;
b) Reverse the "direction" of the test: the constant 1 (true)
is provided in the AST_CASE node, and the expression(s) in the
if statement(s) are given in each AST_COND. This is necessary
because the constant 1, being the common factor, must occupy the
shared AST_CASE position.
(This is handled in the parser "TOK_IF" expansion of behavioral_stmt.)
Observe that:
* The generated AST has not been changed for bare "if"s (those
without unique/priority). This should minimise the risk of
unexpected regressions.
* It is possible that the flattening described in 2) a) above might
affect the behaviour of expressions with side effects in "unique if"
statements (consider "unique if( a ) ...; else if( b++ ) ...": if
a is true, is b incremented?). While it might be possible to provide
precise semantics here, IEEE 1800-2012 12.4.2 seems to be deliberately
vague ("In unique-if and unique0-if, the conditions may be evaluated
and compared in any order[...] The presence of side effects in
conditions may cause nondeterministic results.") and so it seems
doubtful that there is benefit in Yosys providing stronger promises
on the interpretation of questionable code.
Add support to the "read_verilog -sv" parser to validate the
"unique", "unique0", and "priority" keywords in contexts where
they're legal according to 1800-2012 12.4.2.
This affects only the grammar accepted; the behaviour of conditionals
is not changed. (But accepting this syntax will provide scope for
possible optimisations as future work.)
Three test cases ("unique_if", "unique_if_else", and
"unique_if_else_begin") verify that the keywords are accepted where
legal and rejected where illegal, as described in the final paragraph
of 12.4.2.
`read_verilog_file_list` should not try to read arguments as selection args. Without this, trying to pass a file without a `-f|-F` flag is misleading, in the best case giving a warning about the selection not matching any module, or in worst case just doing nothing (if the filename is a valid selection).
This adds optional in-memory caching of parsed liberty files to speed up
flows that repeatedly parse the same liberty files. To avoid increasing
the memory overhead by default, the caching is disabled by default. The
caching can be controlled globally or on a per path basis using the new
`libcache` command, which also allows purging cached data.
Otherwise the `AST_PRIMITIVE` simplifies to the corresponding function and is no longer caught by the check for `AST_PRIMITIVE`s, raising an assertion error instead of an input error.
Add bug4785.ys to tests/verilog to demonstrate.
- Remove unused statics CONST_FALSE and CONST_TRUE (which appear to have been folded into the `Index` declaration as CFALSE and CTRUE).
- Assign default value of EMPTY_LIT to `a` and `b` for comparison ops.
- Tag debug only variables with YS_MAYBE_UNUSED, don't assign unused variables (but continue to call the function because it moves the file pointer).
`Const::size()` returns int, so change iterators that use it to `auto` instead of `size_t`.
For cases where size is being explicitly cast to `int`, use the wrapper that we already have instead: `Yosys::GetSize()`.
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.
Consider this SystemVerilog file:
module top(...);
input clk;
input [7:0] data;
input ack;
always @(posedge clk)
if (ack) begin
assert(data != 8'h0a);
end
endmodule
Before this commit, the span for the assert was:
if (ack) begin>
assert(data != 8'h0a)<;
After this commit, the span for the assert is:
if (ack) begin
>assert(data != 8'h0a)<;
This helps editor integrations that only look at the beginning
of the span.
These are useful for formal verification with SBY where they can be used
to display solver chosen `rand const reg` signals and signals derived
from those.
The previous error message for non-constant initial $display statements
is downgraded to a log message. Constant initial $display statements
will be shown both during elaboration and become part of the RTLIL so
that the `sim` output is complete.
This makes tests/verilog/dynamic_range_lhs.v pass, after ensuring that
nowrshmsk is actually tested.
Stride is extracted from indexing of two-dimensional packed arrays and
variable slices on the form dst[i*stride +: width] = src, and is used
to optimize the generated CASE block.
Also uses less confusing variable names for indexing of lhs wires.
When reading the BLIF input, represent the native sequential elements
with fine-grained cells like `$_FF_` instead of the coarse-grained cells
like `$ff` which we were using up to now.
There are two reasons for this:
* The sequential elements in BLIF are always single-bit, so the gate
cells are a better fit.
* This makes it symmetrical to the BLIF backend which only understands
the fine-grained cells, and only translates those to the native BLIF
features.
The $shift and $shiftx cells perform a left logical shift if the second
operand is negative. This change passes the sign of the second operand
of AST_SHIFT and AST_SHIFTX into $shift and $shiftx cells, respectively.
Compiling on GCC hid this bug as it optimized the nullptr call away as
undefined behavior, but running the SBY tests with a clang build hits
this error.
Instead of passing around in_lvalue/in_param flags to simplify, we make
the flags into properties of the AST nodes themselves. After the tree
is first parsed, we once do
ast->fixup_hierarchy_flags(true)
to walk the full hierarchy and set the flags to their initial correct
values. Then as long as one is using ->clone(), ->cloneInto() and the
AstNode constructor (with children passed to it) to modify the tree, the
flags will be kept in sync automatically. On the other hand if we are
modifying the children list of an existing node, we may need to call
node->fixup_hierarchy_flags()
to do a localized fixup. That fixup will update the flags on the node's
children, and will propagate the change down the tree if necessary.
clone() doesn't always retain the flags of the subtree being cloned. It
will produce a tree with a consistent setting of the flags, but the
root doesn't have in_param/in_lvalue set unless it's intrinsic to the
type of node being cloned (e.g. AST_PARAMETER). cloneInto() will make
sure the cloned subtree has the flags consistent with the new placement
in a hierarchy.
Add asserts to make sure the old and new way of determining the flags
agree.
The following commit will replace the way in_lvalue/in_param is being
tracked in the simplify code. Make tweaks in advance so that it will
be easier to make the old way and the new way agree.
These changes all should be innocuous.
- Add support for assignments within expressions, e.g., `x[y++] = z;` or
`x = (y *= 2) - 1;`. The logic is handled entirely within the parser
by injecting statements into the current procedural block.
- Add support for pre-increment/decrement statements, which are
behaviorally equivalent to post-increment/decrement statements.
- Fix non-standard attribute position used for post-increment/decrement
statements.
The correct way of using the 'at_zero' regime of simplify is to perform
the simplification on a cloned AST subtree, otherwise the "at_zero"
evaluation seeps into the main tree.
Move the effect of the 'at_zero' flag to the cloning itself, so that
the simplify flag can be retired. We assume we can rely on id2ast in
the new clone method.
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.
(* nowrshmsk *) on a struct / union variable now affects dynamic
bit slice assignments to members of the struct / union.
(* nowrshmsk *) can in some cases yield significant resource savings; the
combination of pipeline shifting and indexed writes is an example of this.
Constructs similar to the one below can benefit from (* nowrshmsk *), and
in addition it is no longer necessary to split out the shift assignments
on separate lines in order to avoid the error message "ERROR: incompatible
mix of lookahead and non-lookahead IDs in LHS expression."
always_ff @(posedge clk) begin
if (rotate) begin
{ v5, v4, v3, v2, v1, v0 } <= { v4, v3, v2, v1, v0, v5 };
if (res) begin
v0.bytes <= '0;
end else if (w) begin
v0.bytes[addr] <= data;
end
end
end
When the verilog frontend perfomed constant evaluation of unbased
unsized constants in a context-determined expression it did not properly
extend them by repeating the bit value. This only affected constant
evaluation and not constants that made it through unchanged to RTLIL.
The latter case was already covered by tests and working before.
This fixes the const-eval issue by checking the `is_unsized` flag in
bitsAsConst and extending the value accordingly.
The newly added test also tests the already working non-const-eval case
to highlight that both cases should behave the same.
The difference between void functions and tasks is that always_comb's
implicit sensitivity list behaves as if functions were inlined, but
ignores signals read only in tasks. This only matters for event based
simulation, and for synthesis we can treat a void function like a task.
This uses the same constant parsing for enum_values and for attributes
and extends it to handle signed values as those are used for enums that
implicitly use the int type.
This brings the metadata for packed arrays in packed structs
in line with the metadata for unpacked arrays, and correctly
handles the case when both lsb and msb in an address range are
non-zero.
Otherwise the AST_CELL simplification uses the wrong celltype before the
AST_CELLARRAY simplification has a chance to unroll it and change it to
the $array celltype.
This is primarily intended to enable the standard-permitted use of
module-scoped identifiers to refer to tasks and non-constant functions.
As a side-effect, this also adds support for the non-standard use of
module-scoped identifiers referring to constant functions, a feature
that is supported in some other tools, including Iverilog.