blob: 649245e35d164472b011314a01432daaa08975dd [file] [log] [blame]
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "util.h"
#include "vpr_types.h"
#include "OptionTokens.h"
#include "ReadOptions.h"
/******** Function prototypes ********/
static const char *const *ReadBaseToken(INP const char *const *Args,
OUTP enum e_OptionBaseToken *Token);
static void Error(INP const char *Token);
static void ErrorOption(INP const char *Option);
static const char *const *ProcessOption(INP const char *const *Args,
INOUTP t_options * Options);
static const char *const *ReadFloat(INP const char *const *Args,
OUTP float *Val);
static const char *const *ReadInt(INP const char *const *Args,
OUTP int *Val);
static const char *const *ReadOnOff(INP const char *const *Args,
OUTP boolean * Val);
static const char *const *ReadClusterSeed(INP const char *const *Args,
OUTP enum e_cluster_seed *Type);
static const char *const *ReadFixPins(INP const char *const *Args,
OUTP char **PinFile);
static const char *const *ReadPlaceAlgorithm(INP const char *const *Args,
OUTP enum e_place_algorithm
*Algo);
static const char *const *ReadPlaceCostType(INP const char *const *Args,
OUTP enum place_c_types *Type);
static const char *const *ReadRouterAlgorithm(INP const char *const *Args,
OUTP enum e_router_algorithm
*Algo);
static const char *const *ReadPackerAlgorithm(INP const char *const *Args,
OUTP enum e_packer_algorithm
*Algo);
static const char *const *ReadBaseCostType(INP const char *const *Args,
OUTP enum e_base_cost_type *BaseCostType);
static const char *const *ReadRouteType(INP const char *const *Args,
OUTP enum e_route_type *Type);
static const char *const *ReadString(INP const char *const *Args,
OUTP char **Val);
/******** Subroutine implementations ********/
void
ReadOptions(INP int argc,
INP char **argv,
OUTP t_options * Options)
{
char **Args, **head;
/* 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 =
(char **)ProcessOption((const char *const *)Args,
Options);
}
else if(strncmp("-", *Args, 1) == 0)
{
*Args += 1; /* Skip the prefix */
Args =
(char **)ProcessOption((const char *const *)Args,
Options);
}
else if(NULL == Options->ArchFile)
{
Options->ArchFile = my_strdup(*Args);
++Args;
}
else if(NULL == Options->CircuitName)
{
Options->CircuitName = my_strdup(*Args);
++Args;
}
else
{
/* Not an option and arch and net already specified so fail */
Error(*Args);
}
}
free(head);
}
static const char *const *
ProcessOption(INP const char *const *Args,
INOUTP t_options * Options)
{
enum e_OptionBaseToken Token;
const char *const *PrevArgs;
PrevArgs = Args;
Args = ReadBaseToken(Args, &Token);
if(Token < OT_BASE_UNKNOWN)
{
++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);
/* 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->OutFilePrefix);
/* 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);
case OT_HACK_NO_LEGAL_FRAC_LUT:
return Args;
case OT_HACK_SAFE_LATCH:
return Args;
/* 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_COST_TYPE:
return ReadPlaceCostType(Args, &Options->PlaceCostType);
case OT_PLACE_CHAN_WIDTH:
return ReadInt(Args, &Options->PlaceChanWidth);
case OT_NUM_REGIONS:
return ReadInt(Args, &Options->PlaceNonlinearRegions);
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);
default:
ErrorOption(*PrevArgs);
}
return NULL;
}
static const char *const *
ReadBaseToken(INP const char *const *Args,
OUTP enum e_OptionBaseToken *Token)
{
const 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 = Cur->Enum;
return ++Args;
}
++Cur;
}
*Token = OT_BASE_UNKNOWN;
return ++Args;
}
static const char *const *
ReadToken(INP const char *const *Args,
OUTP enum e_OptionArgToken *Token)
{
const 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 = 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)
{
printf(ERRTAG "Unexpected token '%s' on command line\n", Token);
}
else
{
printf(ERRTAG "Missing token at end of command line\n");
}
exit(1);
}
static void
ErrorOption(INP const char *Option)
{
printf(ERRTAG "Unexpected option '%s' on command line\n", Option);
exit(1);
}
static const char *const *
ReadClusterSeed(INP const char *const *Args,
OUTP enum e_cluster_seed *Type)
{
enum e_OptionArgToken Token;
const char *const *PrevArgs;
PrevArgs = Args;
Args = ReadToken(Args, &Token);
switch (Token)
{
case OT_TIMING:
*Type = VPACK_TIMING;
break;
case OT_MAX_INPUTS:
*Type = NONLINEAR_CONG;
break;
default:
Error(*PrevArgs);
}
return Args;
}
static const char *const *
ReadPackerAlgorithm(INP const char *const *Args,
OUTP enum e_packer_algorithm *Algo)
{
enum e_OptionArgToken Token;
const char *const *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 const char *const *
ReadRouterAlgorithm(INP const char *const *Args,
OUTP enum e_router_algorithm *Algo)
{
enum e_OptionArgToken Token;
const char *const *PrevArgs;
PrevArgs = Args;
Args = ReadToken(Args, &Token);
switch (Token)
{
case OT_BREADTH_FIRST:
*Algo = BREADTH_FIRST;
break;
case OT_DIRECTED_SEARCH:
*Algo = DIRECTED_SEARCH;
break;
case OT_TIMING_DRIVEN:
*Algo = TIMING_DRIVEN;
break;
default:
Error(*PrevArgs);
}
return Args;
}
static const char *const *
ReadBaseCostType(INP const char *const *Args,
OUTP enum e_base_cost_type *BaseCostType)
{
enum e_OptionArgToken Token;
const char *const *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 const char *const *
ReadRouteType(INP const char *const *Args,
OUTP enum e_route_type *Type)
{
enum e_OptionArgToken Token;
const char *const *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 const char *const *
ReadPlaceCostType(INP const char *const *Args,
OUTP enum place_c_types *Type)
{
enum e_OptionArgToken Token;
const char *const *PrevArgs;
PrevArgs = Args;
Args = ReadToken(Args, &Token);
switch (Token)
{
case OT_LINEAR:
*Type = LINEAR_CONG;
break;
case OT_NONLINEAR:
*Type = NONLINEAR_CONG;
break;
default:
Error(*PrevArgs);
}
return Args;
}
static const char *const *
ReadPlaceAlgorithm(INP const char *const *Args,
OUTP enum e_place_algorithm *Algo)
{
enum e_OptionArgToken Token;
const char *const *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 const char *const *
ReadFixPins(INP const char *const *Args,
OUTP char **PinFile)
{
enum e_OptionArgToken Token;
int Len;
const char *const *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 const char *const *
ReadOnOff(INP const char *const *Args,
OUTP boolean * Val)
{
enum e_OptionArgToken Token;
const char *const *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 const char *const *
ReadInt(INP const char *const *Args,
OUTP int *Val)
{
if(NULL == *Args)
Error(*Args);
if((**Args > '9') || (**Args < '0'))
Error(*Args);
*Val = atoi(*Args);
return ++Args;
}
static const char *const *
ReadFloat(INP const char *const *Args,
OUTP float *Val)
{
if(NULL == *Args)
{
Error(*Args);
}
if((**Args != '-') &&
(**Args != '.') && ((**Args > '9') || (**Args < '0')))
{
Error(*Args);
}
*Val = atof(*Args);
return ++Args;
}
static const char *const *
ReadString(INP const char *const *Args,
OUTP char **Val)
{
if(NULL == *Args)
{
Error(*Args);
}
*Val = my_strdup(*Args);
return ++Args;
}