Jlm
Loading...
Searching...
No Matches
view.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2024 David Metz <david.c.metz@ntnu.no>
3 * See COPYING for terms of redistribution.
4 */
5
6#include <jlm/hls/ir/hls.hpp>
8#include <jlm/rvsdg/gamma.hpp>
12#include <jlm/rvsdg/theta.hpp>
14#include <jlm/rvsdg/view.hpp>
15
16#include <algorithm>
17
18namespace jlm::hls
19{
20
21std::string
23{
24 switch (color)
25 {
26 case NONE:
27 return "";
28 break;
29
30 case BLACK:
31 return "black";
32 break;
33
34 case RED:
35 return "red";
36 break;
37
38 default:
39 JLM_UNREACHABLE("HLS view color not defined");
40 break;
41 }
42}
43
44static inline std::string
45hex(size_t i)
46{
47 std::stringstream stream;
48 stream << std::hex << i;
49 return stream.str();
50}
51
52std::string
54{
55 return util::strfmt("n", hex((intptr_t)node));
56}
57
58std::string
60{
61 if (dynamic_cast<rvsdg::RegionArgument *>(output))
62 {
63 return util::strfmt("a", hex((intptr_t)output), ":", "default");
64 }
65
67 {
68 return util::strfmt(GetDotName(simpleNode), ":", "o", hex((intptr_t)output));
69 }
70 else if (dynamic_cast<rvsdg::StructuralOutput *>(output))
71 {
72 return util::strfmt("so", hex((intptr_t)output), ":", "default");
73 }
74 JLM_UNREACHABLE("not implemented");
75}
76
77template<class T>
79GetDefaultColor(std::unordered_map<T *, ViewColors> & map, T * elem, ViewColors def = BLACK)
80{
81 auto f = map.find(elem);
82 if (f == map.end())
83 {
84 return def;
85 }
86 return f->second;
87}
88
89template<class T>
91GetDefaultLabel(std::unordered_map<T *, ViewColors> & map, T * elem, ViewColors def = NONE)
92{
93 auto f = map.find(elem);
94 if (f == map.end())
95 {
96 return def;
97 }
98 return f->second;
99}
100
101std::string
103{
104 if (dynamic_cast<rvsdg::RegionResult *>(input))
105 {
106 return util::strfmt("r", hex((intptr_t)input), ":", "default");
107 }
109 {
110 return util::strfmt(GetDotName(simpleNode), ":", "i", hex((intptr_t)input));
111 }
112 else if (dynamic_cast<rvsdg::StructuralInput *>(input))
113 {
114 return util::strfmt("si", hex((intptr_t)input), ":", "default");
115 }
116 JLM_UNREACHABLE("not implemented");
117}
118
119std::string
120PortToDot(const std::string & display_name, const std::string & dot_name, const ViewColors & color)
121{
122 auto dot =
124 + " [shape=plaintext label=<\n"
125 " <TABLE BORDER=\"0\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\">\n"
126 " <TR>\n"
127 " <TD PORT=\"default\" BORDER=\"1\" CELLPADDING=\"1\"><FONT "
128 "POINT-SIZE=\"10\">"
130 + "</FONT></TD>\n"
131 " </TR>\n"
132 " </TABLE>\n"
133 "> tooltip=\""
134 + dot_name + "\" color=" + ViewcolorToString(color) + " fontcolor=" + ViewcolorToString(color)
135 + "];\n";
136 return dot;
137}
138
139std::string
141{
142 auto display_name = util::strfmt("a", argument->index());
143 auto dot_name = util::strfmt("a", hex((intptr_t)argument));
145}
146
147std::string
149{
150 auto display_name = util::strfmt("r", result->index());
151 auto dot_name = util::strfmt("r", hex((intptr_t)result));
153}
154
155std::string
162
163std::string
170
171std::string
173 jlm::rvsdg::Output * output,
174 jlm::rvsdg::Input * input,
175 std::unordered_map<rvsdg::Output *, ViewColors> & tailLabel,
176 bool back_edge = false)
177{
178 auto color = "black";
180 if (!back_edge)
181 {
182 return GetDotName(output) + " -> " + GetDotName(input)
183 + " [style=\"\", arrowhead=\"normal\", color=" + color
184 + ", headlabel=<>, fontsize=15, labelangle=45, labeldistance=2.0, labelfontcolor=blue, "
185 "tooltip=\""
186 + output->Type()->debug_string() + "\", taillabel=\"" + ViewcolorToString(tailLabelColor)
187 + "\"];\n";
188 }
189 return GetDotName(input) + " -> " + GetDotName(output)
190 + " [style=\"\", arrowhead=\"normal\", color=" + color
191 + ", headlabel=<>, fontsize=15, labelangle=45, labeldistance=2.0, labelfontcolor=blue, "
192 "constraint=false, tooltip=\""
193 + output->Type()->debug_string() + "\", taillabel=\"" + ViewcolorToString(tailLabelColor)
194 + "\"];\n";
195}
196
197std::string
199{
200 auto color = "black";
201 return GetDotName(output) + " -> " + GetDotName(input)
202 + " [style=\"\", arrowhead=\"normal\", color=" + color
203 + ", headlabel=<>, fontsize=10, labelangle=45, labeldistance=2.0, labelfontcolor=black, "
204 "tooltip=\""
205 + output->Type()->debug_string() + "\"];\n";
206}
207
208static bool
209isForbiddenChar(char c)
210{
211 if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || '_' == c)
212 {
213 return false;
214 }
215 return true;
216}
217
218std::string
221 std::unordered_map<rvsdg::Output *, ViewColors> & outputColor,
222 std::unordered_map<rvsdg::Input *, ViewColors> & inputColor,
223 std::unordered_map<rvsdg::Output *, ViewColors> & tailLabel)
224{
225
226 std::ostringstream dot;
227 dot << "subgraph cluster_sn" << hex((intptr_t)structuralNode) << " {\n";
228 dot << "color=\"#ff8080\"\n";
229 dot << "penwidth=6\n";
230 dot << "label=\"" << structuralNode->DebugString() << "\"\n";
231 dot << "labeljust=l\n";
232
233 // input nodes
234 for (size_t i = 0; i < structuralNode->ninputs(); ++i)
235 {
237 structuralNode->input(i),
239 }
240
241 for (size_t i = 0; i < structuralNode->nsubregions(); ++i)
242 {
244 }
245
246 for (size_t i = 0; i < structuralNode->ninputs(); ++i)
247 {
248 for (auto & argument : structuralNode->input(i)->arguments)
249 {
250 dot << SymbolicEdge(structuralNode->input(i), &argument);
251 }
252 }
253
254 // output nodes
255 for (size_t i = 0; i < structuralNode->noutputs(); ++i)
256 {
258 structuralNode->output(i),
260 for (auto & result : structuralNode->output(i)->results)
261 {
262 dot << SymbolicEdge(&result, structuralNode->output(i));
263 }
264 }
265
266 dot << "}\n";
267
268 return dot.str();
269}
270
271std::string
274 std::unordered_map<rvsdg::Output *, ViewColors> & outputColor,
275 std::unordered_map<rvsdg::Input *, ViewColors> & inputColor)
276{
277 auto SPACER = " <TD WIDTH=\"10\"></TD>\n";
278 auto name = GetDotName(simpleNode);
279 auto opname = simpleNode->DebugString();
280 std::replace_if(opname.begin(), opname.end(), isForbiddenChar, '_');
281
282 std::ostringstream inputs;
283 // inputs
284 for (size_t i = 0; i < simpleNode->ninputs(); ++i)
285 {
287 if (i != 0)
288 {
289 inputs << SPACER;
290 }
291 inputs << " <TD PORT=\"i" << hex((intptr_t)simpleNode->input(i))
292 << "\" BORDER=\"1\" CELLPADDING=\"1\" COLOR=\"" << color
293 << "\"><FONT POINT-SIZE=\"10\" COLOR=\"" << color << "\"> i" << i << "</FONT></TD>\n";
294 }
295
296 std::ostringstream outputs;
297 // outputs
298 for (size_t i = 0; i < simpleNode->noutputs(); ++i)
299 {
301 if (i != 0)
302 {
303 outputs << SPACER;
304 }
305 outputs << " <TD PORT=\"o" << hex((intptr_t)simpleNode->output(i))
306 << "\" BORDER=\"1\" CELLPADDING=\"1\" COLOR=\"" << color
307 << "\"><FONT POINT-SIZE=\"10\" COLOR=\"" << color << "\"> o" << i << "</FONT></TD>\n";
308 }
309
310 std::string color = "black";
311 auto dot =
312 name
313 + " [shape=plaintext label=<\n"
314 "<TABLE BORDER=\"0\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\">\n"
315 // inputs
316 " <TR>\n"
317 " <TD BORDER=\"0\">\n"
318 " <TABLE BORDER=\"0\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\">\n"
319 " <TR>\n"
320 " <TD WIDTH=\"20\"></TD>\n"
321 + inputs.str()
322 + " <TD WIDTH=\"20\"></TD>\n"
323 " </TR>\n"
324 " </TABLE>\n"
325 " </TD>\n"
326 " </TR>\n"
327 " <TR>\n"
328 " <TD BORDER=\"3\" STYLE=\"ROUNDED\" CELLPADDING=\"4\">"
329 + opname + "<BR/><FONT POINT-SIZE=\"10\">" + name
330 + "</FONT></TD>\n"
331 " </TR>\n"
332 " <TR>\n"
333 " <TD BORDER=\"0\">\n"
334 " <TABLE BORDER=\"0\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\">\n"
335 " <TR>\n"
336 " <TD WIDTH=\"20\"></TD>\n"
337 + outputs.str()
338 + " <TD WIDTH=\"20\"></TD>\n"
339 " </TR>\n"
340 " </TABLE>\n"
341 " </TD>\n"
342 " </TR>\n"
343 "</TABLE>\n"
344 "> fontcolor="
345 + color + " color=" + color + "];\n";
346 return dot;
347}
348
349std::string
351 rvsdg::Region * region,
352 std::unordered_map<rvsdg::Output *, ViewColors> & outputColor,
353 std::unordered_map<rvsdg::Input *, ViewColors> & inputColor,
354 std::unordered_map<rvsdg::Output *, ViewColors> & tailLabel)
355{
356 std::ostringstream dot;
357 dot << "subgraph cluster_reg" << hex((intptr_t)region) << " {\n";
358 dot << "color=\"#80b3ff\"\n";
359 dot << "penwidth=6\n";
360 dot << "label=\"" << region->index() << " - " << hex((intptr_t)region) << "\"\n";
361
362 // argument nodes
363 dot << "{rank=source; ";
364 for (size_t i = 0; i < region->narguments(); ++i)
365 {
367 region->argument(i),
369 }
370 dot << "}\n";
371
372 // nodes
373 for (auto node : rvsdg::TopDownTraverser(region))
374 {
375 if (auto simpleNode = dynamic_cast<rvsdg::SimpleNode *>(node))
376 {
378 dot << node_dot;
379 }
380 else if (auto structuralNode = dynamic_cast<rvsdg::StructuralNode *>(node))
381 {
383 dot << node_dot;
384 }
385
386 for (size_t i = 0; i < node->ninputs(); ++i)
387 {
388 dot << Edge(node->input(i)->origin(), node->input(i), tailLabel);
389 }
390 }
391
392 // result nodes
393 dot << "{rank=sink; ";
394 for (size_t i = 0; i < region->nresults(); ++i)
395 {
396 dot << ResultToDot(
397 region->result(i),
399 }
400 dot << "}\n";
401 for (size_t i = 0; i < region->nresults(); ++i)
402 {
403 dot << Edge(region->result(i)->origin(), region->result(i), tailLabel);
404 if (auto be = dynamic_cast<BackEdgeResult *>(region->result(i)))
405 {
406 dot << Edge(be->argument(), be, tailLabel, true);
407 }
408 else if (
409 region->result(i)->output()
411 {
412 auto theta = rvsdg::TryGetOwnerNode<rvsdg::ThetaNode>(*region->result(i)->output());
413 auto loopvar = theta->MapOutputLoopVar(*region->result(i)->output());
414 dot << Edge(loopvar.pre, loopvar.post, tailLabel, true);
415 }
416 }
417
418 dot << "}\n";
419
420 return dot.str();
421}
422
423std::string
425 rvsdg::Region * region,
426 std::unordered_map<rvsdg::Output *, ViewColors> & outputColor,
427 std::unordered_map<rvsdg::Input *, ViewColors> & inputColor,
428 std::unordered_map<rvsdg::Output *, ViewColors> & tailLabel)
429{
430 std::ostringstream dot;
431 dot << "digraph G {\n";
433 dot << "}\n";
434 return dot.str();
435}
436
437void
439 rvsdg::Region * region,
440 FILE * out,
441 std::unordered_map<rvsdg::Output *, ViewColors> & outputColor,
442 std::unordered_map<rvsdg::Input *, ViewColors> & inputColor,
443 std::unordered_map<rvsdg::Output *, ViewColors> & tailLabel)
444{
446 fflush(out);
447}
448
449void
451{
452 std::unordered_map<rvsdg::Output *, ViewColors> outputColor;
453 std::unordered_map<rvsdg::Input *, ViewColors> inputColor;
454 std::unordered_map<rvsdg::Output *, ViewColors> tailLabel;
456}
457
458void
460{
461 DumpDot(&rvsdgModule.Rvsdg().GetRootRegion(), file_name);
462}
463
464void
467 const std::string & file_name,
468 std::unordered_map<rvsdg::Output *, ViewColors> outputColor,
469 std::unordered_map<rvsdg::Input *, ViewColors> inputColor,
470 std::unordered_map<rvsdg::Output *, ViewColors> tailLabel)
471{
472 DumpDot(&rvsdgModule.Rvsdg().GetRootRegion(), file_name, outputColor, inputColor, tailLabel);
473}
474
475void
476DumpDot(rvsdg::Region * region, const std::string & file_name)
477{
478 auto dot_file = fopen(file_name.c_str(), "w");
479 ViewDot(region, dot_file);
481}
482
483void
485 rvsdg::Region * region,
486 const std::string & file_name,
487 std::unordered_map<rvsdg::Output *, ViewColors> outputColor,
488 std::unordered_map<rvsdg::Input *, ViewColors> inputColor,
489 std::unordered_map<rvsdg::Output *, ViewColors> tailLabel)
490{
491 auto dot_file = fopen(file_name.c_str(), "w");
494}
495
496void
497DotToSvg(const std::string & file_name)
498{
499 auto cmd = "dot -Tsvg -O " + file_name;
500 if (system(cmd.c_str()))
501 exit(EXIT_FAILURE);
502}
503
505
509
510void
514{
515 const auto file = statisticsCollector.createOutputFile("rvsdg-graph.dot", true);
516 DumpDot(&rvsdgModule.Rvsdg().GetRootRegion(), file.path().to_str());
517}
518
519} // namespace jlm::hls
static jlm::util::StatisticsCollector statisticsCollector
~DumpDotTransformation() noexcept override
void Run(rvsdg::RvsdgModule &rvsdgModule, util::StatisticsCollector &statisticsCollector) override
Definition view.cpp:511
size_t index() const noexcept
Definition node.hpp:52
Output * origin() const noexcept
Definition node.hpp:58
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Definition node.hpp:67
size_t index() const noexcept
Definition node.hpp:274
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Definition node.hpp:366
Represents the argument of a region.
Definition region.hpp:41
Represents the result of a region.
Definition region.hpp:120
StructuralOutput * output() const noexcept
Definition region.hpp:149
Represent acyclic RVSDG subgraphs.
Definition region.hpp:213
RegionArgument * argument(size_t index) const noexcept
Definition region.hpp:466
size_t nresults() const noexcept
Definition region.hpp:494
RegionResult * result(size_t index) const noexcept
Definition region.hpp:500
size_t index() const noexcept
Definition region.hpp:310
size_t narguments() const noexcept
Definition region.hpp:460
Represents an RVSDG transformation.
File createOutputFile(std::string fileNameSuffix, bool includeCount=false)
#define JLM_UNREACHABLE(msg)
Definition common.hpp:43
std::string GetDotName(rvsdg::Node *node)
Definition view.cpp:53
ViewColors GetDefaultLabel(std::unordered_map< T *, ViewColors > &map, T *elem, ViewColors def=NONE)
Definition view.cpp:91
std::string SymbolicEdge(rvsdg::Input *output, rvsdg::Output *input)
Definition view.cpp:198
void DumpDot(llvm::LlvmRvsdgModule &rvsdgModule, const std::string &file_name)
Definition view.cpp:459
std::string RegionToDot(rvsdg::Region *region, std::unordered_map< rvsdg::Output *, ViewColors > &outputColor, std::unordered_map< rvsdg::Input *, ViewColors > &inputColor, std::unordered_map< rvsdg::Output *, ViewColors > &tailLabel)
Definition view.cpp:350
ViewColors
Definition view.hpp:19
@ BLACK
Definition view.hpp:21
@ NONE
Definition view.hpp:20
@ RED
Definition view.hpp:22
std::string ResultToDot(rvsdg::RegionResult *result, const ViewColors &color)
Definition view.cpp:148
std::string PortToDot(const std::string &display_name, const std::string &dot_name, const ViewColors &color)
Definition view.cpp:120
void DotToSvg(const std::string &file_name)
Definition view.cpp:497
void ViewDot(rvsdg::Region *region, FILE *out, std::unordered_map< rvsdg::Output *, ViewColors > &outputColor, std::unordered_map< rvsdg::Input *, ViewColors > &inputColor, std::unordered_map< rvsdg::Output *, ViewColors > &tailLabel)
Definition view.cpp:438
std::string Edge(jlm::rvsdg::Output *output, jlm::rvsdg::Input *input, std::unordered_map< rvsdg::Output *, ViewColors > &tailLabel, bool back_edge=false)
Definition view.cpp:172
std::string StructuralOutputToDot(rvsdg::StructuralOutput *structuralOutput, const ViewColors &color)
Definition view.cpp:164
ViewColors GetDefaultColor(std::unordered_map< T *, ViewColors > &map, T *elem, ViewColors def=BLACK)
Definition view.cpp:79
std::string ToDot(rvsdg::Region *region, std::unordered_map< rvsdg::Output *, ViewColors > &outputColor, std::unordered_map< rvsdg::Input *, ViewColors > &inputColor, std::unordered_map< rvsdg::Output *, ViewColors > &tailLabel)
Definition view.cpp:424
static std::string hex(size_t i)
Definition view.cpp:45
std::string ArgumentToDot(rvsdg::RegionArgument *argument, const ViewColors &color)
Definition view.cpp:140
std::string StructuralNodeToDot(rvsdg::StructuralNode *structuralNode, std::unordered_map< rvsdg::Output *, ViewColors > &outputColor, std::unordered_map< rvsdg::Input *, ViewColors > &inputColor, std::unordered_map< rvsdg::Output *, ViewColors > &tailLabel)
Definition view.cpp:219
std::string StructuralInputToDot(rvsdg::StructuralInput *structuralInput, const ViewColors &color)
Definition view.cpp:156
std::string ViewcolorToString(const ViewColors &color)
Definition view.cpp:22
bool isForbiddenChar(char c)
Definition base-hls.cpp:16
std::string SimpleNodeToDot(rvsdg::SimpleNode *simpleNode, std::unordered_map< rvsdg::Output *, ViewColors > &outputColor, std::unordered_map< rvsdg::Input *, ViewColors > &inputColor)
Definition view.cpp:272
static std::vector< jlm::rvsdg::Output * > outputs(const Node *node)
Definition node.hpp:1058
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
Definition node.hpp:872
detail::TopDownTraverserGeneric< false > TopDownTraverser
Traverser for visiting every node in a region in a top down order.
static std::string strfmt(Args... args)
Definition strfmt.hpp:35