Leak repairs and node leak detection

git-svn-id: file://localhost/svn/verilator/trunk/verilator@967 77ca24e4-aefa-0310-84f0-b9a241c72d87
This commit is contained in:
Wilson Snyder 2007-11-02 11:23:03 +00:00
parent 8075372675
commit 98e35b02ad
23 changed files with 362 additions and 169 deletions

164
Changes
View File

@ -7,23 +7,25 @@ indicates the contributor was also the author of the fix; Thanks!
*** Support "#delay <statement>;" with associated STMTDLY warning.
**** Fix divide-by-zero errors in constant propagator. [Rodney Sinclair]
**** Fixed divide-by-zero errors in constant propagator. [Rodney Sinclair]
**** Fix wrong result with obscure signed-shift underneath a "? :".
**** Fixed wrong result with obscure signed-shift underneath a "? :".
**** Fixed many internal memory leaks, and added leak detector.
* Verilator 3.654 10/18/2007
**** Don't exit early if many warnings but no errors are found. [Stan Mayer]
**** Fix parsing module #(parameter x,y) declarations. [Oleg Rodionov]
**** Fixed parsing module #(parameter x,y) declarations. [Oleg Rodionov]
**** Fix parsing system functions with empty parens. [Oleg Rodionov]
**** Fixed parsing system functions with empty parens. [Oleg Rodionov]
* Verilator 3.653 8/1/2007
**** Support SystemVerilog ==? and !=? operators.
**** Fix SC_LIBS missing from generated makefiles. [Ding Xiaoliang]
**** Fixed SC_LIBS missing from generated makefiles. [Ding Xiaoliang]
* Verilator 3.652 6/21/2007
@ -35,7 +37,7 @@ indicates the contributor was also the author of the fix; Thanks!
**** Optimize constant $display arguments.
**** Fix Preprocessor dropping some `line directives. [Mark Nodine]
**** Fixed Preprocessor dropping some `line directives. [Mark Nodine]
* Verilator 3.651 5/22/2007
@ -70,11 +72,11 @@ indicates the contributor was also the author of the fix; Thanks!
*** Add USER_CPPFLAGS and USER_LDFLAGS to Makefiles. [Gerald Williams]
**** Fix compile errors under Windows MINGW compiler. [Gerald Williams]
**** Fixed compile errors under Windows MINGW compiler. [Gerald Williams]
**** Fix dotted bit reference to local memory. [Eugene Weber]
**** Fixed dotted bit reference to local memory. [Eugene Weber]
**** Fix 3.640 `verilog forcing IEEE 1364-1995 only. [David Hewson]
**** Fixed 3.640 `verilog forcing IEEE 1364-1995 only. [David Hewson]
* Verilator 3.640 3/12/2007
@ -86,13 +88,13 @@ indicates the contributor was also the author of the fix; Thanks!
**** Try all +libext's in the exact order given. [Michael Shinkarovsky]
**** Fix elimination of public signals assigned to constants. [Eugene Weber]
**** Fixed elimination of public signals assigned to constants. [Eugene Weber]
**** Fix internal error when public for loop has empty body. [David Addison]
**** Fixed internal error when public for loop has empty body. [David Addison]
**** Fix "Loops detected" assertion when model exceeds 4GB. [David Hewson]
**** Fixed "Loops detected" assertion when model exceeds 4GB. [David Hewson]
**** Fix display %m names inside named blocks.
**** Fixed display %m names inside named blocks.
* Verilator 3.633 2/7/2007
@ -100,11 +102,11 @@ indicates the contributor was also the author of the fix; Thanks!
*** With VL_DEBUG, show wires causing convergence errors. [Mike Shinkarovsky]
**** Fix isolate_assignments when many signals per always. [Mike Shinkarovsky]
**** Fixed isolate_assignments when many signals per always. [Mike Shinkarovsky]
**** Fix isolate_assignments across task/func temporaries. [Mike Shinkarovsky]
**** Fixed isolate_assignments across task/func temporaries. [Mike Shinkarovsky]
**** Fix $display's with array select followed by wide AND. [David Hewson]
**** Fixed $display's with array select followed by wide AND. [David Hewson]
* Verilator 3.632 1/17/2007
@ -115,11 +117,11 @@ indicates the contributor was also the author of the fix; Thanks!
** Support standard NAME[#] for cells created by arraying or generate for.
This replaces the non-standard name__# syntax used in earlier versions.
**** Fix again dotted references into generate cells. [David Hewson]
**** Fixed again dotted references into generate cells. [David Hewson]
Verilator no longer accepts duplicated variables inside unique
generate blocks as this is illegal according to the specification.
**** Fix $readmem* with filenames < 8 characters. [Emerson Suguimoto]
**** Fixed $readmem* with filenames < 8 characters. [Emerson Suguimoto]
* Verilator 3.630 12/19/2006
@ -131,21 +133,21 @@ indicates the contributor was also the author of the fix; Thanks!
*** Reduce depth of priority encoded case statements. [Eugene Weber]
**** Fix dotted references inside generated cells. [David Hewson]
**** Fixed dotted references inside generated cells. [David Hewson]
**** Fix missed split optimization points underneath other re-split blocks.
**** Fixed missed split optimization points underneath other re-split blocks.
* Verilator 3.623 12/05/2006
*** Add --output-split-cfuncs for accelerating GCC compile. [Eugene Weber]
**** Fix $signed mis-extending when input has a WIDTH violation. [Eugene Weber]
**** Fixed $signed mis-extending when input has a WIDTH violation. [Eugene Weber]
**** Add M32 make variable to support -m32 compiles. [Eugene Weber]
* Verilator 3.622 10/17/2006 Stable
**** Fix --skip-identical without --debug, broken in 3.621. [Andy Meier]
**** Fixed --skip-identical without --debug, broken in 3.621. [Andy Meier]
* Verilator 3.621 10/11/2006 Beta
@ -155,11 +157,11 @@ indicates the contributor was also the author of the fix; Thanks!
**** Remove .vpp intermediate files when not under --debug.
**** Fix link error when using --exe with --trace. [Eugene Weber]
**** Fixed link error when using --exe with --trace. [Eugene Weber]
**** Fix mis-optimization of wide concats with constants.
**** Fixed mis-optimization of wide concats with constants.
**** Fix core dump on printing error when not under --debug. [Allan Cochrane]
**** Fixed core dump on printing error when not under --debug. [Allan Cochrane]
* Verilator 3.620 10/04/2006 Stable
@ -174,9 +176,9 @@ indicates the contributor was also the author of the fix; Thanks!
**** Optimize additional boolean identities (a|a = a, etc.)
**** Fix coredump when dotted cross-ref inside task call. [Eugene Weber]
**** Fixed coredump when dotted cross-ref inside task call. [Eugene Weber]
**** Fix dotted variables in always sensitivity lists. [Allan Cochrane]
**** Fixed dotted variables in always sensitivity lists. [Allan Cochrane]
* Verilator 3.610 09/20/2006 Stable
@ -186,13 +188,13 @@ indicates the contributor was also the author of the fix; Thanks!
**** Removed coverage request variable; see Coverage limitations in docs.
**** Fix DOS carriage returns in multiline defines. [Ralf Karge]
**** Fixed DOS carriage returns in multiline defines. [Ralf Karge]
**** Fix printf format warnings on 64-bit linux.
**** Fixed printf format warnings on 64-bit linux.
* Verilator 3.602 09/11/2006 Stable
**** Fix function references under top inlined module. [David Hewson]
**** Fixed function references under top inlined module. [David Hewson]
* Verilator 3.601 09/06/2006 Beta
@ -205,15 +207,15 @@ indicates the contributor was also the author of the fix; Thanks!
*** Changed how internal functions are invoked to reduce aliasing.
Useful when using GCC's -O2 or -fstrict-aliasing, to gain another ~4%.
**** Fix memory leak when destroying modules. [John Stroebel]
**** Fixed memory leak when destroying modules. [John Stroebel]
**** Fix coredump when unused modules have unused cells. [David Hewson]
**** Fixed coredump when unused modules have unused cells. [David Hewson]
**** Fix 3.600 internal error with arrayed instances. [David Hewson]
**** Fixed 3.600 internal error with arrayed instances. [David Hewson]
**** Fix 3.600 internal error with non-unrolled function loops. [David Hewson]
**** Fixed 3.600 internal error with non-unrolled function loops. [David Hewson]
**** Fix $display %m name not matching Verilog name inside SystemC modules.
**** Fixed $display %m name not matching Verilog name inside SystemC modules.
**** Declare optimized lookup tables as 'static', to reduce D-Cache miss rate.
@ -223,17 +225,17 @@ indicates the contributor was also the author of the fix; Thanks!
**** Lint for x's in generate case statements.
**** Fix line numbers being off by one when first file starts with newline.
**** Fixed line numbers being off by one when first file starts with newline.
**** Fix naming of generate for blocks to prevent non-inline name conflict.
**** Fixed naming of generate for blocks to prevent non-inline name conflict.
**** Fix redundant statements remaining after table optimization.
**** Fixed redundant statements remaining after table optimization.
* Verilator 3.542 08/11/2006 Stable
**** Fix extraneous UNSIGNED warning when comparing genvars. [David Hewson]
**** Fixed extraneous UNSIGNED warning when comparing genvars. [David Hewson]
**** Fix extra white space in $display %c. [by David Addison]
**** Fixed extra white space in $display %c. [by David Addison]
**** vl_finish and vl_fatal now print via VL_PRINTF rather then cerr/cout.
@ -241,15 +243,15 @@ indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.541 07/05/2006 Beta
*** Fix "// verilator lint_on" not re-enabling warnings. [David Hewson]
*** Fixed "// verilator lint_on" not re-enabling warnings. [David Hewson]
*** Fix 3.540's multiple memory assignments to same block. [David Hewson]
*** Fixed 3.540's multiple memory assignments to same block. [David Hewson]
**** Add warning on changeDetect to arrayed structures. [David Hewson]
**** Fix non-zero start number for arrayed instantiations. [Jae Hossell]
**** Fixed non-zero start number for arrayed instantiations. [Jae Hossell]
**** Fix GCC 4.0 header file warnings.
**** Fixed GCC 4.0 header file warnings.
* Verilator 3.540 06/27/2006 Beta
@ -257,27 +259,27 @@ indicates the contributor was also the author of the fix; Thanks!
**** Optimize delayed assignments to memories inside loops, ~0-5% faster.
**** Fix mis-width warning on bit selects of memories. [David Hewson]
**** Fixed mis-width warning on bit selects of memories. [David Hewson]
**** Fix mis-width warning on dead generate-if branches. [Jae Hossell]
**** Fixed mis-width warning on dead generate-if branches. [Jae Hossell]
* Verilator 3.533 06/05/2006 Stable
*** Add PDF user manual, verilator.pdf.
**** Fix delayed bit-selected arrayed assignments. [David Hewson]
**** Fixed delayed bit-selected arrayed assignments. [David Hewson]
**** Fix execution path to Perl. [Shanshan Xu]
**** Fixed execution path to Perl. [Shanshan Xu]
**** Fix Bison compile errors in verilog.y. [by Ben Jackson]
**** Fixed Bison compile errors in verilog.y. [by Ben Jackson]
* Verilator 3.531 05/10/2006 Stable
*** Support $c routines which return 64 bit values.
**** Fix `include `DEFINE.
**** Fixed `include `DEFINE.
**** Fix Verilator core dump when have empty public function. [David.Hewson]
**** Fixed Verilator core dump when have empty public function. [David.Hewson]
* Verilator 3.530 04/24/2006 Stable
@ -286,11 +288,11 @@ indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.523 03/06/2006 Stable
**** Fix error line numbers being off due to multi-line defines. [Mat Zeno]
**** Fixed error line numbers being off due to multi-line defines. [Mat Zeno]
**** Fix GCC sign extending (uint64_t)(a<b). [David Hewson]
**** Fixed GCC sign extending (uint64_t)(a<b). [David Hewson]
**** Fix `systemc_imp_header "undefined macro" error.
**** Fixed `systemc_imp_header "undefined macro" error.
* Verilator 3.522 02/23/2006 Beta
@ -302,7 +304,7 @@ indicates the contributor was also the author of the fix; Thanks!
**** Added SystemVerilog 'x,'z,'0,'1, and new string literals.
**** Fix public module's parent still getting inlined.
**** Fixed public module's parent still getting inlined.
* Verilator 3.520 01/14/2006 Stable
@ -315,28 +317,28 @@ indicates the contributor was also the author of the fix; Thanks!
This adds a small ~2% performance penalty if traces are compiled in,
but not turned on. For best non-tracing performance, do not use --trace.
**** Fix $'s in specify delays causing bad PLI errors. [Mat Zeno]
**** Fixed $'s in specify delays causing bad PLI errors. [Mat Zeno]
**** Fix public functions not setting up proper symbol table. [Mat Zeno]
**** Fixed public functions not setting up proper symbol table. [Mat Zeno]
**** Fix genvars generating trace compile errors. [Mat Zeno]
**** Fixed genvars generating trace compile errors. [Mat Zeno]
**** Fix VL_MULS_WWW compile error with MSVC++. [Wim Michiels]
**** Fixed VL_MULS_WWW compile error with MSVC++. [Wim Michiels]
* Verilator 3.502 11/30/2005 Stable
**** Fix local non-IO variables in public functions and tasks.
**** Fixed local non-IO variables in public functions and tasks.
**** Fix bad lifetime optimization when same signal is assigned multiple
**** Fixed bad lifetime optimization when same signal is assigned multiple
times in both branch of a if. [Danny Ding]
* Verilator 3.501 11/16/2005 Stable
*** Add --profile-cfuncs for correlating profiles back to Verilog.
**** Fix functions where regs are declared before inputs. [Danny Ding]
**** Fixed functions where regs are declared before inputs. [Danny Ding]
**** Fix bad deep expressions with bit-selects and rotate. [Prabhat Gupta]
**** Fixed bad deep expressions with bit-selects and rotate. [Prabhat Gupta]
* Verilator 3.500 10/30/2005 Stable
@ -350,15 +352,15 @@ indicates the contributor was also the author of the fix; Thanks!
** With --assert, generate assertions for synthesis parallel_case and full_case.
**** Fix generate if's with empty if/else blocks. [Mat Zeno]
**** Fixed generate if's with empty if/else blocks. [Mat Zeno]
**** Fix generate for cell instantiations with same name. [Mat Zeno]
**** Fixed generate for cell instantiations with same name. [Mat Zeno]
* Verilator 3.481 10/12/2005 Stable
*** Add /*verilator tracing_on/off*/ for waveform control.
**** Fix split optimization reordering $display statements.
**** Fixed split optimization reordering $display statements.
* Verilator 3.480 9/27/2005 Beta
@ -383,9 +385,9 @@ indicates the contributor was also the author of the fix; Thanks!
**** Add GCC branch prediction hints on generated if statements.
**** Fix bad simulation when same function called twice in same expression.
**** Fixed bad simulation when same function called twice in same expression.
**** Fix preprocessor substitution of quoted parameterized defines.
**** Fixed preprocessor substitution of quoted parameterized defines.
* Verilator 3.464 8/24/2005 Stable
@ -393,7 +395,7 @@ indicates the contributor was also the author of the fix; Thanks!
*** Add --stats option to dump design statistics.
**** Fix core dump with clock inversion optimizations.
**** Fixed core dump with clock inversion optimizations.
* Verilator 3.463 8/5/2005 Stable
@ -401,15 +403,15 @@ indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.462 8/3/2005 Stable
*** Fix reordering of delayed assignments to same memory index. [Wim Michiels]
*** Fixed reordering of delayed assignments to same memory index. [Wim Michiels]
**** Fix compile error with Flex 2.5.1. [Jens Arm]
**** Fixed compile error with Flex 2.5.1. [Jens Arm]
**** Fix multiply-instantiated public tasks generating non-compilable code.
**** Fixed multiply-instantiated public tasks generating non-compilable code.
* Verilator 3.461 7/28/2005 Beta
**** Fix compile error with older versions of bison. [Jeff Dutton]
**** Fixed compile error with older versions of bison. [Jeff Dutton]
* Verilator 3.460 7/27/2005 Beta
@ -422,13 +424,13 @@ indicates the contributor was also the author of the fix; Thanks!
*** When issuing unoptimizable warning, show an example path.
**** Fix false warning when a clock is constant.
**** Fixed false warning when a clock is constant.
**** Fix X/Z in decimal numbers. [Wim Michiels]
**** Fixed X/Z in decimal numbers. [Wim Michiels]
**** Fix genvar statements in non-named generate blocks.
**** Fixed genvar statements in non-named generate blocks.
**** Fix core dump when missing newline in `define. [David van der bokke]
**** Fixed core dump when missing newline in `define. [David van der bokke]
**** Internal tree dumps now indicate edit number that changed the node.
@ -445,7 +447,7 @@ indicates the contributor was also the author of the fix; Thanks!
*** Add support for SystemVerilog keywords $bits, $countones, $isunknown,
$onehot, $onehot0, always_comb, always_ff, always_latch, finish.
**** Fix "=== 1'bx" to always be false, instead of random.
**** Fixed "=== 1'bx" to always be false, instead of random.
* Verilator 3.440 6/28/2005 Stable
@ -453,7 +455,7 @@ indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.431 6/24/2005 Stable
*** Fix selection bugs introduced in 3.430 beta.
*** Fixed selection bugs introduced in 3.430 beta.
* Verilator 3.430 6/22/2005 Beta
@ -1085,7 +1087,7 @@ of input ports exists for tracing.
** [Versions 0 to 1.8 were by Paul Wasson]
**** Fix single bit in concat from instance output incorrect offset bug.
**** Fixed single bit in concat from instance output incorrect offset bug.
* Verilator 1.7 5/20/1996
@ -1100,7 +1102,7 @@ of input ports exists for tracing.
*** Pass structure pointer into translated code,
so multiple instances can use same functions.
**** Fix static value concat on casex items.
**** Fixed static value concat on casex items.
* Verilator 1.1 3/30/1995

View File

@ -134,6 +134,7 @@ inline void AstNode::debugTreeChange(const char* prefix, int lineno, bool next)
// Called on all major tree changers.
// Only for use for those really nasty bugs relating to internals
// Note this may be null.
//if (debug()) cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<": "<<(void*)this<<endl;
//if (debug()) {
// cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<endl;
// v3Global.rootp()->dumpTree(cout,"-treeChange: ");
@ -586,11 +587,29 @@ void AstNode::deleteTree() {
// unlinkFromBack or unlinkFromBackWithNext as appropriate before calling this.
if (!this) return;
UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n");
this->debugTreeChange("-delete: ", __LINE__, true);
this->debugTreeChange("-delTree: ", __LINE__, true);
// MUST be depth first!
deleteTreeIter();
}
//======================================================================
// Memory checks
#ifdef VL_LEAK_CHECKS
void* AstNode::operator new(size_t size) {
AstNode* objp = static_cast<AstNode*>(::operator new(size));
V3Broken::addNewed(objp);
return objp;
}
void AstNode::operator delete(void* objp, size_t size) {
if (!objp) return;
AstNode* nodep = static_cast<AstNode*>(objp);
V3Broken::deleted(nodep);
::operator delete(objp);
}
#endif
//======================================================================
// Iterators

View File

@ -538,6 +538,10 @@ public:
// CONSTRUCTORS
virtual ~AstNode();
#ifdef VL_LEAK_CHECKS
static void* operator new(size_t size);
static void operator delete(void* obj, size_t size);
#endif
// CONSTANT ACCESSORS
static int instrCountBranch() { return 4; } ///< Instruction cycles to branch

View File

@ -32,7 +32,7 @@
#include <stdarg.h>
#include <unistd.h>
#include <algorithm>
#include <set>
#include <map>
#include "V3Global.h"
#include "V3Broken.h"
@ -45,19 +45,100 @@ class BrokenTable : public AstNVisitor {
private:
// MEMBERS
// For each node, we keep if it exists or not.
typedef set<const AstNode*> NodeSet;
static NodeSet s_nodes; // Set of all nodes that exist
typedef map<const AstNode*,int> NodeMap;
static NodeMap s_nodes; // Set of all nodes that exist
// BITMASK
static const int FLAG_ALLOCATED = 0x01; // new() and not delete()ed
static const int FLAG_IN_TREE = 0x02; // Is in netlist tree
static const int FLAG_LINKABLE = 0x04; // Is in netlist tree, can be linked to
static const int FLAG_LEAKED = 0x08; // Known to have been leaked
public:
// METHODS
static void add(const AstNode* nodep) {
s_nodes.insert(nodep);
static void deleted(const AstNode* nodep) {
// Called by operator delete on any node - only if VL_LEAK_CHECKS
if (debug()) cout<<"-nodeDel: "<<(void*)(nodep)<<endl;
NodeMap::iterator iter = s_nodes.find(nodep);
if (iter==s_nodes.end() || !(iter->second & FLAG_ALLOCATED)) {
((AstNode*)(nodep))->v3fatalSrc("Deleting AstNode object that was never tracked or already deleted\n");
}
if (iter!=s_nodes.end()) s_nodes.erase(iter);
}
static bool exists(const AstNode* nodep) {
NodeSet::iterator iter = s_nodes.find(nodep);
return (iter != s_nodes.end());
static void addNewed(const AstNode* nodep) {
// Called by operator new on any node - only if VL_LEAK_CHECKS
if (debug()) cout<<"-nodeNew: "<<(void*)(nodep)<<endl;
NodeMap::iterator iter = s_nodes.find(nodep);
if (iter!=s_nodes.end() || (iter->second & FLAG_ALLOCATED)) {
((AstNode*)(nodep))->v3fatalSrc("Newing AstNode object that is already allocated\n");
}
if (iter == s_nodes.end()) {
s_nodes.insert(make_pair(nodep,FLAG_ALLOCATED));
}
}
static void clear() {
static void addInTree(AstNode* nodep, bool linkable) {
#ifndef VL_LEAK_CHECKS
if (!linkable) return; // save some time, else the map will get huge!
#endif
NodeMap::iterator iter = s_nodes.find(nodep);
if (iter == s_nodes.end()) {
#ifdef VL_LEAK_CHECKS
nodep->v3fatalSrc("AstNode is in tree, but not allocated\n");
#endif
} else {
if (!(iter->second & FLAG_ALLOCATED)) {
#ifdef VL_LEAK_CHECKS
nodep->v3fatalSrc("AstNode is in tree, but not allocated\n");
#endif
}
if (iter->second & FLAG_IN_TREE) {
nodep->v3fatalSrc("AstNode is already in tree at another location\n");
}
}
int or_flags = FLAG_IN_TREE | (linkable?FLAG_LINKABLE:0);
if (iter == s_nodes.end()) {
s_nodes.insert(make_pair(nodep,or_flags));
} else {
iter->second |= or_flags;
}
}
static bool okIfLinkedTo(const AstNode* nodep) {
// Someone has a pointer to this node. Is it kosher?
NodeMap::iterator iter = s_nodes.find(nodep);
if (iter == s_nodes.end()) return false;
#ifdef VL_LEAK_CHECKS
if (!(iter->second & FLAG_ALLOCATED)) return false;
#endif
if (!(iter->second & FLAG_IN_TREE)) return false;
if (!(iter->second & FLAG_LINKABLE)) return false;
return true;
}
static void prepForTree() {
#ifndef VL_LEAK_CHECKS
s_nodes.clear();
#endif
for (NodeMap::iterator it = s_nodes.begin(); it != s_nodes.end(); ++it) {
it->second &= ~FLAG_IN_TREE;
it->second &= ~FLAG_LINKABLE;
}
}
static void doneWithTree() {
for (int backs=0; backs<2; backs++) { // Those with backp() are probably under one leaking without
for (NodeMap::iterator it = s_nodes.begin(); it != s_nodes.end(); ++it) {
if ((it->second & FLAG_ALLOCATED)
&& !(it->second & FLAG_IN_TREE)
&& !(it->second & FLAG_LEAKED)
&& (it->first->backp() ? backs==1 : backs==0)) {
// Use only AstNode::dump instead of the virtual one, as there
// may be varp() and other cross links that are bad.
if (debug()) {
cout<<"%Error: LeakedNode"<<(it->first->backp()?"Back: ":": ");
((AstNode*)(it->first))->AstNode::dump(cout);
cout<<endl;
V3Error::incErrors();
}
it->second |= FLAG_LEAKED;
}
}
}
}
public:
// CONSTUCTORS
@ -65,11 +146,11 @@ public:
virtual ~BrokenTable() {}
};
BrokenTable::NodeSet BrokenTable::s_nodes;
BrokenTable::NodeMap BrokenTable::s_nodes;
bool AstNode::brokeExists() const {
// Called by node->broken() routines to do table lookup
return BrokenTable::exists(this);
return BrokenTable::okIfLinkedTo(this);
}
//######################################################################
@ -82,9 +163,7 @@ private:
// // so userp and friends may not be used
// VISITORS
virtual void visit(AstNode* nodep, AstNUser*) {
if (nodep->maybePointedTo()) {
BrokenTable::add(nodep);
}
BrokenTable::addInTree(nodep, nodep->maybePointedTo());
nodep->iterateChildren(*this);
}
public:
@ -127,8 +206,15 @@ public:
void V3Broken::brokenAll(AstNetlist* nodep) {
//UINFO(9,__FUNCTION__<<": "<<endl);
BrokenTable::clear();
BrokenTable::prepForTree();
BrokenMarkVisitor mvisitor (nodep);
BrokenCheckVisitor cvisitor (nodep);
BrokenTable::clear();
BrokenTable::doneWithTree();
}
void V3Broken::addNewed(AstNode* nodep) {
BrokenTable::addNewed(nodep);
}
void V3Broken::deleted(AstNode* nodep) {
BrokenTable::deleted(nodep);
}

View File

@ -31,6 +31,8 @@
class V3Broken {
public:
static void brokenAll(AstNetlist* nodep);
static void addNewed(AstNode* nodep);
static void deleted(AstNode* nodep);
};
#endif // Guard

View File

@ -218,7 +218,10 @@ private:
a++, b++) {
if (m_valueItem[a] != m_valueItem[b]) { same=false; break; }
}
if (same) return tree0p;
if (same) {
tree1p->deleteTree(); tree1p=NULL;
return tree0p;
}
// Must have differing logic, so make a selection
@ -245,8 +248,7 @@ private:
// CASEx(cexpr,....
// -> tree of IF(msb, IF(msb-1, 11, 10)
// IF(msb-1, 01, 00))
AstNode* cexprp = nodep->exprp();
cexprp->unlinkFrBack();
AstNode* cexprp = nodep->exprp()->unlinkFrBack();
if (debug()>=9) {
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
@ -264,6 +266,8 @@ private:
if (ifrootp) nodep->replaceWith(ifrootp);
else nodep->unlinkFrBack();
nodep->deleteTree(); nodep=NULL;
cexprp->deleteTree(); cexprp=NULL;
if (debug()>=9) ifrootp->dumpTree(cout," _simp: ");
}
@ -304,6 +308,7 @@ private:
and2p = new AstAnd(itemp->fileline(),
new AstConst(itemp->fileline(), numval),
new AstConst(itemp->fileline(), nummask));
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
} else {
// Not a caseX mask, we can simply build CASEEQ(cexpr icond)
and1p = cexprp->cloneTree(false);
@ -320,6 +325,7 @@ private:
itemp->condsp(ifexprp);
}
}
cexprp->deleteTree(); cexprp=NULL;
if (!hadDefault) {
// If there was no default, add a empty one, this greatly simplifies below code
// and constant propagation will just eliminate it for us later.

View File

@ -384,6 +384,8 @@ private:
int shift1 = shift1p->castConst()->asInt(); if (lhsp->castShiftR()) shift1=-shift1;
int shift2 = shift2p->castConst()->asInt(); if (nodep->castShiftR()) shift2=-shift2;
int newshift = shift1+shift2;
shift1p->deleteTree(); shift1p=NULL;
shift2p->deleteTree(); shift1p=NULL;
AstNode* newp;
V3Number mask1 (nodep->fileline(), nodep->width());
V3Number ones (nodep->fileline(), nodep->width());
@ -524,7 +526,8 @@ private:
if (debug()>=9) asn1p->dumpTree(cout," _new: ");
if (debug()>=9) asn2p->dumpTree(cout," _new: ");
// Cleanup
nodep->unlinkFrBack()->deleteTree();
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
conp->deleteTree(); conp=NULL;
// Further reduce, either node may have more reductions.
return true;
}
@ -637,6 +640,7 @@ private:
// If bp was a concat, then we have this exact same form again!
// Recurse rather then calling node->iterate to prevent 2^n recursion!
if (operandConcatMove(abConcp)) moveConcat(abConcp);
bcConcp->deleteTree(); bcConcp=NULL;
} else {
AstConcat* abConcp = nodep->lhsp()->castConcat(); abConcp->unlinkFrBack();
AstNode* ap = abConcp->lhsp()->unlinkFrBack();
@ -647,6 +651,7 @@ private:
nodep->lhsp(ap);
nodep->rhsp(bcConcp);
if (operandConcatMove(bcConcp)) moveConcat(bcConcp);
abConcp->deleteTree(); abConcp=NULL;
}
}
@ -677,6 +682,8 @@ private:
if (lsb1p->castConst() && lsb2p->castConst()) {
newlsbp = new AstConst(lsb1p->fileline(),
lsb1p->castConst()->asInt() + lsb2p->castConst()->asInt());
lsb1p->deleteTree(); lsb1p=NULL;
lsb2p->deleteTree(); lsb2p=NULL;
} else {
// Width is important, we need the width of the fromp's
// expression, not the potentially smaller lsb1p's width
@ -860,7 +867,7 @@ private:
new AstAssign(nodep->fileline(),
varrefp, exprp));
m_modp->addStmtp(newinitp);
nodep->unlinkFrBack(); nodep=NULL;
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
// Set the initial value right in the variable so we can constant propagate
AstNode* initvaluep = exprp->cloneTree(false);
varrefp->varp()->initp(initvaluep);

