From 749fdaae3173cc16c3353b3c074b3db5fb6e22e0 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 1 Sep 2006 16:53:14 +0000 Subject: [PATCH] Optimize n*powers of 2. (For parameterized DDR model) git-svn-id: file://localhost/svn/verilator/trunk/verilator@775 77ca24e4-aefa-0310-84f0-b9a241c72d87 --- src/V3Const.cpp | 32 +++++++++++++++++++++++++++++-- src/V3Number.cpp | 6 ++++++ src/V3Number.h | 1 + test_regress/t/t_math_signed.v | 16 ++++++++++++++++ test_regress/t/t_order_wireloop.v | 12 +++--------- 5 files changed, 56 insertions(+), 11 deletions(-) diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 2f8e67e48..18b0493b4 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -87,6 +87,10 @@ private: return (nodep->castConst() && !nodep->castConst()->num().isFourState()); } + bool operandIsPowTwo(AstNode* nodep) { + if (!operandIsTwostate(nodep)) return false; + return (1==nodep->castConst()->num().countOnes()); + } bool operandShiftOp(AstNodeBiop* nodep) { if (!nodep->rhsp()->castConst()) return false; AstNodeBiop* lhsp = nodep->lhsp()->castNodeBiop(); @@ -317,6 +321,24 @@ private: newp->lhsp()->widthSignedFrom(nodep); nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL; } + void replaceMulShift (AstMul* nodep) { // Mul, but not MulS as not simple shift + UINFO(5,"MUL(2^n,b)->SHIFTL(b,n) "<lhsp()->castConst()->num().mostSetBitP1()-1; // 2^n->n+1 + AstNode* opp = nodep->rhsp()->unlinkFrBack(); + AstShiftL* newp = new AstShiftL(nodep->fileline(), + opp, new AstConst(nodep->fileline(), amount)); + newp->widthSignedFrom(nodep); + nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL; + } + void replaceDivShift (AstDiv* nodep) { // Mul, but not MulS as not simple shift + UINFO(5,"DIV(b,2^n)->SHIFTR(b,n) "<rhsp()->castConst()->num().mostSetBitP1()-1; // 2^n->n+1 + AstNode* opp = nodep->lhsp()->unlinkFrBack(); + AstShiftR* newp = new AstShiftR(nodep->fileline(), + opp, new AstConst(nodep->fileline(), amount)); + newp->widthSignedFrom(nodep); + nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL; + } void replaceShiftOp (AstNodeBiop* nodep) { UINFO(5,"SHIFT(AND(a,b),CONST)->AND(SHIFT(a,CONST),SHIFT(b,CONST)) "<allOnes TREEOP("AstLogOr {$lhsp, $rhsp.isNeqZero}", "replaceNum(nodep,1)"); TREEOP("AstXor {$lhsp.isAllOnes, $rhsp}", "AstNot{$rhsp}"); - TREEOP("AstPow {operandIsTwo($lhsp), $rhsp}","replacePowShift(nodep)"); // 2**a == 1< a< a>>n + TREEOP("AstPow {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<width()-1; bit>=0; bit--) { + if (bitIs1(bit)) return bit+1; + } + return 0; +} //====================================================================== V3Number& V3Number::opBitsNonX (const V3Number& lhs) { // 0/1->1, X/Z->0 diff --git a/src/V3Number.h b/src/V3Number.h index 9dca15811..95ec3fbec 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -130,6 +130,7 @@ public: uint32_t asHash() const; uint32_t dataWord(int word) const; uint32_t countOnes() const; + uint32_t mostSetBitP1() const; // Highest bit set plus one, IE for 16 return 5, for 0 return 0. // STATICS static int log2b(uint32_t num); diff --git a/test_regress/t/t_math_signed.v b/test_regress/t/t_math_signed.v index 228a03aec..d973a62e2 100644 --- a/test_regress/t/t_math_signed.v +++ b/test_regress/t/t_math_signed.v @@ -75,6 +75,7 @@ module t (/*AUTOARG*/ endfunction integer cyc; initial cyc=0; + wire [31:0] ucyc = cyc; always @ (posedge clk) begin cyc <= cyc + 1; $write("%x %x %x %x %x %x %x\n", cyc, sr,srs,sl,sls, b_s,b_us); @@ -88,9 +89,24 @@ module t (/*AUTOARG*/ end 2: begin a <= 16'sh8b1b; b <= 5'sh1e; // shift AMOUNT is really unsigned + if (ucyc / 1 != 32'd2) $stop; + if (ucyc / 2 != 32'd1) $stop; + if (ucyc * 1 != 32'd2) $stop; + if (ucyc * 2 != 32'd4) $stop; + if (ucyc * 3 != 32'd6) $stop; + if (cyc * 32'sd1 != 32'sd2) $stop; + if (cyc * 32'sd2 != 32'sd4) $stop; + if (cyc * 32'sd3 != 32'sd6) $stop; end 3: begin a <= 16'sh0048; b <= 5'sh1f; + if (ucyc * 1 != 32'd3) $stop; + if (ucyc * 2 != 32'd6) $stop; + if (ucyc * 3 != 32'd9) $stop; + if (ucyc * 4 != 32'd12) $stop; + if (cyc * 32'sd1 != 32'sd3) $stop; + if (cyc * 32'sd2 != 32'sd6) $stop; + if (cyc * 32'sd3 != 32'sd9) $stop; end 4: begin a <= 16'sh4154; b <= 5'sh02; diff --git a/test_regress/t/t_order_wireloop.v b/test_regress/t/t_order_wireloop.v index d42c93ce5..6c5bc0128 100644 --- a/test_regress/t/t_order_wireloop.v +++ b/test_regress/t/t_order_wireloop.v @@ -1,14 +1,8 @@ -// $Id:$ +// $Id$ // DESCRIPTION: Verilator: Verilog Test module // -// Use this file as a template for submitting bugs, etc. -// This module takes a single clock input, and should either -// $write("*-* All Finished *-*\n"); -// $finish -// on success, or $stop. -// -// **If you do not wish for your code to be released to the public -// please note it here** +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2005 by Wilson Snyder. module t (/*AUTOARG*/);