Internals: Do not astgen useless Dfg vertex subtypes

This commit is contained in:
Geza Lore 2025-08-15 19:23:16 +01:00
parent ece4469869
commit d273e2cbd0
9 changed files with 116 additions and 158 deletions

View File

@ -50,38 +50,11 @@ DfgArraySel* makeVertex<DfgArraySel, AstArraySel>(const AstArraySel* nodep, DfgG
// Some earlier passes create malformed ArraySels, just bail on those...
// See t_bitsel_wire_array_bad
if (VN_IS(nodep->fromp(), Const)) return nullptr;
AstUnpackArrayDType* const fromDtypep
= VN_CAST(nodep->fromp()->dtypep()->skipRefp(), UnpackArrayDType);
if (!fromDtypep) return nullptr;
if (!VN_IS(nodep->fromp()->dtypep()->skipRefp(), UnpackArrayDType)) return nullptr;
return new DfgArraySel{dfg, nodep->fileline(), DfgVertex::dtypeFor(nodep)};
}
//======================================================================
// Currently unhandled nodes
// LCOV_EXCL_START
// AstCCast changes width, but should not exists where DFG optimization is currently invoked
template <>
DfgCCast* makeVertex<DfgCCast, AstCCast>(const AstCCast*, DfgGraph&) {
return nullptr;
}
// Unhandled in DfgToAst, but also operates on strings which we don't optimize anyway
template <>
DfgAtoN* makeVertex<DfgAtoN, AstAtoN>(const AstAtoN*, DfgGraph&) {
return nullptr;
}
// Unhandled in DfgToAst, but also operates on strings which we don't optimize anyway
template <>
DfgCompareNN* makeVertex<DfgCompareNN, AstCompareNN>(const AstCompareNN*, DfgGraph&) {
return nullptr;
}
// Unhandled in DfgToAst, but also operates on unpacked arrays which we don't optimize anyway
template <>
DfgSliceSel* makeVertex<DfgSliceSel, AstSliceSel>(const AstSliceSel*, DfgGraph&) {
return nullptr;
}
// LCOV_EXCL_STOP
} // namespace
} //namespace
// Visitor that can convert combinational Ast logic constructs/assignments to Dfg
template <bool T_Scoped>

View File