View File

@ -110,18 +110,6 @@ private:
}
AstVarScope* createVarSc(AstVarScope* oldvarscp, string name, int width/*0==fromoldvar*/) {
// Because we've already scoped it, we may need to add both the AstVar and the AstVarScope
AstRange* rangep = NULL;
if (width==0) {
rangep = new AstRange(oldvarscp->fileline(),
oldvarscp->varp()->msb(),
oldvarscp->varp()->lsb());
} else if (width==1) {
rangep = NULL;
} else {
rangep = new AstRange(oldvarscp->fileline(),
width-1, 0);
}
if (!oldvarscp->scopep()) oldvarscp->v3fatalSrc("Var unscoped");
AstVar* varp;
AstModule* addmodp = oldvarscp->scopep()->modp();
@ -131,6 +119,17 @@ private:
// Created module's AstVar earlier under some other scope
varp = iter->second;
} else {
AstRange* rangep = NULL;
if (width==0) {
rangep = new AstRange(oldvarscp->fileline(),
oldvarscp->varp()->msb(),
oldvarscp->varp()->lsb());
} else if (width==1) {
rangep = NULL;
} else {
rangep = new AstRange(oldvarscp->fileline(),
width-1, 0);
}
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, rangep);
if (width==0) varp->widthSignedFrom(oldvarscp);
addmodp->addStmtp(varp);

