1 /* Copyright (c) 2009-2021. The SimGrid Team.
2 * All rights reserved. */
4 /* This program is free software; you can redistribute it and/or modify it
5 * under the terms of the license (GNU LGPL) which comes with this package. */
7 #include "simdag_private.hpp"
8 #include "simgrid/s4u/Activity.hpp"
9 #include "simgrid/s4u/Comm.hpp"
10 #include "simgrid/s4u/Engine.hpp"
11 #include "simgrid/s4u/Exec.hpp"
12 #include "src/internal_config.h"
13 #include "xbt/file.hpp"
16 #include <unordered_map>
20 #include <graphviz/cgraph.h>
22 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(sd_dotparse, sd, "Parsing DOT files");
27 std::vector<ActivityPtr> create_DAG_from_dot(const std::string& filename)
29 FILE* in_file = fopen(filename.c_str(), "r");
30 xbt_assert(in_file != nullptr, "Failed to open file: %s", filename.c_str());
32 Agraph_t* dag_dot = agread(in_file, NIL(Agdisc_t*));
34 std::unordered_map<std::string, ActivityPtr> activities;
35 std::vector<ActivityPtr> dag;
40 /* Create all the nodes */
41 Agnode_t* node = nullptr;
42 for (node = agfstnode(dag_dot); node; node = agnxtnode(dag_dot, node)) {
43 char* name = agnameof(node);
44 double amount = atof(agget(node, (char*)"size"));
46 if (activities.find(name) == activities.end()) {
47 XBT_DEBUG("See <Exec id = %s amount = %.0f>", name, amount);
48 act = Exec::init()->set_name(name)->set_flops_amount(amount)->vetoable_start();
49 activities.insert({std::string(name), act});
50 if (strcmp(name, "root") && strcmp(name, "end"))
53 XBT_WARN("Exec '%s' is defined more than once", name);
56 /*Check if 'root' and 'end' nodes have been explicitly declared. If not, create them. */
57 if (activities.find("root") == activities.end())
58 root = Exec::init()->set_name("root")->set_flops_amount(0)->vetoable_start();
60 root = activities.at("root");
62 if (activities.find("end") == activities.end())
63 end = Exec::init()->set_name("end")->set_flops_amount(0)->vetoable_start();
65 end = activities.at("end");
68 std::vector<Agedge_t*> edges;
69 for (node = agfstnode(dag_dot); node; node = agnxtnode(dag_dot, node)) {
71 for (Agedge_t* edge = agfstout(dag_dot, node); edge; edge = agnxtout(dag_dot, edge))
72 edges.push_back(edge);
74 /* Be sure edges are sorted */
75 std::sort(edges.begin(), edges.end(), [](const Agedge_t* a, const Agedge_t* b) { return AGSEQ(a) < AGSEQ(b); });
77 for (Agedge_t* edge : edges) {
78 const char* src_name = agnameof(agtail(edge));
79 const char* dst_name = agnameof(aghead(edge));
80 double size = atof(agget(edge, (char*)"size"));
82 ActivityPtr src = activities.at(src_name);
83 ActivityPtr dst = activities.at(dst_name);
85 std::string name = std::string(src_name) + "->" + dst_name;
86 XBT_DEBUG("See <Comm id=%s amount = %.0f>", name.c_str(), size);
87 if (activities.find(name) == activities.end()) {
88 act = Comm::sendto_init()->set_name(name)->set_payload_size(size)->vetoable_start();
89 src->add_successor(act);
90 act->add_successor(dst);
91 activities.insert({name, act});
94 XBT_WARN("Comm '%s' is defined more than once", name.c_str());
97 src->add_successor(dst);
102 XBT_DEBUG("All activities have been created, put %s at the beginning and %s at the end", root->get_cname(),
104 dag.insert(dag.begin(), root);
107 /* Connect entry tasks to 'root', and exit tasks to 'end'*/
108 for (const auto& a : dag) {
109 if (a->dependencies_solved() && a != root) {
110 XBT_DEBUG("Activity '%s' has no dependencies. Add dependency from 'root'", a->get_cname());
111 root->add_successor(a);
114 if (a->is_waited_by() == 0 && a != end) {
115 XBT_DEBUG("Activity '%s' has no successors. Add dependency to 'end'", a->get_cname());
116 a->add_successor(end);
122 if (not check_for_cycle(dag)) {
123 std::string base = simgrid::xbt::Path(filename).get_base_name();
124 XBT_ERROR("The DOT described in %s is not a DAG. It contains a cycle.", base.c_str());
125 for (const auto& a : dag)
134 } // namespace simgrid
139 std::vector<ActivityPtr> create_DAG_from_dot(const std::string& filename)
141 xbt_die("create_DAG_from_dot() is not usable because graphviz was not found.\n"
142 "Please install graphviz, graphviz-dev, and libgraphviz-dev (and erase CMakeCache.txt) before recompiling.");
145 } // namespace simgrid