degate  0.1.2
GateLibraryImporter.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 <GateLibraryImporter.h>
00024 #include <ImageHelper.h>
00025 
00026 #include <sys/types.h>
00027 #include <sys/stat.h>
00028 #include <unistd.h>
00029 #include <errno.h>
00030 
00031 #include <string>
00032 #include <iostream>
00033 #include <fstream>
00034 #include <sstream>
00035 #include <stdexcept>
00036 #include <list>
00037 #include <memory>
00038 
00039 using namespace std;
00040 using namespace degate;
00041 
00042 GateLibrary_shptr GateLibraryImporter::import(std::string const& filename) {
00043 
00044   if(RET_IS_NOT_OK(check_file(filename))) {
00045     debug(TM, "Problem: file %s not found.", filename.c_str());
00046     throw InvalidPathException("Can't load gate library from file.");
00047   }
00048 
00049   std::string directory = get_basedir(filename);
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     return parse_gate_library_element(root_elem, directory);
00067 
00068   }
00069   catch(const std::exception& ex) {
00070     std::cout << "Exception caught: " << ex.what() << std::endl;
00071     throw;
00072   }
00073 
00074 
00075 
00076 }
00077 
00078 GateLibrary_shptr GateLibraryImporter::parse_gate_library_element(const xmlpp::Element * const gt_elem,
00079                                                                   std::string const& directory) {
00080 
00081   // parse width and height
00082   GateLibrary_shptr gate_lib(new GateLibrary());
00083   assert(gate_lib != NULL);
00084 
00085   const xmlpp::Element * e = get_dom_twig(gt_elem, "gate-templates");
00086   if(e != NULL) parse_gate_templates_element(e, gate_lib, directory);
00087 
00088   return gate_lib;
00089 }
00090 
00091 void GateLibraryImporter::parse_gate_templates_element(const xmlpp::Element * const gate_template_element,
00092                                                        GateLibrary_shptr gate_lib,
00093                                                        std::string const& directory) {
00094 
00095   if(gate_template_element == NULL || gate_lib == NULL) throw(InvalidPointerException("Invalid pointer"));
00096 
00097   const xmlpp::Node::NodeList gate_list = gate_template_element->get_children("gate");
00098   for(xmlpp::Node::NodeList::const_iterator iter = gate_list.begin();
00099       iter != gate_list.end();
00100       ++iter) {
00101 
00102     if(const xmlpp::Element* gate_elem = dynamic_cast<const xmlpp::Element*>(*iter)) {
00103 
00104       object_id_t object_id = parse_number<object_id_t>(gate_elem, "type-id");
00105       int min_x = parse_number<int>(gate_elem, "min-x", 0);
00106       int min_y = parse_number<int>(gate_elem, "min-y", 0);
00107       int max_x = parse_number<int>(gate_elem, "max-x", 0);
00108       int max_y = parse_number<int>(gate_elem, "max-y", 0);
00109 
00110       int width = parse_number<int>(gate_elem, "width", 0);
00111       int height = parse_number<int>(gate_elem, "height", 0);
00112 
00113       const Glib::ustring name(gate_elem->get_attribute_value("name"));
00114       const Glib::ustring description(gate_elem->get_attribute_value("description"));
00115       const Glib::ustring logic_class(gate_elem->get_attribute_value("logic-class"));
00116       const Glib::ustring frame_color_str(gate_elem->get_attribute_value("frame-color"));
00117       const Glib::ustring fill_color_str(gate_elem->get_attribute_value("fill-color"));
00118 
00119       GateTemplate_shptr gate_template;
00120 
00121       if(min_x == 0 && min_y == 0 && max_x == 0 && max_y == 0) {
00122         gate_template = GateTemplate_shptr(new GateTemplate(width, height));
00123       }
00124       else {
00125         gate_template = GateTemplate_shptr(new GateTemplate(min_x, max_x, min_y, max_y));
00126       }
00127 
00128       gate_template->set_name(string(name.c_str()));
00129       gate_template->set_description(string(description.c_str()));
00130       gate_template->set_logic_class(string(logic_class.c_str()));
00131       gate_template->set_object_id(object_id);
00132       gate_template->set_fill_color(parse_color_string(fill_color_str));
00133       gate_template->set_frame_color(parse_color_string(frame_color_str));
00134 
00135 
00136       const xmlpp::Element * images = get_dom_twig(gate_elem, "images");
00137       if(images != NULL) parse_template_images_element(images, gate_template, directory);
00138 
00139 
00140       const xmlpp::Element * ports = get_dom_twig(gate_elem, "ports");
00141       if(ports != NULL) parse_template_ports_element(ports, gate_template, gate_lib);
00142 
00143       const xmlpp::Element * implementations = get_dom_twig(gate_elem, "implementations");
00144       if(implementations != NULL)
00145         parse_template_implementations_element(implementations, gate_template, directory);
00146 
00147       gate_lib->add_template(gate_template);
00148     }
00149   }
00150 
00151 }
00152 
00153 void GateLibraryImporter::parse_template_images_element(const xmlpp::Element * const template_images_element,
00154                                                         GateTemplate_shptr gate_tmpl,
00155                                                         std::string const& directory) {
00156 
00157   if(template_images_element == NULL ||
00158      gate_tmpl == NULL) throw InvalidPointerException("Invalid pointer");
00159 
00160   const xmlpp::Node::NodeList image_list = template_images_element->get_children("image");
00161   for(xmlpp::Node::NodeList::const_iterator iter = image_list.begin();
00162       iter != image_list.end(); ++iter) {
00163 
00164     if(const xmlpp::Element* image_elem = dynamic_cast<const xmlpp::Element*>(*iter)) {
00165       const std::string layer_type_str(image_elem->get_attribute_value("layer-type"));
00166       const std::string image_file(image_elem->get_attribute_value("image"));
00167 
00168       Layer::LAYER_TYPE layer_type = Layer::get_layer_type_from_string(layer_type_str);
00169       GateTemplateImage_shptr img = load_image<GateTemplateImage>(join_pathes(directory, image_file));
00170 
00171       assert(img != NULL);
00172       gate_tmpl->set_image(layer_type, img);
00173     }
00174   }
00175 
00176 }
00177 
00178 void GateLibraryImporter::parse_template_implementations_element(const xmlpp::Element * const implementations_element,
00179                                                                  GateTemplate_shptr gate_tmpl,
00180                                                                  std::string const& directory) {
00181 
00182   if(implementations_element == NULL ||
00183      gate_tmpl == NULL) throw InvalidPointerException("Invalid pointer");
00184 
00185   const xmlpp::Node::NodeList impl_list = implementations_element->get_children("implementation");
00186   for(xmlpp::Node::NodeList::const_iterator iter = impl_list.begin();
00187       iter != impl_list.end(); ++iter) {
00188 
00189     if(const xmlpp::Element* impl_elem = dynamic_cast<const xmlpp::Element*>(*iter)) {
00190       const std::string impl_type_str(impl_elem->get_attribute_value("type"));
00191       const std::string impl_file_attr(impl_elem->get_attribute_value("file"));
00192       const std::string impl_file(join_pathes(directory, impl_file_attr));
00193 
00194       if(!impl_file_attr.empty()) {
00195         GateTemplate::IMPLEMENTATION_TYPE impl_type;
00196         try {
00197           impl_type = GateTemplate::get_impl_type_from_string(impl_type_str);
00198         }
00199         catch(DegateRuntimeException const &ex) {
00200           boost::format f("Can't interprete attribute %1% while reading gate library (%2%)");
00201           f % impl_type_str % ex.what();
00202           throw XMLAttributeParseException(f.str());
00203         }
00204 
00205         debug(TM, "Parsing file '%s'", impl_file.c_str());
00206         std::ifstream myfile(impl_file.c_str());
00207         std::string line, code;
00208         if(myfile.is_open()) {
00209           while (!myfile.eof()) {
00210             getline(myfile, line);
00211             code.append(line);
00212             code.append("\n");
00213           }
00214           myfile.close();
00215           gate_tmpl->set_implementation(impl_type, code);
00216           gate_tmpl->get_implementation(impl_type);
00217         }
00218         else {
00219           boost::format f("Can't open file %1%");
00220           f % impl_file;
00221           throw FileSystemException(f.str());
00222         }
00223 
00224       }
00225     }
00226   }
00227 
00228 }
00229 
00230 
00231 void GateLibraryImporter::parse_template_ports_element(const xmlpp::Element * const template_ports_element,
00232                                                        GateTemplate_shptr gate_tmpl,
00233                                                        GateLibrary_shptr gate_lib) {
00234 
00235   if(template_ports_element == NULL ||
00236      gate_tmpl == NULL) throw InvalidPointerException("Invalid pointer");
00237 
00238   const xmlpp::Node::NodeList port_list = template_ports_element->get_children("port");
00239   for(xmlpp::Node::NodeList::const_iterator iter = port_list.begin();
00240       iter != port_list.end();
00241       ++iter) {
00242 
00243     if(const xmlpp::Element* port_elem = dynamic_cast<const xmlpp::Element*>(*iter)) {
00244 
00245       object_id_t object_id = parse_number<object_id_t>(port_elem, "id");
00246 
00247       // we check if the object id is somehow present in the logic model
00248       if(gate_lib->exists_template_port(object_id) || gate_lib->exists_template(object_id)) {
00249         boost::format f("Error: The object ID %1% is used twice in the gate library."); 
00250         f % object_id;
00251         std::cout << f.str() << "\n";
00252         throw DegateInconsistencyException(f.str());
00253       }
00254 
00255 
00256       const std::string name(port_elem->get_attribute_value("name"));
00257       const std::string description(port_elem->get_attribute_value("description"));
00258       const std::string type_str(port_elem->get_attribute_value("type").lowercase());
00259 
00260       GateTemplatePort::PORT_TYPE port_type = GateTemplatePort::get_port_type_from_string(type_str);
00261 
00262       GateTemplatePort_shptr tmpl_port;
00263 
00264       int pos_x, pos_y;
00265       try {
00266         pos_x = parse_number<int>(port_elem, "x");
00267         pos_y = parse_number<int>(port_elem, "y");
00268 
00269         tmpl_port = GateTemplatePort_shptr(new GateTemplatePort(pos_x, pos_y, port_type));
00270       }
00271       catch(XMLAttributeMissingException const & ex) {
00272         tmpl_port = GateTemplatePort_shptr(new GateTemplatePort(port_type));
00273       }
00274       assert(tmpl_port != NULL);
00275 
00276 
00277       tmpl_port->set_name(string(name.c_str()));
00278       tmpl_port->set_description(string(description.c_str()));
00279       tmpl_port->set_object_id(object_id);
00280 
00281       // add port to the gate template
00282       gate_tmpl->add_template_port(tmpl_port);
00283     }
00284 
00285 
00286   }
00287 }