|
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 <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 <tr1/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::tr1::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) { 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 intented behaviour. 00503 if(Gate_shptr gate = std::tr1::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 intented behaviour. 00523 if(GatePort_shptr gport = std::tr1::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 }
1.7.4