@ -52,15 +52,6 @@ T_Node* makeNode(const T_Vertex* vtxp, Ops... ops) {
//======================================================================
// Vertices needing special conversion
template <>
AstCountOnes* makeNode<AstCountOnes, DfgCountOnes, AstNodeExpr*>( //
const DfgCountOnes* vtxp, AstNodeExpr* op1) {
AstCountOnes* const nodep = new AstCountOnes{vtxp->fileline(), op1};
// Set dtype same as V3Width
nodep->dtypeSetLogicSized(32, VSigning::UNSIGNED);
return nodep;
}
template <>
AstExtend* makeNode<AstExtend, DfgExtend, AstNodeExpr*>( //
const DfgExtend* vtxp, AstNodeExpr* op1) {
@ -91,38 +82,6 @@ AstShiftRS* makeNode<AstShiftRS, DfgShiftRS, AstNodeExpr*, AstNodeExpr*>( //
return new AstShiftRS{vtxp->fileline(), op1, op2, static_cast<int>(vtxp->width())};
}
//======================================================================
// Currently unhandled nodes - see corresponding AstToDfg functions
// LCOV_EXCL_START
template <>
AstCCast* makeNode<AstCCast, DfgCCast, AstNodeExpr*>(const DfgCCast* vtxp, AstNodeExpr*) {
vtxp->v3fatalSrc("not implemented");
VL_UNREACHABLE;
return nullptr; // LCOV_EXCL_LINE
}
template <>
AstAtoN* makeNode<AstAtoN, DfgAtoN, AstNodeExpr*>(const DfgAtoN* vtxp, AstNodeExpr*) {
vtxp->v3fatalSrc("not implemented");
VL_UNREACHABLE;
return nullptr; // LCOV_EXCL_LINE
}
template <>
AstCompareNN*
makeNode<AstCompareNN, DfgCompareNN, AstNodeExpr*, AstNodeExpr*>(const DfgCompareNN* vtxp,
AstNodeExpr*, AstNodeExpr*) {
vtxp->v3fatalSrc("not implemented");
VL_UNREACHABLE;
return nullptr; // LCOV_EXCL_LINE
}
template <>
AstSliceSel* makeNode<AstSliceSel, DfgSliceSel, AstNodeExpr*, AstNodeExpr*, AstNodeExpr*>(
const DfgSliceSel* vtxp, AstNodeExpr*, AstNodeExpr*, AstNodeExpr*) {
vtxp->v3fatalSrc("not implemented");
VL_UNREACHABLE;
return nullptr; // LCOV_EXCL_LINE
}
// LCOV_EXCL_STOP
} // namespace
template <bool T_Scoped>

View File

@ -79,15 +79,11 @@ using BitwiseToReduction = typename BitwiseToReductionImpl<T_Reduction>::type;
namespace {
template<typename Vertex> void foldOp(V3Number& out, const V3Number& src);
template <> void foldOp<DfgCLog2> (V3Number& out, const V3Number& src) { out.opCLog2(src); }
template <> void foldOp<DfgCountOnes> (V3Number& out, const V3Number& src) { out.opCountOnes(src); }
template <> void foldOp<DfgExtend> (V3Number& out, const V3Number& src) { out.opAssign(src); }
template <> void foldOp<DfgExtendS> (V3Number& out, const V3Number& src) { out.opExtendS(src, src.width()); }
template <> void foldOp<DfgLogNot> (V3Number& out, const V3Number& src) { out.opLogNot(src); }
template <> void foldOp<DfgNegate> (V3Number& out, const V3Number& src) { out.opNegate(src); }
template <> void foldOp<DfgNot> (V3Number& out, const V3Number& src) { out.opNot(src); }
template <> void foldOp<DfgOneHot> (V3Number& out, const V3Number& src) { out.opOneHot(src); }
template <> void foldOp<DfgOneHot0> (V3Number& out, const V3Number& src) { out.opOneHot0(src); }
template <> void foldOp<DfgRedAnd> (V3Number& out, const V3Number& src) { out.opRedAnd(src); }
template <> void foldOp<DfgRedOr> (V3Number& out, const V3Number& src) { out.opRedOr(src); }
template <> void foldOp<DfgRedXor> (V3Number& out, const V3Number& src) { out.opRedXor(src); }
@ -665,14 +661,6 @@ class V3DfgPeephole final : public DfgVisitor {
// DfgVertexUnary
//=========================================================================
void visit(DfgCLog2* vtxp) override {
if (foldUnary(vtxp)) return;
}
void visit(DfgCountOnes* vtxp) override {
if (foldUnary(vtxp)) return;
}
void visit(DfgExtend* vtxp) override {
UASSERT_OBJ(vtxp->width() > vtxp->srcp()->width(), vtxp, "Invalid zero extend");
@ -768,14 +756,6 @@ class V3DfgPeephole final : public DfgVisitor {
}
}
void visit(DfgOneHot* vtxp) override {
if (foldUnary(vtxp)) return;
}
void visit(DfgOneHot0* vtxp) override {
if (foldUnary(vtxp)) return;
}
void visit(DfgRedOr* vtxp) override {
if (optimizeReduction(vtxp)) return;
}

View File

@ -1356,6 +1356,116 @@ DfgVertices["Vertex"].addSubClass(DfgVertices["VertexTernary"])
DfgVertices["VertexVariadic"] = Node("VertexVariadic", DfgVertices["Vertex"])
DfgVertices["Vertex"].addSubClass(DfgVertices["VertexVariadic"])
# AstNodeExpr that are not representable in Dfg
DfgIgnored = (
# Floating point operations
"AcosD",
"AcoshD",
"AddD",
"AsinD",
"AsinhD",
"Atan2D",
"AtanD",
"AtanhD",
"BitsToRealD",
"CeilD",
"CosD",
"CoshD",
"DivD",
"EqD",
"ExpD",
"FloorD",
"GtD",
"GteD",
"HypotD",
"ISToRD",
"IToRD",
"Log10D",
"LogD",
"LtD",
"LteD",
"MulD",
"NegateD",
"NeqD",
"PowD",
"RealToBits",
"RToIRoundS",
"RToIS",
"SinD",
"SinhD",
"SqrtD",
"SubD",
"TanD",
"TanhD",
# String operations
"AtoN",
"CompareNN",
"ConcatN",
"CvtPackString",
"EqN",
"GetcN",
"GetcRefN",
"GteN",
"GtN",
"LenN",
"LteN",
"LtN",
"NeqN",
"NToI",
"PutcN",
"ReplicateN",
"SubstrN",
"ToLowerN",
"ToUpperN",
# Effectful
"PostAdd",
"PostSub",
"PreAdd",
"PreSub",
# Only used after DFG
"ShiftLOvr",
"ShiftROvr",
"ShiftRSOvr",
"WordSel",
# File operations
"FEof",
"FGetC",
"FGetS",
"FUngetC",
# Dynamic array operations
"AssocSel",
"IsUnbounded",
"WildcardSel",
# Type comparison
"EqT",
"NeqT",
# Distributions
"DistChiSquare",
"DistErlang",
"DistExponential",
"DistNormal",
"DistPoisson",
"DistT",
"DistUniform",
# Specials
"CastDynamic",
"CastWrap",
"CAwait",
"CCast",
"CLog2",
"CountOnes",
"IsUnknown",
"NullCheck",
"OneHot",
"OneHot0",
"ResizeLValue",
"Signed",
"SliceSel",
"TimeImport",
"Unsigned",
"URandomRange",
)
# Read DfgVertex definitions
for filename in Args.dfgdef:
read_types(os.path.join(Args.I, filename), DfgVertices, "Dfg")
@ -1370,6 +1480,10 @@ for node in AstNodeList:
if node.name in DfgVertices:
continue
# Ignore expressions types that DFG cannot handle
if node.name in DfgIgnored:
continue
if node.isSubClassOf(AstNodes["NodeUniop"]):
base = DfgVertices["VertexUnary"]
elif node.isSubClassOf(AstNodes["NodeBiop"]):

View File

@ -1,16 +0,0 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('vlt')
test.compile()
test.passes()

View File

@ -1,12 +0,0 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2023 by Geza Lore.
// SPDX-License-Identifier: CC0-1.0
module v(input logic t);
endmodule
module top(input logic [2:0] c);
v v1((int'(c) + int'($countones(c))) > 2);
endmodule

View File

@ -43,14 +43,9 @@ module t (
array[2][7:4] = rand_a[7:4];
end
`signal(FOLD_UNARY_CLog2, $clog2(const_a));
`signal(FOLD_UNARY_CountOnes, $countones(const_a));
`signal(FOLD_UNARY_IsUnknown, $isunknown(const_a));
`signal(FOLD_UNARY_LogNot, !const_a[0]);
`signal(FOLD_UNARY_Negate, -const_a);
`signal(FOLD_UNARY_Not, ~const_a);
`signal(FOLD_UNARY_OneHot, $onehot(const_a));
`signal(FOLD_UNARY_OneHot0, $onehot0(const_a));
`signal(FOLD_UNARY_RedAnd, &const_a);
`signal(FOLD_UNARY_RedOr, |const_a);
`signal(FOLD_UNARY_RedXor, ^const_a);

View File

@ -1,19 +0,0 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('vlt')
test.compile(verilator_flags2=["--stats"])
test.file_grep(test.stats,
r'Optimizations, DFG pre inline AstToDfg, non-representable \(impure\)\s+(\d+)', 1)
test.passes()

View File

@ -1,16 +0,0 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2022 by Geza Lore.
// SPDX-License-Identifier: CC0-1.0
module t (
input wire clk,
output wire [31:0] o0
);
int file;
assign o0 = $fgetc(file); // Impure
endmodule