Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Potential bug in V3Delayed for suspendable/fork #5084

Open
gezalore opened this issue Apr 29, 2024 · 2 comments
Open

Potential bug in V3Delayed for suspendable/fork #5084

gezalore opened this issue Apr 29, 2024 · 2 comments
Labels
status: discussion Issue is waiting for discussions to resolve type: q and a Question and answer about some feature or user question

Comments

@gezalore
Copy link
Member

I'm working on a largeish refactor of V3Delayed and noticed this line:

m_vscpAux(varrefp->varScopep()).suspFinalp = finalp;

And in the larger context:

verilator/src/V3Delayed.cpp

Lines 358 to 373 in 72b96d5

AstAlwaysPost* finalp = nullptr;
if (m_inSuspendableOrFork) {
finalp = m_vscpAux(varrefp->varScopep()).suspFinalp;
if (!finalp) {
FileLine* const flp = nodep->fileline();
finalp = new AstAlwaysPost{flp, nullptr, nullptr};
UINFO(9, " Created " << finalp << endl);
if (!m_procp->user3p()) {
AstActive* const newactp = createActive(varrefp);
m_procp->user3p(newactp);
m_vscpAux(varrefp->varScopep()).suspFinalp = finalp;
}
AstActive* const actp = VN_AS(m_procp->user3p(), Active);
actp->addStmtsp(finalp);
}
} else {

I'm confused what is happening here. 'finalp' is the "Post" scheduled block that commits the NBA. If this doesn't exist, we create it but only save it if this is the first NBA inside the current process? (If there is a second NBA to a different variable in the same process, we create the 'finalp' but won't save it as m_processp->user3 is already set.) Should line 368 be outside the the if that contains it? Even then the variable might be assigned from multiple suspendable processes with different domains, but only the first ever encountered is considered here? @kbieganski could you shed some light on how this is supposed to work?

FWIW I will not change this in the upcoming patch.

@gezalore gezalore added new New issue not seen by maintainers status: discussion Issue is waiting for discussions to resolve type: q and a Question and answer about some feature or user question and removed new New issue not seen by maintainers labels Apr 29, 2024
gezalore added a commit to gezalore/verilator that referenced this issue May 1, 2024
For NBAs that might execute a dynamic number of times in a single
evaluation (specifically: those that assign to array elements inside
loops), we introduce a new run-time VlNBACommitQueue data-structure
(currently a vector), which stores all pending updates and the necessary
info to reconstruct the LHS reference of the AstAssignDly at run-time.

All variables needing a commit queue has their corresponding unique
commit queue.

All NBAs to a variable that requires a commit queue go through the
commit queue. This is necessary to preserve update order in sequential
code, e.g.:
 a[7] <= 10
 for (int i = 1 ; i < 10; ++i) a[i] <= i;
 a[2] <= 10
needs to end with array elements 1..9 being 1, 10, 3, 4, 5, 6, 7, 8, 9.

This enables supporting common forms of NBAs to arrays on the left hand
side of <= in non-suspendable/non-fork code. (Suspendable/fork
implementation is unclear to me so I left it unchanged, see verilator#5084).

Any NBA that does not need a commit queue (i.e.: those that were
supported before), use the same scheme as before, and this patch should
have no effect on the generated code for those NBAs.
gezalore added a commit to gezalore/verilator that referenced this issue May 1, 2024
For NBAs that might execute a dynamic number of times in a single
evaluation (specifically: those that assign to array elements inside
loops), we introduce a new run-time VlNBACommitQueue data-structure
(currently a vector), which stores all pending updates and the necessary
info to reconstruct the LHS reference of the AstAssignDly at run-time.

All variables needing a commit queue has their corresponding unique
commit queue.

All NBAs to a variable that requires a commit queue go through the
commit queue. This is necessary to preserve update order in sequential
code, e.g.:
 a[7] <= 10
 for (int i = 1 ; i < 10; ++i) a[i] <= i;
 a[2] <= 10
needs to end with array elements 1..9 being 1, 10, 3, 4, 5, 6, 7, 8, 9.

This enables supporting common forms of NBAs to arrays on the left hand
side of <= in non-suspendable/non-fork code. (Suspendable/fork
implementation is unclear to me so I left it unchanged, see verilator#5084).

Any NBA that does not need a commit queue (i.e.: those that were
supported before), use the same scheme as before, and this patch should
have no effect on the generated code for those NBAs.
gezalore added a commit to gezalore/verilator that referenced this issue May 1, 2024
For NBAs that might execute a dynamic number of times in a single
evaluation (specifically: those that assign to array elements inside
loops), we introduce a new run-time VlNBACommitQueue data-structure
(currently a vector), which stores all pending updates and the necessary
info to reconstruct the LHS reference of the AstAssignDly at run-time.

All variables needing a commit queue has their corresponding unique
commit queue.

All NBAs to a variable that requires a commit queue go through the
commit queue. This is necessary to preserve update order in sequential
code, e.g.:
 a[7] <= 10
 for (int i = 1 ; i < 10; ++i) a[i] <= i;
 a[2] <= 10
needs to end with array elements 1..9 being 1, 10, 3, 4, 5, 6, 7, 8, 9.

This enables supporting common forms of NBAs to arrays on the left hand
side of <= in non-suspendable/non-fork code. (Suspendable/fork
implementation is unclear to me so I left it unchanged, see verilator#5084).

Any NBA that does not need a commit queue (i.e.: those that were
supported before), use the same scheme as before, and this patch should
have no effect on the generated code for those NBAs.
gezalore added a commit to gezalore/verilator that referenced this issue May 1, 2024
For NBAs that might execute a dynamic number of times in a single
evaluation (specifically: those that assign to array elements inside
loops), we introduce a new run-time VlNBACommitQueue data-structure
(currently a vector), which stores all pending updates and the necessary
info to reconstruct the LHS reference of the AstAssignDly at run-time.

All variables needing a commit queue has their corresponding unique
commit queue.

All NBAs to a variable that requires a commit queue go through the
commit queue. This is necessary to preserve update order in sequential
code, e.g.:
 a[7] <= 10
 for (int i = 1 ; i < 10; ++i) a[i] <= i;
 a[2] <= 10
needs to end with array elements 1..9 being 1, 10, 3, 4, 5, 6, 7, 8, 9.

This enables supporting common forms of NBAs to arrays on the left hand
side of <= in non-suspendable/non-fork code. (Suspendable/fork
implementation is unclear to me so I left it unchanged, see verilator#5084).

Any NBA that does not need a commit queue (i.e.: those that were
supported before), use the same scheme as before, and this patch should
have no effect on the generated code for those NBAs.
gezalore added a commit to gezalore/verilator that referenced this issue May 1, 2024
For NBAs that might execute a dynamic number of times in a single
evaluation (specifically: those that assign to array elements inside
loops), we introduce a new run-time VlNBACommitQueue data-structure
(currently a vector), which stores all pending updates and the necessary
info to reconstruct the LHS reference of the AstAssignDly at run-time.

All variables needing a commit queue has their corresponding unique
commit queue.

All NBAs to a variable that requires a commit queue go through the
commit queue. This is necessary to preserve update order in sequential
code, e.g.:
 a[7] <= 10
 for (int i = 1 ; i < 10; ++i) a[i] <= i;
 a[2] <= 10
needs to end with array elements 1..9 being 1, 10, 3, 4, 5, 6, 7, 8, 9.

This enables supporting common forms of NBAs to arrays on the left hand
side of <= in non-suspendable/non-fork code. (Suspendable/fork
implementation is unclear to me so I left it unchanged, see verilator#5084).

Any NBA that does not need a commit queue (i.e.: those that were
supported before), use the same scheme as before, and this patch should
have no effect on the generated code for those NBAs.
gezalore added a commit to gezalore/verilator that referenced this issue May 2, 2024
For NBAs that might execute a dynamic number of times in a single
evaluation (specifically: those that assign to array elements inside
loops), we introduce a new run-time VlNBACommitQueue data-structure
(currently a vector), which stores all pending updates and the necessary
info to reconstruct the LHS reference of the AstAssignDly at run-time.

All variables needing a commit queue has their corresponding unique
commit queue.

All NBAs to a variable that requires a commit queue go through the
commit queue. This is necessary to preserve update order in sequential
code, e.g.:
 a[7] <= 10
 for (int i = 1 ; i < 10; ++i) a[i] <= i;
 a[2] <= 10
needs to end with array elements 1..9 being 1, 10, 3, 4, 5, 6, 7, 8, 9.

This enables supporting common forms of NBAs to arrays on the left hand
side of <= in non-suspendable/non-fork code. (Suspendable/fork
implementation is unclear to me so I left it unchanged, see verilator#5084).

Any NBA that does not need a commit queue (i.e.: those that were
supported before), use the same scheme as before, and this patch should
have no effect on the generated code for those NBAs.
gezalore added a commit to gezalore/verilator that referenced this issue May 2, 2024
For NBAs that might execute a dynamic number of times in a single
evaluation (specifically: those that assign to array elements inside
loops), we introduce a new run-time VlNBACommitQueue data-structure
(currently a vector), which stores all pending updates and the necessary
info to reconstruct the LHS reference of the AstAssignDly at run-time.

All variables needing a commit queue has their corresponding unique
commit queue.

All NBAs to a variable that requires a commit queue go through the
commit queue. This is necessary to preserve update order in sequential
code, e.g.:
 a[7] <= 10
 for (int i = 1 ; i < 10; ++i) a[i] <= i;
 a[2] <= 10
needs to end with array elements 1..9 being 1, 10, 3, 4, 5, 6, 7, 8, 9.

This enables supporting common forms of NBAs to arrays on the left hand
side of <= in non-suspendable/non-fork code. (Suspendable/fork
implementation is unclear to me so I left it unchanged, see verilator#5084).

Any NBA that does not need a commit queue (i.e.: those that were
supported before), use the same scheme as before, and this patch should
have no effect on the generated code for those NBAs.
@kbieganski
Copy link
Member

I think you're right, this code is completely incorrect.

A quick test that demonstrates it:

module t;
   logic clk1 = 0, clk2 = 0, clk3 = 0, clk4 = 0;
   always #2 clk1 = ~clk1;
   assign #1 clk2 = clk1;
   assign #1 clk3 = clk2;
   assign #1 clk4 = clk3;

   int x = 0;
   int cyc = 0;

   always @(posedge clk1) begin
      if (x != 0) $stop;
      $display("[%0t] clk1 | x=%0d cyc=%0d", $realtime, x, cyc);
      @(posedge clk2);
      $display("[%0t] clk2 | x=%0d cyc=%0d", $realtime, x, cyc);
      x <= x + 1;
      cyc <= cyc + 1;
      if (cyc == 10) $finish;
   end

   always @(posedge clk3) begin
      $display("[%0t] clk3 | x=%0d cyc=%0d", $realtime, x, cyc);
      @(posedge clk4);
      $display("[%0t] clk4 | x=%0d cyc=%0d", $realtime, x, cyc);
      x <= x - 1;
   end
endmodule 

A possible fix:

diff --git i/src/V3Delayed.cpp w/src/V3Delayed.cpp
index cb31f131e..b9837b259 100644
--- i/src/V3Delayed.cpp
+++ w/src/V3Delayed.cpp
@@ -84,8 +84,6 @@ class DelayedVisitor final : public VNVisitor {
         AstVarScope* delayVscp = nullptr;
         // Points to activity block of signal (valid when AstVarScope::user1p is valid)
         AstActive* activep = nullptr;
-        // Post block for this variable used for AssignDlys in suspendable processes
-        AstAlwaysPost* suspFinalp = nullptr;
         // Post block for this variable
         AstAlwaysPost* finalp = nullptr;
         // Last blocking or non-blocking reference
@@ -357,19 +355,15 @@ class DelayedVisitor final : public VNVisitor {
         UINFO(9, "     & " << varrefp << endl);
         AstAlwaysPost* finalp = nullptr;
         if (m_inSuspendableOrFork) {
-            finalp = m_vscpAux(varrefp->varScopep()).suspFinalp;
-            if (!finalp) {
                 FileLine* const flp = nodep->fileline();
                 finalp = new AstAlwaysPost{flp, nullptr, nullptr};
                 UINFO(9, "     Created " << finalp << endl);
                 if (!m_procp->user3p()) {
                     AstActive* const newactp = createActive(varrefp);
                     m_procp->user3p(newactp);
-                    m_vscpAux(varrefp->varScopep()).suspFinalp = finalp;
                 }
                 AstActive* const actp = VN_AS(m_procp->user3p(), Active);
                 actp->addStmtsp(finalp);
-            }
         } else {
             finalp = m_vscpAux(varrefp->varScopep()).finalp;
             if (finalp) {

This generates more AstAlwaysPosts but at least it is (more) correct.

What do you think? Shall I make a PR? Or you can include this in your changes.

@gezalore
Copy link
Member Author

gezalore commented May 2, 2024

Thanks for checking, I would appreciate a PR (with the test included), after #5092 is merged, which changes a lot of V3Delayed (but that snippet still exists in a largely unmodified form). Maybe we could add some of the unsupported forms, see BLKLOOPINIT warnings after #5092.

gezalore added a commit to gezalore/verilator that referenced this issue May 3, 2024
For NBAs that might execute a dynamic number of times in a single
evaluation (specifically: those that assign to array elements inside
loops), we introduce a new run-time VlNBACommitQueue data-structure
(currently a vector), which stores all pending updates and the necessary
info to reconstruct the LHS reference of the AstAssignDly at run-time.

All variables needing a commit queue has their corresponding unique
commit queue.

All NBAs to a variable that requires a commit queue go through the
commit queue. This is necessary to preserve update order in sequential
code, e.g.:
 a[7] <= 10
 for (int i = 1 ; i < 10; ++i) a[i] <= i;
 a[2] <= 10
needs to end with array elements 1..9 being 1, 10, 3, 4, 5, 6, 7, 8, 9.

This enables supporting common forms of NBAs to arrays on the left hand
side of <= in non-suspendable/non-fork code. (Suspendable/fork
implementation is unclear to me so I left it unchanged, see verilator#5084).

Any NBA that does not need a commit queue (i.e.: those that were
supported before), use the same scheme as before, and this patch should
have no effect on the generated code for those NBAs.
wsnyder pushed a commit that referenced this issue May 3, 2024
For NBAs that might execute a dynamic number of times in a single
evaluation (specifically: those that assign to array elements inside
loops), we introduce a new run-time VlNBACommitQueue data-structure
(currently a vector), which stores all pending updates and the necessary
info to reconstruct the LHS reference of the AstAssignDly at run-time.

All variables needing a commit queue has their corresponding unique
commit queue.

All NBAs to a variable that requires a commit queue go through the
commit queue. This is necessary to preserve update order in sequential
code, e.g.:
 a[7] <= 10
 for (int i = 1 ; i < 10; ++i) a[i] <= i;
 a[2] <= 10
needs to end with array elements 1..9 being 1, 10, 3, 4, 5, 6, 7, 8, 9.

This enables supporting common forms of NBAs to arrays on the left hand
side of <= in non-suspendable/non-fork code. (Suspendable/fork
implementation is unclear to me so I left it unchanged, see #5084).

Any NBA that does not need a commit queue (i.e.: those that were
supported before), use the same scheme as before, and this patch should
have no effect on the generated code for those NBAs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: discussion Issue is waiting for discussions to resolve type: q and a Question and answer about some feature or user question
Projects
None yet
Development

No branches or pull requests

2 participants