forked from github/verilator
Optimize n*powers of 2. (For parameterized DDR model)
git-svn-id: file://localhost/svn/verilator/trunk/verilator@775 77ca24e4-aefa-0310-84f0-b9a241c72d87
This commit is contained in:
parent
6f48185a1f
commit
749fdaae31
@ -87,6 +87,10 @@ private:
|
|||||||
return (nodep->castConst()
|
return (nodep->castConst()
|
||||||
&& !nodep->castConst()->num().isFourState());
|
&& !nodep->castConst()->num().isFourState());
|
||||||
}
|
}
|
||||||
|
bool operandIsPowTwo(AstNode* nodep) {
|
||||||
|
if (!operandIsTwostate(nodep)) return false;
|
||||||
|
return (1==nodep->castConst()->num().countOnes());
|
||||||
|
}
|
||||||
bool operandShiftOp(AstNodeBiop* nodep) {
|
bool operandShiftOp(AstNodeBiop* nodep) {
|
||||||
if (!nodep->rhsp()->castConst()) return false;
|
if (!nodep->rhsp()->castConst()) return false;
|
||||||
AstNodeBiop* lhsp = nodep->lhsp()->castNodeBiop();
|
AstNodeBiop* lhsp = nodep->lhsp()->castNodeBiop();
|
||||||
@ -317,6 +321,24 @@ private:
|
|||||||
newp->lhsp()->widthSignedFrom(nodep);
|
newp->lhsp()->widthSignedFrom(nodep);
|
||||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
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) "<<nodep<<endl);
|
||||||
|
int amount = nodep->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) "<<nodep<<endl);
|
||||||
|
int amount = nodep->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) {
|
void replaceShiftOp (AstNodeBiop* nodep) {
|
||||||
UINFO(5,"SHIFT(AND(a,b),CONST)->AND(SHIFT(a,CONST),SHIFT(b,CONST)) "<<nodep<<endl);
|
UINFO(5,"SHIFT(AND(a,b),CONST)->AND(SHIFT(a,CONST),SHIFT(b,CONST)) "<<nodep<<endl);
|
||||||
AstNRelinker handle;
|
AstNRelinker handle;
|
||||||
@ -970,8 +992,14 @@ private:
|
|||||||
TREEOP("AstOr {$lhsp, $rhsp.isAllOnes}", "replaceWRhs(nodep)"); //->allOnes
|
TREEOP("AstOr {$lhsp, $rhsp.isAllOnes}", "replaceWRhs(nodep)"); //->allOnes
|
||||||
TREEOP("AstLogOr {$lhsp, $rhsp.isNeqZero}", "replaceNum(nodep,1)");
|
TREEOP("AstLogOr {$lhsp, $rhsp.isNeqZero}", "replaceNum(nodep,1)");
|
||||||
TREEOP("AstXor {$lhsp.isAllOnes, $rhsp}", "AstNot{$rhsp}");
|
TREEOP("AstXor {$lhsp.isAllOnes, $rhsp}", "AstNot{$rhsp}");
|
||||||
TREEOP("AstPow {operandIsTwo($lhsp), $rhsp}","replacePowShift(nodep)"); // 2**a == 1<<a
|
TREEOP("AstMul {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
|
||||||
TREEOP("AstPowS {operandIsTwo($lhsp), $rhsp}","replacePowShift(nodep)"); // 2**a == 1<<a
|
TREEOP("AstMulS {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
|
||||||
|
TREEOP("AstDiv {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
|
||||||
|
TREEOP("AstDivS {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
|
||||||
|
TREEOP("AstMul {operandIsPowTwo($lhsp), $rhsp}", "replaceMulShift(nodep)"); // a*2^n -> a<<n
|
||||||
|
TREEOP("AstDiv {$lhsp, operandIsPowTwo($rhsp)}", "replaceDivShift(nodep)"); // a/2^n -> a>>n
|
||||||
|
TREEOP("AstPow {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a
|
||||||
|
TREEOP("AstPowS {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a
|
||||||
// Trinary ops
|
// Trinary ops
|
||||||
// Note V3Case::Sel requires Cond to always be conditionally executed in C to prevent core dump!
|
// Note V3Case::Sel requires Cond to always be conditionally executed in C to prevent core dump!
|
||||||
TREEOP("AstNodeCond{$condp.isZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr2p)");
|
TREEOP("AstNodeCond{$condp.isZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr2p)");
|
||||||
|
@ -430,6 +430,12 @@ uint32_t V3Number::countOnes() const {
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t V3Number::mostSetBitP1() const {
|
||||||
|
for (int bit=this->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
|
V3Number& V3Number::opBitsNonX (const V3Number& lhs) { // 0/1->1, X/Z->0
|
||||||
|
@ -130,6 +130,7 @@ public:
|
|||||||
uint32_t asHash() const;
|
uint32_t asHash() const;
|
||||||
uint32_t dataWord(int word) const;
|
uint32_t dataWord(int word) const;
|
||||||
uint32_t countOnes() const;
|
uint32_t countOnes() const;
|
||||||
|
uint32_t mostSetBitP1() const; // Highest bit set plus one, IE for 16 return 5, for 0 return 0.
|
||||||
|
|
||||||
// STATICS
|
// STATICS
|
||||||
static int log2b(uint32_t num);
|
static int log2b(uint32_t num);
|
||||||
|
@ -75,6 +75,7 @@ module t (/*AUTOARG*/
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
integer cyc; initial cyc=0;
|
integer cyc; initial cyc=0;
|
||||||
|
wire [31:0] ucyc = cyc;
|
||||||
always @ (posedge clk) begin
|
always @ (posedge clk) begin
|
||||||
cyc <= cyc + 1;
|
cyc <= cyc + 1;
|
||||||
$write("%x %x %x %x %x %x %x\n", cyc, sr,srs,sl,sls, b_s,b_us);
|
$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
|
end
|
||||||
2: begin
|
2: begin
|
||||||
a <= 16'sh8b1b; b <= 5'sh1e; // shift AMOUNT is really unsigned
|
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
|
end
|
||||||
3: begin
|
3: begin
|
||||||
a <= 16'sh0048; b <= 5'sh1f;
|
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
|
end
|
||||||
4: begin
|
4: begin
|
||||||
a <= 16'sh4154; b <= 5'sh02;
|
a <= 16'sh4154; b <= 5'sh02;
|
||||||
|
@ -1,14 +1,8 @@
|
|||||||
// $Id:$
|
// $Id$
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// Use this file as a template for submitting bugs, etc.
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
// This module takes a single clock input, and should either
|
// without warranty, 2005 by Wilson Snyder.
|
||||||
// $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**
|
|
||||||
|
|
||||||
module t (/*AUTOARG*/);
|
module t (/*AUTOARG*/);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user