degate  0.1.2
LogicModelDOTExporter.cc
Go to the documentation of this file.
00001 /*
00002 
00003   This file is part of the IC reverse engineering tool degate.
00004 
00005   Copyright 2008, 2009, 2010 by Martin Schobert
00006 
00007   Degate is free software: you can redistribute it and/or modify
00008   it under the terms of the GNU General Public License as published by
00009   the Free Software Foundation, either version 3 of the License, or
00010   any later version.
00011 
00012   Degate is distributed in the hope that it will be useful,
00013   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015   GNU General Public License for more details.
00016 
00017   You should have received a copy of the GNU General Public License
00018   along with degate. If not, see <http://www.gnu.org/licenses/>.
00019 
00020 */
00021 
00022 #include <degate.h>
00023 #include "LogicModelDOTExporter.h"
00024 #include "DOTAttributes.h"
00025 #include "FileSystem.h"
00026 
00027 #include <sys/types.h>
00028 #include <sys/stat.h>
00029 #include <unistd.h>
00030 #include <errno.h>
00031 
00032 #include <string>
00033 #include <iostream>
00034 #include <sstream>
00035 #include <stdexcept>
00036 #include <list>
00037 #include <memory>
00038 
00039 using namespace std;
00040 using namespace degate;
00041 
00042 #define MAX_NODES 7
00043 
00044 void LogicModelDOTExporter::export_data(std::string const& filename, LogicModel_shptr lmodel) {
00045 
00046   if(lmodel == NULL) throw InvalidPointerException("Logic model pointer is NULL.");
00047 
00048   /* Calculate a scaling, so that we can use pixel coordinates from the logic model
00049      as dot coordinates.
00050 
00051   scaling = (
00052              21.0 // cm  -- the width of an A4 paper
00053               / 2.54 // cm/inch
00054              * (double)get_dots_per_inch() // dots/inch
00055              ) / (double)(lmodel->get_width());
00056 
00057   */
00058 
00059   debug(TM, "scaling: %f", scaling);
00060   string basename(get_basename(filename));
00061   std::ostringstream stm;
00062   stm << "time neato -v -Tsvg"
00063     //<< " -Gdpi=" << get_dots_per_inch()
00064       << " -o " << basename
00065       << ".svg " << basename << ".dot";
00066 
00067 
00068   add_header_line("");
00069   add_header_line("This is a logic model export.");
00070   add_header_line("");
00071   add_header_line("You can generate an image of this graph with:");
00072   add_header_line(stm.str());
00073   add_header_line("");
00074 
00075   add_graph_setting("");
00076 
00077   try {
00078 
00079     // iterate over nets
00080     if(properties[ENABLE_EDGES]) {
00081       for(LogicModel::net_collection::iterator net_iter = lmodel->nets_begin();
00082           net_iter != lmodel->nets_end(); ++net_iter) {
00083         Net_shptr net = (*net_iter).second;
00084         if(net->size() < MAX_NODES)
00085           add_net(net);
00086       }
00087     }
00088 
00089     // iterate over logic model objects
00090     for(LogicModel::object_collection::iterator iter = lmodel->objects_begin();
00091         iter != lmodel->objects_end(); ++iter) {
00092 
00093       PlacedLogicModelObject_shptr o = (*iter).second;
00094 
00095       if(Gate_shptr gate = std::dynamic_pointer_cast<Gate>(o)) {
00096         // check if the gate should be rendered
00097         //if(accept_gate_for_output)
00098         add_gate(gate);
00099       }
00100 
00101       else if(properties[ENABLE_VIAS]) {
00102         if(Via_shptr via = std::dynamic_pointer_cast<Via>(o))
00103           add_via(via);
00104       }
00105 
00106       /*
00107         else if(Wire_shptr wire = std::dynamic_pointer_cast<Wire>(o))
00108           add_wire(wires_elem, wire, layer_pos);
00109 
00110       */
00111     }
00112 
00113     dump_to_file(filename);
00114 
00115   }
00116   catch(const std::exception& ex) {
00117     std::cout << "Exception caught: " << ex.what() << std::endl;
00118     throw;
00119   }
00120 
00121 }
00122 
00123 std::string LogicModelDOTExporter::oid_to_str(std::string const& prefix, object_id_t oid) {
00124   std::ostringstream stm;
00125   stm << prefix << oid_rewriter->get_new_object_id(oid);
00126   return stm.str();
00127 }
00128 
00129 void LogicModelDOTExporter::add_net(Net_shptr net) {
00130 
00131   string net_name(oid_to_str("N", net->get_object_id()));
00132 
00133   DOTAttributes attrs;
00134   //attrs.add("label", net_name);
00135   attrs.add("shape", "point");
00136 
00137   add_node(net_name, attrs.get_string());
00138 
00139 }
00140 
00141 std::string LogicModelDOTExporter::add_implicit_net(Net_shptr net) {
00142 
00143   object_id_t new_oid = net->get_object_id();
00144   string net_name(oid_to_str("N", new_oid));
00145 
00146   if(implicit_net_counter.find(new_oid) == implicit_net_counter.end())
00147     implicit_net_counter[new_oid] = 1;
00148   else
00149     implicit_net_counter[new_oid]++;
00150 
00151 
00152   DOTAttributes attrs;
00153   attrs.add("label", net_name);
00154   attrs.add("shape", "box");
00155   attrs.add("color", "red");
00156 
00157   std::ostringstream stm;
00158   stm << net_name << "_" << implicit_net_counter[new_oid];
00159 
00160 
00161   add_node(stm.str(), attrs.get_string());
00162   return stm.str();
00163 
00164 }
00165 
00166 
00167 void LogicModelDOTExporter::add_gate(Gate_shptr gate) {
00168 
00169   string node_name(oid_to_str("G", gate->get_object_id()));
00170 
00171   std::ostringstream stm;
00172   stm << (gate->has_name() ? gate->get_name() : node_name);
00173 
00174   if(get_property(ENABLE_TEMPLATE_NAMES) && gate->has_template()) {
00175     const GateTemplate_shptr tmpl = gate->get_gate_template();
00176     stm << "\\n" << tmpl->get_name();
00177   }
00178 
00179   string gate_name(stm.str());
00180 
00181   DOTAttributes attrs;
00182   attrs.add("label", gate_name);
00183   attrs.add("shape", "component");
00184 
00185   if(get_fontsize() > 0)
00186     attrs.add_number<unsigned int>("fontsize", get_fontsize());
00187 
00188   if(get_penwidth() > 0)
00189     attrs.add_number<unsigned int>("penwidth", get_penwidth());
00190 
00191   if(properties[PRESERVE_GATE_POSITIONS]) {
00192     attrs.add_number<unsigned int>("height", lround(scaling*gate->get_height()));
00193     attrs.add_number<unsigned int>("width", lround(scaling*gate->get_width()));
00194   }
00195 
00196   /* Use the placement on the chip as hint for graphviz. Graphviz
00197      might benefit from this.
00198   */
00199   attrs.add_position(lround(scaling*gate->get_center_x()),
00200                      lround(scaling*gate->get_center_y()),
00201                      properties[PRESERVE_GATE_POSITIONS]);
00202 
00203 
00204   if(properties[ENABLE_COLORS] &&
00205      (MASK_R(gate->get_fill_color()) != 0 ||
00206       MASK_G(gate->get_fill_color()) != 0 ||
00207       MASK_B(gate->get_fill_color()) != 0 ))
00208     attrs.add("color", to_color_string(gate->get_fill_color()));
00209 
00210   if(properties[PRESERVE_GATE_POSITIONS])
00211     attrs.add("fixedsize", "true");
00212 
00213   add_node(node_name, attrs.get_string());
00214 
00215 
00216 
00217   if(properties[ENABLE_EDGES]) {
00218     for(Gate::port_iterator piter = gate->ports_begin();
00219         piter != gate->ports_end(); ++piter) {
00220       GatePort_shptr gate_port = *piter;
00221 
00222       add_connection(gate_port->get_net(), node_name,
00223                      gate_port->get_template_port()->get_name());
00224 
00225 
00226     }
00227   }
00228 
00229 
00230 }
00231 
00232 
00233 void LogicModelDOTExporter::add_connection(Net_shptr net,
00234                                            std::string const& src_name,
00235                                            std::string const& edge_name) {
00236 
00237   string net_name(oid_to_str("N", net->get_object_id()));
00238 
00239   DOTAttributes edge_attrs;
00240   edge_attrs.add("taillabel", edge_name);
00241 
00242   if(net->size() < MAX_NODES)
00243     add_edge(src_name, net_name,  edge_attrs.get_string());
00244   else {
00245     string implicit_net_name = add_implicit_net(net);
00246     edge_attrs.add("color", "red");
00247     add_edge(src_name, implicit_net_name, edge_attrs.get_string());
00248   }
00249 
00250 }
00251 
00252 
00253 void LogicModelDOTExporter::add_via(Via_shptr via) {
00254 
00255   string via_name(oid_to_str("V", via->get_object_id()));
00256 
00257   DOTAttributes attrs;
00258   attrs.add("label", via_name);
00259   attrs.add("shape", "box");
00260 
00261   if(get_fontsize() > 0)
00262     attrs.add_number<unsigned int>("fontsize", get_fontsize());
00263   if(get_penwidth() > 0)
00264     attrs.add_number<unsigned int>("penwidth", get_penwidth());
00265 
00266   add_node(via_name, attrs.get_string());
00267 
00268   if(properties[ENABLE_EDGES])
00269     add_connection(via->get_net(), via_name, "");
00270 }