Missing initial positive edge when using --x-initial-edge

If --x-initial-edge is set, the __Vclklast of clock values is set to 1 to trigger the negedge action. If the initialization routine sets the value to 1, then neither the positive nor negative edge of that signal are triggered.

The bug was introduced in "Fix ordering of clock enables with delayed assigns, bug613" patch (b277bc8750ea35933e0cced7c107c1e0e61912ba).

I think the old behavior was wrong, and Bug 613 fixed it (very much as an unexpected side effect, which I still don't understand properly). If you define a signal with "initial", then it isn't X to start with, so it should not be affected by --x-initial-edge.

I've tested against an event driven simulator (Icarus), and its behaviour is consistent with this. Do you see the same behavior with NC or VCS?

However...

It used to work for you, and now it is broken. I need to work out if there is a way to restore the behavior you want. You want initial to happen not at the very beginning, but after one cycle of checking for clock edges. Can you confirm this is the semantics you need?

That's a fascinating approach. Marking all variable references in sensitivities as delayed. I need to think this through, to see how it will affect the overally ordering algorithm. Have you run a regression test to see what wider effects this has.

The approach I am investigating was whether the change from Bug 613 could be restricted, so it did not apply to delayed variables in initial blocks.

This is a little tricky, because by the time we get to V3Order.cpp, we don't know if an initial block used delayed assignments. However it is fairly easy to leave a marker around for that. We then need to add initial blocks to the order tree in V3Order.cpp, so we can then detect them in the AstNodeVarRef visitor and if it is a delayed assignment in an initial block add a suitable vertex and edge.

I've done all this, and it mostly works. See branch issue-678 at https://github.com/jeremybennett/verilator.

But...

This change breaks processMove(), and we don't get the correct CFUNC tree generated for initial blocks. The upshot is that you get dupliate declarations of _initial__TOP functions in the generated code. I have partly ameliorated this, by eliminating unused initial logic vertices in iterateNewStmt(), but this is really just covering up the problem. There is still one regression error, t_initial_dlyass.pl caused by this patch, but it is symptomatic of the problem.

It's getting late tonight, but I hope either you or Wilson might see what the final part of the patch is. I'll take another look in a day or two.