|
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 00023 #include <VerilogModuleGenerator.h> 00024 #include <boost/format.hpp> 00025 #include <boost/foreach.hpp> 00026 #include <boost/algorithm/string/join.hpp> 00027 00028 using namespace boost; 00029 using namespace degate; 00030 00031 VerilogModuleGenerator::VerilogModuleGenerator(Module_shptr module, bool do_not_output_gates /* = false */) : 00032 VerilogCodeTemplateGenerator(module->get_name(), module->get_entity_name()), 00033 mod(module), 00034 no_gates(do_not_output_gates) { 00035 00036 // set module ports 00037 for(Module::port_collection::const_iterator iter = module->ports_begin(); 00038 iter != module->ports_end(); ++iter) { 00039 00040 const std::string mod_port_name = iter->first; 00041 const GatePort_shptr gp = iter->second; 00042 const GateTemplatePort_shptr tmpl_port = gp->get_template_port(); 00043 assert(tmpl_port != NULL); 00044 add_port(mod_port_name, tmpl_port->is_inport()); 00045 } 00046 00047 } 00048 00049 00050 VerilogModuleGenerator::~VerilogModuleGenerator() { 00051 } 00052 00053 00054 std::string VerilogModuleGenerator::generate_common_code_for_gates(Module_shptr module, 00055 std::set<GateTemplate_shptr> & already_dumped) const { 00056 std::string common_code; 00057 00058 if(!no_gates) { 00059 for(Module::gate_collection::const_iterator iter = module->gates_begin(); 00060 iter != module->gates_end(); ++iter) { 00061 Gate_shptr gate = *iter; 00062 00063 if(GateTemplate_shptr gtmpl = gate->get_gate_template()) { 00064 00065 if(already_dumped.find(gtmpl) == already_dumped.end()) { 00066 00067 try { 00068 common_code += gtmpl->get_implementation(GateTemplate::VERILOG); 00069 } 00070 catch(CollectionLookupException const& ex) { 00071 // maybe we should pass the exception? 00072 common_code += "// Error: failed to lookup Verilog implementation for module " + gtmpl->get_name() + ".\n\n"; 00073 } 00074 already_dumped.insert(gtmpl); 00075 } 00076 } 00077 } 00078 } 00079 00080 // traverse sub-modules 00081 for(Module::module_collection::const_iterator iter = module->modules_begin(); 00082 iter != module->modules_end(); ++iter) { 00083 00084 Module_shptr sub = *iter; 00085 common_code += generate_common_code_for_gates(sub, already_dumped); 00086 00087 VerilogModuleGenerator codegen(sub, true); 00088 common_code += codegen.generate(); 00089 00090 } 00091 00092 return common_code; 00093 } 00094 00095 std::string VerilogModuleGenerator::generate_common() const { 00096 std::set<GateTemplate_shptr> already_dumped; 00097 return generate_common_code_for_gates(mod, already_dumped); 00098 } 00099 00100 std::string VerilogModuleGenerator::generate_impl(std::string const& logic_class /* unused parameter */ ) const { 00101 00102 std::string impl; 00103 std::string wire_definitions; 00104 00105 unsigned int wire_counter = 0; 00106 00107 typedef std::map<object_id_t /* net */, std::string> net_names_table; 00108 net_names_table nets; 00109 00110 00111 // generate signal names 00112 for(Module::gate_collection::const_iterator iter = mod->gates_begin(); 00113 iter != mod->gates_end(); ++iter) { 00114 00115 Gate_shptr gate = *iter; 00116 GateTemplate_shptr gate_tmpl = gate->get_gate_template(); 00117 for(Gate::port_const_iterator p_iter = gate->ports_begin(); p_iter != gate->ports_end(); ++p_iter) { 00118 const GatePort_shptr gport = *p_iter; 00119 if(gport->is_connected()) { 00120 const Net_shptr net = gport->get_net(); 00121 00122 // first, check if the gate port is directly adjacent to a module port 00123 boost::optional<std::string> is_module_port = mod->lookup_module_port_name(gport); 00124 if(is_module_port) { 00125 nets[net->get_object_id()] = *is_module_port; 00126 } 00127 else if(nets.find(net->get_object_id()) == nets.end()) { 00128 boost::format f("w%1%"); 00129 f % (wire_counter++); 00130 nets[net->get_object_id()] = f.str(); 00131 } 00132 } 00133 } 00134 } 00135 00136 00137 for(Module::module_collection::const_iterator iter = mod->modules_begin(); 00138 iter != mod->modules_end(); ++iter) { 00139 00140 Module_shptr sub = *iter; 00141 std::list<std::string> ports; 00142 00143 // iterate over its module ports 00144 for(Module::port_collection::const_iterator p_iter = sub->ports_begin(); 00145 p_iter != sub->ports_end(); ++p_iter) { 00146 00147 std::string const& submod_port_name= p_iter->first; 00148 const GatePort_shptr gport = p_iter->second; 00149 00150 if(gport->is_connected()) { 00151 const Net_shptr net = gport->get_net(); 00152 00153 nets[net->get_object_id()] = submod_port_name; 00154 } 00155 } 00156 } 00157 00158 00159 // genereate wire definitions 00160 BOOST_FOREACH(net_names_table::value_type const& v, nets) { 00161 if(!mod->exists_module_port_name(v.second)) 00162 wire_definitions += " wire " + v.second + ";\n"; 00163 } 00164 00165 00166 00167 // place single standard cells 00168 00169 for(Module::gate_collection::const_iterator iter = mod->gates_begin(); 00170 iter != mod->gates_end(); ++iter) { 00171 00172 Gate_shptr gate = *iter; 00173 GateTemplate_shptr gate_tmpl = gate->get_gate_template(); 00174 00175 std::list<std::string> ports; 00176 00177 for(Gate::port_const_iterator p_iter = gate->ports_begin(); p_iter != gate->ports_end(); ++p_iter) { 00178 const GatePort_shptr gport = *p_iter; 00179 const GateTemplatePort_shptr tmpl_port = gport->get_template_port(); 00180 00181 if(gport->is_connected()) { 00182 const Net_shptr net = gport->get_net(); 00183 00184 std::string port_name = generate_identifier(tmpl_port->get_name()); 00185 std::transform(port_name.begin(), port_name.end(), port_name.begin(), ::tolower); 00186 00187 boost::format f(" .%1% (%2%)"); 00188 f % port_name 00189 % nets[net->get_object_id()]; 00190 ports.push_back(f.str()); 00191 } 00192 } 00193 00194 00195 boost::format gate_placement(" %1% %2% (\n" 00196 "%3% );\n\n"); 00197 gate_placement 00198 % generate_identifier(gate_tmpl->get_name(), "dg_") 00199 % generate_identifier(gate->get_name()) 00200 % boost::algorithm::join(ports, ",\n"); 00201 00202 impl += gate_placement.str(); 00203 } 00204 00205 00206 // place sub-modules 00207 for(Module::module_collection::const_iterator iter = mod->modules_begin(); 00208 iter != mod->modules_end(); ++iter) { 00209 00210 Module_shptr sub = *iter; 00211 std::list<std::string> ports; 00212 00213 // iterate over its module ports 00214 for(Module::port_collection::const_iterator p_iter = sub->ports_begin(); 00215 p_iter != sub->ports_end(); ++p_iter) { 00216 00217 std::string const& submod_port_name= p_iter->first; 00218 const GatePort_shptr gport = p_iter->second; 00219 00220 if(gport->is_connected()) { 00221 const Net_shptr net = gport->get_net(); 00222 00223 boost::format f(" .%1% (%2%)"); 00224 f % submod_port_name 00225 % nets[net->get_object_id()]; 00226 ports.push_back(f.str()); 00227 } 00228 } 00229 00230 00231 boost::format gate_placement(" %1% %2% (\n" 00232 "%3% );\n\n"); 00233 gate_placement 00234 % generate_identifier(sub->get_entity_name() != "" ? sub->get_entity_name() : sub->get_name() , "dg_") 00235 % generate_identifier(sub->get_name()) 00236 % boost::algorithm::join(ports, ",\n"); 00237 00238 impl += gate_placement.str(); 00239 00240 } 00241 00242 00243 // place sub-modules 00244 return 00245 (wire_definitions != "" ? " // net definitions\n" : "") + 00246 wire_definitions + "\n" + 00247 " // sub-modules\n\n" + 00248 impl; 00249 }
1.7.4