Add stack trace when can't optimize function, bug1158.
Signed-off-by: Wilson Snyder <wsnyder@wsnyder.org>
This commit is contained in:
parent
706a7802cc
commit
54bc8608e3
2
Changes
2
Changes
|
|
@ -13,6 +13,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
||||||
|
|
||||||
**** Fix non-arrayed cells with interface arrays, bug1153. [John Stevenson]
|
**** Fix non-arrayed cells with interface arrays, bug1153. [John Stevenson]
|
||||||
|
|
||||||
|
**** Add stack trace when can't optimize function, bug1158. [Todd Strader]
|
||||||
|
|
||||||
**** Add warning on mis-sized literal, bug1156. [Todd Strader]
|
**** Add warning on mis-sized literal, bug1156. [Todd Strader]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,12 +44,25 @@
|
||||||
#include "V3Task.h"
|
#include "V3Task.h"
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Simulate class functions
|
// Simulate class functions
|
||||||
|
|
||||||
|
class SimulateStackNode {
|
||||||
|
public:
|
||||||
|
// MEMBERS
|
||||||
|
AstFuncRef* m_funcp;
|
||||||
|
V3TaskConnects* m_tconnects;
|
||||||
|
// CONSTRUCTORS
|
||||||
|
SimulateStackNode(AstFuncRef* funcp, V3TaskConnects* tconnects):
|
||||||
|
m_funcp(funcp),
|
||||||
|
m_tconnects(tconnects) {}
|
||||||
|
~SimulateStackNode() {}
|
||||||
|
};
|
||||||
|
|
||||||
class SimulateVisitor : public AstNVisitor {
|
class SimulateVisitor : public AstNVisitor {
|
||||||
// Simulate a node tree, returning value of variables
|
// Simulate a node tree, returning value of variables
|
||||||
// Two major operating modes:
|
// Two major operating modes:
|
||||||
|
|
@ -90,6 +103,7 @@ private:
|
||||||
// Simulating:
|
// Simulating:
|
||||||
deque<V3Number*> m_numFreeps; ///< List of all numbers free and not in use
|
deque<V3Number*> m_numFreeps; ///< List of all numbers free and not in use
|
||||||
deque<V3Number*> m_numAllps; ///< List of all numbers free and in use
|
deque<V3Number*> m_numAllps; ///< List of all numbers free and in use
|
||||||
|
deque<SimulateStackNode*> m_callStack; ///< Call stack for verbose error messages
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
// V3Numbers that represents strings are a bit special and the API for V3Number does not allow changing them.
|
// V3Numbers that represents strings are a bit special and the API for V3Number does not allow changing them.
|
||||||
|
|
@ -103,6 +117,54 @@ private:
|
||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Potentially very slow, intended for debugging
|
||||||
|
string prettyNumber(V3Number* nump, AstNodeDType* dtypep) {
|
||||||
|
if (AstRefDType* refdtypep = dtypep->castRefDType()) {
|
||||||
|
dtypep = refdtypep->skipRefp();
|
||||||
|
}
|
||||||
|
if (AstStructDType* stp = dtypep->castStructDType()) {
|
||||||
|
if (stp->packed()) {
|
||||||
|
ostringstream out;
|
||||||
|
out<<"'{";
|
||||||
|
for (AstMemberDType* itemp = stp->membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) {
|
||||||
|
int width = itemp->width();
|
||||||
|
int lsb = itemp->lsb();
|
||||||
|
int msb = lsb + width - 1;
|
||||||
|
V3Number fieldNum = V3Number(nump->fileline(), width);
|
||||||
|
fieldNum.opSel(*nump, msb, lsb);
|
||||||
|
out<<itemp->name()<<": ";
|
||||||
|
if (AstNodeDType * childTypep = itemp->subDTypep()) {
|
||||||
|
out<<prettyNumber(&fieldNum, childTypep);
|
||||||
|
} else {
|
||||||
|
out<<fieldNum;
|
||||||
|
}
|
||||||
|
if (itemp->nextp()) out<<", ";
|
||||||
|
}
|
||||||
|
out<<"}";
|
||||||
|
return out.str();
|
||||||
|
}
|
||||||
|
} else if (AstPackArrayDType * arrayp = dtypep->castPackArrayDType()) {
|
||||||
|
if (AstNodeDType * childTypep = arrayp->subDTypep()) {
|
||||||
|
ostringstream out;
|
||||||
|
out<<"[";
|
||||||
|
int arrayElements = arrayp->elementsConst();
|
||||||
|
for (int element = 0; element < arrayElements; ++element) {
|
||||||
|
int width = childTypep->width();
|
||||||
|
int lsb = width * element;
|
||||||
|
int msb = lsb + width - 1;
|
||||||
|
V3Number fieldNum = V3Number(nump->fileline(), width);
|
||||||
|
fieldNum.opSel(*nump, msb, lsb);
|
||||||
|
int arrayElem = arrayp->lsb() + element;
|
||||||
|
out<<arrayElem<<" = "<<prettyNumber(&fieldNum, childTypep);
|
||||||
|
if (element < arrayElements - 1) out<<", ";
|
||||||
|
}
|
||||||
|
out<<"]";
|
||||||
|
return out.str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nump->ascii();
|
||||||
|
}
|
||||||
|
|
||||||
// Checking METHODS
|
// Checking METHODS
|
||||||
public:
|
public:
|
||||||
/// Call other-this function on all new *non-constant* var references
|
/// Call other-this function on all new *non-constant* var references
|
||||||
|
|
@ -119,6 +181,19 @@ public:
|
||||||
cout<<endl;
|
cout<<endl;
|
||||||
}
|
}
|
||||||
m_whyNotOptimizable = why;
|
m_whyNotOptimizable = why;
|
||||||
|
ostringstream stack;
|
||||||
|
for (deque<SimulateStackNode*>::iterator it=m_callStack.begin(); it !=m_callStack.end(); ++it) {
|
||||||
|
AstFuncRef* funcp = (*it)->m_funcp;
|
||||||
|
stack<<"\nCalled from:\n"<<funcp->fileline()<<" "<<funcp->prettyName()<<"() with parameters:";
|
||||||
|
V3TaskConnects* tconnects = (*it)->m_tconnects;
|
||||||
|
for (V3TaskConnects::iterator conIt = tconnects->begin(); conIt != tconnects->end(); ++conIt) {
|
||||||
|
AstVar* portp = conIt->first;
|
||||||
|
AstNode* pinp = conIt->second->exprp();
|
||||||
|
AstNodeDType* dtypep = pinp->dtypep();
|
||||||
|
stack<<"\n "<<portp->prettyName()<<" = "<<prettyNumber(fetchNumber(pinp), dtypep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_whyNotOptimizable += stack.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inline bool optimizable() const { return m_whyNotNodep==NULL; }
|
inline bool optimizable() const { return m_whyNotNodep==NULL; }
|
||||||
|
|
@ -718,8 +793,11 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SimulateStackNode stackNode(nodep, &tconnects);
|
||||||
|
m_callStack.push_front(&stackNode);
|
||||||
// Evaluate the function
|
// Evaluate the function
|
||||||
funcp->accept(*this);
|
funcp->accept(*this);
|
||||||
|
m_callStack.pop_front();
|
||||||
if (!m_checkOnly && optimizable()) {
|
if (!m_checkOnly && optimizable()) {
|
||||||
// Grab return value from output variable (if it's a function)
|
// Grab return value from output variable (if it's a function)
|
||||||
if (!funcp->fvarp()) nodep->v3fatalSrc("Function reference points at non-function");
|
if (!funcp->fvarp()) nodep->v3fatalSrc("Function reference points at non-function");
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2017 by Todd Strader. 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.
|
||||||
|
#
|
||||||
|
compile (
|
||||||
|
v_flags2 => ["--lint-only"],
|
||||||
|
fails=>1,
|
||||||
|
expect=>
|
||||||
|
q{%Warning-USERFATAL: f_add = 15
|
||||||
|
%Warning-USERFATAL: Use "/* verilator lint_off USERFATAL */" and lint_on around source to disable this message.
|
||||||
|
%Error: t/t_func_const2_bad.v:10: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_add2'
|
||||||
|
%Error: t/t_func_const2_bad.v:21: ... Location of non-constant STOP: $stop executed during function constification; maybe indicates assertion firing
|
||||||
|
Called from:
|
||||||
|
t/t_func_const2_bad.v:26: f_add() with parameters:
|
||||||
|
a = 32'h7
|
||||||
|
b = 32'h8
|
||||||
|
Called from:
|
||||||
|
t/t_func_const2_bad.v:10: f_add2() with parameters:
|
||||||
|
a = ?32?sh7
|
||||||
|
b = ?32?sh8
|
||||||
|
c = ?32?sh9
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2017 by Todd Strader.
|
||||||
|
|
||||||
|
module t;
|
||||||
|
|
||||||
|
localparam P6 = f_add(5, 1);
|
||||||
|
localparam P14 = f_add2(2, 3, f_add(4, 5));
|
||||||
|
localparam P24 = f_add2(7, 8, 9);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
// Should never get here
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
function integer f_add(input [31:0] a, input [31:0] b);
|
||||||
|
f_add = a+b;
|
||||||
|
if (f_add == 15)
|
||||||
|
$fatal(2, "f_add = 15");
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
// Speced ok: function called from function
|
||||||
|
function integer f_add2(input [31:0] a, input [31:0] b, input [31:0] c);
|
||||||
|
f_add2 = f_add(a,b)+c;
|
||||||
|
endfunction
|
||||||
|
endmodule
|
||||||
|
|
@ -11,24 +11,39 @@ compile (
|
||||||
v_flags2 => ["--lint-only"],
|
v_flags2 => ["--lint-only"],
|
||||||
fails=>1,
|
fails=>1,
|
||||||
expect=>
|
expect=>
|
||||||
q{%Error: t/t_func_const_bad.v:\d+: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_output'
|
q{%Error: t/t_func_const_bad.v:11: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_output'
|
||||||
%Error: t/t_func_const_bad.v:\d+: ... Location of non-constant VAR 'o': Language violation: Outputs not allowed in constant functions
|
%Error: t/t_func_const_bad.v:12: ... Location of non-constant VAR 'o': Language violation: Outputs not allowed in constant functions
|
||||||
%Error: t/t_func_const_bad.v:\d+: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_dotted'
|
%Error: t/t_func_const_bad.v:20: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_dotted'
|
||||||
%Error: t/t_func_const_bad.v:\d+: ... Location of non-constant VARXREF 'EIGHT': Language violation: Dotted hierarchical references not allowed in constant functions
|
%Error: t/t_func_const_bad.v:22: ... Location of non-constant VARXREF 'EIGHT': Language violation: Dotted hierarchical references not allowed in constant functions
|
||||||
%Error: t/t_func_const_bad.v:\d+: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_nonparam'
|
Called from:
|
||||||
%Error: t/t_func_const_bad.v:\d+: ... Location of non-constant VARREF 'modvar': Language violation: reference to non-function-local variable
|
t/t_func_const_bad.v:20: f_bad_dotted() with parameters:
|
||||||
%Error: t/t_func_const_bad.v:\d+: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_infinite'
|
a = ?32?sh2
|
||||||
%Error: t/t_func_const_bad.v:\d+: ... Location of non-constant WHILE: Loop unrolling took too long; probably this is an infinite loop, or set --unroll-count above 1024
|
%Error: t/t_func_const_bad.v:27: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_nonparam'
|
||||||
%Error: t/t_func_const_bad.v:\d+: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_stop'
|
%Error: t/t_func_const_bad.v:29: ... Location of non-constant VARREF 'modvar': Language violation: reference to non-function-local variable
|
||||||
%Error: t/t_func_const_bad.v:\d+: ... Location of non-constant STOP: .stop executed during function constification; maybe indicates assertion firing
|
Called from:
|
||||||
|
t/t_func_const_bad.v:27: f_bad_nonparam() with parameters:
|
||||||
|
a = ?32?sh3
|
||||||
|
%Error: t/t_func_const_bad.v:35: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_infinite'
|
||||||
|
%Error: t/t_func_const_bad.v:37: ... Location of non-constant WHILE: Loop unrolling took too long; probably this is an infinite loop, or set --unroll-count above 1024
|
||||||
|
Called from:
|
||||||
|
t/t_func_const_bad.v:35: f_bad_infinite() with parameters:
|
||||||
|
a = ?32?sh3
|
||||||
|
%Error: t/t_func_const_bad.v:43: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_stop'
|
||||||
|
%Error: t/t_func_const_bad.v:45: ... Location of non-constant STOP: $stop executed during function constification; maybe indicates assertion firing
|
||||||
|
Called from:
|
||||||
|
t/t_func_const_bad.v:43: f_bad_stop() with parameters:
|
||||||
|
a = ?32?sh3
|
||||||
-Info: Printing in loop: 0
|
-Info: Printing in loop: 0
|
||||||
-Info: Printing in loop: 1
|
-Info: Printing in loop: 1
|
||||||
-Info: Printing in loop: 2
|
-Info: Printing in loop: 2
|
||||||
%Warning-USERFATAL: Fatal Error
|
%Warning-USERFATAL: Fatal Error
|
||||||
%Warning-USERFATAL: Use ... verilator lint_off USERFATAL ... and lint_on around source to disable this message.
|
%Warning-USERFATAL: Use "/* verilator lint_off USERFATAL */" and lint_on around source to disable this message.
|
||||||
%Error: t/t_func_const_bad.v:\d+: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_fatal'
|
%Error: t/t_func_const_bad.v:49: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_fatal'
|
||||||
%Error: t/t_func_const_bad.v:\d+: ... Location of non-constant STOP: .stop executed during function constification; maybe indicates assertion firing
|
%Error: t/t_func_const_bad.v:54: ... Location of non-constant STOP: $stop executed during function constification; maybe indicates assertion firing
|
||||||
%Error: Exiting due to.*},
|
Called from:
|
||||||
|
t/t_func_const_bad.v:49: f_bad_fatal() with parameters:
|
||||||
|
a = ?32?sh3
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
ok(1);
|
ok(1);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2017 by Todd Strader. 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.
|
||||||
|
#
|
||||||
|
compile (
|
||||||
|
v_flags2 => ["--lint-only"],
|
||||||
|
fails=>1,
|
||||||
|
expect=>
|
||||||
|
q{%Warning-USERFATAL: f_add = 15
|
||||||
|
%Warning-USERFATAL: Use "/* verilator lint_off USERFATAL */" and lint_on around source to disable this message.
|
||||||
|
%Error: t/t_func_const_packed_array_bad.v:11: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_add2'
|
||||||
|
%Error: t/t_func_const_packed_array_bad.v:22: ... Location of non-constant STOP: $stop executed during function constification; maybe indicates assertion firing
|
||||||
|
Called from:
|
||||||
|
t/t_func_const_packed_array_bad.v:30: f_add() with parameters:
|
||||||
|
params = [0 = 32'h7, 1 = 32'h8]
|
||||||
|
Called from:
|
||||||
|
t/t_func_const_packed_array_bad.v:11: f_add2() with parameters:
|
||||||
|
a = ?32?sh7
|
||||||
|
b = ?32?sh8
|
||||||
|
c = ?32?sh9
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2017 by Todd Strader.
|
||||||
|
|
||||||
|
module t;
|
||||||
|
|
||||||
|
localparam [ 1 : 0 ] [ 31 : 0 ] P = {32'd5, 32'd1};
|
||||||
|
localparam P6 = f_add(P);
|
||||||
|
localparam P14 = f_add2(2, 3, f_add(P));
|
||||||
|
localparam P24 = f_add2(7, 8, 9);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
// Should never get here
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
function integer f_add(input [ 1 : 0 ] [ 31 : 0 ] params);
|
||||||
|
f_add = params[0]+params[1];
|
||||||
|
if (f_add == 15)
|
||||||
|
$fatal(2, "f_add = 15");
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
// Speced ok: function called from function
|
||||||
|
function integer f_add2(input [31:0] a, input [31:0] b, input [31:0] c);
|
||||||
|
logic [ 1 : 0 ] [ 31 : 0 ] params;
|
||||||
|
params[0] = a;
|
||||||
|
params[1] = b;
|
||||||
|
f_add2 = f_add(params)+c;
|
||||||
|
endfunction
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2017 by Todd Strader. 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.
|
||||||
|
#
|
||||||
|
compile (
|
||||||
|
v_flags2 => ["--lint-only"],
|
||||||
|
fails=>1,
|
||||||
|
expect=>
|
||||||
|
q{%Warning-USERFATAL: f_add = 15
|
||||||
|
%Warning-USERFATAL: Use "/* verilator lint_off USERFATAL */" and lint_on around source to disable this message.
|
||||||
|
%Error: t/t_func_const_packed_struct_bad.v:13: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_add2'
|
||||||
|
%Error: t/t_func_const_packed_struct_bad.v:24: ... Location of non-constant STOP: $stop executed during function constification; maybe indicates assertion firing
|
||||||
|
Called from:
|
||||||
|
t/t_func_const_packed_struct_bad.v:32: f_add() with parameters:
|
||||||
|
params = [0 = '{a: 32'h7, b: 32'h22b}, 1 = '{a: 32'h3039, b: 32'h8}]
|
||||||
|
Called from:
|
||||||
|
t/t_func_const_packed_struct_bad.v:13: f_add2() with parameters:
|
||||||
|
a = ?32?sh7
|
||||||
|
b = ?32?sh8
|
||||||
|
c = ?32?sh9
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2017 by Todd Strader.
|
||||||
|
|
||||||
|
module t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [ 31 : 0 ] a;
|
||||||
|
logic [ 31 : 0 ] b;
|
||||||
|
} params_t;
|
||||||
|
|
||||||
|
localparam P24 = f_add2(7, 8, 9);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
// Should never get here
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
function integer f_add(input params_t [ 1 : 0 ] params);
|
||||||
|
f_add = params[0].a+params[1].b;
|
||||||
|
if (f_add == 15)
|
||||||
|
$fatal(2, "f_add = 15");
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
// Speced ok: function called from function
|
||||||
|
function integer f_add2(input [31:0] a, input [31:0] b, input [31:0] c);
|
||||||
|
params_t [ 1 : 0 ] params;
|
||||||
|
params[0] = '{a:a, b:555};
|
||||||
|
params[1] = '{a:12345, b:b};
|
||||||
|
f_add2 = f_add(params)+c;
|
||||||
|
endfunction
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2017 by Todd Strader. 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.
|
||||||
|
#
|
||||||
|
compile (
|
||||||
|
v_flags2 => ["--lint-only"],
|
||||||
|
fails=>1,
|
||||||
|
expect=>
|
||||||
|
q{%Warning-USERFATAL: f_add = 15
|
||||||
|
%Warning-USERFATAL: Use "/* verilator lint_off USERFATAL */" and lint_on around source to disable this message.
|
||||||
|
%Error: t/t_func_const_packed_struct_bad2.v:19: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_add2'
|
||||||
|
%Error: t/t_func_const_packed_struct_bad2.v:30: ... Location of non-constant STOP: $stop executed during function constification; maybe indicates assertion firing
|
||||||
|
Called from:
|
||||||
|
t/t_func_const_packed_struct_bad2.v:42: f_add() with parameters:
|
||||||
|
params = [0 = '{a: 32'h7, foo: 6'hb, sub_params: '{b: 32'h37, bar: 8'h6f}}, 1 = '{a: 32'h3039, foo: 6'hc, sub_params: '{b: 32'h8, bar: 8'h70}}]
|
||||||
|
Called from:
|
||||||
|
t/t_func_const_packed_struct_bad2.v:19: f_add2() with parameters:
|
||||||
|
a = ?32?sh7
|
||||||
|
b = ?32?sh8
|
||||||
|
c = ?32?sh9
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2017 by Todd Strader.
|
||||||
|
|
||||||
|
module t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [ 31 : 0 ] b;
|
||||||
|
logic [ 7 : 0 ] bar;
|
||||||
|
} sub_params_t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [ 31 : 0 ] a;
|
||||||
|
logic [ 5 : 0 ] foo;
|
||||||
|
sub_params_t sub_params;
|
||||||
|
} params_t;
|
||||||
|
|
||||||
|
localparam P24 = f_add2(7, 8, 9);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
// Should never get here
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
function integer f_add(input params_t [ 1 : 0 ] params);
|
||||||
|
f_add = params[0].a+params[1].sub_params.b;
|
||||||
|
if (f_add == 15)
|
||||||
|
$fatal(2, "f_add = 15");
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
// Speced ok: function called from function
|
||||||
|
function integer f_add2(input [31:0] a, input [31:0] b, input [31:0] c);
|
||||||
|
params_t [ 1 : 0 ] params;
|
||||||
|
sub_params_t sp0;
|
||||||
|
sub_params_t sp1;
|
||||||
|
sp0 = '{b:55, bar:111};
|
||||||
|
params[0] = '{a:a, foo:11, sub_params:sp0};
|
||||||
|
sp1 = '{b:b, bar:112};
|
||||||
|
params[1] = '{a:12345, foo:12, sub_params:sp1};
|
||||||
|
f_add2 = f_add(params)+c;
|
||||||
|
endfunction
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2017 by Todd Strader. 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.
|
||||||
|
#
|
||||||
|
compile (
|
||||||
|
v_flags2 => ["--lint-only"],
|
||||||
|
fails=>1,
|
||||||
|
expect=>
|
||||||
|
q{%Warning-USERFATAL: f_add = 15
|
||||||
|
%Warning-USERFATAL: Use "/* verilator lint_off USERFATAL */" and lint_on around source to disable this message.
|
||||||
|
%Error: t/t_func_const_struct_bad.v:16: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_add2'
|
||||||
|
%Error: t/t_func_const_struct_bad.v:27: ... Location of non-constant STOP: $stop executed during function constification; maybe indicates assertion firing
|
||||||
|
Called from:
|
||||||
|
t/t_func_const_struct_bad.v:37: f_add() with parameters:
|
||||||
|
params = '{a: 32'h7, b: 32'h8}
|
||||||
|
Called from:
|
||||||
|
t/t_func_const_struct_bad.v:16: f_add2() with parameters:
|
||||||
|
a = ?32?sh7
|
||||||
|
b = ?32?sh8
|
||||||
|
c = ?32?sh9
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2017 by Todd Strader.
|
||||||
|
|
||||||
|
module t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [ 31 : 0 ] a;
|
||||||
|
logic [ 31 : 0 ] b;
|
||||||
|
} params_t;
|
||||||
|
|
||||||
|
localparam params_t P = '{a:5, b:1};
|
||||||
|
localparam P6 = f_add(P);
|
||||||
|
localparam P14 = f_add2(2, 3, f_add(P));
|
||||||
|
localparam P24 = f_add2(7, 8, 9);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
// Should never get here
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
function integer f_add(input params_t params);
|
||||||
|
f_add = params.a+params.b;
|
||||||
|
if (f_add == 15)
|
||||||
|
$fatal(2, "f_add = 15");
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
// Speced ok: function called from function
|
||||||
|
function integer f_add2(input [31:0] a, input [31:0] b, input [31:0] c);
|
||||||
|
params_t params;
|
||||||
|
params = '{
|
||||||
|
a: a,
|
||||||
|
b: b
|
||||||
|
};
|
||||||
|
f_add2 = f_add(params)+c;
|
||||||
|
endfunction
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue