degate  0.1.2
Module.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 <Module.h>
00025 #include <boost/foreach.hpp>
00026 #include <boost/algorithm/string.hpp>
00027 
00028 #include <iterator>
00029 
00030 using namespace degate;
00031 
00032 
00033 Module::Module(std::string const& module_name, 
00034                std::string const& _entity_name, 
00035                bool _is_root) :
00036   entity_name(_entity_name), 
00037   is_root(_is_root) {
00038 
00039   set_name(module_name);
00040 }
00041 
00042 Module::~Module() {}
00043 
00044 DeepCopyable_shptr Module::cloneShallow() const {
00045   auto clone = std::make_shared<Module>(get_name(), entity_name, is_root);
00046   return clone;
00047 }
00048 
00049 void Module::cloneDeepInto(DeepCopyable_shptr dest, oldnew_t *oldnew) const {
00050   auto clone = std::dynamic_pointer_cast<Module>(dest);
00051   
00052   // modules
00053   std::transform(modules.begin(), modules.end(), std::inserter(clone->modules, clone->modules.begin()), [&](const module_collection::value_type &v) {
00054     return std::dynamic_pointer_cast<Module>(v->cloneDeep(oldnew));
00055   });
00056   
00057   // gates
00058   std::transform(gates.begin(), gates.end(), std::inserter(clone->gates, clone->gates.begin()), [&](const gate_collection::value_type &v) {
00059     return std::dynamic_pointer_cast<Gate>(v->cloneDeep(oldnew));
00060   });
00061   
00062   // ports
00063   std::for_each(ports.begin(), ports.end(), [&](const port_collection::value_type &v) {
00064     clone->ports[v.first] = std::dynamic_pointer_cast<GatePort>(v.second->cloneDeep(oldnew));
00065   });
00066   
00067   LogicModelObjectBase::cloneDeepInto(dest, oldnew);
00068 }
00069 
00070 bool Module::is_main_module() const {
00071   return is_root;
00072 }
00073 
00074 void Module::set_main_module() {
00075   is_root = true;
00076 }
00077 
00078 
00079 void Module::set_entity_name(std::string const& name) {
00080   entity_name = name;
00081 }
00082 
00083 std::string Module::get_entity_name() const {
00084   return entity_name;
00085 }
00086 
00087 
00088 void Module::add_gate(Gate_shptr gate, bool detect_ports) {
00089   if(gate == NULL)
00090     throw InvalidPointerException("Invalid pointer passed to add_gate().");
00091 
00092   gates.insert(gate);
00093   if(!is_root && detect_ports) determine_module_ports();
00094 }
00095 
00096 bool Module::remove_gate(Gate_shptr gate) {
00097   if(gate == NULL)
00098     throw InvalidPointerException("Invalid pointer passed to remove_gate().");
00099 
00100 
00101   gate_collection::const_iterator g_iter = gates.find(gate);
00102   if(g_iter != gates.end()) {
00103     gates.erase(g_iter);
00104     if(!is_root) determine_module_ports();
00105     return true;
00106   }
00107   else {
00108 
00109     for(module_collection::iterator iter = modules.begin();
00110         iter != modules.end(); ++iter) {
00111 
00112       Module_shptr child = *iter;
00113       if((*iter)->remove_gate(gate) == true) return true;
00114     }
00115   }
00116 
00117   return false;
00118 }
00119 
00120 
00121 void Module::add_module(Module_shptr module) {
00122   if(module == NULL)
00123     throw InvalidPointerException("Invalid pointer passed to add_modue().");
00124 
00125   modules.insert(module);
00126 }
00127 
00128 
00129 
00130 bool Module::remove_module(Module_shptr module) {
00131 
00132   if(module == NULL)
00133     throw InvalidPointerException("Invalid pointer passed to remove_module().");
00134 
00135   for(module_collection::iterator iter = modules.begin();
00136       iter != modules.end(); ++iter) {
00137 
00138     Module_shptr child = *iter;
00139 
00140     if(child == module) {
00141       child->move_gates_recursive(this);
00142       modules.erase(iter);
00143       return true;
00144     }
00145     else if((*iter)->remove_module(module) == true)
00146       return true;
00147   }
00148 
00149   return false;
00150 }
00151 
00152 void Module::move_gates_recursive(Module * dst_mod) {
00153 
00154   if(dst_mod == NULL)
00155     throw InvalidPointerException("Invalid pointer passed to move_all_child_gates_into_current_module().");
00156 
00157   for(gate_collection::iterator g_iter = gates_begin();
00158       g_iter != gates_end(); ++g_iter) {
00159     std::cout << "Add gate " << (*g_iter)->get_name() << " to module " << dst_mod->get_name() << std::endl;
00160 
00161     dst_mod->add_gate(*g_iter);
00162   }
00163 
00164   for(module_collection::iterator iter = modules.begin();
00165       iter != modules.end(); ++iter)
00166     (*iter)->move_gates_recursive(dst_mod);
00167 }
00168 
00169 Module::module_collection::iterator Module::modules_begin() {
00170   return modules.begin();
00171 }
00172 
00173 Module::module_collection::iterator Module::modules_end() {
00174   return modules.end();
00175 }
00176 
00177 Module::gate_collection::iterator Module::gates_begin() {
00178   return gates.begin();
00179 }
00180 
00181 Module::gate_collection::iterator Module::gates_end() {
00182   return gates.end();
00183 }
00184 
00185 Module::port_collection::iterator Module::ports_begin() {
00186   return ports.begin();
00187 }
00188 
00189 Module::port_collection::iterator Module::ports_end() {
00190   return ports.end();
00191 }
00192 
00193 Module::module_collection::const_iterator Module::modules_begin() const {
00194   return modules.begin();
00195 }
00196 
00197 Module::module_collection::const_iterator Module::modules_end() const {
00198   return modules.end();
00199 }
00200 
00201 Module::gate_collection::const_iterator Module::gates_begin() const {
00202   return gates.begin();
00203 }
00204 
00205 Module::gate_collection::const_iterator Module::gates_end() const {
00206   return gates.end();
00207 }
00208 
00209 Module::port_collection::const_iterator Module::ports_begin() const {
00210   return ports.begin();
00211 }
00212 
00213 Module::port_collection::const_iterator Module::ports_end() const {
00214   return ports.end();
00215 }
00216 
00217 
00218 void Module::automove_gates() {
00219   /*
00220     from top to down in the module hierarchy:
00221 
00222     for each module: iterate over gates:
00223 
00224       iterate over gate ports:
00225       - port unconnected - ignore
00226       - port connected - check all related
00227 
00228    */
00229 }
00230 
00231 
00232 bool Module::net_completely_internal(Net_shptr net) const {
00233   for(Net::connection_iterator c_iter = net->begin(); c_iter != net->end(); ++c_iter) {
00234     
00235     object_id_t oid = *c_iter;   
00236     GatePort_shptr gport = lookup_gate_port_recursive(oid);
00237     if(gport == NULL) { // external entity
00238       return false;
00239     }
00240   }
00241   return true;
00242 }
00243 
00244 bool Module::net_feeded_internally(Net_shptr net) const {
00245   for(Net::connection_iterator c_iter = net->begin(); c_iter != net->end(); ++c_iter) {
00246     
00247     object_id_t oid = *c_iter;   
00248     GatePort_shptr gport = lookup_gate_port_recursive(oid);
00249     
00250     if(gport != NULL) { // internal entity
00251       GateTemplatePort_shptr tmpl_port = gport->get_template_port();
00252       if(tmpl_port->is_outport()) return true;
00253     }
00254   }
00255   return false;
00256 }
00257 
00258 
00259 std::string gate_port_already_named(degate::Module::port_collection const& ports, degate::GatePort_shptr gate_port) {
00260   for(Module::port_collection::const_iterator iter = ports.begin(); iter != ports.end(); ++iter) {
00261     if(iter->second == gate_port) return iter->first;
00262   }
00263   return "";
00264 }
00265 
00266 
00267 void Module::determine_module_ports() {
00268   
00269   if (is_main_module()) {
00270     throw std::logic_error("determine_module_ports() is not suited for main modules. See determine_module_ports_for_root().");
00271   }
00272   
00273   int pnum = 0;
00274   port_collection new_ports;
00275   std::set<Net_shptr> known_net;
00276 
00277   for(gate_collection::iterator g_iter = gates_begin(); g_iter != gates_end(); ++g_iter) {
00278 
00279     Gate_shptr gate = *g_iter;
00280     assert(gate != NULL);
00281 
00282     for(Gate::port_const_iterator p_iter = gate->ports_begin(); p_iter != gate->ports_end(); ++p_iter) {
00283 
00284       GatePort_shptr gate_port = *p_iter;
00285       assert(gate_port != NULL);
00286 
00287       Net_shptr net = gate_port->get_net();
00288       std::cout << "Check net for object gate port " << gate_port->get_descriptive_identifier() << "?\n";
00289 
00290       bool net_already_processed = known_net.find(net) != known_net.end();
00291       if((net != NULL) && !net_already_processed && !net_completely_internal(net)) {
00292 
00293         bool is_a_port = false;
00294  
00295         for(Net::connection_iterator c_iter = net->begin(); c_iter != net->end() && !is_a_port; ++c_iter) {
00296 
00297           object_id_t oid = *c_iter;
00298 
00299           if(!exists_gate_port_recursive(oid)) { // outbound connection
00300 
00301             // Now we check, whether the connection is feeded by an outside entity or feeded
00302             // from this module.
00303             // Problem: We can't see the object outside this module, because we only have an
00304             // object ID and no logic model object to look up the object ID. Therefore we have
00305             // to derive the state of feeding from the objects we have in this or any sub-module.
00306             // If we see only in-ports in the net, the module port must be driven by an outside
00307             // port.
00308 
00309             GateTemplatePort_shptr tmpl_port = gate_port->get_template_port();
00310             assert(tmpl_port != NULL); // if a gate has no standard cell type, the gate cannot have a port
00311             
00312             if(net_feeded_internally(net) && tmpl_port->is_inport()) {
00313               std::cout << "  Net feeded internally, but port is inport. Will check where the net is driven.\n";        
00314             }
00315             else {
00316               std::string mod_port_name = gate_port_already_named(ports, gate_port);
00317               if(mod_port_name == "") {
00318 
00319                 // generate a new port name and check if the port name is already in use
00320                 do {
00321                   pnum++;
00322                   boost::format f("p%1%");
00323                   f % pnum;
00324                   mod_port_name = f.str();              
00325                 }while(ports.find(mod_port_name) != ports.end());
00326               }
00327               
00328               std::cout << "  New module port: " << gate_port->get_descriptive_identifier() << " == "
00329                         << mod_port_name << "\n";
00330               new_ports[mod_port_name] = gate_port;
00331               
00332               is_a_port = true;
00333               std::cout << "  Set net as known net: " << net->get_descriptive_identifier() << "\n";
00334               known_net.insert(net);
00335             }
00336           }
00337         }
00338       }
00339       else if(net == NULL) {
00340         std::cout << "  Will not check net -- no net.\n";
00341       }
00342       else if(net_already_processed) {
00343         std::cout << "  Will not check net -- already processed " << net->get_descriptive_identifier() << ".\n";
00344       }
00345     }
00346   }
00347   
00348 
00349   // check sub-modules
00350   BOOST_FOREACH(Module_shptr sub, modules) {
00351     
00352     BOOST_FOREACH(port_collection::value_type const& p, sub->ports) {
00353       std::string mod_port_name = p.first;
00354       GatePort_shptr gate_port = p.second;
00355       Net_shptr net = gate_port->get_net();
00356 
00357       bool net_already_processed = known_net.find(net) != known_net.end();
00358       
00359       if(net != NULL && !net_already_processed && !net_completely_internal(net)) { // outbound connection
00360         new_ports[mod_port_name] = gate_port;
00361       }    
00362     }
00363   }
00364   ports = new_ports;
00365 
00366 }
00367 
00368 void Module::determine_module_ports_recursive() {
00369   for (module_collection::iterator it = modules.begin(); it != modules.end(); ++it) {
00370     (*it)->determine_module_ports();
00371     (*it)->determine_module_ports_recursive();
00372   }
00373 }
00374 
00375 void Module::add_module_port(std::string const& module_port_name, GatePort_shptr adjacent_gate_port) {
00376   ports[module_port_name] = adjacent_gate_port;
00377 }
00378 
00379 bool Module::exists_gate_port_recursive(object_id_t oid) const {
00380   return lookup_gate_port_recursive(oid) != NULL;
00381 }
00382 
00383 GatePort_shptr Module::lookup_gate_port_recursive(object_id_t oid) const {
00384   assert(oid != 0);
00385 
00386   for(gate_collection::const_iterator g_iter = gates.begin();
00387       g_iter != gates.end(); ++g_iter) {
00388 
00389     Gate_shptr gate = *g_iter;
00390 
00391     for(Gate::port_const_iterator p_iter = gate->ports_begin();
00392         p_iter != gate->ports_end(); ++p_iter)
00393       if((*p_iter)->get_object_id() == oid) return *p_iter;
00394   }
00395 
00396   for(module_collection::const_iterator iter = modules.begin();
00397       iter != modules.end(); ++iter)
00398     if(GatePort_shptr gport = (*iter)->lookup_gate_port_recursive(oid)) return gport;
00399 
00400   return GatePort_shptr();
00401 }
00402 
00403 
00404 
00405 
00406 void degate::determine_module_ports_for_root(LogicModel_shptr lmodel) {
00407   debug(TM, "Check for module ports.");
00408   /*
00409     Iterate over all gate and check their ports.
00410     Get the net for a port.
00411     Iterate over net.
00412     If a net contains a emarker with a description of 'module-port', use
00413     gate port as module port.
00414    */
00415 
00416   Module_shptr main_module = lmodel->get_main_module();
00417 
00418   main_module->ports.clear(); // reset ports
00419 
00420   for(Module::gate_collection::iterator g_iter = main_module->gates_begin(); 
00421       g_iter != main_module->gates_end(); ++g_iter) {
00422 
00423     Gate_shptr gate = *g_iter;
00424     assert(gate != NULL);
00425 
00426     for(Gate::port_const_iterator p_iter = gate->ports_begin(); p_iter != gate->ports_end(); ++p_iter) {
00427 
00428       GatePort_shptr gate_port = *p_iter;
00429       assert(gate_port != NULL);
00430 
00431       Net_shptr net = gate_port->get_net();
00432       bool is_a_port = false;
00433 
00434       if(net != NULL) {
00435 
00436         for(Net::connection_iterator c_iter = net->begin(); c_iter != net->end() && !is_a_port; ++c_iter) {
00437           
00438           object_id_t oid = *c_iter;
00439           assert(oid != 0);
00440           
00441           PlacedLogicModelObject_shptr lmo = lmodel->get_object(oid);
00442           if(EMarker_shptr em = std::dynamic_pointer_cast<EMarker>(lmo)) {
00443             debug(TM, "Connected with emarker");
00444 
00445             if(em->get_description() == "module-port") {
00446               
00447               GateTemplatePort_shptr tmpl_port = gate_port->get_template_port();
00448               assert(tmpl_port != NULL); // if a gate has no standard cell type, the gate cannot have a port
00449               
00450               main_module->ports[em->get_name()] = gate_port;
00451               is_a_port = true;
00452             }
00453           }
00454         } 
00455             
00456       } // end of net-object-iteration
00457     } // end of gate-portiteration
00458   } // end of gate-iteration
00459 
00460 }
00461 
00462 
00463 
00464 Module_shptr Module::lookup_module(std::string const& module_path) const {
00465 
00466 
00467   std::list<std::string> path_elements;
00468   boost::split(path_elements, module_path, boost::is_any_of("/"));
00469   
00470   if(is_main_module()) {
00471 
00472     // handle absolut path
00473     while(path_elements.size() > 0 &&
00474           get_name() != path_elements.front()) {
00475       path_elements.pop_front();
00476     }
00477   }
00478 
00479   if(path_elements.size() == 0)
00480     return Module_shptr();
00481 
00482 
00483   // leading path element should equals current module name
00484   if(get_name() != path_elements.front())
00485     return Module_shptr();
00486   else {
00487     path_elements.pop_front();
00488     return lookup_module(path_elements); // first real name is name of the main module, skipped
00489   }
00490 
00491 }
00492 
00493 Module_shptr Module::lookup_module(std::list<std::string> & path_elements) const {
00494   
00495   if(path_elements.size() > 0) {
00496 
00497     BOOST_FOREACH(Module_shptr m, modules) {
00498 
00499       if(m->get_name() == path_elements.front()) {
00500 
00501         if(path_elements.size() == 1)
00502           return m;
00503         else {
00504           path_elements.pop_front();
00505           return m->lookup_module(path_elements);
00506         }
00507       }
00508 
00509     }
00510   }
00511 
00512   return Module_shptr();
00513 }
00514 
00515 void Module::set_module_port_name(std::string const& module_port_name, GatePort_shptr adjacent_gate_port) {
00516 
00517   for(Module::port_collection::const_iterator iter = ports.begin(); iter != ports.end(); ++iter) {
00518     if(iter->second == adjacent_gate_port) {
00519       ports.erase(iter->first);
00520       ports[module_port_name] = adjacent_gate_port;
00521       return;
00522     }
00523   }
00524   
00525 }
00526 
00527 
00528 boost::optional<std::string> Module::lookup_module_port_name(GatePort_shptr gate_port) {
00529   
00530   for(Module::port_collection::const_iterator iter = ports.begin(); iter != ports.end(); ++iter) {
00531     if(iter->second == gate_port) {
00532       return boost::optional<std::string>(iter->first);
00533     }
00534   }
00535   return boost::optional<std::string>();
00536 }
00537 
00538 
00539 bool Module::exists_module_port_name(std::string const& module_port_name) const {
00540   return ports.find(module_port_name) != ports.end();
00541 }