15 #include "mlir/IR/Operation.h"
16 #include "mlir/Support/IndentedOstream.h"
18 using namespace circt;
24 SmallVector<Operation *> unhandledOps;
25 unhandledOps.insert(unhandledOps.begin(), allOps.begin(), allOps.end());
27 while (!unhandledOps.empty()) {
32 unsigned numUnhandledBefore = unhandledOps.size();
36 SmallVector<Operation *> worklist;
37 worklist.insert(worklist.begin(), unhandledOps.rbegin(),
41 while (!worklist.empty()) {
42 Operation *op = worklist.pop_back_val();
45 unhandledOps.push_back(op);
48 if (numUnhandledBefore == unhandledOps.size())
49 return prob.
getContainingOp()->emitError() <<
"dependence cycle detected";
57 llvm::raw_fd_ostream out(fileName, ec);
63 mlir::raw_indented_ostream os(stream);
65 os <<
"digraph G {\n";
67 os <<
"rankdir = TB // top to bottom\n";
68 os <<
"splines = spline // draw edges and route around nodes\n";
69 os <<
"nodesep = 0.2 // horizontal compression\n";
70 os <<
"ranksep = 0.5 // vertical compression\n";
71 os <<
"node [shape=box] // default node style\n";
72 os <<
"compound = true // allow edges between subgraphs\n";
74 auto startHTMLLabel = [&os]() {
75 os <<
"<<TABLE BORDER=\"0\">\n";
78 auto emitTableHeader = [&os](std::string str) {
79 os <<
"<TR><TD COLSPAN=\"2\"><B>" << str <<
"</B></TD></TR>\n";
81 auto emitTableRow = [&os](std::pair<std::string, std::string> &kv) {
82 os <<
"<TR><TD ALIGN=\"LEFT\">" << std::get<0>(kv)
83 <<
":</TD><TD ALIGN=\"RIGHT\">" << std::get<1>(kv) <<
"</TD></TR>\n";
85 auto endHTMLLabel = [&os]() {
90 DenseMap<Operation *, std::string> nodes;
92 os <<
"\n// Operations\n";
93 os <<
"subgraph dependence_graph {\n";
97 auto id = std::to_string(nodes.size());
98 auto node =
"op" + id;
101 os << node <<
" [label = ";
103 emitTableHeader((
"#" +
id +
" " + op->getName().getStringRef()).str());
110 os <<
"\n// Dependences\n";
113 os << nodes[dep.getSource()] <<
" -> " << nodes[dep.getDestination()]
115 if (dep.isAuxiliary())
116 os <<
"style = dashed ";
120 for (
auto &kv : props)
129 os <<
"\n// Operator types\n";
130 os <<
"subgraph cluster_operator_types {\n";
132 os <<
"label = \"Operator types\"\n";
133 os <<
"style = filled fillcolor = lightgray\n";
134 os <<
"node [style = \"rounded,filled\" fillcolor = white]\n";
137 os <<
"opr" << oprId <<
" [label = ";
139 emitTableHeader(opr.str());
149 if (
auto instanceProps = prob.
getProperties(); !instanceProps.empty()) {
150 os <<
"\n// Instance\n";
151 os <<
"instance [shape = note, label = ";
153 emitTableHeader(
"Instance");
154 for (
auto &kv : instanceProps)
This class models the most basic scheduling problem.
virtual PropertyStringVector getProperties(Operation *op)
const OperatorTypeSet & getOperatorTypes()
Return the set of operator types.
DependenceRange getDependences(Operation *op)
Return a range object to transparently iterate over op's incoming 1) implicit def-use dependences (ba...
const OperationSet & getOperations()
Return the set of operations.
Operation * getContainingOp()
Return the operation containing this problem, e.g. to emit diagnostics.
LogicalResult handleOperationsInTopologicalOrder(Problem &prob, HandleOpFn fun)
Visit prob's operations in topological order, using an internal worklist.
void dumpAsDOT(Problem &prob, StringRef fileName)
Export prob as a DOT graph into fileName.
std::function< LogicalResult(Operation *)> HandleOpFn
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.