DFG: Add more peephole patterns
This commit is contained in:
parent
694bdbc130
commit
84b9502af4
18
src/V3Dfg.h
18
src/V3Dfg.h
|
|
@ -39,6 +39,7 @@
|
|||
#include "V3Hasher.h"
|
||||
#include "V3List.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
|
|
@ -275,6 +276,8 @@ public:
|
|||
FileLine* fileline() const { return m_filelinep; }
|
||||
// The data type of the result of the nodes
|
||||
AstNodeDType* dtypep() const { return m_dtypep; }
|
||||
// The type of this vertex
|
||||
DfgType type() const { return m_type; }
|
||||
|
||||
// Width of result
|
||||
uint32_t width() const {
|
||||
|
|
@ -365,7 +368,7 @@ public:
|
|||
|
||||
// Returns first source edge which satisfies the given predicate 'p', or nullptr if no such
|
||||
// sink vertex exists
|
||||
inline DfgEdge* findSourceEdge(std::function<bool(const DfgEdge&, size_t)> p);
|
||||
inline const DfgEdge* findSourceEdge(std::function<bool(const DfgEdge&, size_t)> p) const;
|
||||
|
||||
// Returns first sink vertex of type 'Vertex' which satisfies the given predicate 'p',
|
||||
// or nullptr if no such sink vertex exists
|
||||
|
|
@ -747,6 +750,13 @@ public:
|
|||
FileLine* driverFileLine(size_t idx) const { return m_driverData[idx].first; }
|
||||
uint32_t driverIndex(size_t idx) const { return m_driverData[idx].second; }
|
||||
|
||||
DfgVertex* driverAt(size_t idx) const {
|
||||
const DfgEdge* const edgep = findSourceEdge([=](const DfgEdge&, size_t i) { //
|
||||
return driverIndex(i) == idx;
|
||||
});
|
||||
return edgep ? edgep->sourcep() : nullptr;
|
||||
}
|
||||
|
||||
const string srcName(size_t idx) const override { return cvtToStr(driverIndex(idx)); }
|
||||
};
|
||||
|
||||
|
|
@ -897,12 +907,12 @@ void DfgVertex::forEachSinkEdge(std::function<void(const DfgEdge&)> f) const {
|
|||
}
|
||||
}
|
||||
|
||||
DfgEdge* DfgVertex::findSourceEdge(std::function<bool(const DfgEdge&, size_t)> p) {
|
||||
const DfgEdge* DfgVertex::findSourceEdge(std::function<bool(const DfgEdge&, size_t)> p) const {
|
||||
const auto pair = sourceEdges();
|
||||
DfgEdge* const edgesp = pair.first;
|
||||
const DfgEdge* const edgesp = pair.first;
|
||||
const size_t arity = pair.second;
|
||||
for (size_t i = 0; i < arity; ++i) {
|
||||
DfgEdge& edge = edgesp[i];
|
||||
const DfgEdge& edge = edgesp[i];
|
||||
if (p(edge, i)) return &edge;
|
||||
}
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -62,6 +62,24 @@ V3DfgPeepholeContext::~V3DfgPeepholeContext() {
|
|||
#undef OPTIMIZATION_EMIT_STATS
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
template <typename T_Reduction>
|
||||
struct ReductionToBitwiseImpl {};
|
||||
template <> struct ReductionToBitwiseImpl<DfgRedAnd> { using type = DfgAnd; };
|
||||
template <> struct ReductionToBitwiseImpl<DfgRedOr> { using type = DfgOr; };
|
||||
template <> struct ReductionToBitwiseImpl<DfgRedXor> { using type = DfgXor; };
|
||||
template <typename T_Reductoin>
|
||||
using ReductionToBitwise = typename ReductionToBitwiseImpl<T_Reductoin>::type;
|
||||
|
||||
template <typename T_Bitwise>
|
||||
struct BitwiseToReductionImpl {};
|
||||
template <> struct BitwiseToReductionImpl<DfgAnd> { using type = DfgRedAnd; };
|
||||
template <> struct BitwiseToReductionImpl<DfgOr> { using type = DfgRedOr; };
|
||||
template <> struct BitwiseToReductionImpl<DfgXor> { using type = DfgRedXor; };
|
||||
template <typename T_Reductoin>
|
||||
using BitwiseToReduction = typename BitwiseToReductionImpl<T_Reductoin>::type;
|
||||
// clang-format on
|
||||
|
||||
class V3DfgPeephole final : public DfgVisitor {
|
||||
|
||||
// STATE
|
||||
|
|
@ -133,6 +151,22 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
// Transformations that apply to all associative binary vertices
|
||||
void associativeBinary(DfgVertexWithArity<2>* vtxp) {
|
||||
DfgVertex* const lhsp = vtxp->lhsp();
|
||||
|
||||
// Make associative trees right leaning (for better CSE opportunities)
|
||||
if (lhsp->type() == vtxp->type() && !lhsp->hasMultipleSinks()) {
|
||||
DfgVertexWithArity<2>* const lBinp = static_cast<DfgVertexWithArity<2>*>(lhsp);
|
||||
APPLYING(RIGHT_LEANING_ASSOC) {
|
||||
vtxp->replaceWith(lBinp);
|
||||
vtxp->lhsp(lBinp->rhsp());
|
||||
lBinp->rhsp(vtxp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bitwise operation with one side Const, and the other side a Concat
|
||||
template <typename Vertex>
|
||||
bool tryPushBitwiseOpThroughConcat(Vertex* vtxp, DfgConst* constp, DfgConcat* concatp) {
|
||||
|
|
@ -226,33 +260,56 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
return false;
|
||||
}
|
||||
|
||||
template <typename Vertex>
|
||||
void optimizeReduction(Vertex* vtxp) {
|
||||
static_assert(std::is_same<Vertex, DfgRedAnd>::value
|
||||
|| std::is_same<Vertex, DfgRedOr>::value
|
||||
|| std::is_same<Vertex, DfgRedXor>::value,
|
||||
"Invalid 'Vertex' type for this method");
|
||||
template <typename Bitwise>
|
||||
bool tryPushBitwiseOpThroughReductions(Bitwise* vtxp) {
|
||||
using Reduction = BitwiseToReduction<Bitwise>;
|
||||
|
||||
if (Reduction* const lRedp = vtxp->lhsp()->template cast<Reduction>()) {
|
||||
if (Reduction* const rRedp = vtxp->rhsp()->template cast<Reduction>()) {
|
||||
DfgVertex* const lSrcp = lRedp->srcp();
|
||||
DfgVertex* const rSrcp = rRedp->srcp();
|
||||
if (lSrcp->dtypep() == rSrcp->dtypep()) {
|
||||
APPLYING(PUSH_BITWISE_THROUGH_REDUCTION) {
|
||||
FileLine* const flp = vtxp->fileline();
|
||||
Bitwise* const bwp = new Bitwise{m_dfg, flp, lSrcp->dtypep()};
|
||||
bwp->lhsp(lSrcp);
|
||||
bwp->rhsp(rSrcp);
|
||||
Reduction* const redp = new Reduction{m_dfg, flp, m_bitDType};
|
||||
redp->srcp(bwp);
|
||||
vtxp->replaceWith(redp);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Reduction>
|
||||
void optimizeReduction(Reduction* vtxp) {
|
||||
using Bitwise = ReductionToBitwise<Reduction>;
|
||||
|
||||
DfgVertex* const srcp = vtxp->srcp();
|
||||
FileLine* const flp = vtxp->fileline();
|
||||
|
||||
// Reduction of 1-bit value -- Currently unreachable as V3Const can remove these, but
|
||||
// in the future they will be created during this optimization.
|
||||
if (srcp->width() == 1) { // LCOV_EXCL_START
|
||||
// Reduction of 1-bit value
|
||||
if (srcp->width() == 1) {
|
||||
APPLYING(REMOVE_WIDTH_ONE_REDUCTION) {
|
||||
vtxp->replaceWith(srcp);
|
||||
return;
|
||||
}
|
||||
} // LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
if (DfgCond* const condp = srcp->cast<DfgCond>()) {
|
||||
if (condp->thenp()->is<DfgConst>() || condp->elsep()->is<DfgConst>()) {
|
||||
APPLYING(PUSH_REDUCTION_THROUGH_COND_WITH_CONST_BRANCH) {
|
||||
// The new 'then' vertex
|
||||
Vertex* const newThenp = new Vertex{m_dfg, vtxp->fileline(), m_bitDType};
|
||||
Reduction* const newThenp = new Reduction{m_dfg, flp, m_bitDType};
|
||||
newThenp->srcp(condp->thenp());
|
||||
|
||||
// The new 'else' vertex
|
||||
Vertex* const newElsep = new Vertex{m_dfg, vtxp->fileline(), m_bitDType};
|
||||
Reduction* const newElsep = new Reduction{m_dfg, flp, m_bitDType};
|
||||
newElsep->srcp(condp->elsep());
|
||||
|
||||
// The replacement Cond vertex
|
||||
|
|
@ -268,12 +325,33 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
if (DfgConcat* const concatp = srcp->cast<DfgConcat>()) {
|
||||
APPLYING(PUSH_REDUCTION_THROUGH_CONCAT) {
|
||||
// Reduce the parts of the concatenation
|
||||
Reduction* const lReducep = new Reduction{m_dfg, concatp->fileline(), m_bitDType};
|
||||
lReducep->srcp(concatp->lhsp());
|
||||
Reduction* const rReducep = new Reduction{m_dfg, concatp->fileline(), m_bitDType};
|
||||
rReducep->srcp(concatp->rhsp());
|
||||
|
||||
// Bitwise reduce the results
|
||||
DfgVertexWithArity<2>* const replacementp = new Bitwise{m_dfg, flp, m_bitDType};
|
||||
replacementp->lhsp(lReducep);
|
||||
replacementp->rhsp(rReducep);
|
||||
vtxp->replaceWith(replacementp);
|
||||
|
||||
// Optimize the new reductions
|
||||
optimizeReduction(lReducep);
|
||||
optimizeReduction(rReducep);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (DfgConst* const constp = srcp->cast<DfgConst>()) {
|
||||
APPLYING(REPLACE_REDUCTION_OF_CONST) {
|
||||
DfgConst* const replacementp = makeZero(vtxp->fileline(), 1);
|
||||
if (std::is_same<Vertex, DfgRedAnd>::value) {
|
||||
DfgConst* const replacementp = makeZero(flp, 1);
|
||||
if VL_CONSTEXPR_CXX17 (std::is_same<Reduction, DfgRedAnd>::value) {
|
||||
replacementp->num().opRedAnd(constp->num());
|
||||
} else if (std::is_same<Vertex, DfgRedOr>::value) {
|
||||
} else if VL_CONSTEXPR_CXX17 (std::is_same<Reduction, DfgRedOr>::value) {
|
||||
replacementp->num().opRedOr(constp->num());
|
||||
} else {
|
||||
replacementp->num().opRedXor(constp->num());
|
||||
|
|
@ -304,8 +382,9 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
|
||||
FileLine* const flp = vtxp->fileline();
|
||||
|
||||
// Convert Extend into Concat with zeros. This simplifies other patterns as they only need
|
||||
// to handle Concat, which is more generic, and don't need special cases for Extend.
|
||||
// Convert Extend into Concat with zeros. This simplifies other patterns as they only
|
||||
// need to handle Concat, which is more generic, and don't need special cases for
|
||||
// Extend.
|
||||
APPLYING(REPLACE_EXTEND) {
|
||||
DfgConcat* const replacementp = new DfgConcat{m_dfg, flp, vtxp->dtypep()};
|
||||
replacementp->lhsp(makeZero(flp, extension));
|
||||
|
|
@ -354,6 +433,17 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
// Not of Eq
|
||||
if (DfgEq* const eqp = vtxp->srcp()->cast<DfgEq>()) {
|
||||
APPLYING(REPLACE_NOT_EQ) {
|
||||
DfgNeq* const replacementp = new DfgNeq{m_dfg, eqp->fileline(), vtxp->dtypep()};
|
||||
replacementp->lhsp(eqp->lhsp());
|
||||
replacementp->rhsp(eqp->rhsp());
|
||||
vtxp->replaceWith(replacementp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Not of Neq
|
||||
if (DfgNeq* const neqp = vtxp->srcp()->cast<DfgNeq>()) {
|
||||
APPLYING(REPLACE_NOT_NEQ) {
|
||||
|
|
@ -381,22 +471,38 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
UASSERT_OBJ(vtxp->width() == vtxp->rhsp()->width(), vtxp, "Mismatched RHS width");
|
||||
|
||||
commutativeBinary(vtxp);
|
||||
associativeBinary(vtxp);
|
||||
|
||||
DfgVertex* const lhsp = vtxp->lhsp();
|
||||
DfgVertex* const rhsp = vtxp->rhsp();
|
||||
|
||||
FileLine* const flp = vtxp->fileline();
|
||||
|
||||
// Bubble pushing
|
||||
if (lhsp->is<DfgNot>() && rhsp->is<DfgNot>()) {
|
||||
APPLYING(REPLACE_AND_OF_NOT_AND_NOT) {
|
||||
DfgOr* const orp = new DfgOr{m_dfg, flp, vtxp->dtypep()};
|
||||
orp->lhsp(lhsp->as<DfgNot>()->srcp());
|
||||
orp->rhsp(rhsp->as<DfgNot>()->srcp());
|
||||
DfgNot* const notp = new DfgNot{m_dfg, flp, vtxp->dtypep()};
|
||||
notp->srcp(orp);
|
||||
vtxp->replaceWith(notp);
|
||||
return;
|
||||
if (DfgNot* const lhsNotp = lhsp->cast<DfgNot>()) {
|
||||
if (DfgNot* const rhsNotp = rhsp->cast<DfgNot>()) {
|
||||
APPLYING(REPLACE_AND_OF_NOT_AND_NOT) {
|
||||
DfgOr* const orp = new DfgOr{m_dfg, flp, vtxp->dtypep()};
|
||||
orp->lhsp(lhsNotp->srcp());
|
||||
orp->rhsp(rhsNotp->srcp());
|
||||
DfgNot* const notp = new DfgNot{m_dfg, flp, vtxp->dtypep()};
|
||||
notp->srcp(orp);
|
||||
vtxp->replaceWith(notp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (DfgNeq* const rhsNeqp = rhsp->cast<DfgNeq>()) {
|
||||
APPLYING(REPLACE_AND_OF_NOT_AND_NEQ) {
|
||||
DfgOr* const orp = new DfgOr{m_dfg, flp, vtxp->dtypep()};
|
||||
orp->lhsp(lhsNotp->srcp());
|
||||
DfgEq* const newRhsp = new DfgEq{m_dfg, rhsp->fileline(), rhsp->dtypep()};
|
||||
newRhsp->lhsp(rhsNeqp->lhsp());
|
||||
newRhsp->rhsp(rhsNeqp->rhsp());
|
||||
orp->rhsp(newRhsp);
|
||||
DfgNot* const notp = new DfgNot{m_dfg, flp, vtxp->dtypep()};
|
||||
notp->srcp(orp);
|
||||
vtxp->replaceWith(notp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -429,6 +535,8 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
if (tryPushBitwiseOpThroughReductions(vtxp)) return;
|
||||
|
||||
if (DfgNot* const lhsNotp = lhsp->cast<DfgNot>()) {
|
||||
// ~A & A is all zeroes
|
||||
if (lhsNotp->srcp() == rhsp) {
|
||||
|
|
@ -446,10 +554,10 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
UASSERT_OBJ(vtxp->width() == vtxp->rhsp()->width(), vtxp, "Mismatched RHS width");
|
||||
|
||||
commutativeBinary(vtxp);
|
||||
associativeBinary(vtxp);
|
||||
|
||||
DfgVertex* const lhsp = vtxp->lhsp();
|
||||
DfgVertex* const rhsp = vtxp->rhsp();
|
||||
|
||||
FileLine* const flp = vtxp->fileline();
|
||||
|
||||
// Bubble pushing
|
||||
|
|
@ -537,6 +645,8 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
if (tryPushBitwiseOpThroughReductions(vtxp)) return;
|
||||
|
||||
if (DfgNot* const lhsNotp = lhsp->cast<DfgNot>()) {
|
||||
// ~A | A is all ones
|
||||
if (lhsNotp->srcp() == rhsp) {
|
||||
|
|
@ -555,15 +665,42 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
UASSERT_OBJ(vtxp->width() == vtxp->rhsp()->width(), vtxp, "Mismatched RHS width");
|
||||
|
||||
commutativeBinary(vtxp);
|
||||
associativeBinary(vtxp);
|
||||
|
||||
DfgVertex* const lhsp = vtxp->lhsp();
|
||||
DfgVertex* const rhsp = vtxp->rhsp();
|
||||
FileLine* const flp = vtxp->fileline();
|
||||
|
||||
if (DfgConst* const lhsConstp = lhsp->cast<DfgConst>()) {
|
||||
if (DfgConcat* const rhsConcatp = rhsp->cast<DfgConcat>()) {
|
||||
if (tryPushBitwiseOpThroughConcat(vtxp, lhsConstp, rhsConcatp)) return;
|
||||
if (DfgConst* const lConstp = lhsp->cast<DfgConst>()) {
|
||||
if (lConstp->isZero()) {
|
||||
APPLYING(REMOVE_XOR_WITH_ZERO) {
|
||||
vtxp->replaceWith(rhsp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (lConstp->isOnes()) {
|
||||
APPLYING(REPLACE_XOR_WITH_ONES) {
|
||||
DfgNot* const replacementp = new DfgNot{m_dfg, flp, vtxp->dtypep()};
|
||||
replacementp->srcp(rhsp);
|
||||
vtxp->replaceWith(replacementp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (DfgConcat* const rConcatp = rhsp->cast<DfgConcat>()) {
|
||||
tryPushBitwiseOpThroughConcat(vtxp, lConstp, rConcatp);
|
||||
return;
|
||||
}
|
||||
if (DfgConst* const rConstp = rhsp->cast<DfgConst>()) {
|
||||
APPLYING(REPLACE_XOR_OF_CONST_AND_CONST) {
|
||||
DfgConst* const replacementp = makeZero(flp, vtxp->width());
|
||||
replacementp->num().opXor(lConstp->num(), rConstp->num());
|
||||
vtxp->replaceWith(replacementp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tryPushBitwiseOpThroughReductions(vtxp)) return;
|
||||
}
|
||||
|
||||
void visit(DfgAdd* vtxp) override {
|
||||
|
|
@ -571,6 +708,7 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
UASSERT_OBJ(vtxp->width() == vtxp->rhsp()->width(), vtxp, "Mismatched RHS width");
|
||||
|
||||
commutativeBinary(vtxp);
|
||||
associativeBinary(vtxp);
|
||||
}
|
||||
|
||||
void visit(DfgSub* vtxp) override {
|
||||
|
|
@ -808,14 +946,32 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
void visit(DfgRedXor* vtxp) override { optimizeReduction(vtxp); }
|
||||
|
||||
void visit(DfgConcat* vtxp) override {
|
||||
UASSERT_OBJ(vtxp->width() == vtxp->lhsp()->width() + vtxp->rhsp()->width(), vtxp,
|
||||
"Incorrect Concat width: " << vtxp->width() << " != " << vtxp->lhsp()->width()
|
||||
<< " + " << vtxp->rhsp()->width());
|
||||
|
||||
DfgVertex* const lhsp = vtxp->lhsp();
|
||||
DfgVertex* const rhsp = vtxp->rhsp();
|
||||
UASSERT_OBJ(vtxp->width() == lhsp->width() + rhsp->width(), vtxp,
|
||||
"Incorrect Concat width: " << vtxp->width() << " != " << lhsp->width() << " + "
|
||||
<< rhsp->width());
|
||||
|
||||
FileLine* const flp = vtxp->fileline();
|
||||
|
||||
// Make concat trees right leaning (for better CSE opportunities)
|
||||
if (DfgConcat* const lConcatp = lhsp->cast<DfgConcat>()) {
|
||||
if (!lConcatp->hasMultipleSinks()) {
|
||||
APPLYING(RIGHT_LEANING_CONCAT) {
|
||||
const uint32_t topWidth = lConcatp->rhsp()->width() + rhsp->width();
|
||||
DfgConcat* const topp = new DfgConcat{m_dfg, flp, dtypeForWidth(topWidth)};
|
||||
DfgConcat* const botp = new DfgConcat{m_dfg, flp, vtxp->dtypep()};
|
||||
topp->rhsp(rhsp);
|
||||
topp->lhsp(lConcatp->rhsp());
|
||||
botp->rhsp(topp);
|
||||
botp->lhsp(lConcatp->lhsp());
|
||||
vtxp->replaceWith(botp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const auto joinConsts
|
||||
= [this](DfgConst* lConstp, DfgConst* rConstp, FileLine* flp) -> DfgConst* {
|
||||
|
|
@ -1057,6 +1213,49 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
if (vtxp->width() > 1) {
|
||||
// 'cond ? a + 1 : a' -> 'a + cond'
|
||||
if (DfgAdd* const thenAddp = thenp->cast<DfgAdd>()) {
|
||||
if (DfgConst* const constp = thenAddp->lhsp()->cast<DfgConst>()) {
|
||||
if (constp->toI32() == 1) {
|
||||
if (thenAddp->rhsp() == elsep) {
|
||||
APPLYING(REPLACE_COND_INC) {
|
||||
DfgConcat* const extp = new DfgConcat{m_dfg, flp, vtxp->dtypep()};
|
||||
extp->rhsp(condp);
|
||||
extp->lhsp(makeZero(flp, vtxp->width() - 1));
|
||||
FileLine* const thenFlp = thenAddp->fileline();
|
||||
DfgAdd* const addp = new DfgAdd{m_dfg, thenFlp, vtxp->dtypep()};
|
||||
addp->lhsp(thenAddp->rhsp());
|
||||
addp->rhsp(extp);
|
||||
vtxp->replaceWith(addp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 'cond ? a - 1 : a' -> 'a - cond'
|
||||
if (DfgSub* const thenSubp = thenp->cast<DfgSub>()) {
|
||||
if (DfgConst* const constp = thenSubp->rhsp()->cast<DfgConst>()) {
|
||||
if (constp->toI32() == 1) {
|
||||
if (thenSubp->lhsp() == elsep) {
|
||||
APPLYING(REPLACE_COND_DEC) {
|
||||
DfgConcat* const extp = new DfgConcat{m_dfg, flp, vtxp->dtypep()};
|
||||
extp->rhsp(condp);
|
||||
extp->lhsp(makeZero(flp, vtxp->width() - 1));
|
||||
FileLine* const thenFlp = thenSubp->fileline();
|
||||
DfgSub* const subp = new DfgSub{m_dfg, thenFlp, vtxp->dtypep()};
|
||||
subp->lhsp(thenSubp->lhsp());
|
||||
subp->rhsp(extp);
|
||||
vtxp->replaceWith(subp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vtxp->width() == 1) {
|
||||
AstNodeDType* const dtypep = vtxp->dtypep();
|
||||
if (thenp->isZero()) { // a ? 0 : b becomes ~a & b
|
||||
|
|
@ -1102,6 +1301,20 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
void visit(DfgArraySel* vtxp) override {
|
||||
if (DfgConst* const idxp = vtxp->bitp()->cast<DfgConst>()) {
|
||||
if (DfgVarArray* const varp = vtxp->fromp()->cast<DfgVarArray>()) {
|
||||
const uint32_t idx = idxp->toU32();
|
||||
if (DfgVertex* const driverp = varp->driverAt(idx)) {
|
||||
APPLYING(INLINE_ARRAYSEL) {
|
||||
vtxp->replaceWith(driverp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void visit(DfgVarPacked* vtxp) override {
|
||||
// Inline variables fully driven by the logic represented by the DFG
|
||||
if (vtxp->hasSinks() && vtxp->isDrivenFullyByDfg()) {
|
||||
|
|
|
|||
|
|
@ -23,68 +23,80 @@
|
|||
|
||||
#define _FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, arg) macro(arg, #arg)
|
||||
|
||||
// Enumeration of each peephole optimization. Must be kept in sorted order (enforced by tests).
|
||||
// clang-format off
|
||||
#define FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION(macro) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, SWAP_CONST_IN_COMMUTATIVE_BINARY) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, SWAP_NOT_IN_COMMUTATIVE_BINARY) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, SWAP_VAR_IN_COMMUTATIVE_BINARY) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, INLINE_ARRAYSEL) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, INLINE_VAR) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PULL_NOTS_THROUGH_COND) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_BITWISE_OP_THROUGH_CONCAT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_BITWISE_THROUGH_REDUCTION) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_COMPARE_OP_THROUGH_CONCAT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_WIDTH_ONE_REDUCTION) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_REDUCTION_THROUGH_COND_WITH_CONST_BRANCH) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_REDUCTION_OF_CONST) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_EXTEND) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_NOT_THROUGH_COND) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_NOT_NOT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_NOT_NEQ) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_NOT_OF_CONST) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_AND_OF_NOT_AND_NOT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_AND_OF_CONST_AND_CONST) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_AND_WITH_ZERO) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_AND_WITH_ONES) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_CONTRADICTORY_AND) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_OR_OF_NOT_AND_NOT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_OR_OF_NOT_AND_NEQ) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_OR_OF_CONCAT_ZERO_LHS_AND_CONCAT_RHS_ZERO) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_OR_OF_CONCAT_LHS_ZERO_AND_CONCAT_ZERO_RHS) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_OR_OF_CONST_AND_CONST) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_OR_WITH_ZERO) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_OR_WITH_ONES) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_TAUTOLOGICAL_OR) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_SUB_ZERO) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_SUB_WITH_NOT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_REDUNDANT_ZEXT_ON_RHS_OF_SHIFT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_EQ_OF_CONST_AND_CONST) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_FULL_WIDTH_SEL) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_SEL_FROM_RHS_OF_CONCAT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_SEL_FROM_LHS_OF_CONCAT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_SEL_THROUGH_CONCAT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_SEL_THROUGH_REPLICATE) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_SEL_THROUGH_NOT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_SEL_FROM_SEL) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_SEL_THROUGH_COND) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_SEL_THROUGH_SHIFTL) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_SEL_FROM_CONST) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_CONCAT_OF_CONSTS) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_NESTED_CONCAT_OF_CONSTS_ON_LHS) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_NESTED_CONCAT_OF_CONSTS_ON_RHS) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_CONCAT_ZERO_AND_SEL_TOP_WITH_SHIFTR) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_CONCAT_SEL_BOTTOM_AND_ZERO_WITH_SHIFTL) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_CONCAT_THROUGH_NOTS) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_NOT_THROUGH_COND) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_REDUCTION_THROUGH_CONCAT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_REDUCTION_THROUGH_COND_WITH_CONST_BRANCH) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_SEL_THROUGH_CONCAT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_SEL_THROUGH_COND) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_SEL_THROUGH_NOT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_SEL_THROUGH_REPLICATE) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_SEL_THROUGH_SHIFTL) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_AND_WITH_ONES) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_CONCAT_OF_ADJOINING_SELS) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_NESTED_CONCAT_OF_ADJOINING_SELS_ON_LHS) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_NESTED_CONCAT_OF_ADJOINING_SELS_ON_RHS) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_COND_WITH_FALSE_CONDITION) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_COND_WITH_TRUE_CONDITION) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, SWAP_COND_WITH_NOT_CONDITION) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, SWAP_COND_WITH_NEQ_CONDITION) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PULL_NOTS_THROUGH_COND) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_COND_WITH_THEN_BRANCH_ZERO) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_COND_WITH_THEN_BRANCH_ONES) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_COND_WITH_ELSE_BRANCH_ZERO) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_FULL_WIDTH_SEL) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_NOT_NOT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_OR_WITH_ZERO) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_REDUNDANT_ZEXT_ON_RHS_OF_SHIFT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_SEL_FROM_LHS_OF_CONCAT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_SEL_FROM_RHS_OF_CONCAT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_SUB_ZERO) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_WIDTH_ONE_REDUCTION) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REMOVE_XOR_WITH_ZERO) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_AND_OF_CONST_AND_CONST) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_AND_OF_NOT_AND_NEQ) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_AND_OF_NOT_AND_NOT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_AND_WITH_ZERO) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_CONCAT_OF_CONSTS) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_CONCAT_SEL_BOTTOM_AND_ZERO_WITH_SHIFTL) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_CONCAT_ZERO_AND_SEL_TOP_WITH_SHIFTR) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_COND_DEC) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_COND_INC) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_COND_WITH_ELSE_BRANCH_ONES) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, INLINE_VAR)
|
||||
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_COND_WITH_ELSE_BRANCH_ZERO) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_COND_WITH_THEN_BRANCH_ONES) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_COND_WITH_THEN_BRANCH_ZERO) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_CONTRADICTORY_AND) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_EQ_OF_CONST_AND_CONST) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_EXTEND) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_NESTED_CONCAT_OF_ADJOINING_SELS_ON_LHS) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_NESTED_CONCAT_OF_ADJOINING_SELS_ON_RHS) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_NESTED_CONCAT_OF_CONSTS_ON_LHS) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_NESTED_CONCAT_OF_CONSTS_ON_RHS) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_NOT_EQ) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_NOT_NEQ) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_NOT_OF_CONST) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_OR_OF_CONCAT_LHS_ZERO_AND_CONCAT_ZERO_RHS) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_OR_OF_CONCAT_ZERO_LHS_AND_CONCAT_RHS_ZERO) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_OR_OF_CONST_AND_CONST) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_OR_OF_NOT_AND_NEQ) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_OR_OF_NOT_AND_NOT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_OR_WITH_ONES) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_REDUCTION_OF_CONST) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_SEL_FROM_CONST) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_SEL_FROM_SEL) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_SUB_WITH_NOT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_TAUTOLOGICAL_OR) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_XOR_OF_CONST_AND_CONST) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_XOR_WITH_ONES) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, RIGHT_LEANING_ASSOC) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, RIGHT_LEANING_CONCAT) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, SWAP_COND_WITH_NEQ_CONDITION) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, SWAP_COND_WITH_NOT_CONDITION) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, SWAP_CONST_IN_COMMUTATIVE_BINARY) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, SWAP_NOT_IN_COMMUTATIVE_BINARY) \
|
||||
_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, SWAP_VAR_IN_COMMUTATIVE_BINARY)
|
||||
// clang-format on
|
||||
|
||||
class VDfgPeepholePattern final {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,12 @@
|
|||
#include <Vref.h>
|
||||
#include <iostream>
|
||||
|
||||
void rngUpdate(uint64_t& x) {
|
||||
x ^= x << 13;
|
||||
x ^= x >> 7;
|
||||
x ^= x << 17;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
// Create contexts
|
||||
VerilatedContext ctx;
|
||||
|
|
@ -21,17 +27,28 @@ int main(int, char**) {
|
|||
Vref ref{&ctx};
|
||||
Vopt opt{&ctx};
|
||||
|
||||
ref.clk = 0;
|
||||
opt.clk = 0;
|
||||
uint64_t rand_a = 0x5aef0c8dd70a4497;
|
||||
uint64_t rand_b = 0xf0c0a8dd75ae4497;
|
||||
|
||||
while (!ctx.gotFinish()) {
|
||||
for (size_t n = 0; n < 200000; ++n) {
|
||||
// Update rngs
|
||||
rngUpdate(rand_a);
|
||||
rngUpdate(rand_b);
|
||||
|
||||
// Assign inputs
|
||||
ref.rand_a = opt.rand_a = rand_a;
|
||||
ref.rand_b = opt.rand_b = rand_b;
|
||||
|
||||
// Evaluate both models
|
||||
ref.eval();
|
||||
opt.eval();
|
||||
|
||||
// Check equivalence
|
||||
#include "checks.h"
|
||||
|
||||
// increment time
|
||||
ctx.timeInc(1);
|
||||
|
||||
ref.clk = !ref.clk;
|
||||
opt.clk = !opt.clk;
|
||||
}
|
||||
|
||||
std::cout << "*-* All Finished *-*\n";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,35 +12,60 @@ scenarios(vlt_all => 1);
|
|||
|
||||
$Self->{sim_time} = 2000000;
|
||||
|
||||
# Read optimizations
|
||||
my @optimizations = ();
|
||||
{
|
||||
my $hdrFile = "../src/V3DfgPeephole.h";
|
||||
my $hdrFh = IO::File->new("<$hdrFile") or error("$! $hdrFile");
|
||||
my $prevOpt = "";
|
||||
my $lineno = 0;
|
||||
while (defined(my $line = $hdrFh->getline)) {
|
||||
$lineno = $lineno + 1;
|
||||
next if $line !~ /^\s*_FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY\(macro, (\w+)\)/;
|
||||
my $opt = $1;
|
||||
error("$hdrFile:$linenno: '$opt; is not in sorted order") if $prevOpt gt $opt;
|
||||
$prevOpt = $opt;
|
||||
push @optimizations, $opt;
|
||||
}
|
||||
error("no optimizations defined in $hdrFile") if scalar @optimizations == 0;
|
||||
}
|
||||
|
||||
# Generate the equivalence checks and declaration boilerplate
|
||||
my $rdFile = "$Self->{top_filename}";
|
||||
my $plistFile = "$Self->{obj_dir}/portlist.vh";
|
||||
my $pdeclFile = "$Self->{obj_dir}/portdecl.vh";
|
||||
my $checkFile = "$Self->{obj_dir}/checks.h";
|
||||
my $rdFh = IO::File->new("<$rdFile") or error("$! $rdFile");
|
||||
my $plistFh = IO::File->new(">$plistFile") or error("$! $plistFile");
|
||||
my $pdeclFh = IO::File->new(">$pdeclFile") or error("$! $pdeclFile");
|
||||
my $checkFh = IO::File->new(">$checkFile") or error("$! $checkFile");
|
||||
while (defined(my $line = $rdFh->getline)) {
|
||||
next if $line !~ /^\s*.*`signal\((\w+),/;
|
||||
my $signal = $1;
|
||||
print $plistFh "$signal,\n";
|
||||
print $pdeclFh "output $signal;\n";
|
||||
print $checkFh "if (ref.$signal != opt.$signal) {\n";
|
||||
print $checkFh " std::cout << \"Mismatched $signal\" << std::endl;\n";
|
||||
print $checkFh " std::cout << \"Ref: 0x\" << std::hex << (ref.$signal + 0) << std::endl;\n";
|
||||
print $checkFh " std::cout << \"Opt: 0x\" << std::hex << (opt.$signal + 0) << std::endl;\n";
|
||||
print $checkFh " std::exit(1);\n";
|
||||
print $checkFh "}\n";
|
||||
}
|
||||
close $rdFile;
|
||||
close $wrFile;
|
||||
|
||||
|
||||
# Compile un-optimized
|
||||
compile(
|
||||
verilator_flags2 => ["--stats", "--build", "-fno-dfg", "+define+REF",
|
||||
verilator_flags2 => ["--stats", "--build", "-fno-dfg", "+incdir+$Self->{obj_dir}",
|
||||
"-Mdir", "$Self->{obj_dir}/obj_ref", "--prefix", "Vref"],
|
||||
verilator_make_gmake => 0,
|
||||
verilator_make_cmake => 0
|
||||
);
|
||||
|
||||
# Generate the equivalence checks
|
||||
my $rdFile = "$Self->{obj_dir}/obj_ref/Vref.h";
|
||||
my $wrFile = "$Self->{obj_dir}/checks.h";
|
||||
my $rfh = IO::File->new("<$rdFile") or error("$! $rdFile");
|
||||
my $wfh = IO::File->new(">$wrFile") or error("$! $wrFile");
|
||||
while (defined(my $line = $rfh->getline)) {
|
||||
next if $line !~ /.*\b(dfg_[A-Z_]*)\b/;
|
||||
my $signal = $1;
|
||||
print $wfh "if (ref.$signal != opt.$signal) {\n";
|
||||
print $wfh " std::cout << \"Mismatched $signal\" << std::endl;\n";
|
||||
print $wfh " std::cout << \"Ref: 0x\" << std::hex << (ref.$signal + 0) << std::endl;\n";
|
||||
print $wfh " std::cout << \"Opt: 0x\" << std::hex << (opt.$signal + 0) << std::endl;\n";
|
||||
print $wfh " std::exit(1);\n";
|
||||
print $wfh "}\n";
|
||||
}
|
||||
close $rdFile;
|
||||
close $wrFile;
|
||||
|
||||
# Compile optimized - also builds executable
|
||||
compile(
|
||||
verilator_flags2 => ["--stats", "--build", "--exe",
|
||||
verilator_flags2 => ["--stats", "--build", "--exe", "+incdir+$Self->{obj_dir}",
|
||||
"-Mdir", "$Self->{obj_dir}/obj_opt", "--prefix", "Vopt",
|
||||
"--dump-dfg", # To fill code coverage
|
||||
"-CFLAGS \"-I .. -I ../obj_ref\"",
|
||||
|
|
@ -63,65 +88,10 @@ sub check {
|
|||
file_grep("$Self->{obj_dir}/obj_opt/Vopt__stats.txt", qr/DFG\s+(pre|post) inline Peephole, ${name}\s+([1-9]\d*)/i);
|
||||
}
|
||||
|
||||
# Check optimizations
|
||||
check("SWAP_CONST_IN_COMMUTATIVE_BINARY");
|
||||
check("SWAP_NOT_IN_COMMUTATIVE_BINARY");
|
||||
check("SWAP_VAR_IN_COMMUTATIVE_BINARY");
|
||||
check("PUSH_BITWISE_OP_THROUGH_CONCAT");
|
||||
check("PUSH_COMPARE_OP_THROUGH_CONCAT");
|
||||
#check("REMOVE_WIDTH_ONE_REDUCTION"); V3Const eats this
|
||||
check("PUSH_REDUCTION_THROUGH_COND_WITH_CONST_BRANCH");
|
||||
check("REPLACE_REDUCTION_OF_CONST");
|
||||
check("REPLACE_EXTEND");
|
||||
check("PUSH_NOT_THROUGH_COND");
|
||||
check("REMOVE_NOT_NOT");
|
||||
check("REPLACE_NOT_NEQ");
|
||||
check("REPLACE_NOT_OF_CONST");
|
||||
check("REPLACE_AND_OF_NOT_AND_NOT");
|
||||
check("REPLACE_AND_OF_CONST_AND_CONST");
|
||||
check("REPLACE_AND_WITH_ZERO");
|
||||
check("REMOVE_AND_WITH_ONES");
|
||||
check("REPLACE_CONTRADICTORY_AND");
|
||||
check("REPLACE_OR_OF_NOT_AND_NOT");
|
||||
check("REPLACE_OR_OF_NOT_AND_NEQ");
|
||||
check("REPLACE_OR_OF_CONCAT_ZERO_LHS_AND_CONCAT_RHS_ZERO");
|
||||
check("REPLACE_OR_OF_CONCAT_LHS_ZERO_AND_CONCAT_ZERO_RHS");
|
||||
check("REPLACE_OR_OF_CONST_AND_CONST");
|
||||
check("REMOVE_OR_WITH_ZERO");
|
||||
check("REPLACE_OR_WITH_ONES");
|
||||
check("REPLACE_TAUTOLOGICAL_OR");
|
||||
check("REMOVE_SUB_ZERO");
|
||||
check("REPLACE_SUB_WITH_NOT");
|
||||
check("REMOVE_REDUNDANT_ZEXT_ON_RHS_OF_SHIFT");
|
||||
check("REPLACE_EQ_OF_CONST_AND_CONST");
|
||||
check("REMOVE_FULL_WIDTH_SEL");
|
||||
check("REMOVE_SEL_FROM_RHS_OF_CONCAT");
|
||||
check("REMOVE_SEL_FROM_LHS_OF_CONCAT");
|
||||
check("PUSH_SEL_THROUGH_CONCAT");
|
||||
check("PUSH_SEL_THROUGH_REPLICATE");
|
||||
check("PUSH_SEL_THROUGH_NOT");
|
||||
check("REPLACE_SEL_FROM_SEL");
|
||||
check("PUSH_SEL_THROUGH_COND");
|
||||
check("PUSH_SEL_THROUGH_SHIFTL");
|
||||
check("REPLACE_SEL_FROM_CONST");
|
||||
check("REPLACE_CONCAT_OF_CONSTS");
|
||||
check("REPLACE_NESTED_CONCAT_OF_CONSTS_ON_LHS");
|
||||
check("REPLACE_NESTED_CONCAT_OF_CONSTS_ON_RHS");
|
||||
check("REPLACE_CONCAT_ZERO_AND_SEL_TOP_WITH_SHIFTR");
|
||||
check("REPLACE_CONCAT_SEL_BOTTOM_AND_ZERO_WITH_SHIFTL");
|
||||
check("PUSH_CONCAT_THROUGH_NOTS");
|
||||
check("REMOVE_CONCAT_OF_ADJOINING_SELS");
|
||||
check("REPLACE_NESTED_CONCAT_OF_ADJOINING_SELS_ON_LHS");
|
||||
check("REPLACE_NESTED_CONCAT_OF_ADJOINING_SELS_ON_RHS");
|
||||
check("REMOVE_COND_WITH_FALSE_CONDITION");
|
||||
check("REMOVE_COND_WITH_TRUE_CONDITION");
|
||||
check("SWAP_COND_WITH_NOT_CONDITION");
|
||||
check("SWAP_COND_WITH_NEQ_CONDITION");
|
||||
check("PULL_NOTS_THROUGH_COND");
|
||||
check("REPLACE_COND_WITH_THEN_BRANCH_ZERO");
|
||||
check("REPLACE_COND_WITH_THEN_BRANCH_ONES");
|
||||
check("REPLACE_COND_WITH_ELSE_BRANCH_ZERO");
|
||||
check("REPLACE_COND_WITH_ELSE_BRANCH_ONES");
|
||||
# Check all optimizations defined in
|
||||
foreach my $opt (@optimizations) {
|
||||
check($opt);
|
||||
}
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -4,216 +4,116 @@
|
|||
// any use, without warranty, 2022 by Geza Lore.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`define STRINGIFY(x) `"x`"
|
||||
`define signal(name, expr) wire [$bits(expr)-1:0] ``name = expr;
|
||||
|
||||
`define signal(name, expr) wire [$bits(expr)-1:0] dfg_``name = expr;
|
||||
module t (
|
||||
`include "portlist.vh" // Boilerplate generated by t_dfg_peephole.pl
|
||||
rand_a, rand_b
|
||||
);
|
||||
|
||||
`include "portdecl.vh" // Boilerplate generated by t_dfg_peephole.pl
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Outputs
|
||||
dfg_SWAP_CONST_IN_COMMUTATIVE_BINARY,
|
||||
dfg_SWAP_NOT_IN_COMMUTATIVE_BINARY,
|
||||
dfg_SWAP_VAR_IN_COMMUTATIVE_BINARY,
|
||||
dfg_PUSH_BITWISE_OP_THROUGH_CONCAT,
|
||||
dfg_PUSH_BITWISE_OP_THROUGH_CONCAT_2,
|
||||
dfg_PUSH_COMPARE_OP_THROUGH_CONCAT, dfg_REMOVE_WIDTH_ONE_REDUCTION,
|
||||
dfg_PUSH_REDUCTION_THROUGH_COND_WITH_CONST_BRANCH,
|
||||
dfg_REPLACE_REDUCTION_OF_CONST_AND,
|
||||
dfg_REPLACE_REDUCTION_OF_CONST_OR,
|
||||
dfg_REPLACE_REDUCTION_OF_CONST_XOR, dfg_REPLACE_EXTEND,
|
||||
dfg_PUSH_NOT_THROUGH_COND, dfg_REMOVE_NOT_NOT, dfg_REPLACE_NOT_NEQ,
|
||||
dfg_REPLACE_NOT_OF_CONST, dfg_REPLACE_AND_OF_NOT_AND_NOT,
|
||||
dfg_REPLACE_AND_OF_CONST_AND_CONST, dfg_REPLACE_AND_WITH_ZERO,
|
||||
dfg_REMOVE_AND_WITH_ONES, dfg_REPLACE_CONTRADICTORY_AND,
|
||||
dfg_REPLACE_OR_OF_NOT_AND_NOT, dfg_REPLACE_OR_OF_NOT_AND_NEQ,
|
||||
dfg_REPLACE_OR_OF_CONCAT_ZERO_LHS_AND_CONCAT_RHS_ZERO,
|
||||
dfg_REPLACE_OR_OF_CONCAT_LHS_ZERO_AND_CONCAT_ZERO_RHS,
|
||||
dfg_REPLACE_OR_OF_CONST_AND_CONST, dfg_REMOVE_OR_WITH_ZERO,
|
||||
dfg_REPLACE_OR_WITH_ONES, dfg_REPLACE_TAUTOLOGICAL_OR,
|
||||
dfg_REMOVE_SUB_ZERO, dfg_REPLACE_SUB_WITH_NOT,
|
||||
dfg_REMOVE_REDUNDANT_ZEXT_ON_RHS_OF_SHIFT,
|
||||
dfg_REPLACE_EQ_OF_CONST_AND_CONST, dfg_REMOVE_FULL_WIDTH_SEL,
|
||||
dfg_REMOVE_SEL_FROM_RHS_OF_CONCAT,
|
||||
dfg_REMOVE_SEL_FROM_LHS_OF_CONCAT, dfg_PUSH_SEL_THROUGH_CONCAT,
|
||||
dfg_PUSH_SEL_THROUGH_REPLICATE, dfg_REPLACE_SEL_FROM_CONST,
|
||||
dfg_REPLACE_CONCAT_OF_CONSTS,
|
||||
dfg_REPLACE_NESTED_CONCAT_OF_CONSTS_ON_RHS,
|
||||
dfg_REPLACE_NESTED_CONCAT_OF_CONSTS_ON_LHS,
|
||||
dfg_REPLACE_CONCAT_ZERO_AND_SEL_TOP_WITH_SHIFTR,
|
||||
dfg_REPLACE_CONCAT_SEL_BOTTOM_AND_ZERO_WITH_SHIFTL,
|
||||
dfg_PUSH_CONCAT_THROUGH_NOTS, dfg_REMOVE_CONCAT_OF_ADJOINING_SELS,
|
||||
dfg_REPLACE_NESTED_CONCAT_OF_ADJOINING_SELS_ON_LHS,
|
||||
dfg_REPLACE_NESTED_CONCAT_OF_ADJOINING_SELS_ON_RHS,
|
||||
dfg_REMOVE_COND_WITH_FALSE_CONDITION,
|
||||
dfg_REMOVE_COND_WITH_TRUE_CONDITION,
|
||||
dfg_SWAP_COND_WITH_NOT_CONDITION, dfg_SWAP_COND_WITH_NEQ_CONDITION,
|
||||
dfg_PULL_NOTS_THROUGH_COND, dfg_REPLACE_COND_WITH_THEN_BRANCH_ZERO,
|
||||
dfg_REPLACE_COND_WITH_THEN_BRANCH_ONES,
|
||||
dfg_REPLACE_COND_WITH_ELSE_BRANCH_ZERO,
|
||||
dfg_REPLACE_COND_WITH_ELSE_BRANCH_ONES, dfg_PUSH_SEL_THROUGH_COND,
|
||||
dfg_PUSH_SEL_THROUGH_SHIFTL, dfg_REPLACE_SEL_FROM_SEL,
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
input rand_a;
|
||||
input rand_b;
|
||||
wire [63:0] rand_a;
|
||||
wire [63:0] rand_b;
|
||||
|
||||
// Sadly verilog-mode cannot look in macros so need to define these
|
||||
// separately
|
||||
output dfg_SWAP_CONST_IN_COMMUTATIVE_BINARY;
|
||||
output dfg_SWAP_NOT_IN_COMMUTATIVE_BINARY;
|
||||
output dfg_SWAP_VAR_IN_COMMUTATIVE_BINARY;
|
||||
output dfg_PUSH_BITWISE_OP_THROUGH_CONCAT;
|
||||
output dfg_PUSH_BITWISE_OP_THROUGH_CONCAT_2;
|
||||
output dfg_PUSH_COMPARE_OP_THROUGH_CONCAT;
|
||||
output dfg_REMOVE_WIDTH_ONE_REDUCTION;
|
||||
output dfg_PUSH_REDUCTION_THROUGH_COND_WITH_CONST_BRANCH;
|
||||
output dfg_REPLACE_REDUCTION_OF_CONST_AND;
|
||||
output dfg_REPLACE_REDUCTION_OF_CONST_OR;
|
||||
output dfg_REPLACE_REDUCTION_OF_CONST_XOR;
|
||||
output dfg_REPLACE_EXTEND;
|
||||
output dfg_PUSH_NOT_THROUGH_COND;
|
||||
output dfg_REMOVE_NOT_NOT;
|
||||
output dfg_REPLACE_NOT_NEQ;
|
||||
output dfg_REPLACE_NOT_OF_CONST;
|
||||
output dfg_REPLACE_AND_OF_NOT_AND_NOT;
|
||||
output dfg_REPLACE_AND_OF_CONST_AND_CONST;
|
||||
output dfg_REPLACE_AND_WITH_ZERO;
|
||||
output dfg_REMOVE_AND_WITH_ONES;
|
||||
output dfg_REPLACE_CONTRADICTORY_AND;
|
||||
output dfg_REPLACE_OR_OF_NOT_AND_NOT;
|
||||
output dfg_REPLACE_OR_OF_NOT_AND_NEQ;
|
||||
output dfg_REPLACE_OR_OF_CONCAT_ZERO_LHS_AND_CONCAT_RHS_ZERO;
|
||||
output dfg_REPLACE_OR_OF_CONCAT_LHS_ZERO_AND_CONCAT_ZERO_RHS;
|
||||
output dfg_REPLACE_OR_OF_CONST_AND_CONST;
|
||||
output dfg_REMOVE_OR_WITH_ZERO;
|
||||
output dfg_REPLACE_OR_WITH_ONES;
|
||||
output dfg_REPLACE_TAUTOLOGICAL_OR;
|
||||
output dfg_REMOVE_SUB_ZERO;
|
||||
output dfg_REPLACE_SUB_WITH_NOT;
|
||||
output dfg_REMOVE_REDUNDANT_ZEXT_ON_RHS_OF_SHIFT;
|
||||
output dfg_REPLACE_EQ_OF_CONST_AND_CONST;
|
||||
output dfg_REMOVE_FULL_WIDTH_SEL;
|
||||
output dfg_REMOVE_SEL_FROM_RHS_OF_CONCAT;
|
||||
output dfg_REMOVE_SEL_FROM_LHS_OF_CONCAT;
|
||||
output dfg_PUSH_SEL_THROUGH_CONCAT;
|
||||
output dfg_PUSH_SEL_THROUGH_REPLICATE;
|
||||
output dfg_REPLACE_SEL_FROM_CONST;
|
||||
output dfg_REPLACE_CONCAT_OF_CONSTS;
|
||||
output dfg_REPLACE_NESTED_CONCAT_OF_CONSTS_ON_RHS;
|
||||
output dfg_REPLACE_NESTED_CONCAT_OF_CONSTS_ON_LHS;
|
||||
output dfg_REPLACE_CONCAT_ZERO_AND_SEL_TOP_WITH_SHIFTR;
|
||||
output dfg_REPLACE_CONCAT_SEL_BOTTOM_AND_ZERO_WITH_SHIFTL;
|
||||
output dfg_PUSH_CONCAT_THROUGH_NOTS;
|
||||
output dfg_REMOVE_CONCAT_OF_ADJOINING_SELS;
|
||||
output dfg_REPLACE_NESTED_CONCAT_OF_ADJOINING_SELS_ON_LHS;
|
||||
output dfg_REPLACE_NESTED_CONCAT_OF_ADJOINING_SELS_ON_RHS;
|
||||
output dfg_REMOVE_COND_WITH_FALSE_CONDITION;
|
||||
output dfg_REMOVE_COND_WITH_TRUE_CONDITION;
|
||||
output dfg_SWAP_COND_WITH_NOT_CONDITION;
|
||||
output dfg_SWAP_COND_WITH_NEQ_CONDITION;
|
||||
output dfg_PULL_NOTS_THROUGH_COND;
|
||||
output dfg_REPLACE_COND_WITH_THEN_BRANCH_ZERO;
|
||||
output dfg_REPLACE_COND_WITH_THEN_BRANCH_ONES;
|
||||
output dfg_REPLACE_COND_WITH_ELSE_BRANCH_ZERO;
|
||||
output dfg_REPLACE_COND_WITH_ELSE_BRANCH_ONES;
|
||||
output dfg_PUSH_SEL_THROUGH_COND;
|
||||
output dfg_PUSH_SEL_THROUGH_SHIFTL;
|
||||
output dfg_REPLACE_SEL_FROM_SEL;
|
||||
wire logic randbit_a = rand_a[0];
|
||||
wire logic [127:0] rand_ba = {rand_b, rand_a};
|
||||
wire logic [127:0] rand_aa = {2{rand_a}};
|
||||
wire logic [63:0] const_a;
|
||||
wire logic [63:0] const_b;
|
||||
wire logic [63:0] array [3:0];
|
||||
assign array[0] = (rand_a << 32) | (rand_a >> 32);
|
||||
assign array[1] = (rand_a << 16) | (rand_a >> 48);
|
||||
|
||||
integer cyc = 0;
|
||||
|
||||
reg [63:0] crc = 64'h5aef0c8d_d70a4497;
|
||||
reg [63:0] rcr;
|
||||
wire logic [127:0] rcr_crc = {rcr, crc};
|
||||
wire logic [127:0] crc_rep = {2{crc}};
|
||||
wire logic [63:0] const_a;
|
||||
wire logic [63:0] const_b;
|
||||
|
||||
always @ (posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
crc <= {crc[62:0], crc[63] ^ crc[2] ^ crc[0]};
|
||||
rcr <= ~crc;
|
||||
|
||||
`ifdef REF
|
||||
if (cyc >= 100_000) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
`endif
|
||||
end
|
||||
|
||||
// 64'0 but don't tell V3Const
|
||||
// 64 bit all 0 but don't tell V3Const
|
||||
`define ZERO (const_a & ~const_a)
|
||||
// 64'1 but don't tell V3Const
|
||||
// 64 bit all 1 but don't tell V3Const
|
||||
`define ONES (const_a | ~const_a)
|
||||
// x, but in a way only DFG understands
|
||||
`define DFG(x) ((|`ONES) ? (x) : (~x))
|
||||
|
||||
`signal(SWAP_CONST_IN_COMMUTATIVE_BINARY, crc + const_a);
|
||||
`signal(SWAP_NOT_IN_COMMUTATIVE_BINARY, crc + ~crc);
|
||||
`signal(SWAP_VAR_IN_COMMUTATIVE_BINARY, rcr + crc);
|
||||
`signal(PUSH_BITWISE_OP_THROUGH_CONCAT, 32'h12345678 ^ {8'h0, crc[23:0]});
|
||||
`signal(PUSH_BITWISE_OP_THROUGH_CONCAT_2, 32'h12345678 ^ {rcr[7:0], crc[23:0]});
|
||||
`signal(PUSH_COMPARE_OP_THROUGH_CONCAT, 4'b1011 == {2'b10, crc[1:0]});
|
||||
`signal(REMOVE_WIDTH_ONE_REDUCTION, &`DFG(crc[0]));
|
||||
`signal(PUSH_REDUCTION_THROUGH_COND_WITH_CONST_BRANCH, |(crc[32] ? crc[3:0] : 4'h0));
|
||||
`signal(SWAP_CONST_IN_COMMUTATIVE_BINARY, rand_a + const_a);
|
||||
`signal(SWAP_NOT_IN_COMMUTATIVE_BINARY, rand_a + ~rand_a);
|
||||
`signal(SWAP_VAR_IN_COMMUTATIVE_BINARY, rand_b + rand_a);
|
||||
`signal(PUSH_BITWISE_OP_THROUGH_CONCAT, 32'h12345678 ^ {8'h0, rand_a[23:0]});
|
||||
`signal(PUSH_BITWISE_OP_THROUGH_CONCAT_2, 32'h12345678 ^ {rand_b[7:0], rand_a[23:0]});
|
||||
`signal(PUSH_COMPARE_OP_THROUGH_CONCAT, 4'b1011 == {2'b10, rand_a[1:0]});
|
||||
`signal(REMOVE_WIDTH_ONE_REDUCTION, &`DFG(rand_a[0]));
|
||||
`signal(PUSH_REDUCTION_THROUGH_COND_WITH_CONST_BRANCH, |(rand_a[32] ? rand_a[3:0] : 4'h0));
|
||||
`signal(REPLACE_REDUCTION_OF_CONST_AND, &const_a);
|
||||
`signal(REPLACE_REDUCTION_OF_CONST_OR, |const_a);
|
||||
`signal(REPLACE_REDUCTION_OF_CONST_XOR, ^const_a);
|
||||
`signal(REPLACE_EXTEND, 4'(crc[0]));
|
||||
`signal(PUSH_NOT_THROUGH_COND, ~(crc[0] ? crc[4:0] : 5'hb));
|
||||
`signal(REMOVE_NOT_NOT, ~`DFG(~`DFG(crc)));
|
||||
`signal(REPLACE_NOT_NEQ, ~`DFG(crc != rcr));
|
||||
`signal(REPLACE_EXTEND, 4'(rand_a[0]));
|
||||
`signal(PUSH_NOT_THROUGH_COND, ~(rand_a[0] ? rand_a[4:0] : 5'hb));
|
||||
`signal(REMOVE_NOT_NOT, ~`DFG(~`DFG(rand_a)));
|
||||
`signal(REPLACE_NOT_NEQ, ~`DFG(rand_a != rand_b));
|
||||
`signal(REPLACE_NOT_EQ, ~`DFG(rand_a == rand_b));
|
||||
`signal(REPLACE_NOT_OF_CONST, ~4'd0);
|
||||
`signal(REPLACE_AND_OF_NOT_AND_NOT, ~crc[0] & ~rcr[0]);
|
||||
`signal(REPLACE_AND_OF_NOT_AND_NOT, ~rand_a[0] & ~rand_b[0]);
|
||||
`signal(REPLACE_AND_OF_NOT_AND_NEQ, ~rand_a[0] & (rand_b != 64'd2));
|
||||
`signal(REPLACE_AND_OF_CONST_AND_CONST, const_a & const_b);
|
||||
`signal(REPLACE_AND_WITH_ZERO, `ZERO & crc);
|
||||
`signal(REMOVE_AND_WITH_ONES, `ONES & crc);
|
||||
`signal(REPLACE_CONTRADICTORY_AND, crc & ~crc);
|
||||
`signal(REPLACE_OR_OF_NOT_AND_NOT, ~crc[0] | ~rcr[0]);
|
||||
`signal(REPLACE_OR_OF_NOT_AND_NEQ, ~crc[0] | (rcr != 64'd2));
|
||||
`signal(REPLACE_OR_OF_CONCAT_ZERO_LHS_AND_CONCAT_RHS_ZERO, {2'd0, crc[1:0]} | {rcr[1:0], 2'd0});
|
||||
`signal(REPLACE_OR_OF_CONCAT_LHS_ZERO_AND_CONCAT_ZERO_RHS, {crc[1:0], 2'd0} | {2'd0, rcr[1:0]});
|
||||
`signal(REPLACE_AND_WITH_ZERO, `ZERO & rand_a);
|
||||
`signal(REMOVE_AND_WITH_ONES, `ONES & rand_a);
|
||||
`signal(REPLACE_CONTRADICTORY_AND, rand_a & ~rand_a);
|
||||
`signal(REPLACE_OR_OF_NOT_AND_NOT, ~rand_a[0] | ~rand_b[0]);
|
||||
`signal(REPLACE_OR_OF_NOT_AND_NEQ, ~rand_a[0] | (rand_b != 64'd2));
|
||||
`signal(REPLACE_OR_OF_CONCAT_ZERO_LHS_AND_CONCAT_RHS_ZERO, {2'd0, rand_a[1:0]} | {rand_b[1:0], 2'd0});
|
||||
`signal(REPLACE_OR_OF_CONCAT_LHS_ZERO_AND_CONCAT_ZERO_RHS, {rand_a[1:0], 2'd0} | {2'd0, rand_b[1:0]});
|
||||
`signal(REPLACE_OR_OF_CONST_AND_CONST, const_a | const_b);
|
||||
`signal(REMOVE_OR_WITH_ZERO, `ZERO | crc);
|
||||
`signal(REPLACE_OR_WITH_ONES, `ONES | crc);
|
||||
`signal(REPLACE_TAUTOLOGICAL_OR, crc | ~crc);
|
||||
`signal(REMOVE_SUB_ZERO, crc - `ZERO);
|
||||
`signal(REPLACE_SUB_WITH_NOT, crc[0] - 1'b1);
|
||||
`signal(REMOVE_REDUNDANT_ZEXT_ON_RHS_OF_SHIFT, crc << {2'b0, crc[2:0]});
|
||||
`signal(REMOVE_OR_WITH_ZERO, `ZERO | rand_a);
|
||||
`signal(REPLACE_OR_WITH_ONES, `ONES | rand_a);
|
||||
`signal(REPLACE_TAUTOLOGICAL_OR, rand_a | ~rand_a);
|
||||
`signal(REMOVE_SUB_ZERO, rand_a - `ZERO);
|
||||
`signal(REPLACE_SUB_WITH_NOT, rand_a[0] - 1'b1);
|
||||
`signal(REMOVE_REDUNDANT_ZEXT_ON_RHS_OF_SHIFT, rand_a << {2'b0, rand_a[2:0]});
|
||||
`signal(REPLACE_EQ_OF_CONST_AND_CONST, 4'd0 == 4'd1);
|
||||
`signal(REMOVE_FULL_WIDTH_SEL, crc[63:0]);
|
||||
`signal(REMOVE_SEL_FROM_RHS_OF_CONCAT, rcr_crc[63:0]);
|
||||
`signal(REMOVE_SEL_FROM_LHS_OF_CONCAT, rcr_crc[127:64]);
|
||||
`signal(PUSH_SEL_THROUGH_CONCAT, rcr_crc[120:0]);
|
||||
`signal(PUSH_SEL_THROUGH_REPLICATE, crc_rep[0]);
|
||||
`signal(REMOVE_FULL_WIDTH_SEL, rand_a[63:0]);
|
||||
`signal(REMOVE_SEL_FROM_RHS_OF_CONCAT, rand_ba[63:0]);
|
||||
`signal(REMOVE_SEL_FROM_LHS_OF_CONCAT, rand_ba[127:64]);
|
||||
`signal(PUSH_SEL_THROUGH_CONCAT, rand_ba[120:0]);
|
||||
`signal(PUSH_SEL_THROUGH_REPLICATE, rand_aa[0]);
|
||||
`signal(REPLACE_SEL_FROM_CONST, const_a[2]);
|
||||
`signal(REPLACE_CONCAT_OF_CONSTS, {const_a, const_b});
|
||||
`signal(REPLACE_NESTED_CONCAT_OF_CONSTS_ON_RHS, {`DFG({crc, const_a}), const_b});
|
||||
`signal(REPLACE_NESTED_CONCAT_OF_CONSTS_ON_LHS, {const_a, `DFG({const_b, crc})});
|
||||
`signal(REPLACE_CONCAT_ZERO_AND_SEL_TOP_WITH_SHIFTR, {62'd0, crc[63:62]});
|
||||
`signal(REPLACE_CONCAT_SEL_BOTTOM_AND_ZERO_WITH_SHIFTL, {crc[1:0], 62'd0});
|
||||
`signal(PUSH_CONCAT_THROUGH_NOTS, {~crc, ~rcr} );
|
||||
`signal(REMOVE_CONCAT_OF_ADJOINING_SELS, {`DFG(crc[10:3]), `DFG(crc[2:1])});
|
||||
`signal(REPLACE_NESTED_CONCAT_OF_ADJOINING_SELS_ON_LHS, {crc[10:3], {crc[2:1], rcr}});
|
||||
`signal(REPLACE_NESTED_CONCAT_OF_ADJOINING_SELS_ON_RHS, {`DFG({rcr, crc[10:3]}), crc[2:1]});
|
||||
`signal(REMOVE_COND_WITH_FALSE_CONDITION, &`ZERO ? crc : rcr);
|
||||
`signal(REMOVE_COND_WITH_TRUE_CONDITION, |`ONES ? crc : rcr);
|
||||
`signal(SWAP_COND_WITH_NOT_CONDITION, (~crc[0] & |`ONES) ? crc : rcr);
|
||||
`signal(SWAP_COND_WITH_NEQ_CONDITION, rcr != crc ? crc : rcr);
|
||||
`signal(PULL_NOTS_THROUGH_COND, crc[0] ? ~crc[4:0] : ~rcr[4:0]);
|
||||
`signal(REPLACE_COND_WITH_THEN_BRANCH_ZERO, crc[0] ? |`ZERO : crc[1]);
|
||||
`signal(REPLACE_COND_WITH_THEN_BRANCH_ONES, crc[0] ? |`ONES : crc[1]);
|
||||
`signal(REPLACE_COND_WITH_ELSE_BRANCH_ZERO, crc[0] ? crc[1] : |`ZERO);
|
||||
`signal(REPLACE_COND_WITH_ELSE_BRANCH_ONES, crc[0] ? crc[1] : |`ONES);
|
||||
|
||||
assign const_a = (crc | ~crc) & 64'h0123456789abcdef;
|
||||
assign const_b = ~(crc & ~crc) & 64'h98badefc10325647;
|
||||
`signal(REPLACE_NESTED_CONCAT_OF_CONSTS_ON_RHS, {`DFG({rand_a, const_a}), const_b});
|
||||
`signal(REPLACE_NESTED_CONCAT_OF_CONSTS_ON_LHS, {const_a, `DFG({const_b, rand_a})});
|
||||
`signal(REPLACE_CONCAT_ZERO_AND_SEL_TOP_WITH_SHIFTR, {62'd0, rand_a[63:62]});
|
||||
`signal(REPLACE_CONCAT_SEL_BOTTOM_AND_ZERO_WITH_SHIFTL, {rand_a[1:0], 62'd0});
|
||||
`signal(PUSH_CONCAT_THROUGH_NOTS, {~rand_a, ~rand_b} );
|
||||
`signal(REMOVE_CONCAT_OF_ADJOINING_SELS, {`DFG(rand_a[10:3]), `DFG(rand_a[2:1])});
|
||||
`signal(REPLACE_NESTED_CONCAT_OF_ADJOINING_SELS_ON_LHS, {rand_a[10:3], {rand_a[2:1], rand_b}});
|
||||
`signal(REPLACE_NESTED_CONCAT_OF_ADJOINING_SELS_ON_RHS, {`DFG({rand_b, rand_a[10:3]}), rand_a[2:1]});
|
||||
`signal(REMOVE_COND_WITH_FALSE_CONDITION, &`ZERO ? rand_a : rand_b);
|
||||
`signal(REMOVE_COND_WITH_TRUE_CONDITION, |`ONES ? rand_a : rand_b);
|
||||
`signal(SWAP_COND_WITH_NOT_CONDITION, (~rand_a[0] & |`ONES) ? rand_a : rand_b);
|
||||
`signal(SWAP_COND_WITH_NEQ_CONDITION, rand_b != rand_a ? rand_a : rand_b);
|
||||
`signal(PULL_NOTS_THROUGH_COND, rand_a[0] ? ~rand_a[4:0] : ~rand_b[4:0]);
|
||||
`signal(REPLACE_COND_WITH_THEN_BRANCH_ZERO, rand_a[0] ? |`ZERO : rand_a[1]);
|
||||
`signal(REPLACE_COND_WITH_THEN_BRANCH_ONES, rand_a[0] ? |`ONES : rand_a[1]);
|
||||
`signal(REPLACE_COND_WITH_ELSE_BRANCH_ZERO, rand_a[0] ? rand_a[1] : |`ZERO);
|
||||
`signal(REPLACE_COND_WITH_ELSE_BRANCH_ONES, rand_a[0] ? rand_a[1] : |`ONES);
|
||||
`signal(INLINE_ARRAYSEL, array[0]);
|
||||
`signal(PUSH_BITWISE_THROUGH_REDUCTION_AND, (&rand_a) & (&rand_b));
|
||||
`signal(PUSH_BITWISE_THROUGH_REDUCTION_OR, (|rand_a) | (|rand_b));
|
||||
`signal(PUSH_BITWISE_THROUGH_REDUCTION_XOR, (^rand_a) ^ (^rand_b));
|
||||
`signal(PUSH_REDUCTION_THROUGH_CONCAT_AND, &`DFG({rand_a, rand_b}));
|
||||
`signal(PUSH_REDUCTION_THROUGH_CONCAT_OR, |`DFG({rand_a, rand_b}));
|
||||
`signal(PUSH_REDUCTION_THROUGH_CONCAT_XOR, ^`DFG({rand_a, rand_b}));
|
||||
`signal(REMOVE_WIDTH_ONE_REDUCTION_AND, &`DFG({randbit_a, rand_b}));
|
||||
`signal(REMOVE_WIDTH_ONE_REDUCTION_OR, |`DFG({randbit_a, rand_b}));
|
||||
`signal(REMOVE_WIDTH_ONE_REDUCTION_XOR, ^`DFG({randbit_a, rand_b}));
|
||||
`signal(REMOVE_XOR_WITH_ZERO, `ZERO ^ rand_a);
|
||||
`signal(REMOVE_XOR_WITH_ONES, `ONES ^ rand_a);
|
||||
`signal(REPLACE_COND_DEC, randbit_a ? rand_b - 64'b1 : rand_b);
|
||||
`signal(REPLACE_COND_INC, randbit_a ? rand_b + 64'b1 : rand_b);
|
||||
`signal(RIGHT_LEANING_ASSOC, (((rand_a + rand_b) + rand_a) + rand_b));
|
||||
`signal(RIGHT_LEANING_CONCET, {{{rand_a, rand_b}, rand_a}, rand_b});
|
||||
|
||||
// Some selects need extra temporaries
|
||||
wire [63:0] sel_from_cond = crc[0] ? crc : const_a;
|
||||
wire [63:0] sel_from_shiftl = crc << 10;
|
||||
wire [31:0] sel_from_sel = crc[10+:32];
|
||||
wire [63:0] sel_from_cond = rand_a[0] ? rand_a : const_a;
|
||||
wire [63:0] sel_from_shiftl = rand_a << 10;
|
||||
wire [31:0] sel_from_sel = rand_a[10+:32];
|
||||
|
||||
`signal(PUSH_SEL_THROUGH_COND, sel_from_cond[2]);
|
||||
`signal(PUSH_SEL_THROUGH_SHIFTL, sel_from_shiftl[20:0]);
|
||||
|
|
@ -221,7 +121,11 @@ module t (/*AUTOARG*/
|
|||
|
||||
// Sel from not requires the operand to have a sinle sink, so can't use
|
||||
// the chekc due to the raw expression referencing the operand
|
||||
wire [63:0] sel_from_not_tmp = ~(crc >> rcr[2:0] << crc[3:0]);
|
||||
wire [63:0] sel_from_not_tmp = ~(rand_a >> rand_b[2:0] << rand_a[3:0]);
|
||||
wire sel_from_not = sel_from_not_tmp[2];
|
||||
always @(posedge clk) if ($c(0)) $display(sel_from_not); // Do not remove signal
|
||||
always @(posedge randbit_a) if ($c(0)) $display(sel_from_not); // Do not remove signal
|
||||
|
||||
// Assigned at the end to avoid inlining by other passes
|
||||
assign const_a = (rand_a | ~rand_a) & 64'h0123456789abcdef;
|
||||
assign const_b = ~(rand_a & ~rand_a) & 64'h98badefc10325647;
|
||||
endmodule
|
||||
|
|
|
|||
Loading…
Reference in New Issue