From 3e07b14ffc3bb95a81eb85f2d7162d168b221e1b Mon Sep 17 00:00:00 2001 From: Krzysztof Sychla Date: Thu, 27 Mar 2025 15:23:58 +0100 Subject: [PATCH] Add range specifier support in setuphold Signed-off-by: Krzysztof Sychla --- src/V3Width.cpp | 37 ++++++++++++++++++++++++++++-------- src/verilog.y | 14 +++++++------- test_regress/t/t_setuphold.v | 10 ++++++++++ 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/V3Width.cpp b/src/V3Width.cpp index efab1ae7d..9dc680799 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1382,17 +1382,38 @@ class WidthVisitor final : public VNVisitor { AstAssignW* newp = nullptr; - if (nodep->delrefp() != nullptr) { - AstNodeVarRef* lhsp = VN_AS(nodep->delrefp()->cloneTreePure(false), VarRef); - lhsp->access(VAccess::WRITE); - AstNodeVarRef* rhsp = VN_AS(nodep->refevp()->cloneTreePure(false), VarRef); + if (nodep->delrefp()) { + AstNodeExpr* const lhsp = nodep->delrefp()->cloneTreePure(false); + AstNodeExpr* const rhsp = nodep->refevp()->cloneTreePure(false); + if (AstNodeVarRef* varRefp = VN_CAST(lhsp, NodeVarRef)) { + varRefp->access(VAccess::WRITE); + varRefp->varp()->setForcedByCode(); + } + + if (AstNodePreSel* selp = VN_CAST(lhsp, NodePreSel)) { + if (AstNodeVarRef* varRefp = VN_CAST(selp->fromp(), NodeVarRef)) { + varRefp->access(VAccess::WRITE); + varRefp->varp()->setForcedByCode(); + } + } + newp = new AstAssignW{flp, lhsp, rhsp}; } - if (nodep->deldatap() != nullptr) { - AstNodeVarRef* lhsp = VN_AS(nodep->deldatap()->cloneTreePure(false), VarRef); - lhsp->access(VAccess::WRITE); - AstNodeVarRef* rhsp = VN_AS(nodep->dataevp()->cloneTreePure(false), VarRef); + if (nodep->deldatap()) { + AstNodeExpr* const lhsp = nodep->deldatap()->cloneTreePure(false); + AstNodeExpr* const rhsp = nodep->dataevp()->cloneTreePure(false); + if (AstNodeVarRef* varRefp = VN_CAST(lhsp, NodeVarRef)) { + varRefp->access(VAccess::WRITE); + varRefp->varp()->setForcedByCode(); + } + + if (AstNodePreSel* selp = VN_CAST(lhsp, NodePreSel)) { + if (AstNodeVarRef* varRefp = VN_CAST(selp->fromp(), NodeVarRef)) { + varRefp->access(VAccess::WRITE); + varRefp->varp()->setForcedByCode(); + } + } if (newp == nullptr) { newp = new AstAssignW{flp, lhsp, rhsp}; diff --git a/src/verilog.y b/src/verilog.y index 46c25ff7c..28832375d 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -5792,8 +5792,8 @@ setuphold_timing_check: // ==IEEE: $setuphold_timing_check | yD_SETUPHOLD '(' timing_check_event ',' timing_check_event ',' expr ',' expr ',' idAnyE ')' ';' { $$ = nullptr; } | yD_SETUPHOLD '(' timing_check_event ',' timing_check_event ',' expr ',' expr ',' idAnyE ',' minTypMaxE ')' ';' { $$ = nullptr; } | yD_SETUPHOLD '(' timing_check_event ',' timing_check_event ',' expr ',' expr ',' idAnyE ',' minTypMaxE ',' minTypMaxE ')' ';' { $$ = nullptr; } - | yD_SETUPHOLD '(' timing_check_event ',' timing_check_event ',' expr ',' expr ',' idAnyE ',' minTypMaxE ',' minTypMaxE ',' terminal_identifierE ')' ';' { $$ = new AstSetuphold{$1, $3, $5, $17}; } - | yD_SETUPHOLD '(' timing_check_event ',' timing_check_event ',' expr ',' expr ',' idAnyE ',' minTypMaxE ',' minTypMaxE ',' terminal_identifierE ',' terminal_identifierE ')' ';' { $$ = new AstSetuphold{$1, $3, $5, $17, $19}; } + | yD_SETUPHOLD '(' timing_check_event ',' timing_check_event ',' expr ',' expr ',' idAnyE ',' minTypMaxE ',' minTypMaxE ',' delayed_referenceE ')' ';' { $$ = new AstSetuphold{$1, $3, $5, $17}; } + | yD_SETUPHOLD '(' timing_check_event ',' timing_check_event ',' expr ',' expr ',' idAnyE ',' minTypMaxE ',' minTypMaxE ',' delayed_referenceE ',' delayed_referenceE ')' ';' { $$ = new AstSetuphold{$1, $3, $5, $17, $19}; } ; timing_check_event: // ==IEEE: $timing_check_event @@ -5807,13 +5807,13 @@ timing_check_event: // ==IEEE: $timing_check_event | yEDGE terminal_identifier yP_ANDANDAND expr { $$ = $2; } ; -terminal_identifier: - id { $$ = new AstParseRef{$1, VParseRefExp::PX_TEXT, *$1, nullptr, nullptr}; } +delayed_referenceE: + /*empty*/ { $$ = nullptr; } + | terminal_identifier { $$ = $1; } ; -terminal_identifierE: - /*empty*/ { $$ = nullptr; } - | terminal_identifier { $$ = $1; } +terminal_identifier: + idArrayed { $$ = $1; } ; idAnyE: diff --git a/test_regress/t/t_setuphold.v b/test_regress/t/t_setuphold.v index 6ffc59702..451ae4b44 100644 --- a/test_regress/t/t_setuphold.v +++ b/test_regress/t/t_setuphold.v @@ -15,6 +15,10 @@ module t (/*AUTOARG*/ wire delayed_CLK; wire delayed_D; reg notifier; + wire [1:0] BL_X = 2'b11; + wire [5:0] BL_X2; + wire BL_0; + wire [3:0] BL_1 = 4'b1100; logic[3:0] sh1 = 1; logic[3:0] sh2 = 2; @@ -27,13 +31,19 @@ module t (/*AUTOARG*/ $setuphold (posedge clk, negedge d, 0, 0, notifier,,, delayed_CLK, delayed_D); $setuphold (posedge sh1, negedge sh3, 0, 0, notifier,,, sh2, sh4); $setuphold (posedge clk, negedge d, 0, 0); + $setuphold (posedge clk, negedge d, (0:0:0), (0:0:0)); $setuphold (posedge clk, negedge d, 0, 0,,,,,); + $setuphold (posedge clk &&& sh1, BL_X[0], 0, 0, ,,,delayed_CLK, BL_0); + $setuphold (posedge clk &&& sh1, BL_1, 0, 0, ,,,delayed_CLK, BL_X2[4:1]); endspecify initial begin if (sh1 != sh2 || sh3 != sh4) begin $stop; end + if (BL_0 != BL_X[0] || BL_1 != BL_X2[4:1]) begin + $stop; + end end always @(posedge clk) begin