HAL  v4.5.0-83-g30c8f0afc
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
gexf_writer.cpp
Go to the documentation of this file.
2 
6 #include "hal_core/netlist/net.h"
10 #include "hal_version.h"
11 
12 #include <QColor>
13 #include <QDate>
14 #include <QDebug>
15 #include <QFile>
16 
17 namespace hal
18 {
19  // needed for module color
20  extern NetlistRelay* gNetlistRelay;
21 
22  GexfWriter::GexfWriter() : mEdgeId(0)
23  {
24  std::set<std::string> plugins = plugin_manager::get_plugin_names();
25  mGuiLoaded = (plugins.find(std::string("hal_gui")) != plugins.end());
26  }
27 
28  Result<std::monostate> GexfWriter::write(Netlist* netlist, const std::filesystem::path& file_path)
29  {
30  if (netlist == nullptr)
31  {
32  return ERR("could not write netlist to GEXF file '" + file_path.string() + "': netlist is a 'nullptr'");
33  }
34  mNetlist = netlist;
35 
36  if (file_path.empty())
37  {
38  return ERR("could not write netlist to GEXF file '" + file_path.string() + "': file path is empty");
39  }
40  QString filename = QString::fromStdString(file_path);
41 
42  if (!filename.endsWith(".gexf"))
43  {
44  int pos = filename.lastIndexOf('.');
45  if (pos > 0)
46  filename.remove(pos, filename.size());
47  // TODO : handle dot in directory name
48  filename += ".gexf";
49  }
50  QFile of(filename);
51  if (!of.open(QIODevice::WriteOnly))
52  {
53  return ERR("could not write netlist to GEXF file '" + file_path.string() + "': failed to open file");
54  }
55  QXmlStreamWriter xmlOut(&of);
56  xmlOut.setAutoFormatting(true);
57  xmlOut.writeStartDocument();
58  xmlOut.writeStartElement("gexf");
59  xmlOut.writeAttribute("xmlns", "http://www.gexf.net/1.2draft");
60  // xmlOut.writeNamespace("http://www.gexf.net/1.2draft/viz"); // visualisation attributes
61  xmlOut.writeNamespace("http://www.w3.org/2001/XMLSchema-instance", "xsi");
62  xmlOut.writeAttribute("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation", "http://www.gexf.net/1.2draft http://www.gexf.net/1.2draft/gexf.xsd");
63  xmlOut.writeAttribute("version", "1.2");
64  writeMeta(xmlOut);
65  writeGraph(xmlOut);
66  xmlOut.writeEndElement();
67  xmlOut.writeEndDocument();
68  return OK({});
69  }
70 
71  void GexfWriter::writeMeta(QXmlStreamWriter& xmlOut) const
72  {
73  xmlOut.writeStartElement("meta");
74  xmlOut.writeAttribute("lastmodifieddate", QDate::currentDate().toString("yyyy-MM-dd"));
75  xmlOut.writeTextElement("creator", QString("hal %1.%2.%3").arg(hal_version::major).arg(hal_version::minor).arg(hal_version::patch));
76  xmlOut.writeEndElement();
77  }
78 
79  void GexfWriter::writeGraph(QXmlStreamWriter& xmlOut)
80  {
81  xmlOut.writeStartElement("graph");
82  xmlOut.writeAttribute("defaultedgetype", "directed");
83  xmlOut.writeAttribute("mode", "static");
84  // Edge attributes
85  xmlOut.writeStartElement("attributes");
86  xmlOut.writeAttribute("mode", "static");
87  xmlOut.writeAttribute("class", "edge");
88  writeAttribute(xmlOut, 3, "label", "string");
89  writeAttribute(xmlOut, 4, "hal_id", "long");
90  writeAttribute(xmlOut, 5, "source_pin", "string");
91  writeAttribute(xmlOut, 6, "destination_pin", "string");
92  writeAttribute(xmlOut, 7, "networkx_key", "long");
93  xmlOut.writeEndElement();
94  // Node attributes
95  xmlOut.writeStartElement("attributes");
96  xmlOut.writeAttribute("mode", "static");
97  xmlOut.writeAttribute("class", "node");
98  writeAttribute(xmlOut, 0, "type", "string");
99  writeAttribute(xmlOut, 1, "module", "string");
100  writeAttribute(xmlOut, 2, "INIT", "string");
101  xmlOut.writeEndElement();
102  // end attributes
103 
104  xmlOut.writeStartElement("nodes");
105  for (const Gate* g : mNetlist->get_gates())
106  writeNode(xmlOut, g);
107  xmlOut.writeEndElement();
108 
109  xmlOut.writeStartElement("edges");
110  for (const Net* n : mNetlist->get_nets())
111  writeEdge(xmlOut, n);
112  xmlOut.writeEndElement();
113  }
114 
115  void GexfWriter::writeAttribute(QXmlStreamWriter& xmlOut, int id, const QString& title, const QString& type) const
116  {
117  xmlOut.writeStartElement("attribute");
118  xmlOut.writeAttribute("id", QString::number(id));
119  xmlOut.writeAttribute("title", title);
120  xmlOut.writeAttribute("type", type);
121  xmlOut.writeEndElement();
122  }
123 
124  void GexfWriter::writeNode(QXmlStreamWriter& xmlOut, const Gate* g) const
125  {
126  xmlOut.writeStartElement("node");
127  xmlOut.writeAttribute("id", QString::number(g->get_id()));
128  xmlOut.writeAttribute("label", QString::fromStdString(g->get_name()));
129  writeColor(xmlOut, g);
130  xmlOut.writeStartElement("attvalues");
131  writeNodeAttribute(xmlOut, g, 0);
132  writeNodeAttribute(xmlOut, g, 1);
133  writeNodeAttribute(xmlOut, g, 2);
134  xmlOut.writeEndElement();
135  xmlOut.writeEndElement();
136  }
137 
138  void GexfWriter::writeColor(QXmlStreamWriter& xmlOut, const Gate* g) const
139  {
140  if (!mGuiLoaded)
141  return;
142 
143  if (!gNetlistRelay)
144  return;
145 
146  QColor col = gNetlistRelay->getModuleColor(g->get_module()->get_id());
147  if (!col.isValid())
148  return;
149  // xmlOut.writeStartElement("http://www.gexf.net/1.2draft/viz","color");
150  xmlOut.writeStartElement("color");
151  xmlOut.writeAttribute("r", QString::number(col.red()));
152  xmlOut.writeAttribute("g", QString::number(col.green()));
153  xmlOut.writeAttribute("b", QString::number(col.blue()));
154  xmlOut.writeEndElement();
155  }
156 
157  void GexfWriter::writeNodeAttribute(QXmlStreamWriter& xmlOut, const Gate* g, int inx) const
158  {
159  QString value;
160  switch (inx)
161  {
162  case 0:
163  value = QString::fromStdString(g->get_type()->get_name());
164  break;
165  case 1:
166  value = QString::fromStdString(g->get_module()->get_name());
167  break;
168  case 2:
169  for (const auto& [key, val] : g->get_data_map())
170  {
171  QString keyTxt = QString::fromStdString(std::get<1>(key));
172  if (keyTxt == "INIT")
173  {
174  value = QString::fromStdString(std::get<1>(val));
175  break;
176  }
177  }
178  break;
179  }
180 
181  if (value.isEmpty())
182  return;
183 
184  xmlOut.writeStartElement("attvalue");
185  xmlOut.writeAttribute("for", QString::number(inx));
186  xmlOut.writeAttribute("value", value);
187  xmlOut.writeEndElement();
188  }
189 
190  void GexfWriter::writeEdge(QXmlStreamWriter& xmlOut, const Net* n)
191  {
192  for (const Endpoint* epSrc : n->get_sources())
193  {
194  Gate* gSrc = epSrc->get_gate();
195  if (!gSrc)
196  continue;
197 
198  for (const Endpoint* epDst : n->get_destinations())
199  {
200  Gate* gDst = epDst->get_gate();
201  if (!gDst)
202  continue;
203 
204  xmlOut.writeStartElement("edge");
205  xmlOut.writeAttribute("source", QString::number(gSrc->get_id()));
206  xmlOut.writeAttribute("target", QString::number(gDst->get_id()));
207  xmlOut.writeAttribute("id", QString::number(mEdgeId++));
208  xmlOut.writeStartElement("attvalues");
209  writeEdgeAttribute(xmlOut, n, 3);
210  writeEdgeAttribute(xmlOut, n, 4);
211  writeEdgeAttribute(xmlOut, n, 5, epSrc->get_pin()->get_name());
212  writeEdgeAttribute(xmlOut, n, 6, epDst->get_pin()->get_name());
213  writeEdgeAttribute(xmlOut, n, 7);
214  xmlOut.writeEndElement();
215  xmlOut.writeEndElement();
216  }
217  }
218  }
219 
220  void GexfWriter::writeEdgeAttribute(QXmlStreamWriter& xmlOut, const Net* n, int inx, const std::string pin) const
221  {
222  QString value;
223  switch (inx)
224  {
225  case 3:
226  value = QString::fromStdString(n->get_name());
227  break;
228  case 4:
229  value = QString::number(n->get_id());
230  break;
231  case 5:
232  case 6:
233  value = QString::fromStdString(pin);
234  break;
235  case 7:
236  value = "0";
237  break; // networkx_key
238  }
239 
240  if (value.isEmpty())
241  return;
242 
243  xmlOut.writeStartElement("attvalue");
244  xmlOut.writeAttribute("for", QString::number(inx));
245  xmlOut.writeAttribute("value", value);
246  xmlOut.writeEndElement();
247  }
248 
249 } // namespace hal
Result< std::monostate > write(Netlist *netlist, const std::filesystem::path &file_path) override
Definition: gexf_writer.cpp:28
const std::vector< Gate * > & get_gates() const
Definition: netlist.cpp:204
const std::vector< Net * > & get_nets() const
Definition: netlist.cpp:364
QColor getModuleColor(const u32 id)
#define ERR(message)
Definition: result.h:60
#define OK(...)
Definition: result.h:56
std::set< std::string > get_plugin_names()
Definition: defines.h:45
NetlistRelay * gNetlistRelay
Definition: gui_globals.h:74
PinType type
int blue() const const
int green() const const
bool isValid() const const
int red() const const
QDate currentDate()
virtual bool open(QIODevice::OpenMode mode) override
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const const
QString fromStdString(const std::string &str)
bool isEmpty() const const
int lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
QString number(int n, int base)
QString & remove(int position, int n)
int size() const const
void setAutoFormatting(bool enable)
void writeAttribute(const QString &qualifiedName, const QString &value)
void writeEndDocument()
void writeEndElement()
void writeNamespace(const QString &namespaceUri, const QString &prefix)
void writeStartDocument()
void writeStartElement(const QString &qualifiedName)
void writeTextElement(const QString &qualifiedName, const QString &text)