View File

@ -22,6 +22,7 @@
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <set>
#include "V3Error.h"
#ifndef _V3ERROR_NO_GLOBAL_
# include "V3Ast.h"
@ -170,6 +171,46 @@ void FileLine::v3errorEnd(ostringstream& str) {
V3Error::v3errorEnd(str);
}
}
#ifdef VL_LEAK_CHECKS
typedef set<FileLine*> FileLineCheckSet;
FileLineCheckSet fileLineLeakChecks;
void* FileLine::operator new(size_t size) {
FileLine* objp = static_cast<FileLine*>(::operator new(size));
fileLineLeakChecks.insert(objp);
return objp;
}
void FileLine::operator delete(void* objp, size_t size) {
if (!objp) return;
FileLine* flp = static_cast<FileLine*>(objp);
FileLineCheckSet::iterator it = fileLineLeakChecks.find(flp);
if (it != fileLineLeakChecks.end()) {
fileLineLeakChecks.erase(it);
} else {
flp->v3fatalSrc("Deleting FileLine object that was never tracked\n");
}
::operator delete(objp);
}
#endif
void FileLine::deleteAllRemaining() {
#ifdef VL_LEAK_CHECKS
// FileLines are allocated, but never nicely freed, as it's much faster
// that way. Unfortunately this makes our leak checking a big mess, so
// only when leak checking we'll track them all and cleanup.
while (1) {
FileLineCheckSet::iterator it=fileLineLeakChecks.begin();
if (it==fileLineLeakChecks.end()) break;
delete *it;
// Operator delete will remove the iterated object from the list.
// Eventually the list will be empty and terminate the loop.
}
fileLineLeakChecks.clear();
#endif
}
//######################################################################
// V3Error class functions

