From 9e15d4e80c2b7bd10e42e51f9cfde856e1dbf1b9 Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Thu, 4 Apr 2024 15:33:10 +0300 Subject: [PATCH] Fix errors on non blocking assignments with RHS delays inside always_ff (#933) --- source/ast/Statements.cpp | 8 +++--- tests/unittests/ast/MemberTests.cpp | 42 +++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/source/ast/Statements.cpp b/source/ast/Statements.cpp index 77fd407e5..839fc39eb 100644 --- a/source/ast/Statements.cpp +++ b/source/ast/Statements.cpp @@ -2281,12 +2281,14 @@ Statement& ExpressionStatement::fromSyntax(Compilation& compilation, ok = true; break; } - case ExpressionKind::Assignment: - if (auto timing = expr.as().timingControl) - stmtCtx.observeTiming(*timing); + case ExpressionKind::Assignment: { + const AssignmentExpression& ae = expr.as(); + if (ae.isBlocking() && ae.timingControl) + stmtCtx.observeTiming(*ae.timingControl); ok = true; break; + } case ExpressionKind::NewClass: ok = true; break; diff --git a/tests/unittests/ast/MemberTests.cpp b/tests/unittests/ast/MemberTests.cpp index 3a9c0a56d..9d9467fc9 100644 --- a/tests/unittests/ast/MemberTests.cpp +++ b/tests/unittests/ast/MemberTests.cpp @@ -1723,6 +1723,48 @@ endmodule CHECK(diags[5].code == diag::TimingInFuncNotAllowed); } +TEST_CASE("always_ff timing (pass)") { + auto tree = SyntaxTree::fromText(R"( +module x; +reg a; +wire clk; +always_ff @(posedge clk) + a <= #1 1'b0; +endmodule +)"); + + Compilation compilation; + compilation.addSyntaxTree(tree); + + auto& diags = compilation.getAllDiagnostics(); + REQUIRE(diags.size() == 0); +} + +TEST_CASE("always_ff timing (fail)") { + auto tree = SyntaxTree::fromText(R"( +module x1; +reg a; +wire clk; +always_ff @(posedge clk) + #1 a <= 1'b0; +endmodule +module x2; +reg a; +wire clk; +always_ff @(posedge clk) + a = #1 1'b0; +endmodule +)"); + + Compilation compilation; + compilation.addSyntaxTree(tree); + + auto& diags = compilation.getAllDiagnostics(); + REQUIRE(diags.size() == 2); + CHECK(diags[0].code == diag::BlockingInAlwaysFF); + CHECK(diags[1].code == diag::BlockingInAlwaysFF); +} + TEST_CASE("always_comb drivers within nested functions") { auto tree = SyntaxTree::fromText(R"( module m;