mirror of
https://github.com/verilator/verilator.git
synced 2025-01-12 09:37:56 +00:00
DFG: Improve .dot dumps slightly
This commit is contained in:
parent
880cac2fdd
commit
694bdbc130
@ -540,12 +540,18 @@ void DfgGraph::runToFixedPoint(std::function<bool(DfgVertex&)> f) {
|
||||
|
||||
static const string toDotId(const DfgVertex& vtx) { return '"' + cvtToHex(&vtx) + '"'; }
|
||||
|
||||
static bool isSimpleSel(const DfgSel* vtxp) {
|
||||
const DfgConst* const lp = vtxp->lsbp()->cast<DfgConst>();
|
||||
const DfgConst* const wp = vtxp->widthp()->cast<DfgConst>();
|
||||
return lp && wp && !lp->hasMultipleSinks() && !wp->hasMultipleSinks();
|
||||
}
|
||||
|
||||
// Dump one DfgVertex in Graphviz format
|
||||
static void dumpDotVertex(std::ostream& os, const DfgVertex& vtx) {
|
||||
os << toDotId(vtx);
|
||||
|
||||
if (const DfgVarPacked* const varVtxp = vtx.cast<DfgVarPacked>()) {
|
||||
AstVar* const varp = varVtxp->varp();
|
||||
os << toDotId(vtx);
|
||||
os << " [label=\"" << varp->name() << "\nW" << varVtxp->width() << " / F"
|
||||
<< varVtxp->fanout() << '"';
|
||||
|
||||
@ -570,7 +576,9 @@ static void dumpDotVertex(std::ostream& os, const DfgVertex& vtx) {
|
||||
|
||||
if (const DfgVarArray* const arrVtxp = vtx.cast<DfgVarArray>()) {
|
||||
AstVar* const varp = arrVtxp->varp();
|
||||
os << " [label=\"" << varp->name() << "[]\"";
|
||||
const int elements = VN_AS(arrVtxp->dtypep(), UnpackArrayDType)->elementsConst();
|
||||
os << toDotId(vtx);
|
||||
os << " [label=\"" << varp->name() << "[" << elements << "]\"";
|
||||
if (varp->direction() == VDirection::INPUT) {
|
||||
os << ", shape=box3d, style=filled, fillcolor=chartreuse2"; // Green
|
||||
} else if (varp->direction() == VDirection::OUTPUT) {
|
||||
@ -591,18 +599,18 @@ static void dumpDotVertex(std::ostream& os, const DfgVertex& vtx) {
|
||||
}
|
||||
|
||||
if (const DfgConst* const constVtxp = vtx.cast<DfgConst>()) {
|
||||
const bool feedsSimpleSel = !constVtxp->findSink<DfgVertex>([](const DfgVertex& v) { //
|
||||
return !v.is<DfgSel>() || !isSimpleSel(v.as<DfgSel>());
|
||||
});
|
||||
if (feedsSimpleSel) return; // Will draw it in the sel node as it is very common
|
||||
|
||||
const V3Number& num = constVtxp->constp()->num();
|
||||
|
||||
os << toDotId(vtx);
|
||||
os << " [label=\"";
|
||||
if (num.width() <= 32 && !num.isSigned()) {
|
||||
const bool feedsSel = !constVtxp->findSink<DfgVertex>([](const DfgVertex& vtx) { //
|
||||
return !vtx.is<DfgSel>() && !vtx.is<DfgArraySel>();
|
||||
});
|
||||
if (feedsSel) {
|
||||
os << num.toUInt();
|
||||
} else {
|
||||
os << constVtxp->width() << "'d" << num.toUInt() << "\n";
|
||||
os << constVtxp->width() << "'h" << std::hex << num.toUInt() << std::dec;
|
||||
}
|
||||
os << constVtxp->width() << "'d" << num.toUInt() << "\n";
|
||||
os << constVtxp->width() << "'h" << std::hex << num.toUInt() << std::dec;
|
||||
} else {
|
||||
os << num.ascii();
|
||||
}
|
||||
@ -612,6 +620,24 @@ static void dumpDotVertex(std::ostream& os, const DfgVertex& vtx) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (const DfgSel* const selVtxp = vtx.cast<DfgSel>()) {
|
||||
if (isSimpleSel(selVtxp)) {
|
||||
const uint32_t lsb = selVtxp->lsbp()->as<DfgConst>()->toU32();
|
||||
const uint32_t msb = lsb + selVtxp->width() - 1;
|
||||
os << toDotId(vtx);
|
||||
os << " [label=\"SEL\n_[" << msb << ":" << lsb << "]\nW" << vtx.width() << " / F"
|
||||
<< vtx.fanout() << '"';
|
||||
if (vtx.hasMultipleSinks()) {
|
||||
os << ", shape=doublecircle";
|
||||
} else {
|
||||
os << ", shape=circle";
|
||||
}
|
||||
os << "]" << endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
os << toDotId(vtx);
|
||||
os << " [label=\"" << vtx.typeName() << "\nW" << vtx.width() << " / F" << vtx.fanout() << '"';
|
||||
if (vtx.hasMultipleSinks()) {
|
||||
os << ", shape=doublecircle";
|
||||
@ -631,6 +657,16 @@ static void dumpDotEdge(std::ostream& os, const DfgEdge& edge, const string& hea
|
||||
// Dump one DfgVertex and all of its source DfgEdges in Graphviz format
|
||||
static void dumpDotVertexAndSourceEdges(std::ostream& os, const DfgVertex& vtx) {
|
||||
dumpDotVertex(os, vtx);
|
||||
|
||||
if (const DfgSel* const selVtxp = vtx.cast<const DfgSel>()) {
|
||||
if (isSimpleSel(selVtxp)) {
|
||||
UASSERT_OBJ(selVtxp->sourceEdge<0>()->sourcep() == selVtxp->fromp(), selVtxp,
|
||||
"Operand ordering changed");
|
||||
dumpDotEdge(os, *selVtxp->sourceEdge<0>(), "");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
vtx.forEachSourceEdge([&](const DfgEdge& edge, size_t idx) { //
|
||||
if (edge.sourcep()) {
|
||||
string headLabel;
|
||||
|
@ -484,6 +484,12 @@ public:
|
||||
return &m_srcs[Index];
|
||||
}
|
||||
|
||||
template <size_t Index>
|
||||
const DfgEdge* sourceEdge() const {
|
||||
static_assert(Index < Arity, "Source index out of range");
|
||||
return &m_srcs[Index];
|
||||
}
|
||||
|
||||
template <size_t Index>
|
||||
DfgVertex* source() const {
|
||||
static_assert(Index < Arity, "Source index out of range");
|
||||
|
@ -42,6 +42,7 @@ close $wrFile;
|
||||
compile(
|
||||
verilator_flags2 => ["--stats", "--build", "--exe",
|
||||
"-Mdir", "$Self->{obj_dir}/obj_opt", "--prefix", "Vopt",
|
||||
"--dump-dfg", # To fill code coverage
|
||||
"-CFLAGS \"-I .. -I ../obj_ref\"",
|
||||
"../obj_ref/Vref__ALL.a",
|
||||
"../../t/$Self->{name}.cpp"],
|
||||
|
Loading…
Reference in New Issue
Block a user