diff --git a/bin/verilator_difftree b/bin/verilator_difftree index a8f88da63..c7e92b228 100755 --- a/bin/verilator_difftree +++ b/bin/verilator_difftree @@ -62,6 +62,7 @@ sub diff_dir { (my $base = $fn) =~ s!.*/!!; $files{$base}{b} = $fn; } + my $any; foreach my $base (sort (keys %files)) { my $a = $files{$base}{a}; my $b = $files{$base}{b}; @@ -70,6 +71,7 @@ sub diff_dir { print "= $a <-> $b\n"; diff_file($a,$b); } + $any or warn "%Warning: No .tree files found\n"; } sub diff_file { diff --git a/src/V3Ast.h b/src/V3Ast.h index 988c383e5..76eeaab24 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -32,6 +32,9 @@ // Things like: // class V3AstNode; +// Hint class so we can choose constructors +class AstLogicPacked {}; + //###################################################################### class AstType { @@ -1184,7 +1187,9 @@ struct AstNodeDType : public AstNode { AstNodeDType(FileLine* fl) : AstNode(fl) {} ASTNODE_BASE_FUNCS(NodeDType) // Accessors - AstRange* rangep(); + virtual AstBasicDType* basicp() = 0; // (Slow) recurse down to find basic data type + virtual int widthAlignBytes() const = 0; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) + virtual int widthTotalBytes() const = 0; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... }; struct AstNodeSel : public AstNodeBiop { diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 2c725f5e0..5a00cb860 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -35,11 +35,6 @@ //====================================================================== // Special methods -AstRange* AstNodeDType::rangep() { - if (castBasicDType()) return castBasicDType()->rangep(); - else return NULL; -} - // We need these here, because the classes they point to aren't defined when we declare the class bool AstNodeVarRef::broken() const { return ((m_varScopep && !m_varScopep->brokeExists()) || (m_varp && !m_varp->brokeExists())); } @@ -52,6 +47,20 @@ int AstNodeSel::bitConst() const { AstConst* constp=bitp()->castConst(); return (constp?constp->toSInt():0); } +int AstBasicDType::widthAlignBytes() const { + if (width()<=8) return 1; + else if (width()<=16) return 2; + else if (isQuad()) return 8; + else return 4; +} + +int AstBasicDType::widthTotalBytes() const { + if (width()<=8) return 1; + else if (width()<=16) return 2; + else if (isQuad()) return 8; + else return widthWords()*(VL_WORDSIZE/8); +} + bool AstVar::isSigPublic() const { return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar())); } @@ -77,20 +86,6 @@ void AstVar::combineType(AstVarType type) { m_tristate = true; } -int AstVar::widthAlignBytes() const { - if (width()<=8) return 1; - else if (width()<=16) return 2; - else if (isSc() ? isScQuad() : isQuad()) return 8; - else return 4; -} - -int AstVar::widthTotalBytes() const { - if (width()<=8) return 1; - else if (width()<=16) return 2; - else if (isSc() ? isScQuad() : isQuad()) return 8; - else return widthWords()*(VL_WORDSIZE/8); -} - string AstVar::verilogKwd() const { if (isInout()) { return "inout"; @@ -137,32 +132,61 @@ string AstVar::scType() const { } } -AstRange* AstVar::arrayp(int dimension) const { - for (AstRange* arrayp=this->arraysp(); arrayp; arrayp = arrayp->nextp()->castRange()) { - if ((dimension--)==0) return arrayp; +AstNodeDType* AstVar::dtypeDimensionp(int dimension) const { + // dimension passed from AstArraySel::dimension + // Dimension 0 means the VAR itself, 1 is the closest SEL to the AstVar, + // which is the lowest in the dtype list. + // ref order: a[1][2][3][4] + // Created as: reg [4] a [1][2][3]; + // *or* reg a [1][2][3][4]; + // // The bit select is optional; used only if "leftover" []'s + // SEL: SEL4(SEL3(SEL2(SEL1(VARREF0 a)))) + // DECL: VAR a (ARRAYSEL0 (ARRAYSEL1 (ARRAYSEL2 (DT RANGE3)))) + // *or* VAR a (ARRAYSEL0 (ARRAYSEL1 (ARRAYSEL2 (ARRAYSEL3 (DT)))) + // SEL1 needs to select from entire variable which is a pointer to ARRAYSEL0 + int dim = 0; + for (AstNodeDType* dtypep=this->dtypep(); dtypep; ) { + if (AstArrayDType* adtypep = dtypep->castArrayDType()) { + if ((dim++)==dimension) { + return dtypep; + } + dtypep = adtypep->dtypep(); + continue; + } else if (AstBasicDType* adtypep = dtypep->castBasicDType()) { + // AstBasicDType - nothing below, return null + if (adtypep->rangep()) { + if ((dim++) == dimension) { + return adtypep; + } + } + return NULL; + } + // Node no ->next in loop; use continue where necessary + break; } return NULL; } -int AstVar::arrayDimensions() const { - int entries=0; - for (AstRange* arrayp=this->arraysp(); arrayp; arrayp = arrayp->nextp()->castRange()) { - entries++; - } - return entries; -} - uint32_t AstVar::arrayElements() const { uint32_t entries=1; - for (AstRange* arrayp=this->arraysp(); arrayp; arrayp = arrayp->nextp()->castRange()) { - entries *= arrayp->elementsConst(); + for (AstNodeDType* dtypep=this->dtypep(); dtypep; ) { + if (AstArrayDType* adtypep = dtypep->castArrayDType()) { + entries *= adtypep->elementsConst(); + dtypep = adtypep->dtypep(); + } else { + // AstBasicDType - nothing below, 1 + break; + } } return entries; } // Special operators -int AstArraySel::dimension(AstNode* nodep) { ///< How many dimensions is this reference from the base variable? - // Only called after V3Param; so only ArraySel's need to be recursed +int AstArraySel::dimension(AstNode* nodep) { + // How many dimensions is this reference from the base variable? + // nodep is typically the fromp() of a select; thus the first select + // is selecting from the entire variable type - effectively dimension 0. + // Dimension passed to AstVar::dtypeDimensionp; see comments there int dim = 0; while (nodep) { if (nodep->castNodeSel()) { dim++; nodep=nodep->castNodeSel()->fromp(); continue; } diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index b42a35cc5..d9e840ba8 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -105,6 +105,31 @@ public: virtual bool same(AstNode* samep) const { return true; } }; +//###################################################################### +//==== Data Types + +struct AstArrayDType : public AstNodeDType { + AstArrayDType(FileLine* fl, AstNodeDType* dtypep, AstRange* rangep) + : AstNodeDType(fl) { + setOp1p(dtypep); + setOp2p(rangep); + widthSignedFrom(dtypep); + } + ASTNODE_NODE_FUNCS(ArrayDType, ARRAYDTYPE) + AstNodeDType* dtypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable + void dtypep(AstNodeDType* nodep) { setOp1p(nodep); } + AstRange* arrayp() const { return op2p()->castRange(); } // op2 = Array(s) of variable + void arrayp(AstRange* nodep) { setOp2p(nodep); } + // METHODS + virtual AstBasicDType* basicp() { return dtypep()->basicp(); } // (Slow) recurse down to find basic data type + virtual int widthAlignBytes() const { return dtypep()->widthAlignBytes(); } + virtual int widthTotalBytes() const { return elementsConst() * dtypep()->widthTotalBytes(); } + int msb() const { return arrayp()->msbConst(); } + int lsb() const { return arrayp()->lsbConst(); } + int elementsConst() const { return arrayp()->elementsConst(); } + int msbMaxSelect() const { return (lsb()<0 ? msb()-lsb() : msb()); } // Maximum value a [] select may index +}; + struct AstBasicDType : public AstNodeDType { // Builtin atomic/vectored data type private: @@ -112,11 +137,17 @@ private: bool m_implicit; // Implicitly declared public: AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, AstRange* rangep=NULL, AstSignedState signst=signedst_NOP) - : AstNodeDType(fl), m_keyword(kwd) { - init(signst, rangep); + : AstNodeDType(fl) { + init(kwd, signst, rangep); + } + AstBasicDType(FileLine* fl, AstLogicPacked, int wantwidth) + : AstNodeDType(fl) { + init(AstBasicDTypeKwd::LOGIC, signedst_NOP, + ((wantwidth > 1) ? new AstRange(fl, wantwidth-1, 0) : NULL)); } private: - void init(AstSignedState signst, AstRange* rangep) { + void init(AstBasicDTypeKwd kwd, AstSignedState signst, AstRange* rangep) { + m_keyword = kwd; // Implicitness: // "parameter X" is implicit and sized from initial value, "parameter reg x" not m_implicit = false; if (keyword()==AstBasicDTypeKwd::LOGIC_IMPLICIT) { @@ -148,6 +179,9 @@ public: if (signst!=signedst_NOP) isSigned(signst==signedst_SIGNED); } // METHODS + virtual AstBasicDType* basicp() { return this; } // (Slow) recurse down to find basic data type + virtual int widthAlignBytes() const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) + virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... bool isBitLogic() const { return keyword().isBitLogic(); } bool isSloppy() const { return keyword().isSloppy(); } int msb() const { if (!rangep()) return 0; return rangep()->msbConst(); } @@ -159,6 +193,8 @@ public: bool implicit() const { return m_implicit; } }; +//###################################################################### + struct AstArraySel : public AstNodeSel { // Parents: math|stmt // Children: varref|arraysel, math @@ -319,21 +355,19 @@ private: m_trace=false; } public: - AstVar(FileLine* fl, AstVarType type, const string& name, AstNodeDType* dtypep, AstRange* arrayp=NULL) + AstVar(FileLine* fl, AstVarType type, const string& name, AstNodeDType* dtypep) :AstNode(fl) , m_name(name) { init(); - combineType(type); setOp1p(dtypep); addNOp2p(arrayp); + combineType(type); setOp1p(dtypep); width(msb()-lsb()+1,0); } - class LogicPacked {}; - AstVar(FileLine* fl, AstVarType type, const string& name, LogicPacked, int wantwidth) + AstVar(FileLine* fl, AstVarType type, const string& name, AstLogicPacked, int wantwidth) :AstNode(fl) , m_name(name) { init(); combineType(type); - setOp1p(new AstBasicDType(fl, AstBasicDTypeKwd::LOGIC, - ((wantwidth > 1) ? new AstRange(fl, wantwidth-1, 0) : NULL))); + setOp1p(new AstBasicDType(fl, AstLogicPacked(), wantwidth)); width(wantwidth,0); } AstVar(FileLine* fl, AstVarType type, const string& name, AstVar* examplep) @@ -344,9 +378,6 @@ public: if (examplep->dtypep()) { setOp1p(examplep->dtypep()->cloneTree(true)); } - if (examplep->arraysp()) { - setOp2p(examplep->arraysp()->cloneTree(true)); - } width(examplep->width(), examplep->widthMin()); } ASTNODE_NODE_FUNCS(Var, VAR) @@ -361,9 +392,7 @@ public: string scType() const; // Return SysC type: bool, uint32_t, uint64_t, sc_bv void combineType(AstVarType type); AstNodeDType* dtypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable - AstRange* arraysp() const { return op2p()->castRange(); } // op2 = Array(s) of variable - void addArraysp(AstNode* nodep) { addNOp2p(nodep); } - AstRange* arrayp(int dim) const; // op2 = Range for specific dimension # + AstNodeDType* dtypeDimensionp(int depth) const; AstNode* initp() const { return op3p()->castNode(); } // op3 = Initial value that never changes (static const) void initp(AstNode* nodep) { setOp3p(nodep); } void addAttrsp(AstNode* nodep) { addNOp4p(nodep); } @@ -387,6 +416,7 @@ public: void funcReturn(bool flag) { m_funcReturn = flag; } void trace(bool flag) { m_trace=flag; } // METHODS + AstBasicDType* basicp() const { return dtypep()->basicp(); } // (Slow) recurse down to find basic data type virtual void name(const string& name) { m_name = name; } bool isInput() const { return m_input; } bool isOutput() const { return m_output; } @@ -411,7 +441,7 @@ public: bool isParam() const { return (varType()==AstVarType::LPARAM || varType()==AstVarType::GPARAM); } bool isGParam() const { return (varType()==AstVarType::GPARAM); } bool isGenVar() const { return (varType()==AstVarType::GENVAR); } - bool isBitLogic() const { return dtypep()->castBasicDType() && dtypep()->castBasicDType()->isBitLogic(); } + bool isBitLogic() const { AstBasicDType* bdtypep = basicp(); return bdtypep && bdtypep->isBitLogic(); } bool isUsedClock() const { return m_usedClock; } bool isUsedParam() const { return m_usedParam; } bool isSc() const { return m_sc; } @@ -429,15 +459,11 @@ public: bool attrFileDescr() const { return m_fileDescr; } bool attrScClocked() const { return m_scClocked; } bool attrIsolateAssign() const { return m_attrIsolateAssign; } - int widthAlignBytes() const; // Structure alignment 1,2,4 or 8 bytes (arrays affect this) - int widthTotalBytes() const; // Width in bytes rounding up 1,2,4,8,12,... - int msb() const { if (!dtypep()) return 0; return dtypep()->castBasicDType()->msb(); } - int lsb() const { if (!dtypep()) return 0; return dtypep()->castBasicDType()->lsb(); } - int msbEndianed() const { if (!dtypep()) return 0; return dtypep()->castBasicDType()->msbEndianed(); } - int lsbEndianed() const { if (!dtypep()) return 0; return dtypep()->castBasicDType()->lsbEndianed(); } - int msbMaxSelect() const { if (!dtypep()) return 0; return dtypep()->castBasicDType()->msbMaxSelect(); } - bool littleEndian() const { return (dtypep() && dtypep()->castBasicDType()->littleEndian()); } - int arrayDimensions() const; + int msb() const { AstBasicDType* bdtypep = basicp(); return bdtypep ? bdtypep->msb() : 0; } + int lsb() const { AstBasicDType* bdtypep = basicp(); return bdtypep ? bdtypep->lsb() : 0; } + int msbEndianed() const { AstBasicDType* bdtypep = basicp(); return bdtypep ? bdtypep->msbEndianed() : 0; } + int lsbEndianed() const { AstBasicDType* bdtypep = basicp(); return bdtypep ? bdtypep->lsbEndianed() : 0; } + int msbMaxSelect() const { AstBasicDType* bdtypep = basicp(); return bdtypep ? bdtypep->msbMaxSelect() : 0; } uint32_t arrayElements() const; // 1, or total multiplication of all dimensions virtual string verilogKwd() const; void propagateAttrFrom(AstVar* fromp) { @@ -1695,8 +1721,13 @@ public: m_code = 0; m_codeInc = varp->arrayElements() * varp->widthWords(); m_lsb = varp->lsbEndianed(); m_msb = varp->msbEndianed(); - m_arrayLsb = varp->arrayp(0) ? varp->arrayp(0)->lsbConst() : 0; - m_arrayMsb = varp->arrayp(0) ? varp->arrayp(0)->msbConst() : 0; + if (AstArrayDType* adtypep = varp->dtypep()->castArrayDType()) { + m_arrayLsb = adtypep->arrayp()->lsbConst(); + m_arrayMsb = adtypep->arrayp()->msbConst(); + } else { + m_arrayLsb = 0; + m_arrayMsb = 0; + } } virtual int instrCount() const { return 100; } // Large... ASTNODE_NODE_FUNCS(TraceDecl, TRACEDECL) diff --git a/src/V3Begin.cpp b/src/V3Begin.cpp index 607f242b6..69177e039 100644 --- a/src/V3Begin.cpp +++ b/src/V3Begin.cpp @@ -157,7 +157,7 @@ private: // Note var can be signed or unsigned based on original number. AstNode* countp = nodep->countp()->unlinkFrBackWithNext(); string name = string("__Vrepeat")+cvtToStr(m_repeatNum++); - AstVar* varp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, name, AstVar::LogicPacked(), countp->width()); + AstVar* varp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, name, AstLogicPacked(), countp->width()); m_modp->addStmtp(varp); AstNode* initsp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true), countp); diff --git a/src/V3Changed.cpp b/src/V3Changed.cpp index 6558f03c5..07e3ad0ab 100644 --- a/src/V3Changed.cpp +++ b/src/V3Changed.cpp @@ -72,7 +72,7 @@ private: #endif AstVar* varp = vscp->varp(); vscp->v3warn(IMPERFECTSCH,"Imperfect scheduling of variable: "<arraysp()) { + if (!varp->dtypep()->castBasicDType()) { vscp->v3error("Unsupported: Can't detect changes on arrayed variable (probably with UNOPTFLAT warning suppressed): "<prettyName()); } else { string newvarname = "__Vchglast__"+vscp->scopep()->nameDotless()+"__"+varp->shortName(); diff --git a/src/V3Clean.cpp b/src/V3Clean.cpp index d04a94fb4..d00186e38 100644 --- a/src/V3Clean.cpp +++ b/src/V3Clean.cpp @@ -76,7 +76,7 @@ private: } void computeCppWidth (AstNode* nodep) { if (!nodep->user2()) { - if (nodep->castVar()) { // Don't want to change variable widths! + if (nodep->castVar() || nodep->castNodeDType()) { // Don't want to change variable widths! setCppWidth(nodep, nodep->width(), nodep->width()); // set widthMin anyways so can see it later } else { setCppWidth(nodep, cppWidth(nodep), nodep->widthMin()); diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp index 9a50e5d90..238707e8b 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -85,7 +85,7 @@ private: AstVar* varp = vscp->varp(); if (varp->width()!=1) varp->v3error("Unsupported: Clock edge on non-single bit signal: "<prettyName()); string newvarname = ((string)"__Vclklast__"+vscp->scopep()->nameDotless()+"__"+varp->shortName()); - AstVar* newvarp = new AstVar (vscp->fileline(), AstVarType::MODULETEMP, newvarname, AstVar::LogicPacked(), 1); + AstVar* newvarp = new AstVar (vscp->fileline(), AstVarType::MODULETEMP, newvarname, AstLogicPacked(), 1); newvarp->width(1,1); m_modp->addStmtp(newvarp); AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopep, newvarp); @@ -104,7 +104,7 @@ private: AstVarScope* getCreateLocalVar(FileLine* fl, const string& name, AstVar* examplep, int width) { AstVar* newvarp; if (width) { - newvarp = new AstVar (fl, AstVarType::BLOCKTEMP, name, AstVar::LogicPacked(), width); + newvarp = new AstVar (fl, AstVarType::BLOCKTEMP, name, AstLogicPacked(), width); } else { newvarp = new AstVar (fl, AstVarType::BLOCKTEMP, name, examplep); // No range; 1 bit. } diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 9fc1de8c6..c02765eec 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -306,14 +306,14 @@ private: // Extraction checks bool warnSelect(AstSel* nodep) { - AstNode* basefromp = AstArraySel::baseFromp(nodep->fromp()); + AstNode* basefromp = AstArraySel::baseFromp(nodep); if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) { AstVar* varp = varrefp->varp(); if (!varp->dtypep()) varp->v3fatalSrc("Data type lost"); if (m_warn && nodep->lsbp()->castConst() && nodep->widthp()->castConst() - && (!varp->dtypep()->rangep() || varp->msb())) { // else it's non-resolvable parameterized + && (!varp->basicp()->rangep() || varp->msb())) { // else it's non-resolvable parameterized if (nodep->lsbp()->castConst()->num().isFourState() || nodep->widthp()->castConst()->num().isFourState()) { nodep->v3error("Selection index is constantly unknown or tristated: " @@ -771,9 +771,9 @@ private: string name1 = ((string)"__Vconcswap"+cvtToStr(m_modp->varNumGetInc())); string name2 = ((string)"__Vconcswap"+cvtToStr(m_modp->varNumGetInc())); AstVar* temp1p = new AstVar(sel1p->fileline(), AstVarType::BLOCKTEMP, name1, - AstVar::LogicPacked(), msb1-lsb1+1); + AstLogicPacked(), msb1-lsb1+1); AstVar* temp2p = new AstVar(sel2p->fileline(), AstVarType::BLOCKTEMP, name2, - AstVar::LogicPacked(), msb2-lsb2+1); + AstLogicPacked(), msb2-lsb2+1); m_modp->addStmtp(temp1p); m_modp->addStmtp(temp2p); AstNodeAssign* asn1ap=nodep->cloneType diff --git a/src/V3Coverage.cpp b/src/V3Coverage.cpp index af98ead8b..ac2a4d4f7 100644 --- a/src/V3Coverage.cpp +++ b/src/V3Coverage.cpp @@ -48,6 +48,19 @@ private: // TYPES typedef map FileMap; + struct ToggleEnt { + string m_comment; // Comment for coverage dump + AstNode* m_varRefp; // How to get to this element + AstNode* m_chgRefp; // How to get to this element + ToggleEnt(const string& comment, AstNode* vp, AstNode* cp) + : m_comment(comment), m_varRefp(vp), m_chgRefp(cp) {} + ~ToggleEnt() {} + void cleanup() { + m_varRefp->deleteTree(); m_varRefp=NULL; + m_chgRefp->deleteTree(); m_chgRefp=NULL; + } + }; + // STATE bool m_checkBlock; // Should this block get covered? AstModule* m_modp; // Current module to add statement to @@ -143,12 +156,6 @@ private: // Convert to "AstCoverInc(CoverInc...)" // We'll do this, and make the if(...) coverinc later. - // Compute size of the problem - int dimensions = 0; - for (AstRange* arrayp=nodep->arraysp(); arrayp; arrayp = arrayp->nextp()->castRange()) { - dimensions++; - } - // Add signal to hold the old value string newvarname = (string)"__Vtogcov__"+nodep->shortName(); AstVar* chgVarp = new AstVar (nodep->fileline(), AstVarType::MODULETEMP, newvarname, nodep); @@ -157,61 +164,65 @@ private: // Create bucket for each dimension * bit. // This is necessarily an O(n^2) expansion, which is why // we limit coverage to signals with < 256 bits. - vector selects_docs; selects_docs.resize(dimensions); - vector selects_code; selects_code.resize(dimensions); - toggleVarRecurse(nodep, chgVarp, nodep->arraysp(), - 0, selects_docs, selects_code ); + + ToggleEnt newvec (string(""), + new AstVarRef(nodep->fileline(), nodep, false), + new AstVarRef(nodep->fileline(), chgVarp, true)); + toggleVarRecurse(nodep->dtypep(), 0, newvec, + nodep, chgVarp); + newvec.cleanup(); } } } - void toggleVarRecurse(AstVar* nodep, AstVar* chgVarp, AstRange* arrayp, - int dimension, vector& selects_docs, vector& selects_code) { - if (arrayp) { - for (int index=arrayp->lsbConst(); index<=arrayp->msbConst()+1; index++) { - // Handle the next dimension, if any - selects_docs[dimension] = index; - selects_code[dimension] = index - arrayp->lsbConst(); - toggleVarRecurse(nodep, chgVarp, arrayp->nextp()->castRange(), - dimension+1, selects_docs, selects_code); - } - } else { // No more arraying - just each bit in the width - if (nodep->msb() != nodep->lsb()) { - for (int bitindex_docs=nodep->lsb(); bitindex_docsmsb()+1; bitindex_docs++) { - toggleVarBottom(nodep, chgVarp, - dimension, selects_docs, selects_code, - true, bitindex_docs); + void toggleVarBottom(AstNodeDType* nodep, int depth, // per-iteration + const ToggleEnt& above, + AstVar* varp, AstVar* chgVarp) { // Constant + AstCoverToggle* newp + = new AstCoverToggle (varp->fileline(), + newCoverInc(varp->fileline(), "", "v_toggle", + varp->name()+above.m_comment), + above.m_varRefp->cloneTree(true), + above.m_chgRefp->cloneTree(true)); + m_modp->addStmtp(newp); + } + + void toggleVarRecurse(AstNodeDType* nodep, int depth, // per-iteration + const ToggleEnt& above, + AstVar* varp, AstVar* chgVarp) { // Constant + if (AstBasicDType* bdtypep = nodep->castBasicDType()) { + if (bdtypep->rangep()) { + for (int index_docs=bdtypep->lsb(); index_docsmsb()+1; index_docs++) { + int index_code = index_docs - bdtypep->lsb(); + ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]", + new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true), index_code, 1), + new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true), index_code, 1)); + toggleVarBottom(nodep, depth+1, + newent, + varp, chgVarp); + newent.cleanup(); } } else { - toggleVarBottom(nodep, chgVarp, - dimension, selects_docs, selects_code, - false, 0); + toggleVarBottom(nodep, depth+1, + above, + varp, chgVarp); } } - } - void toggleVarBottom(AstVar* nodep, AstVar* chgVarp, - int dimension, vector& selects_docs, vector& selects_code, - bool bitsel, int bitindex_docs) { - string comment = nodep->name(); - AstNode* varRefp = new AstVarRef(nodep->fileline(), nodep, false); - AstNode* chgRefp = new AstVarRef(nodep->fileline(), chgVarp, true); - // Now determine the name of, and how to get to the bit of this slice - for (int dim=0; dimfileline(), varRefp, selects_code[dim]); - chgRefp = new AstArraySel(nodep->fileline(), chgRefp, selects_code[dim]); + else if (AstArrayDType* adtypep = nodep->castArrayDType()) { + for (int index_docs=adtypep->lsb(); index_docs<=adtypep->msb()+1; ++index_docs) { + int index_code = index_docs - adtypep->lsb(); + ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]", + new AstArraySel(varp->fileline(), above.m_varRefp->cloneTree(true), index_code), + new AstArraySel(varp->fileline(), above.m_chgRefp->cloneTree(true), index_code)); + toggleVarRecurse(adtypep->dtypep(), depth+1, + newent, + varp, chgVarp); + newent.cleanup(); + } } - if (bitsel) { - comment += "["+cvtToStr(bitindex_docs)+"]"; - int bitindex_code = bitindex_docs - nodep->lsb(); - varRefp = new AstSel(nodep->fileline(), varRefp, bitindex_code, 1); - chgRefp = new AstSel(nodep->fileline(), chgRefp, bitindex_code, 1); + else { + nodep->v3fatalSrc("Unexpected node data type in toggle coverage generation: "<prettyTypeName()); } - AstCoverToggle* newp = new AstCoverToggle (nodep->fileline(), - newCoverInc(nodep->fileline(), "", "v_toggle", comment), - varRefp, chgRefp); - m_modp->addStmtp(newp); } // VISITORS - LINE COVERAGE diff --git a/src/V3Delayed.cpp b/src/V3Delayed.cpp index 761ea3d53..0d15f9a55 100644 --- a/src/V3Delayed.cpp +++ b/src/V3Delayed.cpp @@ -132,7 +132,7 @@ private: varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, oldvarscp->varp()); varp->widthSignedFrom(oldvarscp); } else { - varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, AstVar::LogicPacked(), width); + varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, AstLogicPacked(), width); } addmodp->addStmtp(varp); m_modVarMap.insert(make_pair(make_pair(addmodp, name), varp)); diff --git a/src/V3Depth.cpp b/src/V3Depth.cpp index f2173e74b..d13a8e83c 100644 --- a/src/V3Depth.cpp +++ b/src/V3Depth.cpp @@ -68,7 +68,7 @@ private: // Width, not widthMin, as we may be in middle of BITSEL expression which // though it's one bit wide, needs the mask in the upper bits. // (Someday we'll have a valid bitmask instead of widths....) - AstVar::LogicPacked(), nodep->width()); + AstLogicPacked(), nodep->width()); if (!m_funcp) nodep->v3fatalSrc("Deep expression not under a function"); m_funcp->addInitsp(varp); // Replace node tree with reference to var diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 0ae657717..fad5350fd 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -274,10 +274,13 @@ public: uint32_t array_lsb = 0; { AstVarRef* varrefp = nodep->memp()->castVarRef(); - if (!varrefp || !varrefp->varp()->arrayp(0)) { nodep->v3error("Readmem loading non-arrayed variable"); } - else { + if (!varrefp) { nodep->v3error("Readmem loading non-variable"); } + else if (AstArrayDType* adtypep = varrefp->varp()->dtypep()->castArrayDType()) { puts(cvtToStr(varrefp->varp()->arrayElements())); - array_lsb = varrefp->varp()->arrayp(0)->lsbConst(); + array_lsb = adtypep->lsb(); + } + else { + nodep->v3error("Readmem loading non-arrayed variable"); } } putbs(", "); @@ -770,7 +773,8 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) { puts(nodep->name()); puts(";\n"); } else { // C++ signals - ofp()->putAlign(nodep->isStatic(), nodep->widthAlignBytes()); + ofp()->putAlign(nodep->isStatic(), nodep->dtypep()->widthAlignBytes(), + nodep->dtypep()->widthTotalBytes()); if (nodep->isInout()) puts("VL_INOUT"); else if (nodep->isInput()) puts("VL_IN"); else if (nodep->isOutput()) puts("VL_OUT"); @@ -793,7 +797,8 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) { } else { // Arrays need a small alignment, but may need different padding after. // For example three VL_SIG8's needs alignment 1 but size 3. - ofp()->putAlign(nodep->isStatic(), nodep->widthAlignBytes(), nodep->arrayElements()*nodep->widthAlignBytes()); + ofp()->putAlign(nodep->isStatic(), nodep->dtypep()->widthAlignBytes(), + nodep->dtypep()->widthTotalBytes()); if (nodep->isStatic() && prefixIfImp=="") puts("static "); if (nodep->isStatic()) puts("VL_ST_"); else puts("VL_"); if (nodep->widthMin() <= 8) { @@ -809,7 +814,8 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) { } if (prefixIfImp!="") { puts(prefixIfImp); puts("::"); } puts(nodep->name()); - for (AstRange* arrayp=nodep->arraysp(); arrayp; arrayp = arrayp->nextp()->castRange()) { + // This isn't very robust and may need cleanup for other data types + for (AstArrayDType* arrayp=nodep->dtypep()->castArrayDType(); arrayp; arrayp = arrayp->dtypep()->castArrayDType()) { puts("["+cvtToStr(arrayp->elementsConst())+"]"); } puts(","+cvtToStr(nodep->msb())+","+cvtToStr(nodep->lsb())); @@ -1154,18 +1160,22 @@ void EmitCImp::emitVarResets(AstModule* modp) { } else if (AstInitArray* initarp = varp->initp()->castInitArray()) { AstConst* constsp = initarp->initsp()->castConst(); - if (!varp->arraysp()) varp->v3fatalSrc("InitArray under non-arrayed var"); - for (int i=0; iarraysp()->elementsConst(); i++) { - if (!constsp) initarp->v3fatalSrc("Not enough values in array initalizement"); - emitSetVarConstant(varp->name()+"["+cvtToStr(i)+"]", constsp); - constsp = constsp->nextp()->castConst(); + if (AstArrayDType* arrayp = varp->dtypep()->castArrayDType()) { + for (int i=0; ielementsConst(); i++) { + if (!constsp) initarp->v3fatalSrc("Not enough values in array initalizement"); + emitSetVarConstant(varp->name()+"["+cvtToStr(i)+"]", constsp); + constsp = constsp->nextp()->castConst(); + } + } else { + varp->v3fatalSrc("InitArray under non-arrayed var"); } } else { int vects = 0; - for (AstRange* arrayp=varp->arraysp(); arrayp; arrayp = arrayp->nextp()->castRange()) { + // This isn't very robust and may need cleanup for other data types + for (AstArrayDType* arrayp=varp->dtypep()->castArrayDType(); arrayp; arrayp = arrayp->dtypep()->castArrayDType()) { int vecnum = vects++; - if (arrayp->msbConst() < arrayp->lsbConst()) varp->v3fatalSrc("Should have swapped msb & lsb earlier."); + if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier."); string ivar = string("__Vi")+cvtToStr(vecnum); // MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block puts("{ int __Vi"+cvtToStr(vecnum)+"="+cvtToStr(0)+";"); @@ -1413,15 +1423,16 @@ void EmitCStmts::emitVarList(AstNode* firstp, EisWhich which, const string& pref } if (varp->isStatic() ? !isstatic : isstatic) doit=false; if (doit) { - int sigbytes = varp->widthAlignBytes(); - if (varp->isUsedClock() && varp->widthMin()==1) sigbytes = 0; - else if (varp->arraysp()) sigbytes=7; - else if (varp->isScBv()) sigbytes=6; - else if (sigbytes==8) sigbytes=5; - else if (sigbytes==4) sigbytes=4; - else if (sigbytes==2) sigbytes=2; - else if (sigbytes==1) sigbytes=1; - if (size==sigbytes) { + int sigbytes = varp->dtypep()->widthAlignBytes(); + int sortbytes = 7; + if (varp->isUsedClock() && varp->widthMin()==1) sortbytes = 0; + else if (varp->dtypep()->castArrayDType()) sortbytes=7; + else if (varp->isScBv()) sortbytes=6; + else if (sigbytes==8) sortbytes=5; + else if (sigbytes==4) sortbytes=4; + else if (sigbytes==2) sortbytes=2; + else if (sigbytes==1) sortbytes=1; + if (size==sortbytes) { emitVarDecl(varp, prefixIfImp); } } @@ -1889,7 +1900,8 @@ class EmitCTrace : EmitCStmts { puts("("); if (emitTraceIsScBv(nodep)) puts("VL_SC_BV_DATAP("); varrefp->iterate(*this); // Put var name out - if (varp->arraysp()) { + // Tracing only supports 1D arrays + if (varp->dtypep()->castArrayDType()) { if (arrayindex==-2) puts("[i]"); else if (arrayindex==-1) puts("[0]"); else puts("["+cvtToStr(arrayindex)+"]"); diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index 4b683627a..55469eb5b 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -423,11 +423,6 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { if (nodep->isSigned()) puts("signed "); nodep->dtypep()->iterateChildren(*this); puts(nodep->name()); - for (AstRange* arrayp=nodep->arraysp(); arrayp; arrayp = arrayp->nextp()->castRange()) { - puts(" ["+cvtToStr(arrayp->msbConst()) - +":"+cvtToStr(arrayp->lsbConst()) - +"]"); - } puts(";\n"); } virtual void visit(AstNodeText*, AstNUser*) {} diff --git a/src/V3Link.cpp b/src/V3Link.cpp index 50d785543..0299058ff 100644 --- a/src/V3Link.cpp +++ b/src/V3Link.cpp @@ -157,7 +157,7 @@ private: if (!forrefp->varp()) { if (!noWarn) forrefp->v3warn(IMPLICIT,"Signal definition not found, creating implicitly: "<prettyName()); AstVar* newp = new AstVar (forrefp->fileline(), AstVarType::WIRE, - forrefp->name(), AstVar::LogicPacked(), 1); + forrefp->name(), AstLogicPacked(), 1); newp->trace(m_modp->modTrace()); m_modp->addStmtp(newp); diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index ba94cd8d6..5abde7836 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -84,8 +84,8 @@ private: virtual void visit(AstVar* nodep, AstNUser*) { nodep->iterateChildren(*this); - if (nodep->arraysp() && nodep->isIO()) { - nodep->v3error("Arrayed variables may not be inputs nor outputs"); + if (nodep->isIO() && !nodep->dtypep()->castBasicDType()) { + nodep->v3error("Unsupported: Inputs and outputs must be simple data types; no arrays"); } if (m_ftaskp) nodep->funcLocal(true); if (nodep->isSigModPublic()) { @@ -124,7 +124,7 @@ private: // Make a new temp wire string newvarname = "__Vsenitemexpr"+cvtToStr(++m_senitemCvtNum); AstVar* newvarp = new AstVar (sensp->fileline(), AstVarType::MODULETEMP, newvarname, - AstVar::LogicPacked(), 1); + AstLogicPacked(), 1); // We can't just add under the module, because we may be inside a generate, begin, etc. // We know a SenItem should be under a SenTree/Always etc, we we'll just hunt upwards AstNode* addwherep = nodep; // Add to this element's next diff --git a/src/V3Premit.cpp b/src/V3Premit.cpp index 49c3f7e0e..97d1c753e 100644 --- a/src/V3Premit.cpp +++ b/src/V3Premit.cpp @@ -103,7 +103,7 @@ private: AstVar* getBlockTemp(AstNode* nodep) { string newvarname = ((string)"__Vtemp"+cvtToStr(m_modp->varNumGetInc())); AstVar* varp = new AstVar (nodep->fileline(), AstVarType::STMTTEMP, newvarname, - AstVar::LogicPacked(), nodep->widthMin()); + AstLogicPacked(), nodep->widthMin()); m_funcp->addInitsp(varp); return varp; } diff --git a/src/V3Simulate.h b/src/V3Simulate.h index 97e5eae88..b9e5be435 100644 --- a/src/V3Simulate.h +++ b/src/V3Simulate.h @@ -244,7 +244,7 @@ private: // We can't have non-delayed assignments with same value on LHS and RHS // as we don't figure out variable ordering. // Delayed is OK though, as we'll decode the next state separately. - if (nodep->varp()->arraysp()) clearOptimizable(nodep,"Array references"); + if (!nodep->varp()->dtypep()->castBasicDType()) clearOptimizable(nodep,"Array references/not basic"); if (nodep->lvalue()) { if (m_inDlyAssign) { if (!(vscp->user1() & VU_LVDLY)) { diff --git a/src/V3Stats.cpp b/src/V3Stats.cpp index e2708d820..8e0173fba 100644 --- a/src/V3Stats.cpp +++ b/src/V3Stats.cpp @@ -94,8 +94,8 @@ private: nodep->iterateChildren(*this); if (m_counting) { if (nodep->isUsedClock()) ++m_statVarClock; - if (nodep->arraysp()) ++m_statVarArray; - if (!nodep->arraysp()) m_statVarBytes += nodep->widthTotalBytes(); + if (nodep->dtypep()->castArrayDType()) ++m_statVarArray; + else m_statVarBytes += nodep->dtypep()->widthTotalBytes(); if (int(m_statVarWidths.size()) <= nodep->width()) { m_statVarWidths.resize(nodep->width()+5); } @@ -106,7 +106,9 @@ private: allNodes(nodep); nodep->iterateChildren(*this); if (m_counting) { - if (!nodep->varp()->arraysp()) m_statVarScpBytes += nodep->varp()->widthTotalBytes(); + if (nodep->varp()->dtypep()->castBasicDType()) { + m_statVarScpBytes += nodep->varp()->dtypep()->widthTotalBytes(); + } } } virtual void visit(AstNodeIf* nodep, AstNUser*) { diff --git a/src/V3Table.cpp b/src/V3Table.cpp index 9ff463e21..0b1bec7f5 100644 --- a/src/V3Table.cpp +++ b/src/V3Table.cpp @@ -163,7 +163,7 @@ public: UINFO(9," SimVARREF "<varScopep(); if (nodep->lvalue()) { - m_outWidth += nodep->varp()->widthTotalBytes(); + m_outWidth += nodep->varp()->dtypep()->widthTotalBytes(); m_outVarps.push_back(vscp); } else { // We'll make the table with a separate natural alignment for each @@ -182,16 +182,19 @@ private: // Index into our table AstVar* indexVarp = new AstVar (nodep->fileline(), AstVarType::BLOCKTEMP, "__Vtableidx" + cvtToStr(m_modTables), - AstVar::LogicPacked(), m_inWidth); + AstLogicPacked(), m_inWidth); m_modp->addStmtp(indexVarp); AstVarScope* indexVscp = new AstVarScope (indexVarp->fileline(), m_scopep, indexVarp); m_scopep->addVarp(indexVscp); // Change it variable - AstVar* chgVarp = new AstVar (nodep->fileline(), AstVarType::MODULETEMP, - "__Vtablechg" + cvtToStr(m_modTables), - AstVar::LogicPacked(), m_outVarps.size()); - chgVarp->addArraysp(new AstRange (nodep->fileline(), VL_MASK_I(m_inWidth), 0)); + FileLine* fl = nodep->fileline(); + AstVar* chgVarp + = new AstVar (fl, AstVarType::MODULETEMP, + "__Vtablechg" + cvtToStr(m_modTables), + new AstArrayDType (fl, + new AstBasicDType(fl, AstLogicPacked(), m_outVarps.size()), + new AstRange (fl, VL_MASK_I(m_inWidth), 0))); chgVarp->isConst(true); chgVarp->initp(new AstInitArray (nodep->fileline(), NULL)); m_modp->addStmtp(chgVarp); @@ -229,11 +232,13 @@ private: for (deque::iterator it = m_outVarps.begin(); it!=m_outVarps.end(); ++it) { AstVarScope* outvscp = *it; AstVar* outvarp = outvscp->varp(); + FileLine* fl = nodep->fileline(); AstVar* tablevarp - = new AstVar (nodep->fileline(), AstVarType::MODULETEMP, + = new AstVar (fl, AstVarType::MODULETEMP, "__Vtable" + cvtToStr(m_modTables) +"_"+outvarp->name(), - AstVar::LogicPacked(), outvarp->widthMin()); - tablevarp->addArraysp(new AstRange (nodep->fileline(), VL_MASK_I(m_inWidth), 0)); + new AstArrayDType (fl, + new AstBasicDType(fl, AstLogicPacked(), outvarp->widthMin()), + new AstRange (fl, VL_MASK_I(m_inWidth), 0))); tablevarp->isConst(true); tablevarp->isStatic(true); tablevarp->initp(new AstInitArray (nodep->fileline(), NULL)); diff --git a/src/V3Trace.cpp b/src/V3Trace.cpp index 782f9a2a7..69547ad41 100644 --- a/src/V3Trace.cpp +++ b/src/V3Trace.cpp @@ -313,7 +313,7 @@ private: if (!activityNumber) activityNumber++; // For simplicity, always create it int activityBits = VL_WORDS_I(activityNumber)*VL_WORDSIZE; // For tighter code; round to next 32 bit point. AstVar* newvarp = new AstVar (m_chgFuncp->fileline(), AstVarType::MODULETEMP, - "__Vm_traceActivity", AstVar::LogicPacked(), activityBits); + "__Vm_traceActivity", AstLogicPacked(), activityBits); m_topModp->addStmtp(newvarp); AstVarScope* newvscp = new AstVarScope(newvarp->fileline(), m_highScopep, newvarp); m_highScopep->addVarp(newvscp); diff --git a/src/V3TraceDecl.cpp b/src/V3TraceDecl.cpp index 36e644d5d..f22a3ce19 100644 --- a/src/V3TraceDecl.cpp +++ b/src/V3TraceDecl.cpp @@ -75,7 +75,11 @@ private: return "Inlined leading underscore"; if (nodep->width() > 256) return "Wide bus > 256 bits"; if (nodep->arrayElements() > 32) return "Wide memory > 32 ents"; - if (nodep->arrayp(1)) return "Unsupported: Multi-dimensional array"; + if (!(nodep->dtypep()->castBasicDType() + || (nodep->dtypep()->castArrayDType() + && nodep->dtypep()->castArrayDType()->dtypep()->castBasicDType()))) { + return "Unsupported: Multi-dimensional array"; + } return NULL; } diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index a27ca7a8b..c79023204 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -207,7 +207,7 @@ private: AstVar* enp = new AstVar (outrefp->varp()->fileline(), AstVarType::MODULETEMP, outrefp->name() + "__en" + suffix + cvtToStr(m_unique++), - AstVar::LogicPacked(), width); + AstLogicPacked(), width); enp->varType2Out(); if (enp->width() != enrhsp->width()) { @@ -381,7 +381,7 @@ private: AstVar* newlhsp = new AstVar(lhsp->fileline(), AstVarType::MODULETEMP, lhsp->name()+"__lhs"+cvtToStr(m_unique++), - AstVar::LogicPacked(), w); + AstLogicPacked(), w); nodep->addStmtp(newlhsp); // now append this driver to the driver logic. @@ -396,7 +396,7 @@ private: bitselp = new AstVar(lhsp->fileline(), AstVarType::MODULETEMP, lhsp->name()+"__sel"+cvtToStr(m_unique-1), - AstVar::LogicPacked(), ws); + AstLogicPacked(), ws); // nodep->addStmtp(bitselp); nodep->addStmtp(new AstAssignW(lhsp->fileline(), diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index 27421eb22..415625e7a 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -127,7 +127,7 @@ private: else { string name = ((string)"__Vlvbound"+cvtToStr(m_modp->varNumGetInc())); AstVar* varp = new AstVar(fl, AstVarType::MODULETEMP, name, - AstVar::LogicPacked(), prep->width()); + AstLogicPacked(), prep->width()); m_modp->addStmtp(varp); AstNode* abovep = prep->backp(); // Grab above point before loose it w/ next replace @@ -288,7 +288,7 @@ private: +cvtToStr(m_modp->varNumGetInc())); AstVar* newvarp = new AstVar (nodep->fileline(), AstVarType::XTEMP, newvarname, - AstVar::LogicPacked(), nodep->width()); + AstLogicPacked(), nodep->width()); m_statUnkVars++; AstNRelinker replaceHandle; nodep->unlinkFrBack(&replaceHandle); @@ -327,7 +327,7 @@ private: // Guard against reading/writing past end of bit vector array int maxmsb = 0; bool lvalue = false; - AstNode* basefromp = AstArraySel::baseFromp(nodep->fromp()); + AstNode* basefromp = AstArraySel::baseFromp(nodep); if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) { lvalue = varrefp->lvalue(); maxmsb = (varrefp->varp()->width()-1); @@ -382,8 +382,10 @@ private: int maxmsb = 0; bool lvalue = false; if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) { + AstArrayDType* adtypep = varrefp->varp()->dtypeDimensionp(dimension)->castArrayDType(); + if (!adtypep) nodep->v3fatalSrc("ArraySel to type without array at same depth"); lvalue = varrefp->lvalue(); - maxmsb = (varrefp->varp()->arrayp(dimension)->elementsConst()-1); + maxmsb = adtypep->elementsConst()-1; } else if (AstConst* lhconstp = basefromp->castConst()) { // If it's a PARAMETER[bit], then basefromp may be a constant instead of a varrefp maxmsb = lhconstp->widthMin(); diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 599799501..66cad2eb1 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -265,6 +265,7 @@ private: virtual void visit(AstSel* nodep, AstNUser* vup) { if (vup->c()->prelim()) { + if (debug()>=9) nodep->dumpTree(cout,"-selWidth: "); nodep->fromp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p()); nodep->lsbp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p()); nodep->widthp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); @@ -299,7 +300,7 @@ private: int frommsb = nodep->fromp()->width() - 1; int fromlsb = 0; AstNodeVarRef* varrp = nodep->fromp()->castNodeVarRef(); - if (varrp && varrp->varp()->dtypep()->rangep()) { // Selecting a bit from a multibit register + if (varrp && varrp->varp()->basicp()->rangep()) { // Selecting a bit from a multibit register frommsb = varrp->varp()->msbMaxSelect(); // Corrected for negative lsb fromlsb = varrp->varp()->lsb(); } @@ -314,6 +315,9 @@ private: <<(nodep->lsbp()->width()!=nodep->lsbp()->widthMin() ?" or "+cvtToStr(nodep->lsbp()->widthMin()):"") <<" bits."); + UINFO(1," Related node: "<varp()<varp()->dtypep()<lsbp()->castConst() && nodep->msbConst() > frommsb) { // See also warning in V3Const @@ -322,6 +326,9 @@ private: nodep->v3error("Selection index out of range: " <msbConst()<<":"<lsbConst() <<" outside "<varp()<varp()->dtypep()<lsbp(),selwidth,selwidth,true); @@ -339,28 +346,34 @@ private: // int frommsb; int fromlsb; - if (!varrp->varp()->arrayp(dimension)) { - nodep->v3fatalSrc("Array reference exceeds dimension of array"); - } - if (1) { // ARRAY slice extraction + AstNodeDType* ddtypep = varrp->varp()->dtypeDimensionp(dimension); + if (AstArrayDType* adtypep = ddtypep->castArrayDType()) { int outwidth = varrp->width(); // Width of variable - frommsb = varrp->varp()->arrayp(dimension)->msbConst(); - fromlsb = varrp->varp()->arrayp(dimension)->lsbConst(); + frommsb = adtypep->msb(); + fromlsb = adtypep->lsb(); if (fromlsb>frommsb) {int t=frommsb; frommsb=fromlsb; fromlsb=t; } // However, if the lsb<0 we may go negative, so need more bits! if (fromlsb < 0) frommsb += -fromlsb; nodep->width(outwidth,outwidth); // Width out = width of array } + else { + nodep->v3fatalSrc("Array reference exceeds dimension of array"); + frommsb = fromlsb = 0; + } int selwidth = V3Number::log2b(frommsb+1-1)+1; // Width to address a bit nodep->fromp()->iterateAndNext(*this,WidthVP(selwidth,selwidth,FINAL).p()); if (widthBad(nodep->bitp(),selwidth,selwidth) - && nodep->bitp()->width()!=32) + && nodep->bitp()->width()!=32) { nodep->v3warn(WIDTH,"Bit extraction of array["<bitp()->width() <<(nodep->bitp()->width()!=nodep->bitp()->widthMin() ?" or "+cvtToStr(nodep->bitp()->widthMin()):"") <<" bits."); + UINFO(1," Related node: "<varp()<bitp(),selwidth,selwidth,true); } } @@ -473,6 +486,13 @@ private: virtual void visit(AstScopeName* nodep, AstNUser* vup) { // Only used in Displays which don't care.... } + virtual void visit(AstArrayDType* nodep, AstNUser* vup) { + // Lower datatype determines the width + nodep->dtypep()->iterateAndNext(*this,vup); + // But also cleanup array size + nodep->arrayp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); + nodep->widthFrom(nodep->dtypep()); + } virtual void visit(AstBasicDType* nodep, AstNUser* vup) { if (nodep->rangep()) { nodep->rangep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); @@ -487,8 +507,6 @@ private: // We can't skip this step when width()!=0, as creating a AstVar // with non-constant range gets size 1, not size 0. int width=1; int mwidth=1; - nodep->arraysp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); - // Parameters if implicit untyped inherit from what they are assigned to AstBasicDType* bdtypep = nodep->dtypep()->castBasicDType(); if (nodep->isParam() && bdtypep && bdtypep->implicit()) { @@ -535,11 +553,9 @@ private: } //if (debug()>=9) { nodep->dumpTree(cout," VRin "); nodep->varp()->dumpTree(cout," forvar "); } // Note genvar's are also entered as integers - AstBasicDType* bdtypep = nodep->varp()->dtypep()->castBasicDType(); - if (bdtypep && bdtypep->isSloppy() - && nodep->backp()->castNodeAssign()) { // On LHS - // Consider Integers on LHS to sized (else would be unsized.) - nodep->width(bdtypep->width(),bdtypep->width()); + if (nodep->backp()->castNodeAssign() && nodep->lvalue()) { // On LHS + // Consider Integers on LHS to sized (else may be unsized.) + nodep->width(nodep->varp()->width(), nodep->varp()->width()); } else { nodep->widthFrom(nodep->varp()); } diff --git a/src/V3WidthSel.cpp b/src/V3WidthSel.cpp index c0f2cbea0..cc9bc2c15 100644 --- a/src/V3WidthSel.cpp +++ b/src/V3WidthSel.cpp @@ -74,22 +74,29 @@ private: } } - void selCheckDimension(AstNode* nodep, AstNode* basefromp, int dimension, bool rangedSelect) { + AstNodeDType* dtypeForExtractp(AstNode* nodep, AstNode* basefromp, int dimension, bool rangedSelect) { // Perform error checks on the node AstVar* varp = varFromBasefrom(basefromp); //UINFO(9,"SCD\n"); if (debug()>=9) nodep->backp()->dumpTree(cout,"-selcheck: "); - int dimensions = varp->arrayDimensions(); - if (dimension < dimensions) { + AstNodeDType* ddtypep = varp->dtypeDimensionp(dimension); + if (AstArrayDType* adtypep = ddtypep->castArrayDType()) { if (rangedSelect) { nodep->v3error("Illegal bit select; can't bit extract from arrayed dimension: "<prettyName()); + return NULL; } - } else if (dimension > dimensions) { // Too many indexes provided - nodep->v3error("Illegal bit or array select; variable already selected, or bad dimension: "<prettyName()); - } else if (dimension == dimensions) { // Right number, but... - if (!varp->dtypep()->rangep()) { - nodep->v3error("Illegal bit select; variable does not have a bit range, or bad dimension: "<prettyName()); - } + return adtypep; } + else if (AstBasicDType* adtypep = ddtypep->castBasicDType()) { + if (!adtypep->rangep()) { + nodep->v3error("Illegal bit select; variable does not have a bit range, or bad dimension: "<prettyName()); + return NULL; + } + return adtypep; + } + else { + nodep->v3error("Illegal bit or array select; variable already selected, or bad dimension: "<prettyName()); + } + return NULL; } AstNode* newSubNeg(AstNode* lhsp, vlsint32_t rhs) { @@ -133,14 +140,14 @@ private: // Don't report WIDTH warnings etc here, as may be inside a generate branch that will be deleted AstVar* varp = varFromBasefrom(basefromp); // SUB #'s Not needed when LSB==0 and MSB>=0 (ie [0:-13] must still get added!) - if (!varp->dtypep()->rangep()) { + if (!varp->basicp()->rangep()) { // vector without range is ok, for example a INTEGER x; y = x[21:0]; return underp; } else { - if (!varp->dtypep()->rangep()->msbp()->castConst() - || !varp->dtypep()->rangep()->lsbp()->castConst()) + if (!varp->basicp()->rangep()->msbp()->castConst() + || !varp->basicp()->rangep()->lsbp()->castConst()) varp->v3fatalSrc("Non-constant variable range; errored earlier"); // in constifyParam(varp) - if (varp->dtypep()->rangep()->littleEndian()) { + if (varp->basicp()->rangep()->littleEndian()) { // reg [1:3] was swapped to [3:1] (lsbEndianedp==3) and needs a SUB(3,under) AstNode* newp = newSubNeg(varp->msb(), underp); return newp; @@ -169,8 +176,7 @@ private: // So, see if we're sitting under a variable's arrayp. AstNode* huntbackp = nodep; while (huntbackp->backp()->castRange()) huntbackp=huntbackp->backp(); - if (huntbackp->backp()->castVar() - && huntbackp->backp()->castVar()->arraysp()==huntbackp) { + if (huntbackp->backp()->castArrayDType()) { } else { // Little endian bits are legal, just remember to swap // Warning is in V3Width to avoid false warnings when in "off" generate if's @@ -189,26 +195,23 @@ private: // lhsp/rhsp do not need to be constant AstNode* basefromp = AstArraySel::baseFromp(nodep->attrp()); int dimension = AstArraySel::dimension(nodep->fromp()); // Not attrp as need hierarchy - selCheckDimension(nodep, basefromp, dimension, false); + AstNodeDType* ddtypep = dtypeForExtractp(nodep, basefromp, dimension, false); AstNode* fromp = nodep->lhsp()->unlinkFrBack(); AstNode* bitp = nodep->rhsp()->unlinkFrBack(); - AstVar* varp = varFromBasefrom(basefromp); if (debug()>=9) nodep->dumpTree(cout,"-vsbmd: "); - if (varp->arrayp(dimension)) { + if (AstArrayDType* adtypep = ddtypep->castArrayDType()) { // SELBIT(array, index) -> ARRAYSEL(array, index) - AstRange* arrayp = varp->arrayp(dimension); // NULL checked above AstNode* subp = bitp; - if (!arrayp->lsbp()->isZero() || arrayp->msbConst()<0) { - subp = newSubNeg (subp, arrayp->lsbConst()); + if (adtypep->lsb()!=0 || adtypep->msb()<0) { + subp = newSubNeg (subp, adtypep->lsb()); } - AstArraySel* newp = new AstArraySel - (nodep->fileline(), - fromp, - subp); + AstArraySel* newp = new AstArraySel (nodep->fileline(), + fromp, subp); UINFO(6," newd"<replaceWith(newp); pushDeletep(nodep); nodep=NULL; } - else { + else if (AstBasicDType* adtypep = ddtypep->castBasicDType()) { + if (adtypep) {} // unused // SELBIT(range, index) -> SEL(array, index, 1) AstSel* newp = new AstSel (nodep->fileline(), fromp, @@ -218,6 +221,11 @@ private: UINFO(6," new "<=9) newp->dumpTree(cout,"-vsbnw: "); nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL; } + else { // NULL=bad extract, or unknown node type + nodep->v3error("Illegal bit or array select; variable already selected, or bad dimension"); + // How to recover? We'll strip a dimension. + nodep->replaceWith(fromp); pushDeletep(nodep); nodep=NULL; + } } virtual void visit(AstSelExtract* nodep, AstNUser*) { @@ -238,25 +246,33 @@ private: AstVar* varp = varFromBasefrom(basefromp); vlsint32_t msb = msbp->castConst()->toSInt(); vlsint32_t lsb = lsbp->castConst()->toSInt(); - selCheckDimension(nodep, basefromp, dimension, msb!=lsb); - if (varp->dtypep()->rangep() && varp->dtypep()->rangep()->littleEndian()) { - // Below code assumes big bit endian; just works out if we swap - int x = msb; msb = lsb; lsb = x; + AstNodeDType* ddtypep = dtypeForExtractp(nodep, basefromp, dimension, msb!=lsb); + if (AstBasicDType* adtypep = ddtypep->castBasicDType()) { + if (adtypep) {} // Unused + if (varp->basicp()->rangep() && varp->basicp()->rangep()->littleEndian()) { + // Below code assumes big bit endian; just works out if we swap + int x = msb; msb = lsb; lsb = x; + } + if (lsb > msb) { + nodep->v3error("["<fileline(), AstConst::Unsized32(), // Unsized so width from user + msb +1-lsb); + AstSel* newp = new AstSel (nodep->fileline(), + fromp, + newSubLsbOf(lsbp, basefromp), + widthp); + UINFO(6," new "<=9) newp->dumpTree(cout,"--SLEXnew: "); + nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL; + pushDeletep(msbp); msbp=NULL; } - if (lsb > msb) { - nodep->v3error("["<v3error("Illegal range select; variable already selected, or bad dimension"); + // How to recover? We'll strip a dimension. + nodep->replaceWith(fromp); pushDeletep(nodep); nodep=NULL; } - AstNode* widthp = new AstConst (msbp->fileline(), AstConst::Unsized32(), // Unsized so width from user - msb +1-lsb); - AstSel* newp = new AstSel (nodep->fileline(), - fromp, - newSubLsbOf(lsbp, basefromp), - widthp); - UINFO(6," new "<=9) newp->dumpTree(cout,"--SLEXnew: "); - nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL; - pushDeletep(msbp); msbp=NULL; } void replaceSelPlusMinus(AstNodePreSel* nodep) { @@ -274,41 +290,49 @@ private: AstVar* varp = varFromBasefrom(basefromp); if (width > (1<<28)) nodep->v3error("Width of :+ or :- is huge; vector of over 1billion bits: "<prettyName()); if (width<0) nodep->v3error("Width of :+ or :- is < 0: "<prettyName()); - selCheckDimension(nodep, basefromp, dimension, width!=1); - AstSel* newp = NULL; - if (nodep->castSelPlus()) { - if (varp->dtypep()->rangep() && varp->dtypep()->rangep()->littleEndian()) { - // SELPLUS(from,lsb,width) -> SEL(from, (vector_msb-width+1)-sel, width) - newp = new AstSel (nodep->fileline(), - fromp, - newSubNeg((varp->msb()-width+1), rhsp), - widthp); + AstNodeDType* ddtypep = dtypeForExtractp(nodep, basefromp, dimension, width!=1); + if (AstBasicDType* adtypep = ddtypep->castBasicDType()) { + if (adtypep) {} // Unused + AstSel* newp = NULL; + if (nodep->castSelPlus()) { + if (varp->basicp()->rangep() && varp->basicp()->rangep()->littleEndian()) { + // SELPLUS(from,lsb,width) -> SEL(from, (vector_msb-width+1)-sel, width) + newp = new AstSel (nodep->fileline(), + fromp, + newSubNeg((varp->msb()-width+1), rhsp), + widthp); + } else { + // SELPLUS(from,lsb,width) -> SEL(from, lsb-vector_lsb, width) + newp = new AstSel (nodep->fileline(), + fromp, + newSubLsbOf(rhsp, basefromp), + widthp); + } + } else if (nodep->castSelMinus()) { + if (varp->basicp()->rangep() && varp->basicp()->rangep()->littleEndian()) { + // SELMINUS(from,msb,width) -> SEL(from, msb-[bit]) + newp = new AstSel (nodep->fileline(), + fromp, + newSubNeg(varp->msb(), rhsp), + widthp); + } else { + // SELMINUS(from,msb,width) -> SEL(from, msb-(width-1)-lsb#) + newp = new AstSel (nodep->fileline(), + fromp, + newSubNeg(rhsp, varp->lsb()+(width-1)), + widthp); + } } else { - // SELPLUS(from,lsb,width) -> SEL(from, lsb-vector_lsb, width) - newp = new AstSel (nodep->fileline(), - fromp, - newSubLsbOf(rhsp, basefromp), - widthp); + nodep->v3fatalSrc("Bad Case"); } - } else if (nodep->castSelMinus()) { - if (varp->dtypep()->rangep() && varp->dtypep()->rangep()->littleEndian()) { - // SELMINUS(from,msb,width) -> SEL(from, msb-[bit]) - newp = new AstSel (nodep->fileline(), - fromp, - newSubNeg(varp->msb(), rhsp), - widthp); - } else { - // SELMINUS(from,msb,width) -> SEL(from, msb-(width-1)-lsb#) - newp = new AstSel (nodep->fileline(), - fromp, - newSubNeg(rhsp, varp->lsb()+(width-1)), - widthp); - } - } else { - nodep->v3fatalSrc("Bad Case"); + UINFO(6," new "<replaceWith(newp); pushDeletep(nodep); nodep=NULL; + } + else { // NULL=bad extract, or unknown node type + nodep->v3error("Illegal +: or -: select; variable already selected, or bad dimension"); + // How to recover? We'll strip a dimension. + nodep->replaceWith(fromp); pushDeletep(nodep); nodep=NULL; } - UINFO(6," new "<replaceWith(newp); pushDeletep(nodep); nodep=NULL; } virtual void visit(AstSelPlus* nodep, AstNUser*) { replaceSelPlusMinus(nodep); diff --git a/src/verilog.y b/src/verilog.y index 96bb9b472..85db9e276 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -2613,9 +2613,21 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, AstRange if (type == AstVarType::GENVAR) { if (arrayp) fileline->v3error("Genvars may not be arrayed: "<nextp()) arrayp = arrayp->nextp()->castRange(); + while (arrayp) { + AstRange* prevp = arrayp->backp()->castRange(); + if (prevp) arrayp->unlinkFrBack(); + arrayDTypep = new AstArrayDType(arrayp->fileline(), arrayDTypep, arrayp); + arrayp = prevp; + } + } + AstVar* nodep = new AstVar(fileline, type, name, - dtypep, - arrayp); + arrayDTypep); nodep->addAttrsp(attrsp); if (GRAMMARP->m_varDecl != AstVarType::UNKNOWN) nodep->combineType(GRAMMARP->m_varDecl); if (GRAMMARP->m_varIO != AstVarType::UNKNOWN) nodep->combineType(GRAMMARP->m_varIO); diff --git a/test_regress/t/t_mem_multi_io_bad.pl b/test_regress/t/t_mem_multi_io_bad.pl index e978db005..1d6e98680 100755 --- a/test_regress/t/t_mem_multi_io_bad.pl +++ b/test_regress/t/t_mem_multi_io_bad.pl @@ -11,7 +11,7 @@ compile ( fails=>$Self->{v3}, nc=>0, expect=> -'%Error: t/t_mem_multi_io_bad.v:\d+: Arrayed variables may not be inputs nor outputs +'%Error: t/t_mem_multi_io_bad.v:\d+: Unsupported: Inputs and outputs must be simple data types; no arrays %Error: Exiting due to.*', ); diff --git a/test_regress/t/t_mem_multi_ref_bad.pl b/test_regress/t/t_mem_multi_ref_bad.pl index b33f9d979..1e005cf1a 100755 --- a/test_regress/t/t_mem_multi_ref_bad.pl +++ b/test_regress/t/t_mem_multi_ref_bad.pl @@ -11,13 +11,13 @@ compile ( fails=>$Self->{v3}, nc=>0, # Need to get it not to give the prompt expect=> -q{%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit select; variable does not have a bit range, or bad dimension: dimn +q{%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension: dimn .*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension: dim0 .*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension: dim1 .*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit select; can't bit extract from arrayed dimension: dim2 .*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit select; can't bit extract from arrayed dimension: dim2 .*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit select; can't bit extract from arrayed dimension: dim0nv -.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit select; variable does not have a bit range, or bad dimension: dim0nv +.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension: dim0nv .*%Error: Exiting due to.*}, ); diff --git a/test_regress/t/t_mem_multidim.v b/test_regress/t/t_mem_multidim.v index 88233d186..3edfc283e 100644 --- a/test_regress/t/t_mem_multidim.v +++ b/test_regress/t/t_mem_multidim.v @@ -40,6 +40,7 @@ module t (/*AUTOARG*/ end reg [71:0] wread; + reg wreadb; always @ (posedge clk) begin //$write("cyc==%0d crc=%x i[%d][%d][%d] nar=%x wide=%x\n",cyc, crc, index0,index1,index2, narrow, wide); @@ -58,12 +59,14 @@ module t (/*AUTOARG*/ index1 <= crc[3:2]; index2 <= crc[6:4]; crc <= {crc[62:0], crc[63]^crc[2]^crc[0]}; + // We never read past bounds, or get unspecific results // We also never read lowest indexes, as writing outside of range may corrupt them if (index0>=0+1 && index0<=2 && index1>=1+1 && index1<=3 && index2>=2+1 && index2<=5) begin narrow <= ({narrow[6:0], narrow[7]^narrow[0]} ^ {memn[index0][index1][index2]}); wread = memw[index0][index1][index2]; + wreadb = memw[index0][index1][index2][2]; wide <= ({wide[70:0], wide[71]^wide[2]^wide[0]} ^ wread); //$write("Get memw[%d][%d][%d] -> %x\n",index0,index1,index2, wread); end diff --git a/test_regress/t/t_trace_public.v b/test_regress/t/t_trace_public.v index 07c5f324f..d59aa8158 100644 --- a/test_regress/t/t_trace_public.v +++ b/test_regress/t/t_trace_public.v @@ -12,6 +12,17 @@ module t ( little little (.clk(CLK)); glbl glbl (); + // A vector + logic [2:1] vec [4:3]; + + integer val = 0; + always @ (posedge CLK) begin + if (RESET) val <= 0; + else val <= val + 1; + vec[3] <= val[1:0]; + vec[4] <= val[3:2]; + end + initial RESET = 1'b1; always @ (posedge CLK) RESET <= glbl.GSR; diff --git a/test_regress/t/t_trace_public_func.out b/test_regress/t/t_trace_public_func.out deleted file mode 100644 index d79b1693a..000000000 --- a/test_regress/t/t_trace_public_func.out +++ /dev/null @@ -1,89 +0,0 @@ -$version Generated by SpTraceVcd $end -$date Sat Sep 26 15:04:50 2009 - $end -$timescale 1ns $end - - $scope module TOP $end - $var wire 1 3 CLK $end - $var wire 1 4 RESET $end - $scope module v $end - $var wire 1 3 CLK $end - $var wire 1 # RESET $end - $scope module glbl $end - $var wire 1 2 GSR $end - $upscope $end - $scope module little $end - $var wire 1 3 clk $end - $var wire 128 . i128 [63:190] $end - $var wire 49 , i48 [1:49] $end - $var wire 8 + i8 [0:7] $end - $upscope $end - $scope module neg $end - $var wire 1 3 clk $end - $var wire 128 ' i128 [63:-64] $end - $var wire 48 % i48 [-1:-48] $end - $var wire 8 $ i8 [0:-7] $end - $upscope $end - $upscope $end - $upscope $end -$enddefinitions $end - - -#0 -1# -b00000000 $ -b000000000000000000000000000000000000000000000000 % -b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ' -b00000000 + -b0000000000000000000000000000000000000000000000000 , -b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 . -12 -14 -03 -#1 -#2 -#3 -b11111111 $ -b111111111111111111111111111111111111111111111111 % -b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 ' -b11111111 + -b1111111111111111111111111111111111111111111111111 , -b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 . -13 -#4 -#5 -#6 -03 -#7 -02 -#8 -#9 -0# -b00000000 $ -b000000000000000000000000000000000000000000000000 % -b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ' -b00000000 + -b0000000000000000000000000000000000000000000000000 , -b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 . -04 -13 -#10 -#11 -#12 -03 -#13 -#14 -#15 -b11111111 $ -b111111111111111111111111111111111111111111111111 % -b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 ' -b11111111 + -b1111111111111111111111111111111111111111111111111 , -b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 . -13 -#16 -#17 -#18 -03 -#19 -#20 diff --git a/test_regress/t/t_trace_public_func.pl b/test_regress/t/t_trace_public_func.pl index 7d33dd264..04c5ab18d 100755 --- a/test_regress/t/t_trace_public_func.pl +++ b/test_regress/t/t_trace_public_func.pl @@ -21,7 +21,7 @@ if ($Self->{v3}) { ); vcd_identical ("$Self->{obj_dir}/simx.vcd", - "t/$Self->{name}.out"); + "t/t_trace_public.out"); } ok(1); diff --git a/test_regress/t/t_trace_public_sig.out b/test_regress/t/t_trace_public_sig.out deleted file mode 100644 index f86635f1c..000000000 --- a/test_regress/t/t_trace_public_sig.out +++ /dev/null @@ -1,89 +0,0 @@ -$version Generated by SpTraceVcd $end -$date Sat Sep 26 15:05:35 2009 - $end -$timescale 1ns $end - - $scope module TOP $end - $var wire 1 2 CLK $end - $var wire 1 3 RESET $end - $scope module v $end - $var wire 1 2 CLK $end - $var wire 1 # RESET $end - $scope module glbl $end - $var wire 1 4 GSR $end - $upscope $end - $scope module little $end - $var wire 1 2 clk $end - $var wire 128 . i128 [63:190] $end - $var wire 49 , i48 [1:49] $end - $var wire 8 + i8 [0:7] $end - $upscope $end - $scope module neg $end - $var wire 1 2 clk $end - $var wire 128 ' i128 [63:-64] $end - $var wire 48 % i48 [-1:-48] $end - $var wire 8 $ i8 [0:-7] $end - $upscope $end - $upscope $end - $upscope $end -$enddefinitions $end - - -#0 -1# -b00000000 $ -b000000000000000000000000000000000000000000000000 % -b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ' -b00000000 + -b0000000000000000000000000000000000000000000000000 , -b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 . -13 -02 -14 -#1 -#2 -#3 -b11111111 $ -b111111111111111111111111111111111111111111111111 % -b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 ' -b11111111 + -b1111111111111111111111111111111111111111111111111 , -b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 . -12 -#4 -#5 -#6 -02 -#7 -04 -#8 -#9 -0# -b00000000 $ -b000000000000000000000000000000000000000000000000 % -b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ' -b00000000 + -b0000000000000000000000000000000000000000000000000 , -b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 . -03 -12 -#10 -#11 -#12 -02 -#13 -#14 -#15 -b11111111 $ -b111111111111111111111111111111111111111111111111 % -b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 ' -b11111111 + -b1111111111111111111111111111111111111111111111111 , -b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 . -12 -#16 -#17 -#18 -02 -#19 -#20 diff --git a/test_regress/t/t_trace_public_sig.pl b/test_regress/t/t_trace_public_sig.pl index e0c98cb95..03927bd73 100755 --- a/test_regress/t/t_trace_public_sig.pl +++ b/test_regress/t/t_trace_public_sig.pl @@ -21,7 +21,7 @@ if ($Self->{v3}) { ); vcd_identical ("$Self->{obj_dir}/simx.vcd", - "t/$Self->{name}.out"); + "t/t_trace_public.out"); # vcd_identical doesn't detect "$var a.b;" vs "$scope module a; $var b;" file_grep ("$Self->{obj_dir}/simx.vcd", qr/module glbl/i); }