Internals: Add V3Const preserving liveness, no functional change
This commit is contained in:
parent
9f161b20ef
commit
c8852d183f
|
|
@ -103,8 +103,9 @@ private:
|
|||
bool m_required; // If true, must become a constant
|
||||
bool m_wremove; // Inside scope, no assignw removal
|
||||
bool m_warn; // Output warnings
|
||||
bool m_doV; // Verilog, not C++ conversion
|
||||
bool m_doExpensive; // Enable computationally expensive optimizations
|
||||
bool m_doNConst; // Enable non-constant-child simplifications
|
||||
bool m_doV; // Verilog, not C++ conversion
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstNode* m_scopep; // Current scope
|
||||
|
||||
|
|
@ -1070,6 +1071,7 @@ private:
|
|||
if (operandConst(nodep->varp()->valuep())
|
||||
&& !nodep->lvalue()
|
||||
&& ((!m_params // Can reduce constant wires into equations
|
||||
&& m_doNConst
|
||||
&& v3Global.opt.oConst()
|
||||
&& !nodep->varp()->isSigPublic())
|
||||
|| nodep->varp()->isParam())) {
|
||||
|
|
@ -1122,8 +1124,9 @@ private:
|
|||
}
|
||||
virtual void visit(AstSenItem* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->sensp()->castConst()
|
||||
|| (nodep->varrefp() && nodep->varrefp()->varp()->isParam())) {
|
||||
if (m_doNConst
|
||||
&& (nodep->sensp()->castConst()
|
||||
|| (nodep->varrefp() && nodep->varrefp()->varp()->isParam()))) {
|
||||
// Constants in sensitivity lists may be removed (we'll simplify later)
|
||||
if (nodep->isClocked()) { // A constant can never get a pos/negexge
|
||||
if (onlySenItemInSenTree(nodep)) {
|
||||
|
|
@ -1136,7 +1139,7 @@ private:
|
|||
nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Combo()));
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
} else if (nodep->sensp()->castNot()) {
|
||||
} else if (m_doNConst && nodep->sensp()->castNot()) {
|
||||
// V3Gate may propagate NOTs into clocks... Just deal with it
|
||||
AstNode* sensp = nodep->sensp();
|
||||
AstNode* lastSensp = sensp;
|
||||
|
|
@ -1306,16 +1309,16 @@ private:
|
|||
// Zero elimination
|
||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
replaceNodeAssign(nodep);
|
||||
if (m_doNConst && replaceNodeAssign(nodep)) return;
|
||||
}
|
||||
virtual void visit(AstAssignAlias* nodep, AstNUser*) {
|
||||
// Don't perform any optimizations, keep the alias around
|
||||
}
|
||||
virtual void visit(AstAssignW* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (replaceNodeAssign(nodep)) return;
|
||||
if (m_doNConst && replaceNodeAssign(nodep)) return;
|
||||
AstNodeVarRef* varrefp = nodep->lhsp()->castVarRef(); // Not VarXRef, as different refs may set different values to each hierarchy
|
||||
if (m_wremove && !m_params
|
||||
if (m_wremove && !m_params && m_doNConst
|
||||
&& m_modp && operandConst(nodep->rhsp())
|
||||
&& !nodep->rhsp()->castConst()->num().isFourState()
|
||||
&& varrefp // Don't do messes with BITREFs/ARRAYREFs
|
||||
|
|
@ -1340,6 +1343,7 @@ private:
|
|||
|
||||
virtual void visit(AstNodeIf* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_doNConst) {
|
||||
if (AstConst* constp = nodep->condp()->castConst()) {
|
||||
AstNode* keepp = NULL;
|
||||
if (constp->isZero()) {
|
||||
|
|
@ -1413,6 +1417,7 @@ private:
|
|||
replaceBoolShift(nodep->condp());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstSFormatF* nodep, AstNUser*) {
|
||||
// Substitute constants into displays. The main point of this is to
|
||||
|
|
@ -1423,7 +1428,7 @@ private:
|
|||
for (AstNode* argp = nodep->exprsp(); argp; argp=argp->nextp()) {
|
||||
if (argp->castConst()) { anyconst=true; break; }
|
||||
}
|
||||
if (anyconst) {
|
||||
if (m_doNConst && anyconst) {
|
||||
//UINFO(9," Display in "<<nodep->text()<<endl);
|
||||
string dispout = "";
|
||||
string fmt = "";
|
||||
|
|
@ -1486,6 +1491,7 @@ private:
|
|||
|
||||
virtual void visit(AstWhile* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_doNConst) {
|
||||
if (nodep->condp()->isZero()) {
|
||||
UINFO(4,"WHILE(0) => nop "<<nodep<<endl);
|
||||
if (nodep->precondsp()) nodep->replaceWith(nodep->precondsp());
|
||||
|
|
@ -1496,6 +1502,7 @@ private:
|
|||
replaceBoolShift(nodep->condp());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// These are converted by V3Param. Don't constify as we don't want the from() VARREF to disappear, if any
|
||||
// If output of a presel didn't get consted, chances are V3Param didn't visit properly
|
||||
|
|
@ -1547,10 +1554,11 @@ private:
|
|||
// Lint Checks
|
||||
// v--- *1* These ops are always first, as we warn before replacing
|
||||
// v--- *V* This op is a verilog op, only in m_doV mode
|
||||
// v--- *C* This op works on all constant children, allowed in m_doConst mode
|
||||
TREEOP1("AstSel{warnSelect(nodep)}", "NEVER");
|
||||
// Generic constants on both side. Do this first to avoid other replacements
|
||||
TREEOP("AstNodeBiop {$lhsp.castConst, $rhsp.castConst}", "replaceConst(nodep)");
|
||||
TREEOP("AstNodeUniop{$lhsp.castConst, !nodep->isOpaque()}", "replaceConst(nodep)");
|
||||
TREEOPC("AstNodeBiop {$lhsp.castConst, $rhsp.castConst}", "replaceConst(nodep)");
|
||||
TREEOPC("AstNodeUniop{$lhsp.castConst, !nodep->isOpaque()}", "replaceConst(nodep)");
|
||||
// Zero on one side or the other
|
||||
TREEOP ("AstAdd {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstAnd {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
|
|
@ -1746,7 +1754,7 @@ private:
|
|||
TREEOPV("AstSel{operandSelExtend(nodep)}", "replaceWChild(nodep, nodep->fromp()->castExtend()->lhsp())");
|
||||
TREEOPV("AstSel{operandSelFull(nodep)}", "replaceWChild(nodep, nodep->fromp())");
|
||||
TREEOPV("AstSel{$fromp.castSel}", "replaceSelSel(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castConst, $lsbp.castConst, $widthp.castConst, }", "replaceConst(nodep)");
|
||||
TREEOPC("AstSel{$fromp.castConst, $lsbp.castConst, $widthp.castConst, }", "replaceConst(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castConcat, $lsbp.castConst, $widthp.castConst, }", "replaceSelConcat(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castReplicate, $lsbp.castConst, $widthp.isOne, }", "replaceSelReplicate(nodep)");
|
||||
// Conversions
|
||||
|
|
@ -1754,7 +1762,7 @@ private:
|
|||
TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}");
|
||||
TREEOPV("AstLogIff{$lhsp, $rhsp}", "AstLogNot{AstXor{$lhsp,$rhsp}}");
|
||||
// Strings
|
||||
TREEOP ("AstCvtPackString{$lhsp.castConst}", "replaceConstString(nodep, nodep->lhsp()->castConst()->num().toString())");
|
||||
TREEOPC("AstCvtPackString{$lhsp.castConst}", "replaceConstString(nodep, nodep->lhsp()->castConst()->num().toString())");
|
||||
|
||||
|
||||
// Possible futures:
|
||||
|
|
@ -1784,6 +1792,7 @@ public:
|
|||
// Processing Mode Enum
|
||||
enum ProcMode {
|
||||
PROC_PARAMS,
|
||||
PROC_V_LIVE,
|
||||
PROC_V_WARN,
|
||||
PROC_V_NOWARN,
|
||||
PROC_V_EXPENSIVE,
|
||||
|
|
@ -1794,19 +1803,21 @@ public:
|
|||
ConstVisitor(ProcMode pmode) {
|
||||
m_params = false;
|
||||
m_required = false;
|
||||
m_doV = false;
|
||||
m_doExpensive = false;
|
||||
m_doNConst = false;
|
||||
m_doV = false;
|
||||
m_warn = false;
|
||||
m_wremove = true; // Overridden in visitors
|
||||
m_modp = NULL;
|
||||
m_scopep = NULL;
|
||||
//
|
||||
switch (pmode) {
|
||||
case PROC_PARAMS: m_doV = true; m_params = true; m_required = true; break;
|
||||
case PROC_V_WARN: m_doV = true; m_warn = true; break;
|
||||
case PROC_V_NOWARN: m_doV = true; break;
|
||||
case PROC_V_EXPENSIVE: m_doV = true; m_doExpensive = true; break;
|
||||
case PROC_CPP: m_doV = false; break;
|
||||
case PROC_PARAMS: m_doV = true; m_doNConst = true; m_params = true; m_required = true; break;
|
||||
case PROC_V_LIVE: m_doV = true; break;
|
||||
case PROC_V_WARN: m_doV = true; m_doNConst = true; m_warn = true; break;
|
||||
case PROC_V_NOWARN: m_doV = true; m_doNConst = true; break;
|
||||
case PROC_V_EXPENSIVE: m_doV = true; m_doNConst = true; m_doExpensive = true; break;
|
||||
case PROC_CPP: m_doV = false; m_doNConst = true; break;
|
||||
default: v3fatalSrc("Bad case"); break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1858,6 +1869,15 @@ AstNode* V3Const::constifyEdit(AstNode* nodep) {
|
|||
return nodep;
|
||||
}
|
||||
|
||||
void V3Const::constifyAllLive(AstNetlist* nodep) {
|
||||
// Only call from Verilator.cpp, as it uses user#'s
|
||||
// This only pushes constants up, doesn't make any other edits
|
||||
// IE doesn't prune dead statements, as we need to do some usability checks after this
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_V_LIVE);
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
}
|
||||
|
||||
void V3Const::constifyAll(AstNetlist* nodep) {
|
||||
// Only call from Verilator.cpp, as it uses user#'s
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ public:
|
|||
// Force this cell node's parameter list to become a constant
|
||||
// Return new node that may have replaced nodep
|
||||
static AstNode* constifyParamsEdit(AstNode* nodep);
|
||||
// Only do constant pushing, without removing dead logic
|
||||
static void constifyAllLive(AstNetlist* nodep);
|
||||
// Everything that's possible
|
||||
static void constifyAll(AstNetlist* nodep);
|
||||
// Also, warn
|
||||
|
|
|
|||
11
src/astgen
11
src/astgen
|
|
@ -268,8 +268,8 @@ sub tree_line {
|
|||
$func =~ s!\s*//.*$!!;
|
||||
$func =~ s!\s*;\s*$!!;
|
||||
|
||||
if ($func =~ /TREEOP(1?)(V?)\s*\(\s* \"([^\"]*)\" \s*,\s* \"([^\"]*)\" \s*\)/sx) {
|
||||
my $order = $1; my $cpp = $2; my $from = $3; my $to = $4;
|
||||
if ($func =~ /TREEOP(1?)([VC]?)\s*\(\s* \"([^\"]*)\" \s*,\s* \"([^\"]*)\" \s*\)/sx) {
|
||||
my $order = $1; my $doflag = $2; my $from = $3; my $to = $4;
|
||||
#$self->print("// $from $to\n");
|
||||
if (!$self->{did_out_tree}) {
|
||||
$self->{did_out_tree} = 1;
|
||||
|
|
@ -284,8 +284,11 @@ sub tree_line {
|
|||
my $subnodes = $2;
|
||||
(::subclasses_of($type)) or $self->error("Unknown AstNode type: $type: in $func");
|
||||
|
||||
my $mif = "";
|
||||
$mif = "m_doV" if $cpp;
|
||||
my $mif;
|
||||
if ($doflag eq '') { $mif = "m_doNConst"; }
|
||||
elsif ($doflag eq 'V') { $mif = "m_doV"; }
|
||||
elsif ($doflag eq 'C') { $mif = ""; }
|
||||
else { die; }
|
||||
$subnodes =~ s/,,/__ESCAPEDCOMMA__/g;
|
||||
foreach my $subnode (split /\s*,\s*/, $subnodes) {
|
||||
$subnode =~ s/__ESCAPEDCOMMA__/,/g;
|
||||
|
|
|
|||
Loading…
Reference in New Issue