OpenFPGA/vpr7_x2p/vpr/SRC/base/ReadOptions.c

1058 lines
31 KiB
C

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "util.h"
#include "hash.h"
#include "vpr_types.h"
#include "OptionTokens.h"
#include "ReadOptions.h"
#include "read_settings.h"
#include "globals.h"
static boolean EchoEnabled;
static boolean Generate_PostSynthesis_Netlist;
static boolean *echoFileEnabled = NULL;
static char **echoFileNames = NULL;
static char **outputFileNames = NULL;
/******** Function prototypes ********/
static char **ReadBaseToken(INP char **Args, OUTP enum e_OptionBaseToken *Token);
static void Error(INP const char *Token);
static char **ProcessOption(INP char **Args, INOUTP t_options * Options);
static void MergeOptions(INOUTP t_options * dest, INP t_options * src, int id);
static char **ReadFloat(INP char **Args, OUTP float *Val);
static char **ReadInt(INP char **Args, OUTP int *Val);
static char **ReadOnOff(INP char **Args, OUTP boolean * Val);
static char **ReadClusterSeed(INP char **Args, OUTP enum e_cluster_seed *Type);
static char **ReadFixPins(INP char **Args, OUTP char **PinFile);
static char **ReadPlaceAlgorithm(INP char **Args,
OUTP enum e_place_algorithm *Algo);
static char **ReadRouterAlgorithm(INP char **Args,
OUTP enum e_router_algorithm *Algo);
static char **ReadPackerAlgorithm(INP char **Args,
OUTP enum e_packer_algorithm *Algo);
static char **ReadBaseCostType(INP char **Args,
OUTP enum e_base_cost_type *BaseCostType);
static char **ReadRouteType(INP char **Args, OUTP enum e_route_type *Type);
static char **ReadString(INP char **Args, OUTP char **Val);
/******** Globally Accessible Function ********/
/* Determines whether timing analysis should be on or off.
Unless otherwise specified, always default to timing.
*/
boolean IsTimingEnabled(INP t_options *Options) {
/* First priority to the '--timing_analysis' flag */
if (Options->Count[OT_TIMING_ANALYSIS]) {
return Options->TimingAnalysis;
}
return TRUE;
}
/* Determines whether file echo should be on or off.
Unless otherwise specified, always default to on.
*/
boolean IsEchoEnabled(INP t_options *Options) {
/* First priority to the '--echo_file' flag */
if (Options->Count[OT_CREATE_ECHO_FILE]) {
return Options->CreateEchoFile;
}
return FALSE;
}
boolean getEchoEnabled(void) {
return EchoEnabled;
}
void setEchoEnabled(boolean echo_enabled) {
/* enable echo outputs */
EchoEnabled = echo_enabled;
if(echoFileEnabled == NULL) {
/* initialize default echo options */
alloc_and_load_echo_file_info();
}
}
boolean GetPostSynthesisOption(void){
return Generate_PostSynthesis_Netlist;
}
void SetPostSynthesisOption(boolean post_synthesis_enabled){
Generate_PostSynthesis_Netlist = post_synthesis_enabled;
}
boolean IsPostSynthesisEnabled(INP t_options *Options) {
/* First priority to the '--generate_postsynthesis_netlist' flag */
if (Options->Count[OT_GENERATE_POST_SYNTHESIS_NETLIST]) {
return Options->Generate_Post_Synthesis_Netlist;
}
return FALSE;
}
void setAllEchoFileEnabled(boolean value) {
int i;
for(i = 0; i < (int) E_ECHO_END_TOKEN; i++) {
echoFileEnabled[i] = value;
}
}
void setEchoFileEnabled(enum e_echo_files echo_option, boolean value) {
echoFileEnabled[(int)echo_option] = value;
}
void setEchoFileName(enum e_echo_files echo_option, const char *name) {
if(echoFileNames[(int)echo_option] != NULL) {
free(echoFileNames[(int)echo_option]);
}
echoFileNames[(int)echo_option] = my_strdup(name);
}
boolean isEchoFileEnabled(enum e_echo_files echo_option) {
if(echoFileEnabled == NULL) {
return FALSE;
} else {
return echoFileEnabled[(int)echo_option];
}
}
char *getEchoFileName(enum e_echo_files echo_option) {
return echoFileNames[(int)echo_option];
}
void alloc_and_load_echo_file_info() {
echoFileEnabled = (boolean*)my_calloc((int) E_ECHO_END_TOKEN, sizeof(boolean));
echoFileNames = (char**)my_calloc((int) E_ECHO_END_TOKEN, sizeof(char*));
setAllEchoFileEnabled(TRUE);
setEchoFileName(E_ECHO_INITIAL_CLB_PLACEMENT, "initial_clb_placement.echo");
setEchoFileName(E_ECHO_INITIAL_PLACEMENT_TIMING_GRAPH, "initial_placement_timing_graph.echo");
setEchoFileName(E_ECHO_INITIAL_PLACEMENT_SLACK, "initial_placement_slack.echo");
setEchoFileName(E_ECHO_INITIAL_PLACEMENT_CRITICALITY, "initial_placement_criticality.echo");
setEchoFileName(E_ECHO_END_CLB_PLACEMENT, "end_clb_placement.echo");
setEchoFileName(E_ECHO_PLACEMENT_SINK_DELAYS, "placement_sink_delays.echo");
setEchoFileName(E_ECHO_FINAL_PLACEMENT_TIMING_GRAPH, "final_placement_timing_graph.echo");
setEchoFileName(E_ECHO_FINAL_PLACEMENT_SLACK, "final_placement_slack.echo");
setEchoFileName(E_ECHO_FINAL_PLACEMENT_CRITICALITY, "final_placement_criticality.echo");
setEchoFileName(E_ECHO_PLACEMENT_CRIT_PATH, "placement_crit_path.echo");
setEchoFileName(E_ECHO_PB_GRAPH, "pb_graph.echo");
setEchoFileName(E_ECHO_ARCH, "arch.echo");
setEchoFileName(E_ECHO_PLACEMENT_CRITICAL_PATH, "placement_critical_path.echo");
setEchoFileName(E_ECHO_PLACEMENT_LOWER_BOUND_SINK_DELAYS, "placement_lower_bound_sink_delays.echo");
setEchoFileName(E_ECHO_PLACEMENT_LOGIC_SINK_DELAYS, "placement_logic_sink_delays.echo");
setEchoFileName(E_ECHO_ROUTING_SINK_DELAYS, "routing_sink_delays.echo");
setEchoFileName(E_ECHO_POST_FLOW_TIMING_GRAPH, "post_flow_timing_graph.blif");
setEchoFileName(E_ECHO_POST_PACK_NETLIST, "post_pack_netlist.blif");
setEchoFileName(E_ECHO_BLIF_INPUT, "blif_input.echo");
setEchoFileName(E_ECHO_NET_DELAY, "net_delay.echo");
setEchoFileName(E_ECHO_TIMING_GRAPH, "timing_graph.echo");
setEchoFileName(E_ECHO_LUT_REMAPPING, "lut_remapping.echo");
setEchoFileName(E_ECHO_PRE_PACKING_TIMING_GRAPH, "pre_packing_timing_graph.echo");
setEchoFileName(E_ECHO_PRE_PACKING_TIMING_GRAPH_AS_BLIF, "pre_packing_timing_graph_as_blif.blif");
setEchoFileName(E_ECHO_CLUSTERING_TIMING_INFO, "clustering_timing_info.echo");
setEchoFileName(E_ECHO_PRE_PACKING_SLACK, "pre_packing_slack.echo");
setEchoFileName(E_ECHO_PRE_PACKING_CRITICALITY, "pre_packing_criticality.echo");
setEchoFileName(E_ECHO_CLUSTERING_BLOCK_CRITICALITIES, "clustering_block_criticalities.echo");
setEchoFileName(E_ECHO_PRE_PACKING_MOLECULES_AND_PATTERNS, "pre_packing_molecules_and_patterns.echo");
setEchoFileName(E_ECHO_MEM, "mem.echo");
setEchoFileName(E_ECHO_RR_GRAPH, "rr_graph.echo");
setEchoFileName(E_ECHO_TIMING_CONSTRAINTS, "timing_constraints.echo");
setEchoFileName(E_ECHO_CRITICAL_PATH, "critical_path.echo");
setEchoFileName(E_ECHO_SLACK, "slack.echo");
setEchoFileName(E_ECHO_CRITICALITY, "criticality.echo");
setEchoFileName(E_ECHO_COMPLETE_NET_TRACE, "complete_net_trace.echo");
setEchoFileName(E_ECHO_SEG_DETAILS, "seg_details.txt");
}
void free_echo_file_info() {
int i;
if(echoFileEnabled != NULL) {
for(i = 0; i < (int) E_ECHO_END_TOKEN; i++) {
if(echoFileNames[i] != NULL) {
free(echoFileNames[i]);
}
}
free(echoFileNames);
free(echoFileEnabled);
echoFileNames = NULL;
echoFileEnabled = NULL;
}
}
void setOutputFileName(enum e_output_files ename, const char *name, const char *default_name) {
if(outputFileNames == NULL) {
alloc_and_load_output_file_names(default_name);
}
if(outputFileNames[(int)ename] != NULL) {
free(outputFileNames[(int)ename]);
}
outputFileNames[(int)ename] = my_strdup(name);
}
char *getOutputFileName(enum e_output_files ename) {
return outputFileNames[(int)ename];
}
void alloc_and_load_output_file_names(const char *default_name) {
char *name;
if(outputFileNames == NULL) {
outputFileNames = (char**)my_calloc((int)E_FILE_END_TOKEN, sizeof(char*));
name = (char*)my_malloc((strlen(default_name) + 40) * sizeof(char));
sprintf(name, "%s.critical_path.out", default_name);
setOutputFileName(E_CRIT_PATH_FILE, name, default_name);
sprintf(name, "%s.slack.out", default_name);
setOutputFileName(E_SLACK_FILE, name, default_name);
sprintf(name, "%s.criticality.out", default_name);
setOutputFileName(E_CRITICALITY_FILE, name, default_name);
free(name);
}
}
void free_output_file_names() {
int i;
if(outputFileNames != NULL) {
for(i = 0; i < (int)E_FILE_END_TOKEN; i++) {
if(outputFileNames[i] != NULL) {
free(outputFileNames[i]);
outputFileNames[i] = NULL;
}
}
free(outputFileNames);
outputFileNames = NULL;
}
}
/******** Subroutine implementations ********/
void ReadOptions(INP int argc, INP char **argv, OUTP t_options * Options) {
char **Args, **head;
int offset;
/* Clear values and pointers to zero */
memset(Options, 0, sizeof(t_options));
/* Alloc a new pointer list for args with a NULL at end.
* This makes parsing the same as for archfile for consistency.
* Skips the first arg as it is the program image path */
--argc;
++argv;
head = Args = (char **) my_malloc(sizeof(char *) * (argc + 1));
memcpy(Args, argv, (sizeof(char *) * argc));
Args[argc] = NULL;
/* Go through the command line args. If they have hyphens they are
* options. Otherwise assume they are part of the four mandatory
* arguments */
while (*Args) {
if (strncmp("--", *Args, 2) == 0) {
*Args += 2; /* Skip the prefix */
Args = ProcessOption(Args, Options);
} else if (strncmp("-", *Args, 1) == 0) {
*Args += 1; /* Skip the prefix */
Args = ProcessOption(Args, Options);
} else if (NULL == Options->ArchFile) {
Options->ArchFile = my_strdup(*Args);
vpr_printf(TIO_MESSAGE_INFO, "Architecture file: %s\n", Options->ArchFile);
++Args;
} else if (NULL == Options->CircuitName) {
Options->CircuitName = my_strdup(*Args);
/*if the user entered the circuit name with the .blif extension, remove it now*/
offset = strlen(Options->CircuitName) - 5;
if (offset > 0 && !strcmp(Options->CircuitName + offset, ".blif")) {
Options->CircuitName[offset] = '\0';
}
vpr_printf(TIO_MESSAGE_INFO, "Circuit name: %s.blif\n", Options->CircuitName);
vpr_printf(TIO_MESSAGE_INFO, "\n");
++Args;
} else {
/* Not an option and arch and net already specified so fail */
Error(*Args);
}
if (Options->Count[OT_SETTINGS_FILE] != Options->read_settings)
{
int tmp_argc = 0;
char **tmp_argv = NULL;
t_options SettingsFileOptions;
tmp_argc = read_settings_file(Options->SettingsFile, &tmp_argv);
ReadOptions(tmp_argc, tmp_argv, &SettingsFileOptions);
MergeOptions(Options, &SettingsFileOptions, Options->Count[OT_SETTINGS_FILE]);
Options->read_settings = Options->Count[OT_SETTINGS_FILE];
/* clean up local data structures */
free(tmp_argv);
}
}
free(head);
}
static char **
ProcessOption(INP char **Args, INOUTP t_options * Options) {
enum e_OptionBaseToken Token;
char **PrevArgs;
PrevArgs = Args;
Args = ReadBaseToken(Args, &Token);
if (Token < OT_BASE_UNKNOWN) {
/* If this was previously set by a lower priority source
* (ie. a settings file), reset the provenance and the
* count */
if (Options->Provenance[Token])
{
Options->Provenance[Token] = 0;
Options->Count[Token] = 1;
}
else
++Options->Count[Token];
}
switch (Token) {
/* File naming options */
case OT_BLIF_FILE:
return ReadString(Args, &Options->BlifFile);
case OT_NET_FILE:
return ReadString(Args, &Options->NetFile);
case OT_PLACE_FILE:
return ReadString(Args, &Options->PlaceFile);
case OT_ROUTE_FILE:
return ReadString(Args, &Options->RouteFile);
case OT_SDC_FILE:
return ReadString(Args, &Options->SDCFile);
case OT_SETTINGS_FILE:
return ReadString(Args, &Options->SettingsFile);
/* General Options */
case OT_NODISP:
return Args;
case OT_AUTO:
return ReadInt(Args, &Options->GraphPause);
case OT_PACK:
case OT_ROUTE:
case OT_PLACE:
return Args;
case OT_TIMING_ANALYZE_ONLY_WITH_NET_DELAY:
return ReadFloat(Args, &Options->constant_net_delay);
case OT_FAST:
case OT_FULL_STATS:
return Args;
case OT_TIMING_ANALYSIS:
return ReadOnOff(Args, &Options->TimingAnalysis);
case OT_OUTFILE_PREFIX:
return ReadString(Args, &Options->out_file_prefix);
case OT_CREATE_ECHO_FILE:
return ReadOnOff(Args, &Options->CreateEchoFile);
case OT_GENERATE_POST_SYNTHESIS_NETLIST:
return ReadOnOff(Args, &Options->Generate_Post_Synthesis_Netlist);
/* Clustering Options */
case OT_GLOBAL_CLOCKS:
return ReadOnOff(Args, &Options->global_clocks);
case OT_HILL_CLIMBING_FLAG:
return ReadOnOff(Args, &Options->hill_climbing_flag);
case OT_SWEEP_HANGING_NETS_AND_INPUTS:
return ReadOnOff(Args, &Options->sweep_hanging_nets_and_inputs);
case OT_TIMING_DRIVEN_CLUSTERING:
return ReadOnOff(Args, &Options->timing_driven);
case OT_CLUSTER_SEED:
return ReadClusterSeed(Args, &Options->cluster_seed_type);
case OT_ALPHA_CLUSTERING:
return ReadFloat(Args, &Options->alpha);
case OT_BETA_CLUSTERING:
return ReadFloat(Args, &Options->beta);
case OT_RECOMPUTE_TIMING_AFTER:
return ReadInt(Args, &Options->recompute_timing_after);
case OT_CLUSTER_BLOCK_DELAY:
return ReadFloat(Args, &Options->block_delay);
case OT_ALLOW_UNRELATED_CLUSTERING:
return ReadOnOff(Args, &Options->allow_unrelated_clustering);
case OT_ALLOW_EARLY_EXIT:
return ReadOnOff(Args, &Options->allow_early_exit);
case OT_INTRA_CLUSTER_NET_DELAY:
return ReadFloat(Args, &Options->intra_cluster_net_delay);
case OT_INTER_CLUSTER_NET_DELAY:
return ReadFloat(Args, &Options->inter_cluster_net_delay);
case OT_CONNECTION_DRIVEN_CLUSTERING:
return ReadOnOff(Args, &Options->connection_driven);
case OT_SKIP_CLUSTERING:
return Args;
case OT_PACKER_ALGORITHM:
return ReadPackerAlgorithm(Args, &Options->packer_algorithm);
/* Placer Options */
case OT_PLACE_ALGORITHM:
return ReadPlaceAlgorithm(Args, &Options->PlaceAlgorithm);
case OT_INIT_T:
return ReadFloat(Args, &Options->PlaceInitT);
case OT_EXIT_T:
return ReadFloat(Args, &Options->PlaceExitT);
case OT_ALPHA_T:
return ReadFloat(Args, &Options->PlaceAlphaT);
case OT_INNER_NUM:
return ReadFloat(Args, &Options->PlaceInnerNum);
case OT_SEED:
return ReadInt(Args, &Options->Seed);
case OT_PLACE_COST_EXP:
return ReadFloat(Args, &Options->place_cost_exp);
case OT_PLACE_CHAN_WIDTH:
return ReadInt(Args, &Options->PlaceChanWidth);
case OT_FIX_PINS:
return ReadFixPins(Args, &Options->PinFile);
case OT_ENABLE_TIMING_COMPUTATIONS:
return ReadOnOff(Args, &Options->ShowPlaceTiming);
case OT_BLOCK_DIST:
return ReadInt(Args, &Options->block_dist);
/* Placement Options Valid Only for Timing-Driven Placement */
case OT_TIMING_TRADEOFF:
return ReadFloat(Args, &Options->PlaceTimingTradeoff);
case OT_RECOMPUTE_CRIT_ITER:
return ReadInt(Args, &Options->RecomputeCritIter);
case OT_INNER_LOOP_RECOMPUTE_DIVIDER:
return ReadInt(Args, &Options->inner_loop_recompute_divider);
case OT_TD_PLACE_EXP_FIRST:
return ReadFloat(Args, &Options->place_exp_first);
case OT_TD_PLACE_EXP_LAST:
return ReadFloat(Args, &Options->place_exp_last);
/* Router Options */
case OT_MAX_ROUTER_ITERATIONS:
return ReadInt(Args, &Options->max_router_iterations);
case OT_BB_FACTOR:
return ReadInt(Args, &Options->bb_factor);
case OT_INITIAL_PRES_FAC:
return ReadFloat(Args, &Options->initial_pres_fac);
case OT_PRES_FAC_MULT:
return ReadFloat(Args, &Options->pres_fac_mult);
case OT_ACC_FAC:
return ReadFloat(Args, &Options->acc_fac);
case OT_FIRST_ITER_PRES_FAC:
return ReadFloat(Args, &Options->first_iter_pres_fac);
case OT_BEND_COST:
return ReadFloat(Args, &Options->bend_cost);
case OT_ROUTE_TYPE:
return ReadRouteType(Args, &Options->RouteType);
case OT_VERIFY_BINARY_SEARCH:
return Args;
case OT_ROUTE_CHAN_WIDTH:
return ReadInt(Args, &Options->RouteChanWidth);
case OT_ROUTER_ALGORITHM:
return ReadRouterAlgorithm(Args, &Options->RouterAlgorithm);
case OT_BASE_COST_TYPE:
return ReadBaseCostType(Args, &Options->base_cost_type);
/* Routing options valid only for timing-driven routing */
case OT_ASTAR_FAC:
return ReadFloat(Args, &Options->astar_fac);
case OT_MAX_CRITICALITY:
return ReadFloat(Args, &Options->max_criticality);
case OT_CRITICALITY_EXP:
return ReadFloat(Args, &Options->criticality_exp);
/* Power options */
case OT_POWER:
return Args;
case OT_ACTIVITY_FILE:
return ReadString(Args, &Options->ActFile);
case OT_POWER_OUT_FILE:
return ReadString(Args, &Options->PowerFile);
case OT_CMOS_TECH_BEHAVIOR_FILE:
return ReadString(Args, &Options->CmosTechFile);
/* Xifan Tang: FPGA X2P Options*/
case OT_FPGA_X2P_RENAME_ILLEGAL_PORT:
return Args;
case OT_FPGA_X2P_SIGNAL_DENSITY_WEIGHT:
return ReadFloat(Args, &Options->fpga_spice_signal_density_weight);
case OT_FPGA_X2P_SIM_WINDOW_SIZE:
return ReadFloat(Args, &Options->fpga_spice_sim_window_size);
case OT_FPGA_X2P_COMPACT_ROUTING_HIERARCHY:
/* use a compact routing hierarchy in SPICE/Verilog generation */
return Args;
/* Xifan TANG: FPGA SPICE Model Options*/
case OT_FPGA_SPICE:
return Args;
case OT_FPGA_SPICE_DIR:
return ReadString(Args, &Options->spice_dir);
case OT_FPGA_SPICE_PRINT_TOP_TESTBENCH:
return Args;
case OT_FPGA_SPICE_PRINT_PB_MUX_TESTBENCH:
return Args;
case OT_FPGA_SPICE_PRINT_CB_MUX_TESTBENCH:
return Args;
case OT_FPGA_SPICE_PRINT_SB_MUX_TESTBENCH:
return Args;
case OT_FPGA_SPICE_PRINT_CB_TESTBENCH:
return Args;
case OT_FPGA_SPICE_PRINT_SB_TESTBENCH:
return Args;
case OT_FPGA_SPICE_PRINT_GRID_TESTBENCH:
return Args;
case OT_FPGA_SPICE_PRINT_LUT_TESTBENCH:
return Args;
case OT_FPGA_SPICE_PRINT_HARDLOGIC_TESTBENCH:
return Args;
case OT_FPGA_SPICE_PRINT_IO_TESTBENCH:
return Args;
case OT_FPGA_SPICE_LEAKAGE_ONLY:
return Args;
case OT_FPGA_SPICE_PARASITIC_NET_ESTIMATION:
return ReadOnOff(Args, &Options->fpga_spice_parasitic_net_estimation);
case OT_FPGA_SPICE_TESTBENCH_LOAD_EXTRACTION:
return ReadOnOff(Args, &Options->fpga_spice_testbench_load_extraction);
case OT_FPGA_SPICE_SIM_MT_NUM:
return ReadInt(Args, &Options->fpga_spice_sim_mt_num);
case OT_FPGA_SPICE_SIMULATOR_PATH:
return ReadString(Args, &Options->fpga_spice_simulator_path);
/* Xifan TANG: Synthesizable Verilog */
case OT_FPGA_VERILOG_SYN:
return Args;
case OT_FPGA_VERILOG_SYN_DIR:
return ReadString(Args, &Options->fpga_syn_verilog_dir);
case OT_FPGA_VERILOG_SYN_PRINT_TOP_TESTBENCH:
return Args;
case OT_FPGA_VERILOG_SYN_PRINT_AUTOCHECK_TOP_TESTBENCH:
return ReadString(Args, &Options->fpga_verilog_reference_benchmark_file);
case OT_FPGA_VERILOG_SYN_PRINT_INPUT_BLIF_TESTBENCH:
return Args;
case OT_FPGA_VERILOG_SYN_PRINT_FORMAL_VERIFICATION_TOP_NETLIST:
return Args;
case OT_FPGA_VERILOG_SYN_INCLUDE_TIMING:
return Args;
case OT_FPGA_VERILOG_SYN_INCLUDE_SIGNAL_INIT:
return Args;
case OT_FPGA_VERILOG_SYN_INCLUDE_ICARUS_SIMULATOR:
return Args;
case OT_FPGA_VERILOG_SYN_PRINT_MODELSIM_AUTODECK:
return ReadString(Args, &Options->fpga_verilog_modelsim_ini_path);
case OT_FPGA_VERILOG_SYN_PRINT_USER_DEFINED_TEMPLATE:
return Args;
case OT_FPGA_VERILOG_SYN_PRINT_REPORT_TIMING_TCL:
return Args;
case OT_FPGA_VERILOG_SYN_REPORT_TIMING_RPT_PATH:
return ReadString(Args, &Options->fpga_verilog_report_timing_path);
case OT_FPGA_VERILOG_SYN_PRINT_SDC_PNR:
return Args;
case OT_FPGA_VERILOG_SYN_PRINT_SDC_ANALYSIS:
return Args;
/* Xifan TANG: Bitstream generator */
case OT_FPGA_BITSTREAM_GENERATOR:
return Args;
case OT_FPGA_BITSTREAM_OUTPUT_FILE:
return ReadString(Args, &Options->fpga_bitstream_file);
/* mrFPGA: Xifan TANG */
case OT_SHOW_SRAM:
case OT_SHOW_PASS_TRANS:
return Args;
/* Xifan TANG: CLB_PIN_REMAP */
case OT_PACK_CLB_PIN_REMAP:
case OT_PLACE_CLB_PIN_REMAP:
return Args;
default:
vpr_printf(TIO_MESSAGE_ERROR, "Unexpected option '%s' on command line.\n", *PrevArgs);
exit(1);
}
}
/*
* Map options set in the source t_options to a target t_options
* structure. Existing values in the destination have priority
* and will not be overwritten
*/
static void MergeOptions(INOUTP t_options * dest, INP t_options * src, int id)
{
int Token;
for (Token = 0; Token < OT_BASE_UNKNOWN; Token++)
{
/* Don't override values already set in the
* target destination. Also do not process
* Tokens that are not present in the source.
*/
if ((dest->Count[Token] || (!src->Count[Token])))
continue;
dest->Count[Token] = src->Count[Token];
dest->Provenance[Token] = id;
switch (Token) {
/* File naming options */
case OT_BLIF_FILE:
dest->BlifFile = src->BlifFile;
break;
case OT_NET_FILE:
dest->NetFile = src->NetFile;
break;
case OT_PLACE_FILE:
dest->PlaceFile = src->PlaceFile;
break;
case OT_ROUTE_FILE:
dest->RouteFile = src->RouteFile;
break;
case OT_SETTINGS_FILE:
dest->SettingsFile = src->SettingsFile;
break;
case OT_SDC_FILE:
dest->SDCFile = src->SDCFile;
break;
/* General Options */
case OT_NODISP:
break;
case OT_AUTO:
dest->GraphPause = src->GraphPause;
break;
case OT_PACK:
case OT_ROUTE:
case OT_PLACE:
break;
case OT_TIMING_ANALYZE_ONLY_WITH_NET_DELAY:
dest->constant_net_delay = src->constant_net_delay;
break;
case OT_FAST:
case OT_FULL_STATS:
break;
case OT_TIMING_ANALYSIS:
dest->TimingAnalysis = src->TimingAnalysis;
break;
case OT_OUTFILE_PREFIX:
dest->out_file_prefix = src->out_file_prefix;
break;
case OT_CREATE_ECHO_FILE:
dest->CreateEchoFile = src->CreateEchoFile;
break;
/* Clustering Options */
case OT_GLOBAL_CLOCKS:
dest->global_clocks = src->global_clocks;
break;
case OT_HILL_CLIMBING_FLAG:
dest->hill_climbing_flag = src->hill_climbing_flag;
break;
case OT_SWEEP_HANGING_NETS_AND_INPUTS:
dest->sweep_hanging_nets_and_inputs = src->sweep_hanging_nets_and_inputs;
break;
case OT_TIMING_DRIVEN_CLUSTERING:
dest->timing_driven = src->timing_driven;
break;
case OT_CLUSTER_SEED:
dest->cluster_seed_type = src->cluster_seed_type;
break;
case OT_ALPHA_CLUSTERING:
dest->alpha = src->alpha;
break;
case OT_BETA_CLUSTERING:
dest->beta = src->beta;
break;
case OT_RECOMPUTE_TIMING_AFTER:
dest->recompute_timing_after = src->recompute_timing_after;
break;
case OT_CLUSTER_BLOCK_DELAY:
dest->block_delay = src->block_delay;
break;
case OT_ALLOW_UNRELATED_CLUSTERING:
dest->allow_unrelated_clustering = src->allow_unrelated_clustering;
break;
case OT_ALLOW_EARLY_EXIT:
dest->allow_early_exit = src->allow_early_exit;
break;
case OT_INTRA_CLUSTER_NET_DELAY:
dest->intra_cluster_net_delay = src->intra_cluster_net_delay;
break;
case OT_INTER_CLUSTER_NET_DELAY:
dest->inter_cluster_net_delay = src->inter_cluster_net_delay;
break;
case OT_CONNECTION_DRIVEN_CLUSTERING:
dest->connection_driven = src->connection_driven;
break;
case OT_SKIP_CLUSTERING:
break;
case OT_PACKER_ALGORITHM:
dest->packer_algorithm = src->packer_algorithm;
break;
/* Placer Options */
case OT_PLACE_ALGORITHM:
dest->PlaceAlgorithm = src->PlaceAlgorithm;
break;
case OT_INIT_T:
dest->PlaceInitT = src->PlaceInitT;
break;
case OT_EXIT_T:
dest->PlaceExitT = src->PlaceExitT;
break;
case OT_ALPHA_T:
dest->PlaceAlphaT = src->PlaceAlphaT;
break;
case OT_INNER_NUM:
dest->PlaceInnerNum = src->PlaceInnerNum;
break;
case OT_SEED:
dest->Seed = src->Seed;
break;
case OT_PLACE_COST_EXP:
dest->place_cost_exp = src->place_cost_exp;
break;
case OT_PLACE_CHAN_WIDTH:
dest->PlaceChanWidth = src->PlaceChanWidth;
break;
case OT_FIX_PINS:
dest->PinFile = src->PinFile;
break;
case OT_ENABLE_TIMING_COMPUTATIONS:
dest->ShowPlaceTiming = src->ShowPlaceTiming;
break;
case OT_BLOCK_DIST:
dest->block_dist = src->block_dist;
break;
/* Placement Options Valid Only for Timing-Driven Placement */
case OT_TIMING_TRADEOFF:
dest->PlaceTimingTradeoff = src->PlaceTimingTradeoff;
break;
case OT_RECOMPUTE_CRIT_ITER:
dest->RecomputeCritIter = src->RecomputeCritIter;
break;
case OT_INNER_LOOP_RECOMPUTE_DIVIDER:
dest->inner_loop_recompute_divider = src->inner_loop_recompute_divider;
break;
case OT_TD_PLACE_EXP_FIRST:
dest->place_exp_first = src->place_exp_first;
break;
case OT_TD_PLACE_EXP_LAST:
dest->place_exp_last = src->place_exp_last;
break;
/* Router Options */
case OT_MAX_ROUTER_ITERATIONS:
dest->max_router_iterations = src->max_router_iterations;
break;
case OT_BB_FACTOR:
dest->bb_factor = src->bb_factor;
break;
case OT_INITIAL_PRES_FAC:
dest->initial_pres_fac = src->initial_pres_fac;
break;
case OT_PRES_FAC_MULT:
dest->pres_fac_mult = src->pres_fac_mult;
break;
case OT_ACC_FAC:
dest->acc_fac = src->acc_fac;
break;
case OT_FIRST_ITER_PRES_FAC:
dest->first_iter_pres_fac = src->first_iter_pres_fac;
break;
case OT_BEND_COST:
dest->bend_cost = src->bend_cost;
break;
case OT_ROUTE_TYPE:
dest->RouteType = src->RouteType;
break;
case OT_VERIFY_BINARY_SEARCH:
break;
case OT_ROUTE_CHAN_WIDTH:
dest->RouteChanWidth = src->RouteChanWidth;
break;
case OT_ROUTER_ALGORITHM:
dest->RouterAlgorithm = src->RouterAlgorithm;
break;
case OT_BASE_COST_TYPE:
dest->base_cost_type = src->base_cost_type;
break;
/* Routing options valid only for timing-driven routing */
case OT_ASTAR_FAC:
dest->astar_fac = src->astar_fac;
break;
case OT_MAX_CRITICALITY:
dest->max_criticality = src->max_criticality;
break;
case OT_CRITICALITY_EXP:
dest->criticality_exp = src->criticality_exp;
break;
default:
break;
}
}
}
static char **
ReadBaseToken(INP char **Args, OUTP enum e_OptionBaseToken *Token) {
struct s_TokenPair *Cur;
/* Empty string is end of tokens marker */
if (NULL == *Args)
Error(*Args);
/* Linear search for the pair */
Cur = OptionBaseTokenList;
while (Cur->Str) {
if (strcmp(*Args, Cur->Str) == 0) {
*Token = (enum e_OptionBaseToken) Cur->Enum;
return ++Args;
}
++Cur;
}
*Token = OT_BASE_UNKNOWN;
return ++Args;
}
static char **
ReadToken(INP char **Args, OUTP enum e_OptionArgToken *Token) {
struct s_TokenPair *Cur;
/* Empty string is end of tokens marker */
if (NULL == *Args)
Error(*Args);
/* Linear search for the pair */
Cur = OptionArgTokenList;
while (Cur->Str) {
if (strcmp(*Args, Cur->Str) == 0) {
*Token = (enum e_OptionArgToken)Cur->Enum;
return ++Args;
}
++Cur;
}
*Token = OT_ARG_UNKNOWN;
return ++Args;
}
/* Called for parse errors. Spits out a message and then exits program. */
static void Error(INP const char *Token) {
if (Token) {
vpr_printf(TIO_MESSAGE_ERROR, "Unexpected token '%s' on command line.\n", Token);
} else {
vpr_printf(TIO_MESSAGE_ERROR, "Missing token at end of command line.\n");
}
exit(1);
}
static char **
ReadClusterSeed(INP char **Args, OUTP enum e_cluster_seed *Type) {
enum e_OptionArgToken Token;
char **PrevArgs;
PrevArgs = Args;
Args = ReadToken(Args, &Token);
switch (Token) {
case OT_TIMING:
*Type = VPACK_TIMING;
break;
case OT_MAX_INPUTS:
*Type = VPACK_MAX_INPUTS;
break;
default:
Error(*PrevArgs);
}
return Args;
}
static char **
ReadPackerAlgorithm(INP char **Args, OUTP enum e_packer_algorithm *Algo) {
enum e_OptionArgToken Token;
char **PrevArgs;
PrevArgs = Args;
Args = ReadToken(Args, &Token);
switch (Token) {
case OT_GREEDY:
*Algo = PACK_GREEDY;
break;
case OT_BRUTE_FORCE:
*Algo = PACK_BRUTE_FORCE;
break;
default:
Error(*PrevArgs);
}
return Args;
}
static char **
ReadRouterAlgorithm(INP char **Args, OUTP enum e_router_algorithm *Algo) {
enum e_OptionArgToken Token;
char **PrevArgs;
PrevArgs = Args;
Args = ReadToken(Args, &Token);
switch (Token) {
case OT_BREADTH_FIRST:
*Algo = BREADTH_FIRST;
break;
case OT_NO_TIMING:
*Algo = NO_TIMING;
break;
case OT_TIMING_DRIVEN:
*Algo = TIMING_DRIVEN;
break;
default:
Error(*PrevArgs);
}
return Args;
}
static char **
ReadBaseCostType(INP char **Args, OUTP enum e_base_cost_type *BaseCostType) {
enum e_OptionArgToken Token;
char **PrevArgs;
PrevArgs = Args;
Args = ReadToken(Args, &Token);
switch (Token) {
case OT_INTRINSIC_DELAY:
*BaseCostType = INTRINSIC_DELAY;
break;
case OT_DELAY_NORMALIZED:
*BaseCostType = DELAY_NORMALIZED;
break;
case OT_DEMAND_ONLY:
*BaseCostType = DEMAND_ONLY;
break;
default:
Error(*PrevArgs);
}
return Args;
}
static char **
ReadRouteType(INP char **Args, OUTP enum e_route_type *Type) {
enum e_OptionArgToken Token;
char **PrevArgs;
PrevArgs = Args;
Args = ReadToken(Args, &Token);
switch (Token) {
case OT_GLOBAL:
*Type = GLOBAL;
break;
case OT_DETAILED:
*Type = DETAILED;
break;
default:
Error(*PrevArgs);
}
return Args;
}
static char **
ReadPlaceAlgorithm(INP char **Args, OUTP enum e_place_algorithm *Algo) {
enum e_OptionArgToken Token;
char **PrevArgs;
PrevArgs = Args;
Args = ReadToken(Args, &Token);
switch (Token) {
case OT_BOUNDING_BOX:
*Algo = BOUNDING_BOX_PLACE;
break;
case OT_NET_TIMING_DRIVEN:
*Algo = NET_TIMING_DRIVEN_PLACE;
break;
case OT_PATH_TIMING_DRIVEN:
*Algo = PATH_TIMING_DRIVEN_PLACE;
break;
default:
Error(*PrevArgs);
}
return Args;
}
static char **
ReadFixPins(INP char **Args, OUTP char **PinFile) {
enum e_OptionArgToken Token;
int Len;
char **PrevArgs = Args;
Args = ReadToken(Args, &Token);
if (OT_RANDOM != Token) {
Len = 1 + strlen(*PrevArgs);
*PinFile = (char *) my_malloc(Len * sizeof(char));
memcpy(*PinFile, *PrevArgs, Len);
}
return Args;
}
static char **
ReadOnOff(INP char **Args, OUTP boolean * Val) {
enum e_OptionArgToken Token;
char **PrevArgs;
PrevArgs = Args;
Args = ReadToken(Args, &Token);
switch (Token) {
case OT_ON:
*Val = TRUE;
break;
case OT_OFF:
*Val = FALSE;
break;
default:
Error(*PrevArgs);
}
return Args;
}
static char **
ReadInt(INP char **Args, OUTP int *Val) {
if (NULL == *Args)
Error(*Args);
if ((**Args > '9') || (**Args < '0'))
Error(*Args);
*Val = atoi(*Args);
return ++Args;
}
static char **
ReadFloat(INP char ** Args, OUTP float *Val) {
if (NULL == *Args) {
Error(*Args);
}
if ((**Args != '-') && (**Args != '.')
&& ((**Args > '9') || (**Args < '0'))) {
Error(*Args);
}
*Val = atof(*Args);
return ++Args;
}
static char **
ReadString(INP char **Args, OUTP char **Val) {
if (NULL == *Args) {
Error(*Args);
}
*Val = my_strdup(*Args);
return ++Args;
}