|
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 <VerilogTBCodeTemplateGenerator.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 VerilogTBCodeTemplateGenerator::VerilogTBCodeTemplateGenerator(std::string const& entity_name, 00032 std::string const& description, 00033 std::string const& logic_class) : 00034 VerilogCodeTemplateGenerator(entity_name, description, logic_class) { 00035 } 00036 00037 VerilogTBCodeTemplateGenerator::~VerilogTBCodeTemplateGenerator() { 00038 } 00039 00040 std::string VerilogTBCodeTemplateGenerator::generate() const { 00041 00042 port_map_type port_map; 00043 BOOST_FOREACH(std::string const& port_name, get_inports()) 00044 port_map[port_name] = port_name; 00045 BOOST_FOREACH(std::string const& port_name, get_outports()) 00046 port_map[port_name] = port_name; 00047 00048 return 00049 generate_header() + 00050 generate_module(entity_name); 00051 00052 } 00053 00054 std::string VerilogTBCodeTemplateGenerator::generate_header() const { 00055 boost::format f("/**\n" 00056 " * This is Verilog testbench for a gate of type %1%\n" 00057 " *\n" 00058 " * Please customize this code template according to your needs.\n" 00059 " */\n\n" 00060 "`timescale 1ns/100ps\n" 00061 "\n\n"); 00062 f % entity_name; 00063 return f.str(); 00064 } 00065 00066 00067 std::string VerilogTBCodeTemplateGenerator::generate_module(std::string const& device_type_name) const { 00068 00069 std::string inports = 00070 boost::algorithm::join(generate_identifier<std::vector<std::string> >(get_inports()), ", "); 00071 00072 std::string outports = 00073 boost::algorithm::join(generate_identifier<std::vector<std::string> >(get_outports()), ", "); 00074 00075 std::list<std::string> port_wiring; 00076 BOOST_FOREACH(std::string const & pname, 00077 generate_identifier(get_ports())) { 00078 boost::format f(".%1%(%2%)"); 00079 f % pname % pname; 00080 port_wiring.push_back(f.str()); 00081 } 00082 00083 std::string inport_init; 00084 BOOST_FOREACH(std::string const & pname, 00085 generate_identifier(get_inports())) { 00086 boost::format f(" %1% <= 1'b0;\n"); 00087 f % pname; 00088 inport_init += f.str(); 00089 } 00090 00091 boost::format f("module testbench_%1%;\n" 00092 " reg %2%;\n" 00093 " wire %3%;\n" 00094 "\n" 00095 " // helper task to simulate a C-style assert() function\n" 00096 " task assert;\n" 00097 " input asserted_value;\n" 00098 " begin\n" 00099 " if(!asserted_value) begin\n" 00100 " $display(\"Assertion failed.\");\n" 00101 " $finish;\n" 00102 " end\n" 00103 " end\n" 00104 " endtask\n" 00105 "\n" 00106 " // create an instance of the device to test\n" 00107 " %4% unit(%5%);\n" 00108 "\n" 00109 " // initialize\n" 00110 " initial begin\n" 00111 " // Enable signal dumping\n" 00112 " // Generate a VCD dump file. Please, do not change the filename.\n" 00113 " $dumpfile(\"test.vcd\"); \n" 00114 " $dumpvars(0, testbench_%6%); // for this module\n" 00115 "\n" 00116 " // initialize signals on ports\n" 00117 "%7%" 00118 " end\n" 00119 "\n" 00120 " initial begin\n" 00121 " #10; // wait 10 ns for port initialisation\n" 00122 "\n" 00123 "%8%" 00124 "\n" 00125 " #10; // wait 10 ns\n" 00126 "\n" 00127 " end\n" 00128 "\n" 00129 "endmodule // testbench_%9%"); 00130 f % generate_identifier(device_type_name, "dg_") 00131 % inports 00132 % outports 00133 % generate_identifier(device_type_name, "dg_") % boost::algorithm::join(port_wiring, ", ") 00134 % generate_identifier(device_type_name, "dg_") 00135 % inport_init 00136 00137 % generate_all_assignments(get_inports(), get_outports()) 00138 00139 % generate_identifier(device_type_name, "dg_"); 00140 00141 return f.str(); 00142 } 00143 00144 00145 /** 00146 * Recursive implementation of an increment function. 00147 * Starts with MSB and increments until position right to LSB is reached. 00148 * @return Returns false, if there is nothing to do. 00149 */ 00150 bool increment(std::vector<int> & assignment, size_t pos = 0) { 00151 if(assignment.size() == 0) return false; 00152 00153 // toggle lsb 00154 if(assignment[pos] == 0) { 00155 assignment[pos] = 1; 00156 return true; 00157 } 00158 else { 00159 assignment[pos] = 0; 00160 if(pos + 1 == assignment.size()) return false; 00161 else return increment(assignment, pos + 1); 00162 } 00163 00164 } 00165 00166 std::string VerilogTBCodeTemplateGenerator::generate_all_assignments 00167 (std::vector<std::string> const& in_port_idents, 00168 std::vector<std::string> const& out_port_idents) const { 00169 00170 // left side: {a, b, c, ... } 00171 std::string assignment_dst = 00172 "{" + 00173 boost::algorithm::join(generate_identifier<std::vector<std::string> >(in_port_idents), ", ") + 00174 "}"; 00175 00176 // right side prefix 00177 boost::format f_prefix("%1%'b"); 00178 f_prefix % in_port_idents.size(); 00179 std::string prefix = f_prefix.str(); 00180 00181 00182 std::string testcode; 00183 00184 std::vector<int> assignment(in_port_idents.size()); // initialized with 0 00185 while(increment(assignment)) { 00186 00187 std::string assignment2; 00188 BOOST_FOREACH(int i, assignment) 00189 assignment2.push_back(boost::lexical_cast<char>(i)); 00190 std::reverse(assignment2.begin(), assignment2.end()); 00191 00192 // generate assignemt string 00193 boost::format f(" %1% = %2%%3%;\n" 00194 " #10;\n"); 00195 f % assignment_dst % prefix % assignment2; 00196 00197 testcode += f.str(); 00198 BOOST_FOREACH(std::string const& oport, 00199 generate_identifier<std::vector<std::string> >(out_port_idents)) { 00200 boost::format f2(" assert(%1% === 1'bX); // please edit\n\n"); 00201 f2 % oport; 00202 testcode += f2.str(); 00203 } 00204 00205 } 00206 00207 return testcode; 00208 } 00209
1.7.4