degate  0.1.2
VerilogModuleGenerator.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 
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 }