diff --git a/Changes b/Changes index 006d757f3..b3a01bf9a 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,8 @@ The contributors that suggested a given feature are shown in []. Thanks! * Verilator 3.903 devel +*** Support ports of array of reals, bug1154. [J Briquet] + **** Add warning on mis-sized literal, bug1156. [Todd Strader] diff --git a/src/V3Ast.h b/src/V3Ast.h index 864ff075d..ad4f2c6c0 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1675,6 +1675,7 @@ public: virtual bool maybePointedTo() const { return true; } virtual AstNodeDType* virtRefDTypep() const { return NULL; } // Iff has a non-null refDTypep(), as generic node function virtual void virtRefDTypep(AstNodeDType* nodep) { } // Iff has refDTypep(), set as generic node function + virtual bool similarDType(AstNodeDType* samep) const = 0; // Assignable equivalence. Call skipRefp() on this and samep before calling // // Changing the width may confuse the data type resolution, so must clear TypeTable cache after use. void widthForce(int width, int sized) { m_width=width; m_widthMin=sized; } @@ -1724,6 +1725,9 @@ public: 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,... // op1 = members + virtual bool similarDType(AstNodeDType* samep) const { + return this==samep; // We don't compare members, require exact equivalence + } AstMemberDType* membersp() const { return op1p()->castMemberDType(); } // op1 = AstMember list void addMembersp(AstNode* nodep) { addNOp1p(nodep); } bool packed() const { return m_packed; } @@ -1754,7 +1758,7 @@ public: virtual void dump(ostream& str); virtual void dumpSmall(ostream& str); virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) - || (!m_refDTypep && childDTypep()))); return NULL; } + || (!m_refDTypep && childDTypep()))); return NULL; } virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); }} @@ -1763,6 +1767,14 @@ public: return (msb()==sp->msb() && subDTypep()==sp->subDTypep() && rangenp()->sameTree(sp->rangenp())); } // HashedDT doesn't recurse, so need to check children + virtual bool similarDType(AstNodeDType* samep) const { + AstNodeArrayDType* sp = samep->castNodeArrayDType(); + return (sp + && type() == samep->type() + && msb() == sp->msb() + && rangenp()->sameTree(sp->rangenp()) + && subDTypep()->skipRefp()->similarDType(sp->subDTypep()->skipRefp())); + } virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_refDTypep),V3Hash(msb()),V3Hash(lsb())); } AstNodeDType* getChildDTypep() const { return childDTypep(); } AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 0e0fc5bb0..b8d688a28 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -180,6 +180,10 @@ public: virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); } virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); } virtual AstNodeDType* skipRefToEnump() const { return subDTypep()->skipRefToEnump(); } + virtual bool similarDType(AstNodeDType* samep) const { + AstParamTypeDType* sp = samep->castParamTypeDType(); + return (sp && this->subDTypep()->skipRefp()->similarDType(sp->subDTypep()->skipRefp())); + } virtual int widthAlignBytes() const { return dtypep()->widthAlignBytes(); } virtual int widthTotalBytes() const { return dtypep()->widthTotalBytes(); } // METHODS @@ -250,7 +254,9 @@ public: m_uniqueNum = uniqueNumInc(); } ASTNODE_NODE_FUNCS(DefImplicitDType) - virtual bool same(AstNode* samep) const { return m_uniqueNum==samep->castDefImplicitDType()->m_uniqueNum; } + virtual bool same(AstNode* samep) const { return m_uniqueNum==samep->castDefImplicitDType()->m_uniqueNum; } + virtual bool similarDType(AstNodeDType* samep) const { + return type()==samep->type() && same(samep); } virtual V3Hash sameHash() const { return V3Hash(m_uniqueNum); } AstNodeDType* getChildDTypep() const { return childDTypep(); } AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable @@ -392,6 +398,8 @@ public: virtual V3Hash sameHash() const { return V3Hash(V3Hash(m.m_keyword), V3Hash(m.m_nrange.hi())); } virtual bool same(AstNode* samep) const { // width/widthMin/numeric compared elsewhere return samep->castBasicDType()->m == m; } + virtual bool similarDType(AstNodeDType* samep) const { + return type()==samep->type() && same(samep); } virtual string name() const { return m.m_keyword.ascii(); } virtual const char* broken() const { BROKEN_RTN(dtypep()!=this); return NULL; } AstRange* rangep() const { return op1p()->castRange(); } // op1 = Range of variable @@ -456,6 +464,8 @@ public: }} virtual bool same(AstNode* samep) const { return (m_refDTypep==samep->castConstDType()->m_refDTypep); } + virtual bool similarDType(AstNodeDType* samep) const { + return skipRefp()->similarDType(samep->skipRefp()); } virtual V3Hash sameHash() const { return V3Hash(m_refDTypep); } // node's type() included elsewhere AstNodeDType* getChildDTypep() const { return childDTypep(); } AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable @@ -499,6 +509,7 @@ public: virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } + virtual bool similarDType(AstNodeDType* samep) const { return this==samep; } virtual int widthAlignBytes() const { return 1; } virtual int widthTotalBytes() const { return 1; } string cellName() const { return m_cellName; } @@ -540,6 +551,8 @@ public: return (m_refDTypep==samep->castRefDType()->m_refDTypep && m_name==samep->castRefDType()->m_name && m_packagep==samep->castRefDType()->m_packagep); } + virtual bool similarDType(AstNodeDType* samep) const { + return skipRefp()->similarDType(samep->skipRefp()); } virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_refDTypep),V3Hash(m_packagep)); } virtual void dump(ostream& str=cout); virtual string name() const { return m_name; } @@ -623,6 +636,7 @@ public: void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; } virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); } + virtual bool similarDType(AstNodeDType* samep) const { return this==samep; } // virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType) AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } // op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType) @@ -704,6 +718,7 @@ public: m_refDTypep = m_refDTypep->clonep(); }} virtual bool same(AstNode* samep) const { return m_uniqueNum==samep->castEnumDType()->m_uniqueNum; } + virtual bool similarDType(AstNodeDType* samep) const { return this==samep; } virtual V3Hash sameHash() const { return V3Hash(m_uniqueNum); } AstNodeDType* getChildDTypep() const { return childDTypep(); } AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Data type @@ -733,6 +748,7 @@ public: ASTNODE_NODE_FUNCS(ParseTypeDType) AstNodeDType* dtypep() const { return NULL; } // METHODS + virtual bool similarDType(AstNodeDType* samep) const { return this==samep; } virtual AstBasicDType* basicp() const { return NULL; } virtual AstNodeDType* skipRefp() const { return NULL; } virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 0dd2153b7..6547bcdbd 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -1861,7 +1861,7 @@ private: } // if (!ok) { - //Cells/interfaces can't be implicit + // Cells/interfaces can't be implicit bool isCell = foundp ? foundp->nodep()->castCell() != NULL : false; bool checkImplicit = (!m_ds.m_dotp && m_ds.m_dotText=="" && !isCell); bool err = !(checkImplicit && m_statep->implicitOk(m_modp, nodep->name())); diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 259f116f6..439f7574e 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -2136,7 +2136,8 @@ private: AstNodeDType* subDTypep = pinDTypep; int pinwidth = pinDTypep->width(); int conwidth = conDTypep->width(); - if (conDTypep == pinDTypep) { // If match, we're golden + if (conDTypep == pinDTypep // If match, we're golden + || similarDTypeRecurse(conDTypep, pinDTypep)) { userIterateAndNext(nodep->exprp(), WidthVP(subDTypep,FINAL).p()); } else if (m_cellRangep) { @@ -2909,6 +2910,9 @@ private: return false; // No change } + bool similarDTypeRecurse(AstNodeDType* node1p, AstNodeDType* node2p) { + return node1p->skipRefp()->similarDType(node2p->skipRefp()); + } void iterateCheckFileDesc (AstNode* nodep, AstNode* underp, Stage stage) { if (stage != BOTH) nodep->v3fatalSrc("Bad call"); // underp may change as a result of replacement diff --git a/test_regress/t/t_vams_wreal.v b/test_regress/t/t_vams_wreal.v index 18bc3ea1b..22860951d 100644 --- a/test_regress/t/t_vams_wreal.v +++ b/test_regress/t/t_vams_wreal.v @@ -30,6 +30,26 @@ module t (/*autoarg*/ // Outputs .out (out)); + // wreal bus declaration + wreal vin_upper_bus[1:0]; + + // wreal nets declaration + wreal vout_split_0; + wreal vout_split_1; + + wreal_bus wreal_bus( .vin_bus(vin_upper_bus[1:0]), + .vout_split_0(vout_split_0), + .vout_split_1(vout_split_1)); + + + // implicit declaration of wreal +`ifdef VERILATOR + wreal wreal_implicit_net; // implicit declaration of wreal not supported yet +`endif + // verilator lint_off IMPLICIT + first_level first_level(.in(cyc[0]), .out(wreal_implicit_net)); + // verilator lint_on IMPLICIT + parameter real lsb = 1; // verilator lint_off WIDTH assign aout = $itor(in) * lsb; @@ -87,3 +107,30 @@ module within_range wreal in_int = vpass - gnd; wire out = (V_MIN <= in_int && in_int <= V_MAX); endmodule + + +module wreal_bus + (input wreal vin_bus [1:0], + output wreal vout_split_0, + output wreal vout_split_1); + assign vout_split_0 = vin_bus[0]; + assign vout_split_1 = vin_bus[1]; +endmodule + +module first_level + (input in, +`ifdef VERILATOR + output wreal out +`else + output out // Implicity becomes real +`endif +); + second_level second_level(.in(in), .out(out)); +endmodule + +module second_level + (input in, + output out); + wreal out; + assign out = in ? 1.23456: 7.8910; +endmodule