degate  0.1.2
VHDLCodeTemplateGenerator.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 <VHDLCodeTemplateGenerator.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 VHDLCodeTemplateGenerator::VHDLCodeTemplateGenerator(std::string const& entity_name,
00032                                                      std::string const& description,
00033                                                      std::string const& logic_class) :
00034   CodeTemplateGenerator(entity_name, description, logic_class) {
00035 }
00036 
00037 
00038 VHDLCodeTemplateGenerator::~VHDLCodeTemplateGenerator() {
00039 }
00040 
00041 std::string VHDLCodeTemplateGenerator::generate() const {
00042   return
00043     generate_header() +
00044     generate_entity(entity_name, generate_port_description()) +
00045     generate_architecture(entity_name, "", generate_impl(logic_class));
00046 }
00047 
00048 std::string VHDLCodeTemplateGenerator::generate_header() const {
00049   boost::format f("--\n"
00050                   "-- This is a VHDL implementation for a gate of type %1%\n"
00051                   "--\n"
00052                   "-- Please customize this code template according to your needs.\n\n"
00053                   "library ieee;\n"
00054                   "use ieee.std_logic_1164.all;\n\n");
00055   f % entity_name;
00056   return f.str();
00057 }
00058 
00059 std::string VHDLCodeTemplateGenerator::generate_port_description() const {
00060 
00061   boost::format f("  port(%1% : in std_logic;\n"
00062                   "       %2% : out std_logic);\n");
00063   f % boost::algorithm::join(generate_identifier<std::vector<std::string> >(get_inports()), ", ")
00064     % boost::algorithm::join(generate_identifier<std::vector<std::string> >(get_outports()), ", ");
00065   return f.str();
00066 }
00067 
00068 
00069 std::string VHDLCodeTemplateGenerator::generate_entity(std::string const& entity_name,
00070                                                        std::string const& port_description) const {
00071 
00072   boost::format f("entity %1% is\n"
00073                   "%2%"
00074                   "end %3%;\n\n");
00075   f % generate_identifier(entity_name, "dg_")
00076     % port_description
00077     % generate_identifier(entity_name, "dg_");
00078   return f.str();
00079 }
00080 
00081 std::string VHDLCodeTemplateGenerator::generate_component(std::string const& entity_name,
00082                                                                   std::string const& port_description) const {
00083 
00084   boost::format f("  component %1% is\n"
00085                   "%2%"
00086                   "  end component;\n\n");
00087   f % generate_identifier(entity_name, "dg_")
00088     % port_description;
00089   return f.str();
00090 }
00091 
00092 std::string VHDLCodeTemplateGenerator::generate_impl(std::string const& logic_class) const {
00093 
00094   std::vector<std::string> in = get_inports();
00095   std::vector<std::string> out = get_outports();
00096 
00097   std::string clock_name = get_port_name_by_type(CLOCK);
00098   if(clock_name.empty()) clock_name = "clock";
00099   std::string reset_name = get_port_name_by_type(RESET);
00100   if(reset_name.empty()) reset_name = "reset";
00101 
00102   if(logic_class == "inverter" &&
00103      in.size() == 1 && out.size() == 1) {
00104     boost::format f("  %1% <= not %2%;");
00105     f % generate_identifier(out[0]) % generate_identifier(in[0]);
00106     return f.str();
00107   }
00108   else if((logic_class == "xor" ||
00109            logic_class == "or" ||
00110            logic_class == "and" ||
00111            logic_class == "nor" ||
00112            logic_class == "nand" ||
00113            logic_class == "xnor") &&
00114           in.size() >= 2 && out.size() == 1) {
00115 
00116     std::string inner_op, outer_op = "not";
00117 
00118     if(logic_class == "nand") inner_op = "and";
00119     else if(logic_class == "nor") inner_op = "or";
00120     else if(logic_class == "xnor") inner_op = "xor";
00121     else {
00122       outer_op = "";
00123       inner_op = logic_class;
00124     }
00125 
00126     boost::format f("  %1% <= %2%%3%%4%%5%;");
00127     f % generate_identifier(out[0])
00128       % outer_op
00129       % (outer_op.empty() ? "" : "(")
00130       % boost::algorithm::join(generate_identifier<std::vector<std::string> >(in),
00131                                std::string(" ") + inner_op + std::string(" "))
00132       % (outer_op.empty() ? "" : ")");
00133 
00134     return f.str();
00135   }
00136   else if(logic_class == "flipflop-async-rst") {
00137     boost::format f(
00138       "  -- \n"
00139       "  -- Please implement behaviour.\n"
00140       "  -- \n"
00141       "  -- process(%1%, %2%)\n"
00142       "  -- begin\n"
00143       "  --  if %3% = '1' then   -- or '0' if RESET is active low...\n"
00144       "  --    Q <= '0';\n"
00145       "  --  elsif rising_edge(%4%) then\n"
00146       "  --    if Enable = '1' then  -- or '0' if Enable is active low...\n"
00147       "  --      Q <= D;\n"
00148       "  --    end if;\n"
00149       "  --   end if;\n"
00150       "  -- end process;\n");
00151     f % clock_name % reset_name
00152       % reset_name
00153       % clock_name;
00154     return f.str();
00155   }
00156   else if(logic_class == "flipflop-sync-rst") {
00157     boost::format f(
00158       "  -- \n"
00159       "  -- Please implement behaviour.\n"
00160       "  -- \n"
00161       "  -- process(%1%)\n"
00162       "  -- begin\n"
00163       "  --   if rising_edge(%2%) then\n"
00164       "  --     if RESET = '1' then\n"
00165       "  --       Q <= '0';\n"
00166       "  --     elsif Enable = '1' then  -- or '0' if Enable is active low...\n"
00167       "  --       Q <= D;\n"
00168       "  --     end if;\n"
00169       "  --   end if;\n"
00170       "  -- end process;\n");
00171     f % clock_name % clock_name;
00172     return f.str();
00173   }
00174   else {
00175     return
00176       "  -- \n"
00177       "  -- Please implement behaviour.\n"
00178       "  -- \n";
00179   }
00180 }
00181 
00182 std::string VHDLCodeTemplateGenerator::generate_architecture(std::string const& entity_name,
00183                                                              std::string const& header,
00184                                                              std::string const& impl) const {
00185 
00186   boost::format f("architecture Behavioral of %1% is\n"
00187                   "%2%\n"
00188                   "begin\n"
00189                   "%3%\n"
00190                   "end Behavioral;\n\n");
00191   f % generate_identifier(entity_name, "dg_")
00192     % header
00193     % impl;
00194   return f.str();
00195 }
00196 
00197 std::string VHDLCodeTemplateGenerator::generate_identifier(std::string const& name, 
00198                                                            std::string const& prefix) const {
00199   std::string identifier = prefix;
00200 
00201   bool first_char = true;
00202   BOOST_FOREACH(char c, name) {
00203     if(c == '/' || c == '!') identifier.append("not");
00204     else if(first_char && !isalpha(c)) {
00205       //identifier.append("entity_");
00206       identifier.push_back(c);
00207     }
00208     else if(isalnum(c)) identifier.push_back(c);
00209     else identifier.push_back('_');
00210 
00211     first_char = false;
00212   }
00213   return identifier;
00214 }
00215 
00216 
00217 std::string VHDLCodeTemplateGenerator::generate_instance(std::string const& instance_name,
00218                                                          std::string const& instance_type,
00219                                                          port_map_type const& port_map) const {
00220 
00221   std::list<std::string> port_map_str;
00222 
00223   BOOST_FOREACH(port_map_type::value_type p, port_map) {
00224     boost::format m("    %1% => %2%");
00225     m % generate_identifier(p.first) % generate_identifier(p.second);
00226     port_map_str.push_back(m.str());
00227   }
00228 
00229   boost::format f("  %1% : %2% port map (\n%3%\n  );\n\n\n");
00230   f % generate_identifier(instance_name)
00231     % generate_identifier(instance_type, "dg_")
00232     % boost::algorithm::join(port_map_str, ",\n");
00233   return f.str();
00234 }