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