diff --git a/fpga_flow/scripts/fpga_flow.pl b/fpga_flow/scripts/fpga_flow.pl index 47dd1b042..8ad66e474 100644 --- a/fpga_flow/scripts/fpga_flow.pl +++ b/fpga_flow/scripts/fpga_flow.pl @@ -1025,6 +1025,16 @@ sub run_odin2($ $ $) { chdir $cwd; } +sub run_pro_blif($ $) { + my ($abc_blif_out_bak, $abc_blif_out) = @_; + `perl pro_blif.pl -i $abc_blif_out_bak -o $abc_blif_out`; + + if (!(-e $abc_blif_out)) { + die "ERROR: Fail pro_blif.pl for benchmark $abc_blif_out.\n"; + } + return; +} + # Run Acitivity Estimation sub run_ace($ $ $ $) { my ($mpack_vpr_blif,$act_file,$ace_new_blif,$log) = @_; @@ -1394,8 +1404,8 @@ sub run_ace_in_flow($ $ $ $ $ $ $) { &run_ace($tmp_blif,$act_file,$ace_new_blif ,$ace_log); } else { &run_ace($abc_blif_out,$act_file,$ace_new_blif,$ace_log); - $abc_blif_out = $ace_new_blif; } + &run_pro_blif($ace_new_blif, $abc_blif_out); } if (("on" eq $opt_ptr->{power})&&(!(-e $act_file))) { @@ -1548,35 +1558,11 @@ sub run_standard_flow($ $ $ $ $) $abc_blif_out = "$prefix"."abc.blif"; $abc_blif_out_bak = "$prefix"."abc_bak.blif"; $abc_log = "$prefix"."abc.log"; - - if ("abc_black_box" eq $flow_enhance) { - my ($pre_abc_blif) = ("$prefix"."pre_abc.blif"); - `perl pro_blif.pl -i $abc_bm -o $pre_abc_blif`; - &run_abc_bb_fpgamap($pre_abc_blif,$abc_blif_out_bak,$abc_log); - } elsif ("classic" eq $flow_enhance) { - &run_abc_fpgamap($abc_bm,$abc_blif_out_bak,$abc_log); - } - `perl pro_blif.pl -i $abc_blif_out_bak -o $abc_blif_out`; - - if (!(-e $abc_blif_out)) { - die "ERROR: Fail pro_blif.pl for benchmark $abc_blif_out.\n"; - } my ($act_file,$ace_new_blif,$ace_log) = ("$prefix"."ace.act","$prefix"."ace.blif","$prefix"."ace.log"); - if ("on" eq $opt_ptr->{power}) { - if ("on" eq $opt_ptr->{black_box_ace}) { - &black_box_blif($abc_blif_out,$ace_new_blif); - &run_ace($ace_new_blif,$act_file,$prefix."ace_new.blif",$ace_log); - } else { - &run_ace($abc_blif_out,$act_file,$ace_new_blif,$ace_log); - $abc_blif_out = $ace_new_blif; - } - if (!(-e $act_file)) { - die "ERROR: Fail ACE2 for benchmark $act_file.\n"; - } - } + my ($vpr_net,$vpr_place,$vpr_route,$vpr_reroute_log,$vpr_log); $vpr_net = "$prefix"."vpr.net"; $vpr_place = "$prefix"."vpr.place"; @@ -1584,81 +1570,20 @@ sub run_standard_flow($ $ $ $ $) $vpr_log = "$prefix"."vpr.log"; $vpr_reroute_log = "$prefix"."vpr_reroute.log"; - if ("on" eq $opt_ptr->{min_route_chan_width}) { - &run_std_vpr($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,-1,$vpr_log.".min_chan_width",$act_file); - # Get the Minimum channel width - my ($min_chan_width) = (&extract_min_chan_width_vpr_stats($tag,$benchmark,$vpr_log.".min_chan_width",$opt_ptr->{K_val}, $opt_ptr->{min_route_chan_width}, $parse_results)); - $min_chan_width = int($min_chan_width*$opt_ptr->{min_route_chan_width_val}); - if (0 != $min_chan_width%2) { - $min_chan_width += 1; - } - # Remove previous route results - if (-e $vpr_route) { - `rm $vpr_route`; - } - # Keep increase min_chan_width until route success - # Extract data from VPR stats - #&run_std_vpr($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,$min_chan_width,$vpr_log,$act_file); - while (1) { - &run_vpr_route($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,$min_chan_width,$vpr_reroute_log,$act_file); - # TODO: Only run the routing stage - if (-e $vpr_route) { - print "INFO: try route_chan_width($min_chan_width) success!\n"; - last; #Jump out - } else { - print "INFO: try route_chan_width($min_chan_width) failed! Retry with +2...\n"; - $min_chan_width += 2; - } - } - if (1 == $parse_results) { - &extract_min_chan_width_vpr_stats($tag,$benchmark,$vpr_reroute_log,$opt_ptr->{K_val}, "off", $parse_results); - &extract_vpr_stats($tag,$benchmark,$vpr_log.".min_chan_width",$opt_ptr->{K_val}); - &extract_vpr_stats($tag,$benchmark,$vpr_reroute_log,$opt_ptr->{K_val}); - } - } elsif ("on" eq $opt_ptr->{fix_route_chan_width}) { - my ($fix_chan_width) = ($benchmarks_ptr->{$benchmark_file}->{fix_route_chan_width}); - # Remove previous route results - if (-e $vpr_route) { - `rm $vpr_route`; - } - # Keep increase min_chan_width until route success - &run_std_vpr($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,$fix_chan_width,$vpr_log,$act_file); - while (1) { - # TODO: Only run the routing stage - if (-e $vpr_route) { - print "INFO: try route_chan_width($fix_chan_width) success!\n"; - last; #Jump out - } else { - print "INFO: try route_chan_width($fix_chan_width) failed! Retry with +2...\n"; - $fix_chan_width += 2; - &run_vpr_route($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,$fix_chan_width,$vpr_reroute_log,$act_file); - } - } - # Extract data from VPR stats - if (1 == $parse_results) { - &extract_min_chan_width_vpr_stats($tag,$benchmark,$vpr_log,$opt_ptr->{K_val}, "off", $parse_results); - &extract_vpr_stats($tag,$benchmark,$vpr_log,$opt_ptr->{K_val}); - if (-e $vpr_reroute_log) { - &extract_vpr_stats($tag,$benchmark,$vpr_reroute_log,$opt_ptr->{K_val}); - } - } - } else { - &run_std_vpr($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,-1,$vpr_log,$act_file); - if (!(-e $vpr_route)) { - die "ERROR: Route Fail for $abc_blif_out!\n"; - } - # Get the Minimum channel width - my ($min_chan_width) = (&extract_min_chan_width_vpr_stats($tag,$benchmark,$vpr_log,$opt_ptr->{K_val},"on",$parse_results)); - if (1 == $parse_results) { - &extract_vpr_stats($tag,$benchmark,$vpr_log,$opt_ptr->{K_val}); - } + + if ("abc_black_box" eq $flow_enhance) { + my ($pre_abc_blif) = ("$prefix"."pre_abc.blif"); + &run_pro_blif($abc_bm, $pre_abc_blif); + &run_abc_bb_fpgamap($pre_abc_blif,$abc_blif_out_bak,$abc_log); + } elsif ("classic" eq $flow_enhance) { + &run_abc_fpgamap($abc_bm,$abc_blif_out_bak,$abc_log); } - # Extract data from VPR Power stats - if (("on" eq $opt_ptr->{power}) - &&(1 == $parse_results)) { - &extract_vpr_power_esti($tag,$abc_blif_out,$benchmark,$opt_ptr->{K_val}); - } + &run_pro_blif($abc_blif_out_bak, $abc_blif_out); + + &run_ace_in_flow($prefix, $abc_blif_out, $act_file, $ace_new_blif, $ace_log); + + &run_vpr_in_flow($tag, $benchmark, $benchmark_file, $abc_blif_out, $vpr_arch, $act_file, $vpr_net, $vpr_place, $vpr_route, $vpr_log, $vpr_reroute_log, $parse_results); return; } @@ -1687,12 +1612,6 @@ sub parse_standard_flow_results($ $ $ $) } my ($act_file,$ace_new_blif,$ace_log) = ("$prefix"."ace.act","$prefix"."ace.blif","$prefix"."ace.log"); - if ("on" eq $opt_ptr->{power}) { - if ("on" eq $opt_ptr->{black_box_ace}) { - } else { - $abc_blif_out = $ace_new_blif; - } - } $vpr_net = "$prefix"."vpr.net"; $vpr_place = "$prefix"."vpr.place"; @@ -2120,16 +2039,11 @@ sub run_vtr_flow($ $ $ $) { # RUN ABC &run_abc_bb_fpgamap($abc_bm,$abc_blif_out_bak,$abc_log); - `perl pro_blif.pl -i $abc_blif_out_bak -o $abc_blif_out`; - if (!(-e $abc_blif_out_bak)) { - die "ERROR: Fail pro_blif for benchmark $benchmark.\n"; - } + &run_pro_blif($abc_blif_out_bak, $abc_blif_out); + # Run ABC my ($act_file,$ace_new_blif,$ace_log) = ("$prefix"."ace.act","$prefix"."ace.blif","$prefix"."ace.log"); - if ("on" eq $opt_ptr->{power}) { - &run_ace($abc_blif_out,$act_file,$ace_new_blif,$ace_log); - $abc_blif_out = $ace_new_blif; - } + &run_ace_in_flow($prefix, $abc_blif_out,$act_file,$ace_new_blif,$ace_log); $vpr_net = "$prefix"."vpr.net"; $vpr_place = "$prefix"."vpr.place"; @@ -2137,76 +2051,9 @@ sub run_vtr_flow($ $ $ $) { $vpr_log = "$prefix"."vpr.log"; $vpr_reroute_log = "$prefix"."vpr_reroute.log"; - if ("on" eq $opt_ptr->{min_route_chan_width}) { - &run_std_vpr($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,-1,$vpr_log.".min_chan_width",$act_file); - # Get the Minimum channel width - my ($min_chan_width) = (&extract_min_chan_width_vpr_stats($tag,$benchmark,$vpr_log.".min_chan_width",$opt_ptr->{K_val}, $opt_ptr->{min_route_chan_width}, $parse_results)); - $min_chan_width = int($min_chan_width*$opt_ptr->{min_route_chan_width_val}); - if (0 != $min_chan_width%2) { - $min_chan_width += 1; - } - # Remove previous route results - `rm $vpr_route`; - # Keep increase min_chan_width until route success - # Extract data from VPR stats - while (1) { - &run_vpr_route($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,$min_chan_width,$vpr_reroute_log,$act_file); - if (-e $vpr_route) { - print "INFO: try route_chan_width($min_chan_width) Success!\n"; - last; #Jump out - } else { - print "INFO: try route_chan_width($min_chan_width) failed! Retry with +2...\n"; - $min_chan_width += 2; - } - } - # Extract data from VPR stats - if (1 == $parse_results) { - &extract_min_chan_width_vpr_stats($tag,$benchmark,$vpr_reroute_log,$opt_ptr->{K_val}, "off", $parse_results); - &extract_vpr_stats($tag,$benchmark,$vpr_log."min_chan_width",$opt_ptr->{K_val}); - &extract_vpr_stats($tag,$benchmark,$vpr_reroute_log,$opt_ptr->{K_val}); - } - } elsif ("on" eq $opt_ptr->{fix_route_chan_width}) { - my ($fix_chan_width) = ($benchmarks_ptr->{$benchmark_file}->{fix_route_chan_width}); - # Remove previous route results - `rm $vpr_route`; - # Keep increase min_chan_width until route success - &run_std_vpr($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,$fix_chan_width,$vpr_log,$act_file); - # Extract data from VPR stats - while (1) { - if (-e $vpr_route) { - print "INFO: try route_chan_width($fix_chan_width) Success!\n"; - last; #Jump out - } else { - print "INFO: try route_chan_width($fix_chan_width) failed! Retry with +2...\n"; - $fix_chan_width += 2; - &run_vpr_route($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,$fix_chan_width,$vpr_reroute_log,$act_file); - } - } - if (1 == $parse_results) { - &extract_min_chan_width_vpr_stats($tag,$benchmark,$vpr_log,$opt_ptr->{K_val}, "off", $parse_results); - &extract_vpr_stats($tag,$benchmark,$vpr_log,$opt_ptr->{K_val}); - if (-e $vpr_reroute_log) { - &extract_min_chan_width_vpr_stats($tag,$benchmark,$vpr_reroute_log,$opt_ptr->{K_val}, "off", $parse_results); - &extract_vpr_stats($tag,$benchmark,$vpr_reroute_log,$opt_ptr->{K_val}); - } - } - } else { - &run_std_vpr($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,-1,$vpr_log,$act_file); - if (!(-e $vpr_route)) { - die "ERROR: Route Fail for $abc_blif_out!\n"; - } - # Get the Minimum channel width - my ($min_chan_width) = (&extract_min_chan_width_vpr_stats($tag,$benchmark,$vpr_log,$opt_ptr->{K_val},$parse_results)); - if (1 == $parse_results) { - &extract_vpr_stats($tag,$benchmark,$vpr_log,$opt_ptr->{K_val}); - } - } + # Run VPR + &run_vpr_in_flow($tag, $benchmark, $benchmark_file, $abc_blif_out, $vpr_arch, $act_file, $vpr_net, $vpr_place, $vpr_route, $vpr_log, $vpr_reroute_log, $parse_results); - # Extract data from VPR Power stats - if (("on" eq $opt_ptr->{power}) - &&(1 == $parse_results)) { - &extract_vpr_power_esti($tag,$abc_blif_out,$benchmark,$opt_ptr->{K_val}); - } return; } @@ -2237,12 +2084,6 @@ sub parse_vtr_flow_results($ $ $) { rename $abc_blif_out,"$abc_blif_out".".bak"; my ($act_file,$ace_new_blif,$ace_log) = ("$prefix"."ace.act","$prefix"."ace.blif","$prefix"."ace.log"); - if ("on" eq $opt_ptr->{power}) { - if ("on" eq $opt_ptr->{black_box_ace}) { - } else { - $abc_blif_out = $ace_new_blif; - } - } $vpr_net = "$prefix"."vpr.net"; $vpr_place = "$prefix"."vpr.place"; @@ -2344,16 +2185,11 @@ sub run_vtr_mccl_flow($ $ $ $) { # RUN ABC &run_abc_mccl_fpgamap($abc_bm,$abc_blif_out_bak,$abc_log); - `perl pro_blif.pl -i $abc_blif_out_bak -o $abc_blif_out`; - if (!(-e $abc_blif_out_bak)) { - die "ERROR: Fail pro_blif for benchmark $benchmark.\n"; - } + &run_pro_blif($abc_blif_out_bak, $abc_blif_out); + # Run ACE my ($act_file,$ace_new_blif,$ace_log) = ("$prefix"."ace.act","$prefix"."ace.blif","$prefix"."ace.log"); - if ("on" eq $opt_ptr->{power}) { - &run_ace($abc_blif_out,$act_file,$ace_new_blif,$ace_log); - $abc_blif_out = $ace_new_blif; - } + &run_ace_in_flow($prefix,i $abc_blif_out,$act_file,$ace_new_blif,$ace_log); $vpr_net = "$prefix"."vpr.net"; $vpr_place = "$prefix"."vpr.place"; @@ -2361,76 +2197,9 @@ sub run_vtr_mccl_flow($ $ $ $) { $vpr_log = "$prefix"."vpr.log"; $vpr_reroute_log = "$prefix"."vpr_reroute.log"; - if ("on" eq $opt_ptr->{min_route_chan_width}) { - &run_std_vpr($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,-1,$vpr_log.".min_chan_width",$act_file); - # Get the Minimum channel width - my ($min_chan_width) = (&extract_min_chan_width_vpr_stats($tag,$benchmark,$vpr_log.".min_chan_width",$opt_ptr->{K_val}, $opt_ptr->{min_route_chan_width}, $parse_results)); - $min_chan_width = int($min_chan_width*$opt_ptr->{min_route_chan_width_val}); - if (0 != $min_chan_width%2) { - $min_chan_width += 1; - } - # Remove previous route results - `rm $vpr_route`; - # Keep increase min_chan_width until route success - # Extract data from VPR stats - while (1) { - &run_vpr_route($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,$min_chan_width,$vpr_reroute_log,$act_file); - if (-e $vpr_route) { - print "INFO: try route_chan_width($min_chan_width) Success!\n"; - last; #Jump out - } else { - print "INFO: try route_chan_width($min_chan_width) failed! Retry with +2...\n"; - $min_chan_width += 2; - } - } - # Extract data from VPR stats - if (1 == $parse_results) { - &extract_min_chan_width_vpr_stats($tag,$benchmark,$vpr_reroute_log,$opt_ptr->{K_val}, "off", $parse_results); - &extract_vpr_stats($tag,$benchmark,$vpr_log."min_chan_width",$opt_ptr->{K_val}); - &extract_vpr_stats($tag,$benchmark,$vpr_reroute_log,$opt_ptr->{K_val}); - } - } elsif ("on" eq $opt_ptr->{fix_route_chan_width}) { - my ($fix_chan_width) = ($benchmarks_ptr->{$benchmark_file}->{fix_route_chan_width}); - # Remove previous route results - `rm $vpr_route`; - # Keep increase min_chan_width until route success - &run_std_vpr($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,$fix_chan_width,$vpr_log,$act_file); - # Extract data from VPR stats - while (1) { - if (-e $vpr_route) { - print "INFO: try route_chan_width($fix_chan_width) Success!\n"; - last; #Jump out - } else { - print "INFO: try route_chan_width($fix_chan_width) failed! Retry with +2...\n"; - $fix_chan_width += 2; - &run_vpr_route($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,$fix_chan_width,$vpr_reroute_log,$act_file); - } - } - if (1 == $parse_results) { - &extract_min_chan_width_vpr_stats($tag,$benchmark,$vpr_log,$opt_ptr->{K_val}, "off", $parse_results); - &extract_vpr_stats($tag,$benchmark,$vpr_log,$opt_ptr->{K_val}); - if (-e $vpr_reroute_log) { - &extract_min_chan_width_vpr_stats($tag,$benchmark,$vpr_reroute_log,$opt_ptr->{K_val}, "off", $parse_results); - &extract_vpr_stats($tag,$benchmark,$vpr_reroute_log,$opt_ptr->{K_val}); - } - } - } else { - &run_std_vpr($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,-1,$vpr_log,$act_file); - if (!(-e $vpr_route)) { - die "ERROR: Route Fail for $abc_blif_out!\n"; - } - # Get the Minimum channel width - my ($min_chan_width) = (&extract_min_chan_width_vpr_stats($tag,$benchmark,$vpr_log,$opt_ptr->{K_val},$parse_results)); - if (1 == $parse_results) { - &extract_vpr_stats($tag,$benchmark,$vpr_log,$opt_ptr->{K_val}); - } - } - - # Extract data from VPR Power stats - if (("on" eq $opt_ptr->{power}) - &&(1 == $parse_results)) { - &extract_vpr_power_esti($tag,$abc_blif_out,$benchmark,$opt_ptr->{K_val}); - } + # Run VPR + &run_vpr_in_flow($tag, $benchmark, $benchmark_file, $abc_blif_out, $vpr_arch, $act_file, $vpr_net, $vpr_place, $vpr_route, $vpr_log, $vpr_reroute_log, $parse_results); + return; } @@ -2456,26 +2225,11 @@ sub run_mccl_flow($ $ $ $ $) # RUN ABC &run_abc_mccl_fpgamap($abc_bm,$abc_blif_out_bak,$abc_log); - `perl pro_blif.pl -i $abc_blif_out_bak -o $abc_blif_out`; - - if (!(-e $abc_blif_out)) { - die "ERROR: Fail pro_blif.pl for benchmark $abc_blif_out.\n"; - } + &run_pro_blif($abc_blif_out_bak, $abc_blif_out); + # Run ACE my ($act_file,$ace_new_blif,$ace_log) = ("$prefix"."ace.act","$prefix"."ace.blif","$prefix"."ace.log"); - if ("on" eq $opt_ptr->{power}) { - if ("on" eq $opt_ptr->{black_box_ace}) { - &black_box_blif($abc_blif_out,$ace_new_blif); - &run_ace($ace_new_blif,$act_file,$prefix."ace_new.blif",$ace_log); - } else { - &run_ace($abc_blif_out,$act_file,$ace_new_blif,$ace_log); - $abc_blif_out = $ace_new_blif; - } - } - - if (!(-e $act_file)) { - die "ERROR: Fail ACE2 for benchmark $act_file.\n"; - } + &run_ace_in_flow($prefix,i $abc_blif_out,$act_file,$ace_new_blif,$ace_log); $vpr_net = "$prefix"."vpr.net"; $vpr_place = "$prefix"."vpr.place"; @@ -2483,81 +2237,8 @@ sub run_mccl_flow($ $ $ $ $) $vpr_log = "$prefix"."vpr.log"; $vpr_reroute_log = "$prefix"."vpr_reroute.log"; - if ("on" eq $opt_ptr->{min_route_chan_width}) { - &run_std_vpr($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,-1,$vpr_log.".min_chan_width",$act_file); - # Get the Minimum channel width - my ($min_chan_width) = (&extract_min_chan_width_vpr_stats($tag,$benchmark,$vpr_log.".min_chan_width",$opt_ptr->{K_val}, $opt_ptr->{min_route_chan_width}, $parse_results)); - $min_chan_width = int($min_chan_width*$opt_ptr->{min_route_chan_width_val}); - if (0 != $min_chan_width%2) { - $min_chan_width += 1; - } - # Remove previous route results - if (-e $vpr_route) { - `rm $vpr_route`; - } - # Keep increase min_chan_width until route success - # Extract data from VPR stats - #&run_std_vpr($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,$min_chan_width,$vpr_log,$act_file); - while (1) { - &run_vpr_route($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,$min_chan_width,$vpr_reroute_log,$act_file); - # TODO: Only run the routing stage - if (-e $vpr_route) { - print "INFO: try route_chan_width($min_chan_width) success!\n"; - last; #Jump out - } else { - print "INFO: try route_chan_width($min_chan_width) failed! Retry with +2...\n"; - $min_chan_width += 2; - } - } - if (1 == $parse_results) { - &extract_min_chan_width_vpr_stats($tag,$benchmark,$vpr_reroute_log,$opt_ptr->{K_val}, "off", $parse_results); - &extract_vpr_stats($tag,$benchmark,$vpr_log.".min_chan_width",$opt_ptr->{K_val}); - &extract_vpr_stats($tag,$benchmark,$vpr_reroute_log,$opt_ptr->{K_val}); - } - } elsif ("on" eq $opt_ptr->{fix_route_chan_width}) { - my ($fix_chan_width) = ($benchmarks_ptr->{$benchmark_file}->{fix_route_chan_width}); - # Remove previous route results - if (-e $vpr_route) { - `rm $vpr_route`; - } - # Keep increase min_chan_width until route success - &run_std_vpr($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,$fix_chan_width,$vpr_log,$act_file); - while (1) { - # TODO: Only run the routing stage - if (-e $vpr_route) { - print "INFO: try route_chan_width($fix_chan_width) success!\n"; - last; #Jump out - } else { - print "INFO: try route_chan_width($fix_chan_width) failed! Retry with +2...\n"; - $fix_chan_width += 2; - &run_vpr_route($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,$fix_chan_width,$vpr_reroute_log,$act_file); - } - } - # Extract data from VPR stats - if (1 == $parse_results) { - &extract_min_chan_width_vpr_stats($tag,$benchmark,$vpr_log,$opt_ptr->{K_val}, "off", $parse_results); - &extract_vpr_stats($tag,$benchmark,$vpr_log,$opt_ptr->{K_val}); - if (-e $vpr_reroute_log) { - &extract_vpr_stats($tag,$benchmark,$vpr_reroute_log,$opt_ptr->{K_val}); - } - } - } else { - &run_std_vpr($abc_blif_out,$benchmark,$vpr_arch,$vpr_net,$vpr_place,$vpr_route,-1,$vpr_log,$act_file); - if (!(-e $vpr_route)) { - die "ERROR: Route Fail for $abc_blif_out!\n"; - } - # Get the Minimum channel width - my ($min_chan_width) = (&extract_min_chan_width_vpr_stats($tag,$benchmark,$vpr_log,$opt_ptr->{K_val},"on",$parse_results)); - if (1 == $parse_results) { - &extract_vpr_stats($tag,$benchmark,$vpr_log,$opt_ptr->{K_val}); - } - } - - # Extract data from VPR Power stats - if (("on" eq $opt_ptr->{power}) - &&(1 == $parse_results)) { - &extract_vpr_power_esti($tag,$abc_blif_out,$benchmark,$opt_ptr->{K_val}); - } + # Run VPR + &run_vpr_in_flow($tag, $benchmark, $benchmark_file, $abc_blif_out, $vpr_arch, $act_file, $vpr_net, $vpr_place, $vpr_route, $vpr_log, $vpr_reroute_log, $parse_results); return; } diff --git a/vpr7_rram/vpr/SRC/fpga_spice/fpga_spice_utils.c b/vpr7_rram/vpr/SRC/fpga_spice/fpga_spice_utils.c index 4f6609784..806dd8bc4 100644 --- a/vpr7_rram/vpr/SRC/fpga_spice/fpga_spice_utils.c +++ b/vpr7_rram/vpr/SRC/fpga_spice/fpga_spice_utils.c @@ -219,6 +219,7 @@ char* chomp_file_name_postfix(char* file_name) { return ret; } + /* Print SRAM bits, typically in a comment line */ void fprint_commented_sram_bits(FILE* fp, int num_sram_bits, int* sram_bits) { @@ -603,6 +604,25 @@ char* my_itoa(int input) { return ret; } +/* Generate a filename (string) for a grid subckt SPICE netlist, + * with given x and y coordinates + */ +char* fpga_spice_create_one_subckt_filename(char* file_name_prefix, + int subckt_x, int subckt_y, + char* file_name_postfix) { + char* fname = NULL; + + fname = (char*) my_malloc(sizeof(char) * (strlen(file_name_prefix) + + strlen(my_itoa(subckt_x)) + strlen(my_itoa(subckt_y)) + + strlen(file_name_postfix) + 1)); + + sprintf(fname, "%s%d_%d%s", + file_name_prefix, subckt_x, subckt_y, file_name_postfix); + + return fname; +} + + /* With given spice_model_port, find the pb_type port with same name and type*/ t_port* find_pb_type_port_match_spice_model_port(t_pb_type* pb_type, t_spice_model_port* spice_model_port) { @@ -1964,15 +1984,15 @@ int recommend_num_sim_clock_cycle(float sim_window_size) { /* It may be more reasonable to use median * But, if median density is 0, we use average density */ - if ((0 == median_density) && (0 == avg_density)) { + if ((0. == median_density) && (0. == avg_density)) { recmd_num_sim_clock_cycle = 1; vpr_printf(TIO_MESSAGE_WARNING, "All the signal density is zero! No. of clock cycles in simulations are set to be %d!", recmd_num_sim_clock_cycle); - } else if (0 == avg_density) { - recmd_num_sim_clock_cycle = (int)(1/median_density); - } else if (0 == median_density) { - recmd_num_sim_clock_cycle = (int)(1/avg_density); + } else if (0. == avg_density) { + recmd_num_sim_clock_cycle = (int)round(1/median_density); + } else if (0. == median_density) { + recmd_num_sim_clock_cycle = (int)round(1/avg_density); } else { /* add a sim window size to balance the weight of average density and median density * In practice, we find that there could be huge difference between avereage and median values @@ -5730,6 +5750,14 @@ char** assign_lut_truth_table(t_logical_block* mapped_logical_block, return truth_table; } +/* Get initial value of a Latch/FF output*/ +int get_ff_output_init_val(t_logical_block* ff_logical_block) { + assert((0 == ff_logical_block->init_val)||(1 == ff_logical_block->init_val)); + + return ff_logical_block->init_val; +} + +/* Get initial value of a mapped LUT output*/ int get_lut_output_init_val(t_logical_block* lut_logical_block) { int i; int* sram_bits = NULL; /* decoded SRAM bits */ @@ -5831,7 +5859,7 @@ int get_logical_block_output_init_val(t_logical_block* cur_logical_block) { /* We have no information, give a default 0 now... * TODO: find a smarter way! */ - output_init_val = 0; + output_init_val = get_ff_output_init_val(cur_logical_block); break; default: vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid type of SPICE MODEL (name=%s) in determining the initial output value of logical block(name=%s)!\n", @@ -7213,4 +7241,40 @@ int count_cb_info_num_ipin_rr_nodes(t_cb cur_cb_info) { return cnt; } +/* Add a subckt file name to a linked list */ +t_llist* add_one_subckt_file_name_to_llist(t_llist* cur_head, + char* subckt_file_path) { + t_llist* new_head = NULL; + + if (NULL == cur_head) { + new_head = create_llist(1); + new_head->dptr = (void*) my_strdup(subckt_file_path); + } else { + new_head = insert_llist_node_before_head(cur_head); + new_head->dptr = (void*) my_strdup(subckt_file_path); + } + + return new_head; +} + +/* Check if SPICE subckt is already created + * (if they exist in a given linked-list + */ +boolean check_subckt_file_exist_in_llist(t_llist* subckt_llist_head, + char* subckt_file_name) { + t_llist* temp = NULL; + + temp = subckt_llist_head; + while (temp) { + if (0 == strcmp(subckt_file_name, (char*)(temp->dptr))) { + return TRUE; + } + temp = temp->next; + } + + return FALSE; +} + + + diff --git a/vpr7_rram/vpr/SRC/fpga_spice/fpga_spice_utils.h b/vpr7_rram/vpr/SRC/fpga_spice/fpga_spice_utils.h index 27a6742d8..65dc09e5c 100644 --- a/vpr7_rram/vpr/SRC/fpga_spice/fpga_spice_utils.h +++ b/vpr7_rram/vpr/SRC/fpga_spice/fpga_spice_utils.h @@ -48,6 +48,10 @@ t_spice_transistor_type* find_mosfet_tech_lib(t_spice_tech_lib tech_lib, char* my_itoa(int input); +char* fpga_spice_create_one_subckt_filename(char* file_name_prefix, + int subckt_x, int subckt_y, + char* file_name_postfix); + char* chomp_spice_node_prefix(char* spice_node_prefix); char* format_spice_node_prefix(char* spice_node_prefix); @@ -450,6 +454,8 @@ int* generate_lut_sram_bits(int truth_table_len, char** assign_lut_truth_table(t_logical_block* mapped_logical_block, int* truth_table_length); +int get_ff_output_init_val(t_logical_block* ff_logical_block); + int get_lut_output_init_val(t_logical_block* lut_logical_block); int get_logical_block_output_init_val(t_logical_block* cur_logical_block); @@ -616,3 +622,9 @@ boolean is_cb_exist(t_rr_type cb_type, int cb_x, int cb_y); int count_cb_info_num_ipin_rr_nodes(t_cb cur_cb_info); + +t_llist* add_one_subckt_file_name_to_llist(t_llist* cur_head, + char* subckt_file_path); + +boolean check_subckt_file_exist_in_llist(t_llist* subckt_llist_head, + char* subckt_file_name); diff --git a/vpr7_rram/vpr/SRC/spice/spice_api.c b/vpr7_rram/vpr/SRC/spice/spice_api.c index 3667278fb..296a34823 100644 --- a/vpr7_rram/vpr/SRC/spice/spice_api.c +++ b/vpr7_rram/vpr/SRC/spice/spice_api.c @@ -330,7 +330,7 @@ void vpr_print_spice_netlists(t_vpr_setup vpr_setup, lut_testbench_dir_path = my_strcat(spice_dir_formatted, spice_lut_tb_dir_name); create_dir_path(lut_testbench_dir_path); spice_print_lut_testbench(lut_testbench_dir_path, chomped_circuit_name, include_dir_path, subckt_dir_path, - rr_node_indices, num_clocks, Arch, vpr_setup.FPGA_SPICE_Opts.SpiceOpts.fpga_spice_leakage_only); + rr_node_indices, num_clocks, Arch, vpr_setup.FPGA_SPICE_Opts.SpiceOpts.fpga_spice_leakage_only); } /* Print hardlogic testbench file if needed */ diff --git a/vpr7_rram/vpr/SRC/spice/spice_globals.c b/vpr7_rram/vpr/SRC/spice/spice_globals.c index b3c53d758..ec7efab14 100644 --- a/vpr7_rram/vpr/SRC/spice/spice_globals.c +++ b/vpr7_rram/vpr/SRC/spice/spice_globals.c @@ -12,6 +12,8 @@ /* Threshold of max transistor width for each transistor */ float max_width_per_trans = 5.; +char* spice_netlist_file_postfix = ".sp"; + char* nmos_subckt_name = "vpr_nmos"; char* pmos_subckt_name = "vpr_pmos"; char* io_nmos_subckt_name = "vpr_io_nmos"; @@ -24,13 +26,21 @@ char* basics_spice_file_name = "inv_buf_trans_gate.sp"; char* muxes_spice_file_name = "muxes.sp"; char* rram_veriloga_file_name = "rram_behavior.va"; char* wires_spice_file_name = "wires.sp"; -char* logic_block_spice_file_name = "logic_blocks.sp"; +char* logic_block_spice_file_name = "grid_header.sp"; char* luts_spice_file_name = "luts.sp"; -char* routing_spice_file_name = "routing.sp"; +char* routing_spice_file_name = "routing_header.sp"; char* meas_header_file_name = "meas_params.sp"; char* stimu_header_file_name = "stimulate_params.sp"; char* design_param_header_file_name = "design_params.sp"; +/* Prefix for subckt SPICE netlists */ +char* grid_spice_file_name_prefix = "grid_"; +char* chanx_spice_file_name_prefix = "chanx_"; +char* chany_spice_file_name_prefix = "chany_"; +char* sb_spice_file_name_prefix = "sb_"; +char* cbx_spice_file_name_prefix = "cbx_"; +char* cby_spice_file_name_prefix = "cby_"; + /* Postfix for circuit design parameters */ char* design_param_postfix_input_buf_size = "_input_buf_size"; char* design_param_postfix_output_buf_size = "_output_buf_size"; @@ -82,6 +92,11 @@ int num_used_io_tb = 0; /* linked-list for all the testbenches */ t_llist* tb_head = NULL; + +/* Linked-list that stores submodule Verilog file mames */ +t_llist* grid_spice_subckt_file_path_head = NULL; +t_llist* routing_spice_subckt_file_path_head = NULL; + /* linked-list for heads of scan-chain */ t_llist* scan_chain_heads = NULL; diff --git a/vpr7_rram/vpr/SRC/spice/spice_globals.h b/vpr7_rram/vpr/SRC/spice/spice_globals.h index 9ab1d92cd..9484eb554 100644 --- a/vpr7_rram/vpr/SRC/spice/spice_globals.h +++ b/vpr7_rram/vpr/SRC/spice/spice_globals.h @@ -1,6 +1,8 @@ /* global parameters for SPICE support*/ extern float max_width_per_trans; +extern char* spice_netlist_file_postfix; + extern char* nmos_subckt_name; extern char* pmos_subckt_name; extern char* io_nmos_subckt_name; @@ -20,6 +22,14 @@ extern char* meas_header_file_name; extern char* stimu_header_file_name; extern char* design_param_header_file_name; +/* Prefix for subckt SPICE netlists */ +extern char* grid_spice_file_name_prefix; +extern char* chanx_spice_file_name_prefix; +extern char* chany_spice_file_name_prefix; +extern char* sb_spice_file_name_prefix; +extern char* cbx_spice_file_name_prefix; +extern char* cby_spice_file_name_prefix; + /* Postfix for circuit design parameters */ extern char* design_param_postfix_input_buf_size; extern char* design_param_postfix_output_buf_size; @@ -78,7 +88,14 @@ extern int num_used_lut_tb; extern int num_used_dff_tb; extern int num_used_hardlogic_tb; extern int num_used_io_tb; + +/* linked-list for all the testbenches */ extern t_llist* tb_head; + +/* Linked-list that stores submodule Verilog file mames */ +extern t_llist* grid_spice_subckt_file_path_head; +extern t_llist* routing_spice_subckt_file_path_head; + /* Heads of scan-chain */ extern t_llist* scan_chain_heads; diff --git a/vpr7_rram/vpr/SRC/spice/spice_grid_testbench.c b/vpr7_rram/vpr/SRC/spice/spice_grid_testbench.c index 96646e639..cb232b6b9 100644 --- a/vpr7_rram/vpr/SRC/spice/spice_grid_testbench.c +++ b/vpr7_rram/vpr/SRC/spice/spice_grid_testbench.c @@ -452,14 +452,20 @@ int fprint_spice_one_grid_testbench(char* formatted_spice_dir, /* Special subckts for Top-level SPICE netlist */ fprintf(fp, "****** Include subckt netlists: Look-Up Tables (LUTs) *****\n"); - temp_include_file_path = my_strcat(formatted_subckt_dir_path, luts_spice_file_name); - fprintf(fp, ".include \'%s\'\n", temp_include_file_path); - my_free(temp_include_file_path); + spice_print_one_include_subckt_line(fp, formatted_subckt_dir_path, luts_spice_file_name); - fprintf(fp, "****** Include subckt netlists: Logic Blocks *****\n"); - temp_include_file_path = my_strcat(formatted_subckt_dir_path, logic_block_spice_file_name); - fprintf(fp, ".include \'%s\'\n", temp_include_file_path); - my_free(temp_include_file_path); + /* Generate filename */ + fprintf(fp, "****** Include subckt netlists: Grid[%d][%d] *****\n", + grid_x, grid_y); + temp_include_file_path = fpga_spice_create_one_subckt_filename(grid_spice_file_name_prefix, grid_x, grid_y, spice_netlist_file_postfix); + /* Check if we include an existing file! */ + if (FALSE == check_subckt_file_exist_in_llist(grid_spice_subckt_file_path_head, + my_strcat(formatted_subckt_dir_path, temp_include_file_path))) { + vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Intend to include a non-existed SPICE netlist %s!\n", + __FILE__, __LINE__, temp_include_file_path); + exit(1); + } + spice_print_one_include_subckt_line(fp, formatted_subckt_dir_path, temp_include_file_path); /* Print simulation temperature and other options for SPICE */ fprint_spice_options(fp, arch.spice->spice_params); @@ -516,6 +522,7 @@ void spice_print_grid_testbench(char* formatted_spice_dir, t_arch arch, boolean leakage_only) { char* grid_testbench_name = NULL; + char* temp_include_file_path = NULL; int ix, iy; int cnt = 0; int used; @@ -524,6 +531,15 @@ void spice_print_grid_testbench(char* formatted_spice_dir, for (ix = 1; ix < (nx+1); ix++) { for (iy = 1; iy < (ny+1); iy++) { + /* Check if we include an existing subckt file! */ + temp_include_file_path = fpga_spice_create_one_subckt_filename(grid_spice_file_name_prefix, ix, iy, spice_netlist_file_postfix); + if (FALSE == check_subckt_file_exist_in_llist(grid_spice_subckt_file_path_head, + my_strcat(subckt_dir_path, temp_include_file_path))) { + /* free */ + my_free(temp_include_file_path); + continue; + } + /* Create a testbench for the existing subckt */ grid_testbench_name = (char*)my_malloc(sizeof(char)*( strlen(circuit_name) + 6 + strlen(my_itoa(ix)) + 1 + strlen(my_itoa(iy)) + 1 @@ -539,6 +555,7 @@ void spice_print_grid_testbench(char* formatted_spice_dir, } /* free */ my_free(grid_testbench_name); + my_free(temp_include_file_path); } } /* Update the global counter */ diff --git a/vpr7_rram/vpr/SRC/spice/spice_lut_testbench.c b/vpr7_rram/vpr/SRC/spice/spice_lut_testbench.c index ffdf18e25..7644654c8 100644 --- a/vpr7_rram/vpr/SRC/spice/spice_lut_testbench.c +++ b/vpr7_rram/vpr/SRC/spice/spice_lut_testbench.c @@ -651,14 +651,20 @@ int fprint_spice_one_lut_testbench(char* formatted_spice_dir, /* Special subckts for Top-level SPICE netlist */ fprintf(fp, "****** Include subckt netlists: Look-Up Tables (LUTs) *****\n"); - temp_include_file_path = my_strcat(formatted_subckt_dir_path, luts_spice_file_name); - fprintf(fp, ".include \'%s\'\n", temp_include_file_path); - my_free(temp_include_file_path); + spice_print_one_include_subckt_line(fp, formatted_subckt_dir_path, luts_spice_file_name); - fprintf(fp, "****** Include subckt netlists: Logic Blocks *****\n"); - temp_include_file_path = my_strcat(formatted_subckt_dir_path, logic_block_spice_file_name); - fprintf(fp, ".include \'%s\'\n", temp_include_file_path); - my_free(temp_include_file_path); + /* Generate filename */ + fprintf(fp, "****** Include subckt netlists: Grid[%d][%d] *****\n", + grid_x, grid_y); + temp_include_file_path = fpga_spice_create_one_subckt_filename(grid_spice_file_name_prefix, grid_x, grid_y, spice_netlist_file_postfix); + /* Check if we include an existing file! */ + if (FALSE == check_subckt_file_exist_in_llist(grid_spice_subckt_file_path_head, + my_strcat(formatted_subckt_dir_path, temp_include_file_path))) { + vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Intend to include a non-existed SPICE netlist %s!\n", + __FILE__, __LINE__, temp_include_file_path); + exit(1); + } + spice_print_one_include_subckt_line(fp, formatted_subckt_dir_path, temp_include_file_path); /* Print simulation temperature and other options for SPICE */ fprint_spice_options(fp, arch.spice->spice_params); @@ -705,6 +711,9 @@ int fprint_spice_one_lut_testbench(char* formatted_spice_dir, used = 0; } + /* Free */ + my_free(temp_include_file_path); + return used; } @@ -719,6 +728,7 @@ void spice_print_lut_testbench(char* formatted_spice_dir, t_arch arch, boolean leakage_only) { char* lut_testbench_name = NULL; + char* temp_include_file_path = NULL; int ix, iy; int cnt = 0; int used; @@ -727,6 +737,16 @@ void spice_print_lut_testbench(char* formatted_spice_dir, for (ix = 1; ix < (nx+1); ix++) { for (iy = 1; iy < (ny+1); iy++) { + /* Check if we include an existing subckt file! */ + temp_include_file_path = fpga_spice_create_one_subckt_filename(grid_spice_file_name_prefix, ix, iy, spice_netlist_file_postfix); + if (FALSE == check_subckt_file_exist_in_llist(grid_spice_subckt_file_path_head, + my_strcat(subckt_dir_path, temp_include_file_path))) { + /* free */ + my_free(temp_include_file_path); + continue; + } + + /* Create a testbench for the existing subckt */ lut_testbench_name = (char*)my_malloc(sizeof(char)*( strlen(circuit_name) + 6 + strlen(my_itoa(ix)) + 1 + strlen(my_itoa(iy)) + 1 @@ -742,6 +762,7 @@ void spice_print_lut_testbench(char* formatted_spice_dir, } /* free */ my_free(lut_testbench_name); + my_free(temp_include_file_path); } } /* Update the global counter */ diff --git a/vpr7_rram/vpr/SRC/spice/spice_mux_testbench.c b/vpr7_rram/vpr/SRC/spice/spice_mux_testbench.c index e30346f71..83b643eba 100644 --- a/vpr7_rram/vpr/SRC/spice/spice_mux_testbench.c +++ b/vpr7_rram/vpr/SRC/spice/spice_mux_testbench.c @@ -1813,14 +1813,6 @@ int fprint_spice_one_mux_testbench(char* formatted_spice_dir, init_include_user_defined_netlists(*(arch.spice)); fprint_include_user_defined_netlists(fp, *(arch.spice)); - /* Special subckts for Top-level SPICE netlist */ - /* - fprintf(fp, "****** Include subckt netlists: Look-Up Tables (LUTs) *****\n"); - temp_include_file_path = my_strcat(formatted_subckt_dir_path, luts_spice_file_name); - fprintf(fp, ".include %s\n", temp_include_file_path); - my_free(temp_include_file_path); - */ - /* Print simulation temperature and other options for SPICE */ fprint_spice_options(fp, arch.spice->spice_params); diff --git a/vpr7_rram/vpr/SRC/spice/spice_pbtypes.c b/vpr7_rram/vpr/SRC/spice/spice_pbtypes.c index fd77fb0bd..5fa0a340d 100644 --- a/vpr7_rram/vpr/SRC/spice/spice_pbtypes.c +++ b/vpr7_rram/vpr/SRC/spice/spice_pbtypes.c @@ -2092,9 +2092,8 @@ void fprint_io_grid_block_subckt_pins(FILE* fp, } /* Print the SPICE netlist for a physical grid blocks */ -void fprint_grid_physical_blocks(FILE* fp, - int ix, - int iy, +void fprint_grid_physical_blocks(char* subckt_dir, + int ix, int iy, t_arch* arch) { int subckt_name_str_len = 0; char* subckt_name = NULL; @@ -2102,13 +2101,9 @@ void fprint_grid_physical_blocks(FILE* fp, int iz; int cur_block_index = 0; int capacity; + FILE* fp = NULL; + char* fname = NULL; - /* Check the file handler*/ - if (NULL == fp) { - vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", - __FILE__, __LINE__); - exit(1); - } /* Check */ assert((!(0 > ix))&&(!(ix > (nx + 1)))); assert((!(0 > iy))&&(!(iy > (ny + 1)))); @@ -2126,6 +2121,10 @@ void fprint_grid_physical_blocks(FILE* fp, update_spice_models_grid_index_high(ix, iy, arch->spice->num_spice_model, arch->spice->spice_models); return; } + + /* Create file handler */ + fp = spice_create_one_subckt_file(subckt_dir, "Phyiscal Logic Block ", grid_spice_file_name_prefix, ix, iy, &fname); + capacity = grid[ix][iy].type->capacity; assert(0 < capacity); @@ -2199,8 +2198,15 @@ void fprint_grid_physical_blocks(FILE* fp, fprintf(fp, ".eom\n"); + /* Close the file */ + fclose(fp); + + /* Add fname to the linked list */ + grid_spice_subckt_file_path_head = add_one_subckt_file_name_to_llist(grid_spice_subckt_file_path_head, fname); + /* Free */ my_free(subckt_name); + my_free(fname); return; } @@ -2208,9 +2214,8 @@ void fprint_grid_physical_blocks(FILE* fp, /* Print the SPICE netlist for a grid blocks */ -void fprint_grid_blocks(FILE* fp, - int ix, - int iy, +void fprint_grid_blocks(char* subckt_dir, + int ix, int iy, t_arch* arch) { int subckt_name_str_len = 0; char* subckt_name = NULL; @@ -2218,13 +2223,9 @@ void fprint_grid_blocks(FILE* fp, int iz; int cur_block_index = 0; int capacity; + FILE* fp = NULL; + char* fname = NULL; - /* Check the file handler*/ - if (NULL == fp) { - vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", - __FILE__, __LINE__); - exit(1); - } /* Check */ assert((!(0 > ix))&&(!(ix > (nx + 1)))); assert((!(0 > iy))&&(!(iy > (ny + 1)))); @@ -2244,6 +2245,9 @@ void fprint_grid_blocks(FILE* fp, return; } + /* Create file handler */ + fp = spice_create_one_subckt_file(subckt_dir, "Logic Block", grid_spice_file_name_prefix, ix, iy, &fname); + capacity= grid[ix][iy].type->capacity; assert(0 < capacity); @@ -2330,8 +2334,15 @@ void fprint_grid_blocks(FILE* fp, fprintf(fp, ".eom\n"); + /* Close the file */ + fclose(fp); + + /* Add fname to the linked list */ + grid_spice_subckt_file_path_head = add_one_subckt_file_name_to_llist(grid_spice_subckt_file_path_head, fname); + /* Free */ my_free(subckt_name); + my_free(fname); return; } @@ -2345,8 +2356,6 @@ void fprint_grid_blocks(FILE* fp, void generate_spice_logic_blocks(char* subckt_dir, t_arch* arch) { /* Create file names */ - char* sp_name = my_strcat(subckt_dir, logic_block_spice_file_name); - FILE* fp = NULL; int ix, iy; /* Check the grid*/ @@ -2357,15 +2366,6 @@ void generate_spice_logic_blocks(char* subckt_dir, vpr_printf(TIO_MESSAGE_INFO,"Grid size of FPGA: nx=%d ny=%d\n", nx + 1, ny + 1); assert(NULL != grid); - /* Create a file*/ - fp = fopen(sp_name, "w"); - if (NULL == fp) { - vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create subckt SPICE netlist %s",__FILE__, __LINE__, sp_name); - exit(1); - } - /* Generate the descriptions*/ - fprint_spice_head(fp,"Logic Blocks in FPGA"); - /* Print the core logic block one by one * Note ix=0 and ix = nx + 1 are IO pads. They surround the core logic blocks */ @@ -2376,7 +2376,7 @@ void generate_spice_logic_blocks(char* subckt_dir, assert(IO_TYPE != grid[ix][iy].type); /* Ensure a valid usage */ assert((0 == grid[ix][iy].usage)||(0 < grid[ix][iy].usage)); - fprint_grid_blocks(fp, ix, iy, arch); + fprint_grid_blocks(subckt_dir, ix, iy, arch); } } @@ -2388,7 +2388,7 @@ void generate_spice_logic_blocks(char* subckt_dir, /* Ensure this is a io */ assert(IO_TYPE == grid[ix][iy].type); /* TODO: replace with physical block generator */ - fprint_grid_physical_blocks(fp, ix, iy, arch); + fprint_grid_physical_blocks(subckt_dir, ix, iy, arch); } /* Right side : x = nx + 1, y = 1 .. ny*/ ix = nx + 1; @@ -2396,7 +2396,7 @@ void generate_spice_logic_blocks(char* subckt_dir, /* Ensure this is a io */ assert(IO_TYPE == grid[ix][iy].type); /* TODO: replace with physical block generator */ - fprint_grid_physical_blocks(fp, ix, iy, arch); + fprint_grid_physical_blocks(subckt_dir, ix, iy, arch); } /* Bottom side : x = 1 .. nx + 1, y = 0 */ iy = 0; @@ -2404,7 +2404,7 @@ void generate_spice_logic_blocks(char* subckt_dir, /* Ensure this is a io */ assert(IO_TYPE == grid[ix][iy].type); /* TODO: replace with physical block generator */ - fprint_grid_physical_blocks(fp, ix, iy, arch); + fprint_grid_physical_blocks(subckt_dir, ix, iy, arch); } /* Top side : x = 1 .. nx + 1, y = nx + 1 */ iy = ny + 1; @@ -2412,15 +2412,14 @@ void generate_spice_logic_blocks(char* subckt_dir, /* Ensure this is a io */ assert(IO_TYPE == grid[ix][iy].type); /* TODO: replace with physical block generator */ - fprint_grid_physical_blocks(fp, ix, iy, arch); + fprint_grid_physical_blocks(subckt_dir, ix, iy, arch); } + /* Output a header file for all the logic blocks */ + vpr_printf(TIO_MESSAGE_INFO,"Generating header file for grid submodules...\n"); + spice_print_subckt_header_file(grid_spice_subckt_file_path_head, + subckt_dir, + logic_block_spice_file_name); - /* Close the file */ - fclose(fp); - - /* Free */ - my_free(sp_name); - return; } diff --git a/vpr7_rram/vpr/SRC/spice/spice_routing.c b/vpr7_rram/vpr/SRC/spice/spice_routing.c index c2cfb021a..3165964d0 100644 --- a/vpr7_rram/vpr/SRC/spice/spice_routing.c +++ b/vpr7_rram/vpr/SRC/spice/spice_routing.c @@ -34,7 +34,7 @@ #include "spice_routing.h" -void fprint_routing_chan_subckt(FILE* fp, +void fprint_routing_chan_subckt(char* subckt_dir, int x, int y, t_rr_type chan_type, int LL_num_rr_nodes, t_rr_node* LL_rr_node, t_ivec*** LL_rr_node_indices, @@ -43,13 +43,9 @@ void fprint_routing_chan_subckt(FILE* fp, char* chan_prefix = NULL; int chan_width = 0; t_rr_node** chan_rr_nodes = NULL; - - /* Check the file handler*/ - if (NULL == fp) { - vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", - __FILE__, __LINE__); - exit(1); - } + FILE* fp = NULL; + char* fname = NULL; + /* Check */ assert((!(0 > x))&&(!(x > (nx + 1)))); assert((!(0 > y))&&(!(y > (ny + 1)))); @@ -58,10 +54,14 @@ void fprint_routing_chan_subckt(FILE* fp, /* Initial chan_prefix*/ switch (chan_type) { case CHANX: + /* Create file handler */ + fp = spice_create_one_subckt_file(subckt_dir, "Channel X-direction ", chanx_spice_file_name_prefix, x, y, &fname); chan_prefix = "chanx"; fprintf(fp, "***** Subckt for Channel X [%d][%d] *****\n", x, y); break; case CHANY: + /* Create file handler */ + fp = spice_create_one_subckt_file(subckt_dir, "Channel Y-direction ", chany_spice_file_name_prefix, x, y, &fname); chan_prefix = "chany"; fprintf(fp, "***** Subckt for Channel Y [%d][%d] *****\n", x, y); break; @@ -147,8 +147,15 @@ void fprint_routing_chan_subckt(FILE* fp, fprintf(fp, ".eom\n"); + /* Close the file*/ + fclose(fp); + + /* Add fname to the linked list */ + routing_spice_subckt_file_path_head = add_one_subckt_file_name_to_llist(routing_spice_subckt_file_path_head, fname); + /* Free */ my_free(chan_rr_nodes); + my_free(fname); return; } @@ -641,22 +648,21 @@ void fprint_switch_box_interc(FILE* fp, * For channels chanX with INC_DIRECTION on the right side, they should be marked as outputs * For channels chanX with DEC_DIRECTION on the right side, they should be marked as inputs */ -void fprint_routing_switch_box_subckt(FILE* fp, t_sb cur_sb_info, +void fprint_routing_switch_box_subckt(char* subckt_dir, + t_sb cur_sb_info, int LL_num_rr_nodes, t_rr_node* LL_rr_node, t_ivec*** LL_rr_node_indices) { int itrack, inode, side, ix, iy, x, y; - - /* Check the file handler*/ - if (NULL == fp) { - vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", - __FILE__, __LINE__); - exit(1); - } + FILE* fp = NULL; + char* fname = NULL; /* Check */ assert((!(0 > cur_sb_info.x))&&(!(cur_sb_info.x > (nx + 1)))); assert((!(0 > cur_sb_info.y))&&(!(cur_sb_info.y > (ny + 1)))); + /* Create file handler */ + fp = spice_create_one_subckt_file(subckt_dir, "Switch Block ", sb_spice_file_name_prefix, cur_sb_info.x, cur_sb_info.y, &fname); + x = cur_sb_info.x; y = cur_sb_info.y; @@ -734,7 +740,14 @@ void fprint_routing_switch_box_subckt(FILE* fp, t_sb cur_sb_info, fprintf(fp, ".eom\n"); + /* Close the file*/ + fclose(fp); + + /* Add fname to the linked list */ + routing_spice_subckt_file_path_head = add_one_subckt_file_name_to_llist(routing_spice_subckt_file_path_head, fname); + /* Free */ + my_free(fname); return; } @@ -1024,18 +1037,31 @@ void fprint_connection_box_interc(FILE* fp, * | | Connection | | * --------------Box_Y[x][y-1]-------------- */ -void fprint_routing_connection_box_subckt(FILE* fp, t_cb cur_cb_info, +void fprint_routing_connection_box_subckt(char* subckt_dir, + t_cb cur_cb_info, int LL_num_rr_nodes, t_rr_node* LL_rr_node, t_ivec*** LL_rr_node_indices) { int itrack, inode, side, x, y; int side_cnt = 0; + FILE* fp = NULL; + char* fname = NULL; - /* Check the file handler*/ - if (NULL == fp) { - vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", - __FILE__, __LINE__); + /* Identify the type of connection box + * Create file handler + */ + switch(cur_cb_info.type) { + case CHANX: + fp = spice_create_one_subckt_file(subckt_dir, "Connection Block X-channel ", cbx_spice_file_name_prefix, cur_cb_info.x, cur_cb_info.y, &fname); + break; + case CHANY: + fp = spice_create_one_subckt_file(subckt_dir, "Connection Block Y-channel ", cby_spice_file_name_prefix, cur_cb_info.x, cur_cb_info.y, &fname); + break; + default: + vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d])Invalid type of connection box!\n", + __FILE__, __LINE__); exit(1); } + /* Check */ assert((!(0 > cur_cb_info.x))&&(!(cur_cb_info.x > (nx + 1)))); assert((!(0 > cur_cb_info.y))&&(!(cur_cb_info.y > (ny + 1)))); @@ -1167,6 +1193,15 @@ void fprint_routing_connection_box_subckt(FILE* fp, t_cb cur_cb_info, fprintf(fp, ".eom\n"); + /* Close the file*/ + fclose(fp); + + /* Add fname to the linked list */ + routing_spice_subckt_file_path_head = add_one_subckt_file_name_to_llist(routing_spice_subckt_file_path_head, fname); + + /* Free */ + my_free(fname); + return; } @@ -1178,19 +1213,9 @@ void generate_spice_routing_resources(char* subckt_dir, t_det_routing_arch* routing_arch, int LL_num_rr_nodes, t_rr_node* LL_rr_node, t_ivec*** LL_rr_node_indices) { - FILE* fp = NULL; - char* sp_name = my_strcat(subckt_dir, routing_spice_file_name); int ix, iy; assert(UNI_DIRECTIONAL == routing_arch->directionality); - - /* Create FILE */ - fp = fopen(sp_name, "w"); - if (NULL == fp) { - vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create SPICE netlist %s",__FILE__, __LINE__, wires_spice_file_name); - exit(1); - } - fprint_spice_head(fp,"Routing Resources"); /* Two major tasks: * 1. Generate sub-circuits for Routing Channels @@ -1214,7 +1239,7 @@ void generate_spice_routing_resources(char* subckt_dir, vpr_printf(TIO_MESSAGE_INFO, "Writing X-direction Channels...\n"); for (iy = 0; iy < (ny + 1); iy++) { for (ix = 1; ix < (nx + 1); ix++) { - fprint_routing_chan_subckt(fp, ix, iy, CHANX, + fprint_routing_chan_subckt(subckt_dir, ix, iy, CHANX, LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices, arch.num_segments, arch.Segments); } @@ -1223,7 +1248,7 @@ void generate_spice_routing_resources(char* subckt_dir, vpr_printf(TIO_MESSAGE_INFO, "Writing Y-direction Channels...\n"); for (ix = 0; ix < (nx + 1); ix++) { for (iy = 1; iy < (ny + 1); iy++) { - fprint_routing_chan_subckt(fp, ix, iy, CHANY, + fprint_routing_chan_subckt(subckt_dir, ix, iy, CHANY, LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices, arch.num_segments, arch.Segments); } @@ -1234,7 +1259,7 @@ void generate_spice_routing_resources(char* subckt_dir, for (ix = 0; ix < (nx + 1); ix++) { for (iy = 0; iy < (ny + 1); iy++) { update_spice_models_routing_index_low(ix, iy, SOURCE, arch.spice->num_spice_model, arch.spice->spice_models); - fprint_routing_switch_box_subckt(fp, sb_info[ix][iy], + fprint_routing_switch_box_subckt(subckt_dir, sb_info[ix][iy], LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices); update_spice_models_routing_index_high(ix, iy, SOURCE, arch.spice->num_spice_model, arch.spice->spice_models); } @@ -1249,7 +1274,7 @@ void generate_spice_routing_resources(char* subckt_dir, /* Check if this cby_info exists, it may be covered by a heterogenous block */ if ((TRUE == is_cb_exist(CHANX, ix, iy)) &&(0 < count_cb_info_num_ipin_rr_nodes(cbx_info[ix][iy]))) { - fprint_routing_connection_box_subckt(fp, cbx_info[ix][iy], + fprint_routing_connection_box_subckt(subckt_dir, cbx_info[ix][iy], LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices); } update_spice_models_routing_index_high(ix, iy, CHANX, arch.spice->num_spice_model, arch.spice->spice_models); @@ -1262,16 +1287,18 @@ void generate_spice_routing_resources(char* subckt_dir, /* Check if this cby_info exists, it may be covered by a heterogenous block */ if ((TRUE == is_cb_exist(CHANY, ix, iy)) &&(0 < count_cb_info_num_ipin_rr_nodes(cby_info[ix][iy]))) { - fprint_routing_connection_box_subckt(fp, cby_info[ix][iy], + fprint_routing_connection_box_subckt(subckt_dir, cby_info[ix][iy], LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices); } update_spice_models_routing_index_high(ix, iy, CHANY, arch.spice->num_spice_model, arch.spice->spice_models); } } - /* Close the file*/ - fclose(fp); - + /* Output a header file for all the routing blocks */ + vpr_printf(TIO_MESSAGE_INFO,"Generating header file for routing submodules...\n"); + spice_print_subckt_header_file(routing_spice_subckt_file_path_head, + subckt_dir, + routing_spice_file_name); return; } diff --git a/vpr7_rram/vpr/SRC/spice/spice_routing_testbench.c b/vpr7_rram/vpr/SRC/spice/spice_routing_testbench.c index 792f959e6..ea1be2060 100644 --- a/vpr7_rram/vpr/SRC/spice/spice_routing_testbench.c +++ b/vpr7_rram/vpr/SRC/spice/spice_routing_testbench.c @@ -562,9 +562,11 @@ int fprint_spice_one_cb_testbench(char* formatted_spice_dir, switch (cb_type) { case CHANX: cb_tb_name = "Connection Box X-channel "; + temp_include_file_path = fpga_spice_create_one_subckt_filename(cbx_spice_file_name_prefix, grid_x, grid_y, spice_netlist_file_postfix); break; case CHANY: cb_tb_name = "Connection Box Y-channel "; + temp_include_file_path = fpga_spice_create_one_subckt_filename(cby_spice_file_name_prefix, grid_x, grid_y, spice_netlist_file_postfix); break; default: vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d]) Invalid connection_box_type!\n", __FILE__, __LINE__); @@ -611,15 +613,21 @@ int fprint_spice_one_cb_testbench(char* formatted_spice_dir, /* Quote defined Logic blocks subckts (Grids) */ init_spice_routing_testbench_globals(*(arch.spice)); - fprintf(fp, "****** Include subckt netlists: Routing structures (Switch Boxes, Channels, Connection Boxes) *****\n"); - temp_include_file_path = my_strcat(formatted_subckt_dir_path, routing_spice_file_name); - fprintf(fp, ".include \'%s\'\n", temp_include_file_path); - my_free(temp_include_file_path); - /* one cbx, one cby*/ switch (cb_type) { case CHANX: case CHANY: + /* Generate filename */ + fprintf(fp, "****** Include subckt netlists: %s [%d][%d] *****\n", + cb_tb_name, grid_x, grid_y); + /* Check if we include an existing file! */ + if (FALSE == check_subckt_file_exist_in_llist(routing_spice_subckt_file_path_head, + my_strcat(formatted_subckt_dir_path, temp_include_file_path))) { + vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Intend to include a non-existed SPICE netlist %s!", + __FILE__, __LINE__, temp_include_file_path); + exit(1); + } + spice_print_one_include_subckt_line(fp, formatted_subckt_dir_path, temp_include_file_path); used = fprint_spice_routing_testbench_call_one_cb_tb(fp, *(arch.spice), cb_type, grid_x, grid_y, LL_rr_node_indices); break; default: @@ -642,6 +650,9 @@ int fprint_spice_one_cb_testbench(char* formatted_spice_dir, max_sim_num_clock_cycles); used = 1; + /* Free */ + my_free(temp_include_file_path); + return used; } @@ -704,12 +715,22 @@ int fprint_spice_one_sb_testbench(char* formatted_spice_dir, /* Quote defined Logic blocks subckts (Grids) */ init_spice_routing_testbench_globals(*(arch.spice)); - fprintf(fp, "****** Include subckt netlists: Routing structures (Switch Boxes, Channels, Connection Boxes) *****\n"); - temp_include_file_path = my_strcat(formatted_subckt_dir_path, routing_spice_file_name); - fprintf(fp, ".include \'%s\'\n", temp_include_file_path); - my_free(temp_include_file_path); + /* Generate filename */ + fprintf(fp, "****** Include subckt netlists: Switch Block[%d][%d] *****\n", + grid_x, grid_y); + temp_include_file_path = fpga_spice_create_one_subckt_filename(sb_spice_file_name_prefix, grid_x, grid_y, spice_netlist_file_postfix); + /* Check if we include an existing file! */ + if (FALSE == check_subckt_file_exist_in_llist(routing_spice_subckt_file_path_head, + my_strcat(formatted_subckt_dir_path, temp_include_file_path))) { + vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Intend to include a non-existed SPICE netlist %s!", + __FILE__, __LINE__, temp_include_file_path); + exit(1); + } + spice_print_one_include_subckt_line(fp, formatted_subckt_dir_path, temp_include_file_path); + used = fprint_spice_routing_testbench_call_one_sb_tb(fp, *(arch.spice), grid_x, grid_y, LL_rr_node_indices); + /* Generate SPICE routing testbench generic stimuli*/ fprintf_spice_routing_testbench_generic_stimuli(fp, num_clocks); diff --git a/vpr7_rram/vpr/SRC/spice/spice_utils.c b/vpr7_rram/vpr/SRC/spice/spice_utils.c index 3362f94f6..f31aa0443 100644 --- a/vpr7_rram/vpr/SRC/spice/spice_utils.c +++ b/vpr7_rram/vpr/SRC/spice/spice_utils.c @@ -49,6 +49,104 @@ void fprint_spice_head(FILE* fp, return; } +/* Create a file handler for a subckt SPICE netlist */ +FILE* spice_create_one_subckt_file(char* subckt_dir, + char* subckt_name_prefix, + char* spice_subckt_file_name_prefix, + int grid_x, int grid_y, + char** sp_name) { + FILE* fp = NULL; + char* file_description = NULL; + (*sp_name) = my_strcat(subckt_dir, + fpga_spice_create_one_subckt_filename(spice_subckt_file_name_prefix, grid_x, grid_y, spice_netlist_file_postfix)); + + /* Create a file*/ + fp = fopen((*sp_name), "w"); + + if (NULL == fp) { + vpr_printf(TIO_MESSAGE_ERROR, + "(FILE:%s,LINE[%d])Failure in create subckt SPICE netlist %s", + __FILE__, __LINE__, (*sp_name)); + exit(1); + } + + /* Generate the descriptions*/ + file_description = (char*) my_malloc(sizeof(char) * (strlen(subckt_name_prefix) + 2 + + strlen(my_itoa(grid_x)) + 2 + strlen(my_itoa(grid_y)) + + 9)); + sprintf(file_description, "%s [%d][%d] in FPGA", + subckt_name_prefix, grid_x, grid_y); + fprint_spice_head(fp, file_description); + + /* Free */ + my_free(file_description); + + return fp; +} + +/* Include a subckt in SPICE netlist */ +void spice_print_one_include_subckt_line(FILE* fp, + char* subckt_dir, + char* subckt_file_name) { + char* temp_include_file_path = NULL; + + if (NULL == fp) { + vpr_printf(TIO_MESSAGE_ERROR, + "(FILE:%s,LINE[%d])Invalid File Handler of subckt SPICE netlist %s", + __FILE__, __LINE__); + exit(1); + } + + temp_include_file_path = my_strcat(subckt_dir, subckt_file_name); + fprintf(fp, ".include \'%s\'\n", temp_include_file_path); + my_free(temp_include_file_path); + + return; +} + +/* Output all the created subckt file names in a header file, + * that can be easily imported in a top-level netlist + */ +void spice_print_subckt_header_file(t_llist* subckt_llist_head, + char* subckt_dir, + char* header_file_name) { + FILE* fp = NULL; + char* spice_fname = NULL; + t_llist* temp = NULL; + + spice_fname = my_strcat(subckt_dir, + header_file_name); + + /* Create a file*/ + fp = fopen(spice_fname, "w"); + + if (NULL == fp) { + vpr_printf(TIO_MESSAGE_ERROR, + "(FILE:%s,LINE[%d])Failure in create SPICE netlist %s", + __FILE__, __LINE__, spice_fname); + exit(1); + } + + /* Generate the descriptions*/ + fprint_spice_head(fp, "Header file"); + + /* Output file names */ + temp = subckt_llist_head; + while (temp) { + fprintf(fp, ".include \'%s\'\n", + (char*)(temp->dptr)); + temp = temp->next; + } + + /* Close fp */ + fclose(fp); + + /* Free */ + my_free(spice_fname); + + return; +} + /* Print all the global ports that are stored in the linked list * Return the number of ports that have been dumped diff --git a/vpr7_rram/vpr/SRC/spice/spice_utils.h b/vpr7_rram/vpr/SRC/spice/spice_utils.h index eb2919c05..9a14f3f15 100644 --- a/vpr7_rram/vpr/SRC/spice/spice_utils.h +++ b/vpr7_rram/vpr/SRC/spice/spice_utils.h @@ -9,11 +9,24 @@ enum e_measure_type { void fprint_spice_head(FILE* fp, char* usage); +FILE* spice_create_one_subckt_file(char* subckt_dir, + char* subckt_name_prefix, + char* spice_subckt_file_name_prefix, + int grid_x, int grid_y, + char** sp_name); + +void spice_print_one_include_subckt_line(FILE* fp, + char* subckt_dir, + char* subckt_file_name); int rec_fprint_spice_model_global_ports(FILE* fp, t_spice_model* cur_spice_model, boolean recursive); +void spice_print_subckt_header_file(t_llist* subckt_llist_head, + char* subckt_dir, + char* header_file_name); + int fprint_spice_global_ports(FILE* fp, t_llist* head); void fprint_spice_generic_testbench_global_ports(FILE* fp, diff --git a/vpr7_rram/vpr/SRC/syn_verilog/verilog_global.c b/vpr7_rram/vpr/SRC/syn_verilog/verilog_global.c index 9e2c3b71a..729d2456f 100644 --- a/vpr7_rram/vpr/SRC/syn_verilog/verilog_global.c +++ b/vpr7_rram/vpr/SRC/syn_verilog/verilog_global.c @@ -8,6 +8,8 @@ #include "fpga_spice_globals.h" #include "verilog_global.h" +char* verilog_netlist_file_postfix = ".v"; + char* verilog_top_postfix = "_top.v"; char* bitstream_verilog_file_postfix = ".bitstream"; char* top_testbench_verilog_file_postfix = "_top_tb.v"; @@ -23,6 +25,14 @@ char* decoders_verilog_file_name = "decoders.v"; char* verilog_mux_basis_posfix = "_basis"; char* verilog_mux_special_basis_posfix = "_special_basis"; +/* Prefix for subckt Verilog netlists */ +char* grid_verilog_file_name_prefix = "grid_"; +char* chanx_verilog_file_name_prefix = "chanx_"; +char* chany_verilog_file_name_prefix = "chany_"; +char* sb_verilog_file_name_prefix = "sb_"; +char* cbx_verilog_file_name_prefix = "cbx_"; +char* cby_verilog_file_name_prefix = "cby_"; + /* SRAM SPICE MODEL should be set as global*/ t_spice_model* sram_verilog_model = NULL; enum e_sram_orgz sram_verilog_orgz_type = SPICE_SRAM_STANDALONE; @@ -34,4 +44,8 @@ t_spice_model* iopad_verilog_model = NULL; /* Linked-list that stores all the configuration bits */ t_llist* conf_bits_head = NULL; +/* Linked-list that stores submodule Verilog file mames */ +t_llist* grid_verilog_subckt_file_path_head = NULL; +t_llist* routing_verilog_subckt_file_path_head = NULL; + int verilog_default_signal_init_value = 0; diff --git a/vpr7_rram/vpr/SRC/syn_verilog/verilog_global.h b/vpr7_rram/vpr/SRC/syn_verilog/verilog_global.h index f98c3355b..15b3ffdec 100644 --- a/vpr7_rram/vpr/SRC/syn_verilog/verilog_global.h +++ b/vpr7_rram/vpr/SRC/syn_verilog/verilog_global.h @@ -1,4 +1,7 @@ /* global parameters for dumping synthesizable verilog */ + +extern char* verilog_netlist_file_postfix; + extern char* verilog_top_postfix; extern char* bitstream_verilog_file_postfix; extern char* top_testbench_verilog_file_postfix; @@ -13,6 +16,14 @@ extern char* decoders_verilog_file_name; extern char* verilog_mux_basis_posfix; extern char* verilog_mux_special_basis_posfix; +/* Prefix for subckt Verilog netlists */ +extern char* grid_verilog_file_name_prefix; +extern char* chanx_verilog_file_name_prefix; +extern char* chany_verilog_file_name_prefix; +extern char* sb_verilog_file_name_prefix; +extern char* cbx_verilog_file_name_prefix; +extern char* cby_verilog_file_name_prefix; + extern t_spice_model* sram_verilog_model; extern enum e_sram_orgz sram_verilog_orgz_type; extern t_sram_orgz_info* sram_verilog_orgz_info; @@ -25,6 +36,10 @@ extern t_spice_model* iopad_verilog_model; /* Linked-list that stores all the configuration bits */ extern t_llist* conf_bits_head; +/* Linked-list that stores submodule Verilog file mames */ +extern t_llist* grid_verilog_subckt_file_path_head; +extern t_llist* routing_verilog_subckt_file_path_head; + extern int verilog_default_signal_init_value; enum e_dump_verilog_port_type { diff --git a/vpr7_rram/vpr/SRC/syn_verilog/verilog_pbtypes.c b/vpr7_rram/vpr/SRC/syn_verilog/verilog_pbtypes.c index 9b663ec1d..a32c8ed68 100644 --- a/vpr7_rram/vpr/SRC/syn_verilog/verilog_pbtypes.c +++ b/vpr7_rram/vpr/SRC/syn_verilog/verilog_pbtypes.c @@ -3135,10 +3135,9 @@ void dump_verilog_io_grid_block_subckt_pins(FILE* fp, } /* Print the SPICE netlist for a grid blocks */ -void dump_verilog_grid_blocks(FILE* fp, - int ix, - int iy, - t_arch* arch) { +void dump_verilog_grid_blocks(char* subckt_dir, + int ix, int iy, + t_arch* arch) { int subckt_name_str_len = 0; char* subckt_name = NULL; t_block* mapped_block = NULL; @@ -3152,13 +3151,9 @@ void dump_verilog_grid_blocks(FILE* fp, int temp_inpad_lsb, temp_inpad_msb; int temp_outpad_lsb, temp_outpad_msb; int temp_iopad_lsb, temp_iopad_msb; + FILE* fp = NULL; + char* fname = NULL; - /* Check the file handler*/ - if (NULL == fp) { - vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", - __FILE__, __LINE__); - exit(1); - } /* Check */ assert((!(0 > ix))&&(!(ix > (nx + 1)))); assert((!(0 > iy))&&(!(iy > (ny + 1)))); @@ -3179,6 +3174,10 @@ void dump_verilog_grid_blocks(FILE* fp, update_spice_models_grid_index_high(ix, iy, arch->spice->num_spice_model, arch->spice->spice_models); return; } + + /* Create file handler */ + fp = verilog_create_one_subckt_file(subckt_dir, "Logic Block ", grid_verilog_file_name_prefix, ix, iy, &fname); + capacity= grid[ix][iy].type->capacity; assert(0 < capacity); @@ -3336,16 +3335,22 @@ void dump_verilog_grid_blocks(FILE* fp, assert(temp_conf_bits_msb == get_sram_orgz_info_num_mem_bit(sram_verilog_orgz_info)); + /* Close file*/ + fclose(fp); + + /* Add fname to the linked list */ + grid_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(grid_verilog_subckt_file_path_head, fname); + /* Free */ my_free(subckt_name); + my_free(fname); return; } /* Print the SPICE netlist for a I/O grid blocks */ -void dump_verilog_physical_grid_blocks(FILE* fp, - int ix, - int iy, +void dump_verilog_physical_grid_blocks(char* subckt_dir, + int ix, int iy, t_arch* arch) { int subckt_name_str_len = 0; char* subckt_name = NULL; @@ -3357,13 +3362,9 @@ void dump_verilog_physical_grid_blocks(FILE* fp, int temp_inpad_lsb, temp_inpad_msb; int temp_outpad_lsb, temp_outpad_msb; int temp_iopad_lsb, temp_iopad_msb; + FILE* fp = NULL; + char* fname = NULL; - /* Check the file handler*/ - if (NULL == fp) { - vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", - __FILE__, __LINE__); - exit(1); - } /* Check */ assert((!(0 > ix))&&(!(ix > (nx + 1)))); assert((!(0 > iy))&&(!(iy > (ny + 1)))); @@ -3384,6 +3385,10 @@ void dump_verilog_physical_grid_blocks(FILE* fp, update_spice_models_grid_index_high(ix, iy, arch->spice->num_spice_model, arch->spice->spice_models); return; } + + /* Create file handler */ + fp = verilog_create_one_subckt_file(subckt_dir, "Physical Logic Block ", grid_verilog_file_name_prefix, ix, iy, &fname); + capacity= grid[ix][iy].type->capacity; assert(0 < capacity); @@ -3520,8 +3525,15 @@ void dump_verilog_physical_grid_blocks(FILE* fp, assert(temp_conf_bits_msb == get_sram_orgz_info_num_mem_bit(sram_verilog_orgz_info)); assert(temp_iopad_msb == iopad_verilog_model->grid_index_high[ix][iy]); + /* Close the file */ + fclose(fp); + + /* Add fname to the linked list */ + grid_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(grid_verilog_subckt_file_path_head, fname); + /* Free */ my_free(subckt_name); + my_free(fname); return; } @@ -3533,9 +3545,6 @@ void dump_verilog_physical_grid_blocks(FILE* fp, */ void dump_verilog_logic_blocks(char* subckt_dir, t_arch* arch) { - /* Create file names */ - char* sp_name = my_strcat(subckt_dir, logic_block_verilog_file_name); - FILE* fp = NULL; int ix, iy; /* Check the grid*/ @@ -3543,18 +3552,10 @@ void dump_verilog_logic_blocks(char* subckt_dir, vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid grid size (nx=%d, ny=%d)!\n", __FILE__, __LINE__, nx, ny); return; } + vpr_printf(TIO_MESSAGE_INFO,"Grid size of FPGA: nx=%d ny=%d\n", nx + 1, ny + 1); assert(NULL != grid); - /* Create a file*/ - fp = fopen(sp_name, "w"); - if (NULL == fp) { - vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create verilog netlist %s",__FILE__, __LINE__, sp_name); - exit(1); - } - /* Generate the descriptions*/ - dump_verilog_file_header(fp,"Logic Blocks in FPGA"); - /* Print the core logic block one by one * Note ix=0 and ix = nx + 1 are IO pads. They surround the core logic blocks */ @@ -3565,7 +3566,7 @@ void dump_verilog_logic_blocks(char* subckt_dir, assert(IO_TYPE != grid[ix][iy].type); /* Ensure a valid usage */ assert((0 == grid[ix][iy].usage)||(0 < grid[ix][iy].usage)); - dump_verilog_grid_blocks(fp, ix, iy, arch); + dump_verilog_grid_blocks(subckt_dir, ix, iy, arch); } } @@ -3576,36 +3577,37 @@ void dump_verilog_logic_blocks(char* subckt_dir, for (iy = 1; iy < (ny + 1); iy++) { /* Ensure this is a io */ assert(IO_TYPE == grid[ix][iy].type); - dump_verilog_physical_grid_blocks(fp, ix, iy, arch); + dump_verilog_physical_grid_blocks(subckt_dir, ix, iy, arch); } /* Right side : x = nx + 1, y = 1 .. ny*/ ix = nx + 1; for (iy = 1; iy < (ny + 1); iy++) { /* Ensure this is a io */ assert(IO_TYPE == grid[ix][iy].type); - dump_verilog_physical_grid_blocks(fp, ix, iy, arch); + dump_verilog_physical_grid_blocks(subckt_dir, ix, iy, arch); } /* Bottom side : x = 1 .. nx + 1, y = 0 */ iy = 0; for (ix = 1; ix < (nx + 1); ix++) { /* Ensure this is a io */ assert(IO_TYPE == grid[ix][iy].type); - dump_verilog_physical_grid_blocks(fp, ix, iy, arch); + dump_verilog_physical_grid_blocks(subckt_dir, ix, iy, arch); } /* Top side : x = 1 .. nx + 1, y = nx + 1 */ iy = ny + 1; for (ix = 1; ix < (nx + 1); ix++) { /* Ensure this is a io */ assert(IO_TYPE == grid[ix][iy].type); - dump_verilog_physical_grid_blocks(fp, ix, iy, arch); + dump_verilog_physical_grid_blocks(subckt_dir, ix, iy, arch); } - - /* Close the file */ - fclose(fp); + /* Output a header file for all the logic blocks */ + vpr_printf(TIO_MESSAGE_INFO,"Generating header file for grid submodules...\n"); + dump_verilog_subckt_header_file(grid_verilog_subckt_file_path_head, + subckt_dir, + logic_block_verilog_file_name); /* Free */ - my_free(sp_name); return; } diff --git a/vpr7_rram/vpr/SRC/syn_verilog/verilog_routing.c b/vpr7_rram/vpr/SRC/syn_verilog/verilog_routing.c index 76b48a130..2305058ce 100644 --- a/vpr7_rram/vpr/SRC/syn_verilog/verilog_routing.c +++ b/vpr7_rram/vpr/SRC/syn_verilog/verilog_routing.c @@ -34,7 +34,7 @@ #include "verilog_routing.h" -void dump_verilog_routing_chan_subckt(FILE* fp, +void dump_verilog_routing_chan_subckt(char* subckt_dir, int x, int y, t_rr_type chan_type, int LL_num_rr_nodes, t_rr_node* LL_rr_node, @@ -44,13 +44,9 @@ void dump_verilog_routing_chan_subckt(FILE* fp, char* chan_prefix = NULL; int chan_width = 0; t_rr_node** chan_rr_nodes = NULL; + FILE* fp = NULL; + char* fname = NULL; - /* Check the file handler*/ - if (NULL == fp) { - vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", - __FILE__, __LINE__); - exit(1); - } /* Check */ assert((!(0 > x))&&(!(x > (nx + 1)))); assert((!(0 > y))&&(!(y > (ny + 1)))); @@ -59,11 +55,15 @@ void dump_verilog_routing_chan_subckt(FILE* fp, /* Initial chan_prefix*/ switch (chan_type) { case CHANX: + /* Create file handler */ + fp = verilog_create_one_subckt_file(subckt_dir, "Routing Channel - X direction ", chanx_verilog_file_name_prefix, x, y, &fname); chan_prefix = "chanx"; /* Comment lines */ fprintf(fp, "//----- Verilog Module of Channel X [%d][%d] -----\n", x, y); break; case CHANY: + /* Create file handler */ + fp = verilog_create_one_subckt_file(subckt_dir, "Routing Channel - Y direction ", chany_verilog_file_name_prefix, x, y, &fname); chan_prefix = "chany"; /* Comment lines */ fprintf(fp, "//----- Verilog Module Channel Y [%d][%d] -----\n", x, y); @@ -162,9 +162,16 @@ void dump_verilog_routing_chan_subckt(FILE* fp, exit(1); } + /* Close file handler */ + fclose(fp); + + /* Add fname to the linked list */ + routing_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(routing_verilog_subckt_file_path_head, fname); + /* Free */ my_free(chan_rr_nodes); - + my_free(fname); + return; } @@ -1056,18 +1063,13 @@ int count_verilog_switch_box_conf_bits(t_sb* cur_sb_info) { * | | | | * -------------- -------------- */ -void dump_verilog_routing_switch_box_subckt(FILE* fp, t_sb* cur_sb_info, +void dump_verilog_routing_switch_box_subckt(char* subckt_dir, t_sb* cur_sb_info, int LL_num_rr_nodes, t_rr_node* LL_rr_node, t_ivec*** LL_rr_node_indices) { int itrack, inode, side, ix, iy, x, y; int cur_num_sram, num_conf_bits, num_reserved_conf_bits, esti_sram_cnt; - - /* Check the file handler*/ - if (NULL == fp) { - vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", - __FILE__, __LINE__); - exit(1); - } + FILE* fp = NULL; + char* fname = NULL; /* Check */ assert((!(0 > cur_sb_info->x))&&(!(cur_sb_info->x > (nx + 1)))); @@ -1088,6 +1090,9 @@ void dump_verilog_routing_switch_box_subckt(FILE* fp, t_sb* cur_sb_info, cur_sb_info->conf_bits_lsb = cur_num_sram; cur_sb_info->conf_bits_msb = cur_num_sram + num_conf_bits; + /* Create file handler */ + fp = verilog_create_one_subckt_file(subckt_dir, "Switch Block ", sb_verilog_file_name_prefix, cur_sb_info->x, cur_sb_info->y, &fname); + /* Comment lines */ fprintf(fp, "//----- Verilog Module of Switch Box[%d][%d] -----\n", cur_sb_info->x, cur_sb_info->y); /* Print the definition of subckt*/ @@ -1175,7 +1180,14 @@ void dump_verilog_routing_switch_box_subckt(FILE* fp, t_sb* cur_sb_info, /* Check */ assert(esti_sram_cnt == get_sram_orgz_info_num_mem_bit(sram_verilog_orgz_info)); + /* Close file handler */ + fclose(fp); + + /* Add fname to the linked list */ + routing_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(routing_verilog_subckt_file_path_head, fname); + /* Free chan_rr_nodes */ + my_free(fname); return; } @@ -1640,20 +1652,15 @@ int count_verilog_connection_box_reserved_conf_bits(t_cb* cur_cb_info) { * | | Connection | | * --------------Box_Y[x][y-1]-------------- */ -void dump_verilog_routing_connection_box_subckt(FILE* fp, t_cb* cur_cb_info, +void dump_verilog_routing_connection_box_subckt(char* subckt_dir, t_cb* cur_cb_info, int LL_num_rr_nodes, t_rr_node* LL_rr_node, t_ivec*** LL_rr_node_indices) { int itrack, inode, side, x, y; int side_cnt = 0; - + FILE* fp = NULL; + char* fname = NULL; int cur_num_sram, num_conf_bits, num_reserved_conf_bits, esti_sram_cnt; - - /* Check the file handler*/ - if (NULL == fp) { - vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", - __FILE__, __LINE__); - exit(1); - } + /* Check */ assert((!(0 > cur_cb_info->x))&&(!(cur_cb_info->x > (nx + 1)))); assert((!(0 > cur_cb_info->y))&&(!(cur_cb_info->y > (ny + 1)))); @@ -1665,12 +1672,16 @@ void dump_verilog_routing_connection_box_subckt(FILE* fp, t_cb* cur_cb_info, /* Identify the type of connection box */ switch(cur_cb_info->type) { case CHANX: + /* Create file handler */ + fp = verilog_create_one_subckt_file(subckt_dir, "Connection Block - X direction ", cbx_verilog_file_name_prefix, cur_cb_info->x, cur_cb_info->y, &fname); /* Comment lines */ fprintf(fp, "//----- Verilog Module of Connection Box -X direction [%d][%d] -----\n", x, y); fprintf(fp, "module "); fprintf(fp, "cbx_%d__%d_ ", cur_cb_info->x, cur_cb_info->y); break; case CHANY: + /* Create file handler */ + fp = verilog_create_one_subckt_file(subckt_dir, "Connection Block - Y direction ", cby_verilog_file_name_prefix, cur_cb_info->x, cur_cb_info->y, &fname); /* Comment lines */ fprintf(fp, "//----- Verilog Module of Connection Box -Y direction [%d][%d] -----\n", x, y); fprintf(fp, "module "); @@ -1804,12 +1815,18 @@ void dump_verilog_routing_connection_box_subckt(FILE* fp, t_cb* cur_cb_info, /* Check */ assert(esti_sram_cnt == get_sram_orgz_info_num_mem_bit(sram_verilog_orgz_info)); + /* Close file handler */ + fclose(fp); + + /* Add fname to the linked list */ + routing_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(routing_verilog_subckt_file_path_head, fname); + /* Free */ + my_free(fname); return; } - /* Top Function*/ /* Build the routing resource SPICE sub-circuits*/ void dump_verilog_routing_resources(char* subckt_dir, @@ -1817,19 +1834,9 @@ void dump_verilog_routing_resources(char* subckt_dir, t_det_routing_arch* routing_arch, int LL_num_rr_nodes, t_rr_node* LL_rr_node, t_ivec*** LL_rr_node_indices) { - FILE* fp = NULL; - char* verilog_name = my_strcat(subckt_dir, routing_verilog_file_name); int ix, iy; assert(UNI_DIRECTIONAL == routing_arch->directionality); - - /* Create FILE */ - fp = fopen(verilog_name, "w"); - if (NULL == fp) { - vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create verilog netlist %s",__FILE__, __LINE__, routing_verilog_file_name); - exit(1); - } - dump_verilog_file_header(fp,"Routing Resources"); /* Two major tasks: * 1. Generate sub-circuits for Routing Channels @@ -1853,7 +1860,7 @@ void dump_verilog_routing_resources(char* subckt_dir, vpr_printf(TIO_MESSAGE_INFO, "Writing X-direction Channels...\n"); for (iy = 0; iy < (ny + 1); iy++) { for (ix = 1; ix < (nx + 1); ix++) { - dump_verilog_routing_chan_subckt(fp, ix, iy, CHANX, + dump_verilog_routing_chan_subckt(subckt_dir, ix, iy, CHANX, LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices, arch.num_segments, arch.Segments); } @@ -1862,7 +1869,7 @@ void dump_verilog_routing_resources(char* subckt_dir, vpr_printf(TIO_MESSAGE_INFO, "Writing Y-direction Channels...\n"); for (ix = 0; ix < (nx + 1); ix++) { for (iy = 1; iy < (ny + 1); iy++) { - dump_verilog_routing_chan_subckt(fp, ix, iy, CHANY, + dump_verilog_routing_chan_subckt(subckt_dir, ix, iy, CHANY, LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices, arch.num_segments, arch.Segments); } @@ -1873,7 +1880,7 @@ void dump_verilog_routing_resources(char* subckt_dir, for (iy = 0; iy < (ny + 1); iy++) { /* vpr_printf(TIO_MESSAGE_INFO, "Writing Switch Boxes[%d][%d]...\n", ix, iy); */ update_spice_models_routing_index_low(ix, iy, SOURCE, arch.spice->num_spice_model, arch.spice->spice_models); - dump_verilog_routing_switch_box_subckt(fp, &(sb_info[ix][iy]), + dump_verilog_routing_switch_box_subckt(subckt_dir, &(sb_info[ix][iy]), LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices); update_spice_models_routing_index_high(ix, iy, SOURCE, arch.spice->num_spice_model, arch.spice->spice_models); } @@ -1887,7 +1894,7 @@ void dump_verilog_routing_resources(char* subckt_dir, update_spice_models_routing_index_low(ix, iy, CHANX, arch.spice->num_spice_model, arch.spice->spice_models); if ((TRUE == is_cb_exist(CHANX, ix, iy)) &&(0 < count_cb_info_num_ipin_rr_nodes(cbx_info[ix][iy]))) { - dump_verilog_routing_connection_box_subckt(fp, &(cbx_info[ix][iy]), + dump_verilog_routing_connection_box_subckt(subckt_dir, &(cbx_info[ix][iy]), LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices); } update_spice_models_routing_index_high(ix, iy, CHANX, arch.spice->num_spice_model, arch.spice->spice_models); @@ -1900,15 +1907,18 @@ void dump_verilog_routing_resources(char* subckt_dir, update_spice_models_routing_index_low(ix, iy, CHANY, arch.spice->num_spice_model, arch.spice->spice_models); if ((TRUE == is_cb_exist(CHANY, ix, iy)) &&(0 < count_cb_info_num_ipin_rr_nodes(cby_info[ix][iy]))) { - dump_verilog_routing_connection_box_subckt(fp, &(cby_info[ix][iy]), + dump_verilog_routing_connection_box_subckt(subckt_dir, &(cby_info[ix][iy]), LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices); } update_spice_models_routing_index_high(ix, iy, CHANY, arch.spice->num_spice_model, arch.spice->spice_models); } } - - /* Close the file*/ - fclose(fp); + + /* Output a header file for all the routing blocks */ + vpr_printf(TIO_MESSAGE_INFO,"Generating header file for routing submodules...\n"); + dump_verilog_subckt_header_file(routing_verilog_subckt_file_path_head, + subckt_dir, + routing_verilog_file_name); return; } diff --git a/vpr7_rram/vpr/SRC/syn_verilog/verilog_top_netlist.c b/vpr7_rram/vpr/SRC/syn_verilog/verilog_top_netlist.c index 5f0d732d8..5e9b30280 100644 --- a/vpr7_rram/vpr/SRC/syn_verilog/verilog_top_netlist.c +++ b/vpr7_rram/vpr/SRC/syn_verilog/verilog_top_netlist.c @@ -2759,6 +2759,115 @@ void dump_verilog_top_netlist(char* circuit_name, return; } +/***** Print Top-level SPICE netlist *****/ +void dump_verilog_top_netlist_tile_orgz(char* circuit_name, + char* top_netlist_name, + char* include_dir_path, + char* subckt_dir_path, + int LL_num_rr_nodes, + t_rr_node* LL_rr_node, + t_ivec*** LL_rr_node_indices, + int num_clock, + t_spice verilog) { + FILE* fp = NULL; + char* formatted_subckt_dir_path = format_dir_path(subckt_dir_path); + char* temp_include_file_path = NULL; + char* title = my_strcat("FPGA Verilog Netlist for Design: ", circuit_name); + + /* Check if the path exists*/ + fp = fopen(top_netlist_name,"w"); + if (NULL == fp) { + vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create top Verilog netlist %s!",__FILE__, __LINE__, top_netlist_name); + exit(1); + } + + vpr_printf(TIO_MESSAGE_INFO, "Writing FPGA Top-level Verilog Netlist for %s...\n", circuit_name); + + /* Print the title */ + dump_verilog_file_header(fp, title); + my_free(title); + + /* Include user-defined sub-circuit netlist */ + fprintf(fp, "//----- Include User-defined netlists -----\n"); + init_include_user_defined_verilog_netlists(verilog); + dump_include_user_defined_verilog_netlists(fp, verilog); + + /* Special subckts for Top-level SPICE netlist */ + fprintf(fp, "//----- Include subckt netlists: Multiplexers -----\n"); + temp_include_file_path = my_strcat(formatted_subckt_dir_path, muxes_verilog_file_name); + fprintf(fp, "// `include \"%s\"\n", temp_include_file_path); + my_free(temp_include_file_path); + + fprintf(fp, "//----- Include subckt netlists: Wires -----\n"); + temp_include_file_path = my_strcat(formatted_subckt_dir_path, wires_verilog_file_name); + fprintf(fp, "// `include \"%s\"\n", temp_include_file_path); + my_free(temp_include_file_path); + + fprintf(fp, "//----- Include subckt netlists: Look-Up Tables (LUTs) -----\n"); + temp_include_file_path = my_strcat(formatted_subckt_dir_path, luts_verilog_file_name); + fprintf(fp, "// `include \"%s\"\n", temp_include_file_path); + my_free(temp_include_file_path); + + fprintf(fp, "//------ Include subckt netlists: Logic Blocks -----\n"); + temp_include_file_path = my_strcat(formatted_subckt_dir_path, logic_block_verilog_file_name); + fprintf(fp, "// `include \"%s\"\n", temp_include_file_path); + my_free(temp_include_file_path); + + fprintf(fp, "//----- Include subckt netlists: Routing structures (Switch Boxes, Channels, Connection Boxes) -----\n"); + temp_include_file_path = my_strcat(formatted_subckt_dir_path, routing_verilog_file_name); + fprintf(fp, "// `include \"%s\"\n", temp_include_file_path); + my_free(temp_include_file_path); + + /* Include decoders if required */ + switch(sram_verilog_orgz_type) { + case SPICE_SRAM_STANDALONE: + case SPICE_SRAM_SCAN_CHAIN: + break; + case SPICE_SRAM_MEMORY_BANK: + /* Include verilog decoder */ + fprintf(fp, "//----- Include subckt netlists: Decoders (controller for memeory bank) -----\n"); + temp_include_file_path = my_strcat(formatted_subckt_dir_path, decoders_verilog_file_name); + fprintf(fp, "// `include \"%s\"\n", temp_include_file_path); + my_free(temp_include_file_path); + break; + default: + vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization in Verilog Generator!\n", + __FILE__, __LINE__); + exit(1); + } + + /* Print all global wires*/ + dump_verilog_top_netlist_ports(fp, num_clock, circuit_name, verilog); + + dump_verilog_top_netlist_internal_wires(fp); + + /* Quote defined Logic blocks subckts (Grids) */ + dump_verilog_defined_grids(fp); + + /* Quote Routing structures: Channels */ + dump_verilog_defined_channels(fp, LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices); + + /* Quote Routing structures: Conneciton Boxes */ + dump_verilog_defined_connection_boxes(fp); + + /* Quote Routing structures: Switch Boxes */ + dump_verilog_defined_switch_boxes(fp); + + /* Apply CLB to CLB direct connections */ + dump_verilog_clb2clb_directs(fp, num_clb2clb_directs, clb2clb_direct); + + /* Dump configuration circuits */ + dump_verilog_configuration_circuits(fp); + + /* verilog ends*/ + fprintf(fp, "endmodule\n"); + + /* Close the file*/ + fclose(fp); + + return; +} + /** Top level function 2: Testbench for the top-level netlist * This testbench includes a top-level module of a mapped FPGA and voltage pulses */ diff --git a/vpr7_rram/vpr/SRC/syn_verilog/verilog_top_netlist.h b/vpr7_rram/vpr/SRC/syn_verilog/verilog_top_netlist.h index 72829d050..0d26840fc 100644 --- a/vpr7_rram/vpr/SRC/syn_verilog/verilog_top_netlist.h +++ b/vpr7_rram/vpr/SRC/syn_verilog/verilog_top_netlist.h @@ -9,6 +9,16 @@ void dump_verilog_top_netlist(char* circuit_name, int num_clock, t_spice spice); +void dump_verilog_top_netlist_tile_orgz(char* circuit_name, + char* top_netlist_name, + char* include_dir_path, + char* subckt_dir_path, + int LL_num_rr_nodes, + t_rr_node* LL_rr_node, + t_ivec*** LL_rr_node_indices, + int num_clock, + t_spice verilog); + void dump_verilog_top_testbench(char* circuit_name, char* top_netlist_name, int num_clock, diff --git a/vpr7_rram/vpr/SRC/syn_verilog/verilog_utils.c b/vpr7_rram/vpr/SRC/syn_verilog/verilog_utils.c index d14688efc..5d33d7bd7 100644 --- a/vpr7_rram/vpr/SRC/syn_verilog/verilog_utils.c +++ b/vpr7_rram/vpr/SRC/syn_verilog/verilog_utils.c @@ -161,6 +161,85 @@ void dump_verilog_file_header(FILE* fp, return; } +/* Create a file handler for a subckt Verilog netlist */ +FILE* verilog_create_one_subckt_file(char* subckt_dir, + char* subckt_name_prefix, + char* verilog_subckt_file_name_prefix, + int grid_x, int grid_y, + char** verilog_fname) { + FILE* fp = NULL; + char* file_description = NULL; + + (*verilog_fname) = my_strcat(subckt_dir, + fpga_spice_create_one_subckt_filename(verilog_subckt_file_name_prefix, grid_x, grid_y, verilog_netlist_file_postfix)); + + /* Create a file*/ + fp = fopen((*verilog_fname), "w"); + + if (NULL == fp) { + vpr_printf(TIO_MESSAGE_ERROR, + "(FILE:%s,LINE[%d])Failure in create Verilog netlist %s", + __FILE__, __LINE__, (*verilog_fname)); + exit(1); + } + + /* Generate the descriptions*/ + file_description = (char*) my_malloc(sizeof(char) * (strlen(subckt_name_prefix) + 2 + + strlen(my_itoa(grid_x)) + 2 + strlen(my_itoa(grid_y)) + + 9)); + sprintf(file_description, "%s [%d][%d] in FPGA", + subckt_name_prefix, grid_x, grid_y); + dump_verilog_file_header(fp, file_description); + + /* Free */ + my_free(file_description); + + return fp; +} + +/* Output all the created subckt file names in a header file, + * that can be easily imported in a top-level netlist + */ +void dump_verilog_subckt_header_file(t_llist* subckt_llist_head, + char* subckt_dir, + char* header_file_name) { + FILE* fp = NULL; + char* verilog_fname = NULL; + t_llist* temp = NULL; + + verilog_fname = my_strcat(subckt_dir, + header_file_name); + + /* Create a file*/ + fp = fopen(verilog_fname, "w"); + + if (NULL == fp) { + vpr_printf(TIO_MESSAGE_ERROR, + "(FILE:%s,LINE[%d])Failure in create Verilog netlist %s", + __FILE__, __LINE__, verilog_fname); + exit(1); + } + + /* Generate the descriptions*/ + dump_verilog_file_header(fp, "Header file"); + + /* Output file names */ + temp = subckt_llist_head; + while (temp) { + fprintf(fp, "`include \"%s\"\n", + (char*)(temp->dptr)); + temp = temp->next; + } + + /* Close fp */ + fclose(fp); + + /* Free */ + my_free(verilog_fname); + + return; +} + /* Determine the split sign for generic port */ char determine_verilog_generic_port_split_sign(enum e_dump_verilog_port_type dump_port_type) { char ret; diff --git a/vpr7_rram/vpr/SRC/syn_verilog/verilog_utils.h b/vpr7_rram/vpr/SRC/syn_verilog/verilog_utils.h index d3af25e8f..e6c59f5ba 100644 --- a/vpr7_rram/vpr/SRC/syn_verilog/verilog_utils.h +++ b/vpr7_rram/vpr/SRC/syn_verilog/verilog_utils.h @@ -10,6 +10,16 @@ void dump_include_user_defined_verilog_netlists(FILE* fp, void dump_verilog_file_header(FILE* fp, char* usage); +FILE* verilog_create_one_subckt_file(char* subckt_dir, + char* subckt_name_prefix, + char* verilog_subckt_file_name_prefix, + int grid_x, int grid_y, + char** verilog_fname); + +void dump_verilog_subckt_header_file(t_llist* subckt_llist_head, + char* subckt_dir, + char* header_file_name); + char determine_verilog_generic_port_split_sign(enum e_dump_verilog_port_type dump_port_type); void dump_verilog_generic_port(FILE* fp,