View File

@ -117,8 +117,6 @@ class V3Error {
static ostringstream s_errorStr; // Error string being formed
static V3ErrorCode s_errorCode; // Error string being formed will abort
enum MaxErrors { MAX_ERRORS = 50 }; // Fatal after this may errors
static void incErrors();
static void incWarnings();
V3Error() { cerr<<("Static class"); abort(); }
@ -132,6 +130,8 @@ class V3Error {
static int warnCount() { return s_warnCount; }
static int errorOrWarnCount() { return errorCount()+warnCount(); }
// METHODS
static void incErrors();
static void incWarnings();
static void init();
static void abortIfErrors();
static void abortIfWarnings();
@ -199,9 +199,14 @@ protected:
void incLineno() { m_lineno++; }
FileLine* copyOrSameFileLine();
public:
FileLine (const string& filename, int lineno) { m_lineno=lineno; m_filename = filename; m_warnOff=s_defaultFileLine.m_warnOff;}
FileLine (FileLine* fromp) { m_lineno=fromp->lineno(); m_filename = fromp->filename(); m_warnOff=fromp->m_warnOff;};
FileLine (EmptySecret) { m_lineno=0; m_filename="COMMAND_LINE"; m_warnOff=0; } // Only for static constructor
FileLine (const string& filename, int lineno) { m_lineno=lineno; m_filename = filename; m_warnOff=s_defaultFileLine.m_warnOff; }
FileLine (FileLine* fromp) { m_lineno=fromp->lineno(); m_filename = fromp->filename(); m_warnOff=fromp->m_warnOff; }
FileLine (EmptySecret) { m_lineno=0; m_filename="COMMAND_LINE"; m_warnOff=0; }
~FileLine() { }
#ifdef VL_LEAK_CHECKS
static void* operator new(size_t size);
static void operator delete(void* obj, size_t size);
#endif
static FileLine& defaultFileLine() { return s_defaultFileLine; }
int lineno () const { return m_lineno; }
string ascii() const;
@ -218,6 +223,8 @@ public:
void v3errorEnd(ostringstream& str);
inline bool operator==(FileLine rhs) { return (m_lineno==rhs.m_lineno && m_filename==rhs.m_filename); }
static void deleteAllRemaining();
};
ostream& operator<<(ostream& os, FileLine* fileline);

View File

@ -531,6 +531,8 @@ private:
rhsp, lsb)));
}
}
rhsp->deleteTree(); rhsp=NULL;
destp->deleteTree(); destp=NULL;
} else {
UINFO(8," ASSIGNSEL(const,narrow) "<<nodep<<endl);
if (destp->isQuad() && !rhsp->isQuad()) rhsp = new AstCast(nodep->fileline(), rhsp, nodep);

View File

@ -151,7 +151,7 @@ private:
// Remove the cell
newmodp->deleteTree(); newmodp=NULL; // Clear any leftover ports, etc
nodep->unlinkFrBack();
nodep = NULL;
pushDeletep(nodep); nodep = NULL;
if (debug()>=9) { m_modp->dumpTree(cout,"donemod:"); }
}
}
@ -332,14 +332,14 @@ private:
} else {
m_modp->user(1);
}
nodep->unlinkFrBack(); nodep=NULL; // Remove so don't propagate to upper cell...
nodep->unlinkFrBack()->deleteTree(); nodep=NULL; // Remove so don't propagate to upper cell...
} else if (nodep->pragType() == AstPragmaType::NO_INLINE_MODULE) {
if (!m_modp) {
nodep->v3error("Inline pragma not under a module");
} else {
cantInline("Pragma NO_INLINE_MODULE");
}
nodep->unlinkFrBack(); nodep=NULL; // Remove so don't propagate to upper cell...
nodep->unlinkFrBack()->deleteTree(); nodep=NULL; // Remove so don't propagate to upper cell...
} else {
nodep->iterateChildren(*this);
}

