forked from github/verilator
Support command-line -G/+pvalue param overrides, bug1045.
Signed-off-by: Wilson Snyder <wsnyder@wsnyder.org>
This commit is contained in:
parent
b2623b9841
commit
482bdab0e0
2
Changes
2
Changes
@ -8,6 +8,8 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
** Support parameter type, bug376. [Alan Hunter, et al]
|
||||
|
||||
** Support command-line -G/+pvalue param overrides, bug1045. [Stefan Wallentowitz]
|
||||
|
||||
|
||||
* Verilator 3.882 2016-03-01
|
||||
|
||||
|
@ -54,7 +54,18 @@ push @ARGV, (split ' ',$ENV{VERILATOR_TEST_FLAGS}||"");
|
||||
# We sneak a look at the flags so we can do some pre-environment checks
|
||||
# All flags will hit verilator...
|
||||
foreach my $sw (@ARGV) {
|
||||
$sw = "'$sw'" if $sw =~ m![^---a-zA-Z0-9_/\\:.+]!;
|
||||
# Some special treatment for parameters to allow verilog literals for numbers
|
||||
if ((substr($sw, 0, 2) eq "-G") || (substr($sw, 0, 8) eq "-pvalue+")) {
|
||||
# If there is a single quote in the parameter put it double quotes ,
|
||||
# else just put it in double quotes
|
||||
if ($sw =~ m![\']!) {
|
||||
$sw = "\"$sw\"";
|
||||
} else {
|
||||
$sw = "'$sw'";
|
||||
}
|
||||
} else {
|
||||
$sw = "'$sw'" if $sw =~ m![^---a-zA-Z0-9_/\\:.+]!;
|
||||
}
|
||||
push @Opt_Verilator_Sw, $sw;
|
||||
}
|
||||
|
||||
@ -269,6 +280,7 @@ descriptions in the next sections for more information.
|
||||
--exe Link to create executable
|
||||
-F <file> Parse options from a file, relatively
|
||||
-f <file> Parse options from a file
|
||||
-G<name>=<value> Overwrite toplevel parameter
|
||||
--gdb Run Verilator under GDB interactively
|
||||
--gdbbt Run Verilator under GDB for backtrace
|
||||
--help Display this help
|
||||
@ -308,6 +320,7 @@ descriptions in the next sections for more information.
|
||||
--profile-cfuncs Name functions for profiling
|
||||
--private Debugging; see docs
|
||||
--public Debugging; see docs
|
||||
-pvalue+<name>=<value> Overwrite toplevel parameter
|
||||
--report-unoptflat Extra diagnostics for UNOPTFLAT
|
||||
--savable Enable model save-restore
|
||||
--sc Create SystemC output
|
||||
@ -688,6 +701,35 @@ The file may contain // comments which are ignored to the end of the line.
|
||||
Any $VAR, $(VAR), or ${VAR} will be replaced with the specified environment
|
||||
variable.
|
||||
|
||||
=item -GI<name>=I<value>
|
||||
|
||||
Overwrites the given parameter of the toplevel module. The value is limited
|
||||
to basic data literals:
|
||||
|
||||
=over 4
|
||||
|
||||
=item Verilog integer literals
|
||||
|
||||
The standard verilog integer literals are supported, so values like 32'h8,
|
||||
2'b00, 4 etc. are allowed. Care must be taken that the single quote (I') is
|
||||
properly escaped in an interactive shell, e.g., as -GWIDTH=8\'hx.
|
||||
|
||||
=item C integer literals
|
||||
|
||||
It is also possible to use C integer notation, including hexadecimal (0x..),
|
||||
octal (0..) or binary (0b..) notation.
|
||||
|
||||
=item Double literals
|
||||
|
||||
Double literals must contain a dot (.) and/or an exponent (e).
|
||||
|
||||
=item Strings
|
||||
|
||||
String must in double quotes ("). On the command line it is required to escape
|
||||
them properly, e.g. as -GSTR="\"My String\"" or -GSTR='"My String"'.
|
||||
|
||||
=back
|
||||
|
||||
=item --gdb
|
||||
|
||||
Run Verilator underneath an interactive GDB (or VERILATOR_GDB environment
|
||||
@ -946,6 +988,11 @@ inlining. This will also turn off inlining as if all modules had a
|
||||
/*verilator public_module*/, unless the module specifically enabled it with
|
||||
/*verilator inline_module*/.
|
||||
|
||||
=item -pvalue+I<name>=I<value>
|
||||
|
||||
Overwrites the given parameter(s) of the toplevel module. See -G for a
|
||||
detailed description.
|
||||
|
||||
=item --report-unoptflat
|
||||
|
||||
Extra diagnostics for UNOPTFLAT warnings. This includes for each loop, the
|
||||
@ -1340,7 +1387,7 @@ This is an example similar to the above, but using SystemC.
|
||||
top = new Vour("top"); // SP_CELL (top, Vour);
|
||||
top->clk(clk); // SP_PIN (top, clk, clk);
|
||||
while (!Verilated::gotFinish()) { sc_start(1, SC_NS); }
|
||||
delete top;
|
||||
delete top;
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
@ -1603,7 +1650,7 @@ example:
|
||||
|
||||
double sc_time_stamp () { // Called by $time in Verilog
|
||||
return main_time; // converts to double, to match
|
||||
// what SystemC does
|
||||
// what SystemC does
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
@ -1847,7 +1894,7 @@ accesses the above would be:
|
||||
if (!vh1) { error... }
|
||||
const char* name = vpi_get_str(vpiName, vh1);
|
||||
printf("Module name: %s\n"); // Prints "readme"
|
||||
|
||||
|
||||
s_vpi_value v;
|
||||
v.format = vpiIntVal;
|
||||
vpi_get_value(vh1, &v);
|
||||
|
@ -77,6 +77,7 @@
|
||||
#include "V3SymTable.h"
|
||||
#include "V3Graph.h"
|
||||
#include "V3Ast.h"
|
||||
#include "V3ParseImp.h"
|
||||
|
||||
//######################################################################
|
||||
// LinkDot state, as a visitor of each AstNode
|
||||
@ -586,6 +587,42 @@ class LinkDotFindVisitor : public AstNVisitor {
|
||||
// METHODS
|
||||
int debug() { return LinkDotState::debug(); }
|
||||
|
||||
virtual AstConst* parseParamLiteral(FileLine* fl, string literal) {
|
||||
bool success = false;
|
||||
if (literal[0] == '"') {
|
||||
// This is a string
|
||||
string v = literal.substr(1, literal.find('"', 1) - 1);
|
||||
V3Number n(V3Number::VerilogStringLiteral(), fl, v);
|
||||
return new AstConst(fl,n);
|
||||
} else if ((literal.find(".") != string::npos)
|
||||
|| (literal.find("e") != string::npos)) {
|
||||
// This may be a real
|
||||
double v = V3ParseImp::parseDouble(literal.c_str(), literal.length(), &success);
|
||||
if (success) {
|
||||
return new AstConst(fl, AstConst::RealDouble(), v);
|
||||
}
|
||||
}
|
||||
if (!success) {
|
||||
// This is either an integer or an error
|
||||
// We first try to convert it as C literal. If strtol returns
|
||||
// 0 this is either an error or 0 was parsed. But in any case
|
||||
// we will try to parse it as a verilog literal, hence having
|
||||
// the false negative for 0 is okay. If anything remains in
|
||||
// the string after the number, this is invalid C and we try
|
||||
// the Verilog literal parser.
|
||||
char* endp;
|
||||
int v = strtol(literal.c_str(), &endp, 0);
|
||||
if ((v != 0) && (endp[0] == 0)) { // C literal
|
||||
V3Number n(fl, 32, v);
|
||||
return new AstConst(fl, n);
|
||||
} else { // Try a Verilog literal (fatals if not)
|
||||
V3Number n(fl, literal.c_str());
|
||||
return new AstConst(fl, n);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// VISITs
|
||||
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
||||
// Process $unit or other packages
|
||||
@ -873,6 +910,24 @@ class LinkDotFindVisitor : public AstNVisitor {
|
||||
}
|
||||
}
|
||||
if (ins) {
|
||||
if (m_statep->forPrimary() && nodep->isGParam()
|
||||
&& (m_statep->rootEntp()->nodep() == m_modSymp->parentp()->nodep())) {
|
||||
// This is the toplevel module. Check for command line overwrites of parameters
|
||||
// We first search if the parameter is overwritten and then replace it with a
|
||||
// new value. It will keep the same FileLine information.
|
||||
if (v3Global.opt.hasParameter(nodep->name())) {
|
||||
AstVar* newp = new AstVar(nodep->fileline(), AstVarType(AstVarType::GPARAM),
|
||||
nodep->name(), nodep);
|
||||
string svalue = v3Global.opt.parameter(nodep->name());
|
||||
if (AstNode* valuep = parseParamLiteral(nodep->fileline(), svalue)) {
|
||||
newp->valuep(valuep);
|
||||
UINFO(9," replace parameter "<<nodep<<endl);
|
||||
UINFO(9," with "<<newp<<endl);
|
||||
nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
nodep = newp;
|
||||
}
|
||||
}
|
||||
}
|
||||
VSymEnt* insp = m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep);
|
||||
if (m_statep->forPrimary() && nodep->isGParam()) {
|
||||
m_paramNum++;
|
||||
|
@ -130,6 +130,52 @@ void V3Options::addDefine(const string& defline, bool allowPlus) {
|
||||
V3PreShell::defineCmdLine(def,value);
|
||||
}
|
||||
}
|
||||
void V3Options::addParameter(const string& paramline, bool allowPlus) {
|
||||
// Split +define+foo=value into the appropriate parts and parse
|
||||
// Optional + says to allow multiple defines on the line
|
||||
// + is not quotable, as other simulators do not allow that
|
||||
string left = paramline;
|
||||
while (left != "") {
|
||||
string param = left;
|
||||
string::size_type pos;
|
||||
if (allowPlus && ((pos=left.find("+")) != string::npos)) {
|
||||
left = left.substr(pos+1);
|
||||
param.erase(pos);
|
||||
} else {
|
||||
left = "";
|
||||
}
|
||||
string value;
|
||||
if ((pos=param.find("=")) != string::npos) {
|
||||
value = param.substr(pos+1);
|
||||
param.erase(pos);
|
||||
}
|
||||
UINFO(4,"Add parameter"<<param<<"="<<value<<endl);
|
||||
(void)m_parameters.erase(param);
|
||||
m_parameters[param] = value;
|
||||
}
|
||||
}
|
||||
|
||||
bool V3Options::hasParameter(string name) {
|
||||
return m_parameters.find(name) != m_parameters.end();
|
||||
}
|
||||
|
||||
string V3Options::parameter(string name) {
|
||||
string value = m_parameters.find(name)->second;
|
||||
m_parameters.erase(m_parameters.find(name));
|
||||
return value;
|
||||
}
|
||||
|
||||
void V3Options::checkParameters() {
|
||||
if (!m_parameters.empty()) {
|
||||
stringstream msg;
|
||||
msg << "Parameters from the command line were not found in the design:";
|
||||
for (map<string,string>::iterator it = m_parameters.begin();
|
||||
it != m_parameters.end(); ++it) {
|
||||
msg << " " << it->first;
|
||||
}
|
||||
v3fatal(msg.str()<<endl);
|
||||
}
|
||||
}
|
||||
|
||||
void V3Options::addCppFile(const string& filename) {
|
||||
if (m_cppFiles.find(filename) == m_cppFiles.end()) {
|
||||
@ -658,6 +704,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
else if ( !strcmp (sw, "-private") ) { m_public = false; }
|
||||
else if ( onoff (sw, "-profile-cfuncs", flag/*ref*/) ) { m_profileCFuncs = flag; }
|
||||
else if ( onoff (sw, "-public", flag/*ref*/) ) { m_public = flag; }
|
||||
else if ( !strncmp(sw, "-pvalue+", strlen("-pvalue+"))) { addParameter(string(sw+strlen("-pvalue+")), false); }
|
||||
else if ( onoff (sw, "-report-unoptflat", flag/*ref*/) ) { m_reportUnoptflat = flag; }
|
||||
else if ( onoff (sw, "-savable", flag/*ref*/) ) { m_savable = flag; }
|
||||
else if ( !strcmp (sw, "-sc") ) { m_outFormatOk = true; m_systemC = true; m_systemPerl = false; }
|
||||
@ -748,6 +795,9 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
shift;
|
||||
V3Error::errorLimit(atoi(argv[i]));
|
||||
}
|
||||
else if ( !strncmp (sw, "-G", strlen("-G"))) {
|
||||
addParameter (string (sw+strlen("-G")), false);
|
||||
}
|
||||
else if ( !strncmp (sw, "-I", 2)) {
|
||||
addIncDirUser (parseFileArg(optdir, string (sw+strlen("-I"))));
|
||||
}
|
||||
|
@ -58,6 +58,8 @@ class V3Options {
|
||||
V3StringList m_vFiles; // argument: Verilog files to read
|
||||
DebugSrcMap m_debugSrcs; // argument: --debugi-<srcfile>=<level>
|
||||
DebugSrcMap m_dumpTrees; // argument: --dump-treei-<srcfile>=<level>
|
||||
map<string,string> m_parameters; // Parameters
|
||||
|
||||
|
||||
bool m_preprocOnly; // main switch: -E
|
||||
bool m_makeDepend; // main switch: -MMD
|
||||
@ -162,6 +164,7 @@ class V3Options {
|
||||
void addFuture(const string& flag);
|
||||
void addIncDirUser(const string& incdir); // User requested
|
||||
void addIncDirFallback(const string& incdir); // Low priority if not found otherwise
|
||||
void addParameter(const string& paramline, bool allowPlus);
|
||||
void addLangExt(const string& langext, const V3LangCode& lc);
|
||||
void addLibExtV(const string& libext);
|
||||
void optimize(int level);
|
||||
@ -279,6 +282,10 @@ class V3Options {
|
||||
const V3StringList& vFiles() const { return m_vFiles; }
|
||||
const V3LangCode& defaultLanguage() const { return m_defaultLanguage; }
|
||||
|
||||
bool hasParameter(string name);
|
||||
string parameter(string name);
|
||||
void checkParameters();
|
||||
|
||||
bool isFuture(const string& flag) const;
|
||||
bool isLibraryFile(const string& filename) const;
|
||||
bool isClocker(const string& signame) const;
|
||||
|
@ -160,6 +160,8 @@ void process () {
|
||||
// Cross-link dotted hierarchical references
|
||||
V3LinkDot::linkDotPrimary(v3Global.rootp());
|
||||
v3Global.checkTree(); // Force a check, as link is most likely place for problems
|
||||
// Check if all parameters have been found
|
||||
v3Global.opt.checkParameters();
|
||||
// Correct state we couldn't know at parse time, repair SEL's
|
||||
V3LinkResolve::linkResolve(v3Global.rootp());
|
||||
// Set Lvalue's in variable refs
|
||||
|
20
test_regress/t/t_flag_parameter.pl
Executable file
20
test_regress/t/t_flag_parameter.pl
Executable 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 2008 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.
|
||||
|
||||
compile (
|
||||
# It is not possible to put them into the options file
|
||||
v_flags2 => ['-Gstring1="\"New String\"" -pvalue+string2="\"New String\"" -f t/t_flag_parameter.vc'],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
49
test_regress/t/t_flag_parameter.v
Normal file
49
test_regress/t/t_flag_parameter.v
Normal file
@ -0,0 +1,49 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2016 by Wilson Snyder
|
||||
|
||||
`define check(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: Wrong parameter value", `__FILE__,`__LINE__); $stop; end while(0);
|
||||
|
||||
module t;
|
||||
parameter string1 = "Original String";
|
||||
parameter string2 = "Original String";
|
||||
|
||||
parameter real11 = 0.1;
|
||||
parameter real12 = 0.1;
|
||||
parameter real21 = 0.1;
|
||||
parameter real22 = 0.1;
|
||||
parameter real31 = 0.1;
|
||||
parameter real32 = 0.1;
|
||||
|
||||
parameter int11 = 1;
|
||||
parameter int12 = 1;
|
||||
parameter int21 = 1;
|
||||
parameter int22 = 1;
|
||||
parameter int31 = 1;
|
||||
parameter int32 = 1;
|
||||
parameter int41 = 1;
|
||||
parameter int42 = 1;
|
||||
|
||||
initial begin
|
||||
`check(string1,"New String");
|
||||
`check(string2,"New String");
|
||||
`check(real11,0.2);
|
||||
`check(real12,0.2);
|
||||
`check(real21,400);
|
||||
`check(real22,400);
|
||||
`check(real31,20);
|
||||
`check(real32,20);
|
||||
`check(int11,16);
|
||||
`check(int12,16);
|
||||
`check(int21,16);
|
||||
`check(int22,16);
|
||||
`check(int31,123);
|
||||
`check(int32,123);
|
||||
`check(int41,32'hdeadbeef);
|
||||
`check(int42,32'hdeadbeef);
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
15
test_regress/t/t_flag_parameter.vc
Normal file
15
test_regress/t/t_flag_parameter.vc
Normal file
@ -0,0 +1,15 @@
|
||||
-Greal11=0.2
|
||||
-pvalue+real12=0.2
|
||||
-Greal21=4e2
|
||||
-pvalue+real22=4e2
|
||||
-Greal31=0.2e2
|
||||
-pvalue+real32=0.2e2
|
||||
-Gint11=0x10
|
||||
-pvalue+int12=0x10
|
||||
-Gint21=020
|
||||
-pvalue+int22=020
|
||||
-Gint31=123
|
||||
-pvalue+int32=123
|
||||
-Gint41=32'hdead_beef
|
||||
-pvalue+int42=32'hdead_beef
|
||||
|
Loading…
Reference in New Issue
Block a user