Re-associating constants can enable further simplification e.g. when
those constant become all zero/all ones. Run these patterns to fixed
point to capture the simplification, by revisiting the node.
V3Const eagerly deletes nodes (we want that in V3Const instead of using
pushDeletep, as otherwise the transient peak memory use during
verilation can be very high)
The std::map used to cache the predicate checking if a subtree contains
a member access then stale if a new node is allocated in the same address.
Fix by using unique node IDs stored in user4 as cache keys.
This is the bug uncovered by #8147
Related to #6963
Disable MULTIDRIVENPROC for static variables used as loop induction
variables. Same way as we disable similar warning in Dfg. While bad
style and bad for performance, it's common legacy code style.
The loops modelling the SystemVerilog scheduling regions are no longer
generated. They now live in 'VerilatedEvalLoop' in the runtime library.
The generated model holds one as a member, passing itself to it, and
exposes each evaluation entry point to it as a pure virtual method on
VerilatedModel. The model's 'eval' and 'eval_step' remain the top level
entry points, and are backward compatible.
V3Sched no longer emits '_eval' or '_eval_settle', etc.. Instead every
evaluation entry point called from the runtime is enumerated by 'VEval',
Scheduling creates all entry points, for all scheduling regions, even if
they are empty, and the runtime eval loop calls everything
unconditionally. If regions are empty, this is simply a call to an empty
function. This will hurt performance on very small models, but should
not be noticeable on anything meaningful, so it is likely best to keep
to reduce complexity.
A scheduling entry points evaluate a single iteration and returns
whether it did any work, they are effectively the previous
`_eval_phase_*` functions.
The following used to crash:
```systemverilog
class base #(type T = int); endclass
class derived extends base; endclass
derived #() d; // <- crash due to '#()'
```