forked from github/verilator
Detect MSB overflow when under VL_DEBUG, bug1238.
This commit is contained in:
parent
4d074b5414
commit
cbb7cd16d0
2
Changes
2
Changes
@ -6,6 +6,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
**** Fix MacOS portability, bug1232. [Jeff Bush]
|
||||
|
||||
**** Detect MSB overflow when under VL_DEBUG, bug1238. [Junyi Xi]
|
||||
|
||||
|
||||
* Verilator 3.914 2017-10-14
|
||||
|
||||
|
@ -1488,6 +1488,14 @@ const char* Verilated::commandArgsPlusMatch(const char* prefixp) VL_MT_SAFE {
|
||||
return outstr;
|
||||
}
|
||||
|
||||
void Verilated::overWidthError(const char* signame) VL_MT_SAFE {
|
||||
// Slowpath - Called only when signal sets too high of a bit
|
||||
std::string msg = (std::string("Testbench C set input '")
|
||||
+ signame
|
||||
+ "' to value that overflows what the signal's width can fit");
|
||||
VL_FATAL_MT("unknown",0,"", msg.c_str());
|
||||
}
|
||||
|
||||
void Verilated::quiesce() VL_MT_SAFE {
|
||||
#ifdef VL_THREADED
|
||||
// Wait until all threads under this evaluation are quiet
|
||||
|
@ -429,9 +429,14 @@ public:
|
||||
// METHODS - INTERNAL USE ONLY (but public due to what uses it)
|
||||
// Internal: Create a new module name by concatenating two strings
|
||||
static const char* catName(const char* n1, const char* n2); // Returns static data
|
||||
|
||||
// Internal: Throw signal assertion
|
||||
static void overWidthError(const char* signame) VL_MT_SAFE;
|
||||
|
||||
// Internal: Find scope
|
||||
static const VerilatedScope* scopeFind(const char* namep) VL_MT_SAFE;
|
||||
static const VerilatedScopeNameMap* scopeNameMap() VL_MT_SAFE;
|
||||
|
||||
// Internal: Get and set DPI context
|
||||
static const VerilatedScope* dpiScope() VL_MT_SAFE { return t_s.t_dpiScopep; }
|
||||
static void dpiScope(const VerilatedScope* scopep) VL_MT_SAFE { t_s.t_dpiScopep=scopep; }
|
||||
@ -442,6 +447,7 @@ public:
|
||||
static const char* dpiFilenamep() VL_MT_SAFE { return t_s.t_dpiFilename; }
|
||||
static int dpiLineno() VL_MT_SAFE { return t_s.t_dpiLineno; }
|
||||
static int exportFuncNum(const char* namep) VL_MT_SAFE;
|
||||
|
||||
static size_t serializedSize() VL_PURE { return sizeof(s_s); }
|
||||
static void* serializedPtr() VL_MT_UNSAFE { return &s_s; } // Unsafe, for Serialize only
|
||||
#ifdef VL_THREADED
|
||||
|
@ -2878,7 +2878,7 @@ private:
|
||||
bool m_unique0Pragma; // unique0 case
|
||||
bool m_priorityPragma; // priority case
|
||||
public:
|
||||
AstIf(FileLine* fileline, AstNode* condp, AstNode* ifsp, AstNode* elsesp)
|
||||
AstIf(FileLine* fileline, AstNode* condp, AstNode* ifsp, AstNode* elsesp=NULL)
|
||||
: AstNodeIf(fileline, condp, ifsp, elsesp) {
|
||||
m_uniquePragma=false; m_unique0Pragma=false; m_priorityPragma=false;
|
||||
}
|
||||
@ -5153,6 +5153,7 @@ private:
|
||||
string m_cname; // C name, for dpiExports
|
||||
string m_rtnType; // void, bool, or other return type
|
||||
string m_argTypes;
|
||||
string m_ifdef; // #ifdef symbol around this function
|
||||
bool m_dontCombine:1; // V3Combine shouldn't compare this func tree, it's special
|
||||
bool m_skipDecl:1; // Don't declare it
|
||||
bool m_declPrivate:1; // Declare it private
|
||||
@ -5225,6 +5226,8 @@ public:
|
||||
void funcPublic(bool flag) { m_funcPublic = flag; }
|
||||
void argTypes(const string& str) { m_argTypes = str; }
|
||||
string argTypes() const { return m_argTypes; }
|
||||
void ifdef(const string& str) { m_ifdef = str; }
|
||||
string ifdef() const { return m_ifdef; }
|
||||
void funcType(AstCFuncType flag) { m_funcType = flag; }
|
||||
AstCFuncType funcType() const { return m_funcType; }
|
||||
bool isInline() const { return m_isInline; }
|
||||
|
@ -23,6 +23,8 @@
|
||||
// for all AstCoverDecl, move the declaration into a _configure_coverage AstCFunc.
|
||||
// For each variable that needs reset, add a AstCReset node.
|
||||
//
|
||||
// For primary inputs, add _eval_debug_assertions.
|
||||
//
|
||||
// This transformation honors outputSplitCFuncs.
|
||||
//*************************************************************************
|
||||
#include "config_build.h"
|
||||
@ -101,8 +103,46 @@ private:
|
||||
|
||||
//######################################################################
|
||||
|
||||
void V3CCtors::evalAsserts() {
|
||||
AstNodeModule* modp = v3Global.rootp()->modulesp(); // Top module
|
||||
AstCFunc* funcp = new AstCFunc(modp->fileline(), "_eval_debug_assertions", NULL, "void");
|
||||
funcp->declPrivate(true);
|
||||
funcp->isStatic(false);
|
||||
funcp->slow(false);
|
||||
funcp->ifdef("VL_DEBUG");
|
||||
modp->addStmtp(funcp);
|
||||
for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) {
|
||||
if (AstVar* varp = np->castVar()) {
|
||||
if (varp->isPrimaryIn() && !varp->isSc()) {
|
||||
if (AstBasicDType* basicp = varp->dtypeSkipRefp()->castBasicDType()) {
|
||||
int storedWidth = basicp->widthAlignBytes() * 8;
|
||||
int lastWordWidth = varp->width() % storedWidth;
|
||||
if (lastWordWidth != 0) {
|
||||
// if (signal & CONST(upper_non_clean_mask)) { fail; }
|
||||
AstNode* newp = new AstVarRef(varp->fileline(), varp, false);
|
||||
if (varp->isWide()) {
|
||||
newp = new AstWordSel(varp->fileline(), newp,
|
||||
new AstConst(varp->fileline(), varp->widthWords()-1));
|
||||
}
|
||||
uint64_t value = VL_MASK_Q(storedWidth) & ~VL_MASK_Q(lastWordWidth);
|
||||
V3Number num (varp->fileline(), storedWidth, value);
|
||||
newp = new AstAnd(varp->fileline(), newp,
|
||||
new AstConst(varp->fileline(), num));
|
||||
AstNodeIf* ifp = new AstIf(varp->fileline(), newp,
|
||||
new AstCStmt(varp->fileline(), "Verilated::overWidthError(\""+varp->prettyName()+"\");"));
|
||||
ifp->branchPred(AstBranchPred::BP_UNLIKELY);
|
||||
newp = ifp;
|
||||
funcp->addStmtsp(newp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void V3CCtors::cctorsAll() {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
evalAsserts();
|
||||
for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp=modp->nextp()->castNodeModule()) {
|
||||
// Process each module in turn
|
||||
{
|
||||
|
@ -30,6 +30,8 @@
|
||||
class V3CCtors {
|
||||
public:
|
||||
static void cctorsAll();
|
||||
private:
|
||||
static void evalAsserts();
|
||||
};
|
||||
|
||||
|
||||
|
@ -872,6 +872,7 @@ class EmitCImp : EmitCStmts {
|
||||
splitSizeInc(nodep);
|
||||
|
||||
puts("\n");
|
||||
if (nodep->ifdef()!="") puts("#ifdef "+nodep->ifdef()+"\n");
|
||||
if (nodep->isInline()) puts("VL_INLINE_OPT ");
|
||||
puts(nodep->rtnTypeVoid()); puts(" ");
|
||||
puts(modClassName(m_modp)+"::"+nodep->name()
|
||||
@ -908,6 +909,7 @@ class EmitCImp : EmitCStmts {
|
||||
|
||||
//puts("__Vm_activity = true;\n");
|
||||
puts("}\n");
|
||||
if (nodep->ifdef()!="") puts("#endif // "+nodep->ifdef()+"\n");
|
||||
}
|
||||
|
||||
void emitChangeDet() {
|
||||
@ -1731,14 +1733,18 @@ void EmitCImp::emitSensitives() {
|
||||
|
||||
void EmitCImp::emitWrapEval(AstNodeModule* modp) {
|
||||
puts("\nvoid "+modClassName(modp)+"::eval() {\n");
|
||||
puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+++++TOP Evaluate "+modClassName(modp)+"::eval\\n\"); );\n");
|
||||
puts(EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp; // Setup global symbol table\n");
|
||||
puts(EmitCBaseVisitor::symTopAssign()+"\n");
|
||||
puts("#ifdef VL_DEBUG\n");
|
||||
putsDecoration("// Debug assertions\n");
|
||||
puts("_eval_debug_assertions();\n");
|
||||
puts("#endif // VL_DEBUG\n");
|
||||
putsDecoration("// Initialize\n");
|
||||
puts("if (VL_UNLIKELY(!vlSymsp->__Vm_didInit)) _eval_initial_loop(vlSymsp);\n");
|
||||
if (v3Global.opt.inhibitSim()) {
|
||||
puts("if (VL_UNLIKELY(__Vm_inhibitSim)) return;\n");
|
||||
}
|
||||
puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+++++TOP Evaluate "+modClassName(modp)+"::eval\\n\"); );\n");
|
||||
|
||||
if (v3Global.opt.threads()) { // THREADED-TODO move to per-train
|
||||
uint32_t trainId = 0;
|
||||
@ -1859,9 +1865,11 @@ void EmitCImp::emitIntFuncDecls(AstNodeModule* modp) {
|
||||
AstCFunc* funcp = *it;
|
||||
if (!funcp->dpiImport()) { // DPI is prototyped in __Dpi.h
|
||||
ofp()->putsPrivate(funcp->declPrivate());
|
||||
if (funcp->ifdef()!="") puts("#ifdef "+funcp->ifdef()+"\n");
|
||||
if (funcp->isStatic()) puts("static ");
|
||||
puts(funcp->rtnTypeVoid()); puts(" ");
|
||||
puts(funcp->name()); puts("("+cFuncArgs(funcp)+");\n");
|
||||
if (funcp->ifdef()!="") puts("#endif // "+funcp->ifdef()+"\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ int main(int argc, char **argv, char **env) {
|
||||
top->clk = 0;
|
||||
|
||||
while (main_time < 190) { // Creates 2 files
|
||||
top->clk = ~top->clk;
|
||||
top->clk = !top->clk;
|
||||
top->eval();
|
||||
|
||||
if ((main_time % 100) == 0) {
|
||||
|
@ -32,7 +32,7 @@ int main(int argc, char **argv, char **env) {
|
||||
top->clk = 0;
|
||||
|
||||
while (main_time < 190*VL_TIME_MULTIPLIER) {
|
||||
top->clk = ~top->clk;
|
||||
top->clk = !top->clk;
|
||||
top->eval();
|
||||
tfp->dump((unsigned int)(main_time));
|
||||
// Advance by 0.5 time units, to make sure our fractional
|
||||
|
44
test_regress/t/t_var_overwidth_bad.cpp
Normal file
44
test_regress/t/t_var_overwidth_bad.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2010-2011 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.
|
||||
//
|
||||
// Verilator is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#include "Vt_var_overwidth_bad.h"
|
||||
#include "verilated.h"
|
||||
|
||||
//======================================================================
|
||||
|
||||
double main_time;
|
||||
|
||||
double sc_time_stamp () {
|
||||
return main_time;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **env) {
|
||||
Verilated::debug(0);
|
||||
|
||||
VM_PREFIX* topp = new VM_PREFIX (""); // Note null name - we're flattening it out
|
||||
|
||||
main_time = 0;
|
||||
|
||||
topp->clk = 0;
|
||||
topp->eval();
|
||||
main_time += 10;
|
||||
|
||||
topp->clk = 0x2; // ILLEGAL
|
||||
topp->eval();
|
||||
topp->final();
|
||||
|
||||
delete topp; topp=NULL;
|
||||
exit(0L);
|
||||
}
|
23
test_regress/t/t_var_overwidth_bad.pl
Executable file
23
test_regress/t/t_var_overwidth_bad.pl
Executable 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 2010 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 (
|
||||
make_main => 0,
|
||||
verilator_flags2 => ["--exe $Self->{t_dir}/t_var_overwidth_bad.cpp"],
|
||||
);
|
||||
|
||||
execute (
|
||||
fails=>1,
|
||||
expect=>
|
||||
qr{%Error: unknown:0: Testbench C set input 'clk' to value that overflows what the signal's width can fit
|
||||
Aborting....*}
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
19
test_regress/t/t_var_overwidth_bad.v
Normal file
19
test_regress/t/t_var_overwidth_bad.v
Normal file
@ -0,0 +1,19 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// Copyright 2010 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.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
|
||||
input clk;
|
||||
|
||||
always @ (posedge clk) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
Loading…
Reference in New Issue
Block a user