View File

@ -165,7 +165,7 @@ private:
if ((findvarp->isIO() && nodep->isSignal())
|| (findvarp->isSignal() && nodep->isIO())) {
findvarp->combineType(nodep);
nodep->unlinkFrBack(); nodep=NULL;
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
} else {
nodep->v3error("Duplicate declaration of signal: "<<nodep->prettyName());
findvarp->v3error("... Location of original declaration");

View File

@ -155,6 +155,9 @@ public:
void movedVertex(OrderVisitor* ovp, OrderMoveVertex* vertexp); // Mark one vertex as finished, remove from ready list if done
// STATIC MEMBERS (for lookup)
static void clear() {
for (DomScopeMap::iterator it=s_dsMap.begin(); it!=s_dsMap.end(); ++it) {
delete it->second;
}
s_dsMap.clear();
}
V3List<OrderMoveVertex*>& readyVertices() { return m_readyVertices; }
@ -426,15 +429,18 @@ private:
m_finder.main(m_topScopep);
// ProcessDomainsIterate will use these when it needs to move
// something to a combodomain. This saves a ton of find() operations.
AstSenTree comb (nodep->fileline(), // Gets cloned() so ok if goes out of scope
new AstSenItem(nodep->fileline(), AstSenItem::Combo()));
m_comboDomainp = m_finder.getSenTree(nodep->fileline(), &comb);
AstSenTree settle (nodep->fileline(), // Gets cloned() so ok if goes out of scope
new AstSenItem(nodep->fileline(), AstSenItem::Settle()));
m_settleDomainp = m_finder.getSenTree(nodep->fileline(), &settle);
AstSenTree* combp = new AstSenTree (nodep->fileline(), // Gets cloned() so ok if goes out of scope
new AstSenItem(nodep->fileline(), AstSenItem::Combo()));
m_comboDomainp = m_finder.getSenTree(nodep->fileline(), combp);
pushDeletep(combp); // Cleanup when done
AstSenTree* settlep = new AstSenTree (nodep->fileline(), // Gets cloned() so ok if goes out of scope
new AstSenItem(nodep->fileline(), AstSenItem::Settle()));
m_settleDomainp = m_finder.getSenTree(nodep->fileline(), settlep);
pushDeletep(settlep); // Cleanup when done
// Fake AstSenTree we set domainp to indicate needs deletion
m_deleteDomainp = new AstSenTree (nodep->fileline(),
new AstSenItem(nodep->fileline(), AstSenItem::Settle()));
pushDeletep(m_deleteDomainp); // Cleanup when done
UINFO(5," DeleteDomain = "<<m_deleteDomainp<<endl);
// Base vertices
m_activeSenVxp = NULL;

View File

@ -57,10 +57,10 @@ protected:
s_preprocp->debug(debug());
// Default defines
FileLine* prefl = new FileLine("INTERNAL_VERILATOR_DEFINE",0);
s_preprocp->define(prefl,"verilator", "1");
s_preprocp->define(prefl,"verilator3", "1");
s_preprocp->define(prefl,"systemc_clock", "/*verilator systemc_clock*/");
s_preprocp->define(prefl,"coverage_block_off", "/*verilator coverage_block_off*/");
s_preprocp->define(prefl,"verilator", "1"); // LEAK_OK
s_preprocp->define(prefl,"verilator3", "1"); // LEAK_OK
s_preprocp->define(prefl,"systemc_clock", "/*verilator systemc_clock*/"); // LEAK_OK
s_preprocp->define(prefl,"coverage_block_off", "/*verilator coverage_block_off*/"); // LEAK_OK
}
}

