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()
|
||||
&& !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) "<<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) {
|
||||
UINFO(5,"SHIFT(AND(a,b),CONST)->AND(SHIFT(a,CONST),SHIFT(b,CONST)) "<<nodep<<endl);
|
||||
AstNRelinker handle;
|
||||
@ -970,6 +992,12 @@ private:
|
||||
TREEOP("AstOr {$lhsp, $rhsp.isAllOnes}", "replaceWRhs(nodep)"); //->allOnes
|
||||
TREEOP("AstLogOr {$lhsp, $rhsp.isNeqZero}", "replaceNum(nodep,1)");
|
||||
TREEOP("AstXor {$lhsp.isAllOnes, $rhsp}", "AstNot{$rhsp}");
|
||||
TREEOP("AstMul {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
|
||||
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
|
||||
|
@ -430,6 +430,12 @@ uint32_t V3Number::countOnes() const {
|
||||
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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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*/);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user