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>
10#include <jlm/rvsdg/region.hpp>
13#include <jlm/rvsdg/theta.hpp>
15#include <jlm/rvsdg/view.hpp>
16
17#include <algorithm>
18
19namespace jlm::hls
20{
21
22std::string
24{
25 switch (color)
26 {
27 case NONE:
28 return "";
29 break;
30
31 case BLACK:
32 return "black";
33 break;
34
35 case RED:
36 return "red";
37 break;
38
39 default:
40 JLM_UNREACHABLE("HLS view color not defined");
41 break;
42 }
43}
44
45static inline std::string
46hex(size_t i)
47{
48 std::stringstream stream;
49 stream << std::hex << i;
50 return stream.str();
51}
52
53std::string
55{
56 return util::strfmt("n", hex((intptr_t)node));
57}
58
59std::string
61{
62 if (dynamic_cast<rvsdg::RegionArgument *>(output))
63 {
64 return util::strfmt("a", hex((intptr_t)output), ":", "default");
65 }
66
68 {
69 return util::strfmt(GetDotName(simpleNode), ":", "o", hex((intptr_t)output));
70 }
71 else if (dynamic_cast<rvsdg::StructuralOutput *>(output))
72 {
73 return util::strfmt("so", hex((intptr_t)output), ":", "default");
74 }
75 JLM_UNREACHABLE("not implemented");
76}
77
78template<class T>
80GetDefaultColor(std::unordered_map<T *, ViewColors> & map, T * elem, ViewColors def = BLACK)
81{
82 auto f = map.find(elem);
83 if (f == map.end())
84 {
85 return def;
86 }
87 return f->second;
88}
89
90template<class T>
92GetDefaultLabel(std::unordered_map<T *, ViewColors> & map, T * elem, ViewColors def = NONE)
93{
94 auto f = map.find(elem);
95 if (f == map.end())
96 {
97 return def;
98 }
99 return f->second;
100}
101
102std::string
104{
105 if (dynamic_cast<rvsdg::RegionResult *>(input))
106 {
107 return util::strfmt("r", hex((intptr_t)input), ":", "default");
108 }
110 {
111 return util::strfmt(GetDotName(simpleNode), ":", "i", hex((intptr_t)input));
112 }
113 else if (dynamic_cast<rvsdg::StructuralInput *>(input))
114 {
115 return util::strfmt("si", hex((intptr_t)input), ":", "default");
116 }
117 JLM_UNREACHABLE("not implemented");
118}
119
120std::string
121PortToDot(const std::string & display_name, const std::string & dot_name, const ViewColors & color)
122{
123 auto dot =
125 + " [shape=plaintext label=<\n"
126 " <TABLE BORDER=\"0\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\">\n"
127 " <TR>\n"
128 " <TD PORT=\"default\" BORDER=\"1\" CELLPADDING=\"1\"><FONT "
129 "POINT-SIZE=\"10\">"
131 + "</FONT></TD>\n"
132 " </TR>\n"
133 " </TABLE>\n"
134 "> tooltip=\""
135 + dot_name + "\" color=" + ViewcolorToString(color) + " fontcolor=" + ViewcolorToString(color)
136 + "];\n";
137 return dot;
138}
139
140std::string
142{
143 auto display_name = util::strfmt("a", argument->index());
144 auto dot_name = util::strfmt("a", hex((intptr_t)argument));
146}
147
148std::string
150{
151 auto display_name = util::strfmt("r", result->index());
152 auto dot_name = util::strfmt("r", hex((intptr_t)result));
154}
155
156std::string
163
164std::string
171
172std::string
174 jlm::rvsdg::Output * output,
175 jlm::rvsdg::Input * input,
176 std::unordered_map<rvsdg::Output *, ViewColors> & tailLabel,
177 bool back_edge = false)
178{
179 auto color = "black";
181 if (!back_edge)
182 {
183 return GetDotName(output) + " -> " + GetDotName(input)
184 + " [style=\"\", arrowhead=\"normal\", color=" + color
185 + ", headlabel=<>, fontsize=15, labelangle=45, labeldistance=2.0, labelfontcolor=blue, "
186 "tooltip=\""
187 + output->Type()->debug_string() + "\", taillabel=\"" + ViewcolorToString(tailLabelColor)
188 + "\"];\n";
189 }
190 return GetDotName(input) + " -> " + GetDotName(output)
191 + " [style=\"\", arrowhead=\"normal\", color=" + color
192 + ", headlabel=<>, fontsize=15, labelangle=45, labeldistance=2.0, labelfontcolor=blue, "
193 "constraint=false, tooltip=\""
194 + output->Type()->debug_string() + "\", taillabel=\"" + ViewcolorToString(tailLabelColor)
195 + "\"];\n";
196}
197
198std::string
200{
201 auto color = "black";
202 return GetDotName(output) + " -> " + GetDotName(input)
203 + " [style=\"\", arrowhead=\"normal\", color=" + color
204 + ", headlabel=<>, fontsize=10, labelangle=45, labeldistance=2.0, labelfontcolor=black, "
205 "tooltip=\""
206 + output->Type()->debug_string() + "\"];\n";
207}
208
209static bool
210isForbiddenChar(char c)
211{
212 if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || '_' == c)
213 {
214 return false;
215 }
216 return true;
217}
218
219std::string
222 std::unordered_map<rvsdg::Output *, ViewColors> & outputColor,
223 std::unordered_map<rvsdg::Input *, ViewColors> & inputColor,
224 std::unordered_map<rvsdg::Output *, ViewColors> & tailLabel)
225{
226
227 std::ostringstream dot;
228 dot << "subgraph cluster_sn" << hex((intptr_t)structuralNode) << " {\n";
229 dot << "color=\"#ff8080\"\n";
230 dot << "penwidth=6\n";
231 dot << "label=\"" << structuralNode->DebugString() << "\"\n";
232 dot << "labeljust=l\n";
233
234 // input nodes
235 for (size_t i = 0; i < structuralNode->ninputs(); ++i)
236 {
238 structuralNode->input(i),
240 }
241
242 for (size_t i = 0; i < structuralNode->nsubregions(); ++i)
243 {
245 }
246
247 for (size_t i = 0; i < structuralNode->ninputs(); ++i)
248 {
249 for (auto & argument : structuralNode->input(i)->arguments)
250 {
251 dot << SymbolicEdge(structuralNode->input(i), &argument);
252 }
253 }
254
255 // output nodes
256 for (size_t i = 0; i < structuralNode->noutputs(); ++i)
257 {
259 structuralNode->output(i),
261 for (auto & result : structuralNode->output(i)->results)
262 {
263 dot << SymbolicEdge(&result, structuralNode->output(i));
264 }
265 }
266
267 dot << "}\n";
268
269 return dot.str();
270}
271
272std::string
275 std::unordered_map<rvsdg::Output *, ViewColors> & outputColor,
276 std::unordered_map<rvsdg::Input *, ViewColors> & inputColor)
277{
278 auto SPACER = " <TD WIDTH=\"10\"></TD>\n";
279 auto name = GetDotName(simpleNode);
280 auto opname = simpleNode->DebugString();
281 std::replace_if(opname.begin(), opname.end(), isForbiddenChar, '_');
282
283 std::ostringstream inputs;
284 // inputs
285 for (size_t i = 0; i < simpleNode->ninputs(); ++i)
286 {
288 if (i != 0)
289 {
290 inputs << SPACER;
291 }
292 inputs << " <TD PORT=\"i" << hex((intptr_t)simpleNode->input(i))
293 << "\" BORDER=\"1\" CELLPADDING=\"1\" COLOR=\"" << color
294 << "\"><FONT POINT-SIZE=\"10\" COLOR=\"" << color << "\"> i" << i << "</FONT></TD>\n";
295 }
296
297 std::ostringstream outputs;
298 // outputs
299 for (size_t i = 0; i < simpleNode->noutputs(); ++i)
300 {
302 if (i != 0)
303 {
304 outputs << SPACER;
305 }
306 outputs << " <TD PORT=\"o" << hex((intptr_t)simpleNode->output(i))
307 << "\" BORDER=\"1\" CELLPADDING=\"1\" COLOR=\"" << color
308 << "\"><FONT POINT-SIZE=\"10\" COLOR=\"" << color << "\"> o" << i << "</FONT></TD>\n";
309 }
310
311 std::string color = "black";
312 auto dot =
313 name
314 + " [shape=plaintext label=<\n"
315 "<TABLE BORDER=\"0\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\">\n"
316 // inputs
317 " <TR>\n"
318 " <TD BORDER=\"0\">\n"
319 " <TABLE BORDER=\"0\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\">\n"
320 " <TR>\n"
321 " <TD WIDTH=\"20\"></TD>\n"
322 + inputs.str()
323 + " <TD WIDTH=\"20\"></TD>\n"
324 " </TR>\n"
325 " </TABLE>\n"
326 " </TD>\n"
327 " </TR>\n"
328 " <TR>\n"
329 " <TD BORDER=\"3\" STYLE=\"ROUNDED\" CELLPADDING=\"4\">"
330 + opname + "<BR/><FONT POINT-SIZE=\"10\">" + name
331 + "</FONT></TD>\n"
332 " </TR>\n"
333 " <TR>\n"
334 " <TD BORDER=\"0\">\n"
335 " <TABLE BORDER=\"0\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\">\n"
336 " <TR>\n"
337 " <TD WIDTH=\"20\"></TD>\n"
338 + outputs.str()
339 + " <TD WIDTH=\"20\"></TD>\n"
340 " </TR>\n"
341 " </TABLE>\n"
342 " </TD>\n"
343 " </TR>\n"
344 "</TABLE>\n"
345 "> fontcolor="
346 + color + " color=" + color + "];\n";
347 return dot;
348}
349
350std::string
352 rvsdg::Region * region,
353 std::unordered_map<rvsdg::Output *, ViewColors> & outputColor,
354 std::unordered_map<rvsdg::Input *, ViewColors> & inputColor,
355 std::unordered_map<rvsdg::Output *, ViewColors> & tailLabel)
356{
357 std::ostringstream dot;
358 dot << "subgraph cluster_reg" << hex((intptr_t)region) << " {\n";
359 dot << "color=\"#80b3ff\"\n";
360 dot << "penwidth=6\n";
361 dot << "label=\"" << region->index() << " - " << hex((intptr_t)region) << "\"\n";
362
363 // argument nodes
364 dot << "{rank=source; ";
365 for (size_t i = 0; i < region->narguments(); ++i)
366 {
368 region->argument(i),
370 }
371 dot << "}\n";
372
373 // nodes
374 for (auto node : rvsdg::TopDownTraverser(region))
375 {
376 if (auto simpleNode = dynamic_cast<rvsdg::SimpleNode *>(node))
377 {
379 dot << node_dot;
380 }
381 else if (auto structuralNode = dynamic_cast<rvsdg::StructuralNode *>(node))
382 {
384 dot << node_dot;
385 }
386
387 for (size_t i = 0; i < node->ninputs(); ++i)
388 {
389 dot << Edge(node->input(i)->origin(), node->input(i), tailLabel);
390 }
391 }
392
393 // result nodes
394 dot << "{rank=sink; ";
395 for (size_t i = 0; i < region->nresults(); ++i)
396 {
397 dot << ResultToDot(
398 region->result(i),
400 }
401 dot << "}\n";
402
403 for (size_t i = 0; i < region->nresults(); ++i)
404 {
405 dot << Edge(region->result(i)->origin(), region->result(i), tailLabel);
406 }
407
408 if (region->node())
409 {
411 *region->node(),
412 [&](rvsdg::ThetaNode & theta)
413 {
414 for (auto & var : theta.GetLoopVars())
415 {
416 dot << Edge(var.pre, var.post, tailLabel, true);
417 }
418 },
419 [&](LoopNode & loop)
420 {
421 for (auto & var : loop.getBackEdgeVars())
422 {
423 dot << Edge(var.pre, var.post, tailLabel, true);
424 }
425 });
426 }
427
428 dot << "}\n";
429
430 return dot.str();
431}
432
433std::string
435 rvsdg::Region * region,
436 std::unordered_map<rvsdg::Output *, ViewColors> & outputColor,
437 std::unordered_map<rvsdg::Input *, ViewColors> & inputColor,
438 std::unordered_map<rvsdg::Output *, ViewColors> & tailLabel)
439{
440 std::ostringstream dot;
441 dot << "digraph G {\n";
442 dot << RegionToDot(region, outputColor, inputColor, tailLabel);
443 dot << "}\n";
444 return dot.str();
445}
446
447void
449 rvsdg::Region * region,
450 FILE * out,
451 std::unordered_map<rvsdg::Output *, ViewColors> & outputColor,
452 std::unordered_map<rvsdg::Input *, ViewColors> & inputColor,
453 std::unordered_map<rvsdg::Output *, ViewColors> & tailLabel)
454{
455 fputs(ToDot(region, outputColor, inputColor, tailLabel).c_str(), out);
456 fflush(out);
457}
458
459void
460ViewDot(rvsdg::Region * region, FILE * out)
461{
462 std::unordered_map<rvsdg::Output *, ViewColors> outputColor;
463 std::unordered_map<rvsdg::Input *, ViewColors> inputColor;
464 std::unordered_map<rvsdg::Output *, ViewColors> tailLabel;
465 ViewDot(region, out, outputColor, inputColor, tailLabel);
466}
467
468void
469DumpDot(llvm::LlvmRvsdgModule & rvsdgModule, const std::string & file_name)
470{
471 DumpDot(&rvsdgModule.Rvsdg().GetRootRegion(), file_name);
472}
473
474void
476 llvm::LlvmRvsdgModule & rvsdgModule,
477 const std::string & file_name,
478 std::unordered_map<rvsdg::Output *, ViewColors> outputColor,
479 std::unordered_map<rvsdg::Input *, ViewColors> inputColor,
480 std::unordered_map<rvsdg::Output *, ViewColors> tailLabel)
481{
482 DumpDot(&rvsdgModule.Rvsdg().GetRootRegion(), file_name, outputColor, inputColor, tailLabel);
483}
484
485void
486DumpDot(rvsdg::Region * region, const std::string & file_name)
487{
488 auto dot_file = fopen(file_name.c_str(), "w");
489 ViewDot(region, dot_file);
490 fclose(dot_file);
491}
492
493void
495 rvsdg::Region * region,
496 const std::string & file_name,
497 std::unordered_map<rvsdg::Output *, ViewColors> outputColor,
498 std::unordered_map<rvsdg::Input *, ViewColors> inputColor,
499 std::unordered_map<rvsdg::Output *, ViewColors> tailLabel)
500{
501 auto dot_file = fopen(file_name.c_str(), "w");
502 ViewDot(region, dot_file, outputColor, inputColor, tailLabel);
503 fclose(dot_file);
504}
505
506void
507DotToSvg(const std::string & file_name)
508{
509 auto cmd = "dot -Tsvg -O " + file_name;
510 if (system(cmd.c_str()))
511 exit(EXIT_FAILURE);
512}
513
514DumpDotTransformation::~DumpDotTransformation() noexcept = default;
515
519
520void
521DumpDotTransformation::Run(
522 rvsdg::RvsdgModule & rvsdgModule,
524{
525 const auto file = statisticsCollector.createOutputFile("rvsdg-graph.dot", true);
526 DumpDot(&rvsdgModule.Rvsdg().GetRootRegion(), file.path().to_str());
527}
528
529} // namespace jlm::hls
static jlm::util::StatisticsCollector statisticsCollector
Definition PullTests.cpp:17
Region & GetRootRegion() const noexcept
Definition graph.hpp:99
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
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
rvsdg::StructuralNode * node() const noexcept
Definition region.hpp:301
size_t narguments() const noexcept
Definition region.hpp:460
Graph & Rvsdg() noexcept
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:54
ViewColors GetDefaultLabel(std::unordered_map< T *, ViewColors > &map, T *elem, ViewColors def=NONE)
Definition view.cpp:92
std::string SymbolicEdge(rvsdg::Input *output, rvsdg::Output *input)
Definition view.cpp:199
void DumpDot(llvm::LlvmRvsdgModule &rvsdgModule, const std::string &file_name)
Definition view.cpp:469
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:351
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:149
std::string PortToDot(const std::string &display_name, const std::string &dot_name, const ViewColors &color)
Definition view.cpp:121
void DotToSvg(const std::string &file_name)
Definition view.cpp:507
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:448
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:173
std::string StructuralOutputToDot(rvsdg::StructuralOutput *structuralOutput, const ViewColors &color)
Definition view.cpp:165
ViewColors GetDefaultColor(std::unordered_map< T *, ViewColors > &map, T *elem, ViewColors def=BLACK)
Definition view.cpp:80
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:434
static std::string hex(size_t i)
Definition view.cpp:46
std::string ArgumentToDot(rvsdg::RegionArgument *argument, const ViewColors &color)
Definition view.cpp:141
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:220
std::string StructuralInputToDot(rvsdg::StructuralInput *structuralInput, const ViewColors &color)
Definition view.cpp:157
std::string ViewcolorToString(const ViewColors &color)
Definition view.cpp:23
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:273
void MatchType(T &obj, const Fns &... fns)
Pattern match over subclass type of given object.
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