View File

@ -78,6 +78,19 @@ void V3Read::statePop() { s_readp->m_lexerp->statePop(); }
//######################################################################
// Read class functions
V3Read::~V3Read() {
for (deque<string*>::iterator it = m_stringps.begin(); it != m_stringps.end(); ++it) {
delete (*it);
}
m_stringps.clear();
for (deque<V3Number*>::iterator it = m_numberps.begin(); it != m_numberps.end(); ++it) {
delete (*it);
}
m_numberps.clear();
if (m_lexerp) { delete m_lexerp; m_lexerp = NULL; }
parserClear();
}
void V3Read::readFile(FileLine* fileline, const string& modfilename, bool inLibrary) {
string modname = V3Options::filenameNonExt(modfilename);

View File

@ -110,16 +110,8 @@ public:
m_inBeginKwd = 0;
m_lastVerilogState = stateVerilogRecent();
}
~V3Read() {
for (deque<string*>::iterator it = m_stringps.begin(); it != m_stringps.end(); ++it) {
delete (*it);
}
m_stringps.clear();
for (deque<V3Number*>::iterator it = m_numberps.begin(); it != m_numberps.end(); ++it) {
delete (*it);
}
m_numberps.clear();
}
~V3Read();
void parserClear();
// METHODS
// Preprocess and read the Verilog file specified into the netlist database

