Update documentation
Merge branch 'heterogeneous' of https://github.com/LNIS-Projects/OpenFPGA into heterogeneous
This commit is contained in:
commit
9e99048815
|
@ -18,7 +18,6 @@ FPGA-Bitstream is the part of the flow in charge of the functional verification
|
|||
|
||||
How to compile
|
||||
==============
|
||||
Running the Makefile in the root of the released package can compile all the source codes.
|
||||
Guides can be found in the *compilation* directory in the main folder. We tested it for MacOS High Sierra 10.13.4, Ubuntu 18.04 and Red Hat 7.5. This list is not exhaustive as other distributions could work as well.
|
||||
|
||||
As a general rule, the compilation follows these steps:
|
||||
|
@ -31,21 +30,24 @@ If you need the full flow:
|
|||
|
||||
2) Go into the folder you just cloned and make the different submodules through a global Makefile:
|
||||
cd OpenFPGA
|
||||
make
|
||||
OR
|
||||
make -j
|
||||
(if you have multiple cores, this will make the compilation way faster.)
|
||||
mkdir build (*if folder doesn't already exist*)
|
||||
cd build
|
||||
cmake ..
|
||||
make OR make -j (*if you have multiple cores, this will make the compilation way faster*)
|
||||
|
||||
If you only need vpr:
|
||||
cd OpenFPGA/vpr7_x2p
|
||||
make/make -j
|
||||
cd OpenFPGA
|
||||
mkdir build (if folder doesn't already exist)
|
||||
cd build
|
||||
cmake ..
|
||||
make vpr/make vpr -j
|
||||
|
||||
3) Architectures, circuits and already written scripts exist to allow you to test the flow without having to provide any new information to the system. For this:
|
||||
cd vpr7_x2p (if not done already)
|
||||
cd vpr7_x2p
|
||||
cd vpr
|
||||
source ./go.sh
|
||||
source ./go_fpga_verilog/spice.sh
|
||||
|
||||
go.sh is a script linking to a testing architecture and a simple circuit. The output will be in the folders spice_demo and verilog_demo.
|
||||
They are scripts linking to a testing architecture and a simple circuit.
|
||||
|
||||
4) If you only need to see the new options implemented in vpr, do:
|
||||
./vpr
|
||||
|
|
|
@ -8,11 +8,12 @@ FPGA-Verilog Supported Options::
|
|||
--fpga_verilog
|
||||
--fpga_verilog_dir <directory_path_of_dumped_verilog_files>
|
||||
--fpga_verilog_include_timing
|
||||
--fpga_verilog_init_sim
|
||||
--fpga_verilog_print_modelsim_autodeck
|
||||
--fpga_verilog_modelsim_ini_path <string>
|
||||
--fpga_verilog_include_signal_init
|
||||
--fpga_verilog_print_modelsim_autodeck <modelsim_ini_path>
|
||||
--fpga_verilog_print_top_testbench
|
||||
--fpga_verilog_print_top_auto_testbench <path_to_the_verilog_benchmark>
|
||||
--fpga_verilog_print_autocheck_top_testbench <reference_verilog_file_path>
|
||||
--fpga_verilog_print_formal_verification_top_netlist
|
||||
--fpga_verilog_include_icarus_simulator
|
||||
|
||||
|
||||
.. csv-table:: Commmand-line Options of FPGA-Verilog
|
||||
|
@ -20,6 +21,7 @@ FPGA-Verilog Supported Options::
|
|||
:widths: 15, 30
|
||||
|
||||
"--fpga_verilog", "Turn on the FPGA-Verilog."
|
||||
<<<<<<< HEAD
|
||||
"--fpga_verilog_dir <dir_path>", "Specify the directory that all the Verilog files will be outputted to <dir_path> is the destination directory."
|
||||
"--fpga_verilog_include_timing", "Includes the timings found in the XML file."
|
||||
"--fpga_verilog_init_sim", "Initializes the simulation for ModelSim."
|
||||
|
@ -28,6 +30,17 @@ FPGA-Verilog Supported Options::
|
|||
"--fpga_verilog_print_top_testbench", "Print the full-chip-level testbench for the FPGA. Determines the type of autodeck."
|
||||
"--fpga_verilog_print_top_auto_testbench \
|
||||
<path_to_the_verilog_benchmark>", "Prints the testbench associated with the given benchmark. Determines the type of autodeck."
|
||||
=======
|
||||
"--fpga_verilog_dir <dir_path>", "Specify the directory where all the Verilog files will be outputted to. <dir_path> is the destination directory."
|
||||
"--fpga_verilog_include_timing", "Includes the timings found in the XML architecture description file."
|
||||
"--fpga_verilog_include_signal_init", "Set all nets to random value to be close of a real power-on case"
|
||||
"--fpga_verilog_print_modelsim_autodeck <modelsim_ini_path>", "Generates the scripts necessary to the ModelSim simulation and specify the path to modelsim.ini file."
|
||||
"--fpga_verilog_print_top_testbench", "Prints the full-chip-level testbench for the FPGA, which includes programming phase and operationg phase (random patterns)."
|
||||
"--fpga_verilog_print_autocheck_top_testbench \
|
||||
<reference_verilog_file_path>", "Prints a testbench stimulating the generated FPGA and the initial benchmark to compare stimuli responses, which includes programming phase and operationg phase (random patterns)"
|
||||
"--fpga_verilog_print_formal_verification_top_netlist", "Prints a Verilog top file compliant with formal verification tools. With this top file the FPGA is initialy programmed. It also prints a testbench with random patterns, which can be manually or automatically check regarding previous options."
|
||||
"--fpga_verilog_include_icarus_simulator", "Activates waveforms .vcd file generation and simulation timeout, which are required for Icarus Verilog simulator"
|
||||
>>>>>>> f56adc681567b73c7826228641e089482dffc009
|
||||
|
||||
.. note:: The selected directory will contain the *Verilog top file* and three other folders. The folders are:
|
||||
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
Hierarchy of Verilog Output Files
|
||||
============================
|
||||
|
||||
All the generated Verilog Netlists are located in the <verilog_dir> as you specify in the command-line options. Under the <verilog_dir>, FPGA-Verilog creates the top file name_top.v and some folders: lb (logic blocks), routing and sub_modules.
|
||||
All the generated Verilog Netlists are located in the <verilog_dir>/SRC as you specify in the command-line options. Under the <verilog_dir>/SRC, FPGA-Verilog creates the top file name_top.v and some folders: lb (logic blocks), routing and sub_modules.
|
||||
|
||||
.. csv-table:: Folder hierarchy of FPGA-Verilog
|
||||
:header: "Folder", "Content"
|
||||
:header: "File/Folder", "Content"
|
||||
:widths: 10, 20
|
||||
|
||||
"name_top.v", "Contains the top module and calls all the other .v files"
|
||||
"name.bitstream", "Only if --fpga_verilog_print_top_testbench or --fpga_verilog_print_top_auto_testbench is chosen. Contains the bitstream programming the generated FPGA."
|
||||
"name_top_tb.v", "Only if --fpga_verilog_print_top_testbench or --fpga_verilog_print_top_auto_testbench is chosen. Contains the testbench used for the simulation."
|
||||
"name_top_tb.v", "Only if --fpga_verilog_print_top_testbench. Contains a testbench used for the simulation."
|
||||
"name_autocheck_top_tb.v", "Only if --fpga_verilog_print_autocheck_top_testbench is chosen. Contains a testbench used for the simulation."
|
||||
"name_formal_random_top_tb.v", "Only if --fpga_verilog_print_formal_verification_top_netlist is chosen. Contains a testbench used for the simulation."
|
||||
"name_top_formal_verification.v", "Only if --fpga_verilog_print_formal_verification_top_netlist is chosen. Contains a top fil used for formal verification and by name_formal_random_top_tb.v."
|
||||
"fpga_defines.v", "Contains all the defines set as 'include_timing'"
|
||||
"name_include_netlists.v", "Contains all the netlists and defines paths used for the simulation."
|
||||
"lb", "Logic Block. Contains all the CLBs. The logic_block.v includes all the CLB and is called by the top module afterward."
|
||||
"routing", "Contains all the routing in the circuit. You can find in it the Switch Boxes, the Connection Blocks and the routing needed to connect the different blocks. The routing.v file packs them all and is called by the top module."
|
||||
"sub_modules", "Contains the modules generated by the flow to build the CLBs."
|
||||
|
|
|
@ -20,6 +20,7 @@ my $mydate = gmctime();
|
|||
my $cwd = getcwd();
|
||||
|
||||
# Global Variants
|
||||
my ($max_route_width_retry) = (1000);
|
||||
# input Option Hash
|
||||
my %opt_h;
|
||||
my $opt_ptr = \%opt_h;
|
||||
|
@ -112,7 +113,7 @@ sub generate_path($)
|
|||
mkpath "$mypath";
|
||||
print "Path($mypath) does not exist...Create it.\n";
|
||||
}
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Print the usage
|
||||
|
@ -127,6 +128,7 @@ sub print_usage()
|
|||
print " -N <int> : N-LUT/Matrix\n";
|
||||
print " Other Options:\n";
|
||||
print " [ General ] \n";
|
||||
print " \t-matlab_rpt <data_name> : .m file consists of data compatible to matlab scripts. Specify the data name to be appeared in the script\n";
|
||||
print " \t-I <int> : Number of inputs of a CLB, mandatory when mpack1 flow is chosen\n";
|
||||
print " \t-K <int> : K-LUT, mandatory when standard flow is chosen\n";
|
||||
print " \t-M <int> : M-Matrix, mandatory when mpack1 flow is chosen\n";
|
||||
|
@ -269,7 +271,7 @@ sub read_opt_into_hash($ $ $)
|
|||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Read options
|
||||
|
@ -307,6 +309,7 @@ sub opts_read()
|
|||
&read_opt_into_hash("conf","on","on");
|
||||
&read_opt_into_hash("benchmark","on","on");
|
||||
&read_opt_into_hash("rpt","on","on");
|
||||
&read_opt_into_hash("matlab_rpt","on","off"); # Add an option to output report file compatible to matlab scripts
|
||||
&read_opt_into_hash("N","on","on");
|
||||
&read_opt_into_hash("K","on","off");
|
||||
&read_opt_into_hash("I","on","off");
|
||||
|
@ -374,7 +377,7 @@ sub opts_read()
|
|||
|
||||
&print_opts();
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
# List the options
|
||||
|
@ -385,7 +388,7 @@ sub print_opts()
|
|||
while(my ($key,$value) = each(%opt_h))
|
||||
{print "$key : $value\n";}
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -433,7 +436,7 @@ sub check_keywords_conf()
|
|||
{die "Error: Keyword($mctgy[$imcg],$sctgy[$imcg]->[$iscg]) is missing!\n";}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Read the configuration file
|
||||
|
@ -471,7 +474,7 @@ sub read_conf()
|
|||
print "Checking these keywords...";
|
||||
print "Successfully\n";
|
||||
close(CONF);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub read_benchmarks()
|
||||
|
@ -503,7 +506,7 @@ sub read_benchmarks()
|
|||
foreach my $temp(@benchmark_names)
|
||||
{print "$temp\n";}
|
||||
close(FCONF);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Input program path is like "~/program_dir/program_name"
|
||||
|
@ -1298,7 +1301,6 @@ sub run_std_vpr($ $ $ $ $ $ $ $ $)
|
|||
{
|
||||
my ($blif,$bm,$arch,$net,$place,$route,$fix_chan_width,$log,$act_file) = @_;
|
||||
my ($vpr_dir,$vpr_name) = &split_prog_path($conf_ptr->{dir_path}->{vpr_path}->{val});
|
||||
chdir $vpr_dir;
|
||||
|
||||
my ($power_opts);
|
||||
if ("on" eq $opt_ptr->{power}) {
|
||||
|
@ -1435,6 +1437,10 @@ sub run_std_vpr($ $ $ $ $ $ $ $ $)
|
|||
if ("on" eq $opt_ptr->{vpr_max_router_iteration}) {
|
||||
$other_opt .= "--max_router_iterations $opt_ptr->{vpr_max_router_iteration_val} ";
|
||||
}
|
||||
|
||||
chdir $vpr_dir;
|
||||
print "Entering $vpr_dir\n";
|
||||
|
||||
print "./$vpr_name $arch $blif --net_file $net --place_file $place --route_file $route --full_stats --nodisp $power_opts $packer_opts $chan_width_opt $vpr_spice_opts $other_opt > $log\n";
|
||||
system("./$vpr_name $arch $blif --net_file $net --place_file $place --route_file $route --full_stats --nodisp $power_opts $packer_opts $chan_width_opt $vpr_spice_opts $other_opt > $log");
|
||||
|
||||
|
@ -1463,7 +1469,6 @@ sub run_vpr_route($ $ $ $ $ $ $ $ $)
|
|||
{
|
||||
my ($blif,$bm,$arch,$net,$place,$route,$fix_chan_width,$log,$act_file) = @_;
|
||||
my ($vpr_dir,$vpr_name) = &split_prog_path($conf_ptr->{dir_path}->{vpr_path}->{val});
|
||||
chdir $vpr_dir;
|
||||
|
||||
my ($power_opts);
|
||||
if ("on" eq $opt_ptr->{power}) {
|
||||
|
@ -1517,7 +1522,12 @@ sub run_vpr_route($ $ $ $ $ $ $ $ $)
|
|||
$other_opt .= "--router_algorithm breadth_first ";
|
||||
}
|
||||
|
||||
chdir $vpr_dir;
|
||||
print "Entering $vpr_dir\n";
|
||||
|
||||
print "./$vpr_name $arch $blif --route --blif_file $blif --net_file $net --place_file $place --route_file $route --full_stats --nodisp $power_opts $chan_width_opt $vpr_spice_opts $other_opt > $log\n";
|
||||
system("./$vpr_name $arch $blif --route --blif_file $blif --net_file $net --place_file $place --route_file $route --full_stats --nodisp $power_opts $chan_width_opt $vpr_spice_opts $other_opt > $log");
|
||||
print "\n";
|
||||
|
||||
chdir $cwd;
|
||||
}
|
||||
|
@ -1754,6 +1764,9 @@ sub run_vpr_in_flow($ $ $ $ $ $ $ $ $ $ $ $) {
|
|||
if (-e $vpr_route) {
|
||||
print "INFO: try route_chan_width($min_chan_width) success!\n";
|
||||
last; #Jump out
|
||||
} elsif ($max_route_width_retry < $min_chan_width) {
|
||||
# I set a threshold of 1000 as it is the limit of VPR
|
||||
die "ERROR: Route Fail for $abc_blif_out with a min_chan_width of $min_chan_width!\n";
|
||||
} else {
|
||||
print "INFO: try route_chan_width($min_chan_width) failed! Retry with +2...\n";
|
||||
$min_chan_width += 2;
|
||||
|
@ -1777,6 +1790,9 @@ sub run_vpr_in_flow($ $ $ $ $ $ $ $ $ $ $ $) {
|
|||
if (-e $vpr_route) {
|
||||
print "INFO: try route_chan_width($fix_chan_width) success!\n";
|
||||
last; #Jump out
|
||||
} elsif ($max_route_width_retry < $fix_chan_width) {
|
||||
# I set a threshold of 1000 as it is the limit of VPR
|
||||
die "ERROR: Route Fail for $abc_blif_out with a min_chan_width of $fix_chan_width!\n";
|
||||
} else {
|
||||
print "INFO: try route_chan_width($fix_chan_width) failed! Retry with +2...\n";
|
||||
$fix_chan_width += 2;
|
||||
|
@ -2978,6 +2994,14 @@ sub gen_csv_rpt_vtr_flow($ $)
|
|||
my @keywords;
|
||||
my ($K_val,$N_val) = ($opt_ptr->{K_val},$opt_ptr->{N_val});
|
||||
|
||||
# adapt to matlab format if the option is enabled
|
||||
if ("on" eq $opt_ptr->{matlab_rpt}) {
|
||||
# Print the data name
|
||||
print $CSVFH "$opt_ptr->{matlab_rpt_val} = [\n";
|
||||
# We will set the stats line to be commented
|
||||
print $CSVFH "%";
|
||||
}
|
||||
|
||||
# Print out Standard Stats First
|
||||
print $CSVFH "$tag";
|
||||
print $CSVFH ",LUTs";
|
||||
|
@ -3006,7 +3030,14 @@ sub gen_csv_rpt_vtr_flow($ $)
|
|||
# Check log/stats one by one
|
||||
foreach $tmp(@benchmark_names) {
|
||||
$tmp =~ s/\.v$//g;
|
||||
print $CSVFH "$tmp";
|
||||
|
||||
# For matlab script, we use {} for string
|
||||
if ("on" eq $opt_ptr->{matlab_rpt}) {
|
||||
print $CSVFH "{'$tmp'}";
|
||||
} else {
|
||||
print $CSVFH "$tmp";
|
||||
}
|
||||
|
||||
print $CSVFH ",$rpt_h{$tag}->{$tmp}->{$N_val}->{$K_val}->{LUTs}";
|
||||
if ("on" eq $opt_ptr->{min_route_chan_width}) {
|
||||
print $CSVFH ",$rpt_h{$tag}->{$tmp}->{$N_val}->{$K_val}->{min_route_chan_width}";
|
||||
|
@ -3034,7 +3065,17 @@ sub gen_csv_rpt_vtr_flow($ $)
|
|||
print $CSVFH ",$rpt_ptr->{$tag}->{$tmp}->{$N_val}->{$K_val}->{power}->{dynamic}";
|
||||
print $CSVFH ",$rpt_ptr->{$tag}->{$tmp}->{$N_val}->{$K_val}->{power}->{leakage}";
|
||||
}
|
||||
print $CSVFH "\n";
|
||||
# For matlab script, we end with a semicolumn to be compatiable to matlab
|
||||
if ("on" eq $opt_ptr->{matlab_rpt}) {
|
||||
print $CSVFH ";\n";
|
||||
} else {
|
||||
print $CSVFH "\n";
|
||||
}
|
||||
}
|
||||
|
||||
# For matlab script, we end with ];
|
||||
if ("on" eq $opt_ptr->{matlab_rpt}) {
|
||||
print $CSVFH "];\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3044,6 +3085,14 @@ sub gen_csv_rpt_yosys_vpr_flow($ $)
|
|||
my ($tmp,$ikw,$tmpkw);
|
||||
my @keywords;
|
||||
my ($K_val,$N_val) = ($opt_ptr->{K_val},$opt_ptr->{N_val});
|
||||
|
||||
# adapt to matlab format if the option is enabled
|
||||
if ("on" eq $opt_ptr->{matlab_rpt}) {
|
||||
# Print the data name
|
||||
print $CSVFH "$opt_ptr->{matlab_rpt_val} = [\n";
|
||||
# We will set the stats line to be commented
|
||||
print $CSVFH "%";
|
||||
}
|
||||
|
||||
# Print out Standard Stats First
|
||||
print $CSVFH "$tag";
|
||||
|
@ -3074,7 +3123,14 @@ sub gen_csv_rpt_yosys_vpr_flow($ $)
|
|||
foreach $tmp(@benchmark_names) {
|
||||
my @tokens = split('/', $tmp);
|
||||
$tmp = $tokens[0];
|
||||
print $CSVFH "$tmp";
|
||||
|
||||
# For matlab script, we use {} for string
|
||||
if ("on" eq $opt_ptr->{matlab_rpt}) {
|
||||
print $CSVFH "{'$tmp'}";
|
||||
} else {
|
||||
print $CSVFH "$tmp";
|
||||
}
|
||||
|
||||
print $CSVFH ",$rpt_h{$tag}->{$tmp}->{$N_val}->{$K_val}->{LUTs}";
|
||||
if ("on" eq $opt_ptr->{min_route_chan_width}) {
|
||||
print $CSVFH ",$rpt_h{$tag}->{$tmp}->{$N_val}->{$K_val}->{min_route_chan_width}";
|
||||
|
@ -3102,7 +3158,17 @@ sub gen_csv_rpt_yosys_vpr_flow($ $)
|
|||
print $CSVFH ",$rpt_ptr->{$tag}->{$tmp}->{$N_val}->{$K_val}->{power}->{dynamic}";
|
||||
print $CSVFH ",$rpt_ptr->{$tag}->{$tmp}->{$N_val}->{$K_val}->{power}->{leakage}";
|
||||
}
|
||||
print $CSVFH "\n";
|
||||
# For matlab script, we end with a semicolumn to be compatiable to matlab
|
||||
if ("on" eq $opt_ptr->{matlab_rpt}) {
|
||||
print $CSVFH ";\n";
|
||||
} else {
|
||||
print $CSVFH "\n";
|
||||
}
|
||||
}
|
||||
|
||||
# For matlab script, we end with ];
|
||||
if ("on" eq $opt_ptr->{matlab_rpt}) {
|
||||
print $CSVFH "];\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3112,6 +3178,14 @@ sub gen_csv_rpt_standard_flow($ $)
|
|||
my ($tmp,$ikw,$tmpkw);
|
||||
my @keywords;
|
||||
my ($K_val,$N_val) = ($opt_ptr->{K_val},$opt_ptr->{N_val});
|
||||
|
||||
# adapt to matlab format if the option is enabled
|
||||
if ("on" eq $opt_ptr->{matlab_rpt}) {
|
||||
# Print the data name
|
||||
print $CSVFH "$opt_ptr->{matlab_rpt_val} = [\n";
|
||||
# We will set the stats line to be commented
|
||||
print $CSVFH "%";
|
||||
}
|
||||
|
||||
# Print out Standard Stats First
|
||||
print $CSVFH "$tag";
|
||||
|
@ -3141,7 +3215,13 @@ sub gen_csv_rpt_standard_flow($ $)
|
|||
# Check log/stats one by one
|
||||
foreach $tmp(@benchmark_names) {
|
||||
$tmp =~ s/\.blif$//g;
|
||||
print $CSVFH "$tmp";
|
||||
# For matlab script, we use {} for string
|
||||
if ("on" eq $opt_ptr->{matlab_rpt}) {
|
||||
print $CSVFH "{'$tmp'}";
|
||||
} else {
|
||||
print $CSVFH "$tmp";
|
||||
}
|
||||
|
||||
print $CSVFH ",$rpt_h{$tag}->{$tmp}->{$N_val}->{$K_val}->{LUTs}";
|
||||
if ("on" eq $opt_ptr->{min_route_chan_width}) {
|
||||
print $CSVFH ",$rpt_h{$tag}->{$tmp}->{$N_val}->{$K_val}->{min_route_chan_width}";
|
||||
|
@ -3173,7 +3253,18 @@ sub gen_csv_rpt_standard_flow($ $)
|
|||
print $CSVFH ",$rpt_ptr->{$tag}->{$tmp}->{$N_val}->{$K_val}->{power}->{dynamic}";
|
||||
print $CSVFH ",$rpt_ptr->{$tag}->{$tmp}->{$N_val}->{$K_val}->{power}->{leakage}";
|
||||
}
|
||||
print $CSVFH "\n";
|
||||
|
||||
# For matlab script, we end with a semicolumn to be compatiable to matlab
|
||||
if ("on" eq $opt_ptr->{matlab_rpt}) {
|
||||
print $CSVFH ";\n";
|
||||
} else {
|
||||
print $CSVFH "\n";
|
||||
}
|
||||
}
|
||||
|
||||
# For matlab script, we end with ];
|
||||
if ("on" eq $opt_ptr->{matlab_rpt}) {
|
||||
print $CSVFH "];\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3184,6 +3275,14 @@ sub gen_csv_rpt_mpack2_flow($ $)
|
|||
my @keywords;
|
||||
my ($K_val,$N_val) = ($opt_ptr->{K_val},$opt_ptr->{N_val});
|
||||
|
||||
# adapt to matlab format if the option is enabled
|
||||
if ("on" eq $opt_ptr->{matlab_rpt}) {
|
||||
# Print the data name
|
||||
print $CSVFH "$opt_ptr->{matlab_rpt_val} = [\n";
|
||||
# We will set the stats line to be commented
|
||||
print $CSVFH "%";
|
||||
}
|
||||
|
||||
# Print out Mpack stats Second
|
||||
print $CSVFH "$tag";
|
||||
if ("on" eq $opt_ptr->{min_route_chan_width}) {
|
||||
|
@ -3217,7 +3316,13 @@ sub gen_csv_rpt_mpack2_flow($ $)
|
|||
# Check log/stats one by one
|
||||
foreach $tmp(@benchmark_names) {
|
||||
$tmp =~ s/\.blif$//g;
|
||||
print $CSVFH "$tmp";
|
||||
# For matlab script, we use {} for string
|
||||
if ("on" eq $opt_ptr->{matlab_rpt}) {
|
||||
print $CSVFH "{'$tmp'}";
|
||||
} else {
|
||||
print $CSVFH "$tmp";
|
||||
}
|
||||
|
||||
if ("on" eq $opt_ptr->{min_route_chan_width}) {
|
||||
print $CSVFH ",$rpt_h{$tag}->{$tmp}->{$N_val}->{$K_val}->{min_route_chan_width}";
|
||||
print $CSVFH ",$rpt_h{$tag}->{$tmp}->{$N_val}->{$K_val}->{fix_route_chan_width}";
|
||||
|
@ -3250,7 +3355,17 @@ sub gen_csv_rpt_mpack2_flow($ $)
|
|||
print $CSVFH ",$rpt_ptr->{$tag}->{$tmp}->{$N_val}->{$K_val}->{power}->{dynamic}";
|
||||
print $CSVFH ",$rpt_ptr->{$tag}->{$tmp}->{$N_val}->{$K_val}->{power}->{leakage}";
|
||||
}
|
||||
print $CSVFH "\n";
|
||||
# For matlab script, we end with a semicolumn to be compatiable to matlab
|
||||
if ("on" eq $opt_ptr->{matlab_rpt}) {
|
||||
print $CSVFH ";\n";
|
||||
} else {
|
||||
print $CSVFH "\n";
|
||||
}
|
||||
}
|
||||
|
||||
# For matlab script, we end with ];
|
||||
if ("on" eq $opt_ptr->{matlab_rpt}) {
|
||||
print $CSVFH "];\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3261,6 +3376,14 @@ sub gen_csv_rpt_mpack1_flow($ $)
|
|||
my @keywords;
|
||||
my ($N_val,$M_val) = ($opt_ptr->{N_val},$opt_ptr->{M_val});
|
||||
|
||||
# adapt to matlab format if the option is enabled
|
||||
if ("on" eq $opt_ptr->{matlab_rpt}) {
|
||||
# Print the data name
|
||||
print $CSVFH "$opt_ptr->{matlab_rpt_val} = [\n";
|
||||
# We will set the stats line to be commented
|
||||
print $CSVFH "%";
|
||||
}
|
||||
|
||||
# Print out Mpack stats Second
|
||||
print $CSVFH "$tag";
|
||||
print $CSVFH ",MATRIX";
|
||||
|
@ -3284,7 +3407,13 @@ sub gen_csv_rpt_mpack1_flow($ $)
|
|||
# Check log/stats one by one
|
||||
foreach $tmp(@benchmark_names) {
|
||||
$tmp =~ s/\.blif$//g;
|
||||
print $CSVFH "$tmp";
|
||||
# For matlab script, we use {} for string
|
||||
if ("on" eq $opt_ptr->{matlab_rpt}) {
|
||||
print $CSVFH "{'$tmp'}";
|
||||
} else {
|
||||
print $CSVFH "$tmp";
|
||||
}
|
||||
|
||||
#foreach $tmpkw(@keywords) {
|
||||
print $CSVFH ",$rpt_ptr->{$tag}->{$tmp}->{$N_val}->{$M_val}->{MATRIX}";
|
||||
@keywords = split /\|/,$conf_ptr->{csv_tags}->{mpack_tags}->{val};
|
||||
|
@ -3309,7 +3438,17 @@ sub gen_csv_rpt_mpack1_flow($ $)
|
|||
print $CSVFH ",$rpt_ptr->{$tag}->{$tmp}->{$N_val}->{$M_val}->{power}->{total}";
|
||||
print $CSVFH ",$rpt_ptr->{$tag}->{$tmp}->{$N_val}->{$M_val}->{power}->{dynamic}";
|
||||
print $CSVFH ",$rpt_ptr->{$tag}->{$tmp}->{$N_val}->{$M_val}->{power}->{leakage}";
|
||||
print $CSVFH "\n";
|
||||
# For matlab script, we end with a semicolumn to be compatiable to matlab
|
||||
if ("on" eq $opt_ptr->{matlab_rpt}) {
|
||||
print $CSVFH ";\n";
|
||||
} else {
|
||||
print $CSVFH "\n";
|
||||
}
|
||||
}
|
||||
|
||||
# For matlab script, we end with ];
|
||||
if ("on" eq $opt_ptr->{matlab_rpt}) {
|
||||
print $CSVFH "];\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ sub print_usage()
|
|||
print " -add_default_clk\n";
|
||||
print " -initial_blif <input_blif_path>\n";
|
||||
print "\n";
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub opts_read()
|
||||
|
@ -53,7 +53,7 @@ sub opts_read()
|
|||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Print a line of blif netlist
|
||||
|
@ -432,15 +432,15 @@ sub scan_blif()
|
|||
}
|
||||
close($FIN2);
|
||||
close($FOUT);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub main()
|
||||
{
|
||||
&opts_read();
|
||||
&scan_blif();
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
&main();
|
||||
exit(1);
|
||||
exit(0);
|
||||
|
|
|
@ -90,7 +90,7 @@ sub findPath(){
|
|||
} else {
|
||||
$path = "$path"."/"."$folders[$count]";
|
||||
if($folders[$count] eq $folder_top){
|
||||
print "$path\n";
|
||||
#print "$path\n";
|
||||
return $path;
|
||||
}
|
||||
}
|
||||
|
@ -135,4 +135,4 @@ sub main()
|
|||
}
|
||||
|
||||
&main();
|
||||
exit(1);
|
||||
exit(0);
|
||||
|
|
|
@ -931,9 +931,11 @@ struct s_arch {
|
|||
bool tileable; /* Xifan TANG: tileable rr_graph support */
|
||||
t_chan_width_dist Chans;
|
||||
enum e_switch_block_type SBType;
|
||||
enum e_switch_block_type SBSubType;
|
||||
float R_minW_nmos;
|
||||
float R_minW_pmos;
|
||||
int Fs;
|
||||
int SubFs;
|
||||
float C_ipin_cblock;
|
||||
float T_ipin_cblock;
|
||||
/* mrFPGA: Xifan TANG */
|
||||
|
|
|
@ -1,4 +1,39 @@
|
|||
/* The XML parser processes an XML file into a tree data structure composed of *
|
||||
/**********************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 LNIS - The University of Utah
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
***********************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Filename: rr_blocks.cpp
|
||||
* Created by: Xifan Tang
|
||||
* Change history:
|
||||
* +-------------------------------------+
|
||||
* | Date | Author | Notes
|
||||
* +-------------------------------------+
|
||||
* | 2019/07/02 | Xifan Tang | Modified to support passing_track_type for switch blocks
|
||||
* +-------------------------------------+
|
||||
***********************************************************************/
|
||||
/************************************************************************
|
||||
* The XML parser processes an XML file into a tree data structure composed of *
|
||||
* ezxml_t nodes. Each ezxml_t node represents an XML element. For example *
|
||||
* <a> <b/> </a> will generate two ezxml_t nodes. One called "a" and its *
|
||||
* child "b". Each ezxml_t node can contain various XML data such as attribute *
|
||||
|
@ -22,7 +57,7 @@
|
|||
* Because of how the XML tree traversal works, we free everything when we're *
|
||||
* done reading an architecture file to make sure that there isn't some part *
|
||||
* of the architecture file that got missed. *
|
||||
*/
|
||||
***********************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
@ -2142,6 +2177,29 @@ static void ProcessDevice(INOUTP ezxml_t Node, OUTP struct s_arch *arch,
|
|||
|
||||
arch->Fs = GetIntProperty(Cur, "fs", TRUE, 3);
|
||||
|
||||
/* SubType is the switch block type of passing tracks */
|
||||
/* By default, the subType is the same as the main type */
|
||||
Prop = FindProperty(Cur, "sub_type", FALSE);
|
||||
if (NULL != Prop) {
|
||||
if (strcmp(Prop, "wilton") == 0) {
|
||||
arch->SBSubType = WILTON;
|
||||
} else if (strcmp(Prop, "universal") == 0) {
|
||||
arch->SBSubType = UNIVERSAL;
|
||||
} else if (strcmp(Prop, "subset") == 0) {
|
||||
arch->SBSubType = SUBSET;
|
||||
} else {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,
|
||||
"[LINE %d] Unknown property %s for switch block type x\n",
|
||||
Cur->line, Prop);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
ezxml_set_attr(Cur, "sub_type", NULL);
|
||||
|
||||
/* SubFs is Fs for the switch block type of passing tracks */
|
||||
/* By default, the subFs is the same as the main Fs */
|
||||
arch->SubFs = GetIntProperty(Cur, "sub_fs", FALSE, arch->Fs);
|
||||
|
||||
FreeNode(Cur);
|
||||
}
|
||||
|
||||
|
@ -4132,3 +4190,6 @@ void SetupPinEquivalenceAutoDetect(ezxml_t Parent, t_type_descriptor* Type) {
|
|||
return;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* End of file : read_xml_arch_file.c
|
||||
***********************************************************************/
|
||||
|
|
|
@ -536,9 +536,11 @@ static void SetupRoutingArch(INP t_arch Arch,
|
|||
OUTP struct s_det_routing_arch *RoutingArch) {
|
||||
|
||||
RoutingArch->switch_block_type = Arch.SBType;
|
||||
RoutingArch->switch_block_sub_type = Arch.SBSubType;
|
||||
RoutingArch->R_minW_nmos = Arch.R_minW_nmos;
|
||||
RoutingArch->R_minW_pmos = Arch.R_minW_pmos;
|
||||
RoutingArch->Fs = Arch.Fs;
|
||||
RoutingArch->sub_Fs = Arch.SubFs;
|
||||
RoutingArch->directionality = BI_DIRECTIONAL;
|
||||
if (Arch.Segments)
|
||||
RoutingArch->directionality = Arch.Segments[0].directionality;
|
||||
|
|
|
@ -560,8 +560,10 @@ static int binary_search_place_and_route(struct s_placer_opts placer_opts,
|
|||
free_rr_graph();
|
||||
|
||||
build_rr_graph(graph_type, num_types, type_descriptors, nx, ny, grid,
|
||||
chan_width_x[0], NULL, det_routing_arch.switch_block_type,
|
||||
det_routing_arch.Fs, det_routing_arch.num_segment,
|
||||
chan_width_x[0], NULL,
|
||||
det_routing_arch.switch_block_type, det_routing_arch.Fs,
|
||||
det_routing_arch.switch_block_sub_type, det_routing_arch.sub_Fs,
|
||||
det_routing_arch.num_segment,
|
||||
det_routing_arch.num_switch, segment_inf,
|
||||
det_routing_arch.global_route_switch,
|
||||
det_routing_arch.delayless_switch, timing_inf,
|
||||
|
|
|
@ -807,6 +807,8 @@ struct s_det_routing_arch {
|
|||
enum e_directionality directionality; /* UDSD by AY */
|
||||
int Fs;
|
||||
enum e_switch_block_type switch_block_type;
|
||||
int sub_Fs;
|
||||
enum e_switch_block_type switch_block_sub_type;
|
||||
int num_segment;
|
||||
short num_switch;
|
||||
short global_route_switch;
|
||||
|
|
|
@ -506,3 +506,182 @@ void print_rr_graph_stats(const t_rr_graph& rr_graph) {
|
|||
|
||||
return;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Print statistics of a rr_graph
|
||||
* 1. We print number of nodes by types
|
||||
* 2. Print the number of edges
|
||||
************************************************************************/
|
||||
void print_rr_graph_stats() {
|
||||
|
||||
/* Print number of nodes */
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Statistics on number of RR nodes (by node type): \n");
|
||||
|
||||
/* Count the number of nodes */
|
||||
std::vector<size_t> num_nodes_per_type;
|
||||
num_nodes_per_type.resize(NUM_RR_TYPES);
|
||||
num_nodes_per_type.assign(NUM_RR_TYPES, 0);
|
||||
|
||||
for (int inode = 0; inode < num_rr_nodes; ++inode) {
|
||||
num_nodes_per_type[rr_node[inode].type]++;
|
||||
}
|
||||
|
||||
/* Get the largest string size of rr_node_typename */
|
||||
size_t max_str_typename = 0;
|
||||
for (int type = 0; type < NUM_RR_TYPES; ++type) {
|
||||
max_str_typename = std::max(max_str_typename, strlen(rr_node_typename[type]));
|
||||
}
|
||||
|
||||
/* Constant strings */
|
||||
char* type_str = " Type ";
|
||||
char* total_str = " Total ";
|
||||
char* node_str = " No. of nodes ";
|
||||
char* edge_str = " No. of edges ";
|
||||
|
||||
/* Count the number of characters per line:
|
||||
* we check the string length of each node type
|
||||
* Then we plus two reserved strings "type" and "total"
|
||||
*/
|
||||
size_t num_char_per_line = 0;
|
||||
for (int type = 0; type < NUM_RR_TYPES; ++type) {
|
||||
num_char_per_line += 6 + max_str_typename;
|
||||
}
|
||||
num_char_per_line += strlen(type_str);
|
||||
num_char_per_line += strlen(total_str);
|
||||
|
||||
/* Print splitter */
|
||||
for (size_t ichar = 0; ichar < num_char_per_line; ++ichar) {
|
||||
vpr_printf(TIO_MESSAGE_INFO, "-");
|
||||
}
|
||||
vpr_printf(TIO_MESSAGE_INFO, "\n");
|
||||
|
||||
/* Print node type */
|
||||
vpr_printf(TIO_MESSAGE_INFO, "%s", type_str);
|
||||
for (int type = 0; type < NUM_RR_TYPES; ++type) {
|
||||
vpr_printf(TIO_MESSAGE_INFO, " %s ", rr_node_typename[type]);
|
||||
}
|
||||
vpr_printf(TIO_MESSAGE_INFO, "%s", total_str);
|
||||
vpr_printf(TIO_MESSAGE_INFO, "\n");
|
||||
|
||||
/* Print node numbers */
|
||||
int total_num_nodes = 0;
|
||||
vpr_printf(TIO_MESSAGE_INFO, "%s", node_str);
|
||||
for (int type = 0; type < NUM_RR_TYPES; ++type) {
|
||||
vpr_printf(TIO_MESSAGE_INFO, " %10lu ", num_nodes_per_type[type]);
|
||||
total_num_nodes += num_nodes_per_type[type];
|
||||
}
|
||||
vpr_printf(TIO_MESSAGE_INFO, " %10lu ", num_rr_nodes);
|
||||
vpr_printf(TIO_MESSAGE_INFO, "\n");
|
||||
|
||||
/* Check we have the same number as stated in rr_graph */
|
||||
assert (total_num_nodes == num_rr_nodes);
|
||||
|
||||
/* Count the number of edges */
|
||||
size_t num_edges = 0;
|
||||
std::vector<size_t> num_edges_per_type;
|
||||
num_edges_per_type.resize(NUM_RR_TYPES);
|
||||
num_edges_per_type.assign(NUM_RR_TYPES, 0);
|
||||
|
||||
for (int inode = 0; inode < num_rr_nodes; ++inode) {
|
||||
num_edges_per_type[rr_node[inode].type] += rr_node[inode].num_edges;
|
||||
}
|
||||
for (int inode = 0; inode < num_rr_nodes; ++inode) {
|
||||
num_edges += rr_node[inode].num_edges;
|
||||
}
|
||||
|
||||
/* Print number of edges */
|
||||
vpr_printf(TIO_MESSAGE_INFO, "%s", edge_str);
|
||||
for (int type = 0; type < NUM_RR_TYPES; ++type) {
|
||||
vpr_printf(TIO_MESSAGE_INFO, " %10lu ", num_edges_per_type[type]);
|
||||
}
|
||||
vpr_printf(TIO_MESSAGE_INFO, " %10lu ", num_edges);
|
||||
vpr_printf(TIO_MESSAGE_INFO, "\n");
|
||||
|
||||
/* Print splitter */
|
||||
for (size_t ichar = 0; ichar < num_char_per_line; ++ichar) {
|
||||
vpr_printf(TIO_MESSAGE_INFO, "-");
|
||||
}
|
||||
vpr_printf(TIO_MESSAGE_INFO, "\n");
|
||||
|
||||
/* Print MUX size distribution */
|
||||
/* Get the maximum SB mux size */
|
||||
short max_sb_mux_size = 0;
|
||||
for (int inode = 0; inode < num_rr_nodes; ++inode) {
|
||||
/* MUX multiplexers for SBs */
|
||||
if ( (CHANX == rr_node[inode].type)
|
||||
|| (CHANY == rr_node[inode].type) ) {
|
||||
max_sb_mux_size = std::max(rr_node[inode].fan_in, max_sb_mux_size);
|
||||
}
|
||||
}
|
||||
/* Get the minimum SB mux size */
|
||||
short min_sb_mux_size = max_sb_mux_size;
|
||||
for (int inode = 0; inode < num_rr_nodes; ++inode) {
|
||||
/* MUX multiplexers for SBs */
|
||||
if ( (CHANX == rr_node[inode].type)
|
||||
|| (CHANY == rr_node[inode].type) ) {
|
||||
min_sb_mux_size = std::min(rr_node[inode].fan_in, min_sb_mux_size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the minimum SB mux size */
|
||||
int num_sb_mux = 0;
|
||||
short avg_sb_mux_size = 0;
|
||||
for (int inode = 0; inode < num_rr_nodes; ++inode) {
|
||||
/* MUX multiplexers for SBs */
|
||||
if ( (CHANX == rr_node[inode].type)
|
||||
|| (CHANY == rr_node[inode].type) ) {
|
||||
avg_sb_mux_size += rr_node[inode].fan_in;
|
||||
num_sb_mux++;
|
||||
}
|
||||
}
|
||||
avg_sb_mux_size /= num_sb_mux;
|
||||
/* Print statistics */
|
||||
vpr_printf(TIO_MESSAGE_INFO, "------------------------------------------------\n");
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Total No. of Switch Block Multiplexer size:%d\n", num_sb_mux);
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Maximum Switch Block Multiplexer size:%d\n", max_sb_mux_size);
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Minimum Switch Block Multiplexer size:%d\n", min_sb_mux_size);
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Average Switch Block Multiplexer size:%d\n", avg_sb_mux_size);
|
||||
vpr_printf(TIO_MESSAGE_INFO, "------------------------------------------------\n");
|
||||
|
||||
/* Get the maximum SB mux size */
|
||||
short max_cb_mux_size = 0;
|
||||
for (int inode = 0; inode < num_rr_nodes; ++inode) {
|
||||
/* MUX multiplexers for SBs */
|
||||
if (IPIN == rr_node[inode].type) {
|
||||
max_cb_mux_size = std::max(rr_node[inode].fan_in, max_cb_mux_size);
|
||||
}
|
||||
}
|
||||
/* Get the minimum SB mux size */
|
||||
short min_cb_mux_size = max_cb_mux_size;
|
||||
for (int inode = 0; inode < num_rr_nodes; ++inode) {
|
||||
/* MUX multiplexers for SBs */
|
||||
if (IPIN == rr_node[inode].type) {
|
||||
min_cb_mux_size = std::min(rr_node[inode].fan_in, min_cb_mux_size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the minimum SB mux size */
|
||||
int num_cb_mux = 0;
|
||||
short avg_cb_mux_size = 0;
|
||||
for (int inode = 0; inode < num_rr_nodes; ++inode) {
|
||||
/* MUX multiplexers for SBs */
|
||||
if (IPIN == rr_node[inode].type) {
|
||||
avg_cb_mux_size += rr_node[inode].fan_in;
|
||||
num_cb_mux++;
|
||||
}
|
||||
}
|
||||
avg_cb_mux_size /= num_cb_mux;
|
||||
vpr_printf(TIO_MESSAGE_INFO, "------------------------------------------------\n");
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Total No. of Connection Block Multiplexer size:%d\n", num_cb_mux);
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Maximum Connection Block Multiplexer size:%d\n", max_cb_mux_size);
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Minimum Connection Block Multiplexer size:%d\n", min_cb_mux_size);
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Average Connection Block Multiplexer size:%d\n", avg_cb_mux_size);
|
||||
vpr_printf(TIO_MESSAGE_INFO, "------------------------------------------------\n");
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* End of file : rr_graph_builder_utils.cpp
|
||||
***********************************************************************/
|
||||
|
|
|
@ -43,5 +43,7 @@ short get_track_rr_node_end_track_id(const t_rr_node* track_rr_node);
|
|||
|
||||
void print_rr_graph_stats(const t_rr_graph& rr_graph);
|
||||
|
||||
void print_rr_graph_stats();
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
* +-------------------------------------+
|
||||
* | 2019/06/11 | Xifan Tang | Created
|
||||
* +-------------------------------------+
|
||||
* | 2019/07/02 | Xifan Tang | Modified to support SB subtype and SubFs
|
||||
* +-------------------------------------+
|
||||
***********************************************************************/
|
||||
/************************************************************************
|
||||
* This file contains a builder for the complex rr_graph data structure
|
||||
|
@ -777,7 +779,8 @@ void build_rr_graph_edges(t_rr_graph* rr_graph,
|
|||
const std::vector<size_t> device_chan_width,
|
||||
const std::vector<t_segment_inf> segment_inf,
|
||||
int** Fc_in, int** Fc_out,
|
||||
const enum e_switch_block_type sb_type, const int Fs) {
|
||||
const enum e_switch_block_type sb_type, const int Fs,
|
||||
const enum e_switch_block_type sb_subtype, const int subFs) {
|
||||
|
||||
/* Create edges for SOURCE and SINK nodes for a tileable rr_graph */
|
||||
build_rr_graph_edges_for_source_nodes(rr_graph, grids);
|
||||
|
@ -804,7 +807,7 @@ void build_rr_graph_edges(t_rr_graph* rr_graph,
|
|||
|
||||
/* adapt the switch_block_conn for the GSB nodes */
|
||||
t_track2track_map sb_conn; /* [0..from_gsb_side][0..chan_width-1][track_indices] */
|
||||
sb_conn = build_gsb_track_to_track_map(rr_graph, rr_gsb, sb_type, Fs, segment_inf);
|
||||
sb_conn = build_gsb_track_to_track_map(rr_graph, rr_gsb, sb_type, Fs, sb_subtype, subFs, segment_inf);
|
||||
|
||||
/* Build edges for a GSB */
|
||||
build_edges_for_one_tileable_rr_gsb(rr_graph, &rr_gsb,
|
||||
|
@ -904,6 +907,7 @@ void build_tileable_unidir_rr_graph(INP const int L_num_types,
|
|||
INP t_type_ptr types, INP const int L_nx, INP const int L_ny,
|
||||
INP struct s_grid_tile **L_grid, INP const int chan_width,
|
||||
INP const enum e_switch_block_type sb_type, INP const int Fs,
|
||||
INP const enum e_switch_block_type sb_subtype, INP const int subFs,
|
||||
INP const int num_seg_types,
|
||||
INP const t_segment_inf * segment_inf,
|
||||
INP const int num_switches, INP const int delayless_switch,
|
||||
|
@ -1021,7 +1025,7 @@ void build_tileable_unidir_rr_graph(INP const int L_num_types,
|
|||
/* Create edges for a tileable rr_graph */
|
||||
build_rr_graph_edges(&rr_graph, device_size, grids, device_chan_width, segment_infs,
|
||||
Fc_in, Fc_out,
|
||||
sb_type, Fs);
|
||||
sb_type, Fs, sb_subtype, subFs);
|
||||
|
||||
/************************************************************************
|
||||
* 6.2 Build direction connection lists
|
||||
|
@ -1034,7 +1038,7 @@ void build_tileable_unidir_rr_graph(INP const int L_num_types,
|
|||
build_rr_graph_direct_connections(&rr_graph, device_size, grids, delayless_switch,
|
||||
num_directs, directs, clb_to_clb_directs);
|
||||
|
||||
print_rr_graph_stats(rr_graph);
|
||||
//print_rr_graph_stats(rr_graph);
|
||||
|
||||
/* Clear driver switches of the rr_graph */
|
||||
clear_rr_graph_driver_switch(&rr_graph);
|
||||
|
|
|
@ -9,6 +9,7 @@ void build_tileable_unidir_rr_graph(INP const int L_num_types,
|
|||
INP t_type_ptr types, INP const int L_nx, INP const int L_ny,
|
||||
INP struct s_grid_tile **L_grid, INP const int chan_width,
|
||||
INP const enum e_switch_block_type sb_type, INP const int Fs,
|
||||
INP const enum e_switch_block_type sb_subtype, INP const int subFs,
|
||||
INP const int num_seg_types,
|
||||
INP const t_segment_inf * segment_inf,
|
||||
INP const int num_switches, INP const int delayless_switch,
|
||||
|
|
|
@ -475,6 +475,8 @@ t_track2track_map build_gsb_track_to_track_map(const t_rr_graph* rr_graph,
|
|||
const RRGSB& rr_gsb,
|
||||
const enum e_switch_block_type sb_type,
|
||||
const int Fs,
|
||||
const enum e_switch_block_type sb_subtype,
|
||||
const int subFs,
|
||||
const std::vector<t_segment_inf> segment_inf) {
|
||||
t_track2track_map track2track_map; /* [0..gsb_side][0..chan_width][track_indices] */
|
||||
|
||||
|
@ -555,7 +557,7 @@ t_track2track_map build_gsb_track_to_track_map(const t_rr_graph* rr_graph,
|
|||
* TODO: This can be improved with different patterns!
|
||||
*/
|
||||
build_gsb_one_group_track_to_track_map(rr_graph, rr_gsb,
|
||||
sb_type, Fs,
|
||||
sb_subtype, subFs,
|
||||
pass_tracks, start_tracks,
|
||||
&track2track_map);
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@ t_track2track_map build_gsb_track_to_track_map(const t_rr_graph* rr_graph,
|
|||
const RRGSB& rr_gsb,
|
||||
const enum e_switch_block_type sb_type,
|
||||
const int Fs,
|
||||
const enum e_switch_block_type sb_subtype,
|
||||
const int subFs,
|
||||
const std::vector<t_segment_inf> segment_inf);
|
||||
|
||||
RRGSB build_one_tileable_rr_gsb(const DeviceCoordinator& device_range,
|
||||
|
|
|
@ -1,3 +1,41 @@
|
|||
/**********************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 LNIS - The University of Utah
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
***********************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Filename: fpga_x2p_bitstream_utils.c
|
||||
* Created by: Xifan Tang
|
||||
* Change history:
|
||||
* +-------------------------------------+
|
||||
* | Date | Author | Notes
|
||||
* +-------------------------------------+
|
||||
* | 2019/07/02 | Xifan Tang | Created
|
||||
* +-------------------------------------+
|
||||
***********************************************************************/
|
||||
/************************************************************************
|
||||
* This file contains most utilized functions for the bitstream generator
|
||||
***********************************************************************/
|
||||
|
||||
/***********************************/
|
||||
/* Synthesizable Verilog Dumping */
|
||||
/* Xifan TANG, EPFL/LSI */
|
||||
|
@ -30,11 +68,14 @@
|
|||
#include "fpga_x2p_mux_utils.h"
|
||||
#include "fpga_x2p_globals.h"
|
||||
|
||||
#include "fpga_x2p_bitstream_utils.h"
|
||||
|
||||
/* Determine the size of input address of a decoder */
|
||||
int determine_decoder_size(int num_addr_out) {
|
||||
return ceil(log(num_addr_out)/log(2.));
|
||||
}
|
||||
|
||||
static
|
||||
int count_num_sram_bits_one_lut_spice_model(t_spice_model* cur_spice_model) {
|
||||
int num_sram_bits = 0;
|
||||
int iport;
|
||||
|
@ -98,6 +139,7 @@ int count_num_sram_bits_one_lut_spice_model(t_spice_model* cur_spice_model) {
|
|||
return num_sram_bits;
|
||||
}
|
||||
|
||||
static
|
||||
int count_num_sram_bits_one_mux_spice_model(t_spice_model* cur_spice_model,
|
||||
int mux_size) {
|
||||
int num_sram_bits = 0;
|
||||
|
@ -162,7 +204,7 @@ int count_num_sram_bits_one_mux_spice_model(t_spice_model* cur_spice_model,
|
|||
return num_sram_bits;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int count_num_sram_bits_one_generic_spice_model(t_spice_model* cur_spice_model) {
|
||||
int iport;
|
||||
int num_sram_bits = 0;
|
||||
|
@ -227,6 +269,7 @@ int count_num_sram_bits_one_spice_model(t_spice_model* cur_spice_model,
|
|||
return -1;
|
||||
}
|
||||
|
||||
static
|
||||
int count_num_mode_bits_one_generic_spice_model(t_spice_model* cur_spice_model) {
|
||||
int iport;
|
||||
int num_mode_bits = 0;
|
||||
|
@ -424,20 +467,7 @@ int count_num_reserved_conf_bits_one_mux_spice_model(t_spice_model* cur_spice_mo
|
|||
break;
|
||||
case SPICE_SRAM_SCAN_CHAIN:
|
||||
case SPICE_SRAM_STANDALONE:
|
||||
/* 4T1R MUX requires more configuration bits */
|
||||
if (SPICE_MODEL_STRUCTURE_TREE == cur_spice_model->design_tech_info.mux_info->structure) {
|
||||
/* For tree-structure: we need 3 times more config. bits */
|
||||
num_reserved_conf_bits = 0;
|
||||
} else if (SPICE_MODEL_STRUCTURE_MULTILEVEL == cur_spice_model->design_tech_info.mux_info->structure) {
|
||||
/* For multi-level structure: we need 1 more config. bits for each level */
|
||||
num_reserved_conf_bits = 0;
|
||||
} else {
|
||||
num_reserved_conf_bits = 0;
|
||||
}
|
||||
/* For 2:1 MUX, whatever structure, there is only one level */
|
||||
if (2 == num_input_size) {
|
||||
num_reserved_conf_bits = 0;
|
||||
}
|
||||
num_reserved_conf_bits = 0;
|
||||
break;
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Invalid type of SRAM organization!\n",
|
||||
|
@ -533,7 +563,7 @@ int count_num_reserved_conf_bits_one_spice_model(t_spice_model* cur_spice_model,
|
|||
return num_reserved_conf_bits;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int count_num_conf_bits_one_lut_spice_model(t_spice_model* cur_spice_model,
|
||||
enum e_sram_orgz cur_sram_orgz_type) {
|
||||
int num_conf_bits = 0;
|
||||
|
@ -611,7 +641,7 @@ int count_num_conf_bits_one_lut_spice_model(t_spice_model* cur_spice_model,
|
|||
return num_conf_bits;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int count_num_conf_bits_one_mux_spice_model(t_spice_model* cur_spice_model,
|
||||
enum e_sram_orgz cur_sram_orgz_type,
|
||||
int mux_size) {
|
||||
|
@ -684,6 +714,7 @@ int count_num_conf_bits_one_mux_spice_model(t_spice_model* cur_spice_model,
|
|||
return num_conf_bits;
|
||||
}
|
||||
|
||||
static
|
||||
int count_num_conf_bits_one_generic_spice_model(t_spice_model* cur_spice_model,
|
||||
enum e_sram_orgz cur_sram_orgz_type) {
|
||||
int num_conf_bits = 0;
|
||||
|
@ -1098,9 +1129,9 @@ add_mux_conf_bits_to_llist(int mux_size,
|
|||
}
|
||||
|
||||
/* Add SCFF configutration bits to a linked list*/
|
||||
void
|
||||
add_sram_scff_conf_bits_to_llist(t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int num_sram_bits, int* sram_bits) {
|
||||
static
|
||||
void add_sram_scff_conf_bits_to_llist(t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int num_sram_bits, int* sram_bits) {
|
||||
int ibit, cur_mem_bit;
|
||||
t_conf_bit** sram_bit = NULL;
|
||||
t_spice_model* cur_sram_spice_model = NULL;
|
||||
|
@ -1592,3 +1623,7 @@ void add_mux_conf_bits_to_sram_orgz_info(t_sram_orgz_info* cur_sram_orgz_info,
|
|||
|
||||
return;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* End of file : fpga_x2p_bitstream_utils.c
|
||||
***********************************************************************/
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#ifndef FPGA_X2P_BITSTREAM_UTILS_H
|
||||
#define FPGA_X2P_BITSTREAM_UTILS_H
|
||||
|
||||
int determine_decoder_size(int num_addr_out);
|
||||
|
||||
|
@ -24,6 +26,9 @@ int count_num_reserved_conf_bits_one_spice_model(t_spice_model* cur_spice_model,
|
|||
enum e_sram_orgz cur_sram_orgz_type,
|
||||
int mux_size);
|
||||
|
||||
int count_num_reserved_conf_bit_one_interc(t_interconnect* cur_interc,
|
||||
enum e_sram_orgz cur_sram_orgz_type);
|
||||
|
||||
void
|
||||
add_mux_scff_conf_bits_to_llist(int mux_size,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
|
@ -78,3 +83,5 @@ void add_sram_conf_bits_to_sram_orgz_info(t_sram_orgz_info* cur_sram_orgz_info,
|
|||
|
||||
void add_mux_conf_bits_to_sram_orgz_info(t_sram_orgz_info* cur_sram_orgz_info,
|
||||
t_spice_model* mux_spice_model, int mux_size) ;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef FPGA_X2P_PBTYPES_UTILS_H
|
||||
#define FPGA_X2P_PBTYPES_UTILS_H
|
||||
|
||||
#include "fpga_x2p_bitstream_utils.h"
|
||||
|
||||
void check_pb_graph_edge(t_pb_graph_edge pb_graph_edge);
|
||||
|
||||
void check_pb_graph_pin_edges(t_pb_graph_pin pb_graph_pin);
|
||||
|
@ -74,9 +76,6 @@ void mark_one_pb_parasitic_nets(t_phy_pb* cur_pb);
|
|||
int count_num_conf_bit_one_interc(t_interconnect* cur_interc,
|
||||
enum e_sram_orgz cur_sram_orgz_type);
|
||||
|
||||
int count_num_reserved_conf_bit_one_interc(t_interconnect* cur_interc,
|
||||
enum e_sram_orgz cur_sram_orgz_type);
|
||||
|
||||
int count_num_conf_bits_pb_type_mode_interc(t_mode* cur_pb_type_mode,
|
||||
enum e_sram_orgz cur_sram_orgz_type);
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#include "fpga_x2p_bitstream_utils.h"
|
||||
#include "fpga_bitstream_primitives.h"
|
||||
|
||||
#include "fpga_bitstream_pbtypes.h"
|
||||
|
||||
|
||||
/***** Subroutines *****/
|
||||
|
||||
|
|
|
@ -1,3 +1,41 @@
|
|||
/**********************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 LNIS - The University of Utah
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
***********************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Filename: fpga_x2p_router.c
|
||||
* Created by: Xifan Tang
|
||||
* Change history:
|
||||
* +-------------------------------------+
|
||||
* | Date | Author | Notes
|
||||
* +-------------------------------------+
|
||||
* | 2019/07/02 | Xifan Tang | Created
|
||||
* +-------------------------------------+
|
||||
***********************************************************************/
|
||||
/************************************************************************
|
||||
* This file contains a breadth-first router which is tailored for packer
|
||||
***********************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
@ -14,6 +52,8 @@
|
|||
#include "fpga_x2p_rr_graph_utils.h"
|
||||
#include "fpga_x2p_pb_rr_graph.h"
|
||||
|
||||
#include "fpga_x2p_router.h"
|
||||
|
||||
void breadth_first_expand_rr_graph_trace_segment(t_rr_graph* local_rr_graph,
|
||||
t_trace *start_ptr,
|
||||
int remaining_connections_to_sink) {
|
||||
|
@ -145,6 +185,7 @@ void breadth_first_add_source_to_rr_graph_heap(t_rr_graph* local_rr_graph,
|
|||
/* A copy of breath_first_add_source_to_heap_cluster
|
||||
* I remove all the use of global variables
|
||||
*/
|
||||
static
|
||||
void breadth_first_add_one_source_to_rr_graph_heap(t_rr_graph* local_rr_graph,
|
||||
int src_net_index,
|
||||
int src_idx) {
|
||||
|
@ -249,6 +290,7 @@ boolean breadth_first_route_one_net_pb_rr_graph(t_rr_graph* local_rr_graph,
|
|||
|
||||
/* Adapt for the multi-source rr_graph routing
|
||||
*/
|
||||
static
|
||||
boolean breadth_first_route_one_single_source_net_pb_rr_graph(t_rr_graph* local_rr_graph,
|
||||
int inet, int isrc,
|
||||
int start_isink,
|
||||
|
@ -434,6 +476,7 @@ boolean breadth_first_route_one_single_source_net_pb_rr_graph(t_rr_graph* local_
|
|||
|
||||
/* Adapt for the multi-source rr_graph routing
|
||||
*/
|
||||
static
|
||||
boolean breadth_first_route_one_multi_source_net_pb_rr_graph(t_rr_graph* local_rr_graph,
|
||||
int inet) {
|
||||
|
||||
|
@ -550,7 +593,7 @@ boolean breadth_first_route_one_multi_source_net_pb_rr_graph(t_rr_graph* local_r
|
|||
return route_success;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
boolean feasible_routing_rr_graph(t_rr_graph* local_rr_graph,
|
||||
boolean verbose) {
|
||||
|
||||
|
@ -845,5 +888,7 @@ boolean try_breadth_first_route_pb_rr_graph(t_rr_graph* local_rr_graph) {
|
|||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* End of file : fpga_x2p_router.c
|
||||
***********************************************************************/
|
||||
|
||||
|
|
|
@ -80,8 +80,7 @@ static void init_spice_mux_testbench_globals(t_spice spice) {
|
|||
}
|
||||
|
||||
static
|
||||
void fprint_spice_mux_testbench_global_ports(FILE* fp,
|
||||
t_spice spice) {
|
||||
void fprint_spice_mux_testbench_global_ports(FILE* fp) {
|
||||
/* A valid file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Invalid File Handler!\n",__FILE__, __LINE__);
|
||||
|
@ -641,7 +640,6 @@ void fprint_spice_mux_testbench_pb_pin_mux(FILE* fp,
|
|||
|
||||
static
|
||||
void fprint_spice_mux_testbench_pb_graph_node_pin_interc(FILE* fp,
|
||||
enum e_spice_pin2pin_interc_type pin2pin_interc_type,
|
||||
t_pb_graph_pin* des_pb_graph_pin,
|
||||
t_mode* cur_mode,
|
||||
int select_path_id,
|
||||
|
@ -734,7 +732,6 @@ static
|
|||
void fprint_spice_mux_testbench_pb_pin_interc(FILE* fp,
|
||||
t_rr_node* pb_rr_graph,
|
||||
t_phy_pb* des_pb,
|
||||
enum e_spice_pin2pin_interc_type pin2pin_interc_type,
|
||||
t_pb_graph_pin* des_pb_graph_pin,
|
||||
t_mode* cur_mode,
|
||||
int select_path_id,
|
||||
|
@ -856,7 +853,6 @@ void fprintf_spice_mux_testbench_pb_graph_port_interc(FILE* fp,
|
|||
assert(NULL == cur_pb);
|
||||
path_id = DEFAULT_PATH_ID;
|
||||
fprint_spice_mux_testbench_pb_graph_node_pin_interc(fp,
|
||||
INPUT2INPUT_INTERC,
|
||||
&(cur_pb_graph_node->input_pins[iport][ipin]),
|
||||
cur_mode,
|
||||
path_id,
|
||||
|
@ -878,7 +874,6 @@ void fprintf_spice_mux_testbench_pb_graph_port_interc(FILE* fp,
|
|||
assert(DEFAULT_PATH_ID != path_id);
|
||||
}
|
||||
fprint_spice_mux_testbench_pb_pin_interc(fp, pb_rr_nodes, cur_pb, /* TODO: find out the child_pb*/
|
||||
INPUT2INPUT_INTERC,
|
||||
&(cur_pb_graph_node->input_pins[iport][ipin]),
|
||||
cur_mode,
|
||||
path_id,
|
||||
|
@ -896,7 +891,6 @@ void fprintf_spice_mux_testbench_pb_graph_port_interc(FILE* fp,
|
|||
assert(NULL == cur_pb);
|
||||
path_id = DEFAULT_PATH_ID;
|
||||
fprint_spice_mux_testbench_pb_graph_node_pin_interc(fp,
|
||||
OUTPUT2OUTPUT_INTERC,
|
||||
&(cur_pb_graph_node->output_pins[iport][ipin]),
|
||||
cur_mode,
|
||||
path_id,
|
||||
|
@ -918,7 +912,6 @@ void fprintf_spice_mux_testbench_pb_graph_port_interc(FILE* fp,
|
|||
assert(DEFAULT_PATH_ID != path_id);
|
||||
}
|
||||
fprint_spice_mux_testbench_pb_pin_interc(fp, pb_rr_nodes, cur_pb, /* TODO: find out the child_pb*/
|
||||
OUTPUT2OUTPUT_INTERC,
|
||||
&(cur_pb_graph_node->output_pins[iport][ipin]),
|
||||
cur_mode,
|
||||
path_id,
|
||||
|
@ -936,7 +929,6 @@ void fprintf_spice_mux_testbench_pb_graph_port_interc(FILE* fp,
|
|||
assert(NULL == cur_pb);
|
||||
path_id = DEFAULT_PATH_ID;
|
||||
fprint_spice_mux_testbench_pb_graph_node_pin_interc(fp,
|
||||
INPUT2INPUT_INTERC,
|
||||
&(cur_pb_graph_node->clock_pins[iport][ipin]),
|
||||
cur_mode,
|
||||
path_id,
|
||||
|
@ -958,7 +950,6 @@ void fprintf_spice_mux_testbench_pb_graph_port_interc(FILE* fp,
|
|||
assert(DEFAULT_PATH_ID != path_id);
|
||||
}
|
||||
fprint_spice_mux_testbench_pb_pin_interc(fp, pb_rr_nodes, cur_pb, /* TODO: find out the child_pb*/
|
||||
INPUT2INPUT_INTERC,
|
||||
&(cur_pb_graph_node->clock_pins[iport][ipin]),
|
||||
cur_mode,
|
||||
path_id,
|
||||
|
@ -1254,6 +1245,7 @@ void fprint_spice_mux_testbench_cb_one_mux(FILE* fp,
|
|||
return;
|
||||
}
|
||||
|
||||
static
|
||||
void fprint_spice_mux_testbench_cb_interc(FILE* fp,
|
||||
t_cb cur_cb_info,
|
||||
t_rr_node* src_rr_node,
|
||||
|
@ -1481,8 +1473,7 @@ int fprint_spice_mux_testbench_sb_one_mux(FILE* fp,
|
|||
|
||||
static
|
||||
int fprint_spice_mux_testbench_call_one_grid_sb_muxes(FILE* fp,
|
||||
t_sb cur_sb_info,
|
||||
t_ivec*** LL_rr_node_indices) {
|
||||
t_sb cur_sb_info) {
|
||||
int itrack, side;
|
||||
int used = 0;
|
||||
|
||||
|
@ -1672,6 +1663,7 @@ void fprint_spice_mux_testbench_measurements(FILE* fp,
|
|||
}
|
||||
|
||||
/* Top-level function in this source file */
|
||||
static
|
||||
int fprint_spice_one_mux_testbench(char* formatted_spice_dir,
|
||||
char* circuit_name,
|
||||
char* mux_testbench_name,
|
||||
|
@ -1743,7 +1735,7 @@ int fprint_spice_one_mux_testbench(char* formatted_spice_dir,
|
|||
fprint_spice_options(fp, arch.spice->spice_params);
|
||||
|
||||
/* Global nodes: Vdd for SRAMs, Logic Blocks(Include IO), Switch Boxes, Connection Boxes */
|
||||
fprint_spice_mux_testbench_global_ports(fp, *(arch.spice));
|
||||
fprint_spice_mux_testbench_global_ports(fp);
|
||||
|
||||
/* Quote defined Logic blocks subckts (Grids) */
|
||||
init_spice_mux_testbench_globals(*(arch.spice));
|
||||
|
@ -1798,7 +1790,7 @@ int fprint_spice_one_mux_testbench(char* formatted_spice_dir,
|
|||
case SPICE_SB_MUX_TB:
|
||||
total_sb_mux_input_density = 0.;
|
||||
/* Output a sb_mux testbench */
|
||||
used = fprint_spice_mux_testbench_call_one_grid_sb_muxes(fp, sb_info[grid_x][grid_y], LL_rr_node_indices);
|
||||
used = fprint_spice_mux_testbench_call_one_grid_sb_muxes(fp, sb_info[grid_x][grid_y]);
|
||||
/* Check and output info. */
|
||||
assert((0 == testbench_sb_mux_cnt)||(0 < testbench_sb_mux_cnt));
|
||||
if (0 < testbench_sb_mux_cnt) {
|
||||
|
|
|
@ -1,3 +1,45 @@
|
|||
/**********************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 LNIS - The University of Utah
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
***********************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Filename: spice_routing.c
|
||||
* Created by: Xifan Tang
|
||||
* Change history:
|
||||
* +-------------------------------------+
|
||||
* | Date | Author | Notes
|
||||
* +-------------------------------------+
|
||||
* | 2019/07/02 | Xifan Tang | Created
|
||||
* +-------------------------------------+
|
||||
***********************************************************************/
|
||||
/************************************************************************
|
||||
* This file contains functions to output SPICE netlists of routing resources
|
||||
* i.e., Switch Block(SB), Connection Block (CB) and routing channels.
|
||||
* Each module will be placed in an individual subckt, which be called
|
||||
* through SPICE testbenches
|
||||
* Note that each subckt is a configured module (SB, CB or Routing channals)
|
||||
***********************************************************************/
|
||||
|
||||
/***********************************/
|
||||
/* SPICE Modeling for VPR */
|
||||
/* Xifan TANG, EPFL/LSI */
|
||||
|
@ -39,7 +81,7 @@
|
|||
#include "fpga_x2p_backannotate_utils.h"
|
||||
#include "spice_routing.h"
|
||||
|
||||
|
||||
static
|
||||
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,
|
||||
|
@ -629,11 +671,9 @@ 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
|
||||
*/
|
||||
static
|
||||
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,
|
||||
boolean compact_routing_hierarchy) {
|
||||
t_sb cur_sb_info) {
|
||||
int itrack, inode, side, ix, iy, x, y;
|
||||
FILE* fp = NULL;
|
||||
char* fname = NULL;
|
||||
|
@ -755,7 +795,15 @@ void fprint_connection_box_short_interc(FILE* fp,
|
|||
assert(1 == src_rr_node->fan_in);
|
||||
|
||||
/* Check the driver*/
|
||||
drive_rr_node = &(rr_node[src_rr_node->prev_node]);
|
||||
drive_rr_node = src_rr_node->drive_rr_nodes[0];
|
||||
/* We have OPINs since we may have direct connections:
|
||||
* These connections should be handled by other functions in the compact_netlist.c
|
||||
* So we just return here for OPINs
|
||||
*/
|
||||
if (OPIN == drive_rr_node->type) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert((CHANX == drive_rr_node->type)||(CHANY == drive_rr_node->type));
|
||||
check_flag = 0;
|
||||
for (iedge = 0; iedge < drive_rr_node->num_edges; iedge++) {
|
||||
|
@ -996,11 +1044,9 @@ void fprint_connection_box_interc(FILE* fp,
|
|||
* | | Connection | |
|
||||
* --------------Box_Y[x][y-1]--------------
|
||||
*/
|
||||
static
|
||||
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,
|
||||
boolean compact_routing_hierarchy) {
|
||||
t_cb cur_cb_info) {
|
||||
|
||||
int itrack, inode, side, x, y;
|
||||
int side_cnt = 0;
|
||||
|
@ -1104,6 +1150,7 @@ void fprint_routing_connection_box_subckt(char* subckt_dir,
|
|||
fprintf(fp, "***** Head of scan-chain *****\n");
|
||||
fprintf(fp, "Rcbx[%d][%d]_sc_head cbx[%d][%d]_sc_head %s[%d]->in 0\n",
|
||||
x, y, x, y, sram_spice_model->prefix, sram_spice_model->cnt);
|
||||
break;
|
||||
case CHANY:
|
||||
fprintf(fp, "***** Head of scan-chain *****\n");
|
||||
fprintf(fp, "Rcby[%d][%d]_sc_head cby[%d][%d]_sc_head %s[%d]->in 0\n",
|
||||
|
@ -1141,6 +1188,7 @@ void fprint_routing_connection_box_subckt(char* subckt_dir,
|
|||
fprintf(fp, "***** Tail of scan-chain *****\n");
|
||||
fprintf(fp, "Rcbx[%d][%d]_sc_tail cbx[%d][%d]_sc_tail %s[%d]->in 0\n",
|
||||
x, y, x, y, sram_spice_model->prefix, sram_spice_model->cnt);
|
||||
break;
|
||||
case CHANY:
|
||||
fprintf(fp, "***** Tail of scan-chain *****\n");
|
||||
fprintf(fp, "Rcby[%d][%d]_sc_tail cby[%d][%d]_sc_tail %s[%d]->in 0\n",
|
||||
|
@ -1173,8 +1221,7 @@ void generate_spice_routing_resources(char* subckt_dir,
|
|||
t_arch arch,
|
||||
t_det_routing_arch* routing_arch,
|
||||
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
|
||||
t_ivec*** LL_rr_node_indices,
|
||||
boolean compact_routing_hierarchy) {
|
||||
t_ivec*** LL_rr_node_indices) {
|
||||
int ix, iy;
|
||||
|
||||
assert(UNI_DIRECTIONAL == routing_arch->directionality);
|
||||
|
@ -1221,9 +1268,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(subckt_dir, sb_info[ix][iy],
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices,
|
||||
compact_routing_hierarchy);
|
||||
fprint_routing_switch_box_subckt(subckt_dir, sb_info[ix][iy]);
|
||||
update_spice_models_routing_index_high(ix, iy, SOURCE, arch.spice->num_spice_model, arch.spice->spice_models);
|
||||
}
|
||||
}
|
||||
|
@ -1237,9 +1282,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(subckt_dir, cbx_info[ix][iy],
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices,
|
||||
compact_routing_hierarchy);
|
||||
fprint_routing_connection_box_subckt(subckt_dir, cbx_info[ix][iy]);
|
||||
}
|
||||
update_spice_models_routing_index_high(ix, iy, CHANX, arch.spice->num_spice_model, arch.spice->spice_models);
|
||||
}
|
||||
|
@ -1251,9 +1294,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(CHANY, ix, iy))
|
||||
&&(0 < count_cb_info_num_ipin_rr_nodes(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,
|
||||
compact_routing_hierarchy);
|
||||
fprint_routing_connection_box_subckt(subckt_dir, cby_info[ix][iy]);
|
||||
}
|
||||
update_spice_models_routing_index_high(ix, iy, CHANY, arch.spice->num_spice_model, arch.spice->spice_models);
|
||||
}
|
||||
|
@ -1267,3 +1308,6 @@ void generate_spice_routing_resources(char* subckt_dir,
|
|||
return;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* End of file : spice_routing.c
|
||||
***********************************************************************/
|
||||
|
|
|
@ -67,6 +67,5 @@ void generate_spice_routing_resources(char* subckt_dir,
|
|||
t_arch arch,
|
||||
t_det_routing_arch* routing_arch,
|
||||
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
|
||||
t_ivec*** LL_rr_node_indices,
|
||||
boolean compact_routing_hierarchy);
|
||||
t_ivec*** LL_rr_node_indices);
|
||||
|
||||
|
|
|
@ -737,8 +737,7 @@ void generate_spice_subckts(char* subckt_dir,
|
|||
/* 6. Generate Routing architecture*/
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Writing Routing Resources....\n");
|
||||
generate_spice_routing_resources(subckt_dir, (*arch), routing_arch,
|
||||
num_rr_nodes, rr_node, rr_node_indices,
|
||||
compact_routing_hierarchy);
|
||||
num_rr_nodes, rr_node, rr_node_indices);
|
||||
|
||||
/* 7. Generate Logic Blocks */
|
||||
vpr_printf(TIO_MESSAGE_INFO,"Writing Logic Blocks...\n");
|
||||
|
|
|
@ -1489,6 +1489,7 @@ void fprint_spice_toplevel_one_grid_side_pin_with_given_index(FILE* fp,
|
|||
}
|
||||
|
||||
/* Apply a CLB to CLB direct connection to a SPICE netlist */
|
||||
static
|
||||
void fprint_spice_one_clb2clb_direct(FILE* fp,
|
||||
int from_grid_x, int from_grid_y,
|
||||
int to_grid_x, int to_grid_y,
|
||||
|
@ -1505,7 +1506,7 @@ void fprint_spice_one_clb2clb_direct(FILE* fp,
|
|||
|
||||
/* Check bandwidth match between from_clb and to_clb pins */
|
||||
if (0 != (cur_direct->from_clb_pin_end_index - cur_direct->from_clb_pin_start_index
|
||||
- cur_direct->to_clb_pin_end_index - cur_direct->to_clb_pin_start_index)) {
|
||||
- (cur_direct->to_clb_pin_end_index - cur_direct->to_clb_pin_start_index))) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(%s, [LINE%d]) Unmatch pin bandwidth in direct connection (name=%s)!\n",
|
||||
__FILE__, __LINE__, cur_direct->name);
|
||||
exit(1);
|
||||
|
@ -1619,6 +1620,7 @@ void fprint_spice_clb2clb_directs(FILE* fp,
|
|||
* 2. Their corresponding rr_node (SINK or IPIN) has 0 fan-in.
|
||||
* In these cases, we short connect them to global GND.
|
||||
*/
|
||||
static
|
||||
void fprint_grid_float_port_stimulation(FILE* fp) {
|
||||
int inode;
|
||||
int num_float_port = 0;
|
||||
|
|
|
@ -459,8 +459,10 @@ static void alloc_routing_structs(struct s_router_opts router_opts,
|
|||
}
|
||||
|
||||
build_rr_graph(graph_type, num_types, dummy_type_descriptors, nx, ny, grid,
|
||||
chan_width_x[0], NULL, det_routing_arch.switch_block_type,
|
||||
det_routing_arch.Fs, det_routing_arch.num_segment,
|
||||
chan_width_x[0], NULL,
|
||||
det_routing_arch.switch_block_type, det_routing_arch.Fs,
|
||||
det_routing_arch.switch_block_sub_type, det_routing_arch.sub_Fs,
|
||||
det_routing_arch.num_segment,
|
||||
det_routing_arch.num_switch, segment_inf,
|
||||
det_routing_arch.global_route_switch,
|
||||
det_routing_arch.delayless_switch, timing_inf,
|
||||
|
|
|
@ -297,8 +297,10 @@ boolean try_route(int width_fac, struct s_router_opts router_opts,
|
|||
/* Set up the routing resource graph defined by this FPGA architecture. */
|
||||
|
||||
build_rr_graph(graph_type, num_types, type_descriptors, nx, ny, grid,
|
||||
chan_width_x[0], NULL, det_routing_arch.switch_block_type,
|
||||
det_routing_arch.Fs, det_routing_arch.num_segment,
|
||||
chan_width_x[0], NULL,
|
||||
det_routing_arch.switch_block_type, det_routing_arch.Fs,
|
||||
det_routing_arch.switch_block_sub_type, det_routing_arch.sub_Fs,
|
||||
det_routing_arch.num_segment,
|
||||
det_routing_arch.num_switch, segment_inf,
|
||||
det_routing_arch.global_route_switch,
|
||||
det_routing_arch.delayless_switch, timing_inf,
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "ReadOptions.h"
|
||||
|
||||
#include "tileable_rr_graph_builder.h"
|
||||
#include "rr_graph_builder_utils.h"
|
||||
|
||||
/* Xifan TANG: SWSEG SUPPORT */
|
||||
#include "rr_graph_swseg.h"
|
||||
|
@ -211,7 +212,8 @@ void build_rr_graph(INP t_graph_type graph_type, INP int L_num_types,
|
|||
INP t_type_ptr types, INP int L_nx, INP int L_ny,
|
||||
INP struct s_grid_tile **L_grid, INP int chan_width,
|
||||
INP struct s_chan_width_dist *chan_capacity_inf,
|
||||
INP enum e_switch_block_type sb_type, INP int Fs, INP int num_seg_types,
|
||||
INP enum e_switch_block_type sb_type, INP int Fs,
|
||||
INP enum e_switch_block_type sb_sub_type, INP int sub_Fs, INP int num_seg_types,
|
||||
INP int num_switches, INP t_segment_inf * segment_inf,
|
||||
INP int global_route_switch, INP int delayless_switch,
|
||||
INP t_timing_inf timing_inf, INP int wire_to_ipin_switch,
|
||||
|
@ -225,7 +227,9 @@ void build_rr_graph(INP t_graph_type graph_type, INP int L_num_types,
|
|||
build_tileable_unidir_rr_graph(L_num_types, types,
|
||||
L_nx, L_ny, L_grid,
|
||||
chan_width,
|
||||
sb_type, Fs, num_seg_types, segment_inf,
|
||||
sb_type, Fs,
|
||||
sb_sub_type, sub_Fs,
|
||||
num_seg_types, segment_inf,
|
||||
num_switches, delayless_switch,
|
||||
timing_inf, wire_to_ipin_switch,
|
||||
base_cost_type, directs, num_directs, ignore_Fc_0, Warnings);
|
||||
|
@ -242,6 +246,9 @@ void build_rr_graph(INP t_graph_type graph_type, INP int L_num_types,
|
|||
|
||||
}
|
||||
|
||||
/* Print statistics of RR graph */
|
||||
print_rr_graph_stats();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ void build_rr_graph(INP t_graph_type graph_type,
|
|||
INP struct s_chan_width_dist *chan_capacity_inf,
|
||||
INP enum e_switch_block_type sb_type,
|
||||
INP int Fs,
|
||||
INP enum e_switch_block_type sb_sub_type, INP int sub_Fs,
|
||||
INP int num_seg_types,
|
||||
INP int num_switches,
|
||||
INP t_segment_inf * segment_inf,
|
||||
|
|
|
@ -692,8 +692,8 @@ static float trans_per_mux(int num_inputs, float trans_sram_bit,
|
|||
break;
|
||||
case SPICE_MODEL_STRUCTURE_MULTILEVEL:
|
||||
assert(1 < target_switch.switch_num_level);
|
||||
sram_trans = trans_sram_bit * target_switch.switch_num_level;
|
||||
mux_basis = determine_num_input_basis_multilevel_mux(num_inputs, target_switch.switch_num_level);
|
||||
sram_trans = trans_sram_bit * target_switch.switch_num_level * mux_basis;
|
||||
num_second_stage_trans = (int)pow((double)mux_basis, (double)(target_switch.switch_num_level - 1));
|
||||
pass_trans = ((num_second_stage_trans - 1) * mux_basis/(mux_basis-1)) * pass_trans_area
|
||||
+ num_inputs * pass_trans_area;
|
||||
|
|
Loading…
Reference in New Issue