28 static std::string
id(std::string internal_id)
30 const char *str = internal_id.c_str();
31 bool do_escape =
false;
36 if (
'0' <= *str && *str <=
'9')
39 for (
int i = 0; str[i]; i++) {
40 if (
'0' <= str[i] && str[i] <=
'9')
42 if (
'a' <= str[i] && str[i] <=
'z')
44 if (
'A' <= str[i] && str[i] <=
'Z')
53 return "\\" + std::string(str) +
" ";
54 return std::string(str);
57 static std::string
idx(std::string str)
64 static std::string
idy(std::string str1, std::string str2 = std::string(), std::string str3 = std::string())
68 str1 +=
"_" +
idx(str2);
70 str1 +=
"_" +
idx(str3);
76 f <<
stringf(
"module testbench;\n\n");
80 f <<
stringf(
"reg [31:0] xorshift128_x = 123456789;\n");
81 f <<
stringf(
"reg [31:0] xorshift128_y = 362436069;\n");
82 f <<
stringf(
"reg [31:0] xorshift128_z = 521288629;\n");
83 f <<
stringf(
"reg [31:0] xorshift128_w = %u; // <-- seed value\n",
int(
time(
NULL)));
84 f <<
stringf(
"reg [31:0] xorshift128_t;\n\n");
85 f <<
stringf(
"task xorshift128;\n");
87 f <<
stringf(
"\txorshift128_t = xorshift128_x ^ (xorshift128_x << 11);\n");
88 f <<
stringf(
"\txorshift128_x = xorshift128_y;\n");
89 f <<
stringf(
"\txorshift128_y = xorshift128_z;\n");
90 f <<
stringf(
"\txorshift128_z = xorshift128_w;\n");
91 f <<
stringf(
"\txorshift128_w = xorshift128_w ^ (xorshift128_w >> 19) ^ xorshift128_t ^ (xorshift128_t >> 8);\n");
97 std::map<std::string, int> signal_in;
98 std::map<std::string, std::string> signal_const;
99 std::map<std::string, int> signal_clk;
100 std::map<std::string, int> signal_out;
104 if (mod->get_bool_attribute(
"\\gentb_skip"))
108 log(
"Generating test bench for module `%s'.\n", it->first.c_str());
109 for (
auto it2 = mod->
wires_.begin(); it2 != mod->
wires_.end(); it2++) {
117 bool is_clksignal = wire->get_bool_attribute(
"\\gentb_clock");
119 for (
auto it4 = it3->second->syncs.begin(); it4 != it3->second->syncs.end(); it4++) {
123 for (
auto &c : signal.
chunks())
127 if (is_clksignal && wire->attributes.count(
"\\gentb_constant") == 0) {
131 if (wire->attributes.count(
"\\gentb_constant") != 0)
132 signal_const[
idy(
"sig", mod->
name.
str(), wire->
name.
str())] = wire->attributes[
"\\gentb_constant"].as_string();
138 for (
auto it2 = mod->
wires_.begin(); it2 != mod->
wires_.end(); it2++) {
142 idy(
"sig", mod->
name.
str(), wire->
name.
str()).c_str(), --count_ports ?
"," :
"");
148 int delay_counter = 0;
149 for (
auto it = signal_in.begin(); it != signal_in.end(); it++)
150 f <<
stringf(
"\t%s <= #%d 0;\n", it->first.c_str(), ++delay_counter*2);
151 for (
auto it = signal_clk.begin(); it != signal_clk.end(); it++)
152 f <<
stringf(
"\t%s <= #%d 0;\n", it->first.c_str(), ++delay_counter*2);
153 for (
auto it = signal_clk.begin(); it != signal_clk.end(); it++) {
154 f <<
stringf(
"\t#100; %s <= 1;\n", it->first.c_str());
155 f <<
stringf(
"\t#100; %s <= 0;\n", it->first.c_str());
158 for (
auto it = signal_in.begin(); it != signal_in.end(); it++)
159 f <<
stringf(
"\t%s <= #%d ~0;\n", it->first.c_str(), ++delay_counter*2);
160 for (
auto it = signal_clk.begin(); it != signal_clk.end(); it++) {
161 f <<
stringf(
"\t#100; %s <= 1;\n", it->first.c_str());
162 f <<
stringf(
"\t#100; %s <= 0;\n", it->first.c_str());
165 for (
auto it = signal_in.begin(); it != signal_in.end(); it++) {
166 if (signal_const.count(it->first) == 0)
168 f <<
stringf(
"\t%s <= #%d 'b%s;\n", it->first.c_str(), ++delay_counter*2, signal_const[it->first].c_str());
176 for (
auto it = signal_in.begin(); it != signal_in.end(); it++) {
177 if (signal_const.count(it->first) > 0)
179 f <<
stringf(
"\txorshift128;\n");
180 f <<
stringf(
"\t%s <= #%d { xorshift128_x, xorshift128_y, xorshift128_z, xorshift128_w };\n", it->first.c_str(), ++delay_counter*2);
187 if (signal_clk.size()) {
188 f <<
stringf(
"\txorshift128;\n");
190 int total_clock_bits = 0;
191 for (
auto it = signal_clk.begin(); it != signal_clk.end(); it++) {
192 f <<
stringf(
"%s %s", it == signal_clk.begin() ?
"" :
",", it->first.c_str());
193 total_clock_bits += it->second;
196 for (
auto it = signal_clk.begin(); it != signal_clk.end(); it++)
197 f <<
stringf(
"%s %s", it == signal_clk.begin() ?
"" :
",", it->first.c_str());
198 f <<
stringf(
" } ^ (%d'b1 << (xorshift128_w %% %d));\n", total_clock_bits, total_clock_bits);
203 char shorthand =
'A';
204 std::vector<std::string> header1;
205 std::string header2 =
"";
209 f <<
stringf(
"\t$display(\"#OUT# %%b %%b %%b %%t %%d\", {");
210 if (signal_in.size())
211 for (
auto it = signal_in.begin(); it != signal_in.end(); it++) {
212 f <<
stringf(
"%s %s", it == signal_in.begin() ?
"" :
",", it->first.c_str());
213 int len = it->second;
215 header2 +=
"/", len--;
217 header2 +=
"-", len--;
219 header2 += shorthand, len--;
220 header1.push_back(
" " + it->first);
221 header1.back()[0] = shorthand++;
229 if (signal_clk.size()) {
230 for (
auto it = signal_clk.begin(); it != signal_clk.end(); it++) {
231 f <<
stringf(
"%s %s", it == signal_clk.begin() ?
"" :
",", it->first.c_str());
232 int len = it->second;
234 header2 +=
"/", len--;
236 header2 +=
"-", len--;
238 header2 += shorthand, len--;
239 header1.push_back(
" " + it->first);
240 header1.back()[0] = shorthand++;
248 if (signal_out.size()) {
249 for (
auto it = signal_out.begin(); it != signal_out.end(); it++) {
250 f <<
stringf(
"%s %s", it == signal_out.begin() ?
"" :
",", it->first.c_str());
251 int len = it->second;
253 header2 +=
"/", len--;
255 header2 +=
"-", len--;
257 header2 += shorthand, len--;
258 header1.push_back(
" " + it->first);
259 header1.back()[0] = shorthand++;
265 f <<
stringf(
" }, $time, i);\n");
271 f <<
stringf(
"\t$display(\"#OUT#\");\n");
272 for (
auto &hdr : header1)
273 f <<
stringf(
"\t$display(\"#OUT# %s\");\n", hdr.c_str());
274 f <<
stringf(
"\t$display(\"#OUT#\");\n");
275 f <<
stringf(
"\t$display(\"#OUT# %s\");\n", header2.c_str());
281 f <<
stringf(
"\t$display(\"#OUT#\\n#OUT# ==== %s ====\");\n",
idy(mod->
name.
str()).c_str());
283 f <<
stringf(
"\tfor (i=0; i<%d; i=i+1) begin\n", num_iter);
284 f <<
stringf(
"\t\tif (i %% 20 == 0) %s;\n",
idy(mod->
name.
str(),
"print_header").c_str());
293 f <<
stringf(
"initial begin\n");
294 f <<
stringf(
"\t// $dumpfile(\"testbench.vcd\");\n");
295 f <<
stringf(
"\t// $dumpvars(0, testbench);\n");
296 for (
auto it = design->
modules_.begin(); it != design->
modules_.end(); it++)
297 if (!it->second->get_bool_attribute(
"\\gentb_skip"))
298 f <<
stringf(
"\t%s;\n",
idy(it->first.str(),
"test").c_str());
311 log(
" test_autotb [options] [filename]\n");
313 log(
"Automatically create primitive verilog test benches for all modules in the\n");
314 log(
"design. The generated testbenches toggle the input pins of the module in\n");
315 log(
"a semi-random manner and dumps the resulting output signals.\n");
317 log(
"This can be used to check the synthesis results for simple circuits by\n");
318 log(
"comparing the testbench output for the input files and the synthesis results.\n");
320 log(
"The backend automatically detects clock signals. Additionally a signal can\n");
321 log(
"be forced to be interpreted as clock signal by setting the attribute\n");
322 log(
"'gentb_clock' on the signal.\n");
324 log(
"The attribute 'gentb_constant' can be used to force a signal to a constant\n");
325 log(
"value after initialization. This can e.g. be used to force a reset signal\n");
326 log(
"low in order to explore more inner states in a state machine.\n");
329 log(
" number of iterations the test bench shuld run (default = 1000)\n");
336 log_header(
"Executing TEST_AUTOTB backend (auto-generate pseudo-random test benches).\n");
339 for (argidx = 1; argidx <
GetSize(args); argidx++)
341 if (args[argidx] ==
"-n" && argidx+1 <
GetSize(args)) {
342 num_iter = atoi(args[++argidx].c_str());
std::string stringf(const char *fmt,...)
void log_header(const char *format,...)
virtual void execute(std::ostream *&f, std::string filename, std::vector< std::string > args, RTLIL::Design *design)
std::map< RTLIL::IdString, RTLIL::Wire * > wires_
static std::string idx(std::string str)
void extra_args(std::ostream *&f, std::string &filename, std::vector< std::string > args, size_t argidx)
#define PRIVATE_NAMESPACE_BEGIN
int GetSize(RTLIL::Wire *wire)
#define PRIVATE_NAMESPACE_END
std::map< RTLIL::IdString, RTLIL::Process * > processes
#define USING_YOSYS_NAMESPACE
std::map< RTLIL::IdString, RTLIL::Module * > modules_
void log(const char *format,...)
static std::string idy(std::string str1, std::string str2=std::string(), std::string str3=std::string())
USING_YOSYS_NAMESPACE static PRIVATE_NAMESPACE_BEGIN std::string id(std::string internal_id)
static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter)
TestAutotbBackend TestAutotbBackend
const std::vector< RTLIL::SigChunk > & chunks() const