Add more boolean identity fixes

git-svn-id: file://localhost/svn/verilator/trunk/verilator@798 77ca24e4-aefa-0310-84f0-b9a241c72d87
This commit is contained in:
Wilson Snyder 2006-09-27 18:00:53 +00:00
parent ca4e3c1737
commit 94f0809d33
6 changed files with 87 additions and 23 deletions

View File

@ -9,11 +9,13 @@ indicates the contributor was also the author of the fix; Thanks!
*** Allow overriding Perl, Flex and Bison versions. [by Robert Farrell] *** Allow overriding Perl, Flex and Bison versions. [by Robert Farrell]
*** Optimize variables set to constants within basic blocks. *** Optimize variables set to constants within basic blocks for ~3%.
**** Default make no longer makes the docs; if you edit the documentation **** Default make no longer makes the docs; if you edit the documentation
sources, run "make info" to get them. sources, run "make info" to get them.
**** Optimize additional boolean identities (a|a = a, etc.)
* Verilator 3.610 09/20/2006 * Verilator 3.610 09/20/2006
*** Verilator now works under DJGPP (Pentium GCC). [John Stroebel] *** Verilator now works under DJGPP (Pentium GCC). [John Stroebel]

View File

@ -1516,6 +1516,11 @@ Call Verilated::assertOn(false) before you first call the model, then turn
it back on after reset. It defaults to true. When false, all assertions it back on after reset. It defaults to true. When false, all assertions
controlled by --assert are disabled. controlled by --assert are disabled.
=item Why do I get "undefined reference to `sc_time_stamp()'"?
In C++ (non SystemC) code you need to define this function so that the
simulator knows the current time. See the "CONNECTING TO C++" examples.
=item Is the PLI supported? =item Is the PLI supported?
No. No.

View File

