From 62a7d713a7b33bfe1d4f71cdbeb640d0b24cae69 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 6 Jan 2019 17:38:27 -0500 Subject: [PATCH] Fix internal error on xrefs into unrolled functions, bug1387. --- Changes | 2 ++ internals.pod | 8 ++++---- src/V3Ast.h | 8 +++++--- src/V3AstNodes.h | 2 ++ src/V3ClkGater.cpp | 4 ++++ src/V3Combine.cpp | 4 ++++ src/V3Depth.cpp | 6 +++++- src/V3DepthBlock.cpp | 6 +++++- src/V3Expand.cpp | 4 ++++ src/V3Premit.cpp | 8 ++++++-- src/V3SplitAs.cpp | 4 ++++ src/V3Task.cpp | 4 ++++ src/V3Unknown.cpp | 8 ++++---- test_regress/t/t_func_unit.pl | 20 ++++++++++++++++++++ test_regress/t/t_func_unit.v | 23 +++++++++++++++++++++++ 15 files changed, 96 insertions(+), 15 deletions(-) create mode 100755 test_regress/t/t_func_unit.pl create mode 100644 test_regress/t/t_func_unit.v diff --git a/Changes b/Changes index 45920c2d5..1adee83c5 100644 --- a/Changes +++ b/Changes @@ -19,6 +19,8 @@ The contributors that suggested a given feature are shown in []. Thanks! **** Fix uninitialized data in verFiles and unroller, bug1385. bug1386. [Al Grant] +**** Fix internal error on xrefs into unrolled functions, bug1387. [Al Grant] + * Verilator 4.008 2018-12-01 diff --git a/internals.pod b/internals.pod index ecbeddfb4..af3e847b3 100644 --- a/internals.pod +++ b/internals.pod @@ -452,10 +452,10 @@ implementation is not found, the system will look in turn for overloaded implementations up the inheritance hierarchy. For example calling C on C will look in turn for: - void visit (AstIf* nodep) - void visit (AstNodeIf* nodep) - void visit (AstNodeStmt* nodep) - void visit (AstNode* nodep) + void visit(AstIf* nodep) + void visit(AstNodeIf* nodep) + void visit(AstNodeStmt* nodep) + void visit(AstNode* nodep) There are three ways data is passed between visitor functions. diff --git a/src/V3Ast.h b/src/V3Ast.h index aa852f9f6..36664bda4 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1642,6 +1642,7 @@ public: : AstNode(fl) {} ASTNODE_BASE_FUNCS(NodeStmt) // METHODS + virtual bool isStatement() const { return true; } // Really a statement virtual void addNextStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here virtual void addBeforeStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here }; @@ -2067,8 +2068,9 @@ public: bool pure() const { return m_pure; } }; -class AstNodeFTaskRef : public AstNode { +class AstNodeFTaskRef : public AstNodeStmt { // A reference to a task (or function) + // Functions are not statements, while tasks are. AstNodeStmt needs isStatement() to deal. private: AstNodeFTask* m_taskp; // [AfterLink] Pointer to task referenced string m_name; // Name of variable @@ -2077,12 +2079,12 @@ private: AstPackage* m_packagep; // Package hierarchy public: AstNodeFTaskRef(FileLine* fl, AstNode* namep, AstNode* pinsp) - : AstNode(fl) + : AstNodeStmt(fl) , m_taskp(NULL), m_packagep(NULL) { setOp1p(namep); addNOp2p(pinsp); } AstNodeFTaskRef(FileLine* fl, const string& name, AstNode* pinsp) - : AstNode(fl) + : AstNodeStmt(fl) , m_taskp(NULL), m_name(name), m_packagep(NULL) { addNOp2p(pinsp); } diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 642ccb9e4..326a5fc4e 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -2026,6 +2026,7 @@ public: AstTaskRef(FileLine* fl, const string& name, AstNode* pinsp) :AstNodeFTaskRef(fl, name, pinsp) {} ASTNODE_NODE_FUNCS(TaskRef) + virtual bool isStatement() const { return true; } // A statement, unlike FuncRef }; class AstFuncRef : public AstNodeFTaskRef { @@ -2036,6 +2037,7 @@ public: AstFuncRef(FileLine* fl, const string& name, AstNode* pinsp) :AstNodeFTaskRef(fl, name, pinsp) {} ASTNODE_NODE_FUNCS(FuncRef) + virtual bool isStatement() const { return false; } // Not a statement, unlike TaskRef virtual bool hasDType() const { return true; } }; diff --git a/src/V3ClkGater.cpp b/src/V3ClkGater.cpp index b31851c19..7b8256f3c 100644 --- a/src/V3ClkGater.cpp +++ b/src/V3ClkGater.cpp @@ -273,6 +273,10 @@ class GaterBodyVisitor : public GaterBaseVisitor { // (We may get empty IFs but the constant propagater will rip them up for us) virtual void visit(AstNodeStmt* nodep) { + if (!nodep->isStatement()) { + iterateChildren(nodep); + return; + } uint32_t oldstate = m_state; // Find if children want to delete this or not. // Note children may bicker, and want to both keep and delete (branches on a if) diff --git a/src/V3Combine.cpp b/src/V3Combine.cpp index 4efeb2476..39e9fbdf3 100644 --- a/src/V3Combine.cpp +++ b/src/V3Combine.cpp @@ -433,6 +433,10 @@ private: m_funcp = NULL; } virtual void visit(AstNodeStmt* nodep) { + if (!nodep->isStatement()) { + iterateChildren(nodep); + return; + } if (m_state == STATE_HASH && m_funcp) { hashStatement(nodep); } diff --git a/src/V3Depth.cpp b/src/V3Depth.cpp index 56af83979..943312c48 100644 --- a/src/V3Depth.cpp +++ b/src/V3Depth.cpp @@ -102,7 +102,11 @@ private: m_stmtp = NULL; } virtual void visit(AstNodeStmt* nodep) { - visitStmt(nodep); + if (!nodep->isStatement()) { + iterateChildren(nodep); + } else { + visitStmt(nodep); + } } // Operators virtual void visit(AstNodeTermop* nodep) { diff --git a/src/V3DepthBlock.cpp b/src/V3DepthBlock.cpp index 666c258cb..5dcaa954a 100644 --- a/src/V3DepthBlock.cpp +++ b/src/V3DepthBlock.cpp @@ -107,7 +107,11 @@ private: m_depth--; } virtual void visit(AstNodeStmt* nodep) { - visitStmt(nodep); + if (!nodep->isStatement()) { + iterateChildren(nodep); + } else { + visitStmt(nodep); + } } virtual void visit(AstNodeMath* nodep) {} // Accelerate diff --git a/src/V3Expand.cpp b/src/V3Expand.cpp index 7550cfbe4..ef0d8ef58 100644 --- a/src/V3Expand.cpp +++ b/src/V3Expand.cpp @@ -871,6 +871,10 @@ private: virtual void visit(AstNodeStmt* nodep) { if (nodep->user1SetOnce()) return; // Process once + if (!nodep->isStatement()) { + iterateChildren(nodep); + return; + } m_stmtp = nodep; iterateChildren(nodep); m_stmtp = NULL; diff --git a/src/V3Premit.cpp b/src/V3Premit.cpp index 081f17a20..fb76c9fd6 100644 --- a/src/V3Premit.cpp +++ b/src/V3Premit.cpp @@ -241,8 +241,12 @@ private: m_stmtp = NULL; } virtual void visit(AstNodeStmt* nodep) { - UINFO(4," STMT "<isStatement()) { + iterateChildren(nodep); + return; + } + UINFO(4," STMT "<isStatement()) { + iterateChildren(nodep); + return; + } UINFO(6," CL STMT "<v3fatalSrc("For statements should have been converted to while statements in V3Begin.cpp"); } virtual void visit(AstNodeStmt* nodep) { + if (!nodep->isStatement()) { + iterateChildren(nodep); + return; + } m_insMode = IM_BEFORE; m_insStmtp = nodep; iterateChildren(nodep); diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index a44178503..7e02a8456 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -135,10 +135,10 @@ private: new AstVarRef(fl, varp, false)))), NULL); newp->branchPred(AstBranchPred::BP_LIKELY); - if (debug()>=9) newp->dumpTree(cout," _new: "); - abovep->addNextStmt(newp,abovep); - prep->user2p(newp); // Save so we may LogAnd it next time - } + if (debug()>=9) newp->dumpTree(cout," _new: "); + abovep->addNextStmt(newp, abovep); + prep->user2p(newp); // Save so we may LogAnd it next time + } } // VISITORS diff --git a/test_regress/t/t_func_unit.pl b/test_regress/t/t_func_unit.pl new file mode 100755 index 000000000..6b3b15be5 --- /dev/null +++ b/test_regress/t/t_func_unit.pl @@ -0,0 +1,20 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2019 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. + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_func_unit.v b/test_regress/t/t_func_unit.v new file mode 100644 index 000000000..14d533f56 --- /dev/null +++ b/test_regress/t/t_func_unit.v @@ -0,0 +1,23 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2019 by Wilson Snyder. + +task tsk(output fo); + assign fo = 1'b0; +endtask + +module t (/*AUTOARG*/ + // Outputs + to + ); + output to[2:0]; + + integer i = 0; + + initial begin + tsk(to[i]); + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule