1
2
3
4
5
6
7
8
9
10
11
12 use strict;
13 use warnings;
14 use diagnostics;
15 use 5.006;
16 use FileHandle;
17 use List::MoreUtils qw(firstidx);
18 use IPC::System::Simple qw(system);
19 use Benchmark qw(:all);
20 use PDL;
21 use PDL::Graphics::PLplot;
22 use Time::HiRes qw(gettimeofday tv_interval clock);
23 local $| = 1;
24
25
26
27 sub partial_products;
28 sub wallace_tree;
29 sub kogge_stone;
30 sub generate_multiplier;
31 sub generate_and_test;
32 sub verilog_testbench;
33 sub cpp_testbench;
34 sub make;
35 sub makefile;
36 sub chart;
37
38
39 &generate_and_test();
40 exit(0);
41
42
43 sub generate_multiplier()
44 {
45 my ($i,$j)=(@_);
46 my $pp=partial_products($i,$j);
47 my @pp=@$pp;
48 my $pph=wallace_tree(\@pp);
49 my %pp=%$pph;
50 my $pl=$i+$j-1;
51 kogge_stone($pl,\%pp);
52 return;
53 }
54
55
56 sub partial_products()
57 {
58 my ($multiplicand_length,$multiplier_length)=(@_);
59 my $ul =$multiplicand_length-1;
60 my $zl =$multiplier_length-1;
61 my $ul2 ="a" . "$ul";
62 my $zl2 ="b" . "$zl";
63 my @rmultiplicand;
64 my @pp;
65 my $i; my $k; my $fh;
66 for ($i=0; $i < $multiplicand_length; $i++)
67 { $rmultiplicand[$i]= 'a'.$i; }
68 my @multiplicand=reverse(@rmultiplicand);
69 my $multiplicand = @multiplicand;
70 my @rmultiplier;
71 for ($i=0; $i < $multiplier_length; $i++)
72 { $rmultiplier[$i]= 'b'.$i; }
73 my @multiplier=reverse(@rmultiplier);
74 my $multiplier = @multiplier;
75 my $product = $multiplicand + $multiplier;
76 my $pl =$product - 1;
77 for my $multiplier (@multiplier)
78 { for my $multiplicand (@multiplicand)
79 {push @pp, $multiplier.$multiplicand;}
80 }
81 open $fh, ">", "wallace.vl";
82 print $fh ("module wallace(a, b, product);\n");
83 print $fh (" // Unsigned nonrecoded Wallace multiplier.\n");
84 print $fh (" // John Bryan, 2017.\n");
85 print $fh (" input [$ul:0] a;\n input [$zl:0] b;\n");
86 print $fh (" output [$pl:0] product;\n");
87 my $icount=$zl;
88 my $jcount=$ul;
89 loop_g:
90 for($k = 0; $k < scalar(@pp); $k++)
91 {
92 print $fh (" assign ", $pp[$k], " = ","b[",$icount,"]", " & ",
93 "a[",$jcount,"];\n");
94 if ($jcount==0)
95 { $icount--;
96 $jcount=$ul; }
97 else
98 { $jcount--; }
99 }
100 close $fh;
101 return (\@pp);
102 }
103
104
105 sub wallace_tree()
106 {
107 my @pp=@{$_[0]};
108 my $i;
109 my $j;
110 my $k;
111 my(@other_array)=();
112 my %counts;
113 my %pp;
114 my %pp_copy;
115 my $key;
116 my $fh;
117 my $value;
118 my $final_flag;
119 my $flag;
120 my $tag;
121 my $string="";
122 my $c_string="";
123 my $cutoff_count;
124 my @sum_array=();
125 my @carry_array=();
126 my @sorted_pp_keys = ();
127 my @sca=();
128 my @carries=();
129 my $sca_count;
130 my $sum_array_index=0;
131 my $carry_array_index=0;
132 my $array_index=0;
133 my $carries_index=0;
134 my @array = ("aaaa" .. "zzzz");
135 @pp{@pp} = (1) x @pp;
136 my @two_nums;
137 while ( ($key, $value) = each(%pp) )
138 {
139 @two_nums=$key =~ /(\d+)/g;
140 $pp{$key}=$two_nums[0]+$two_nums[1];
141 }
142 @other_array=values %pp;
143 $counts{$_} ++ for @other_array;
144 $j=scalar(keys %counts)-1;
145 %pp_copy=%pp;
146 $sca_count=0;
147 $flag=1;
148 $tag=0;
149 loop_e:
150 while (($j>-1)&&($flag==1))
151 {
152 loop_d:
153
154 for ($i=0;$i<int($counts{$j}/3);$i++)
155 {
156 $cutoff_count=0;
157 $string=$array[$array_index];
158 $array_index++;
159 $c_string=$array[$array_index];
160 $array_index++;
161 loop_c:
162 while ( ($key, $value) = each(%pp_copy) )
163 {
164 conditional_b:
165 if (($value==$j) && ($cutoff_count < 3))
166 {
167 $cutoff_count++;
168 $pp{$string} = $pp{$key};
169 $pp{$c_string} = $pp{$key};
170 $sca[$sca_count] = $key;
171 $sca_count++;
172 delete($pp{$key});
173 delete($pp_copy{$key});
174 my $n = keys %pp;
175 conditional_a:
176 if ($cutoff_count==3)
177 {
178 $pp{$c_string} = int($pp{$c_string})+1;
179 $sum_array[$sum_array_index]= " assign $string" . ' = ' . "$sca[0]" . ' ^ ' .
180 "$sca[1]" . ' ^ ' . "$sca[2]" . ';';
181 $carry_array[$carry_array_index]= " assign $c_string" . ' = (' . "$sca[0]" .' & '.
182 "$sca[1]" .') | ('. "$sca[2]" .' & (' .
183 "$sca[0]" .' ^ '. "$sca[1]" .'));';
184 $sum_array_index++;
185 $carry_array_index++;
186 $sca_count=0;
187 }
188 }
189 }
190 $tag=1;
191 }
192 $counts{$j}=$counts{$j}-(3*($i));
193 loop_h:
194
195 for ($i=0;$i<int($counts{$j}/2);$i++)
196 {
197 $counts{$j}=$counts{$j}-2;
198 $cutoff_count=0;
199 $string=$array[$array_index];
200 $array_index++;
201 $c_string=$array[$array_index];
202 $array_index++;
203 loop_i:
204 while ( ($key, $value) = each(%pp_copy) )
205 {
206 if (($value==$j) && ($cutoff_count < 2))
207 {
208 $cutoff_count++;
209 $pp{$string} = $pp{$key};
210 $pp{$c_string} = $pp{$key};
211 $sca[$sca_count] = $key;
212 $sca_count++;
213 delete($pp{$key});
214 delete($pp_copy{$key});
215 if ($cutoff_count ==2 )
216 {
217 $pp{$c_string} = $pp{$c_string}+1;
218 $sum_array[$sum_array_index]= " assign $string" . ' = ' . "$sca[0]" .
219 ' ^ ' . "$sca[1]" . ';';
220 $carry_array[$carry_array_index]= " assign $c_string" . ' = ' . "$sca[0]" .
221 ' & '. "$sca[1]" .';';
222 $sum_array_index++;
223 $carry_array_index++;
224 $sca_count=0;
225 }
226 }
227 }
228 $tag=1;
229 }
230 $j=$j-1;
231 conditional_c:
232 if (($tag==1) && ($j==-1))
233 {
234 @other_array=values %pp;
235 $_ = 0 for %counts;
236 $counts{$_} ++ for @other_array;
237 $j=scalar(keys %counts)-1;
238 %pp_copy=%pp;
239 $flag=0;
240 for my $i ( 0 .. (keys %counts) )
241 {
242 if (defined $counts{$i})
243 { if ($counts{$i}>2)
244 { $flag=1; }
245 }
246 }
247 }
248 }
249 open $fh, ">>", "wallace.vl";
250 for ($k = 0; $k < $sum_array_index; $k++)
251 { print $fh "$sum_array[$k]\n";
252 print $fh "$carry_array[$k]\n";
253 }
254 close $fh;
255 return (\%pp);
256 }
257
258
259 sub kogge_stone()
260 {
261 my ($pl,$pp)=(@_);
262 my %pp=%$pp;
263 my @other_array;
264 my %counts;
265 my @sorted_counts=();
266 @other_array=values %pp;
267 $counts{$_}=0 for @other_array;
268 $counts{$_}++ for @other_array;
269 $sorted_counts[$_]=$counts{$_} for sort {$a <=> $b} keys %counts;
270 my @sorted_pp_keys = sort {$pp{$a} <=> $pp{$b}} keys %pp;
271 my $first_index= firstidx { $_ eq '2' } @sorted_counts;
272 my $adder_length=$pl+1-$first_index;
273 my @p0= ("p000" .. "p200");
274 my @p1= ("pa000" .. "pa200");
275 my @p2= ("pb000" .. "pb200");
276 my @p3= ("pc000" .. "pc200");
277 my @p4= ("pd000" .. "pd200");
278 my @p5= ("pe000" .. "pe200");
279 my @p6= ("pf000" .. "pf200");
280 my @p7= ("pg000" .. "pg200");
281 my @g0= ("g000" .. "g200");
282 my @g1= ("ga000" .. "ga200");
283 my @g2= ("gb000" .. "gb200");
284 my @g3= ("gc000" .. "gc200");
285 my @g4= ("gd000" .. "gd200");
286 my @g5= ("ge000" .. "ge200");
287 my @g6= ("gf000" .. "gf200");
288 my @g7= ("gg000" .. "gg200");
289 my $final_flag=0; my $i=0; my $k=0; my $gg=0; my $fh;
290 open $fh, ">>", "wallace.vl";
291 loop_k:
292 for my $k ( 0 .. $#sorted_counts )
293 {
294 if (($sorted_counts[$k]==1) && ($final_flag==0))
295 {
296 print $fh " assign product[$k] = $sorted_pp_keys[$i];\n";
297 $i++;
298 }
299 conditional_d:
300 if (($sorted_counts[$k]==2) && ($final_flag==0))
301 {
302 print $fh " assign $p0[$gg] = $sorted_pp_keys[$i] ^ $sorted_pp_keys[$i+1];\n";
303 print $fh " assign product[$k] = $p0[$gg];\n";
304 print $fh " assign $g0[$gg] = $sorted_pp_keys[$i] & $sorted_pp_keys[$i+1];\n";
305 if ($adder_length > 1)
306 {
307 print $fh " buf($p1[$gg],$p0[$gg]);\n";
308 print $fh " buf($g1[$gg],$g0[$gg]);\n";
309 }
310 if ($adder_length > 2)
311 {
312 print $fh " buf($p2[$gg],$p1[$gg]);\n";
313 print $fh " buf($g2[$gg],$g1[$gg]);\n";
314 }
315 if ($adder_length > 4)
316 {
317 print $fh " buf($p3[$gg],$p2[$gg]);\n";
318 print $fh " buf($g3[$gg],$g2[$gg]);\n";
319 }
320 if ($adder_length > 8)
321 {
322 print $fh " buf($p4[$gg],$p3[$gg]);\n";
323 print $fh " buf($g4[$gg],$g3[$gg]);\n";
324 }
325 if ($adder_length > 16)
326 {
327 print $fh " buf($p5[$gg],$p4[$gg]);\n";
328 print $fh " buf($g5[$gg],$g4[$gg]);\n";
329 }
330 if ($adder_length > 32)
331 {
332 print $fh " buf($p6[$gg],$p5[$gg]);\n";
333 print $fh " buf($g6[$gg],$g5[$gg]);\n";
334 }
335 if ($adder_length > 64)
336 {
337 print $fh " buf($p7[$gg],$p6[$gg]);\n";
338 print $fh " buf($g7[$gg],$g6[$gg]);\n";
339 }
340 $final_flag=1;
341 $gg=$gg+1;
342 $i=$i+2;
343 next;
344 }
345 conditional_e:
346 if ($final_flag==1)
347 {
348 conditional_f:
349 if ($k < $pl)
350 {
351 print $fh " assign $p0[$gg] = $sorted_pp_keys[$i] ^ $sorted_pp_keys[$i+1];\n";
352 print $fh " assign $g0[$gg] = $sorted_pp_keys[$i] & $sorted_pp_keys[$i+1];\n";
353 if ($adder_length==2)
354 { print $fh " assign product[$k] = $p0[$gg];\n"; }
355 if ($adder_length==3)
356 { print $fh " assign product[$k] = $p0[$gg] ^ $g1[$gg-1];\n"; }
357 if ((6> $adder_length) && ($adder_length > 3))
358 { print $fh " assign product[$k] = $p0[$gg] ^ $g2[$gg-1];\n"; }
359 if ((9> $adder_length) && ($adder_length > 5))
360 { print $fh " assign product[$k] = $p0[$gg] ^ $g3[$gg-1];\n"; }
361 if ((18> $adder_length) && ($adder_length > 8))
362 { print $fh " assign product[$k] = $p0[$gg] ^ $g4[$gg-1];\n"; }
363 if ((34> $adder_length) && ($adder_length > 17))
364 { print $fh " assign product[$k] = $p0[$gg] ^ $g5[$gg-1];\n"; }
365 if ((66> $adder_length) && ($adder_length > 33))
366 { print $fh " assign product[$k] = $p0[$gg] ^ $g6[$gg-1];\n"; }
367 if ((130> $adder_length) && ($adder_length > 65))
368 { print $fh " assign product[$k] = $p0[$gg] ^ $g7[$gg-1];\n"; }
369 if ($adder_length > 1)
370 { if ($gg>0)
371 { print $fh " assign $p1[$gg] = $p0[$gg] & $p0[$gg-1];\n";
372 print $fh " assign $g1[$gg] = $g0[$gg] | ($p0[$gg] & $g0[$gg-1]);\n"; }
373 else
374 { print $fh " buf($p1[$gg],$p0[$gg]);\n";
375 print $fh " buf($g1[$gg],$g0[$gg]);\n"; }
376 }
377 if ($adder_length > 2)
378 { if ($gg>1)
379 { print $fh " assign $p2[$gg] = $p1[$gg] & $p1[$gg-2];\n";
380 print $fh " assign $g2[$gg] = $g1[$gg] | ($p1[$gg] & $g1[$gg-2]);\n"; }
381 else
382 { print $fh " buf($p2[$gg],$p1[$gg]);\n";
383 print $fh " buf($g2[$gg],$g1[$gg]);\n"; }
384 }
385 if ($adder_length > 4)
386 { if ($gg>3)
387 { print $fh " assign $p3[$gg] = $p2[$gg] & $p2[$gg-4];\n";
388 print $fh " assign $g3[$gg] = $g2[$gg] | ($p2[$gg] & $g2[$gg-4]);\n"; }
389 else
390 { print $fh " buf($p3[$gg],$p2[$gg]);\n";
391 print $fh " buf($g3[$gg],$g2[$gg]);\n"; }
392 }
393 if ($adder_length > 8)
394 { if ($gg>7)
395 { print $fh " assign $p4[$gg] = $p3[$gg] & $p3[$gg-8];\n";
396 print $fh " assign $g4[$gg] = $g3[$gg] | ($p3[$gg] & $g3[$gg-8]);\n"; }
397 else
398 { print $fh " buf($p4[$gg],$p3[$gg]);\n";
399 print $fh " buf($g4[$gg],$g3[$gg]);\n"; }
400 }
401 if ($adder_length > 16)
402 { if ($gg>15)
403 { print $fh " assign $p5[$gg] = $p4[$gg] & $p4[$gg-16];\n";
404 print $fh " assign $g5[$gg] = $g4[$gg] | ($p4[$gg] & $g4[$gg-16]);\n"; }
405 else
406 { print $fh " buf($p5[$gg],$p4[$gg]);\n";
407 print $fh " buf($g5[$gg],$g4[$gg]);\n"; }
408 }
409 if ($adder_length > 32)
410 { if ($gg>31)
411 { print $fh " assign $p6[$gg] = $p5[$gg] & $p5[$gg-32];\n";
412 print $fh " assign $g6[$gg] = $g5[$gg] | ($p5[$gg] & $g5[$gg-32]);\n"; }
413 else
414 { print $fh " buf($p6[$gg],$p5[$gg]);\n";
415 print $fh " buf($g6[$gg],$g5[$gg]);\n"; }
416 }
417 if ($adder_length > 64)
418 { if ($gg>63)
419 { print $fh " assign $p7[$gg] = $p6[$gg] & $p6[$gg-64];\n";
420 print $fh " assign $g7[$gg] = $g6[$gg] | ($p6[$gg] & $g6[$gg-64]);\n"; }
421 else
422 { print $fh " buf($p7[$gg],$p6[$gg]);\n";
423 print $fh " buf($g7[$gg],$g6[$gg]);\n"; }
424 }
425 }
426 else
427 {
428 if ($k==$pl)
429 {
430 if ($sorted_counts[$k]==2)
431 {print $fh " assign $p0[$gg] = $sorted_pp_keys[$i] ^ $sorted_pp_keys[$i+1];\n";}
432 else
433 {print $fh " assign $p0[$gg] = $sorted_pp_keys[$i];\n";}
434 if ($adder_length==2)
435 {
436 print $fh " assign product[$k] = $p0[$gg] ^ $g0[$gg-1];\n";
437 }
438 if ($adder_length==3)
439 {
440 print $fh " assign product[$k] = $p0[$gg] ^ $g1[$gg-1];\n";
441 }
442 if (($adder_length==4) || ($adder_length == 5))
443 {
444 print $fh " assign product[$k] = $p0[$gg] ^ $g2[$gg-1];\n";
445 }
446 if ((10> $adder_length) && ($adder_length > 5))
447 {
448 print $fh " assign product[$k] = $p0[$gg] ^ $g3[$gg-1];\n";
449 }
450 if ((18> $adder_length) && ($adder_length > 9))
451 {
452 print $fh " assign product[$k] = $p0[$gg] ^ $g4[$gg-1];\n";
453 }
454 if ((34> $adder_length) && ($adder_length > 17))
455 {
456 print $fh " assign product[$k] = $p0[$gg] ^ $g5[$gg-1];\n";
457 }
458 if ((66> $adder_length) && ($adder_length > 33))
459 {
460 print $fh " assign product[$k] = $p0[$gg] ^ $g6[$gg-1];\n";
461 }
462 if ((130> $adder_length) && ($adder_length > 65))
463 {
464 print $fh " assign product[$k] = $p0[$gg] ^ $g7[$gg-1];\n";
465 }
466 }
467 }
468 $i=$i+2;
469 $gg=$gg+1;
470 }
471 }
472 if ($pl>$#sorted_counts)
473 {
474 if ($adder_length==2)
475 {
476 print $fh " assign product[$pl] = $g0[$gg-1];\n";
477 }
478 if ($adder_length==3)
479 {
480 print $fh " assign product[$pl] = $g1[$gg-1];\n";
481 }
482 if (($adder_length==4) || ($adder_length == 5))
483 {
484 print $fh " assign product[$pl] = $g2[$gg-1];\n";
485 }
486 if (($adder_length>=6) && ($adder_length<=9))
487 {
488 print $fh " assign product[$pl] = $g3[$gg-1];\n";
489 }
490 if (($adder_length>=10) && ($adder_length<=17))
491 {
492 print $fh " assign product[$pl] = $g4[$gg-1];\n";
493 }
494 if (($adder_length>=18) && ($adder_length<=33))
495 {
496 print $fh " assign product[$pl] = $g5[$gg-1];\n";
497 }
498 if (($adder_length>=34) && ($adder_length<=65))
499 {
500 print $fh " assign product[$pl] = $g6[$gg-1];\n";
501 }
502 }
503 print $fh "endmodule";
504 close $fh;
505 return;
506 }
507
508
509 sub verilog_testbench()
510 {
511 my ($mdl,$mrl)=(@_);
512 my $ul =$mdl-1;
513 my $zl =$mrl-1;
514 my $pl =$ul+$zl+1;
515 my $plplus1=$pl+1;
516 my $fh;
517 open $fh, ">", "tb_wallace.vl";
518 print $fh "`timescale 1ns/1ns\n";
519 print $fh "module tb_wallace;\n";
520 print $fh " // Unsigned multiplier Verilog testbench\n";
521 print $fh " // John Bryan, 2017\n";
522 print $fh " reg [$ul:0] a;\n";
523 print $fh " reg [$zl:0] b;\n";
524 print $fh " wire [$pl:0] product;\n";
525 print $fh " reg [$pl:0] check;\n";
526 my $mdlul = 2**$mdl;
527 my $mrlul = 2**$mrl;
528 my $total_tested = $mdlul*$mrlul;
529 my $mdlp1 = $mdl+1;
530 my $mrlp1 = $mrl+1;
531 print $fh " reg [$mdl:0] i,mdlul;\n";
532 print $fh " reg [$mrl:0] j,mrlul;\n\n";
533 print $fh " wallace wall0(a,b,product);\n\n";
534 print $fh " initial\n";
535 print $fh " begin\n";
536 print $fh " a=$mdl\'d0;\n";
537 print $fh " b=$mrl\'d0;\n";
538 print $fh " mrlul=$mrlp1\'d$mrlul;\n";
539 print $fh " mdlul=$mdlp1\'d$mdlul;\n";
540 print $fh " for (i=0;i<mdlul;i=i+1)\n";
541 print $fh " begin\n";
542 print $fh " for (j=0;j<mrlul;j=j+1)\n";
543 print $fh " begin\n";
544 print $fh " check=a*b;\n";
545 print $fh " #1;\n";
546 print $fh " if (product != check)\n";
547 print $fh " begin\n";
548 print $fh " \$display(\"time=%0t\", \$time);\n";
549 print $fh " \$display(\"a =%0d, b=%0d\", a, b);\n";
550 print $fh " \$display(\"product=%0d, check=%0d\", product, check);\n";
551 print $fh " \$finish;\n";
552 print $fh " end\n";
553 print $fh " b=b+1'b1;\n";
554 print $fh " end\n";
555 print $fh " a=a+1'b1;\n";
556 print $fh " end\n";
557 print $fh " \$display(\" All $total_tested were correct using Verilog tb.\");\n";
558 print $fh " \$finish;\n";
559 print $fh " end\n\n";
560 print $fh " endmodule\n";
561 close $fh;
562 return;
563 }
564
565
566
567 sub cpp_testbench()
568 {
569 my ($mdl,$mrl)=(@_);
570 my $ul =$mdl - 1;
571 my $zl =$mrl - 1;
572 my $pl =$ul+$zl+1;
573 my $plplus1 =$pl+1;
574 my $fh;
575 my $mdul=0;
576 my $mrul=0;
577 my $mdll;
578 my $mrll;
579 open $fh, ">", "sim_main.cpp";
580 print $fh "// C++ multiplier testbench\n";
581 print $fh "\#include <stdlib.h>\n";
582 print $fh "\#include <iostream>\n";
583 print $fh "\#include <ctime>\n";
584 print $fh "\#include \"Vwallace.h\"\n";
585 print $fh "\#include \"verilated.h\"\n";
586 print $fh "using namespace std;\n\n";
587 print $fh "int main(int argc, char **argv, char **env)\n";
588 print $fh "{\n";
589 print $fh " Verilated::commandArgs(argc,argv);\n";
590 print $fh " Vwallace *top=new Vwallace;\n";
591 $mdul = 2**$mdl;
592 $mrul = 2**$mrl;
593 my $total_tested = $mdul*$mrul;
594 print $fh " const unsigned int mdlul=$mdul;\n";
595 print $fh " const unsigned int mrlul=$mrul;\n";
596 print $fh " unsigned int check;\n";
597 print $fh " unsigned int i,j;\n";
598 print $fh " unsigned int flag=0;\n";
599 print $fh " for (i=0;i<mdlul;i++)\n";
600 print $fh " {\n";
601 print $fh " top->a=i;\n";
602 print $fh " for (j=0;j<mrlul;j++)\n";
603 print $fh " {\n";
604 print $fh " top->b=j;\n";
605 print $fh " check=top->a*top->b;\n";
606 print $fh " top->eval();\n";
607 print $fh " if (top->product!=check)\n";
608 print $fh " {\n";
609 print $fh " printf(\"\\na=%d, b=%d\\n\", top->a,top->b);\n";
610 print $fh " printf(\"product=%d, check=%d\\n\",top->product,check);\n";
611 print $fh " flag=1;\n";
612 print $fh " break;\n";
613 print $fh " }\n";
614 print $fh " }\n";
615 print $fh " }\n";
616 print $fh " if (flag==0)\n";
617 print $fh " {printf(\" All $total_tested were correct using C++ tb.\\n\\n\");}\n";
618
619 print $fh " delete top;\n";
620 print $fh " exit(0);\n";
621 print $fh "}\n";
622 close $fh;
623 return;
624 }
625
626
627 sub makefile()
628 {
629 my $fh;
630 open $fh, ">", "Makefile";
631 print $fh "TARGET=wallace\n\n";
632 print $fh "clean:\n";
633 print $fh "\t\@rm -rf obj_dir *~\n";
634 print $fh "all:\n";
635 print $fh "\t\@verilator -cc \$(TARGET).vl --exe sim_main.cpp -Wno-lint\n";
636 print $fh "build:\n";
637 print $fh "\t\@make -w -s -C obj_dir -f V\$(TARGET).mk V\$(TARGET) > /dev/null 2>&1\n";
638 print $fh "test:\n";
639 print $fh "\t\@./obj_dir/V\$(TARGET) -s\n";
640 close $fh;
641 return;
642 }
643
644
645 sub make()
646 {
647 system("make clean");
648 system("make all");
649 system("make build");
650 system("make test");
651 return;
652 }
653
654
655 sub chart()
656 {
657 my ($x_ref,$y_ref,$v_ref)=(@_);
658 my @x=@$x_ref;
659 my @y=@$y_ref;
660 my @v=@$v_ref;
661 my $pl = PDL::Graphics::PLplot->new(DEV=>'svg', FILE=>'chart.svg');
662 my $x = pdl(@x);
663 my $y = pdl(@y);
664 my $v = pdl(@v);
665 $pl->xyplot($x, $v, COLOR => 'BROWN', PLOTTYPE => 'LINEPOINTS');
666 $pl->xyplot($x, $y, COLOR => 'BLUE', PLOTTYPE => 'LINEPOINTS');
667 $pl->xyplot(pdl(13,14), pdl(90,90),COLOR=>'BROWN');
668 $pl->xyplot(pdl(13,14), pdl(80,80),COLOR=>'BLUE');
669 $pl->text("Icarus", COLOR=>'BROWN',TEXTPOSITION => [14.5,90,15.5,0,0]);
670 $pl->text("Verilator", COLOR=>'BLUE',TEXTPOSITION => [14.5,80,15.5,0,0]);
671 $pl->text('Performance vs Product Size',COLOR=>'BLACK',TEXTPOSITION=>['t',1.5,0.5,0.5]);
672 $pl->text('Time (seconds)',COLOR=>'BLACK',TEXTPOSITION=>['l',3,.5,.5]);
673 $pl->text('Product bit size',COLOR=>'BLACK',TEXTPOSITION=>['b',3,.5,.5]);
674 $pl->close;
675 return;
676 }
677
678
679 sub generate_and_test
680 {
681 my ($i,$j,$increment)=@ARGV;
682 my $hl=$i+$j+$increment+1;
683 my $ll=$i+$j;
684 my $count=$ll;
685 my $left; my $pl; my $k;
686 my $t0; my $t1; my $td; my $m;
687 my @x; my @y; my @v;
688 u_for:
689 for (;($i+$j)<$hl;$i++)
690 {
691 $left=$hl-$count;
692 print "\n $left test(s) to go . . .\n";
693 $pl=$i+$j;
694 print " Testing product length of $pl . . .\n";
695 &generate_multiplier($i,$j);
696 &verilog_testbench($i,$j);
697 $t0=[gettimeofday];
698 system ("iverilog wallace.vl tb_wallace.vl");
699 system ("vvp a.out");
700 $t1=[gettimeofday];
701 $td=tv_interval $t0,$t1;
702 push @v, $td;
703 &cpp_testbench($i,$j);
704 &makefile;
705 $t0=[gettimeofday];
706 &make;
707 $t1=[gettimeofday];
708 $td=tv_interval $t0,$t1;
709 push @y, $td;
710 my $x=$i+$j;
711 push @x, $x;
712 $count++;
713 $left=$hl-$count;
714 $j=$j+1;
715 if (($i+$j)<$hl)
716 {
717 print "\n $left test(s) to go . . .\n";
718 $pl=$i+$j;
719 print " Testing product length of $pl . . .\n";
720 &generate_multiplier($i,$j);
721 &verilog_testbench($i,$j);
722 $t0=[gettimeofday];
723 system ("iverilog wallace.vl tb_wallace.vl");
724 system ("vvp a.out");
725 $t1=[gettimeofday];
726 $td=tv_interval $t0,$t1;
727 push @v, $td;
728 &cpp_testbench($i,$j);
729 &makefile;
730 $t0=[gettimeofday];
731 &make;
732 $t1=[gettimeofday];
733 $td=tv_interval $t0,$t1;
734 push @y, $td;
735 my $x=$i+$j;
736 push @x, $x;
737 $count++;
738 $left=$hl-$count;
739 }
740 }
741 &chart(\@x,\@y,\@v);
742 return;
743 }