 |
Cerata
A library to generate structural hardware designs
|
15 #include "cerata/dot/dot.h"
19 #include "cerata/logging.h"
20 #include "cerata/edge.h"
21 #include "cerata/type.h"
22 #include "cerata/output.h"
23 #include "cerata/utils.h"
24 #include "cerata/node.h"
25 #include "cerata/expression.h"
33 if (o.comp !=
nullptr) {
34 CERATA_LOG(DEBUG,
"DOT: Generating output for Graph: " + o.comp->name());
40 static std::string ToHex(
const Node &n) {
41 std::stringstream ret;
42 ret << std::hex << reinterpret_cast<uint64_t>(&n);
47 std::stringstream ret;
49 for (
const auto &e : all_edges) {
57 if ((dst ==
nullptr) || (src ==
nullptr)) {
61 if (dst->IsLiteral() || src->IsLiteral()) {
65 auto draw_style =
false;
69 auto srcname = ToHex(*src);
72 ret <<
"\"" + srcname +
"\"";
86 switch (src->type()->id()) {
94 if (src->array() && !dst->array()) {
95 sb <<
"label=\"" + std::to_string((*src->array())->IndexOf(*src)) +
"\"";
97 if (!src->array() && dst->array()) {
98 sb <<
"label=\"" + std::to_string((*dst->array())->IndexOf(*dst)) +
"\"";
100 if (src->array() && dst->array()) {
101 sb <<
"label=\"" + std::to_string((*src->array())->IndexOf(*src)) +
" to "
102 + std::to_string((*dst->array())->IndexOf(*dst)) +
"\"";
106 if (dst->IsSignal()) {
109 }
else if (dst->IsPort()) {
124 sb <<
"lhead=\"cluster_" +
NodeName(*src) +
"\"";
141 const std::string &name,
143 std::stringstream
str;
146 auto rec =
dynamic_cast<const Record &
>(t);
147 str << R
"(<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0")";
149 str << R
"( PORT="cell")";
159 str << R
"( PORT="cell")";
162 str << R"(<TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0">)";
163 for (
const auto &f : rec.fields()) {
170 str <<
"</TR></TABLE>";
174 auto vec =
dynamic_cast<const Vector &
>(t);
175 auto width = vec.
width();
177 str <<
"[" + width.value()->ToString() +
"]";
187 const std::string &name,
189 std::stringstream
str;
192 auto rec =
dynamic_cast<const Record &
>(t);
199 auto record_fields = rec.fields();
200 for (
const auto &f : record_fields) {
202 if (f != record_fields.back()) {
214 std::stringstream str;
230 std::stringstream ret;
231 auto nodes = graph.GetNodesOfType(
id);
232 auto arrays = graph.GetArraysOfType(
id);
233 if (!nodes.empty() || !arrays.empty()) {
235 ret <<
tab(level) <<
"subgraph cluster_" <<
sanitize(graph.name()) +
"_" +
ToString(
id) <<
" {\n";
237 ret <<
tab(level + 1) <<
"rankdir=LR;\n";
238 ret <<
tab(level + 1) <<
"label=\"\";\n";
242 for (
const auto &n : nodes) {
243 ret <<
GenNode(*n, level + no_group + 1);
245 for (
const auto &a : arrays) {
246 ret <<
GenNode(*a->base(), level + no_group + 1);
249 ret <<
tab(level) <<
"}\n";
256 std::stringstream ret;
260 ret <<
"digraph {\n";
264 ret <<
tab(level + 1) <<
"splines=ortho;\n";
265 ret <<
tab(level + 1) <<
"rankdir=LR;\n";
267 ret <<
tab(level) <<
"subgraph cluster_" <<
sanitize(graph.
name()) <<
" {\n";
268 ret <<
tab(level + 1) <<
"rankdir=TB;\n";
271 ret <<
tab(level + 1) <<
"label=\"" <<
sanitize(graph.
name()) <<
"\";\n";
291 auto &comp =
dynamic_cast<const Component &
>(graph);
292 if (!comp.children().empty()) {
297 for (
const auto &child : comp.children()) {
305 ret <<
tab(level) <<
"}\n";
312 std::ofstream out(path);
319 std::stringstream str;
322 if (!prefix.empty()) {
323 node_id = prefix +
"_";
325 node_id += ToHex(node);
328 str <<
"subgraph cluster_" +
NodeName(node) +
" {\n";
331 str <<
"\"" + node_id +
"\" [label=\"" +
sanitize(node.
name()) +
"\" ";
333 str <<
", color=red";
336 if (node.IsExpression()) {
337 auto expr =
dynamic_cast<const Expression &
>(node);
338 auto left_node_id = node_id +
"_" + ToHex(*expr.lhs());
339 auto right_node_id = node_id +
"_" + ToHex(*expr.rhs());
340 str <<
"\"" + node_id +
"\" -> \"" + left_node_id +
"\"\n";
341 str <<
"\"" + node_id +
"\" -> \"" + right_node_id +
"\"\n";
342 str <<
GenExpr(*expr.lhs(), node_id, level + 1);
343 str <<
GenExpr(*expr.rhs(), node_id, level + 1);
352 std::stringstream ret;
354 auto name = (*node.
parent())->name();
357 if (node.IsExpression()) {
359 }
else if (!node.
name().empty()) {
363 return sanitize(ret.str()) + suffix;
bool signals
Show signals.
struct cerata::dot::Config::NodeConfig nodes
Node configuration.
std::string tab(uint n)
Return indent string.
struct cerata::dot::Style::SubGraph subgraph
Style for sub graphs.
std::string subdir() override
Returns the subdirectory used by this OutputGenerator.
std::string root_dir_
The root directory to generate the output in.
std::vector< Edge * > GetAllEdges(const Graph &graph)
Obtain all edges in a graph.
Dot graph output generator.
str record
Record node color.
str param
Style for parameter edges.
@ LITERAL
No-input AND multi-output node with storage type and storage value.
std::string GenFile(const Graph &graph, const std::string &path)
Generate a DOT file.
bool expressions
Show expressions.
void Generate() override
Generate the DOT graphs.
A node representing a binary tree of other nodes.
str base
Base style for groups.
A graph representing a hardware structure.
str port_to_port
Style for port-to-port.
std::optional< Node * > width() const override
Return a pointer to the node representing the width of this vector, if specified.
A Record type containing zero or more fields.
str expr
Style for expressions.
static std::string GenExpr(const Node &exp, const std::string &prefix="", int level=0)
Generate expressions.
std::string GenNode(const Node &n, int level=0)
Generate a node.
bool IsComponent() const
Return true if this graph is a component, false otherwise.
std::string str
Short-hand for std::string.
str color
Color for groups.
std::string GetStyle(const Node &n)
Get the style for a node.
Convenience structure to build up dot styles.
bool parameters
Show parameters.
bool Is(ID type_id) const
Return true if the Type ID is type_id, false otherwise.
@ PARAMETER
Single-input AND multi-output node with default value.
str port_to_sig
Style for port-to-signal.
struct cerata::dot::Style::NodeGroup nodegroup
Style for group of nodes.
std::string GenNodes(const Graph &graph, Node::NodeID id, int level=0, bool no_group=false)
Generate nodes.
NodeID node_id() const
Return the node type ID.
std::string GenEdges(const Graph &graph, int level=0)
Generate edges.
std::string name() const
Return the name of the object.
NodeID
Node type IDs with different properties.
std::string ToString(Expression::Op operation)
Human-readable expression operator.
@ EXPRESSION
No-input AND multi-output node that forms a binary tree with operations and nodes.
Contains everything related to the DOT back-end.
struct cerata::dot::Style::NodeStyle node
Style for nodes.
struct cerata::dot::Config::NodeConfig::ExpandConfig expand
Configures what types of nodes to expand.
@ SIGNAL
Single-input AND multi-output node.
std::string GenGraph(const Graph &graph, int level=0)
Generate a graph.
struct cerata::dot::Style::EdgeStyle edge
Style for edges.
bool expression
Expand expressions.
void CreateDir(const std::string &dir_name)
Create a directory.
str base
Subgraph base style.
str sig_to_port
Style for signal-to-port.
std::string ToString()
Generate the style string.
bool Contains(const std::vector< std::shared_ptr< T >> &list, const std::shared_ptr< T > &item)
Return true if vector contains item, false otherwise.
std::vector< OutputSpec > outputs_
A list of things to put out.
Config config
Configuration of what types of constructs to show or hide for this style.
static std::string GenDotRecordCell(const Type &t, const std::string &name, int level=0)
Generate a DOT record cell from a type.
bool literals
Show literals.
str lit
Style for literal edges.
std::string sanitize(std::string in)
Sanitize a string for usage in DOT.
std::string NodeName(const Node &node, const std::string &suffix)
Return the DOT name of a node.
@ PORT
Single-input AND multi-output node with direction.
std::string GenHTMLTableCell(const Type &t, const std::string &name, int level=0)
Generate a HTML table cell from a type.
str record_child
Record child color.
virtual std::optional< Graph * > parent() const
Return the parent graph of this object, if any. Returns empty option otherwise.
struct cerata::dot::Style::NodeStyle::Colors color
Colors for specific nodes.
std::vector< Edge * > drawn_edges
Edges that were already drawn.