diff --git a/src/V3AstNodeDType.h b/src/V3AstNodeDType.h index fcb2183ba..6c791c2f2 100644 --- a/src/V3AstNodeDType.h +++ b/src/V3AstNodeDType.h @@ -968,7 +968,7 @@ class AstMemberDType final : public AstNodeDType { string m_tag; // Holds the string of the verilator tag -- used in JSON output. int m_lsb = -1; // Within this level's packed struct, the LSB of the first bit of the member bool m_constrainedRand = false; - // UNSUP: int m_randType; // Randomization type (IEEE) + VRandAttr m_rand; // Randomizability of this member (rand, randc, etc) public: AstMemberDType(FileLine* fl, const string& name, VFlagChildDType, AstNodeDType* dtp, AstNode* valuep) @@ -1025,6 +1025,8 @@ public: } bool isConstrainedRand() const { return m_constrainedRand; } void markConstrainedRand(bool flag) { m_constrainedRand = flag; } + VRandAttr rand() const { return m_rand; } + void rand(const VRandAttr flag) { m_rand = flag; } }; class AstNBACommitQueueDType final : public AstNodeDType { // @astgen ptr := m_subDTypep : AstNodeDType // Type of the corresponding variable diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 26126e5fd..95b92f8ee 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -2488,12 +2488,14 @@ const char* AstLoopTest::broken() const { void AstMemberDType::dump(std::ostream& str) const { this->AstNodeDType::dump(str); if (isConstrainedRand()) str << " [CONSTRAINEDRAND]"; + if (rand().isRandomizable()) str << " [" << rand() << "]"; if (name() != "") str << " name=" << name(); if (tag() != "") str << " tag=" << tag(); } void AstMemberDType::dumpJson(std::ostream& str) const { dumpJsonBoolFuncIf(str, isConstrainedRand); + if (rand().isRandomizable()) dumpJsonStr(str, "rand", rand().ascii()); dumpJsonStrFunc(str, name); dumpJsonStrFunc(str, tag); dumpJsonGen(str); diff --git a/src/V3ParseGrammar.h b/src/V3ParseGrammar.h index c081d599a..ad46d9a05 100644 --- a/src/V3ParseGrammar.h +++ b/src/V3ParseGrammar.h @@ -31,6 +31,7 @@ public: AstCase* m_caseAttrp = nullptr; // Current case statement for attribute adding AstNodeDType* m_varDTypep = nullptr; // Pointer to data type for next signal declaration AstNodeDType* m_memDTypep = nullptr; // Pointer to data type for next member declaration + VRandAttr m_memRand; // 'rand'/'randc' qualifier for next member declaration AstDelay* m_netDelayp = nullptr; // Pointer to delay for next signal declaration AstStrengthSpec* m_netStrengthp = nullptr; // Pointer to strength for next net declaration FileLine* m_instModuleFl = nullptr; // Fileline of module referenced for instantiations diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h index 882b0e817..ee1a836a9 100644 --- a/src/V3ParseImp.h +++ b/src/V3ParseImp.h @@ -69,6 +69,11 @@ struct VMemberQualifiers final { q.m_flags = a.m_flags | b.m_flags; return q; } + VRandAttr randAttr() const { + if (m_randc) return VRandAttr::RAND_CYCLIC; + if (m_rand) return VRandAttr::RAND; + return VRandAttr::NONE; + } void applyToNodes(AstNodeFTask* nodesp) const { for (AstNodeFTask* nodep = nodesp; nodep; nodep = VN_AS(nodep->nextp(), NodeFTask)) { if (m_local) nodep->isHideLocal(true); diff --git a/src/verilog.y b/src/verilog.y index 378c4f402..ad804dba3 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -2204,11 +2204,13 @@ struct_union_memberList: // IEEE: { struct_union_member } ; struct_union_member: // ==IEEE: struct_union_member - // // UNSUP random_qualifer not propagated until have randomize support random_qualifierE data_type_or_void - /*mid*/ { GRAMMARP->m_memDTypep = $2; } // As a list follows, need to attach this dtype to each member. + /*mid*/ { GRAMMARP->m_memDTypep = $2; // As a list follows, need to attach this dtype to each member. + GRAMMARP->m_memRand = $1.randAttr(); } /*cont*/ list_of_member_decl_assignments ';' - { $$ = $4; DEL(GRAMMARP->m_memDTypep); GRAMMARP->m_memDTypep = nullptr; } + { $$ = $4; + DEL(GRAMMARP->m_memDTypep); GRAMMARP->m_memDTypep = nullptr; + GRAMMARP->m_memRand = VRandAttr::NONE; } | vlTag { $$ = nullptr; } ; @@ -2226,6 +2228,7 @@ member_decl_assignment: // Derived from IEEE: variable_decl_assi ? GRAMMARP->m_memDTypep->cloneTree(true) : nullptr), $2, false), nullptr}; + $$->rand(GRAMMARP->m_memRand); PARSEP->tagNodep($$); } | idAny variable_dimensionListE '=' variable_declExpr @@ -2234,6 +2237,7 @@ member_decl_assignment: // Derived from IEEE: variable_decl_assi ? GRAMMARP->m_memDTypep->cloneTree(true) : nullptr), $2, false), $4}; + $$->rand(GRAMMARP->m_memRand); PARSEP->tagNodep($$); } | idSVKwd { $$ = nullptr; } diff --git a/test_regress/t/t_debug_emitv.out b/test_regress/t/t_debug_emitv.out index 5fcf5c7d7..2574d2c56 100644 --- a/test_regress/t/t_debug_emitv.out +++ b/test_regress/t/t_debug_emitv.out @@ -10,6 +10,7 @@ module Vt_debug_emitv_t; } ps_t; typedef struct { logic signed [2:0] a; + logic [1:0] b; } us_t; typedef union { logic a; @@ -19,6 +20,7 @@ module Vt_debug_emitv_t; } ps[0:2]; struct { logic signed [2:0] a; + logic [1:0] b; } us; union { logic a; diff --git a/test_regress/t/t_debug_emitv.v b/test_regress/t/t_debug_emitv.v index 7e474c305..1255b5c3c 100644 --- a/test_regress/t/t_debug_emitv.v +++ b/test_regress/t/t_debug_emitv.v @@ -64,6 +64,7 @@ module t (/*AUTOARG*/ } ps_t; typedef struct { logic signed [2:0] a; + rand logic [1:0] b; } us_t; typedef union { logic a;