@ -1597,7 +1597,8 @@ public:
bool hasClocked() const { return m_sensesp->hasClocked(); } bool hasClocked() const { return m_sensesp->hasClocked(); }
}; };
class AstAttrOf : public AstNode { struct AstAttrOf : public AstNode {
private:
// Return a value of a attribute, for example a LSB or array LSB of a signal // Return a value of a attribute, for example a LSB or array LSB of a signal
AstAttrType m_attrType; // What sort of extraction AstAttrType m_attrType; // What sort of extraction
int m_dimension; // Dimension number (0 is leftmost), for ARRAY_LSB extractions int m_dimension; // Dimension number (0 is leftmost), for ARRAY_LSB extractions
@ -1739,6 +1740,7 @@ struct AstRedXor : public AstNodeUniop {
virtual int instrCount() const { return 1+V3Number::log2b(width()); } virtual int instrCount() const { return 1+V3Number::log2b(width()); }
}; };
struct AstRedXnor : public AstNodeUniop { struct AstRedXnor : public AstNodeUniop {
// AstRedXnors are replaced with AstRedXors in V3Const.
AstRedXnor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { AstRedXnor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(1,1); } width(1,1); }
virtual ~AstRedXnor() {} virtual ~AstRedXnor() {}

View File

@ -170,15 +170,10 @@ private:
static bool operandsSame(AstNode* node1p, AstNode* node2p) { static bool operandsSame(AstNode* node1p, AstNode* node2p) {
// For now we just detect constants & simple vars, though it could be more generic // For now we just detect constants & simple vars, though it could be more generic
if (node1p->castConst() && node2p->castConst()) { if (node1p->castConst() && node2p->castConst()) {
// Match ignoring any X values return node1p->sameTree(node2p);
V3Number num (node1p->fileline(), 1);
num.opCaseEq(node1p->castConst()->num(), node2p->castConst()->num());
return num.isNeqZero();
} }
else if (node1p->castVarRef() && node2p->castVarRef() else if (node1p->castVarRef() && node2p->castVarRef()) {
&& node1p->sameTree(node2p)) { return node1p->sameTree(node2p);
// Same variable
return true;
} else { } else {
return false; return false;
} }
@ -239,6 +234,12 @@ private:
void replaceZero(AstNode* nodep) { void replaceZero(AstNode* nodep) {
replaceNum(nodep, 0); nodep=NULL; replaceNum(nodep, 0); nodep=NULL;
} }
void replaceAllOnes (AstNode* nodep) {
V3Number num (nodep->fileline(), nodep->width(), 0);
V3Number ones (nodep->fileline(), nodep->width());
ones.opNot(num);
replaceNum(nodep, ones); nodep=NULL;
}
void replaceConst(AstNodeUniop* nodep) { void replaceConst(AstNodeUniop* nodep) {
V3Number num (nodep->fileline(), nodep->width()); V3Number num (nodep->fileline(), nodep->width());
nodep->numberOperate(num, nodep->lhsp()->castConst()->num()); nodep->numberOperate(num, nodep->lhsp()->castConst()->num());
@ -945,6 +946,7 @@ private:
// }" # bracket not paren // }" # bracket not paren
// ,"function to call" // ,"function to call"
// or ,"AstREPLACEMENT_TYPE{ $accessor }" // or ,"AstREPLACEMENT_TYPE{ $accessor }"
// or ,"! # Print line number when matches, so can see operations
// Lint Checks // Lint Checks
// v--- *1* These ops are always first, as we warn before replacing // v--- *1* These ops are always first, as we warn before replacing
@ -969,6 +971,7 @@ private:
TREEOP("AstShiftR{$lhsp.isZero, $rhsp}", "replaceZero(nodep)"); TREEOP("AstShiftR{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZero(nodep)"); TREEOP("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)"); TREEOP("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstXnor {$lhsp.isZero, $rhsp}", "AstNot{$rhsp}");
TREEOP("AstSub {$lhsp.isZero, $rhsp}", "AstUnaryMin{$rhsp}"); TREEOP("AstSub {$lhsp.isZero, $rhsp}", "AstUnaryMin{$rhsp}");
TREEOP("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)"); TREEOP("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstAnd {$lhsp, $rhsp.isZero}", "replaceZero(nodep)"); TREEOP("AstAnd {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
@ -982,6 +985,7 @@ private:
TREEOP("AstShiftRS{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)"); TREEOP("AstShiftRS{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstSub {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)"); TREEOP("AstSub {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstXor {$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 // Non-zero on one side or the other
TREEOP("AstAnd {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)"); TREEOP("AstAnd {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstLogAnd{$lhsp.isNeqZero, $rhsp}", "replaceWRhs(nodep)"); TREEOP("AstLogAnd{$lhsp.isNeqZero, $rhsp}", "replaceWRhs(nodep)");
@ -992,6 +996,7 @@ 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("AstXnor {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstMul {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)"); TREEOP("AstMul {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstMulS {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)"); TREEOP("AstMulS {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstDiv {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)"); TREEOP("AstDiv {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
@ -1058,6 +1063,28 @@ private:
TREEOP ("AstShiftL{operandShiftShift(nodep)}", "replaceShiftShift(nodep)"); TREEOP ("AstShiftL{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
TREEOP ("AstShiftR{operandShiftShift(nodep)}", "replaceShiftShift(nodep)"); TREEOP ("AstShiftR{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
TREEOP ("AstWordSel{operandWordOOB(nodep)}", "replaceZero(nodep)"); TREEOP ("AstWordSel{operandWordOOB(nodep)}", "replaceZero(nodep)");
// Identical operands on both sides
// AstLogAnd/AstLogOr already converted to AstAnd/AstOr for these rules
// AstAdd->ShiftL(#,1) but uncommon
TREEOP("AstAnd {operandsSame($lhsp,,$rhsp)}", "replaceWLhs(nodep)");
TREEOP("AstDiv {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
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("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstGteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstLtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstLte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
///=== Verilog operators ///=== Verilog operators
// Comparison against 1'b0/1'b1; must be careful about widths. // Comparison against 1'b0/1'b1; must be careful about widths.
// These use Not, so must be Verilog only // These use Not, so must be Verilog only
@ -1075,7 +1102,6 @@ private:
TREEOPV("AstLte {$lhsp->width()==$rhsp->width(), $rhsp.isAllOnes}", "replaceNum(nodep,1)"); TREEOPV("AstLte {$lhsp->width()==$rhsp->width(), $rhsp.isAllOnes}", "replaceNum(nodep,1)");
// Simplify reduction operators // Simplify reduction operators
// This also gets &{...,0,....} => const 0 (Common for unused_ok signals) // This also gets &{...,0,....} => const 0 (Common for unused_ok signals)
TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's
TREEOPV("AstRedAnd{$lhsp, $lhsp.width1}", "replaceWLhs(nodep)"); TREEOPV("AstRedAnd{$lhsp, $lhsp.width1}", "replaceWLhs(nodep)");
TREEOPV("AstRedOr {$lhsp, $lhsp.width1}", "replaceWLhs(nodep)"); TREEOPV("AstRedOr {$lhsp, $lhsp.width1}", "replaceWLhs(nodep)");
TREEOPV("AstRedXor{$lhsp, $lhsp.width1}", "replaceWLhs(nodep)"); TREEOPV("AstRedXor{$lhsp, $lhsp.width1}", "replaceWLhs(nodep)");
@ -1108,6 +1134,7 @@ private:
TREEOPV("AstSel{$fromp.castConcat, $lsbp.castConst, $widthp.castConst, }", "replaceSelConcat(nodep)"); TREEOPV("AstSel{$fromp.castConcat, $lsbp.castConst, $widthp.castConst, }", "replaceSelConcat(nodep)");
TREEOPV("AstSel{$fromp.castReplicate, $lsbp.castConst, $widthp.isOne, }", "replaceSelReplicate(nodep)"); TREEOPV("AstSel{$fromp.castReplicate, $lsbp.castConst, $widthp.isOne, }", "replaceSelReplicate(nodep)");
// Conversions // Conversions
TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's
TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}"); TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}");
TREEOPV("AstLogIff{$lhsp, $rhsp}", "AstLogNot{AstXor{$lhsp,$rhsp}}"); TREEOPV("AstLogIff{$lhsp, $rhsp}", "AstLogNot{AstXor{$lhsp,$rhsp}}");

View File

@ -324,6 +324,7 @@ sub tree_line {
match_func => "match_${type}_${n}", match_func => "match_${type}_${n}",
match_if => $mif, match_if => $mif,
exec_func => $exec_func, exec_func => $exec_func,
uinfo_level => ($to =~ /^!/ ? 0:7),
}; };
($typefunc->{uinfo} = $func) =~ s/[ \t\"\{\}]+/ /g; ($typefunc->{uinfo} = $func) =~ s/[ \t\"\{\}]+/ /g;
push @{$self->{treeop}{$type}}, $typefunc; push @{$self->{treeop}{$type}}, $typefunc;
@ -373,8 +374,11 @@ sub _exec_new_recurse {
sub treeop_exec_func { sub treeop_exec_func {
my $self = shift; my $self = shift;
my $func = shift; my $func = shift;
my $out = "";
$func =~ s/^!//;
if ($func =~ /^\s*[a-zA-Z0-9]+\s*\(/) { # Function call if ($func =~ /^\s*[a-zA-Z0-9]+\s*\(/) { # Function call
$func =~ s/\$([a-zA-Z0-9]+)/nodep->$1()/g; (my $outl = $func) =~ s/\$([a-zA-Z0-9]+)/nodep->$1()/g;
$out .= $outl;
} }
elsif ($func =~ /^\s*Ast([a-zA-Z0-9]+) \s*\{\s* (.*) \s* \}$/x) { elsif ($func =~ /^\s*Ast([a-zA-Z0-9]+) \s*\{\s* (.*) \s* \}$/x) {
@ -419,23 +423,22 @@ sub treeop_exec_func {
$_Exec_Nsyms = 0; $_Exec_Nsyms = 0;
_exec_syms_recurse($aref); _exec_syms_recurse($aref);
$func = "";
foreach my $sym (sort {$_Exec_Syms{$a} cmp $_Exec_Syms{$b}} (keys %_Exec_Syms)) { foreach my $sym (sort {$_Exec_Syms{$a} cmp $_Exec_Syms{$b}} (keys %_Exec_Syms)) {
my $argnp = $_Exec_Syms{$sym}; my $argnp = $_Exec_Syms{$sym};
my $arg = add_nodep($sym); my $arg = add_nodep($sym);
$func .= "AstNode* ${argnp} = ${arg}->unlinkFrBack();\n"; $out .= "AstNode* ${argnp} = ${arg}->unlinkFrBack();\n";
} }
$func .= "AstNode* newp = " . _exec_new_recurse($aref).";\n"; $out .= "AstNode* newp = " . _exec_new_recurse($aref).";\n";
$func .= "nodep->replaceWith(newp);"; $out .= "nodep->replaceWith(newp);";
$func .= "nodep->deleteTree(); nodep=NULL;"; $out .= "nodep->deleteTree(); nodep=NULL;";
#print "FF $func\n" if $Debug; #print "FF $out\n" if $Debug;
} elsif ($func eq "NEVER") { } elsif ($func eq "NEVER") {
$func = "nodep->v3fatalSrc(\"Executing transform that was NEVERed\");"; $out .= "nodep->v3fatalSrc(\"Executing transform that was NEVERed\");";
} else { } else {
$self->error("Unknown execution function format: $func\n"); $self->error("Unknown execution function format: $func\n");
} }
return $func; return $out;
} }
sub tree_match { sub tree_match {
@ -448,7 +451,7 @@ sub tree_match {
$self->print(" bool $typefunc->{match_func}(Ast${base}* nodep) {\n", $self->print(" bool $typefunc->{match_func}(Ast${base}* nodep) {\n",
"\t// $typefunc->{comment}\n",); "\t// $typefunc->{comment}\n",);
$self->print( "\tif ($typefunc->{match_if}) {\n"); $self->print( "\tif ($typefunc->{match_if}) {\n");
$self->print( "\t UINFO(7,(void*)(nodep)<<\" $typefunc->{uinfo}\\n\");\n"); $self->print( "\t UINFO($typefunc->{uinfo_level},(void*)(nodep)<<\" $typefunc->{uinfo}\\n\");\n");
$self->print( "\t $typefunc->{exec_func};\n"); $self->print( "\t $typefunc->{exec_func};\n");
$self->print( "\t return true;\n"); $self->print( "\t return true;\n");
$self->print( "\t}\n"); $self->print( "\t}\n");

View File

@ -54,6 +54,7 @@ our $Raise_Weight_Max = 50;
'VCONST'=> {weight=>1&&20, width=>0, sc=>1, terminal=>1, v=>'%v', }, 'VCONST'=> {weight=>1&&20, width=>0, sc=>1, terminal=>1, v=>'%v', },
'VIDNEW'=> {weight=>1&&10, width=>0, sc=>1, terminal=>0, v=>'%i', }, 'VIDNEW'=> {weight=>1&&10, width=>0, sc=>1, terminal=>0, v=>'%i', },
'VIDOLD'=> {weight=>1&&20, width=>0, sc=>1, terminal=>0, v=>'%i', }, 'VIDOLD'=> {weight=>1&&20, width=>0, sc=>1, terminal=>0, v=>'%i', },
'VIDSAME'=> {weight=>1&&200, width=>0, sc=>1, terminal=>0, v=>'%i', },
'VRANGE'=> {weight=>1&&30, width=>0, signed=>0,sc=>0, terminal=>0, v=>'%i[%2:%3]', }, 'VRANGE'=> {weight=>1&&30, width=>0, signed=>0,sc=>0, terminal=>0, v=>'%i[%2:%3]', },
'VBITSEL'=> {weight=>1&&10, width=>1, signed=>0,sc=>0, terminal=>0, v=>'%i[%2]', }, 'VBITSEL'=> {weight=>1&&10, width=>1, signed=>0,sc=>0, terminal=>0, v=>'%i[%2]', },
'VBITSELP'=> {weight=>1&&10, width=>0, signed=>0,sc=>0, terminal=>0, v=>'%i[%2+:%3]', }, 'VBITSELP'=> {weight=>1&&10, width=>0, signed=>0,sc=>0, terminal=>0, v=>'%i[%2+:%3]', },
@ -119,7 +120,8 @@ my %ops2 =
'VCONST'=> {pl=>'', rnd=>'rnd_const(%tr);'}, 'VCONST'=> {pl=>'', rnd=>'rnd_const(%tr);'},
'VIDNEW'=> {pl=>'%tv=$Vars{%i}{val};', 'VIDNEW'=> {pl=>'%tv=$Vars{%i}{val};',
rnd=>'%i=next_id(%tw); $Vars{%i}=gen_leaf(width=>%tw,trunc=>1,signed=>%tg); id_commit(%tr,"%i");1;',}, rnd=>'%i=next_id(%tw); $Vars{%i}=gen_leaf(width=>%tw,trunc=>1,signed=>%tg); id_commit(%tr,"%i");1;',},
'VIDOLD'=> {pl=>'%tv=$Vars{%i}{val};', rnd=>'%i=old_id(%tr);', ok_id_width=>1,}, 'VIDOLD'=> {pl=>'%tv=$Vars{%i}{val};', rnd=>'%i=id_old(%tr);', ok_id_width=>1,},
'VIDSAME'=> {pl=>'%tv=$Vars{%i}{val};', rnd=>'%i=id_same(%tr);', ok_id_width=>1,},
'VRANGE'=> {pl=>'VRANGE(%tr,$Vars{%i}{val},%2v,%3v);', rnd=>'%i=next_id(%tw); my $lsb=rnd(128-%tw); my $msb=$lsb+%tw-1; %2r=val_leaf($msb); %3r=val_leaf($lsb); $Vars{%i}=gen_leaf(width=>($msb+1));'}, 'VRANGE'=> {pl=>'VRANGE(%tr,$Vars{%i}{val},%2v,%3v);', rnd=>'%i=next_id(%tw); my $lsb=rnd(128-%tw); my $msb=$lsb+%tw-1; %2r=val_leaf($msb); %3r=val_leaf($lsb); $Vars{%i}=gen_leaf(width=>($msb+1));'},
'VBITSEL'=> {pl=>'VRANGE(%tr,$Vars{%i}{val},%2v,%2v);', rnd=>'%i=next_id(%tw); my $wid=min(128,rnd_width()|3); %2r=gen_leaf(width=>(log2($wid)-1),signed=>0); $Vars{%i}=gen_leaf(width=>$wid);'}, 'VBITSEL'=> {pl=>'VRANGE(%tr,$Vars{%i}{val},%2v,%2v);', rnd=>'%i=next_id(%tw); my $wid=min(128,rnd_width()|3); %2r=gen_leaf(width=>(log2($wid)-1),signed=>0); $Vars{%i}=gen_leaf(width=>$wid);'},
'VBITSELP'=> {pl=>'VBITSELP(%tr,$Vars{%i}{val},%2v,%3v);', rnd=>'%i=next_id(%tw); my $wid=min(128,(%tw+rnd_width()|3)); %3r=val_leaf(%tw); my $maxval = $wid-%tw; %2r=(($maxval<4)?val_leaf($maxval):gen_leaf(width=>(log2($maxval)-1),signed=>0)); $Vars{%i}=gen_leaf(width=>$wid);'}, 'VBITSELP'=> {pl=>'VBITSELP(%tr,$Vars{%i}{val},%2v,%3v);', rnd=>'%i=next_id(%tw); my $wid=min(128,(%tw+rnd_width()|3)); %3r=val_leaf(%tw); my $maxval = $wid-%tw; %2r=(($maxval<4)?val_leaf($maxval):gen_leaf(width=>(log2($maxval)-1),signed=>0)); $Vars{%i}=gen_leaf(width=>$wid);'},
@ -421,7 +423,7 @@ sub id_commit {
}; };
} }
sub old_id { sub id_old {
my $treeref = shift; my $treeref = shift;
my $width = $treeref->{width}; my $width = $treeref->{width};
my $signed = $treeref->{signed}; my $signed = $treeref->{signed};
@ -433,6 +435,29 @@ sub old_id {
return $id; return $id;
} }
sub id_same {
my $treeref = shift;
my $width = $treeref->{width};
my $signed = $treeref->{signed};
my @possible;
foreach my $id (keys %VarsBlock) {
next if !$VarsBlock{$id}{used};
my $varref = $Vars{$id};
next if $varref->{signed} != $signed;
next if $varref->{width} != $width;
push @possible, $id;
}
my $n = $#possible + 1;
if ($n<1) { # Nothing, grab another!
return id_old($treeref,$width,$signed);
}
my $idn = rnd($n);
my $id = $possible[$idn];
$VarsBlock{$id}{used} = 1;
return $id;
}
sub write_output_v { sub write_output_v {
my $filename = shift; my $filename = shift;