Fix null access on optimized-out fork statements (#3658)

`V3SchedTiming` currently assumes that if a fork still exists, it must
have statements within it (otherwise it would have been deleted by
`V3Timing`). However, in a case like this:
```
module t;
    reg a;
    initial fork a = 1; join
endmodule
```
the assignment in the fork is optimized out by `V3Dead` after
`V3Timing`. This leads to `V3SchedTiming` accessing fork's `stmtsp`
pointer, which at this point is null. This patch addresses that issue.

Signed-off-by: Krzysztof Bieganski <kbieganski@antmicro.com>
This commit is contained in:
Krzysztof Bieganski 2022-10-06 15:38:59 +02:00 committed by GitHub
parent 5b742571d3
commit 97add4d57a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 10 additions and 2 deletions

View File

@ -323,8 +323,10 @@ void transformForks(AstNetlist* const netlistp) {
iterateChildrenConst(nodep); // Const, so we don't iterate the calls twice
// Replace self with the function calls (no co_await, as we don't want the main
// process to suspend whenever any of the children do)
nodep->replaceWith(nodep->stmtsp()->unlinkFrBackWithNext());
VL_DO_DANGLING(nodep->deleteTree(), nodep);
// V3Dead could have removed all statements from the fork, so guard against it
AstNode* const stmtsp = nodep->stmtsp();
if (stmtsp) nodep->addNextHere(stmtsp->unlinkFrBackWithNext());
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
void visit(AstBegin* nodep) override {
UASSERT_OBJ(m_forkp, nodep, "Begin outside of a fork");

View File

@ -15,6 +15,8 @@
-V{t#,#}+ Vt_timing_debug2___024root____Vfork___h########__0__5
-V{t#,#} Awaiting join of fork at: t/t_timing_fork_join.v:13
-V{t#,#}+ Vt_timing_debug2___024root___eval_initial__TOP__1
-V{t#,#}+ Vt_timing_debug2___024root___eval_initial__TOP__2
-V{t#,#} Awaiting join of fork at: t/t_timing_fork_join.v:83
-V{t#,#}+ Vt_timing_debug2___024root___eval_settle
-V{t#,#}+ Eval
-V{t#,#}+ Vt_timing_debug2___024root___eval

View File

@ -77,4 +77,8 @@ module t;
$finish;
end
initial #100 $stop; // timeout
// Test optimized-out fork statements:
reg a;
initial fork a = 1; join
endmodule