forked from github/verilator
Validate integer run-time arguments
This commit is contained in:
parent
bab8462789
commit
c7440b250f
@ -55,6 +55,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
#include <cstdlib>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <sys/stat.h> // mkdir
|
#include <sys/stat.h> // mkdir
|
||||||
#include <list>
|
#include <list>
|
||||||
@ -2506,13 +2507,16 @@ std::pair<int, char**> VerilatedContextImp::argc_argv() VL_MT_SAFE_EXCLUDES(m_ar
|
|||||||
|
|
||||||
void VerilatedContextImp::commandArgVl(const std::string& arg) {
|
void VerilatedContextImp::commandArgVl(const std::string& arg) {
|
||||||
if (0 == std::strncmp(arg.c_str(), "+verilator+", std::strlen("+verilator+"))) {
|
if (0 == std::strncmp(arg.c_str(), "+verilator+", std::strlen("+verilator+"))) {
|
||||||
std::string value;
|
std::string str;
|
||||||
|
uint64_t u64;
|
||||||
if (arg == "+verilator+debug") {
|
if (arg == "+verilator+debug") {
|
||||||
Verilated::debug(4);
|
Verilated::debug(4);
|
||||||
} else if (commandArgVlValue(arg, "+verilator+debugi+", value /*ref*/)) {
|
} else if (commandArgVlUint64(arg, "+verilator+debugi+", u64, 0,
|
||||||
Verilated::debug(std::atoi(value.c_str()));
|
std::numeric_limits<int>::max())) {
|
||||||
} else if (commandArgVlValue(arg, "+verilator+error+limit+", value /*ref*/)) {
|
Verilated::debug(static_cast<int>(u64));
|
||||||
errorLimit(std::atoi(value.c_str()));
|
} else if (commandArgVlUint64(arg, "+verilator+error+limit+", u64, 0,
|
||||||
|
std::numeric_limits<int>::max())) {
|
||||||
|
errorLimit(static_cast<int>(u64));
|
||||||
} else if (arg == "+verilator+help") {
|
} else if (arg == "+verilator+help") {
|
||||||
VerilatedImp::versionDump();
|
VerilatedImp::versionDump();
|
||||||
VL_PRINTF_MT("For help, please see 'verilator --help'\n");
|
VL_PRINTF_MT("For help, please see 'verilator --help'\n");
|
||||||
@ -2520,18 +2524,19 @@ void VerilatedContextImp::commandArgVl(const std::string& arg) {
|
|||||||
"Exiting due to command line argument (not an error)");
|
"Exiting due to command line argument (not an error)");
|
||||||
} else if (arg == "+verilator+noassert") {
|
} else if (arg == "+verilator+noassert") {
|
||||||
assertOn(false);
|
assertOn(false);
|
||||||
} else if (commandArgVlValue(arg, "+verilator+prof+threads+start+", value /*ref*/)) {
|
} else if (commandArgVlUint64(arg, "+verilator+prof+threads+start+", u64)) {
|
||||||
profThreadsStart(std::atoll(value.c_str()));
|
profThreadsStart(u64);
|
||||||
} else if (commandArgVlValue(arg, "+verilator+prof+threads+window+", value /*ref*/)) {
|
} else if (commandArgVlUint64(arg, "+verilator+prof+threads+window+", u64, 1)) {
|
||||||
profThreadsWindow(std::atol(value.c_str()));
|
profThreadsWindow(u64);
|
||||||
} else if (commandArgVlValue(arg, "+verilator+prof+threads+file+", value /*ref*/)) {
|
} else if (commandArgVlString(arg, "+verilator+prof+threads+file+", str)) {
|
||||||
profThreadsFilename(value);
|
profThreadsFilename(str);
|
||||||
} else if (commandArgVlValue(arg, "+verilator+prof+vlt+file+", value /*ref*/)) {
|
} else if (commandArgVlString(arg, "+verilator+prof+vlt+file+", str)) {
|
||||||
profVltFilename(value);
|
profVltFilename(str);
|
||||||
} else if (commandArgVlValue(arg, "+verilator+rand+reset+", value /*ref*/)) {
|
} else if (commandArgVlUint64(arg, "+verilator+rand+reset+", u64, 0, 2)) {
|
||||||
randReset(std::atoi(value.c_str()));
|
randReset(static_cast<int>(u64));
|
||||||
} else if (commandArgVlValue(arg, "+verilator+seed+", value /*ref*/)) {
|
} else if (commandArgVlUint64(arg, "+verilator+seed+", u64, 1,
|
||||||
randSeed(std::atoi(value.c_str()));
|
std::numeric_limits<int>::max())) {
|
||||||
|
randSeed(static_cast<int>(u64));
|
||||||
} else if (arg == "+verilator+V") {
|
} else if (arg == "+verilator+V") {
|
||||||
VerilatedImp::versionDump(); // Someday more info too
|
VerilatedImp::versionDump(); // Someday more info too
|
||||||
VL_FATAL_MT("COMMAND_LINE", 0, "",
|
VL_FATAL_MT("COMMAND_LINE", 0, "",
|
||||||
@ -2541,12 +2546,14 @@ void VerilatedContextImp::commandArgVl(const std::string& arg) {
|
|||||||
VL_FATAL_MT("COMMAND_LINE", 0, "",
|
VL_FATAL_MT("COMMAND_LINE", 0, "",
|
||||||
"Exiting due to command line argument (not an error)");
|
"Exiting due to command line argument (not an error)");
|
||||||
} else {
|
} else {
|
||||||
VL_PRINTF_MT("%%Warning: Unknown +verilator runtime argument: '%s'\n", arg.c_str());
|
const std::string msg = "Unknown runtime argument: " + arg;
|
||||||
|
VL_FATAL_MT("COMMAND_LINE", 0, "", msg.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool VerilatedContextImp::commandArgVlValue(const std::string& arg, const std::string& prefix,
|
|
||||||
std::string& valuer) {
|
bool VerilatedContextImp::commandArgVlString(const std::string& arg, const std::string& prefix,
|
||||||
|
std::string& valuer) {
|
||||||
const size_t len = prefix.length();
|
const size_t len = prefix.length();
|
||||||
if (0 == std::strncmp(prefix.c_str(), arg.c_str(), len)) {
|
if (0 == std::strncmp(prefix.c_str(), arg.c_str(), len)) {
|
||||||
valuer = arg.substr(len);
|
valuer = arg.substr(len);
|
||||||
@ -2556,6 +2563,30 @@ bool VerilatedContextImp::commandArgVlValue(const std::string& arg, const std::s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VerilatedContextImp::commandArgVlUint64(const std::string& arg, const std::string& prefix,
|
||||||
|
uint64_t& valuer, uint64_t min, uint64_t max) {
|
||||||
|
std::string str;
|
||||||
|
if (commandArgVlString(arg, prefix, str)) {
|
||||||
|
const auto fail = [&](const std::string& extra = "") {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "Argument '" << prefix << "' must be an unsigned integer";
|
||||||
|
if (min != std::numeric_limits<uint64_t>::min()) ss << ", greater than " << min - 1;
|
||||||
|
if (max != std::numeric_limits<uint64_t>::max()) ss << ", less than " << max + 1;
|
||||||
|
if (!extra.empty()) ss << ". " << extra;
|
||||||
|
const std::string& msg = ss.str();
|
||||||
|
VL_FATAL_MT("COMMAND_LINE", 0, "", msg.c_str());
|
||||||
|
};
|
||||||
|
|
||||||
|
if (std::any_of(str.begin(), str.end(), [](int c) { return !std::isdigit(c); })) fail();
|
||||||
|
char* end;
|
||||||
|
valuer = std::strtoull(str.c_str(), &end, 10);
|
||||||
|
if (errno == ERANGE) fail("Value out of range of uint64_t");
|
||||||
|
if (valuer < min || valuer > max) fail();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
// VerilatedContext:: + VerilatedContextImp:: Methods - random
|
// VerilatedContext:: + VerilatedContextImp:: Methods - random
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <limits>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <set>
|
#include <set>
|
||||||
@ -394,7 +395,11 @@ protected:
|
|||||||
// METHODS - protected
|
// METHODS - protected
|
||||||
void commandArgsAddGuts(int argc, const char** argv);
|
void commandArgsAddGuts(int argc, const char** argv);
|
||||||
void commandArgVl(const std::string& arg);
|
void commandArgVl(const std::string& arg);
|
||||||
bool commandArgVlValue(const std::string& arg, const std::string& prefix, std::string& valuer);
|
bool commandArgVlString(const std::string& arg, const std::string& prefix,
|
||||||
|
std::string& valuer);
|
||||||
|
bool commandArgVlUint64(const std::string& arg, const std::string& prefix, uint64_t& valuer,
|
||||||
|
uint64_t min = std::numeric_limits<uint64_t>::min(),
|
||||||
|
uint64_t max = std::numeric_limits<uint64_t>::max());
|
||||||
void commandArgDump() const VL_MT_SAFE_EXCLUDES(m_argMutex);
|
void commandArgDump() const VL_MT_SAFE_EXCLUDES(m_argMutex);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
%Warning: Unknown +verilator runtime argument: '+verilator+bad+flag+testing'
|
|
||||||
*-* All Finished *-*
|
|
2
test_regress/t/t_runflag_bad.out-a
Normal file
2
test_regress/t/t_runflag_bad.out-a
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
%Error: COMMAND_LINE:0: Unknown runtime argument: +verilator+bad+flag+testing
|
||||||
|
Aborting...
|
2
test_regress/t/t_runflag_bad.out-b
Normal file
2
test_regress/t/t_runflag_bad.out-b
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
%Error: COMMAND_LINE:0: Argument '+verilator+rand+reset+' must be an unsigned integer, less than 3
|
||||||
|
Aborting...
|
2
test_regress/t/t_runflag_bad.out-c
Normal file
2
test_regress/t/t_runflag_bad.out-c
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
%Error: COMMAND_LINE:0: Argument '+verilator+rand+reset+' must be an unsigned integer, less than 3
|
||||||
|
Aborting...
|
2
test_regress/t/t_runflag_bad.out-d
Normal file
2
test_regress/t/t_runflag_bad.out-d
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
%Error: COMMAND_LINE:0: Argument '+verilator+prof+threads+window+' must be an unsigned integer, greater than 0
|
||||||
|
Aborting...
|
2
test_regress/t/t_runflag_bad.out-e
Normal file
2
test_regress/t/t_runflag_bad.out-e
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
%Error: COMMAND_LINE:0: Argument '+verilator+prof+threads+window+' must be an unsigned integer, greater than 0. Value out of range of uint64_t
|
||||||
|
Aborting...
|
@ -15,8 +15,32 @@ compile(
|
|||||||
|
|
||||||
execute(
|
execute(
|
||||||
all_run_flags => ["+verilator+bad+flag+testing"],
|
all_run_flags => ["+verilator+bad+flag+testing"],
|
||||||
#fails => 1, # doesn't fail just prints
|
fails => 1,
|
||||||
expect_filename => $Self->{golden_filename},
|
expect_filename => $Self->{golden_filename} . "-a",
|
||||||
|
);
|
||||||
|
|
||||||
|
execute(
|
||||||
|
all_run_flags => ["+verilator+rand+reset+-1"],
|
||||||
|
fails => 1,
|
||||||
|
expect_filename => $Self->{golden_filename} . "-b"
|
||||||
|
);
|
||||||
|
|
||||||
|
execute(
|
||||||
|
all_run_flags => ["+verilator+rand+reset+3"],
|
||||||
|
fails => 1,
|
||||||
|
expect_filename => $Self->{golden_filename} . "-c"
|
||||||
|
);
|
||||||
|
|
||||||
|
execute(
|
||||||
|
all_run_flags => ["+verilator+prof+threads+window+0"],
|
||||||
|
fails => 1,
|
||||||
|
expect_filename => $Self->{golden_filename} . "-d"
|
||||||
|
);
|
||||||
|
|
||||||
|
execute(
|
||||||
|
all_run_flags => ["+verilator+prof+threads+window+1000000000000000000000000"],
|
||||||
|
fails => 1,
|
||||||
|
expect_filename => $Self->{golden_filename} . "-e"
|
||||||
);
|
);
|
||||||
|
|
||||||
ok(1);
|
ok(1);
|
||||||
|
Loading…
Reference in New Issue
Block a user