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