|
degate 0.1.1
|
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 <tr1/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::tr1::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::tr1::dynamic_pointer_cast<Via>(o)) 00103 add_via(via); 00104 } 00105 00106 /* 00107 else if(Wire_shptr wire = std::tr1::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 }
1.7.4