blob: 5e686ce24666b3ca13fdcd9d4dbc86d4cd758e9e [file] [log] [blame]
#include <cstring>
using namespace std;
#include <assert.h>
#include <vector>
#include "util.h"
#include "vpr_types.h"
#include "OptionTokens.h"
#include "ReadOptions.h"
#include "globals.h"
#include "read_xml_arch_file.h"
#include "SetupVPR.h"
#include "pb_type_graph.h"
#include "pack_types.h"
#include "lb_type_rr_graph.h"
#include "ReadOptions.h"
#include "rr_graph_area.h"
static void SetupOperation(INP t_options Options,
OUTP enum e_operation *Operation);
static void SetupPackerOpts(INP t_options Options, INP bool TimingEnabled,
INP t_arch Arch, INP char *net_file,
OUTP struct s_packer_opts *PackerOpts);
static void SetupPlacerOpts(INP t_options Options, INP bool TimingEnabled,
OUTP struct s_placer_opts *PlacerOpts);
static void SetupAnnealSched(INP t_options Options,
OUTP struct s_annealing_sched *AnnealSched);
static void SetupRouterOpts(INP t_options Options, INP bool TimingEnabled,
OUTP struct s_router_opts *RouterOpts);
static void SetupRoutingArch(INP t_arch Arch,
OUTP struct s_det_routing_arch *RoutingArch);
static void SetupTiming(INP t_options Options, INP t_arch Arch,
INP bool TimingEnabled, INP enum e_operation Operation,
INP struct s_placer_opts PlacerOpts,
INP struct s_router_opts RouterOpts, OUTP t_timing_inf * Timing);
static void SetupSwitches(INP t_arch Arch,
INOUTP struct s_det_routing_arch *RoutingArch,
INP struct s_arch_switch_inf *ArchSwitches, INP int NumArchSwitches);
static void SetupPowerOpts(t_options Options, t_power_opts *power_opts,
t_arch * Arch);
/* Sets VPR parameters and defaults. Does not do any error checking
* as this should have been done by the various input checkers */
void SetupVPR(INP t_options *Options, INP bool TimingEnabled,
INP bool readArchFile, OUTP struct s_file_name_opts *FileNameOpts,
INOUTP t_arch * Arch, OUTP enum e_operation *Operation,
OUTP t_model ** user_models, OUTP t_model ** library_models,
OUTP struct s_packer_opts *PackerOpts,
OUTP struct s_placer_opts *PlacerOpts,
OUTP struct s_annealing_sched *AnnealSched,
OUTP struct s_router_opts *RouterOpts,
OUTP struct s_det_routing_arch *RoutingArch,
OUTP vector <t_lb_type_rr_node> **PackerRRGraphs,
OUTP t_segment_inf ** Segments, OUTP t_timing_inf * Timing,
OUTP bool * ShowGraphics, OUTP int *GraphPause,
t_power_opts * PowerOpts) {
int i, j, len;
len = strlen(Options->CircuitName) + 6; /* circuit_name.blif/0*/
if (Options->out_file_prefix != NULL ) {
len += strlen(Options->out_file_prefix);
}
default_output_name = (char*) my_calloc(len, sizeof(char));
if (Options->out_file_prefix == NULL ) {
sprintf(default_output_name, "%s", Options->CircuitName);
} else {
sprintf(default_output_name, "%s%s", Options->out_file_prefix,
Options->CircuitName);
}
/* init default filenames */
if (Options->BlifFile == NULL ) {
len = strlen(Options->CircuitName) + 6; /* circuit_name.blif/0*/
if (Options->out_file_prefix != NULL ) {
len += strlen(Options->out_file_prefix);
}
Options->BlifFile = (char*) my_calloc(len, sizeof(char));
if (Options->out_file_prefix == NULL ) {
sprintf(Options->BlifFile, "%s.blif", Options->CircuitName);
} else {
sprintf(Options->BlifFile, "%s%s.blif", Options->out_file_prefix,
Options->CircuitName);
}
}
if (Options->NetFile == NULL ) {
len = strlen(Options->CircuitName) + 5; /* circuit_name.net/0*/
if (Options->out_file_prefix != NULL ) {
len += strlen(Options->out_file_prefix);
}
Options->NetFile = (char*) my_calloc(len, sizeof(char));
if (Options->out_file_prefix == NULL ) {
sprintf(Options->NetFile, "%s.net", Options->CircuitName);
} else {
sprintf(Options->NetFile, "%s%s.net", Options->out_file_prefix,
Options->CircuitName);
}
}
if (Options->PlaceFile == NULL ) {
len = strlen(Options->CircuitName) + 7; /* circuit_name.place/0*/
if (Options->out_file_prefix != NULL ) {
len += strlen(Options->out_file_prefix);
}
Options->PlaceFile = (char*) my_calloc(len, sizeof(char));
if (Options->out_file_prefix == NULL ) {
sprintf(Options->PlaceFile, "%s.place", Options->CircuitName);
} else {
sprintf(Options->PlaceFile, "%s%s.place", Options->out_file_prefix,
Options->CircuitName);
}
}
if (Options->RouteFile == NULL ) {
len = strlen(Options->CircuitName) + 7; /* circuit_name.route/0*/
if (Options->out_file_prefix != NULL ) {
len += strlen(Options->out_file_prefix);
}
Options->RouteFile = (char*) my_calloc(len, sizeof(char));
if (Options->out_file_prefix == NULL ) {
sprintf(Options->RouteFile, "%s.route", Options->CircuitName);
} else {
sprintf(Options->RouteFile, "%s%s.route", Options->out_file_prefix,
Options->CircuitName);
}
}
if (Options->ActFile == NULL ) {
len = strlen(Options->CircuitName) + 7; /* circuit_name.route/0*/
if (Options->out_file_prefix != NULL ) {
len += strlen(Options->out_file_prefix);
}
Options->ActFile = (char*) my_calloc(len, sizeof(char));
if (Options->out_file_prefix == NULL ) {
sprintf(Options->ActFile, "%s.act", Options->CircuitName);
} else {
sprintf(Options->ActFile, "%s%s.act", Options->out_file_prefix,
Options->CircuitName);
}
}
if (Options->PowerFile == NULL ) {
len = strlen(Options->CircuitName) + 7; /* circuit_name.route/0*/
if (Options->out_file_prefix != NULL ) {
len += strlen(Options->out_file_prefix);
}
Options->PowerFile = (char*) my_calloc(len, sizeof(char));
if (Options->out_file_prefix == NULL ) {
sprintf(Options->PowerFile, "%s.power", Options->CircuitName);
} else {
sprintf(Options->ActFile, "%s%s.power", Options->out_file_prefix,
Options->CircuitName);
}
}
alloc_and_load_output_file_names(default_output_name);
FileNameOpts->CircuitName = Options->CircuitName;
FileNameOpts->ArchFile = Options->ArchFile;
FileNameOpts->BlifFile = Options->BlifFile;
FileNameOpts->NetFile = Options->NetFile;
FileNameOpts->PlaceFile = Options->PlaceFile;
FileNameOpts->RouteFile = Options->RouteFile;
FileNameOpts->ActFile = Options->ActFile;
FileNameOpts->PowerFile = Options->PowerFile;
FileNameOpts->CmosTechFile = Options->CmosTechFile;
FileNameOpts->out_file_prefix = Options->out_file_prefix;
SetupOperation(*Options, Operation);
SetupPlacerOpts(*Options, TimingEnabled, PlacerOpts);
SetupAnnealSched(*Options, AnnealSched);
SetupRouterOpts(*Options, TimingEnabled, RouterOpts);
SetupPowerOpts(*Options, PowerOpts, Arch);
if (readArchFile == true) {
XmlReadArch(Options->ArchFile, TimingEnabled, Arch, &type_descriptors,
&num_types);
}
*user_models = Arch->models;
*library_models = Arch->model_library;
/* TODO: this is inelegant, I should be populating this information in XmlReadArch */
EMPTY_TYPE = NULL;
FILL_TYPE = NULL;
IO_TYPE = NULL;
for (i = 0; i < num_types; i++) {
if (strcmp(type_descriptors[i].name, "<EMPTY>") == 0) {
EMPTY_TYPE = &type_descriptors[i];
} else if (strcmp(type_descriptors[i].name, "io") == 0) {
IO_TYPE = &type_descriptors[i];
} else {
for (j = 0; j < type_descriptors[i].num_grid_loc_def; j++) {
if (type_descriptors[i].grid_loc_def[j].grid_loc_type == FILL) {
assert(FILL_TYPE == NULL);
FILL_TYPE = &type_descriptors[i];
}
}
}
}
assert(EMPTY_TYPE != NULL && FILL_TYPE != NULL && IO_TYPE != NULL);
*Segments = Arch->Segments;
RoutingArch->num_segment = Arch->num_segments;
#ifdef INTERPOSER_BASED_ARCHITECTURE
/* getting the data from the options struct for interposer-based architectures*/
percent_wires_cut = Options->percent_wires_cut;
num_cuts = Options->num_cuts;
delay_increase = Options->delay_increase;
placer_cost_constant = Options->placer_cost_constant;
constant_type = Options->constant_type;
/* used for experiments of interposer-based architectures */
allow_chanx_interposer_connections = Options->allow_chanx_interposer_connections? true: false;
transfer_interposer_fanins = Options->transfer_interposer_fanins? true: false;
allow_additional_interposer_fanins = Options->allow_additional_interposer_fanins? true: false;
pct_of_interposer_nodes_each_chany_can_drive = Options->pct_of_interposer_nodes_each_chany_can_drive;
transfer_interposer_fanouts = Options->transfer_interposer_fanouts? true: false;
allow_additional_interposer_fanouts = Options->allow_additional_interposer_fanouts? true: false;
pct_of_chany_wires_an_interposer_node_can_drive = Options->pct_of_chany_wires_an_interposer_node_can_drive;
#endif
SetupSwitches(*Arch, RoutingArch, Arch->Switches, Arch->num_switches);
SetupRoutingArch(*Arch, RoutingArch);
SetupTiming(*Options, *Arch, TimingEnabled, *Operation, *PlacerOpts,
*RouterOpts, Timing);
SetupPackerOpts(*Options, TimingEnabled, *Arch, Options->NetFile,
PackerOpts);
RoutingArch->dump_rr_structs_file = Options->dump_rr_structs_file;
/* init global variables */
out_file_prefix = Options->out_file_prefix;
grid_logic_tile_area = Arch->grid_logic_tile_area;
/* Set seed for pseudo-random placement, default seed to 1 */
PlacerOpts->seed = 1;
if (Options->Count[OT_SEED]) {
PlacerOpts->seed = Options->Seed;
}
my_srandom(PlacerOpts->seed);
vpr_printf_info("Building complex block graph.\n");
alloc_and_load_all_pb_graphs(PowerOpts->do_power);
*PackerRRGraphs = alloc_and_load_all_lb_type_rr_graph();
if (getEchoEnabled() && isEchoFileEnabled(E_ECHO_LB_TYPE_RR_GRAPH)) {
echo_lb_type_rr_graphs(getEchoFileName(E_ECHO_LB_TYPE_RR_GRAPH),*PackerRRGraphs);
}
if (getEchoEnabled() && isEchoFileEnabled(E_ECHO_PB_GRAPH)) {
echo_pb_graph(getEchoFileName(E_ECHO_PB_GRAPH));
}
*GraphPause = 1; /* DEFAULT */
if (Options->Count[OT_AUTO]) {
*GraphPause = Options->GraphPause;
}
#ifdef NO_GRAPHICS
*ShowGraphics = false; /* DEFAULT */
#else /* NO_GRAPHICS */
*ShowGraphics = true; /* DEFAULT */
if (Options->Count[OT_NODISP]) {
*ShowGraphics = false;
}
#endif /* NO_GRAPHICS */
if (getEchoEnabled() && isEchoFileEnabled(E_ECHO_ARCH)) {
EchoArch(getEchoFileName(E_ECHO_ARCH), type_descriptors, num_types,
Arch);
}
}
static void SetupTiming(INP t_options Options, INP t_arch Arch,
INP bool TimingEnabled, INP enum e_operation Operation,
INP struct s_placer_opts PlacerOpts,
INP struct s_router_opts RouterOpts, OUTP t_timing_inf * Timing) {
/* Don't do anything if they don't want timing */
if (false == TimingEnabled) {
memset(Timing, 0, sizeof(t_timing_inf));
Timing->timing_analysis_enabled = false;
return;
}
Timing->C_ipin_cblock = Arch.C_ipin_cblock;
Timing->T_ipin_cblock = Arch.T_ipin_cblock;
Timing->timing_analysis_enabled = TimingEnabled;
/* If the user specified an SDC filename on the command line, look for specified_name.sdc, otherwise look for circuit_name.sdc*/
if (Options.SDCFile == NULL ) {
Timing->SDCFile = (char*) my_calloc(strlen(Options.CircuitName) + 5,
sizeof(char)); /* circuit_name.sdc/0*/
sprintf(Timing->SDCFile, "%s.sdc", Options.CircuitName);
} else {
Timing->SDCFile = (char*) my_strdup(Options.SDCFile);
}
if (Options.SlackDefinition != '\0') {
Timing->slack_definition = Options.SlackDefinition;
assert(Timing->slack_definition == 'R' || Timing->slack_definition == 'I' ||
Timing->slack_definition == 'S' || Timing->slack_definition == 'G' ||
Timing->slack_definition == 'C' || Timing->slack_definition == 'N');
} else {
Timing->slack_definition = 'R'; // default
}
}
/* This loads up VPR's arch_switch_inf data by combining the switches from
* the arch file with the special switches that VPR needs. */
static void SetupSwitches(INP t_arch Arch,
INOUTP struct s_det_routing_arch *RoutingArch,
INP struct s_arch_switch_inf *ArchSwitches, INP int NumArchSwitches) {
int switches_to_copy = NumArchSwitches;
g_num_arch_switches = NumArchSwitches;
/* If ipin cblock info has not been read in from a switch, then we will
create a new switch for it. Otherwise, the switch already exists */
if (NULL == Arch.ipin_cblock_switch_name){
/* Depends on g_num_arch_switches */
RoutingArch->wire_to_arch_ipin_switch = g_num_arch_switches;
++g_num_arch_switches;
++NumArchSwitches;
} else {
/* need to find the index of the input cblock switch */
int ipin_cblock_switch_index = -1;
char *ipin_cblock_switch_name = Arch.ipin_cblock_switch_name;
for (int iswitch = 0; iswitch < g_num_arch_switches; iswitch++){
char *iswitch_name = ArchSwitches[iswitch].name;
if (0 == strcmp(ipin_cblock_switch_name, iswitch_name)){
ipin_cblock_switch_index = iswitch;
break;
}
}
if (ipin_cblock_switch_index == -1){
vpr_throw(VPR_ERROR_OTHER,__FILE__, __LINE__, "Could not find arch switch matching name %s\n", ipin_cblock_switch_name);
}
RoutingArch->wire_to_arch_ipin_switch = ipin_cblock_switch_index;
}
#ifdef INTERPOSER_BASED_ARCHITECTURE
/* Order of the switches will be as follows:
* 0..NumArchSwitches-1: Original switches from arch file (including wire to ipin switch)
* NumArchSwitches...2*NumArchSwitches-1: switches with increased delay
* 2*NumArchSwitches: delayless switch */
int i;
double d_delay_increase;
/* Convert the delay to seconds, as it is given as int in ps */
d_delay_increase = (double)delay_increase * 1e-12;
vpr_printf_info("delay_increase:%d d_delay_increase: %g\n", delay_increase, d_delay_increase);
/* ANDRE: Adds the extra switch types with increased delay */
g_num_arch_switches *= 2;
/* Depends on RoutingArch->num_arch_switches */
RoutingArch->delayless_switch = g_num_arch_switches;
RoutingArch->global_route_switch = RoutingArch->delayless_switch;
++g_num_arch_switches;
/* Alloc the list now that we know the final num_arch_switches value */
g_arch_switch_inf = new s_arch_switch_inf[g_num_arch_switches];
/* Mapping of the switches to their respective increased delay versions */
increased_delay_edge_map = (int *) my_malloc(sizeof(int) * g_num_arch_switches);
/* create delay edge map which maps from a normal switch to its increased-delay counterpart */
for(i = 0; i < switches_to_copy; i++){
increased_delay_edge_map[i] = i + NumArchSwitches;
increased_delay_edge_map[i+NumArchSwitches] = i + NumArchSwitches;
}
increased_delay_edge_map[RoutingArch->delayless_switch] = RoutingArch->delayless_switch;
/* copy switches that were specified in the architecture file */
for (int iswitch = 0; iswitch < NumArchSwitches; iswitch++){
g_arch_switch_inf[iswitch] = ArchSwitches[iswitch];
}
/* If ipin cblock info has *not* been read in from a switch, then we have
created a new switch for it, and now need to set its values */
if (NULL == Arch.ipin_cblock_switch_name){
/* The wire to ipin switch for all types. Curently all types
* must share ipin switch. Some of the timing code would
* need to be changed otherwise. */
g_arch_switch_inf[RoutingArch->wire_to_arch_ipin_switch].buffered = true;
g_arch_switch_inf[RoutingArch->wire_to_arch_ipin_switch].R = 0.;
g_arch_switch_inf[RoutingArch->wire_to_arch_ipin_switch].Cin = Arch.C_ipin_cblock;
g_arch_switch_inf[RoutingArch->wire_to_arch_ipin_switch].Cout = 0.;
g_arch_switch_inf[RoutingArch->wire_to_arch_ipin_switch].Tdel_map[UNDEFINED] = Arch.T_ipin_cblock;
g_arch_switch_inf[RoutingArch->wire_to_arch_ipin_switch].power_buffer_type = POWER_BUFFER_TYPE_NONE;
g_arch_switch_inf[RoutingArch->wire_to_arch_ipin_switch].mux_trans_size = Arch.ipin_mux_trans_size;
/* Assume the ipin cblock output to lblock input buffer below is 4x *
* minimum drive strength (enough to drive a fanout of up to 16 pretty *
* nicely) -- should cover a reasonable wiring C plus the fanout. */
g_arch_switch_inf[RoutingArch->wire_to_arch_ipin_switch].buf_size = trans_per_buf(Arch.R_minW_nmos / 4., Arch.R_minW_nmos, Arch.R_minW_pmos);
}
/* Actually create the new switch types for the switch boxes */
for(i = NumArchSwitches; i < 2*NumArchSwitches; i++){
g_arch_switch_inf[i] = g_arch_switch_inf[i-NumArchSwitches];
std::map<int, double> *Tdel_map = &g_arch_switch_inf[i].Tdel_map;
std::map<int, double>::iterator it;
for (it = Tdel_map->begin(); it != Tdel_map->end(); it++){
it->second += d_delay_increase;
}
}
/* Delayless switch for connecting sinks and sources with their pins. */
g_arch_switch_inf[RoutingArch->delayless_switch].buffered = true;
g_arch_switch_inf[RoutingArch->delayless_switch].R = 0.;
g_arch_switch_inf[RoutingArch->delayless_switch].Cin = 0.;
g_arch_switch_inf[RoutingArch->delayless_switch].Cout = 0.;
g_arch_switch_inf[RoutingArch->delayless_switch].Tdel_map[UNDEFINED] = 0.;
g_arch_switch_inf[RoutingArch->delayless_switch].power_buffer_type = POWER_BUFFER_TYPE_NONE;
g_arch_switch_inf[RoutingArch->delayless_switch].mux_trans_size = 0.;
#else
/* Depends on g_num_arch_switches */
RoutingArch->delayless_switch = g_num_arch_switches;
RoutingArch->global_route_switch = RoutingArch->delayless_switch;
++g_num_arch_switches;
/* Alloc the list now that we know the final num_arch_switches value */
g_arch_switch_inf = new s_arch_switch_inf[g_num_arch_switches];
for (int iswitch = 0; iswitch < switches_to_copy; iswitch++){
g_arch_switch_inf[iswitch] = ArchSwitches[iswitch];
}
/* Delayless switch for connecting sinks and sources with their pins. */
g_arch_switch_inf[RoutingArch->delayless_switch].buffered = true;
g_arch_switch_inf[RoutingArch->delayless_switch].R = 0.;
g_arch_switch_inf[RoutingArch->delayless_switch].Cin = 0.;
g_arch_switch_inf[RoutingArch->delayless_switch].Cout = 0.;
g_arch_switch_inf[RoutingArch->delayless_switch].Tdel_map[UNDEFINED] = 0.;
g_arch_switch_inf[RoutingArch->delayless_switch].power_buffer_type = POWER_BUFFER_TYPE_NONE;
g_arch_switch_inf[RoutingArch->delayless_switch].mux_trans_size = 0.;
/* If ipin cblock info has *not* been read in from a switch, then we have
created a new switch for it, and now need to set its values */
if (NULL == Arch.ipin_cblock_switch_name){
/* The wire to ipin switch for all types. Curently all types
* must share ipin switch. Some of the timing code would
* need to be changed otherwise. */
g_arch_switch_inf[RoutingArch->wire_to_arch_ipin_switch].buffered = true;
g_arch_switch_inf[RoutingArch->wire_to_arch_ipin_switch].R = 0.;
g_arch_switch_inf[RoutingArch->wire_to_arch_ipin_switch].Cin = Arch.C_ipin_cblock;
g_arch_switch_inf[RoutingArch->wire_to_arch_ipin_switch].Cout = 0.;
g_arch_switch_inf[RoutingArch->wire_to_arch_ipin_switch].Tdel_map[UNDEFINED] = Arch.T_ipin_cblock;
g_arch_switch_inf[RoutingArch->wire_to_arch_ipin_switch].power_buffer_type = POWER_BUFFER_TYPE_NONE;
g_arch_switch_inf[RoutingArch->wire_to_arch_ipin_switch].mux_trans_size = Arch.ipin_mux_trans_size;
/* Assume the ipin cblock output to lblock input buffer below is 4x *
* minimum drive strength (enough to drive a fanout of up to 16 pretty *
* nicely) -- should cover a reasonable wiring C plus the fanout. */
g_arch_switch_inf[RoutingArch->wire_to_arch_ipin_switch].buf_size = trans_per_buf(Arch.R_minW_nmos / 4., Arch.R_minW_nmos, Arch.R_minW_pmos);
}
#endif
}
/* Sets up routing structures. Since checks are already done, this
* just copies values across */
static void SetupRoutingArch(INP t_arch Arch,
OUTP struct s_det_routing_arch *RoutingArch) {
RoutingArch->switch_block_type = Arch.SBType;
RoutingArch->R_minW_nmos = Arch.R_minW_nmos;
RoutingArch->R_minW_pmos = Arch.R_minW_pmos;
RoutingArch->Fs = Arch.Fs;
RoutingArch->directionality = BI_DIRECTIONAL;
if (Arch.Segments){
RoutingArch->directionality = Arch.Segments[0].directionality;
}
/* copy over the switch block information */
RoutingArch->switchblocks = Arch.switchblocks;
}
static void SetupRouterOpts(INP t_options Options, INP bool TimingEnabled,
OUTP struct s_router_opts *RouterOpts) {
RouterOpts->astar_fac = 1.2; /* DEFAULT */
if (Options.Count[OT_ASTAR_FAC]) {
RouterOpts->astar_fac = Options.astar_fac;
}
RouterOpts->bb_factor = 3; /* DEFAULT */
if (Options.Count[OT_FAST]) {
RouterOpts->bb_factor = 0; /* DEFAULT */
}
if (Options.Count[OT_BB_FACTOR]) {
RouterOpts->bb_factor = Options.bb_factor;
}
RouterOpts->criticality_exp = 1.0; /* DEFAULT */
if (Options.Count[OT_CRITICALITY_EXP]) {
RouterOpts->criticality_exp = Options.criticality_exp;
}
RouterOpts->max_criticality = 0.99; /* DEFAULT */
if (Options.Count[OT_MAX_CRITICALITY]) {
RouterOpts->max_criticality = Options.max_criticality;
}
RouterOpts->max_router_iterations = 50; /* DEFAULT */
if (Options.Count[OT_FAST]) {
RouterOpts->max_router_iterations = 10;
}
if (Options.Count[OT_MAX_ROUTER_ITERATIONS]) {
RouterOpts->max_router_iterations = Options.max_router_iterations;
}
RouterOpts->pres_fac_mult = 1.3; /* DEFAULT */
if (Options.Count[OT_PRES_FAC_MULT]) {
RouterOpts->pres_fac_mult = Options.pres_fac_mult;
}
RouterOpts->route_type = DETAILED; /* DEFAULT */
if (Options.Count[OT_ROUTE_TYPE]) {
RouterOpts->route_type = Options.RouteType;
}
RouterOpts->full_stats = false; /* DEFAULT */
if (Options.Count[OT_FULL_STATS]) {
RouterOpts->full_stats = true;
}
RouterOpts->congestion_analysis = false;
if (Options.Count[OT_CONGESTION_ANALYSIS]) {
RouterOpts->congestion_analysis = true;
}
RouterOpts->fanout_analysis = false;
if (Options.Count[OT_FANOUT_ANALYSIS]) {
RouterOpts->fanout_analysis = true;
}
RouterOpts->switch_usage_analysis = false;
if (Options.Count[OT_SWITCH_USAGE_ANALYSIS]) {
RouterOpts->switch_usage_analysis = true;
}
RouterOpts->verify_binary_search = false; /* DEFAULT */
if (Options.Count[OT_VERIFY_BINARY_SEARCH]) {
RouterOpts->verify_binary_search = true;
}
/* Depends on RouteOpts->route_type */
RouterOpts->router_algorithm = NO_TIMING; /* DEFAULT */
if (TimingEnabled) {
RouterOpts->router_algorithm = TIMING_DRIVEN; /* DEFAULT */
}
if (GLOBAL == RouterOpts->route_type) {
RouterOpts->router_algorithm = NO_TIMING; /* DEFAULT */
}
if (Options.Count[OT_ROUTER_ALGORITHM]) {
RouterOpts->router_algorithm = Options.RouterAlgorithm;
}
RouterOpts->fixed_channel_width = NO_FIXED_CHANNEL_WIDTH; /* DEFAULT */
if (Options.Count[OT_ROUTE_CHAN_WIDTH]) {
RouterOpts->fixed_channel_width = Options.RouteChanWidth;
}
RouterOpts->trim_empty_channels = false; /* DEFAULT */
if (Options.Count[OT_TRIM_EMPTY_CHAN]) {
RouterOpts->trim_empty_channels = Options.TrimEmptyChan;
}
RouterOpts->trim_obs_channels = false; /* DEFAULT */
if (Options.Count[OT_TRIM_OBS_CHAN]) {
RouterOpts->trim_obs_channels = Options.TrimObsChan;
}
/* Depends on RouterOpts->router_algorithm */
RouterOpts->initial_pres_fac = 0.5; /* DEFAULT */
if (NO_TIMING == RouterOpts->router_algorithm || Options.Count[OT_FAST]) {
RouterOpts->initial_pres_fac = 10000.0; /* DEFAULT */
}
if (Options.Count[OT_INITIAL_PRES_FAC]) {
RouterOpts->initial_pres_fac = Options.initial_pres_fac;
}
/* Depends on RouterOpts->router_algorithm */
RouterOpts->base_cost_type = DELAY_NORMALIZED; /* DEFAULT */
if (BREADTH_FIRST == RouterOpts->router_algorithm) {
RouterOpts->base_cost_type = DEMAND_ONLY; /* DEFAULT */
}
if (NO_TIMING == RouterOpts->router_algorithm) {
RouterOpts->base_cost_type = DEMAND_ONLY; /* DEFAULT */
}
if (Options.Count[OT_BASE_COST_TYPE]) {
RouterOpts->base_cost_type = Options.base_cost_type;
}
/* Depends on RouterOpts->router_algorithm */
RouterOpts->first_iter_pres_fac = 0.5; /* DEFAULT */
if (BREADTH_FIRST == RouterOpts->router_algorithm) {
RouterOpts->first_iter_pres_fac = 0.0; /* DEFAULT */
}
if (NO_TIMING == RouterOpts->router_algorithm || Options.Count[OT_FAST]) {
RouterOpts->first_iter_pres_fac = 10000.0; /* DEFAULT */
}
if (Options.Count[OT_FIRST_ITER_PRES_FAC]) {
RouterOpts->first_iter_pres_fac = Options.first_iter_pres_fac;
}
/* Depends on RouterOpts->router_algorithm */
RouterOpts->acc_fac = 1.0;
if (BREADTH_FIRST == RouterOpts->router_algorithm) {
RouterOpts->acc_fac = 0.2;
}
if (Options.Count[OT_ACC_FAC]) {
RouterOpts->acc_fac = Options.acc_fac;
}
/* Depends on RouterOpts->route_type */
RouterOpts->bend_cost = 0.0; /* DEFAULT */
if (GLOBAL == RouterOpts->route_type) {
RouterOpts->bend_cost = 1.0; /* DEFAULT */
}
if (Options.Count[OT_BEND_COST]) {
RouterOpts->bend_cost = Options.bend_cost;
}
RouterOpts->doRouting = false;
if (Options.Count[OT_ROUTE]) {
RouterOpts->doRouting = true;
} else if (!Options.Count[OT_PACK] && !Options.Count[OT_PLACE]
&& !Options.Count[OT_ROUTE]) {
if (!Options.Count[OT_TIMING_ANALYZE_ONLY_WITH_NET_DELAY])
RouterOpts->doRouting = true;
}
/* Andre: Default value for the predictor is SAFE */
RouterOpts->routing_failure_predictor = SAFE;
if (Options.Count[OT_ROUTING_FAILURE_PREDICTOR]) {
RouterOpts->routing_failure_predictor = Options.routing_failure_predictor;
}
}
static void SetupAnnealSched(INP t_options Options,
OUTP struct s_annealing_sched *AnnealSched) {
AnnealSched->alpha_t = 0.8; /* DEFAULT */
if (Options.Count[OT_ALPHA_T]) {
AnnealSched->alpha_t = Options.PlaceAlphaT;
}
if (AnnealSched->alpha_t >= 1 || AnnealSched->alpha_t <= 0) {
vpr_throw(VPR_ERROR_OTHER,__FILE__, __LINE__, "alpha_t must be between 0 and 1 exclusive.\n");
}
AnnealSched->exit_t = 0.01; /* DEFAULT */
if (Options.Count[OT_EXIT_T]) {
AnnealSched->exit_t = Options.PlaceExitT;
}
if (AnnealSched->exit_t <= 0) {
vpr_throw(VPR_ERROR_OTHER,__FILE__, __LINE__, "exit_t must be greater than 0.\n");
}
AnnealSched->init_t = 100.0; /* DEFAULT */
if (Options.Count[OT_INIT_T]) {
AnnealSched->init_t = Options.PlaceInitT;
}
if (AnnealSched->init_t <= 0) {
vpr_throw(VPR_ERROR_OTHER,__FILE__, __LINE__, "init_t must be greater than 0.\n");
}
if (AnnealSched->init_t < AnnealSched->exit_t) {
vpr_throw(VPR_ERROR_OTHER,__FILE__, __LINE__, "init_t must be greater or equal to than exit_t.\n");
}
AnnealSched->inner_num = 1.0; /* DEFAULT */
if (Options.Count[OT_INNER_NUM]) {
AnnealSched->inner_num = Options.PlaceInnerNum;
}
if (AnnealSched->inner_num <= 0) {
vpr_throw(VPR_ERROR_OTHER,__FILE__, __LINE__, "init_t must be greater than 0.\n");
}
AnnealSched->type = AUTO_SCHED; /* DEFAULT */
if ((Options.Count[OT_ALPHA_T]) || (Options.Count[OT_EXIT_T])
|| (Options.Count[OT_INIT_T])) {
AnnealSched->type = USER_SCHED;
}
}
/* Sets up the s_packer_opts structure baesd on users inputs and on the architecture specified.
* Error checking, such as checking for conflicting params is assumed to be done beforehand
*/
void SetupPackerOpts(INP t_options Options, INP bool TimingEnabled,
INP t_arch Arch, INP char *net_file,
OUTP struct s_packer_opts *PackerOpts) {
if (Arch.clb_grid.IsAuto) {
PackerOpts->aspect = Arch.clb_grid.Aspect;
} else {
PackerOpts->aspect = (float) Arch.clb_grid.H / (float) Arch.clb_grid.W;
}
PackerOpts->output_file = net_file;
PackerOpts->blif_file_name = Options.BlifFile;
PackerOpts->doPacking = false; /* DEFAULT */
if (Options.Count[OT_PACK]) {
PackerOpts->doPacking = true;
} else if (!Options.Count[OT_PACK] && !Options.Count[OT_PLACE]
&& !Options.Count[OT_ROUTE]) {
if (!Options.Count[OT_TIMING_ANALYZE_ONLY_WITH_NET_DELAY])
PackerOpts->doPacking = true;
}
PackerOpts->global_clocks = true; /* DEFAULT */
if (Options.Count[OT_GLOBAL_CLOCKS]) {
PackerOpts->global_clocks = Options.global_clocks;
}
PackerOpts->hill_climbing_flag = false; /* DEFAULT */
if (Options.Count[OT_HILL_CLIMBING_FLAG]) {
PackerOpts->hill_climbing_flag = Options.hill_climbing_flag;
}
PackerOpts->sweep_hanging_nets_and_inputs = true;
if (Options.Count[OT_SWEEP_HANGING_NETS_AND_INPUTS]) {
PackerOpts->sweep_hanging_nets_and_inputs =
Options.sweep_hanging_nets_and_inputs;
}
PackerOpts->skip_clustering = false; /* DEFAULT */
if (Options.Count[OT_SKIP_CLUSTERING]) {
PackerOpts->skip_clustering = true;
}
PackerOpts->allow_unrelated_clustering = true; /* DEFAULT */
if (Options.Count[OT_ALLOW_UNRELATED_CLUSTERING]) {
PackerOpts->allow_unrelated_clustering =
Options.allow_unrelated_clustering;
}
PackerOpts->allow_early_exit = false; /* DEFAULT */
if (Options.Count[OT_ALLOW_EARLY_EXIT]) {
PackerOpts->allow_early_exit = Options.allow_early_exit;
}
PackerOpts->connection_driven = true; /* DEFAULT */
if (Options.Count[OT_CONNECTION_DRIVEN_CLUSTERING]) {
PackerOpts->connection_driven = Options.connection_driven;
}
PackerOpts->timing_driven = TimingEnabled; /* DEFAULT */
if (Options.Count[OT_TIMING_DRIVEN_CLUSTERING]) {
PackerOpts->timing_driven = Options.timing_driven;
}
PackerOpts->cluster_seed_type = (
TimingEnabled ? VPACK_BLEND : VPACK_MAX_INPUTS); /* DEFAULT */
if (Options.Count[OT_CLUSTER_SEED]) {
PackerOpts->cluster_seed_type = Options.cluster_seed_type;
}
PackerOpts->alpha = 0.75; /* DEFAULT */
if (Options.Count[OT_ALPHA_CLUSTERING]) {
PackerOpts->alpha = Options.alpha;
}
PackerOpts->beta = 0.9; /* DEFAULT */
if (Options.Count[OT_BETA_CLUSTERING]) {
PackerOpts->beta = Options.beta;
}
/* never recomputer timing */
PackerOpts->recompute_timing_after = MAX_SHORT; /* DEFAULT */
if (Options.Count[OT_RECOMPUTE_TIMING_AFTER]) {
PackerOpts->recompute_timing_after = Options.recompute_timing_after;
}
PackerOpts->block_delay = 0; /* DEFAULT */
if (Options.Count[OT_CLUSTER_BLOCK_DELAY]) {
PackerOpts->block_delay = Options.block_delay;
}
PackerOpts->intra_cluster_net_delay = 0; /* DEFAULT */
if (Options.Count[OT_INTRA_CLUSTER_NET_DELAY]) {
PackerOpts->intra_cluster_net_delay = Options.intra_cluster_net_delay;
}
PackerOpts->inter_cluster_net_delay = 1.0; /* DEFAULT */
PackerOpts->auto_compute_inter_cluster_net_delay = true;
if (Options.Count[OT_INTER_CLUSTER_NET_DELAY]) {
PackerOpts->inter_cluster_net_delay = Options.inter_cluster_net_delay;
PackerOpts->auto_compute_inter_cluster_net_delay = false;
}
PackerOpts->packer_algorithm = PACK_GREEDY; /* DEFAULT */
if (Options.Count[OT_PACKER_ALGORITHM]) {
PackerOpts->packer_algorithm = Options.packer_algorithm;
}
}
/* Sets up the s_placer_opts structure based on users input. Error checking,
* such as checking for conflicting params is assumed to be done beforehand */
static void SetupPlacerOpts(INP t_options Options, INP bool TimingEnabled,
OUTP struct s_placer_opts *PlacerOpts) {
PlacerOpts->block_dist = 1; /* DEFAULT */
if (Options.Count[OT_BLOCK_DIST]) {
PlacerOpts->block_dist = Options.block_dist;
}
PlacerOpts->inner_loop_recompute_divider = 0; /* DEFAULT */
if (Options.Count[OT_INNER_LOOP_RECOMPUTE_DIVIDER]) {
PlacerOpts->inner_loop_recompute_divider =
Options.inner_loop_recompute_divider;
}
PlacerOpts->place_cost_exp = 1.; /* DEFAULT */
if (Options.Count[OT_PLACE_COST_EXP]) {
PlacerOpts->place_cost_exp = Options.place_cost_exp;
}
PlacerOpts->td_place_exp_first = 1.; /* DEFAULT */
if (Options.Count[OT_TD_PLACE_EXP_FIRST]) {
PlacerOpts->td_place_exp_first = Options.place_exp_first;
}
PlacerOpts->td_place_exp_last = 8.; /* DEFAULT */
if (Options.Count[OT_TD_PLACE_EXP_LAST]) {
PlacerOpts->td_place_exp_last = Options.place_exp_last;
}
PlacerOpts->place_algorithm = BOUNDING_BOX_PLACE; /* DEFAULT */
if (TimingEnabled) {
PlacerOpts->place_algorithm = PATH_TIMING_DRIVEN_PLACE; /* DEFAULT */
}
if (Options.Count[OT_PLACE_ALGORITHM]) {
PlacerOpts->place_algorithm = Options.PlaceAlgorithm;
}
PlacerOpts->pad_loc_file = NULL; /* DEFAULT */
if (Options.Count[OT_FIX_PINS]) {
if (Options.PinFile) {
PlacerOpts->pad_loc_file = my_strdup(Options.PinFile);
}
}
PlacerOpts->pad_loc_type = FREE; /* DEFAULT */
if (Options.Count[OT_FIX_PINS]) {
PlacerOpts->pad_loc_type = (Options.PinFile ? USER : RANDOM);
}
PlacerOpts->place_chan_width = 100; /* DEFAULT */
if (Options.Count[OT_PLACE_CHAN_WIDTH]) {
PlacerOpts->place_chan_width = Options.PlaceChanWidth;
}
PlacerOpts->recompute_crit_iter = 1; /* DEFAULT */
if (Options.Count[OT_RECOMPUTE_CRIT_ITER]) {
PlacerOpts->recompute_crit_iter = Options.RecomputeCritIter;
}
PlacerOpts->timing_tradeoff = 0.5; /* DEFAULT */
if (Options.Count[OT_TIMING_TRADEOFF]) {
PlacerOpts->timing_tradeoff = Options.PlaceTimingTradeoff;
}
/* Depends on PlacerOpts->place_algorithm */
PlacerOpts->enable_timing_computations = false; /* DEFAULT */
if ((PlacerOpts->place_algorithm == PATH_TIMING_DRIVEN_PLACE)
|| (PlacerOpts->place_algorithm == NET_TIMING_DRIVEN_PLACE)) {
PlacerOpts->enable_timing_computations = true; /* DEFAULT */
}
if (Options.Count[OT_ENABLE_TIMING_COMPUTATIONS]) {
PlacerOpts->enable_timing_computations = Options.ShowPlaceTiming;
}
PlacerOpts->place_freq = PLACE_ONCE; /* DEFAULT */
if ((Options.Count[OT_ROUTE_CHAN_WIDTH])
|| (Options.Count[OT_PLACE_CHAN_WIDTH])) {
PlacerOpts->place_freq = PLACE_ONCE;
}
PlacerOpts->doPlacement = false; /* DEFAULT */
if (Options.Count[OT_PLACE]) {
PlacerOpts->doPlacement = true;
} else if (!Options.Count[OT_PACK] && !Options.Count[OT_PLACE]
&& !Options.Count[OT_ROUTE]) {
if (!Options.Count[OT_TIMING_ANALYZE_ONLY_WITH_NET_DELAY])
PlacerOpts->doPlacement = true;
}
if (PlacerOpts->doPlacement == false) {
PlacerOpts->place_freq = PLACE_NEVER;
}
}
static void SetupOperation(INP t_options Options,
OUTP enum e_operation *Operation) {
*Operation = RUN_FLOW; /* DEFAULT */
if (Options.Count[OT_TIMING_ANALYZE_ONLY_WITH_NET_DELAY]) {
*Operation = TIMING_ANALYSIS_ONLY;
}
}
static void SetupPowerOpts(t_options Options, t_power_opts *power_opts,
t_arch * Arch) {
if (Options.Count[OT_POWER]) {
power_opts->do_power = true;
} else {
power_opts->do_power = false;
}
if (power_opts->do_power) {
if (!Arch->power)
Arch->power = (t_power_arch*) my_malloc(sizeof(t_power_arch));
if (!Arch->clocks)
Arch->clocks = (t_clock_arch*) my_malloc(sizeof(t_clock_arch));
g_clock_arch = Arch->clocks;
} else {
Arch->power = NULL;
Arch->clocks = NULL;
g_clock_arch = NULL;
}
}