diff --git a/src/V3Ast.h b/src/V3Ast.h index bc946cf72..42c53a82d 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -606,6 +606,7 @@ struct VNumRange { int lo() const { return m_lo; } int left() const { return littleEndian()?lo():hi(); } // How to show a declaration int right() const { return littleEndian()?hi():lo(); } + int leftToRightInc() const { return littleEndian()?1:-1; } int elements() const { return hi()-lo()+1; } bool ranged() const { return m_ranged; } bool littleEndian() const { return m_littleEndian; } diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 7402fa0f3..29e19bc36 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -4201,15 +4201,15 @@ private: bool m_default; public: AstPatMember(FileLine* fl, AstNode* lhsp, AstNode* keyp, AstNode* repp) : AstNodeMath(fl) { - setOp1p(lhsp), setNOp2p(keyp), setNOp3p(repp); m_default = false; } + addOp1p(lhsp), setNOp2p(keyp), setNOp3p(repp); m_default = false; } ASTNODE_NODE_FUNCS(PatMember, PATMEMBER) virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { V3ERROR_NA; } - virtual string emitVerilog() { return lhsp()?"%f{%r{%k%l}}":"%l"; } + virtual string emitVerilog() { return lhssp()?"%f{%r{%k%l}}":"%l"; } virtual string emitC() { V3ERROR_NA; return "";} virtual string emitSimpleOperator() { V3ERROR_NA; return "";} virtual bool cleanOut() {V3ERROR_NA; return "";} virtual int instrCount() const { return widthInstrs()*2; } - AstNode* lhsp() const { return op1p(); } // op1 = expression to assign or another AstPattern + AstNode* lhssp() const { return op1p(); } // op1 = expression to assign or another AstPattern (list if replicated) AstNode* keyp() const { return op2p(); } // op2 = assignment key (Const, id Text) AstNode* repp() const { return op3p(); } // op3 = replication count, or NULL for count 1 bool isDefault() const { return m_default; } diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 18e84260f..79477ff41 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1177,8 +1177,8 @@ private: nodep->dtypep(vdtypep); UINFO(9," adtypep "<dtypep(vdtypep); + // Determine replication count, and replicate initial value as widths need to be individually determined for (AstPatMember* patp = nodep->itemsp()->castPatMember(); patp; patp = patp->nextp()->castPatMember()) { - // Determine replication count, and replicate initial value as widths need to be individually determined int times = visitPatMemberRep(patp); for (int i=1; icloneTree(false); @@ -1186,6 +1186,20 @@ private: // This loop will see the new elements as part of nextp() } } + // Convert any PatMember with multiple items to multiple PatMembers + for (AstPatMember* patp = nodep->itemsp()->castPatMember(); patp; patp = patp->nextp()->castPatMember()) { + if (patp->lhssp()->nextp()) { + // Can't just addNext, as would add to end of all members. So detach, add next and reattach + AstNRelinker relinkHandle; + patp->unlinkFrBack(&relinkHandle); + while (AstNode* movep = patp->lhssp()->nextp()) { + movep->unlinkFrBack(); // Not unlinkFrBackWithNext, just one + AstPatMember* newp = new AstPatMember(patp->fileline(), movep, patp->keyp()->cloneTree(true), NULL); + patp->addNext(newp); + } + relinkHandle.relink(patp); + } + } AstPatMember* defaultp = NULL; for (AstPatMember* patp = nodep->itemsp()->castPatMember(); patp; patp = patp->nextp()->castPatMember()) { if (patp->isDefault()) { @@ -1255,9 +1269,9 @@ private: patp->dtypep(memp); patp->accept(*this,WidthVP(memp,BOTH).p()); // Convert to concat for now - if (!newp) newp = patp->lhsp()->unlinkFrBack(); + if (!newp) newp = patp->lhssp()->unlinkFrBack(); else { - AstConcat* concatp = new AstConcat(patp->fileline(), newp, patp->lhsp()->unlinkFrBack()); + AstConcat* concatp = new AstConcat(patp->fileline(), newp, patp->lhssp()->unlinkFrBack()); newp = concatp; newp->dtypeSetLogicSized(concatp->lhsp()->width()+concatp->rhsp()->width(), concatp->lhsp()->width()+concatp->rhsp()->width(), @@ -1277,9 +1291,10 @@ private: AstNodeDType* vdtypep = vup->c()->dtypep(); if (!vdtypep) nodep->v3fatalSrc("Pattern member type not assigned by AstPattern visitor"); nodep->dtypep(vdtypep); - nodep->lhsp()->dtypeFrom(nodep); + if (nodep->lhssp()->nextp()) nodep->v3fatalSrc("PatMember value should be singular w/replicates removed"); + nodep->lhssp()->dtypeFrom(nodep); nodep->iterateChildren(*this,WidthVP(nodep->dtypep(),BOTH).p()); - widthCheck(nodep,"LHS",nodep->lhsp(),nodep->width(),nodep->width()); + widthCheck(nodep,"LHS",nodep->lhssp(),nodep->width(),nodep->width()); } int visitPatMemberRep(AstPatMember* nodep) { uint32_t times = 1; diff --git a/test_regress/t/t_array_pattern_packed.v b/test_regress/t/t_array_pattern_packed.v index 8f743d289..9c8712815 100644 --- a/test_regress/t/t_array_pattern_packed.v +++ b/test_regress/t/t_array_pattern_packed.v @@ -30,7 +30,7 @@ module t (/*AUTOARG*/ if (array_simp !== 32'h3210_1234) $stop; // Doesn't seem to work for unpacked arrays in other simulators - //array_simp <= '{2 { '{4 { 4'd3, 4'd2, 4'd1, 4'd0 }} } }; + array_simp = '{2 { '{4 { 4'd3, 4'd2, 4'd1, 4'd0 }} } }; $write("*-* All Finished *-*\n"); $finish; @@ -86,8 +86,8 @@ module t (/*AUTOARG*/ else if (cnt[30:2]== 2) array_bg <= '{default:13}; else if (cnt[30:2]== 3) array_bg <= '{0:4, 1:5, 2:6, 3:7}; else if (cnt[30:2]== 4) array_bg <= '{2:15, default:13}; - else if (cnt[30:2]== 5) array_bg <= '{WA { {WB {2'b10}} }}; - else if (cnt[30:2]== 6) array_bg <= '{cnt+0, cnt+1, cnt+2, cnt+3}; + else if (cnt[30:2]== 5) array_bg <= '{WA { {WB/2 {2'b10}} }}; + else if (cnt[30:2]== 6) array_bg <= '{cnt[3:0]+0, cnt[3:0]+1, cnt[3:0]+2, cnt[3:0]+3}; end else if (cnt[1:0]==2'd2) begin // chack array agains expected value if (cnt[30:2]== 0) begin if (array_bg !== 16'b0000000000000000) begin $display("%b", array_bg); $stop(); end end @@ -122,7 +122,7 @@ module t (/*AUTOARG*/ else if (cnt[30:2]== 3) array_lt <= '{3:4, 2:5, 1:6, 0:7}; else if (cnt[30:2]== 4) array_lt <= '{1:15, default:13}; else if (cnt[30:2]== 5) array_lt <= '{WA { {WB/2 {2'b10}} }}; - else if (cnt[30:2]==10) array_lt <= '{cnt+0, cnt+1, cnt+2, cnt+3}; + else if (cnt[30:2]==10) array_lt <= '{cnt[3:0]+0, cnt[3:0]+1, cnt[3:0]+2, cnt[3:0]+3}; end else if (cnt[1:0]==2'd2) begin // chack array agains expected value if (cnt[30:2]== 0) begin if (array_lt !== 16'b0000000000000000) begin $display("%b", array_lt); $stop(); end end diff --git a/test_regress/t/t_array_pattern_unpacked.v b/test_regress/t/t_array_pattern_unpacked.v index bc63cdf63..617535c3d 100644 --- a/test_regress/t/t_array_pattern_unpacked.v +++ b/test_regress/t/t_array_pattern_unpacked.v @@ -25,7 +25,7 @@ module t (/*AUTOARG*/); array_simp[0][3],array_simp[0][2],array_simp[0][1],array_simp[0][0]} !== 32'h3210_1234) $stop; // Doesn't seem to work for unpacked arrays in other simulators - //array_simp <= '{2{ '{4{ 4'd3, 4'd2, 4'd1, 4'd0 }} }}; + array_simp = '{2 { '{4 { 4'd3, 4'd2, 4'd1, 4'd0 }} } }; $write("*-* All Finished *-*\n"); $finish;