13 #ifndef CIRCT_DIALECT_HW_HWMODULEGRAPH_H
14 #define CIRCT_DIALECT_HW_HWMODULEGRAPH_H
21 #include "llvm/ADT/GraphTraits.h"
22 #include "llvm/ADT/STLExtras.h"
23 #include "llvm/ADT/TypeSwitch.h"
24 #include "llvm/ADT/iterator.h"
25 #include "llvm/Support/DOTGraphTraits.h"
26 #include "llvm/Support/GraphWriter.h"
53 :
public llvm::GraphTraits<circt::hw::detail::HWOperation *> {
57 return &mod.getBodyBlock()->front();
71 :
public llvm::DefaultDOTGraphTraits {
72 using DefaultDOTGraphTraits::DefaultDOTGraphTraits;
75 circt::hw::HWModuleOp) {
76 return llvm::TypeSwitch<mlir::Operation *, std::string>(node)
77 .Case<circt::comb::AddOp>([&](
auto) {
return "+"; })
78 .Case<circt::comb::SubOp>([&](
auto) {
return "-"; })
79 .Case<circt::comb::AndOp>([&](
auto) {
return "&"; })
80 .Case<circt::comb::OrOp>([&](
auto) {
return "|"; })
81 .Case<circt::comb::XorOp>([&](
auto) {
return "^"; })
82 .Case<circt::comb::MulOp>([&](
auto) {
return "*"; })
83 .Case<circt::comb::MuxOp>([&](
auto) {
return "mux"; })
84 .Case<circt::comb::ShrSOp, circt::comb::ShrUOp>(
85 [&](
auto) {
return ">>"; })
86 .Case<circt::comb::ShlOp>([&](
auto) {
return "<<"; })
87 .Case<circt::comb::ICmpOp>([&](
auto op) {
88 switch (op.getPredicate()) {
89 case circt::comb::ICmpPredicate::eq:
90 case circt::comb::ICmpPredicate::ceq:
91 case circt::comb::ICmpPredicate::weq:
93 case circt::comb::ICmpPredicate::wne:
94 case circt::comb::ICmpPredicate::cne:
95 case circt::comb::ICmpPredicate::ne:
97 case circt::comb::ICmpPredicate::uge:
98 case circt::comb::ICmpPredicate::sge:
100 case circt::comb::ICmpPredicate::ugt:
101 case circt::comb::ICmpPredicate::sgt:
103 case circt::comb::ICmpPredicate::ule:
104 case circt::comb::ICmpPredicate::sle:
106 case circt::comb::ICmpPredicate::ult:
107 case circt::comb::ICmpPredicate::slt:
110 llvm_unreachable(
"unhandled ICmp predicate");
112 .Case<circt::seq::FirRegOp>([&](
auto op) {
return op.getName().str(); })
113 .Case<circt::seq::CompRegOp>([&](
auto op) -> std::string {
114 if (
auto name = op.getName())
118 .Case<circt::hw::ConstantOp>([&](
auto op) {
119 llvm::SmallString<64> valueString;
120 op.getValue().toString(valueString, 10,
false);
121 return valueString.str().str();
123 .Default([&](
auto op) {
return op->getName().getStringRef().str(); });
127 circt::hw::HWModuleOp) {
128 return llvm::TypeSwitch<mlir::Operation *, std::string>(node)
129 .Case<circt::hw::ConstantOp>(
130 [&](
auto) {
return "fillcolor=darkgoldenrod1,style=filled"; })
131 .Case<circt::comb::MuxOp>([&](
auto) {
132 return "shape=invtrapezium,fillcolor=bisque,style=filled";
134 .Case<circt::hw::OutputOp>(
135 [&](
auto) {
return "fillcolor=lightblue,style=filled"; })
136 .Default([&](
auto op) {
137 return llvm::TypeSwitch<mlir::Dialect *, std::string>(
139 .Case<circt::comb::CombDialect>([&](
auto) {
140 return "shape=oval,fillcolor=bisque,style=filled";
142 .
template Case<circt::seq::SeqDialect>([&](
auto) {
143 return "shape=folder,fillcolor=gainsboro,style=filled";
145 .Default([&](
auto) {
return ""; });
151 llvm::GraphWriter<circt::hw::HWModuleOp> &g) {
154 auto &os = g.getOStream();
155 os <<
"subgraph cluster_entry_args {\n";
156 os <<
"label=\"Input arguments\";\n";
158 for (
auto [info, arg] :
159 llvm::zip(iports.
getInputs(), mod.getBodyBlock()->getArguments())) {
160 g.emitSimpleNode(
reinterpret_cast<void *
>(&arg),
"",
161 info.getName().str());
164 for (
auto [info, arg] :
165 llvm::zip(iports.
getInputs(), mod.getBodyBlock()->getArguments())) {
166 for (
auto *user : arg.getUsers()) {
167 g.emitEdge(
reinterpret_cast<void *
>(&arg), 0, user, -1,
"");
172 template <
typename Iterator>
174 Iterator it, circt::hw::HWModuleOp mod) {
176 mlir::OpOperand &operand = *it.getCurrent();
177 mlir::Value v = operand.get();
179 llvm::raw_string_ostream os(str);
180 auto verboseEdges = mod->getAttrOfType<mlir::BoolAttr>(
"dot_verboseEdges");
181 if (verboseEdges.getValue()) {
182 os <<
"label=\"" << operand.getOperandNumber() <<
" (" << v.getType()
mlir::Operation HWOperation
int64_t getBitWidth(mlir::Type type)
Return the hardware bit width of a type.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
This holds a decoded list of input/inout and output ports for a module or instance.
PortDirectionRange getInputs()
static void addCustomGraphFeatures(circt::hw::HWModuleOp mod, llvm::GraphWriter< circt::hw::HWModuleOp > &g)
static std::string getEdgeAttributes(circt::hw::detail::HWOperation *node, Iterator it, circt::hw::HWModuleOp mod)
static std::string getNodeLabel(circt::hw::detail::HWOperation *node, circt::hw::HWModuleOp)
std::string getNodeAttributes(circt::hw::detail::HWOperation *node, circt::hw::HWModuleOp)
circt::hw::HWModuleOp GraphType
pointer_iterator< mlir::Block::iterator > nodes_iterator
static nodes_iterator nodes_begin(GraphType mod)
static nodes_iterator nodes_end(GraphType mod)
static NodeRef getEntryNode(GraphType mod)
circt::hw::detail::HWOperation NodeType
static ChildIteratorType child_begin(NodeRef op)
static NodeRef getEntryNode(NodeRef op)
static ChildIteratorType child_end(NodeRef op)
mlir::Operation::user_iterator ChildIteratorType