diff --git a/Changes b/Changes index 21622bb2c..69b8ceb54 100644 --- a/Changes +++ b/Changes @@ -7,6 +7,8 @@ indicates the contributor was also the author of the fix; Thanks! **** Support $bits(data_type), bug327. [Alex Solomatnikov] +**** Accelerate bit-selected inversions. + **** Fix concatenates and vectored bufif1, bug326. [Iztok Jeras] * Verilator 3.811 2011/02/14 diff --git a/src/V3Ast.h b/src/V3Ast.h index 1c4fd8e87..7a10bc232 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -976,6 +976,7 @@ struct AstNodeUniop : public AstNodeMath { setOp1p(lhsp); } ASTNODE_BASE_FUNCS(NodeUniop) AstNode* lhsp() const { return op1p()->castNode(); } + void lhsp(AstNode* nodep) { return setOp1p(nodep); } // METHODS virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs virtual bool cleanLhs() = 0; diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 14a8fe0b7..9ddd85d17 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -1078,6 +1078,20 @@ private: fromp->widthSignedFrom(nodep); nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL; } + void replaceSelIntoUniop(AstSel* nodep) { + // SEL(NOT(a),1,bit) => NOT(SEL(a,bit)) + AstNodeUniop* fromp = nodep->fromp()->unlinkFrBack()->castNodeUniop(); + if (!fromp) nodep->v3fatalSrc("Called on non biop"); + AstNode* lsbp = nodep->lsbp()->unlinkFrBack(); + AstNode* widthp = nodep->widthp()->unlinkFrBack(); + // + AstNode* bilhsp = fromp->lhsp()->unlinkFrBack(); + // + fromp->lhsp(new AstSel(nodep->fileline(), + bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true))); + fromp->widthSignedFrom(nodep); + nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL; + } virtual void visit(AstVarRef* nodep, AstNUser*) { nodep->iterateChildren(*this); @@ -1786,9 +1800,14 @@ private: TREEOPV("AstSel{$fromp.castConcat, $lsbp.castConst, $widthp.castConst, }", "replaceSelConcat(nodep)"); TREEOPV("AstSel{$fromp.castReplicate, $lsbp.castConst, $widthp.isOne, }", "replaceSelReplicate(nodep)"); // V3Tristate requires selects below BufIf1. - // We can probably extend this to additional logical operators, but only definite + // Also do additional operators that are bit-independent, but only definite // win if bit select is a constant (otherwise we may need to compute bit index several times) - TREEOPV("AstSel{$fromp.castBufIf1}", "replaceSelIntoBiop(nodep)"); + TREEOPV("AstSel{$fromp.castBufIf1}", "replaceSelIntoBiop(nodep)"); + TREEOPV("AstSel{$fromp.castNot}", "replaceSelIntoUniop(nodep)"); + 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 TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}");