VPR-6.0
|
00001 #include <stdio.h> 00002 #include <string.h> 00003 #include <assert.h> 00004 #include "util.h" 00005 #include "vpr_types.h" 00006 #include "OptionTokens.h" 00007 #include "ReadOptions.h" 00008 00009 /******** Function prototypes ********/ 00010 00011 static const char *const *ReadBaseToken(INP const char *const *Args, 00012 OUTP enum e_OptionBaseToken *Token); 00013 static void Error(INP const char *Token); 00014 static void ErrorOption(INP const char *Option); 00015 static const char *const *ProcessOption(INP const char *const *Args, 00016 INOUTP t_options * Options); 00017 static const char *const *ReadFloat(INP const char *const *Args, 00018 OUTP float *Val); 00019 static const char *const *ReadInt(INP const char *const *Args, 00020 OUTP int *Val); 00021 static const char *const *ReadOnOff(INP const char *const *Args, 00022 OUTP boolean * Val); 00023 static const char *const *ReadClusterSeed(INP const char *const *Args, 00024 OUTP enum e_cluster_seed *Type); 00025 static const char *const *ReadFixPins(INP const char *const *Args, 00026 OUTP char **PinFile); 00027 static const char *const *ReadPlaceAlgorithm(INP const char *const *Args, 00028 OUTP enum e_place_algorithm 00029 *Algo); 00030 static const char *const *ReadPlaceCostType(INP const char *const *Args, 00031 OUTP enum place_c_types *Type); 00032 static const char *const *ReadRouterAlgorithm(INP const char *const *Args, 00033 OUTP enum e_router_algorithm 00034 *Algo); 00035 static const char *const *ReadPackerAlgorithm(INP const char *const *Args, 00036 OUTP enum e_packer_algorithm 00037 *Algo); 00038 static const char *const *ReadBaseCostType(INP const char *const *Args, 00039 OUTP enum e_base_cost_type *BaseCostType); 00040 static const char *const *ReadRouteType(INP const char *const *Args, 00041 OUTP enum e_route_type *Type); 00042 static const char *const *ReadString(INP const char *const *Args, 00043 OUTP char **Val); 00044 00045 00046 /******** Subroutine implementations ********/ 00047 00048 void 00049 ReadOptions(INP int argc, 00050 INP char **argv, 00051 OUTP t_options * Options) 00052 { 00053 char **Args, **head; 00054 00055 /* Clear values and pointers to zero */ 00056 memset(Options, 0, sizeof(t_options)); 00057 00058 /* Alloc a new pointer list for args with a NULL at end. 00059 * This makes parsing the same as for archfile for consistency. 00060 * Skips the first arg as it is the program image path */ 00061 --argc; 00062 ++argv; 00063 head = Args = (char **)my_malloc(sizeof(char *) * (argc + 1)); 00064 memcpy(Args, argv, (sizeof(char *) * argc)); 00065 Args[argc] = NULL; 00066 00067 /* Go through the command line args. If they have hyphens they are 00068 * options. Otherwise assume they are part of the four mandatory 00069 * arguments */ 00070 while(*Args) 00071 { 00072 if(strncmp("--", *Args, 2) == 0) 00073 { 00074 *Args += 2; /* Skip the prefix */ 00075 Args = 00076 (char **)ProcessOption((const char *const *)Args, 00077 Options); 00078 } 00079 else if(strncmp("-", *Args, 1) == 0) 00080 { 00081 *Args += 1; /* Skip the prefix */ 00082 Args = 00083 (char **)ProcessOption((const char *const *)Args, 00084 Options); 00085 } 00086 else if(NULL == Options->ArchFile) 00087 { 00088 Options->ArchFile = my_strdup(*Args); 00089 ++Args; 00090 } 00091 else if(NULL == Options->CircuitName) 00092 { 00093 Options->CircuitName = my_strdup(*Args); 00094 ++Args; 00095 } 00096 else 00097 { 00098 /* Not an option and arch and net already specified so fail */ 00099 Error(*Args); 00100 } 00101 } 00102 free(head); 00103 } 00104 00105 00106 static const char *const * 00107 ProcessOption(INP const char *const *Args, 00108 INOUTP t_options * Options) 00109 { 00110 enum e_OptionBaseToken Token; 00111 const char *const *PrevArgs; 00112 00113 PrevArgs = Args; 00114 Args = ReadBaseToken(Args, &Token); 00115 00116 if(Token < OT_BASE_UNKNOWN) 00117 { 00118 ++Options->Count[Token]; 00119 } 00120 00121 switch (Token) 00122 { 00123 /* File naming options */ 00124 case OT_BLIF_FILE: 00125 return ReadString(Args, &Options->BlifFile); 00126 case OT_NET_FILE: 00127 return ReadString(Args, &Options->NetFile); 00128 case OT_PLACE_FILE: 00129 return ReadString(Args, &Options->PlaceFile); 00130 case OT_ROUTE_FILE: 00131 return ReadString(Args, &Options->RouteFile); 00132 /* General Options */ 00133 case OT_NODISP: 00134 return Args; 00135 case OT_AUTO: 00136 return ReadInt(Args, &Options->GraphPause); 00137 case OT_PACK: 00138 case OT_ROUTE: 00139 case OT_PLACE: 00140 return Args; 00141 case OT_TIMING_ANALYZE_ONLY_WITH_NET_DELAY: 00142 return ReadFloat(Args, &Options->constant_net_delay); 00143 case OT_FAST: 00144 case OT_FULL_STATS: 00145 return Args; 00146 case OT_TIMING_ANALYSIS: 00147 return ReadOnOff(Args, &Options->TimingAnalysis); 00148 case OT_OUTFILE_PREFIX: 00149 return ReadString(Args, &Options->OutFilePrefix); 00150 00151 /* Clustering Options */ 00152 case OT_GLOBAL_CLOCKS: 00153 return ReadOnOff(Args, &Options->global_clocks); 00154 case OT_HILL_CLIMBING_FLAG: 00155 return ReadOnOff(Args, &Options->hill_climbing_flag); 00156 case OT_SWEEP_HANGING_NETS_AND_INPUTS: 00157 return ReadOnOff(Args, &Options->sweep_hanging_nets_and_inputs); 00158 case OT_TIMING_DRIVEN_CLUSTERING: 00159 return ReadOnOff(Args, &Options->timing_driven); 00160 case OT_CLUSTER_SEED: 00161 return ReadClusterSeed(Args, &Options->cluster_seed_type); 00162 case OT_ALPHA_CLUSTERING: 00163 return ReadFloat(Args, &Options->alpha); 00164 case OT_BETA_CLUSTERING: 00165 return ReadFloat(Args, &Options->beta); 00166 case OT_RECOMPUTE_TIMING_AFTER: 00167 return ReadInt(Args, &Options->recompute_timing_after); 00168 case OT_CLUSTER_BLOCK_DELAY: 00169 return ReadFloat(Args, &Options->block_delay); 00170 case OT_ALLOW_UNRELATED_CLUSTERING: 00171 return ReadOnOff(Args, &Options->allow_unrelated_clustering); 00172 case OT_ALLOW_EARLY_EXIT: 00173 return ReadOnOff(Args, &Options->allow_early_exit); 00174 case OT_INTRA_CLUSTER_NET_DELAY: 00175 return ReadFloat(Args, &Options->intra_cluster_net_delay); 00176 case OT_INTER_CLUSTER_NET_DELAY: 00177 return ReadFloat(Args, &Options->inter_cluster_net_delay); 00178 case OT_CONNECTION_DRIVEN_CLUSTERING: 00179 return ReadOnOff(Args, &Options->connection_driven); 00180 case OT_SKIP_CLUSTERING: 00181 return Args; 00182 case OT_PACKER_ALGORITHM: 00183 return ReadPackerAlgorithm(Args, &Options->packer_algorithm); 00184 case OT_HACK_NO_LEGAL_FRAC_LUT: 00185 return Args; 00186 case OT_HACK_SAFE_LATCH: 00187 return Args; 00188 00189 00190 /* Placer Options */ 00191 case OT_PLACE_ALGORITHM: 00192 return ReadPlaceAlgorithm(Args, &Options->PlaceAlgorithm); 00193 case OT_INIT_T: 00194 return ReadFloat(Args, &Options->PlaceInitT); 00195 case OT_EXIT_T: 00196 return ReadFloat(Args, &Options->PlaceExitT); 00197 case OT_ALPHA_T: 00198 return ReadFloat(Args, &Options->PlaceAlphaT); 00199 case OT_INNER_NUM: 00200 return ReadFloat(Args, &Options->PlaceInnerNum); 00201 case OT_SEED: 00202 return ReadInt(Args, &Options->Seed); 00203 case OT_PLACE_COST_EXP: 00204 return ReadFloat(Args, &Options->place_cost_exp); 00205 case OT_PLACE_COST_TYPE: 00206 return ReadPlaceCostType(Args, &Options->PlaceCostType); 00207 case OT_PLACE_CHAN_WIDTH: 00208 return ReadInt(Args, &Options->PlaceChanWidth); 00209 case OT_NUM_REGIONS: 00210 return ReadInt(Args, &Options->PlaceNonlinearRegions); 00211 case OT_FIX_PINS: 00212 return ReadFixPins(Args, &Options->PinFile); 00213 case OT_ENABLE_TIMING_COMPUTATIONS: 00214 return ReadOnOff(Args, &Options->ShowPlaceTiming); 00215 case OT_BLOCK_DIST: 00216 return ReadInt(Args, &Options->block_dist); 00217 00218 /* Placement Options Valid Only for Timing-Driven Placement */ 00219 case OT_TIMING_TRADEOFF: 00220 return ReadFloat(Args, &Options->PlaceTimingTradeoff); 00221 case OT_RECOMPUTE_CRIT_ITER: 00222 return ReadInt(Args, &Options->RecomputeCritIter); 00223 case OT_INNER_LOOP_RECOMPUTE_DIVIDER: 00224 return ReadInt(Args, &Options->inner_loop_recompute_divider); 00225 case OT_TD_PLACE_EXP_FIRST: 00226 return ReadFloat(Args, &Options->place_exp_first); 00227 case OT_TD_PLACE_EXP_LAST: 00228 return ReadFloat(Args, &Options->place_exp_last); 00229 00230 /* Router Options */ 00231 case OT_MAX_ROUTER_ITERATIONS: 00232 return ReadInt(Args, &Options->max_router_iterations); 00233 case OT_BB_FACTOR: 00234 return ReadInt(Args, &Options->bb_factor); 00235 case OT_INITIAL_PRES_FAC: 00236 return ReadFloat(Args, &Options->initial_pres_fac); 00237 case OT_PRES_FAC_MULT: 00238 return ReadFloat(Args, &Options->pres_fac_mult); 00239 case OT_ACC_FAC: 00240 return ReadFloat(Args, &Options->acc_fac); 00241 case OT_FIRST_ITER_PRES_FAC: 00242 return ReadFloat(Args, &Options->first_iter_pres_fac); 00243 case OT_BEND_COST: 00244 return ReadFloat(Args, &Options->bend_cost); 00245 case OT_ROUTE_TYPE: 00246 return ReadRouteType(Args, &Options->RouteType); 00247 case OT_VERIFY_BINARY_SEARCH: 00248 return Args; 00249 case OT_ROUTE_CHAN_WIDTH: 00250 return ReadInt(Args, &Options->RouteChanWidth); 00251 case OT_ROUTER_ALGORITHM: 00252 return ReadRouterAlgorithm(Args, &Options->RouterAlgorithm); 00253 case OT_BASE_COST_TYPE: 00254 return ReadBaseCostType(Args, &Options->base_cost_type); 00255 00256 /* Routing options valid only for timing-driven routing */ 00257 case OT_ASTAR_FAC: 00258 return ReadFloat(Args, &Options->astar_fac); 00259 case OT_MAX_CRITICALITY: 00260 return ReadFloat(Args, &Options->max_criticality); 00261 case OT_CRITICALITY_EXP: 00262 return ReadFloat(Args, &Options->criticality_exp); 00263 default: 00264 ErrorOption(*PrevArgs); 00265 } 00266 return NULL; 00267 } 00268 00269 00270 static const char *const * 00271 ReadBaseToken(INP const char *const *Args, 00272 OUTP enum e_OptionBaseToken *Token) 00273 { 00274 const struct s_TokenPair *Cur; 00275 00276 /* Empty string is end of tokens marker */ 00277 if(NULL == *Args) 00278 Error(*Args); 00279 00280 /* Linear search for the pair */ 00281 Cur = OptionBaseTokenList; 00282 while(Cur->Str) 00283 { 00284 if(strcmp(*Args, Cur->Str) == 0) 00285 { 00286 *Token = Cur->Enum; 00287 return ++Args; 00288 } 00289 ++Cur; 00290 } 00291 00292 *Token = OT_BASE_UNKNOWN; 00293 return ++Args; 00294 } 00295 00296 00297 static const char *const * 00298 ReadToken(INP const char *const *Args, 00299 OUTP enum e_OptionArgToken *Token) 00300 { 00301 const struct s_TokenPair *Cur; 00302 00303 /* Empty string is end of tokens marker */ 00304 if(NULL == *Args) 00305 Error(*Args); 00306 00307 /* Linear search for the pair */ 00308 Cur = OptionArgTokenList; 00309 while(Cur->Str) 00310 { 00311 if(strcmp(*Args, Cur->Str) == 0) 00312 { 00313 *Token = Cur->Enum; 00314 return ++Args; 00315 } 00316 ++Cur; 00317 } 00318 00319 *Token = OT_ARG_UNKNOWN; 00320 return ++Args; 00321 } 00322 00323 00324 /** Called for parse errors. Spits out a message and then exits program. */ 00325 static void 00326 Error(INP const char *Token) 00327 { 00328 if(Token) 00329 { 00330 printf(ERRTAG "Unexpected token '%s' on command line\n", Token); 00331 } 00332 else 00333 { 00334 printf(ERRTAG "Missing token at end of command line\n"); 00335 } 00336 exit(1); 00337 } 00338 00339 00340 static void 00341 ErrorOption(INP const char *Option) 00342 { 00343 printf(ERRTAG "Unexpected option '%s' on command line\n", Option); 00344 exit(1); 00345 } 00346 00347 static const char *const * 00348 ReadClusterSeed(INP const char *const *Args, 00349 OUTP enum e_cluster_seed *Type) 00350 { 00351 enum e_OptionArgToken Token; 00352 const char *const *PrevArgs; 00353 00354 PrevArgs = Args; 00355 Args = ReadToken(Args, &Token); 00356 switch (Token) 00357 { 00358 case OT_TIMING: 00359 *Type = VPACK_TIMING; 00360 break; 00361 case OT_MAX_INPUTS: 00362 *Type = NONLINEAR_CONG; 00363 break; 00364 default: 00365 Error(*PrevArgs); 00366 } 00367 00368 return Args; 00369 } 00370 00371 static const char *const * 00372 ReadPackerAlgorithm(INP const char *const *Args, 00373 OUTP enum e_packer_algorithm *Algo) 00374 { 00375 enum e_OptionArgToken Token; 00376 const char *const *PrevArgs; 00377 00378 PrevArgs = Args; 00379 Args = ReadToken(Args, &Token); 00380 switch (Token) 00381 { 00382 case OT_GREEDY: 00383 *Algo = PACK_GREEDY; 00384 break; 00385 case OT_BRUTE_FORCE: 00386 *Algo = PACK_BRUTE_FORCE; 00387 break; 00388 default: 00389 Error(*PrevArgs); 00390 } 00391 00392 return Args; 00393 } 00394 00395 static const char *const * 00396 ReadRouterAlgorithm(INP const char *const *Args, 00397 OUTP enum e_router_algorithm *Algo) 00398 { 00399 enum e_OptionArgToken Token; 00400 const char *const *PrevArgs; 00401 00402 PrevArgs = Args; 00403 Args = ReadToken(Args, &Token); 00404 switch (Token) 00405 { 00406 case OT_BREADTH_FIRST: 00407 *Algo = BREADTH_FIRST; 00408 break; 00409 case OT_DIRECTED_SEARCH: 00410 *Algo = DIRECTED_SEARCH; 00411 break; 00412 case OT_TIMING_DRIVEN: 00413 *Algo = TIMING_DRIVEN; 00414 break; 00415 default: 00416 Error(*PrevArgs); 00417 } 00418 00419 return Args; 00420 } 00421 00422 static const char *const * 00423 ReadBaseCostType(INP const char *const *Args, 00424 OUTP enum e_base_cost_type *BaseCostType) 00425 { 00426 enum e_OptionArgToken Token; 00427 const char *const *PrevArgs; 00428 00429 PrevArgs = Args; 00430 Args = ReadToken(Args, &Token); 00431 switch (Token) 00432 { 00433 case OT_INTRINSIC_DELAY: 00434 *BaseCostType = INTRINSIC_DELAY; 00435 break; 00436 case OT_DELAY_NORMALIZED: 00437 *BaseCostType = DELAY_NORMALIZED; 00438 break; 00439 case OT_DEMAND_ONLY: 00440 *BaseCostType = DEMAND_ONLY; 00441 break; 00442 default: 00443 Error(*PrevArgs); 00444 } 00445 00446 return Args; 00447 } 00448 00449 00450 static const char *const * 00451 ReadRouteType(INP const char *const *Args, 00452 OUTP enum e_route_type *Type) 00453 { 00454 enum e_OptionArgToken Token; 00455 const char *const *PrevArgs; 00456 00457 PrevArgs = Args; 00458 Args = ReadToken(Args, &Token); 00459 switch (Token) 00460 { 00461 case OT_GLOBAL: 00462 *Type = GLOBAL; 00463 break; 00464 case OT_DETAILED: 00465 *Type = DETAILED; 00466 break; 00467 default: 00468 Error(*PrevArgs); 00469 } 00470 00471 return Args; 00472 } 00473 00474 00475 static const char *const * 00476 ReadPlaceCostType(INP const char *const *Args, 00477 OUTP enum place_c_types *Type) 00478 { 00479 enum e_OptionArgToken Token; 00480 const char *const *PrevArgs; 00481 00482 PrevArgs = Args; 00483 Args = ReadToken(Args, &Token); 00484 switch (Token) 00485 { 00486 case OT_LINEAR: 00487 *Type = LINEAR_CONG; 00488 break; 00489 case OT_NONLINEAR: 00490 *Type = NONLINEAR_CONG; 00491 break; 00492 default: 00493 Error(*PrevArgs); 00494 } 00495 00496 return Args; 00497 } 00498 00499 00500 static const char *const * 00501 ReadPlaceAlgorithm(INP const char *const *Args, 00502 OUTP enum e_place_algorithm *Algo) 00503 { 00504 enum e_OptionArgToken Token; 00505 const char *const *PrevArgs; 00506 00507 PrevArgs = Args; 00508 Args = ReadToken(Args, &Token); 00509 switch (Token) 00510 { 00511 case OT_BOUNDING_BOX: 00512 *Algo = BOUNDING_BOX_PLACE; 00513 break; 00514 case OT_NET_TIMING_DRIVEN: 00515 *Algo = NET_TIMING_DRIVEN_PLACE; 00516 break; 00517 case OT_PATH_TIMING_DRIVEN: 00518 *Algo = PATH_TIMING_DRIVEN_PLACE; 00519 break; 00520 default: 00521 Error(*PrevArgs); 00522 } 00523 00524 return Args; 00525 } 00526 00527 static const char *const * 00528 ReadFixPins(INP const char *const *Args, 00529 OUTP char **PinFile) 00530 { 00531 enum e_OptionArgToken Token; 00532 int Len; 00533 const char *const *PrevArgs = Args; 00534 00535 Args = ReadToken(Args, &Token); 00536 if(OT_RANDOM != Token) 00537 { 00538 Len = 1 + strlen(*PrevArgs); 00539 *PinFile = (char *)my_malloc(Len * sizeof(char)); 00540 memcpy(*PinFile, *PrevArgs, Len); 00541 } 00542 return Args; 00543 } 00544 00545 00546 static const char *const * 00547 ReadOnOff(INP const char *const *Args, 00548 OUTP boolean * Val) 00549 { 00550 enum e_OptionArgToken Token; 00551 const char *const *PrevArgs; 00552 00553 PrevArgs = Args; 00554 Args = ReadToken(Args, &Token); 00555 switch (Token) 00556 { 00557 case OT_ON: 00558 *Val = TRUE; 00559 break; 00560 case OT_OFF: 00561 *Val = FALSE; 00562 break; 00563 default: 00564 Error(*PrevArgs); 00565 } 00566 return Args; 00567 } 00568 00569 00570 static const char *const * 00571 ReadInt(INP const char *const *Args, 00572 OUTP int *Val) 00573 { 00574 if(NULL == *Args) 00575 Error(*Args); 00576 if((**Args > '9') || (**Args < '0')) 00577 Error(*Args); 00578 00579 *Val = atoi(*Args); 00580 00581 return ++Args; 00582 } 00583 00584 00585 static const char *const * 00586 ReadFloat(INP const char *const *Args, 00587 OUTP float *Val) 00588 { 00589 if(NULL == *Args) 00590 { 00591 Error(*Args); 00592 } 00593 00594 if((**Args != '-') && 00595 (**Args != '.') && ((**Args > '9') || (**Args < '0'))) 00596 { 00597 Error(*Args); 00598 } 00599 00600 *Val = atof(*Args); 00601 00602 return ++Args; 00603 } 00604 00605 00606 static const char *const * 00607 ReadString(INP const char *const *Args, 00608 OUTP char **Val) 00609 { 00610 if(NULL == *Args) 00611 { 00612 Error(*Args); 00613 } 00614 00615 *Val = my_strdup(*Args); 00616 00617 return ++Args; 00618 }