Assign unique names for blocks in do..while loop (#4019)

This commit is contained in:
Ryszard Rozak 2023-03-14 09:54:43 +01:00 committed by GitHub
parent 2c62714a30
commit 1d0a06438c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 101 additions and 15 deletions

View File

@ -2651,17 +2651,13 @@ public:
bool addNewline() const { return displayType().addNewline(); }
};
class AstDoWhile final : public AstNodeStmt {
// @astgen op1 := precondsp : List[AstNode]
// @astgen op2 := condp : AstNodeExpr
// @astgen op3 := stmtsp : List[AstNode]
// @astgen op4 := incsp : List[AstNode]
// @astgen op1 := condp : AstNodeExpr
// @astgen op2 := stmtsp : List[AstNode]
public:
AstDoWhile(FileLine* fl, AstNodeExpr* conditionp, AstNode* stmtsp = nullptr,
AstNode* incsp = nullptr)
AstDoWhile(FileLine* fl, AstNodeExpr* conditionp, AstNode* stmtsp = nullptr)
: ASTGEN_SUPER_DoWhile(fl) {
condp(conditionp);
addStmtsp(stmtsp);
addIncsp(incsp);
}
ASTGEN_MEMBERS_AstDoWhile;
bool isGateOptimizable() const override { return false; }

View File

@ -128,6 +128,19 @@ private:
return labelp;
}
}
void addPrefixToBlocksRecurse(AstNode* nodep) {
// Add do_while_ prefix to blocks
// Used to not have blocks with duplicated names
if (AstBegin* const beginp = VN_CAST(nodep, Begin)) {
if (beginp->name() != "") beginp->name("__Vdo_while_" + beginp->name());
}
if (nodep->op1p()) addPrefixToBlocksRecurse(nodep->op1p());
if (nodep->op2p()) addPrefixToBlocksRecurse(nodep->op2p());
if (nodep->op3p()) addPrefixToBlocksRecurse(nodep->op3p());
if (nodep->op4p()) addPrefixToBlocksRecurse(nodep->op4p());
if (nodep->nextp()) addPrefixToBlocksRecurse(nodep->nextp());
}
// VISITORS
void visit(AstNodeModule* nodep) override {
@ -200,23 +213,21 @@ private:
void visit(AstDoWhile* nodep) override {
// It is converted to AstWhile in this visit method
VL_RESTORER(m_loopp);
VL_RESTORER(m_loopInc);
{
m_loopp = nodep;
m_loopInc = false;
iterateAndNextNull(nodep->precondsp());
iterateAndNextNull(nodep->condp());
iterateAndNextNull(nodep->stmtsp());
m_loopInc = true;
iterateAndNextNull(nodep->incsp());
}
AstNodeExpr* const condp = nodep->condp() ? nodep->condp()->unlinkFrBack() : nullptr;
AstNode* const bodyp = nodep->stmtsp() ? nodep->stmtsp()->unlinkFrBack() : nullptr;
AstNode* const incsp = nodep->incsp() ? nodep->incsp()->unlinkFrBack() : nullptr;
AstWhile* const whilep = new AstWhile{nodep->fileline(), condp, bodyp, incsp};
AstWhile* const whilep = new AstWhile{nodep->fileline(), condp, bodyp};
nodep->replaceWith(whilep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
if (bodyp) whilep->addHereThisAsNext(bodyp->cloneTree(false));
if (bodyp) {
AstNode* const copiedBodyp = bodyp->cloneTree(false);
addPrefixToBlocksRecurse(copiedBodyp);
whilep->addHereThisAsNext(copiedBodyp);
}
}
void visit(AstForeach* nodep) override {
VL_RESTORER(m_loopp);

21
test_regress/t/t_do_while.pl Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2020 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator => 1);
compile(
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,58 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2023 by Antmicro Ltd.
// SPDX-License-Identifier: CC0-1.0
function automatic int get_1;
int a = 0;
do begin
int x = 1;
a += x;
end while (a < 0);
return a;
endfunction
module t (/*AUTOARG*/);
int a;
initial begin
if (get_1() != 1) $stop;
a = 0;
do begin
int x = 1;
a += x;
if (a == 1) begin
a = 2;
end
end while (a < 0);
if (a != 2) $stop;
a = 1;
do begin
if (a == 1) begin
a = 2;
end
if (a == 2) begin
a = 3;
end
end while (a < 0);
if (a != 3) $stop;
a = 1;
do begin
if (a == 1) begin
do begin
a++;
end while (a < 5);
end
if (a == 2) begin
a = 3;
end
end while (a < 0);
if (a != 5) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule