degate  0.1.2
Layer.cc
Go to the documentation of this file.
00001 /* -*-c++-*-
00002 
00003   This file is part of the IC reverse engineering tool degate.
00004 
00005   Copyright 2008, 2009, 2010 by Martin Schobert
00006   Copyright 2012 Robert Nitsch
00007 
00008   Degate is free software: you can redistribute it and/or modify
00009   it under the terms of the GNU General Public License as published by
00010   the Free Software Foundation, either version 3 of the License, or
00011   any later version.
00012 
00013   Degate is distributed in the hope that it will be useful,
00014   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016   GNU General Public License for more details.
00017 
00018   You should have received a copy of the GNU General Public License
00019   along with degate. If not, see <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #include <degate.h>
00024 #include <Layer.h>
00025 #include <boost/format.hpp>
00026 
00027 using namespace degate;
00028 
00029 void Layer::add_object(std::shared_ptr<PlacedLogicModelObject> o) {
00030 
00031   if(o->get_bounding_box() == BoundingBox(0, 0, 0, 0)) {
00032     boost::format fmter("Error in add_object(): Object %1% with ID %2% has an "
00033                         "undefined bounding box. Can't insert it into the quadtree");
00034     fmter % o->get_object_type_name() % o->get_object_id();
00035     throw DegateLogicException(fmter.str());
00036   }
00037 
00038   if(RET_IS_NOT_OK(quadtree.insert(o))) {
00039     debug(TM, "Failed to insert object into quadtree.");
00040     throw DegateRuntimeException("Failed to insert object into quadtree.");
00041   }
00042   objects[o->get_object_id()] = o;
00043 }
00044 
00045 void Layer::remove_object(std::shared_ptr<PlacedLogicModelObject> o) {
00046   if(RET_IS_NOT_OK(quadtree.remove(o))) {
00047     debug(TM, "Failed to remove object from quadtree.");
00048     throw std::runtime_error("Failed to remove object from quadtree.");
00049   }
00050 
00051   objects.erase(o->get_object_id());
00052 }
00053 
00054 Layer::Layer(BoundingBox const & bbox, Layer::LAYER_TYPE _layer_type) :
00055   quadtree(bbox, 100),
00056   layer_type(_layer_type),
00057   layer_pos(0),
00058   enabled(true),
00059   layer_id(0) {
00060 }
00061 
00062 Layer::Layer(BoundingBox const & bbox, Layer::LAYER_TYPE _layer_type,
00063              BackgroundImage_shptr img) :
00064   quadtree(bbox, 100),
00065   layer_type(_layer_type),
00066   layer_pos(0),
00067   enabled(true),
00068   layer_id(0) {
00069 
00070   set_image(img);
00071 }
00072 
00073 
00074 Layer::~Layer() {
00075 }
00076 
00077 /**
00078  * @todo Check whether scaling_manager can really be reused by clones without trouble.
00079  */
00080 DeepCopyable_shptr Layer::cloneShallow() const {
00081   auto clone = std::make_shared<Layer>(quadtree.get_bounding_box(), layer_type);
00082   clone->layer_pos = layer_pos;
00083   clone->enabled = enabled;
00084   clone->description = description;
00085   clone->layer_id = layer_id;
00086   clone->scaling_manager = scaling_manager;
00087   return clone;
00088 }
00089 
00090 void Layer::cloneDeepInto(DeepCopyable_shptr dest, oldnew_t *oldnew) const {
00091   auto clone = std::dynamic_pointer_cast<Layer>(dest);
00092 
00093   // quadtree
00094   std::vector<quadtree_element_type> quadtree_elems;
00095   quadtree.get_all_elements(quadtree_elems);
00096   std::for_each(quadtree_elems.begin(), quadtree_elems.end(), [=,oldnew,&clone](const quadtree_element_type &t) {
00097     clone->quadtree.insert(std::dynamic_pointer_cast<PlacedLogicModelObject>(t->cloneDeep(oldnew)));
00098   });
00099 
00100   // objects
00101   std::for_each(objects.begin(), objects.end(), [&](object_collection::value_type v) {
00102     clone->objects[v.first] = std::dynamic_pointer_cast<PlacedLogicModelObject>(v.second->cloneDeep(oldnew));
00103   });
00104 }
00105 
00106 unsigned int Layer::get_width() const {
00107   return quadtree.get_width();
00108 }
00109 
00110 unsigned int Layer::get_height() const {
00111   return quadtree.get_height();
00112 }
00113 
00114 BoundingBox const& Layer::get_bounding_box() const {
00115   return quadtree.get_bounding_box();
00116 }
00117 
00118 
00119 const std::string Layer::get_layer_type_as_string() const {
00120   return get_layer_type_as_string(layer_type);
00121 }
00122 
00123 const std::string Layer::get_layer_type_as_string(LAYER_TYPE _layer_type) {
00124   switch(_layer_type) {
00125   case METAL:
00126     return std::string("metal");
00127   case LOGIC:
00128     return std::string("logic");
00129   case TRANSISTOR:
00130     return std::string("transistor");
00131   case UNDEFINED:
00132   default:
00133     return std::string("undefined");
00134   }
00135 }
00136 
00137 Layer::LAYER_TYPE Layer::get_layer_type_from_string(std::string const& layer_type_str) {
00138 
00139   if(layer_type_str == "metal") return Layer::METAL;
00140   else if(layer_type_str == "logic") return Layer::LOGIC;
00141   else if(layer_type_str == "transistor") return Layer::TRANSISTOR;
00142   else if(layer_type_str == "undefined") return Layer::UNDEFINED;
00143   else throw DegateRuntimeException("Can't parse layer type.");
00144 }
00145 
00146 
00147 Layer::LAYER_TYPE Layer::get_layer_type() const {
00148   return layer_type;
00149 }
00150 
00151 void Layer::set_layer_type(LAYER_TYPE _layer_type) {
00152   layer_type = _layer_type;
00153 }
00154 
00155 
00156 bool Layer::is_empty() const {
00157   return quadtree.is_empty();
00158 }
00159 
00160 layer_position_t Layer::get_layer_pos() const {
00161   return layer_pos;
00162 }
00163 
00164 Layer::object_iterator Layer::objects_begin() {
00165   return quadtree.region_iter_begin();
00166 }
00167 
00168 Layer::object_iterator Layer::objects_end() {
00169   return quadtree.region_iter_end();
00170 }
00171 
00172 Layer::qt_region_iterator Layer::region_begin(int min_x, int max_x, int min_y, int max_y) {
00173   return quadtree.region_iter_begin(min_x, max_x, min_y, max_y);
00174 }
00175 
00176 Layer::qt_region_iterator Layer::region_begin(BoundingBox const& bbox) {
00177   return quadtree.region_iter_begin(bbox);
00178 }
00179 
00180 Layer::qt_region_iterator Layer::region_end() {
00181   return quadtree.region_iter_end();
00182 }
00183 
00184 void Layer::set_image(BackgroundImage_shptr img) {
00185 
00186   scaling_manager =
00187     std::shared_ptr<ScalingManager<BackgroundImage> >
00188     (new ScalingManager<BackgroundImage>(img, img->get_directory()));
00189 
00190   scaling_manager->create_scalings();
00191 }
00192 
00193 BackgroundImage_shptr Layer::get_image() {
00194   if(scaling_manager != NULL) {
00195     ScalingManager<BackgroundImage>::image_map_element p = scaling_manager->get_image(1);
00196     return p.second;
00197   }
00198   else throw DegateLogicException("You have to set the background image first.");
00199 }
00200 
00201 std::string Layer::get_image_filename() const {
00202 
00203   if(scaling_manager == NULL)
00204     throw DegateLogicException("There is no scaling manager.");
00205   else {
00206     const ScalingManager<BackgroundImage>::image_map_element p =
00207       scaling_manager->get_image(1);
00208 
00209     if(p.second != NULL)
00210       return p.second->get_directory();
00211     else
00212       throw DegateLogicException("The scaling manager failed to return an image pointer.");
00213   }
00214 }
00215 
00216 bool Layer::has_background_image() const {
00217   return scaling_manager != NULL;
00218 }
00219 
00220 void Layer::unset_image() {
00221   if(scaling_manager == NULL) throw DegateLogicException("There is no scaling manager.");
00222   std::string img_dir = get_image_filename();
00223   scaling_manager.reset();
00224   debug(TM, "remove directory: %s", img_dir.c_str());
00225   remove_directory(img_dir);
00226 }
00227 
00228 ScalingManager_shptr Layer::get_scaling_manager() {
00229   return scaling_manager;
00230 }
00231 
00232 void Layer::print(std::ostream & os) {
00233 
00234   os
00235     << "Layer position       : " << get_layer_pos() << std::endl
00236     << "Width                : " << get_width() << std::endl
00237     << "Height               : " << get_height() << std::endl
00238     << "Layer type           : " << get_layer_type_as_string() << std::endl
00239     << "Has background image : " << (has_background_image() ? "true" : "false") << std::endl
00240     << "Background image     : " << (has_background_image() ? get_image_filename() : "none" ) << std::endl
00241     << std::endl
00242     ;
00243 
00244   quadtree.print(os);
00245 }
00246 
00247 void Layer::notify_shape_change(object_id_t object_id) {
00248 
00249   if(!object_id)
00250     throw InvalidObjectIDException("Invalid object ID in Layer::notify_shape_change()");
00251 
00252   object_collection::iterator iter = objects.find(object_id);
00253   if(iter == objects.end())
00254     throw CollectionLookupException("Error in Layer::notify_shape_change(): "
00255                                     "The object is not in the layer.");
00256 
00257   quadtree.notify_shape_change((*iter).second);
00258 }
00259 
00260 
00261 PlacedLogicModelObject_shptr Layer::get_object_at_position(int x, int y, int max_distance) {
00262 
00263   debug(TM, "get_object_at_position %d, %d (max-dist: %d)", x, y, max_distance);
00264   PlacedLogicModelObject_shptr plo;
00265 
00266   for(qt_region_iterator iter = quadtree.region_iter_begin(x - max_distance,
00267                                                            x + max_distance,
00268                                                            y - max_distance,
00269                                                            y + max_distance);
00270       iter != quadtree.region_iter_end(); ++iter) {
00271 
00272     if((*iter)->in_shape(x, y, max_distance)) {
00273       plo = *iter;
00274     }
00275 
00276     /* Prefer gate ports */
00277     if(std::dynamic_pointer_cast<GatePort>(*iter) != NULL) {
00278       return *iter;
00279     }
00280   }
00281   return plo;
00282 }
00283 
00284 unsigned int Layer::get_distance_to_gate_boundary(unsigned int x, unsigned int y,
00285                                                   bool query_horizontal_distance,
00286                                                   unsigned int width,
00287                                                   unsigned int height) {
00288 
00289   for(Layer::qt_region_iterator iter = quadtree.region_iter_begin(x, x + width, y, y + height);
00290       iter != quadtree.region_iter_end(); ++iter) {
00291 
00292     if(Gate_shptr gate = std::dynamic_pointer_cast<Gate>(*iter)) {
00293 
00294       if(query_horizontal_distance) {
00295         assert(gate->get_max_x() >= (int)x);
00296         return gate->get_max_x() - x;
00297       }
00298       else {
00299         assert(gate->get_max_y() >= (int)y);
00300         return gate->get_max_y() - y;
00301       }
00302     }
00303   }
00304 
00305   return 0;
00306 }
00307 
00308 
00309 void Layer::set_enabled(bool state) {
00310   enabled = state;
00311 }
00312 
00313 bool Layer::is_enabled() const {
00314   return enabled;
00315 }
00316 
00317 
00318 std::string Layer::get_description() const {
00319   return description;
00320 }
00321 
00322 
00323 void Layer::set_description(std::string const& description) {
00324   this->description = description;
00325 }