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
00010
00011 static const char *const *ReadBaseToken(IN const char *const *Args,
00012 OUT enum e_OptionBaseToken *Token);
00013 static void Error(IN const char *Token);
00014 static void ErrorOption(IN const char *Option);
00015 static const char *const *ProcessOption(IN const char *const *Args,
00016 INOUT t_options * Options);
00017 static const char *const *ReadFloat(IN const char *const *Args,
00018 OUT float *Val);
00019 static const char *const *ReadInt(IN const char *const *Args,
00020 OUT int *Val);
00021 static const char *const *ReadOnOff(IN const char *const *Args,
00022 OUT boolean * Val);
00023 static const char *const *ReadFixPins(IN const char *const *Args,
00024 OUT char **PinFile);
00025 static const char *const *ReadPlaceAlgorithm(IN const char *const *Args,
00026 OUT enum e_place_algorithm
00027 *Algo);
00028 static const char *const *ReadPlaceCostType(IN const char *const *Args,
00029 OUT enum place_c_types *Type);
00030 static const char *const *ReadRouterAlgorithm(IN const char *const *Args,
00031 OUT enum e_router_algorithm
00032 *Algo);
00033 static const char *const *ReadBaseCostType(IN const char *const *Args,
00034 OUT enum e_base_cost_type *BaseCostType);
00035 static const char *const *ReadRouteType(IN const char *const *Args,
00036 OUT enum e_route_type *Type);
00037 static const char *const *ReadString(IN const char *const *Args,
00038 OUT char **Val);
00039
00040
00041
00042
00043 void
00044 ReadOptions(IN int argc,
00045 IN char **argv,
00046 OUT t_options * Options)
00047 {
00048 char **Args, **head;
00049
00050
00051 memset(Options, 0, sizeof(t_options));
00052
00053
00054
00055
00056 --argc;
00057 ++argv;
00058 head = Args = (char **)my_malloc(sizeof(char *) * (argc + 1));
00059 memcpy(Args, argv, (sizeof(char *) * argc));
00060 Args[argc] = NULL;
00061
00062
00063
00064
00065 while(*Args)
00066 {
00067 if(strncmp("--", *Args, 2) == 0)
00068 {
00069 *Args += 2;
00070 Args =
00071 (char **)ProcessOption((const char *const *)Args,
00072 Options);
00073 }
00074 else if(strncmp("-", *Args, 1) == 0)
00075 {
00076 *Args += 1;
00077 Args =
00078 (char **)ProcessOption((const char *const *)Args,
00079 Options);
00080 }
00081 else if(NULL == Options->NetFile)
00082 {
00083 Options->NetFile = my_strdup(*Args);
00084 ++Args;
00085 }
00086 else if(NULL == Options->ArchFile)
00087 {
00088 Options->ArchFile = my_strdup(*Args);
00089 ++Args;
00090 }
00091 else if(NULL == Options->PlaceFile)
00092 {
00093 Options->PlaceFile = my_strdup(*Args);
00094 ++Args;
00095 }
00096 else if(NULL == Options->RouteFile)
00097 {
00098 Options->RouteFile = my_strdup(*Args);
00099 ++Args;
00100 }
00101 else
00102 {
00103
00104 Error(*Args);
00105 }
00106 }
00107 free(head);
00108 }
00109
00110
00111 static const char *const *
00112 ProcessOption(IN const char *const *Args,
00113 INOUT t_options * Options)
00114 {
00115 enum e_OptionBaseToken Token;
00116 const char *const *PrevArgs;
00117
00118 PrevArgs = Args;
00119 Args = ReadBaseToken(Args, &Token);
00120
00121 if(Token < OT_BASE_UNKNOWN)
00122 {
00123 ++Options->Count[Token];
00124 }
00125
00126 switch (Token)
00127 {
00128
00129 case OT_NODISP:
00130 return Args;
00131 case OT_AUTO:
00132 return ReadInt(Args, &Options->GraphPause);
00133 case OT_ROUTE_ONLY:
00134 case OT_PLACE_ONLY:
00135 return Args;
00136 case OT_TIMING_ANALYZE_ONLY_WITH_NET_DELAY:
00137 return ReadFloat(Args, &Options->constant_net_delay);
00138 case OT_FAST:
00139 case OT_FULL_STATS:
00140 return Args;
00141 case OT_TIMING_ANALYSIS:
00142 return ReadOnOff(Args, &Options->TimingAnalysis);
00143 case OT_OUTFILE_PREFIX:
00144 return ReadString(Args, &Options->OutFilePrefix);
00145
00146
00147 case OT_PLACE_ALGORITHM:
00148 return ReadPlaceAlgorithm(Args, &Options->PlaceAlgorithm);
00149 case OT_INIT_T:
00150 return ReadFloat(Args, &Options->PlaceInitT);
00151 case OT_EXIT_T:
00152 return ReadFloat(Args, &Options->PlaceExitT);
00153 case OT_ALPHA_T:
00154 return ReadFloat(Args, &Options->PlaceAlphaT);
00155 case OT_INNER_NUM:
00156 return ReadFloat(Args, &Options->PlaceInnerNum);
00157 case OT_SEED:
00158 return ReadInt(Args, &Options->Seed);
00159 case OT_PLACE_COST_EXP:
00160 return ReadFloat(Args, &Options->place_cost_exp);
00161 case OT_PLACE_COST_TYPE:
00162 return ReadPlaceCostType(Args, &Options->PlaceCostType);
00163 case OT_PLACE_CHAN_WIDTH:
00164 return ReadInt(Args, &Options->PlaceChanWidth);
00165 case OT_NUM_REGIONS:
00166 return ReadInt(Args, &Options->PlaceNonlinearRegions);
00167 case OT_FIX_PINS:
00168 return ReadFixPins(Args, &Options->PinFile);
00169 case OT_ENABLE_TIMING_COMPUTATIONS:
00170 return ReadOnOff(Args, &Options->ShowPlaceTiming);
00171 case OT_BLOCK_DIST:
00172 return ReadInt(Args, &Options->block_dist);
00173
00174
00175 case OT_TIMING_TRADEOFF:
00176 return ReadFloat(Args, &Options->PlaceTimingTradeoff);
00177 case OT_RECOMPUTE_CRIT_ITER:
00178 return ReadInt(Args, &Options->RecomputeCritIter);
00179 case OT_INNER_LOOP_RECOMPUTE_DIVIDER:
00180 return ReadInt(Args, &Options->inner_loop_recompute_divider);
00181 case OT_TD_PLACE_EXP_FIRST:
00182 return ReadFloat(Args, &Options->place_exp_first);
00183 case OT_TD_PLACE_EXP_LAST:
00184 return ReadFloat(Args, &Options->place_exp_last);
00185
00186
00187 case OT_MAX_ROUTER_ITERATIONS:
00188 return ReadInt(Args, &Options->max_router_iterations);
00189 case OT_BB_FACTOR:
00190 return ReadInt(Args, &Options->bb_factor);
00191 case OT_INITIAL_PRES_FAC:
00192 return ReadFloat(Args, &Options->initial_pres_fac);
00193 case OT_PRES_FAC_MULT:
00194 return ReadFloat(Args, &Options->pres_fac_mult);
00195 case OT_ACC_FAC:
00196 return ReadFloat(Args, &Options->acc_fac);
00197 case OT_FIRST_ITER_PRES_FAC:
00198 return ReadFloat(Args, &Options->first_iter_pres_fac);
00199 case OT_BEND_COST:
00200 return ReadFloat(Args, &Options->bend_cost);
00201 case OT_ROUTE_TYPE:
00202 return ReadRouteType(Args, &Options->RouteType);
00203 case OT_VERIFY_BINARY_SEARCH:
00204 return Args;
00205 case OT_ROUTE_CHAN_WIDTH:
00206 return ReadInt(Args, &Options->RouteChanWidth);
00207 case OT_ROUTER_ALGORITHM:
00208 return ReadRouterAlgorithm(Args, &Options->RouterAlgorithm);
00209 case OT_BASE_COST_TYPE:
00210 return ReadBaseCostType(Args, &Options->base_cost_type);
00211
00212
00213 case OT_ASTAR_FAC:
00214 return ReadFloat(Args, &Options->astar_fac);
00215 case OT_MAX_CRITICALITY:
00216 return ReadFloat(Args, &Options->max_criticality);
00217 case OT_CRITICALITY_EXP:
00218 return ReadFloat(Args, &Options->criticality_exp);
00219 default:
00220 ErrorOption(*PrevArgs);
00221 }
00222 return NULL;
00223 }
00224
00225
00226 static const char *const *
00227 ReadBaseToken(IN const char *const *Args,
00228 OUT enum e_OptionBaseToken *Token)
00229 {
00230 const struct s_TokenPair *Cur;
00231
00232
00233 if(NULL == *Args)
00234 Error(*Args);
00235
00236
00237 Cur = OptionBaseTokenList;
00238 while(Cur->Str)
00239 {
00240 if(strcmp(*Args, Cur->Str) == 0)
00241 {
00242 *Token = Cur->Enum;
00243 return ++Args;
00244 }
00245 ++Cur;
00246 }
00247
00248 *Token = OT_BASE_UNKNOWN;
00249 return ++Args;
00250 }
00251
00252
00253 static const char *const *
00254 ReadToken(IN const char *const *Args,
00255 OUT enum e_OptionArgToken *Token)
00256 {
00257 const struct s_TokenPair *Cur;
00258
00259
00260 if(NULL == *Args)
00261 Error(*Args);
00262
00263
00264 Cur = OptionArgTokenList;
00265 while(Cur->Str)
00266 {
00267 if(strcmp(*Args, Cur->Str) == 0)
00268 {
00269 *Token = Cur->Enum;
00270 return ++Args;
00271 }
00272 ++Cur;
00273 }
00274
00275 *Token = OT_ARG_UNKNOWN;
00276 return ++Args;
00277 }
00278
00279
00280
00281 static void
00282 Error(IN const char *Token)
00283 {
00284 if(Token)
00285 {
00286 printf(ERRTAG "Unexpected token '%s' on command line\n", Token);
00287 }
00288 else
00289 {
00290 printf(ERRTAG "Missing token at end of command line\n");
00291 }
00292 exit(1);
00293 }
00294
00295
00296 static void
00297 ErrorOption(IN const char *Option)
00298 {
00299 printf(ERRTAG "Unexpected option '%s' on command line\n", Option);
00300 exit(1);
00301 }
00302
00303
00304 static const char *const *
00305 ReadRouterAlgorithm(IN const char *const *Args,
00306 OUT enum e_router_algorithm *Algo)
00307 {
00308 enum e_OptionArgToken Token;
00309 const char *const *PrevArgs;
00310
00311 PrevArgs = Args;
00312 Args = ReadToken(Args, &Token);
00313 switch (Token)
00314 {
00315 case OT_BREADTH_FIRST:
00316 *Algo = BREADTH_FIRST;
00317 break;
00318 case OT_DIRECTED_SEARCH:
00319 *Algo = DIRECTED_SEARCH;
00320 break;
00321 case OT_TIMING_DRIVEN:
00322 *Algo = TIMING_DRIVEN;
00323 break;
00324 default:
00325 Error(*PrevArgs);
00326 }
00327
00328 return Args;
00329 }
00330
00331 static const char *const *
00332 ReadBaseCostType(IN const char *const *Args,
00333 OUT enum e_base_cost_type *BaseCostType)
00334 {
00335 enum e_OptionArgToken Token;
00336 const char *const *PrevArgs;
00337
00338 PrevArgs = Args;
00339 Args = ReadToken(Args, &Token);
00340 switch (Token)
00341 {
00342 case OT_INTRINSIC_DELAY:
00343 *BaseCostType = INTRINSIC_DELAY;
00344 break;
00345 case OT_DELAY_NORMALIZED:
00346 *BaseCostType = DELAY_NORMALIZED;
00347 break;
00348 case OT_DEMAND_ONLY:
00349 *BaseCostType = DEMAND_ONLY;
00350 break;
00351 default:
00352 Error(*PrevArgs);
00353 }
00354
00355 return Args;
00356 }
00357
00358
00359 static const char *const *
00360 ReadRouteType(IN const char *const *Args,
00361 OUT enum e_route_type *Type)
00362 {
00363 enum e_OptionArgToken Token;
00364 const char *const *PrevArgs;
00365
00366 PrevArgs = Args;
00367 Args = ReadToken(Args, &Token);
00368 switch (Token)
00369 {
00370 case OT_GLOBAL:
00371 *Type = GLOBAL;
00372 break;
00373 case OT_DETAILED:
00374 *Type = DETAILED;
00375 break;
00376 default:
00377 Error(*PrevArgs);
00378 }
00379
00380 return Args;
00381 }
00382
00383
00384 static const char *const *
00385 ReadPlaceCostType(IN const char *const *Args,
00386 OUT enum place_c_types *Type)
00387 {
00388 enum e_OptionArgToken Token;
00389 const char *const *PrevArgs;
00390
00391 PrevArgs = Args;
00392 Args = ReadToken(Args, &Token);
00393 switch (Token)
00394 {
00395 case OT_LINEAR:
00396 *Type = LINEAR_CONG;
00397 break;
00398 case OT_NONLINEAR:
00399 *Type = NONLINEAR_CONG;
00400 break;
00401 default:
00402 Error(*PrevArgs);
00403 }
00404
00405 return Args;
00406 }
00407
00408
00409 static const char *const *
00410 ReadPlaceAlgorithm(IN const char *const *Args,
00411 OUT enum e_place_algorithm *Algo)
00412 {
00413 enum e_OptionArgToken Token;
00414 const char *const *PrevArgs;
00415
00416 PrevArgs = Args;
00417 Args = ReadToken(Args, &Token);
00418 switch (Token)
00419 {
00420 case OT_BOUNDING_BOX:
00421 *Algo = BOUNDING_BOX_PLACE;
00422 break;
00423 case OT_NET_TIMING_DRIVEN:
00424 *Algo = NET_TIMING_DRIVEN_PLACE;
00425 break;
00426 case OT_PATH_TIMING_DRIVEN:
00427 *Algo = PATH_TIMING_DRIVEN_PLACE;
00428 break;
00429 default:
00430 Error(*PrevArgs);
00431 }
00432
00433 return Args;
00434 }
00435
00436 static const char *const *
00437 ReadFixPins(IN const char *const *Args,
00438 OUT char **PinFile)
00439 {
00440 enum e_OptionArgToken Token;
00441 int Len;
00442 const char *const *PrevArgs = Args;
00443
00444 Args = ReadToken(Args, &Token);
00445 if(OT_RANDOM != Token)
00446 {
00447 Len = 1 + strlen(*PrevArgs);
00448 *PinFile = (char *)my_malloc(Len * sizeof(char));
00449 memcpy(*PinFile, *PrevArgs, Len);
00450 }
00451 return Args;
00452 }
00453
00454
00455 static const char *const *
00456 ReadOnOff(IN const char *const *Args,
00457 OUT boolean * Val)
00458 {
00459 enum e_OptionArgToken Token;
00460 const char *const *PrevArgs;
00461
00462 PrevArgs = Args;
00463 Args = ReadToken(Args, &Token);
00464 switch (Token)
00465 {
00466 case OT_ON:
00467 *Val = TRUE;
00468 break;
00469 case OT_OFF:
00470 *Val = FALSE;
00471 break;
00472 default:
00473 Error(*PrevArgs);
00474 }
00475 return Args;
00476 }
00477
00478
00479 static const char *const *
00480 ReadInt(IN const char *const *Args,
00481 OUT int *Val)
00482 {
00483 if(NULL == *Args)
00484 Error(*Args);
00485 if((**Args > '9') || (**Args < '0'))
00486 Error(*Args);
00487
00488 *Val = atoi(*Args);
00489
00490 return ++Args;
00491 }
00492
00493
00494 static const char *const *
00495 ReadFloat(IN const char *const *Args,
00496 OUT float *Val)
00497 {
00498 if(NULL == *Args)
00499 {
00500 Error(*Args);
00501 }
00502
00503 if((**Args != '-') &&
00504 (**Args != '.') && ((**Args > '9') || (**Args < '0')))
00505 {
00506 Error(*Args);
00507 }
00508
00509 *Val = atof(*Args);
00510
00511 return ++Args;
00512 }
00513
00514
00515 static const char *const *
00516 ReadString(IN const char *const *Args,
00517 OUT char **Val)
00518 {
00519 if(NULL == *Args)
00520 {
00521 Error(*Args);
00522 }
00523
00524 *Val = my_strdup(*Args);
00525
00526 return ++Args;
00527 }