|
degate 0.1.1
|
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 }
1.7.4