CIRCT 20.0.0git
Loading...
Searching...
No Matches
HWModuleGraph.h
Go to the documentation of this file.
1//===- HWModuleGraph.h - HWModule graph -------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the HWModuleGraph.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef CIRCT_DIALECT_HW_HWMODULEGRAPH_H
14#define CIRCT_DIALECT_HW_HWMODULEGRAPH_H
15
20#include "circt/Support/LLVM.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"
27
28namespace circt {
29namespace hw {
30namespace detail {
31
32// Using declaration to avoid polluting global namespace with CIRCT-specific
33// graph traits for mlir::Operation.
34using HWOperation = mlir::Operation;
35
36} // namespace detail
37} // namespace hw
38} // namespace circt
39
40template <>
41struct llvm::GraphTraits<circt::hw::detail::HWOperation *> {
43 using NodeRef = NodeType *;
44
45 using ChildIteratorType = mlir::Operation::user_iterator;
46 static NodeRef getEntryNode(NodeRef op) { return op; }
47 static ChildIteratorType child_begin(NodeRef op) { return op->user_begin(); }
48 static ChildIteratorType child_end(NodeRef op) { return op->user_end(); }
49};
50
51template <>
52struct llvm::GraphTraits<circt::hw::HWModuleOp>
53 : public llvm::GraphTraits<circt::hw::detail::HWOperation *> {
54 using GraphType = circt::hw::HWModuleOp;
55
57 return &mod.getBodyBlock()->front();
58 }
59
60 using nodes_iterator = pointer_iterator<mlir::Block::iterator>;
62 return nodes_iterator{mod.getBodyBlock()->begin()};
63 }
65 return nodes_iterator{mod.getBodyBlock()->end()};
66 }
67};
68
69template <>
70struct llvm::DOTGraphTraits<circt::hw::HWModuleOp>
71 : public llvm::DefaultDOTGraphTraits {
72 using DefaultDOTGraphTraits::DefaultDOTGraphTraits;
73
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:
92 return "==";
93 case circt::comb::ICmpPredicate::wne:
94 case circt::comb::ICmpPredicate::cne:
95 case circt::comb::ICmpPredicate::ne:
96 return "!=";
97 case circt::comb::ICmpPredicate::uge:
98 case circt::comb::ICmpPredicate::sge:
99 return ">=";
100 case circt::comb::ICmpPredicate::ugt:
101 case circt::comb::ICmpPredicate::sgt:
102 return ">";
103 case circt::comb::ICmpPredicate::ule:
104 case circt::comb::ICmpPredicate::sle:
105 return "<=";
106 case circt::comb::ICmpPredicate::ult:
107 case circt::comb::ICmpPredicate::slt:
108 return "<";
109 }
110 llvm_unreachable("unhandled ICmp predicate");
111 })
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())
115 return name->str();
116 return "reg";
117 })
118 .Case<circt::hw::ConstantOp>([&](auto op) {
119 llvm::SmallString<64> valueString;
120 op.getValue().toString(valueString, 10, false);
121 return valueString.str().str();
122 })
123 .Default([&](auto op) { return op->getName().getStringRef().str(); });
124 }
125
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";
133 })
134 .Case<circt::hw::OutputOp>(
135 [&](auto) { return "fillcolor=lightblue,style=filled"; })
136 .Default([&](auto op) {
137 return llvm::TypeSwitch<mlir::Dialect *, std::string>(
138 op->getDialect())
139 .Case<circt::comb::CombDialect>([&](auto) {
140 return "shape=oval,fillcolor=bisque,style=filled";
141 })
142 .template Case<circt::seq::SeqDialect>([&](auto) {
143 return "shape=folder,fillcolor=gainsboro,style=filled";
144 })
145 .Default([&](auto) { return ""; });
146 });
147 }
148
149 static void
150 addCustomGraphFeatures(circt::hw::HWModuleOp mod,
151 llvm::GraphWriter<circt::hw::HWModuleOp> &g) {
152
153 // Add module input args.
154 auto &os = g.getOStream();
155 os << "subgraph cluster_entry_args {\n";
156 os << "label=\"Input arguments\";\n";
157 circt::hw::ModulePortInfo iports(mod.getPortList());
158 for (auto [info, arg] :
159 llvm::zip(iports.getInputs(), mod.getBodyBlock()->getArguments())) {
160 g.emitSimpleNode(reinterpret_cast<void *>(&arg), "",
161 info.getName().str());
162 }
163 os << "}\n";
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, "");
168 }
169 }
170 }
171
172 template <typename Iterator>
174 Iterator it, circt::hw::HWModuleOp mod) {
175
176 mlir::OpOperand &operand = *it.getCurrent();
177 mlir::Value v = operand.get();
178 std::string str;
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()
183 << ")\"";
184 }
185
186 int64_t width = circt::hw::getBitWidth(v.getType());
187 if (width > 1)
188 os << " style=bold";
189
190 return os.str();
191 }
192};
193
194#endif // CIRCT_DIALECT_HW_HWMODULEGRAPH_H
mlir::Operation HWOperation
int64_t getBitWidth(mlir::Type type)
Return the hardware bit width of a type.
Definition HWTypes.cpp:110
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition hw.py:1
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)
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)
static ChildIteratorType child_begin(NodeRef op)
static ChildIteratorType child_end(NodeRef op)