#include #include #include #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: Tileable routing support !!! */ case OT_USE_TILEABLE_ROUTE_CHAN_WIDTH: return Args; /* 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; case OT_FPGA_X2P_OUTPUT_SB_XML: /* Read the file prefix to output SB XML files */ return ReadString(Args, &Options->sb_xml_dir); case OT_FPGA_X2P_DUPLICATE_GRID_PIN: 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_EXPLICIT_MAPPING: return Args; 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; case OT_FPGA_VERILOG_SYN_PRINT_SIMULATION_INI: return Args; case OT_FPGA_VERILOG_SYN_SIMULATION_INI_FILE: return ReadString(Args, &Options->fpga_verilog_simulation_ini_path); /* Xifan TANG: Bitstream generator */ case OT_FPGA_BITSTREAM_GENERATOR: return Args; // case OT_FPGA_BITSTREAM_OUTPUT_FILE: // AA: temporarily deprecated // 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; }