View File

@ -349,6 +349,7 @@ private:
// Connect to this exact variable
AstVarScope* localVscp = varrefp->varScopep(); if (!localVscp) varrefp->v3fatalSrc("Null var scope");
portp->user2p(localVscp);
pushDeletep(pinp);
} else {
pinp->v3warn(TASKNSVAR,"Unsupported: Function/task input argument is not simple variable");
}

View File

@ -95,6 +95,8 @@ private:
|| (rhsp->castConst() && rhsp->castConst()->num().isFourState()))) {
V3Number num (nodep->fileline(), 1, (nodep->castEqCase()?0:1));
newp = new AstConst (nodep->fileline(), num);
lhsp->deleteTree(); lhsp=NULL;
rhsp->deleteTree(); rhsp=NULL;
} else {
if (nodep->castEqCase())
newp = new AstEq (nodep->fileline(), lhsp, rhsp);
@ -221,6 +223,7 @@ private:
if (debug()>=9) newref1p->dumpTree(cout," _new: ");
if (debug()>=9) newvarp->dumpTree(cout," _new: ");
if (debug()>=9) newinitp->dumpTree(cout," _new: ");
nodep->deleteTree(); nodep=NULL;
}
}
}

View File

@ -198,6 +198,7 @@ private:
constInitp->num(),
condBip, constStopp->num(),
incInstrp, constIncp->num()); nodep = NULL;
// Cleanup
return true;
}
@ -229,7 +230,6 @@ private:
loopValue.opAssign(numInit);
AstNode* newbodysp = NULL;
AstNode* clonedIncsp = NULL; // Last cloned incp() statements
m_statLoops++;
if (stmtsp) {
int times = 0;
@ -244,25 +244,8 @@ private:
// Replace iterator values with constant.
AstNode* oneloopp = stmtsp->cloneTree(true);
// A nicer way to propage the loop constant would be to set the variable to the value
// and call a constant-propagator like V3Table, so temp values
// that are calculated propagate down.
// If we do this, we can remove the below
if (nodep->castWhile() && incp) {
if (clonedIncsp) {
// Previous iteration of loop set the variable.
// This set is redundant with this next iteration and can be removed.
if (clonedIncsp == newbodysp) { // Increment was only thing in list
newbodysp = NULL;
} else {
clonedIncsp->unlinkFrBack();
}
clonedIncsp->deleteTree();
}
clonedIncsp = incp->clonep(); if (!clonedIncsp) nodep->v3fatalSrc("inc failed");
}
m_varValuep = new AstConst(nodep->fileline(), loopValue);
m_varModeReplace = true;
oneloopp->iterateAndNext(*this);
m_varModeReplace = false;
@ -280,6 +263,8 @@ private:
V3Number newnum(nodep->fileline(), m_forVarp->width()); // Can't increment in-place
incInstrp->numberOperate(newnum, loopValue, numInc);
loopValue.opAssign(newnum);
pushDeletep(m_varValuep); m_varValuep=NULL;
}
}
}
@ -287,6 +272,9 @@ private:
// Replace the FOR()
if (newbodysp) nodep->replaceWith(newbodysp);
else nodep->unlinkFrBack();
if (bodysp) { pushDeletep(bodysp); bodysp=NULL; }
if (precondsp) { pushDeletep(precondsp); precondsp=NULL; }
if (initp) { pushDeletep(initp); initp=NULL; }
if (debug()>=9) newbodysp->dumpTree(cout,"- _new: ");
}
@ -311,7 +299,7 @@ private:
if (forUnrollCheck(nodep, initp,
nodep->precondsp(), nodep->condp(),
incp, nodep->bodysp())) {
nodep=NULL; // Did replacement
pushDeletep(nodep); nodep=NULL; // Did replacement
}
}
}
@ -328,7 +316,7 @@ private:
if (forUnrollCheck(nodep, nodep->initsp(),
NULL, nodep->condp(),
nodep->incsp(), nodep->bodysp())) {
nodep=NULL; // Did replacement
pushDeletep(nodep); nodep=NULL; // Did replacement
} else {
nodep->v3error("For loop doesn't have genvar index, or is misformed");
}
@ -373,6 +361,7 @@ private:
&& !nodep->lvalue()) {
AstNode* newconstp = m_varValuep->cloneTree(false);
nodep->replaceWith(newconstp);
pushDeletep(nodep);
}
}

