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.
Distinguish between the A, B input ports of `$_ANDNOT_`, `$_ORNOT_`
gates when considering those for sharing. Unlike the input ports of the
other supported single-bit gates, those are not interchangeable.
Fixes#3848.
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
This include seems to have been copied over from the JSON backend where
AIG models are sometimes inserted into the JSON output, but these other
backends don't do anything with AIG.
Python 3.12 emits a SyntaxWarning when encountering invalid escape
sequences. They still parse as expected. Marking these raw produces
the same result without the warnings.
An `std::vector<T>::reverse_iterator` stores the
`std::vector<T>::iterator` which points to the (forwards-ordered)
*following* item. Thus while `vec.rbegin()` dereferences to the final
item of `vec`, the iterator it wraps (`vec.rbegin().base()`) is equal to
`vec.end()`.
In the remove case here, we advance `it` (backwards), erasing the item
we just advanced past by grabbing its (pre-increment) base
forward-iterator and subtracting 1.
The iterator maths here is obviously all OK, but the forward-iterator
that `it` wraps post-increment actually points to the item we just
removed. That iterator was invalidated by the `erase()` call.
That this works anyway is (AFAICT) some combination of luck and/or
promises that aren't part of the C++ spec, but MSVC's debug iterator
support picks this up.
`erase()` returns the new iterator that follows the item just erased,
which happens to be the exact one we want our reverse-iterator to wrap
for the next loop; we get a fresh iterator to the same base, now without
the preceding item.