forked from github/verilator
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]
|
||||
|
||||
**** Add stack trace when can't optimize function, bug1158. [Todd Strader]
|
||||
|
||||
**** Add warning on mis-sized literal, bug1156. [Todd Strader]
|
||||
|
||||
|
||||
|
@ -44,12 +44,25 @@
|
||||
#include "V3Task.h"
|
||||
|
||||
#include <deque>
|
||||
#include <sstream>
|
||||
|
||||
//============================================================================
|
||||
|
||||
//######################################################################
|
||||
// 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 {
|
||||
// Simulate a node tree, returning value of variables
|
||||
// Two major operating modes:
|
||||
@ -90,6 +103,7 @@ private:
|
||||
// Simulating:
|
||||
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<SimulateStackNode*> m_callStack; ///< Call stack for verbose error messages
|
||||
|
||||
// Cleanup
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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
|
||||
public:
|
||||
/// Call other-this function on all new *non-constant* var references
|
||||
@ -119,6 +181,19 @@ public:
|
||||
cout<<endl;
|
||||
}
|
||||
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; }
|
||||
@ -718,8 +793,11 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
SimulateStackNode stackNode(nodep, &tconnects);
|
||||
m_callStack.push_front(&stackNode);
|
||||
// Evaluate the function
|
||||
funcp->accept(*this);
|
||||
m_callStack.pop_front();
|
||||
if (!m_checkOnly && optimizable()) {
|
||||
// Grab return value from output variable (if it's a function)
|
||||
if (!funcp->fvarp()) nodep->v3fatalSrc("Function reference points at non-function");
|
||||
|
31
test_regress/t/t_func_const2_bad.pl
Executable file
31
test_regress/t/t_func_const2_bad.pl
Executable file
@ -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;
|
28
test_regress/t/t_func_const2_bad.v
Normal file
28
test_regress/t/t_func_const2_bad.v
Normal file
@ -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"],
|
||||
fails=>1,
|
||||
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'
|
||||
%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:\d+: 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:\d+: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_nonparam'
|
||||
%Error: t/t_func_const_bad.v:\d+: ... Location of non-constant VARREF 'modvar': Language violation: reference to non-function-local variable
|
||||
%Error: t/t_func_const_bad.v:\d+: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_infinite'
|
||||
%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:\d+: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_stop'
|
||||
%Error: t/t_func_const_bad.v:\d+: ... Location of non-constant STOP: .stop executed during function constification; maybe indicates assertion firing
|
||||
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:12: ... Location of non-constant VAR 'o': Language violation: Outputs not allowed in constant functions
|
||||
%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:22: ... Location of non-constant VARXREF 'EIGHT': Language violation: Dotted hierarchical references not allowed in constant functions
|
||||
Called from:
|
||||
t/t_func_const_bad.v:20: f_bad_dotted() with parameters:
|
||||
a = ?32?sh2
|
||||
%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:29: ... Location of non-constant VARREF 'modvar': Language violation: reference to non-function-local variable
|
||||
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: 1
|
||||
-Info: Printing in loop: 2
|
||||
%Warning-USERFATAL: Fatal Error
|
||||
%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:\d+: ... Location of non-constant STOP: .stop executed during function constification; maybe indicates assertion firing
|
||||
%Error: Exiting due to.*},
|
||||
%Warning-USERFATAL: Use "/* verilator lint_off USERFATAL */" and lint_on around source to disable this message.
|
||||
%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:54: ... Location of non-constant STOP: $stop executed during function constification; maybe indicates assertion firing
|
||||
Called from:
|
||||
t/t_func_const_bad.v:49: f_bad_fatal() with parameters:
|
||||
a = ?32?sh3
|
||||
},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
|
30
test_regress/t/t_func_const_packed_array_bad.pl
Executable file
30
test_regress/t/t_func_const_packed_array_bad.pl
Executable file
@ -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;
|
32
test_regress/t/t_func_const_packed_array_bad.v
Normal file
32
test_regress/t/t_func_const_packed_array_bad.v
Normal file
@ -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
|
30
test_regress/t/t_func_const_packed_struct_bad.pl
Executable file
30
test_regress/t/t_func_const_packed_struct_bad.pl
Executable file
@ -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;
|
34
test_regress/t/t_func_const_packed_struct_bad.v
Normal file
34
test_regress/t/t_func_const_packed_struct_bad.v
Normal file
@ -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
|
30
test_regress/t/t_func_const_packed_struct_bad2.pl
Executable file
30
test_regress/t/t_func_const_packed_struct_bad2.pl
Executable file
@ -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;
|
44
test_regress/t/t_func_const_packed_struct_bad2.v
Normal file
44
test_regress/t/t_func_const_packed_struct_bad2.v
Normal file
@ -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
|
30
test_regress/t/t_func_const_struct_bad.pl
Executable file
30
test_regress/t/t_func_const_struct_bad.pl
Executable file
@ -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;
|
39
test_regress/t/t_func_const_struct_bad.v
Normal file
39
test_regress/t/t_func_const_struct_bad.v
Normal file
@ -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
Block a user