Merge from master

This commit is contained in:
Wilson Snyder 2018-08-22 17:51:31 -04:00
commit 4d034d774d
5 changed files with 64 additions and 6 deletions

View File

@ -28,13 +28,15 @@ The contributors that suggested a given feature are shown in []. Thanks!
**** Add OBJCACHE envvar support to examples and generated Makefiles. **** Add OBJCACHE envvar support to examples and generated Makefiles.
**** Change MODDUP errors to warnings, msg2588. [Marshal Qiao]
**** Fix define argument stringification (`"), broke since 3.914. [Joe DErrico] **** Fix define argument stringification (`"), broke since 3.914. [Joe DErrico]
**** Fix to ignore Unicode UTF-8 BOM sequences, msg2576. [HyungKi Jeong] **** Fix to ignore Unicode UTF-8 BOM sequences, msg2576. [HyungKi Jeong]
**** Fix std:: build error, bug1322. **** Fix std:: build error, bug1322.
**** Change MODDUP errors to warnings, msg2588. [Marshal Qiao] **** Fix function inlining inside certain while loops, bug1330. [Julien Margetts]
* Verilator 3.924 2018-06-12 * Verilator 3.924 2018-06-12

View File

@ -336,7 +336,7 @@ public:
virtual void visit(AstNodeReadWriteMem* nodep) { virtual void visit(AstNodeReadWriteMem* nodep) {
puts(nodep->cFuncPrefixp()); puts(nodep->cFuncPrefixp());
emitIQW(nodep->filenamep()); emitIQW(nodep->filenamep());
puts(" ("); // We take a void* rather than emitIQW(nodep->memp()); puts("("); // We take a void* rather than emitIQW(nodep->memp());
puts(nodep->isHex()?"true":"false"); puts(nodep->isHex()?"true":"false");
putbs(","); putbs(",");
puts(cvtToStr(nodep->memp()->widthMin())); // Need real storage width puts(cvtToStr(nodep->memp()->widthMin())); // Need real storage width

View File

@ -1079,10 +1079,12 @@ private:
m_insMode = prevInsMode; m_insMode = prevInsMode;
m_insStmtp = prevInsStmtp; m_insStmtp = prevInsStmtp;
} }
void insertBeforeStmt(AstNode* nodep, AstNode* newp) { AstNode* insertBeforeStmt(AstNode* nodep, AstNode* newp) {
// Return node that must be visited, if any
// See also AstNode::addBeforeStmt; this predates that function // See also AstNode::addBeforeStmt; this predates that function
if (debug()>=9) { nodep->dumpTree(cout,"-newstmt:"); } if (debug()>=9) { nodep->dumpTree(cout,"-newstmt:"); }
if (!m_insStmtp) nodep->v3fatalSrc("Function not underneath a statement"); if (!m_insStmtp) nodep->v3fatalSrc("Function not underneath a statement");
AstNode* visitp = NULL;
if (m_insMode == IM_BEFORE) { if (m_insMode == IM_BEFORE) {
// Add the whole thing before insertAt // Add the whole thing before insertAt
UINFO(5," IM_Before "<<m_insStmtp<<endl); UINFO(5," IM_Before "<<m_insStmtp<<endl);
@ -1090,20 +1092,22 @@ private:
m_insStmtp->addHereThisAsNext(newp); m_insStmtp->addHereThisAsNext(newp);
} }
else if (m_insMode == IM_AFTER) { else if (m_insMode == IM_AFTER) {
UINFO(5," IM_After "<<m_insStmtp); UINFO(5," IM_After "<<m_insStmtp<<endl);
m_insStmtp->addNextHere(newp); m_insStmtp->addNextHere(newp);
} }
else if (m_insMode == IM_WHILE_PRECOND) { else if (m_insMode == IM_WHILE_PRECOND) {
UINFO(5," IM_While_Precond "<<m_insStmtp); UINFO(5," IM_While_Precond "<<m_insStmtp<<endl);
AstWhile* whilep = VN_CAST(m_insStmtp, While); AstWhile* whilep = VN_CAST(m_insStmtp, While);
if (!whilep) nodep->v3fatalSrc("Insert should be under WHILE"); if (!whilep) nodep->v3fatalSrc("Insert should be under WHILE");
whilep->addPrecondsp(newp); whilep->addPrecondsp(newp);
visitp = newp;
} }
else { else {
nodep->v3fatalSrc("Unknown InsertMode"); nodep->v3fatalSrc("Unknown InsertMode");
} }
m_insMode = IM_AFTER; m_insMode = IM_AFTER;
m_insStmtp = newp; m_insStmtp = newp;
return visitp;
} }
// VISITORS // VISITORS
@ -1148,12 +1152,13 @@ private:
beginp = createInlinedFTask(nodep, namePrefix, outvscp); beginp = createInlinedFTask(nodep, namePrefix, outvscp);
} }
// Replace the ref // Replace the ref
AstNode* visitp = NULL;
if (VN_IS(nodep, FuncRef)) { if (VN_IS(nodep, FuncRef)) {
if (!nodep->taskp()->isFunction()) nodep->v3fatalSrc("func reference to non-function"); if (!nodep->taskp()->isFunction()) nodep->v3fatalSrc("func reference to non-function");
AstVarRef* outrefp = new AstVarRef (nodep->fileline(), outvscp, false); AstVarRef* outrefp = new AstVarRef (nodep->fileline(), outvscp, false);
nodep->replaceWith(outrefp); nodep->replaceWith(outrefp);
// Insert new statements // Insert new statements
insertBeforeStmt(nodep, beginp); visitp = insertBeforeStmt(nodep, beginp);
} else { } else {
// outvscp maybe non-NULL if calling a function in a taskref, // outvscp maybe non-NULL if calling a function in a taskref,
// but if so we want to simply ignore the function result // but if so we want to simply ignore the function result
@ -1162,6 +1167,8 @@ private:
// Cleanup // Cleanup
nodep->deleteTree(); VL_DANGLING(nodep); nodep->deleteTree(); VL_DANGLING(nodep);
UINFO(4," FTask REF Done.\n"); UINFO(4," FTask REF Done.\n");
// Visit nodes that normal iteration won't find
if (visitp) iterateAndNextNull(visitp);
} }
virtual void visit(AstNodeFTask* nodep) { virtual void visit(AstNodeFTask* nodep) {
UINFO(4," Inline "<<nodep<<endl); UINFO(4," Inline "<<nodep<<endl);

17
test_regress/t/t_func_while.pl Executable file
View File

@ -0,0 +1,17 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 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(
verilator_flags2 => ["--trace"],
);
ok(1);
1;

View File

@ -0,0 +1,32 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2018 by Julien Margetts.
module t #(parameter sz = 4096)
(
input wire clk,
output reg [tdw(sz)-1:0] data
);
// bug1330
function integer clog2(input integer value);
integer tmp;
tmp = value-1;
clog2 = 0;
for (clog2=0; (tmp>0) && (clog2<32); clog2=clog2+1)
tmp = tmp>>1;
endfunction
function integer tdw(input integer sz);
tdw = clog2(sz);
endfunction
integer b;
always @(posedge clk)
for (b=0; b<tdw(sz); b=b+1)
if ((data[b] === 1'bx))
$display("WARNING: %1t Writing X's to tag RAM [%m]", $time);
endmodule