degate  0.1.2
LogicModelImporter.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 <LogicModelImporter.h>
00024 #include <SubProjectAnnotation.h>
00025 
00026 #include <sys/types.h>
00027 #include <sys/stat.h>
00028 #include <unistd.h>
00029 #include <errno.h>
00030 
00031 #include <memory>
00032 #include <string>
00033 #include <iostream>
00034 #include <sstream>
00035 #include <stdexcept>
00036 #include <list>
00037 
00038 #include <boost/format.hpp>
00039 #include <boost/foreach.hpp>
00040 
00041 using namespace std;
00042 using namespace degate;
00043 
00044 void LogicModelImporter::import_into(LogicModel_shptr lmodel,
00045                                      std::string const& filename) {
00046   if(RET_IS_NOT_OK(check_file(filename))) {
00047     debug(TM, "Problem: file %s not found.", filename.c_str());
00048     throw InvalidPathException("Can't load logic model from file.");
00049   }
00050 
00051   try {
00052     //debug(TM, "try to parse file %s", filename.c_str());
00053 
00054     xmlpp::DomParser parser;
00055     parser.set_substitute_entities(); // We just want the text to be resolved/unescaped automatically.
00056 
00057     parser.parse_file(filename);
00058     assert(parser == true);
00059 
00060     const xmlpp::Document * doc = parser.get_document();
00061     assert(doc != NULL);
00062 
00063     const xmlpp::Element * root_elem = doc->get_root_node(); // deleted by DomParser
00064     assert(root_elem != NULL);
00065 
00066     lmodel->set_gate_library(gate_library);
00067 
00068     parse_logic_model_element(root_elem, lmodel);
00069 
00070     // check if the ports of placed standard cell are available and create them if necessary
00071     BOOST_FOREACH(Gate_shptr g, gates) {
00072       lmodel->update_ports(g);
00073     }
00074 
00075   }
00076   catch(const std::exception& ex) {
00077     std::cout << "Exception caught: " << ex.what() << std::endl;
00078     throw;
00079   }
00080 
00081 }
00082 
00083 LogicModel_shptr LogicModelImporter::import(std::string const& filename) {
00084 
00085   LogicModel_shptr lmodel(new LogicModel(width, height));
00086   assert(lmodel != NULL);
00087 
00088   import_into(lmodel, filename);
00089 
00090   return lmodel;
00091 }
00092 
00093 void LogicModelImporter::parse_logic_model_element(const xmlpp::Element * const lm_elem,
00094                                                    LogicModel_shptr lmodel) {
00095 
00096 
00097   const xmlpp::Element * gates_elem = get_dom_twig(lm_elem, "gates");
00098   if(gates_elem != NULL) parse_gates_element(gates_elem, lmodel);
00099 
00100   const xmlpp::Element * vias_elem = get_dom_twig(lm_elem, "vias");
00101   if(vias_elem != NULL) parse_vias_element(vias_elem, lmodel);
00102 
00103   const xmlpp::Element * emarkers_elem = get_dom_twig(lm_elem, "emarkers");
00104   if(emarkers_elem != NULL) parse_emarkers_element(emarkers_elem, lmodel);
00105 
00106   const xmlpp::Element * wires_elem = get_dom_twig(lm_elem, "wires");
00107   if(wires_elem != NULL) parse_wires_element(wires_elem, lmodel);
00108 
00109   const xmlpp::Element * nets_elem = get_dom_twig(lm_elem, "nets");
00110   if(nets_elem != NULL) parse_nets_element(nets_elem, lmodel);
00111 
00112   const xmlpp::Element * annotations_elem = get_dom_twig(lm_elem, "annotations");
00113   if(annotations_elem != NULL) parse_annotations_element(annotations_elem, lmodel);
00114 
00115   const xmlpp::Element * modules_elem = get_dom_twig(lm_elem, "modules");
00116   if(modules_elem != NULL) {
00117     std::list<Module_shptr> mods = parse_modules_element(modules_elem, lmodel);
00118     assert(mods.size() == 1);    
00119     lmodel->set_main_module(mods.front());
00120   }
00121 
00122 }
00123 
00124 void LogicModelImporter::parse_nets_element(const xmlpp::Element * const nets_element,
00125                                             LogicModel_shptr lmodel) {
00126 
00127   if(nets_element == NULL || lmodel == NULL)
00128     throw InvalidPointerException("Got a NULL pointer in  LogicModelImporter::parse_nets_element()");
00129 
00130   const xmlpp::Node::NodeList net_list = nets_element->get_children("net");
00131   for(xmlpp::Node::NodeList::const_iterator iter = net_list.begin();
00132       iter != net_list.end();
00133       ++iter) {
00134 
00135     int object_counter = 0;
00136     if(const xmlpp::Element* net_elem = dynamic_cast<const xmlpp::Element*>(*iter)) {
00137 
00138       object_id_t net_id = parse_number<object_id_t>(net_elem, "id");
00139 
00140       Net_shptr net(new Net());
00141       net->set_object_id(net_id);
00142 
00143       const xmlpp::Node::NodeList connection_list = net_elem->get_children("connection");
00144       for(xmlpp::Node::NodeList::const_iterator iter2 = connection_list.begin();
00145           iter2 != connection_list.end();
00146           ++iter2) {
00147 
00148         if(const xmlpp::Element* conn_elem = dynamic_cast<const xmlpp::Element*>(*iter2)) {
00149 
00150           object_id_t object_id = parse_number<object_id_t>(conn_elem, "object-id");
00151 
00152           // add connection
00153           try {
00154             PlacedLogicModelObject_shptr placed_object = lmodel->get_object(object_id);
00155             if(placed_object == NULL) {
00156               debug(TM,
00157                     "Failed to lookup logic model object %d. Can't connect it to net %d.",
00158                     object_id, net_id);
00159             }
00160             else {
00161               ConnectedLogicModelObject_shptr o =
00162                 std::dynamic_pointer_cast<ConnectedLogicModelObject>(placed_object);
00163               if(o != NULL) {
00164                 o->set_net(net);
00165               }
00166               else {
00167                 debug(TM, "Failed to dynamic_cast<> a logic model object with ID %d", object_id);
00168               }
00169             }
00170 
00171           }
00172           catch(CollectionLookupException const & ex) {
00173             debug(TM,
00174                   "Failed to insert a connection for net %d into the logic layer. "
00175                   "Can't lookup logic model object %d that should be connected to that net.",
00176                   net_id, object_id);
00177             throw; // rethrow
00178           }
00179         } // end of if
00180 
00181         object_counter++;
00182       } // end of for
00183 
00184       if(object_counter < 2) {
00185         boost::format f("Net with ID %1% has only a single object. This should not occur.");
00186         f % net_id;
00187         std::cout << "WARNING: " << f.str() << std::endl;
00188         //throw DegateLogicException(f.str());
00189       }
00190       lmodel->add_net(net);
00191     }
00192   }
00193 }
00194 
00195 void LogicModelImporter::parse_wires_element(const xmlpp::Element * const wires_element,
00196                                             LogicModel_shptr lmodel) {
00197 
00198   if(wires_element == NULL || lmodel == NULL)
00199     throw InvalidPointerException("Null pointer in LogicModelImporter::parse_wires_element()");
00200 
00201   const xmlpp::Node::NodeList wire_list = wires_element->get_children("wire");
00202   for(xmlpp::Node::NodeList::const_iterator iter = wire_list.begin();
00203       iter != wire_list.end();
00204       ++iter) {
00205 
00206     if(const xmlpp::Element* wire_elem = dynamic_cast<const xmlpp::Element*>(*iter)) {
00207 
00208       // XXX PORT ID REPLACER ...
00209 
00210       object_id_t object_id = parse_number<object_id_t>(wire_elem, "id");
00211       int from_x = parse_number<int>(wire_elem, "from-x");
00212       int from_y = parse_number<int>(wire_elem, "from-y");
00213       int to_x = parse_number<int>(wire_elem, "to-x");
00214       int to_y = parse_number<int>(wire_elem, "to-y");
00215       int diameter = parse_number<int>(wire_elem, "diameter");
00216       int layer = parse_number<int>(wire_elem, "layer");
00217       int remote_id = parse_number<object_id_t>(wire_elem, "remote-id", 0);
00218 
00219       const Glib::ustring name(wire_elem->get_attribute_value("name"));
00220       const Glib::ustring description(wire_elem->get_attribute_value("description"));
00221       const Glib::ustring fill_color_str(wire_elem->get_attribute_value("fill-color"));
00222       const Glib::ustring frame_color_str(wire_elem->get_attribute_value("frame-color"));
00223 
00224 
00225       Wire_shptr wire(new Wire(from_x, from_y, to_x, to_y, diameter));
00226       wire->set_name(name.c_str());
00227       wire->set_description(description.c_str());
00228       wire->set_object_id(object_id);
00229       wire->set_fill_color(parse_color_string(fill_color_str));
00230       wire->set_frame_color(parse_color_string(frame_color_str));
00231 
00232       wire->set_remote_object_id(remote_id);
00233       lmodel->add_object(layer, wire);
00234     }
00235   }
00236 }
00237 
00238 void LogicModelImporter::parse_vias_element(const xmlpp::Element * const vias_element,
00239                                             LogicModel_shptr lmodel) {
00240 
00241   if(vias_element == NULL || lmodel == NULL) throw InvalidPointerException();
00242 
00243   const xmlpp::Node::NodeList via_list = vias_element->get_children("via");
00244   for(xmlpp::Node::NodeList::const_iterator iter = via_list.begin();
00245       iter != via_list.end();
00246       ++iter) {
00247 
00248     if(const xmlpp::Element* via_elem = dynamic_cast<const xmlpp::Element*>(*iter)) {
00249 
00250       // XXX PORT ID REPLACER ...
00251 
00252       object_id_t object_id = parse_number<object_id_t>(via_elem, "id");
00253       int x = parse_number<int>(via_elem, "x");
00254       int y = parse_number<int>(via_elem, "y");
00255       int diameter = parse_number<int>(via_elem, "diameter");
00256       int layer = parse_number<int>(via_elem, "layer");
00257       int remote_id = parse_number<object_id_t>(via_elem, "remote-id", 0);
00258 
00259       const Glib::ustring name(via_elem->get_attribute_value("name"));
00260       const Glib::ustring description(via_elem->get_attribute_value("description"));
00261       const Glib::ustring fill_color_str(via_elem->get_attribute_value("fill-color"));
00262       const Glib::ustring frame_color_str(via_elem->get_attribute_value("frame-color"));
00263       const Glib::ustring direction_str(via_elem->get_attribute_value("direction").lowercase());
00264 
00265       Via::DIRECTION direction;
00266       if(direction_str == "undefined") direction = Via::DIRECTION_UNDEFINED;
00267       else if(direction_str == "up") direction = Via::DIRECTION_UP;
00268       else if(direction_str == "down") direction = Via::DIRECTION_DOWN;
00269       else {
00270         boost::format f("Can't parse via direction type: %1%");
00271         f % direction_str;
00272         throw XMLAttributeParseException(f.str());
00273       }
00274 
00275       Via_shptr via(new Via(x, y, diameter, direction));
00276       via->set_name(name.c_str());
00277       via->set_description(description.c_str());
00278       via->set_object_id(object_id);
00279       via->set_fill_color(parse_color_string(fill_color_str));
00280       via->set_frame_color(parse_color_string(frame_color_str));
00281 
00282       via->set_remote_object_id(remote_id);
00283 
00284       lmodel->add_object(layer, via);
00285     }
00286   }
00287 }
00288 
00289 void LogicModelImporter::parse_emarkers_element(const xmlpp::Element * const emarkers_element,
00290                                                 LogicModel_shptr lmodel) {
00291 
00292   if(emarkers_element == NULL || lmodel == NULL) throw InvalidPointerException();
00293 
00294   const xmlpp::Node::NodeList emarker_list = emarkers_element->get_children("emarker");
00295   for(xmlpp::Node::NodeList::const_iterator iter = emarker_list.begin();
00296       iter != emarker_list.end();
00297       ++iter) {
00298 
00299     if(const xmlpp::Element* emarker_elem = dynamic_cast<const xmlpp::Element*>(*iter)) {
00300 
00301       // XXX PORT ID REPLACER ...
00302 
00303       object_id_t object_id = parse_number<object_id_t>(emarker_elem, "id");
00304       int x = parse_number<int>(emarker_elem, "x");
00305       int y = parse_number<int>(emarker_elem, "y");
00306       int diameter = parse_number<diameter_t>(emarker_elem, "diameter");
00307       int layer = parse_number<int>(emarker_elem, "layer");
00308       int remote_id = parse_number<object_id_t>(emarker_elem, "remote-id", 0);
00309 
00310       const Glib::ustring name(emarker_elem->get_attribute_value("name"));
00311       const Glib::ustring description(emarker_elem->get_attribute_value("description"));
00312       const Glib::ustring fill_color_str(emarker_elem->get_attribute_value("fill-color"));
00313       const Glib::ustring frame_color_str(emarker_elem->get_attribute_value("frame-color"));
00314       const Glib::ustring direction_str(emarker_elem->get_attribute_value("direction").lowercase());
00315 
00316       EMarker_shptr emarker(new EMarker(x, y, diameter));
00317       emarker->set_name(name.c_str());
00318       emarker->set_description(description.c_str());
00319       emarker->set_object_id(object_id);
00320       emarker->set_fill_color(parse_color_string(fill_color_str));
00321       emarker->set_frame_color(parse_color_string(frame_color_str));
00322 
00323       emarker->set_remote_object_id(remote_id);
00324 
00325       lmodel->add_object(layer, emarker);
00326     }
00327   }
00328 }
00329 
00330 void LogicModelImporter::parse_gates_element(const xmlpp::Element * const gates_element,
00331                                              LogicModel_shptr lmodel) {
00332 
00333   if(gates_element == NULL || lmodel == NULL) throw InvalidPointerException();
00334 
00335 
00336   const xmlpp::Node::NodeList gate_list = gates_element->get_children("gate");
00337   for(xmlpp::Node::NodeList::const_iterator iter = gate_list.begin();
00338       iter != gate_list.end();
00339       ++iter) {
00340 
00341     if(const xmlpp::Element* gate_elem = dynamic_cast<const xmlpp::Element*>(*iter)) {
00342 
00343 
00344       object_id_t object_id = parse_number<object_id_t>(gate_elem, "id");
00345       int min_x = parse_number<int>(gate_elem, "min-x");
00346       int min_y = parse_number<int>(gate_elem, "min-y");
00347       int max_x = parse_number<int>(gate_elem, "max-x");
00348       int max_y = parse_number<int>(gate_elem, "max-y");
00349 
00350       int layer = parse_number<int>(gate_elem, "layer");
00351 
00352       int gate_type_id = parse_number<int>(gate_elem, "type-id");
00353       const Glib::ustring name(gate_elem->get_attribute_value("name"));
00354       const Glib::ustring description(gate_elem->get_attribute_value("description"));
00355       const Glib::ustring orientation_str(gate_elem->get_attribute_value("orientation").lowercase());
00356       const Glib::ustring frame_color_str(gate_elem->get_attribute_value("frame-color"));
00357       const Glib::ustring fill_color_str(gate_elem->get_attribute_value("fill-color"));
00358 
00359       Gate::ORIENTATION orientation;
00360       if(orientation_str == "undefined") orientation = Gate::ORIENTATION_UNDEFINED;
00361       else if(orientation_str == "normal") orientation = Gate::ORIENTATION_NORMAL;
00362       else if(orientation_str == "flipped-left-right") orientation = Gate::ORIENTATION_FLIPPED_LEFT_RIGHT;
00363       else if(orientation_str == "flipped-up-down") orientation = Gate::ORIENTATION_FLIPPED_UP_DOWN;
00364       else if(orientation_str == "flipped-both") orientation = Gate::ORIENTATION_FLIPPED_BOTH;
00365       else throw XMLAttributeParseException("Can't parse orientation type.");
00366 
00367       // create a new gate and add it into the logic model
00368 
00369       Gate_shptr gate(new Gate(min_x, max_x, min_y, max_y, orientation));
00370       gate->set_name(name.c_str());
00371       gate->set_description(description.c_str());
00372       gate->set_object_id(object_id);
00373       gate->set_template_type_id(gate_type_id);
00374       gate->set_fill_color(parse_color_string(fill_color_str));
00375       gate->set_frame_color(parse_color_string(frame_color_str));
00376 
00377       if(gate_library != NULL && gate_type_id != 0) {
00378         GateTemplate_shptr tmpl = gate_library->get_template(gate_type_id);
00379         assert(tmpl != NULL);
00380         gate->set_gate_template(tmpl);
00381       }
00382 
00383       // parse port instances
00384       const xmlpp::Node::NodeList port_list = gate_elem->get_children("port");
00385       for(xmlpp::Node::NodeList::const_iterator iter2 = port_list.begin();
00386           iter2 != port_list.end();
00387           ++iter2) {
00388 
00389         if(const xmlpp::Element* port_elem = dynamic_cast<const xmlpp::Element*>(*iter2)) {
00390 
00391           object_id_t template_port_id = parse_number<object_id_t>(port_elem, "type-id");
00392 
00393           // create a new port
00394           GatePort_shptr gate_port(new GatePort(gate));
00395           gate_port->set_object_id(parse_number<object_id_t>(port_elem, "id"));
00396           gate_port->set_template_port_type_id(template_port_id);
00397           gate_port->set_diameter(parse_number<diameter_t>(port_elem, "diameter", 5));
00398 
00399           if(gate_library != NULL) {
00400             GateTemplatePort_shptr tmpl_port = gate_library->get_template_port(template_port_id);
00401             gate_port->set_template_port(tmpl_port);
00402           }
00403 
00404           gate->add_port(gate_port);
00405         }
00406       }
00407 
00408       lmodel->add_object(layer, gate);
00409       gate->print();
00410 
00411       // Collect placed standard cells in a first step.
00412       // Later we call lmodel->update_ports().
00413       gates.push_back(gate);
00414     }
00415   }
00416 
00417 }
00418 
00419 
00420 void LogicModelImporter::parse_annotations_element(const xmlpp::Element * const annotations_element,
00421                                                    LogicModel_shptr lmodel) {
00422 
00423   if(annotations_element == NULL || lmodel == NULL) throw InvalidPointerException();
00424 
00425   const xmlpp::Node::NodeList annotation_list = annotations_element->get_children("annotation");
00426   for(xmlpp::Node::NodeList::const_iterator iter = annotation_list.begin();
00427       iter != annotation_list.end();
00428       ++iter) {
00429 
00430     if(const xmlpp::Element* annotation_elem = dynamic_cast<const xmlpp::Element*>(*iter)) {
00431 
00432       object_id_t object_id = parse_number<object_id_t>(annotation_elem, "id");
00433 
00434       int min_x = parse_number<int>(annotation_elem, "min-x");
00435       int min_y = parse_number<int>(annotation_elem, "min-y");
00436       int max_x = parse_number<int>(annotation_elem, "max-x");
00437       int max_y = parse_number<int>(annotation_elem, "max-y");
00438 
00439       int layer = parse_number<int>(annotation_elem, "layer");
00440       Annotation::class_id_t class_id = parse_number<Annotation::class_id_t>(annotation_elem, "class-id");
00441 
00442       const Glib::ustring name(annotation_elem->get_attribute_value("name"));
00443       const Glib::ustring description(annotation_elem->get_attribute_value("description"));
00444       const Glib::ustring fill_color_str(annotation_elem->get_attribute_value("fill-color"));
00445       const Glib::ustring frame_color_str(annotation_elem->get_attribute_value("frame-color"));
00446 
00447 
00448       Annotation_shptr annotation;
00449 
00450       if(class_id == Annotation::SUBPROJECT) {
00451         const std::string path = annotation_elem->get_attribute_value("subproject-directory");
00452         annotation = Annotation_shptr(new SubProjectAnnotation(min_x, max_x, min_y, max_y, path));
00453       }
00454       else
00455         annotation = Annotation_shptr(new Annotation(min_x, max_x, min_y, max_y, class_id));
00456 
00457       annotation->set_name(name.c_str());
00458       annotation->set_description(description.c_str());
00459       annotation->set_object_id(object_id);
00460       annotation->set_fill_color(parse_color_string(fill_color_str));
00461       annotation->set_frame_color(parse_color_string(frame_color_str));
00462 
00463       lmodel->add_object(layer, annotation);
00464     }
00465   }
00466 }
00467 
00468 std::list<Module_shptr> LogicModelImporter::parse_modules_element(const xmlpp::Element * const modules_element,
00469                                                        LogicModel_shptr lmodel) {
00470 
00471   if(modules_element == NULL || lmodel == NULL)
00472     throw InvalidPointerException("Got a NULL pointer in  LogicModelImporter::parse_modules_element()");
00473 
00474   std::list<Module_shptr> modules;
00475 
00476   const xmlpp::Node::NodeList module_list = modules_element->get_children("module");
00477 
00478   for(xmlpp::Node::NodeList::const_iterator m_iter = module_list.begin();  m_iter != module_list.end(); ++m_iter) {
00479 
00480 
00481     if(const xmlpp::Element* module_elem = dynamic_cast<const xmlpp::Element*>(*m_iter)) {
00482 
00483       // parse module attributes
00484       object_id_t id = parse_number<object_id_t>(module_elem, "id");
00485       const Glib::ustring name(module_elem->get_attribute_value("name"));
00486       const Glib::ustring entity(module_elem->get_attribute_value("entity"));
00487 
00488       Module_shptr module(new Module(name, entity));
00489       module->set_object_id(id);
00490 
00491       // parse standard cell list
00492       const xmlpp::Element * cells_elem = get_dom_twig(module_elem, "cells");
00493       if(cells_elem != NULL) {
00494 
00495         const xmlpp::Node::NodeList cell_list = cells_elem->get_children("cell");
00496         for(xmlpp::Node::NodeList::const_iterator c_iter = cell_list.begin();
00497             c_iter != cell_list.end(); ++c_iter) {
00498 
00499           if(const xmlpp::Element* cell_elem = dynamic_cast<const xmlpp::Element*>(*c_iter)) {    
00500             object_id_t cell_id = parse_number<object_id_t>(cell_elem, "object-id");
00501 
00502             // Lookup will throw an exception, if cell is not in the logic model. This is intended behaviour.
00503             if(Gate_shptr gate = std::dynamic_pointer_cast<Gate>(lmodel->get_object(cell_id)))
00504               module->add_gate(gate, /* autodetect module ports = */ false);
00505           }
00506         }
00507       }
00508 
00509       // parse module ports
00510       const xmlpp::Element * mports_elem = get_dom_twig(module_elem, "module-ports");
00511       if(mports_elem != NULL) {
00512 
00513         const xmlpp::Node::NodeList mport_list = mports_elem->get_children("module-port");
00514         for(xmlpp::Node::NodeList::const_iterator mp_iter = mport_list.begin();
00515             mp_iter != mport_list.end(); ++mp_iter) {
00516 
00517           if(const xmlpp::Element* mport_elem = dynamic_cast<const xmlpp::Element*>(*mp_iter)) {
00518 
00519             const Glib::ustring port_name(mport_elem->get_attribute_value("name"));
00520             object_id_t ref_id = parse_number<object_id_t>(mport_elem, "object-id");
00521             
00522             // Lookup will throw an exception, if cell is not in the logic model. This is intended behaviour.
00523             if(GatePort_shptr gport = std::dynamic_pointer_cast<GatePort>(lmodel->get_object(ref_id)))
00524               module->add_module_port(port_name, gport);
00525           }
00526         }
00527       }
00528 
00529 
00530       // parse sub-modules
00531       const xmlpp::Element * sub_modules_elem = get_dom_twig(module_elem, "modules");
00532       if(sub_modules_elem != NULL) {
00533         std::list<Module_shptr> sub_modules = parse_modules_element(sub_modules_elem, lmodel);
00534         BOOST_FOREACH(Module_shptr submod, sub_modules) module->add_module(submod);
00535       }
00536 
00537 
00538       modules.push_back(module);
00539 
00540     }
00541   }
00542 
00543   return modules;
00544 }