degate  0.1.2
Gate.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 <Gate.h>
00025 
00026 #include <boost/format.hpp>
00027 
00028 using namespace degate;
00029 
00030 Gate::Gate(int _min_x, int _max_x, int _min_y, int _max_y,
00031            ORIENTATION _orientation) :
00032   Rectangle(_min_x, _max_x, _min_y, _max_y),
00033   orientation(_orientation),
00034   template_type_id(0) {
00035 }
00036 
00037 Gate::Gate(BoundingBox const& bounding_box,
00038            ORIENTATION _orientation):
00039   Rectangle(bounding_box.get_min_x(), bounding_box.get_max_x(),
00040             bounding_box.get_min_y(), bounding_box.get_max_y()),
00041   orientation(_orientation),
00042   template_type_id(0) {
00043 }
00044 
00045 Gate::~Gate() {
00046   debug(TM, "destroy gate");
00047   if(gate_template != NULL) remove_template();
00048 }
00049 
00050 DeepCopyable_shptr Gate::cloneShallow() const {
00051   auto clone = std::make_shared<Gate>(get_bounding_box(), orientation);
00052   clone->template_type_id = template_type_id;
00053   return clone;
00054 }
00055 
00056 void Gate::cloneDeepInto(DeepCopyable_shptr dest, oldnew_t *oldnew) const {
00057   auto clone = std::dynamic_pointer_cast<Gate>(dest);
00058   
00059   PlacedLogicModelObject::cloneDeepInto(clone, oldnew);
00060   Rectangle::cloneDeepInto(clone, oldnew);
00061   
00062   if (gate_template.get() != 0) {
00063     clone->gate_template = std::dynamic_pointer_cast<GateTemplate>(gate_template->cloneDeep(oldnew));
00064   }
00065   std::for_each(gate_ports.begin(), gate_ports.end(), [&](const GatePort_shptr &d) {
00066     clone->gate_ports.insert(std::dynamic_pointer_cast<GatePort>(d->cloneDeep(oldnew)));
00067   });
00068 }
00069 
00070 void Gate::add_port(GatePort_shptr gate_port) {
00071   if(!gate_port->has_valid_object_id())
00072     throw InvalidObjectIDException("Error in Gate::add_port(). "
00073                                    "The port has no valid object ID.");
00074 
00075   if(!gate_port->has_template_port())
00076     throw DegateLogicException("Error in Gate::add_port(). "
00077                                "The gate port has no template port");
00078 
00079   if(!has_orientation())
00080     throw DegateLogicException("Error in Gate::add_port(). "
00081                                "The gate has no defined orientation");
00082 
00083   gate_port->set_x(get_min_x() +
00084                    get_relative_x_position_within_gate
00085                      (gate_port->get_template_port()->get_x()));
00086   gate_port->set_y(get_min_y() +
00087                    get_relative_y_position_within_gate
00088                      (gate_port->get_template_port()->get_y()));
00089 
00090   gate_ports.insert(gate_port);
00091 }
00092 
00093 
00094 void Gate::remove_port(GatePort_shptr gate_port) {
00095   port_iterator found = gate_ports.find(gate_port);
00096   if(found != gate_ports.end()) {
00097     gate_ports.erase(found);
00098   }
00099   else throw CollectionLookupException();
00100 }
00101 
00102 
00103 GatePort_shptr Gate::get_port_by_template_port(GateTemplatePort_shptr template_port) {
00104   for(port_iterator piter = ports_begin(); piter != ports_end(); ++piter) {
00105     GatePort_shptr gate_port = *piter;
00106     GateTemplatePort_shptr tmpl_port = gate_port->get_template_port();
00107     if(tmpl_port == template_port)
00108       return gate_port;
00109   }
00110   throw CollectionLookupException();
00111 }
00112 
00113 
00114 void Gate::set_template_type_id(object_id_t template_type_id) {
00115   this->template_type_id = template_type_id;
00116 }
00117 
00118 
00119 object_id_t Gate::get_template_type_id() const {
00120   return template_type_id;
00121 }
00122 
00123 
00124 
00125 void Gate::set_gate_template(std::shared_ptr<GateTemplate> gate_template) {
00126   if(has_template()) {
00127     this->gate_template->decrement_reference_counter();
00128   }
00129 
00130   if(this->gate_template != gate_template) {
00131     this->gate_template = gate_template;
00132     set_template_type_id(gate_template->get_object_id());
00133     set_fill_color(gate_template->get_fill_color());
00134     set_frame_color(gate_template->get_frame_color());
00135     this->gate_template->increment_reference_counter();
00136 
00137     if((unsigned int)get_width() != gate_template->get_width() ||
00138        (unsigned int)get_height() != gate_template->get_height()) {
00139       set_max_x(get_min_x() + gate_template->get_width());
00140       set_max_y(get_min_y() + gate_template->get_height());
00141     }
00142   }
00143 }
00144 
00145 
00146 std::shared_ptr<GateTemplate> Gate::get_gate_template() const {
00147   return gate_template;
00148 }
00149 
00150 bool Gate::has_template() const {
00151   return gate_template != NULL;
00152 }
00153 
00154 void Gate::remove_template() {
00155   gate_ports.clear();
00156   orientation = ORIENTATION_UNDEFINED;
00157   template_type_id = 0;
00158   set_fill_color(0);
00159   set_frame_color(0);
00160   if(has_template()) {
00161     gate_template->decrement_reference_counter();
00162     gate_template.reset();
00163   }
00164 }
00165 
00166 bool Gate::has_template_port(GateTemplatePort_shptr template_port) const {
00167   for(port_iterator piter = ports_begin(); piter != ports_end(); ++piter) {
00168     GatePort_shptr gate_port = *piter;
00169 
00170     assert(gate_port->get_template_port()->has_valid_object_id());
00171     assert(template_port->has_valid_object_id());
00172 
00173     if(gate_port->get_template_port()->get_object_id() == template_port->get_object_id()) {
00174 
00175       // debugging
00176       if(gate_port->get_template_port() != template_port) {
00177         std::cout << "ERROR\n";
00178         gate_port->print();
00179       }
00180       // debugging
00181       //assert(gate_port->get_template_port() == template_port);
00182 
00183       return true;
00184     }
00185 
00186   }
00187   return false;
00188 }
00189 
00190 
00191 void Gate::set_orientation(ORIENTATION _orientation) {
00192   orientation = _orientation;
00193 }
00194 
00195 Gate::ORIENTATION Gate::get_orientation() const {
00196   return orientation;
00197 }
00198 
00199 bool Gate::has_orientation() const {
00200   return orientation != ORIENTATION_UNDEFINED;
00201 }
00202 
00203 std::string Gate::get_orienation_type_as_string() const {
00204   switch(orientation) {
00205   case ORIENTATION_NORMAL: return std::string("normal");
00206   case ORIENTATION_FLIPPED_UP_DOWN: return std::string("flipped-up-down");
00207   case ORIENTATION_FLIPPED_LEFT_RIGHT: return std::string("flipped-left-right");
00208   case ORIENTATION_FLIPPED_BOTH: return std::string("flipped-both");
00209   case ORIENTATION_UNDEFINED:
00210   default: return std::string("undefined");
00211   }
00212 }
00213 
00214 
00215 Gate::port_iterator Gate::ports_begin() {
00216   return gate_ports.begin();
00217 }
00218 
00219 Gate::port_const_iterator Gate::ports_begin() const {
00220   return gate_ports.begin();
00221 }
00222 
00223 Gate::port_iterator Gate::ports_end() {
00224   return gate_ports.end();
00225 }
00226 
00227 Gate::port_const_iterator Gate::ports_end() const {
00228   return gate_ports.end();
00229 }
00230 
00231 
00232 unsigned int Gate::get_relative_x_position_within_gate(int rel_x) const {
00233   switch(orientation) {
00234   case ORIENTATION_NORMAL:
00235   case ORIENTATION_FLIPPED_UP_DOWN:
00236     return rel_x;
00237   case ORIENTATION_FLIPPED_LEFT_RIGHT:
00238   case ORIENTATION_FLIPPED_BOTH:
00239     return get_width() - rel_x;
00240   case ORIENTATION_UNDEFINED:
00241   default:
00242     assert(orientation != ORIENTATION_UNDEFINED);
00243     throw DegateRuntimeException("Can't calculate a position for an undefined orientation");
00244   }
00245 }
00246 
00247 
00248 unsigned int Gate::get_relative_y_position_within_gate(int rel_y) const {
00249   switch(orientation) {
00250   case ORIENTATION_NORMAL:
00251   case ORIENTATION_FLIPPED_LEFT_RIGHT:
00252     return rel_y;
00253   case ORIENTATION_FLIPPED_UP_DOWN:
00254   case ORIENTATION_FLIPPED_BOTH:
00255     return get_height() - rel_y;
00256   case ORIENTATION_UNDEFINED:
00257   default:
00258     assert(orientation != ORIENTATION_UNDEFINED);
00259     throw DegateRuntimeException("Can't calculate a position for an undefined orientation");
00260   }
00261 }
00262 
00263 
00264 const std::string Gate::get_descriptive_identifier() const {
00265 
00266   if(has_template()) {
00267     if(has_name()) {
00268       boost::format fmter("%1% : %2%");
00269       fmter % get_name() % get_gate_template()->get_name();
00270       return fmter.str();
00271     }
00272     else {
00273       boost::format fmter("%1% (%2%)");
00274       fmter % get_gate_template()->get_name() % get_object_id();
00275       return fmter.str();
00276     }
00277   }
00278   else {
00279     if(!has_name()) {
00280       boost::format fmter("gate (%1%)");
00281       fmter % get_object_id();
00282       return fmter.str();
00283     }
00284     else {
00285       boost::format fmter("gate %1% (%2%)");
00286       fmter % get_name() % get_object_id();
00287       return fmter.str();
00288     }
00289   }
00290 
00291 }
00292 
00293 
00294 const std::string Gate::get_object_type_name() const {
00295   return std::string("Gate");
00296 }
00297 
00298 void Gate::print(std::ostream & os, int n_tabs) const {
00299 
00300   os
00301     << gen_tabs(n_tabs) << "Gate name        : " << get_name() << std::endl
00302     << gen_tabs(n_tabs) << "Gate description : " << get_description() << std::endl
00303     << gen_tabs(n_tabs) << "Object ID        : " << get_object_id() << std::endl
00304     << gen_tabs(n_tabs) << "Bounding box     : " << Rectangle::get_bounding_box().to_string() << std::endl
00305     << std::endl;
00306 
00307   for(port_const_iterator pi = ports_begin(); pi != ports_end(); ++pi) {
00308     const GatePort_shptr gate_port = *pi;
00309     gate_port->print(os, n_tabs + 1);
00310     os << std::endl;
00311   }
00312 
00313   os << std::endl;
00314 }