From af0e5350153564f33f3183cd30624039a28baa3c Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 10 Dec 2020 00:04:10 -0500 Subject: [PATCH] Internals: Remove Xnor node type. Convert to Not(Xor(x)) up front, to help code coverage and optimize out extra nots sooner. --- docs/TODO | 2 +- include/verilated.h | 6 ------ nodist/vtree_importer | 2 -- src/V3AstNodes.h | 41 ----------------------------------------- src/V3Const.cpp | 12 +----------- src/V3Expand.cpp | 11 ----------- src/V3Number.cpp | 38 -------------------------------------- src/V3Number.h | 2 -- src/V3Number_test.cpp | 2 -- src/V3Width.cpp | 2 -- src/verilog.y | 8 ++++---- 11 files changed, 6 insertions(+), 120 deletions(-) diff --git a/docs/TODO b/docs/TODO index 357a15b28..bbe1311ce 100644 --- a/docs/TODO +++ b/docs/TODO @@ -84,7 +84,7 @@ "if (a) { ... b=2; } else { ... b=2;}" -> "b=2; if ..." Careful though, as b could appear in the statement or multiple times in statement (Could just require exatly two 'b's in statement) -** Simplify XOR/XNOR/AND/OR bit selection trees +** Simplify XOR/AND/OR bit selection trees Foo = A[1] ^ A[2] ^ A[3] etc are better as ^ ( A & 32'b...1110 ) ** Combine variables into wider elements Parallel statements on different bits should become single signal diff --git a/include/verilated.h b/include/verilated.h index d8e8badb0..05d25aa16 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -1370,12 +1370,6 @@ static inline WDataOutP VL_XOR_W(int words, WDataOutP owp, WDataInP lwp, WDataIn for (int i = 0; (i < words); ++i) owp[i] = (lwp[i] ^ rwp[i]); return owp; } -// EMIT_RULE: VL_XNOR: oclean=dirty; obits=lbits; lbits==rbits; -static inline WDataOutP VL_XNOR_W(int words, WDataOutP owp, WDataInP lwp, - WDataInP rwp) VL_MT_SAFE { - for (int i = 0; (i < words); ++i) owp[i] = (lwp[i] ^ ~rwp[i]); - return owp; -} // EMIT_RULE: VL_NOT: oclean=dirty; obits=lbits; static inline WDataOutP VL_NOT_W(int words, WDataOutP owp, WDataInP lwp) VL_MT_SAFE { for (int i = 0; i < words; ++i) owp[i] = ~(lwp[i]); diff --git a/nodist/vtree_importer b/nodist/vtree_importer index 2a2d2c497..6acffed2d 100755 --- a/nodist/vtree_importer +++ b/nodist/vtree_importer @@ -234,7 +234,6 @@ sub gentree { 'RANGE' => sub { t1; local $Avoid_Hex=1; p "[";t2;p ":";t3;p "]"; }, 'REDAND' => sub { p "&(";p1;p ")"; }, 'REDOR' => sub { p "|(";p1;p ")"; }, - 'REDXNOR' => sub { p "~|(";p1;p ")"; }, 'REDXOR' => sub { p "~^(";p1;p ")"; }, 'REPLICATE' => sub { p "{";p1;p "{";p2;p "}}"; }, 'SCCTOR' => sub { p "SCCTOR what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, @@ -263,7 +262,6 @@ sub gentree { 'VARSCOPE' => sub { }, 'WHILE' => sub { t1; p "while (";t2;p ") begin";indentInc;nl;t3;t4;indentDec;p "end";nl; }, 'WORDSEL' => sub { p1;p "[";p2;p ":";p3;p "]"; }, - 'XNOR' => sub { p1;p " ~^ ";p2; }, 'XOR' => sub { p1;p " ^";p2; }, ); } diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 0b6ae6cce..acfddcfb7 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -5647,25 +5647,6 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual int instrCount() const override { return 1 + V3Number::log2b(width()); } }; -class AstRedXnor final : public AstNodeUniop { - // AstRedXnors are replaced with AstRedXors in V3Const. -public: - AstRedXnor(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER(fl, lhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(RedXnor) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedXnor(lhs); } - virtual string emitVerilog() override { return "%f(~^ %l)"; } - virtual string emitC() override { - v3fatalSrc("REDXNOR should have became REDXOR"); - return ""; - } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return 1 + V3Number::log2b(width()); } -}; class AstLenN final : public AstNodeUniop { // Length of a string @@ -6747,28 +6728,6 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual bool sizeMattersRhs() const override { return false; } }; -class AstXnor final : public AstNodeBiComAsv { -public: - AstXnor(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(Xnor) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstXnor(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opXnor(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f^ ~ %r)"; } - virtual string emitC() override { return "VL_XNOR_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "^ ~"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } -}; class AstEq final : public AstNodeBiCom { public: AstEq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 1d0dccd64..e66b760a7 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -509,7 +509,7 @@ private: return true; } bool ifConcatMergeableBiop(const AstNode* nodep) { - return (VN_IS(nodep, And) || VN_IS(nodep, Or) || VN_IS(nodep, Xor) || VN_IS(nodep, Xnor)); + return (VN_IS(nodep, And) || VN_IS(nodep, Or) || VN_IS(nodep, Xor)); } bool ifAdjacentSel(const AstSel* lhsp, const AstSel* rhsp) { if (!v3Global.opt.oAssemble()) return false; // opt disabled @@ -2248,7 +2248,6 @@ private: TREEOP ("AstShiftR{$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)"); TREEOP ("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)"); TREEOP ("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)"); - TREEOP ("AstXnor {$lhsp.isZero, $rhsp}", "AstNot{$rhsp}"); TREEOP ("AstSub {$lhsp.isZero, $rhsp}", "AstNegate{$rhsp}"); TREEOP ("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)"); TREEOP ("AstAnd {$lhsp, $rhsp.isZero}", "replaceZeroChkPure(nodep,$lhsp)"); @@ -2262,7 +2261,6 @@ private: TREEOP ("AstShiftRS{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)"); TREEOP ("AstSub {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)"); TREEOP ("AstXor {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)"); - TREEOP ("AstXnor {$lhsp, $rhsp.isZero}", "AstNot{$lhsp}"); // Non-zero on one side or the other TREEOP ("AstAnd {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)"); TREEOP ("AstLogAnd{$lhsp.isNeqZero, $rhsp}", "replaceWRhs(nodep)"); @@ -2273,7 +2271,6 @@ private: TREEOP ("AstOr {$lhsp, $rhsp.isAllOnes, isTPure($lhsp)}", "replaceWRhs(nodep)"); //->allOnes TREEOP ("AstLogOr {$lhsp, $rhsp.isNeqZero, isTPure($lhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstXor {$lhsp.isAllOnes, $rhsp}", "AstNot{$rhsp}"); - TREEOP ("AstXnor {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)"); TREEOP ("AstMul {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)"); TREEOP ("AstMulS {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)"); TREEOP ("AstDiv {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)"); @@ -2384,7 +2381,6 @@ private: TREEOP ("AstDivS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstOr {operandsSame($lhsp,,$rhsp)}", "replaceWLhs(nodep)"); TREEOP ("AstSub {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); - TREEOP ("AstXnor {operandsSame($lhsp,,$rhsp)}", "replaceAllOnes(nodep)"); TREEOP ("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X. TREEOP ("AstEqD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X. @@ -2461,8 +2457,6 @@ private: TREEOP ("AstAnd {operandShiftSame(nodep)}", "replaceShiftSame(nodep)"); TREEOP ("AstOr {operandShiftSame(nodep)}", "replaceShiftSame(nodep)"); TREEOP ("AstXor {operandShiftSame(nodep)}", "replaceShiftSame(nodep)"); - // "AstXnor{operandShiftSame(nodep)}", // Cannot ShiftSame as the shifted-in - // zeros might create a one // Note can't simplify a extend{extends}, extends{extend}, as the sign // bits end up in the wrong places TREEOPV("AstExtend {$lhsp.castExtend}", "replaceExtend(nodep, VN_CAST(nodep->lhsp(), Extend)->lhsp())"); @@ -2480,7 +2474,6 @@ private: TREEOPV("AstSel{$fromp.castAnd, operandSelBiLower(nodep)}", "DONE"); TREEOPV("AstSel{$fromp.castOr, operandSelBiLower(nodep)}", "DONE"); TREEOPV("AstSel{$fromp.castSub, operandSelBiLower(nodep)}", "DONE"); - TREEOPV("AstSel{$fromp.castXnor,operandSelBiLower(nodep)}", "DONE"); TREEOPV("AstSel{$fromp.castXor, operandSelBiLower(nodep)}", "DONE"); TREEOPV("AstSel{$fromp.castShiftR, operandSelShiftLower(nodep)}", "DONE"); TREEOPC("AstSel{$fromp.castConst, $lsbp.castConst, $widthp.castConst, }", "replaceConst(nodep)"); @@ -2494,9 +2487,6 @@ private: TREEOPV("AstSel{$fromp.castAnd,$lhsp.castConst}", "replaceSelIntoUniop(nodep)"); TREEOPV("AstSel{$fromp.castOr,$lhsp.castConst}", "replaceSelIntoUniop(nodep)"); TREEOPV("AstSel{$fromp.castXor,$lhsp.castConst}", "replaceSelIntoUniop(nodep)"); - TREEOPV("AstSel{$fromp.castXnor,$lhsp.castConst}", "replaceSelIntoUniop(nodep)"); - // Conversions - TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's // This visit function here must allow for short-circuiting. TREEOPS("AstLogIf{$lhsp.isZero}", "replaceNum(nodep, 1)"); TREEOPV("AstLogIf{$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}"); diff --git a/src/V3Expand.cpp b/src/V3Expand.cpp index f594434b2..4af3d7e63 100644 --- a/src/V3Expand.cpp +++ b/src/V3Expand.cpp @@ -270,15 +270,6 @@ private: } return true; } - bool expandWide(AstNodeAssign* nodep, AstXnor* rhsp) { - UINFO(8, " Wordize ASSIGN(XNOR) " << nodep << endl); - for (int w = 0; w < nodep->widthWords(); w++) { - addWordAssign(nodep, w, - new AstXnor(nodep->fileline(), newAstWordSelClone(rhsp->lhsp(), w), - newAstWordSelClone(rhsp->rhsp(), w))); - } - return true; - } //-------- Triops bool expandWide(AstNodeAssign* nodep, AstNodeCond* rhsp) { UINFO(8, " Wordize ASSIGN(COND) " << nodep << endl); @@ -859,8 +850,6 @@ private: did = expandWide(nodep, rhsp); } else if (AstXor* rhsp = VN_CAST(nodep->rhsp(), Xor)) { did = expandWide(nodep, rhsp); - } else if (AstXnor* rhsp = VN_CAST(nodep->rhsp(), Xnor)) { - did = expandWide(nodep, rhsp); } else if (AstNodeCond* rhsp = VN_CAST(nodep->rhsp(), NodeCond)) { did = expandWide(nodep, rhsp); } diff --git a/src/V3Number.cpp b/src/V3Number.cpp index e0af838c3..adacecbc9 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -1118,26 +1118,6 @@ V3Number& V3Number::opRedXor(const V3Number& lhs) { return setSingleBits(outc); } -V3Number& V3Number::opRedXnor(const V3Number& lhs) { - // op i, 1 bit return - NUM_ASSERT_OP_ARGS1(lhs); - NUM_ASSERT_LOGIC_ARGS1(lhs); - char outc = 1; - for (int bit = 0; bit < lhs.width(); bit++) { - if (lhs.bitIs1(bit)) { - if (outc == 1) { - outc = 0; - } else if (outc == 0) { - outc = 1; - } - } else if (lhs.bitIs0(bit)) { - } else { - outc = 'x'; - } - } - return setSingleBits(outc); -} - V3Number& V3Number::opCountBits(const V3Number& expr, const V3Number& ctrl1, const V3Number& ctrl2, const V3Number& ctrl3) { NUM_ASSERT_OP_ARGS4(expr, ctrl1, ctrl2, ctrl3); @@ -1278,24 +1258,6 @@ V3Number& V3Number::opXor(const V3Number& lhs, const V3Number& rhs) { return *this; } -V3Number& V3Number::opXnor(const V3Number& lhs, const V3Number& rhs) { - // i op j, max(L(lhs),L(rhs)) bit return, careful need to X/Z extend. - NUM_ASSERT_OP_ARGS2(lhs, rhs); - NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); - setZero(); - for (int bit = 0; bit < this->width(); bit++) { - if (lhs.bitIs1(bit) && rhs.bitIs1(bit)) { - setBit(bit, 1); - } else if (lhs.bitIs0(bit) && rhs.bitIs0(bit)) { - setBit(bit, 1); - } else if (lhs.bitIsXZ(bit) && rhs.bitIsXZ(bit)) { - setBit(bit, 'x'); - } - // else zero - } - return *this; -} - V3Number& V3Number::opConcat(const V3Number& lhs, const V3Number& rhs) { NUM_ASSERT_OP_ARGS2(lhs, rhs); NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); diff --git a/src/V3Number.h b/src/V3Number.h index 45d8c0f3d..fef1ad1ac 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -326,7 +326,6 @@ public: V3Number& opRedOr(const V3Number& lhs); V3Number& opRedAnd(const V3Number& lhs); V3Number& opRedXor(const V3Number& lhs); - V3Number& opRedXnor(const V3Number& lhs); V3Number& opCountBits(const V3Number& expr, const V3Number& ctrl1, const V3Number& ctrl2, const V3Number& ctrl3); V3Number& opCountOnes(const V3Number& lhs); @@ -375,7 +374,6 @@ public: V3Number& opAnd(const V3Number& lhs, const V3Number& rhs); V3Number& opChangeXor(const V3Number& lhs, const V3Number& rhs); V3Number& opXor(const V3Number& lhs, const V3Number& rhs); - V3Number& opXnor(const V3Number& lhs, const V3Number& rhs); V3Number& opOr(const V3Number& lhs, const V3Number& rhs); V3Number& opShiftR(const V3Number& lhs, const V3Number& rhs); V3Number& opShiftRS(const V3Number& lhs, const V3Number& rhs, // Arithmetic w/carry diff --git a/src/V3Number_test.cpp b/src/V3Number_test.cpp index 894ba5228..dab0bd276 100644 --- a/src/V3Number_test.cpp +++ b/src/V3Number_test.cpp @@ -47,8 +47,6 @@ void test(const string& lhss, const string& op, const string& rhss, const string gotnum.opRedAnd(lhnum); } else if (op == "redXor") { gotnum.opRedXor(lhnum); - } else if (op == "redXnor") { - gotnum.opRedXnor(lhnum); } else if (op == "concat") { gotnum.opConcat(lhnum, rhnum); } else if (op == "repl") { diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 43b512532..188241d8c 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -254,7 +254,6 @@ private: // Widths: 1 bit out, Any width lhs virtual void visit(AstRedAnd* nodep) override { visit_red_and_or(nodep); } virtual void visit(AstRedOr* nodep) override { visit_red_and_or(nodep); } - virtual void visit(AstRedXnor* nodep) override { visit_red_and_or(nodep); } virtual void visit(AstRedXor* nodep) override { visit_red_and_or(nodep); } virtual void visit(AstOneHot* nodep) override { visit_red_and_or(nodep); } virtual void visit(AstOneHot0* nodep) override { visit_red_and_or(nodep); } @@ -300,7 +299,6 @@ private: // Real: Not allowed virtual void visit(AstAnd* nodep) override { visit_boolmath_and_or(nodep); } virtual void visit(AstOr* nodep) override { visit_boolmath_and_or(nodep); } - virtual void visit(AstXnor* nodep) override { visit_boolmath_and_or(nodep); } virtual void visit(AstXor* nodep) override { visit_boolmath_and_or(nodep); } virtual void visit(AstBufIf1* nodep) override { visit_boolmath_and_or(nodep); diff --git a/src/verilog.y b/src/verilog.y index 639e22744..c4d507725 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -4148,7 +4148,7 @@ expr: // IEEE: part of expression/constant_expression/primary | '^' ~r~expr %prec prREDUCTION { $$ = new AstRedXor ($1,$2); } | yP_NAND ~r~expr %prec prREDUCTION { $$ = new AstLogNot($1, new AstRedAnd($1, $2)); } | yP_NOR ~r~expr %prec prREDUCTION { $$ = new AstLogNot($1, new AstRedOr($1, $2)); } - | yP_XNOR ~r~expr %prec prREDUCTION { $$ = new AstRedXnor ($1,$2); } + | yP_XNOR ~r~expr %prec prREDUCTION { $$ = new AstLogNot($1, new AstRedXor($1, $2)); } // // // IEEE: inc_or_dec_expression | ~l~inc_or_dec_expression { $$=$1; $$ = $1; } @@ -4189,9 +4189,9 @@ expr: // IEEE: part of expression/constant_expression/primary | ~l~expr '&' ~r~expr { $$ = new AstAnd ($2,$1,$3); } | ~l~expr '|' ~r~expr { $$ = new AstOr ($2,$1,$3); } | ~l~expr '^' ~r~expr { $$ = new AstXor ($2,$1,$3); } - | ~l~expr yP_XNOR ~r~expr { $$ = new AstXnor ($2,$1,$3); } - | ~l~expr yP_NOR ~r~expr { $$ = new AstNot($2,new AstOr ($2,$1,$3)); } - | ~l~expr yP_NAND ~r~expr { $$ = new AstNot($2,new AstAnd ($2,$1,$3)); } + | ~l~expr yP_XNOR ~r~expr { $$ = new AstNot{$2, new AstXor{$2, $1, $3}}; } + | ~l~expr yP_NOR ~r~expr { $$ = new AstNot{$2, new AstOr{$2, $1, $3}}; } + | ~l~expr yP_NAND ~r~expr { $$ = new AstNot{$2, new AstAnd{$2, $1, $3}}; } | ~l~expr yP_SLEFT ~r~expr { $$ = new AstShiftL ($2,$1,$3); } | ~l~expr yP_SRIGHT ~r~expr { $$ = new AstShiftR ($2,$1,$3); } | ~l~expr yP_SSRIGHT ~r~expr { $$ = new AstShiftRS ($2,$1,$3); }