Fix real parameter assignment, bug1427.

This commit is contained in:
Wilson Snyder 2019-05-17 20:50:57 -04:00
parent 3411279294
commit 59d7d9e8c3
13 changed files with 245 additions and 27 deletions

View File

@ -18,6 +18,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
**** Fix parameter function string returns, bug1441. [Denis Rystsov]
**** Fix real parameter assignment, bug1427. [Todd Strader]
* Verilator 4.014 2019-05-08

View File

@ -607,6 +607,7 @@ public:
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual bool similarDType(AstNodeDType* samep) const { return this==samep; }
virtual V3Hash sameHash() const { return V3Hash(m_cellp); }
virtual int widthAlignBytes() const { return 1; }
virtual int widthTotalBytes() const { return 1; }
string cellName() const { return m_cellName; }

View File

@ -663,6 +663,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
else if ( onoff (sw, "-covsp", flag/*ref*/) ) { } // TBD
else if ( !strcmp (sw, "-debug-abort") ) { abort(); } // Undocumented, see also --debug-sigsegv
else if ( onoff (sw, "-debug-check", flag/*ref*/) ){ m_debugCheck = flag; }
else if ( onoff (sw, "-debug-collision", flag/*ref*/) ){ m_debugCollision = flag; } // Undocumented
else if ( onoff (sw, "-debug-leak", flag/*ref*/) ){ m_debugLeak = flag; }
else if ( onoff (sw, "-debug-nondeterminism", flag/*ref*/) ){ m_debugNondeterminism = flag; }
else if ( onoff (sw, "-debug-partition", flag/*ref*/) ){ m_debugPartition = flag; } // Undocumented
@ -1258,6 +1259,7 @@ V3Options::V3Options() {
m_coverageUnderscore = false;
m_coverageUser = false;
m_debugCheck = false;
m_debugCollision = false;
m_debugLeak = true;
m_debugNondeterminism = false;
m_debugPartition = false;

View File

@ -114,6 +114,7 @@ class V3Options {
bool m_coverageUnderscore;// main switch: --coverage-underscore
bool m_coverageUser; // main switch: --coverage-func
bool m_debugCheck; // main switch: --debug-check
bool m_debugCollision; // main switch: --debug-collision
bool m_debugLeak; // main switch: --debug-leak
bool m_debugNondeterminism; // main switch: --debug-nondeterminism
bool m_debugPartition; // main switch: --debug-partition
@ -281,6 +282,7 @@ class V3Options {
bool coverageUnderscore() const { return m_coverageUnderscore; }
bool coverageUser() const { return m_coverageUser; }
bool debugCheck() const { return m_debugCheck; }
bool debugCollision() const { return m_debugCollision; }
bool debugLeak() const { return m_debugLeak; }
bool debugNondeterminism() const { return m_debugNondeterminism; }
bool debugPartition() const { return m_debugPartition; }

View File

@ -58,6 +58,7 @@
#include "V3Const.h"
#include "V3Width.h"
#include "V3Unroll.h"
#include "V3Hashed.h"
#include <cstdarg>
#include <deque>
@ -96,10 +97,10 @@ private:
LongMap m_longMap; // Hash of very long names to unique identity number
int m_longId;
typedef std::map<AstNode*,int> ValueMap;
typedef std::map<int,int> NextValueMap;
ValueMap m_valueMap; // Hash of node to param value
NextValueMap m_nextValueMap;// Hash of param value to next value to be used
typedef std::pair<int,string> ValueMapValue;
typedef std::map<V3Hash,ValueMapValue> ValueMap;
ValueMap m_valueMap; // Hash of node hash to (param value, name)
int m_nextValue; // Next value to use in m_valueMap
typedef std::multimap<int,AstNodeModule*> LevelModMap;
LevelModMap m_todoModps; // Modules left to process
@ -148,26 +149,34 @@ private:
return st;
}
string paramValueNumber(AstNode* nodep) {
// Given a complicated object create a number to use for param module assignment
// Ideally would be relatively stable if design changes (not use pointer value),
// and must return same value given same input node
// Return must presently be numeric so doesn't collide with 'small' alphanumeric parameter names
ValueMap::iterator it = m_valueMap.find(nodep);
if (it != m_valueMap.end()) {
return cvtToStr(it->second);
} else {
static int BUCKETS = 1000;
V3Hash hash (nodep->name());
int bucket = hash.hshval() % BUCKETS;
int offset = 0;
NextValueMap::iterator it = m_nextValueMap.find(bucket);
if (it != m_nextValueMap.end()) { offset = it->second; it->second = offset + 1; }
else { m_nextValueMap.insert(make_pair(bucket, offset + 1)); }
int num = bucket + offset * BUCKETS;
m_valueMap.insert(make_pair(nodep, num));
// 'z' just to make sure we don't collide with a normal non-hashed number
return string("z")+cvtToStr(num);
}
string key = nodep->name();
if (AstIfaceRefDType* ifrtp = VN_CAST(nodep, IfaceRefDType)) {
if (ifrtp->cellp() && ifrtp->cellp()->modp()) {
key = ifrtp->cellp()->modp()->name();
} else if (ifrtp->ifacep()) {
key = ifrtp->ifacep()->name();
} else {
nodep->v3fatalSrc("Can't parameterize interface without module name");
}
} else if (AstBasicDType* bdtp = VN_CAST(nodep, BasicDType)) {
if (bdtp->isRanged()) {
key += "["+cvtToStr(bdtp->left())+":"+cvtToStr(bdtp->right())+"]";
}
}
V3Hash hash = V3Hashed::uncachedHash(nodep);
// Force hash collisions -- for testing only
if (VL_UNLIKELY(v3Global.opt.debugCollision())) {
hash = V3Hash();
}
int num;
ValueMap::iterator it = m_valueMap.find(hash);
if (it != m_valueMap.end() && it->second.second == key) {
num = it->second.first;
} else {
num = m_nextValue++;
m_valueMap[hash] = make_pair(num, key);
}
return string("z")+cvtToStr(num);
}
void collectPins(CloneMap* clonemapp, AstNodeModule* modp) {
// Grab all I/O so we can remap our pins later
@ -528,9 +537,10 @@ private:
public:
// CONSTUCTORS
explicit ParamVisitor(AstNetlist* nodep) {
m_longId = 0;
m_modp = NULL;
//
m_longId = 0;
m_modp = NULL;
m_nextValue = 1;
//
iterate(nodep);
}
virtual ~ParamVisitor() {}

View File

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

View File

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

20
test_regress/t/t_param_real2.pl Executable file
View File

@ -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 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.
scenarios(simulator => 1);
compile(
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,32 @@
module foo
#( parameter real bar = 2.0)
();
endmodule
module t();
genvar m, r;
generate
for (m = 10; m <= 20; m+=10) begin : gen_m
for (r = 0; r <= 1; r++) begin : gen_r
localparam real lparam = m + (r + 0.5);
initial begin
if (lparam != foo_inst.bar) begin
$display("%m: lparam != foo_inst.bar (%f, %f)",
lparam, foo_inst.bar);
$stop();
end
end
foo #(.bar (lparam)) foo_inst ();
end
end
endgenerate
initial begin
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,23 @@
#!/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 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.
scenarios(simulator => 1);
top_filename("t/t_param_real2.v");
compile(
verilator_flags2 => ["--debug-collision"]
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,23 @@
#!/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);
top_filename("t/t_param_type.v");
compile(
verilator_flags2 => ["--debug-collision"]
);
execute(
check_finished => 1,
);
ok(1);
1;

20
test_regress/t/t_real_param.pl Executable file
View File

@ -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 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.
scenarios(simulator => 1);
compile(
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,37 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2019 by Todd Strader.
module foo
#( parameter real bar = 2.0)
();
endmodule
module t();
genvar m, r;
generate
for (m = 10; m <= 20; m+=10) begin : gen_m
for (r = 0; r <= 1; r++) begin : gen_r
localparam real lparam = m + (r + 0.5);
initial begin
$display("%m lparam = %f foo bar = %f", // TODO -- remove
lparam, foo_inst.bar);
if (lparam != foo_inst.bar) begin
$display("%m: lparam != foo_inst.bar (%f, %f)",
lparam, foo_inst.bar);
$stop();
end
end
foo #(.bar (lparam)) foo_inst ();
end
end
endgenerate
initial begin
$write("*-* All Finished *-*\n");
$finish;
end
endmodule