View File

@ -760,6 +760,7 @@ void WidthVisitor::fixWidthExtend (AstNode* nodep, int expWidth) {
AstNode* newp = new AstConst(nodep->fileline(), num);
newp->signedFrom(constp);
constp->replaceWith(newp);
pushDeletep(constp); constp=NULL;
nodep=newp;
} else if (expWidth<nodep->width()) {
// Trunc - Extract

View File

@ -552,6 +552,7 @@ int main(int argc, char** argv, char** env) {
// Cleanup memory for valgrind leak analysis
v3Global.clear();
#endif
FileLine::deleteAllRemaining();
UINFO(1,"Done, Exiting...\n");
}

View File

@ -66,6 +66,10 @@ public:
nodep->addNext(new AstStop(fileline));
return nodep;
}
static void setRange(AstRange* rangep) {
if (s_varRangep) { s_varRangep->deleteTree(); s_varRangep=NULL; } // It was cloned, so this is safe.
s_varRangep = rangep;
}
static string deQuote(FileLine* fileline, string text);
};
@ -88,7 +92,7 @@ AstCase* V3Parse::s_caseAttrp = NULL;
#define VARDECL(type) { V3Parse::s_varDecl = AstVarType::type; }
#define VARIO(type) { V3Parse::s_varIO = AstVarType::type; }
#define VARSIGNED(value) { V3Parse::s_varSigned = value; }
#define VARRANGE(range) { V3Parse::s_varRangep=(range); }
#define VARRANGE(rangep) { V3Parse::setRange(rangep); }
#define INSTPREP(modname,paramsp) { V3Parse::s_impliedDecl = true; V3Parse::s_instModule = modname; V3Parse::s_instParamp = paramsp; }
@ -858,8 +862,8 @@ stmt: ';' { $$ = NULL; }
| yD_ERROR parenE ';' { $$ = V3Parse::createDisplayError($1); }
| yD_ERROR '(' yaSTRING commaEListE ')' ';' { $$ = new AstDisplay($1,AstDisplayType::ERROR, *$3,NULL,$4); $$->addNext(new AstStop($1)); }
| yD_FATAL parenE ';' { $$ = new AstDisplay($1,AstDisplayType::FATAL, "", NULL,NULL); $$->addNext(new AstStop($1)); }
| yD_FATAL '(' expr ')' ';' { $$ = new AstDisplay($1,AstDisplayType::FATAL, "", NULL,NULL); $$->addNext(new AstStop($1)); }
| yD_FATAL '(' expr ',' yaSTRING commaEListE ')' ';' { $$ = new AstDisplay($1,AstDisplayType::FATAL, *$5,NULL,$6); $$->addNext(new AstStop($1)); }
| yD_FATAL '(' expr ')' ';' { $$ = new AstDisplay($1,AstDisplayType::FATAL, "", NULL,NULL); $$->addNext(new AstStop($1)); if ($3) $3->deleteTree(); }
| yD_FATAL '(' expr ',' yaSTRING commaEListE ')' ';' { $$ = new AstDisplay($1,AstDisplayType::FATAL, *$5,NULL,$6); $$->addNext(new AstStop($1)); if ($3) $3->deleteTree(); }
| yD_READMEMB '(' expr ',' varRefMem ')' ';' { $$ = new AstReadMem($1,false,$3,$5,NULL,NULL); }
| yD_READMEMB '(' expr ',' varRefMem ',' expr ')' ';' { $$ = new AstReadMem($1,false,$3,$5,$7,NULL); }
@ -1314,6 +1318,11 @@ pslExpr: exprPsl { $$ = new AstPslBool($1->fileline(), $1); }
//**********************************************************************
%%
void V3Read::parserClear() {
// Clear up any dynamic memory V3Parser required
V3Parse::setRange(NULL);
}
AstNode* V3Parse::createSupplyExpr(FileLine* fileline, string name, int value) {
FileLine* newfl = new FileLine (fileline);
newfl->warnOff(V3ErrorCode::WIDTH, true);
@ -1328,6 +1337,7 @@ AstNode* V3Parse::createSupplyExpr(FileLine* fileline, string name, int value) {
AstVar* V3Parse::createVariable(FileLine* fileline, string name, AstRange* arrayp) {
AstVarType type = V3Parse::s_varIO;
AstRange* rangep = V3Parse::s_varRangep;
AstRange* cleanup_rangep = NULL;
//UINFO(0,"CREVAR "<<fileline->ascii()<<" decl="<<V3Parse::s_varDecl.ascii()<<" io="<<V3Parse::s_varIO.ascii()<<endl);
if (type == AstVarType::UNKNOWN) type = V3Parse::s_varDecl;
if (type == AstVarType::UNKNOWN) fileline->v3fatalSrc("Unknown signal type declared");
@ -1335,7 +1345,8 @@ AstVar* V3Parse::createVariable(FileLine* fileline, string name, AstRange* array
if (type == AstVarType::INTEGER || V3Parse::s_varDecl == AstVarType::INTEGER
|| type == AstVarType::GENVAR) {
if (rangep) fileline->v3error("Integers may not be ranged: "<<name);
rangep = new AstRange(fileline, 31, 0); // Integer == REG[31:0]
cleanup_rangep = new AstRange(fileline, 31, 0); // Integer == REG[31:0]
rangep = cleanup_rangep;
}
if (type == AstVarType::GENVAR) {
if (arrayp) fileline->v3error("Genvars may not be arrayed: "<<name);
@ -1363,6 +1374,7 @@ AstVar* V3Parse::createVariable(FileLine* fileline, string name, AstRange* array
// Remember the last variable created, so we can attach attributes to it in later parsing
V3Parse::s_varAttrp = nodep;
if (cleanup_rangep) { cleanup_rangep->deleteTree(); cleanup_rangep=NULL; }
return nodep;
}