VPR-6.0

vpr/SRC/base/SetupVPR.h File Reference

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

boolean IsTimingEnabled (INP t_options Options)
void SetupVPR (INP t_options Options, INP boolean TimingEnabled, OUTP struct s_file_name_opts *FileNameOpts, OUTP t_arch *Arch, OUTP enum e_operation *Operation, OUTP t_model **user_models, OUTP t_model **library_models, OUTP struct s_packer_opts *PackerOpts, OUTP struct s_placer_opts *PlacerOpts, OUTP struct s_annealing_sched *AnnealSched, OUTP struct s_router_opts *RouterOpts, OUTP struct s_det_routing_arch *RoutingArch, OUTP t_segment_inf **Segments, OUTP t_timing_inf *Timing, OUTP boolean *ShowGraphics, OUTP int *GraphPause)
void CheckSetup (INP enum e_operation Operation, INP struct s_placer_opts PlacerOpts, INP struct s_annealing_sched AnnealSched, INP struct s_router_opts RouterOpts, INP struct s_det_routing_arch RoutingArch, INP t_segment_inf *Segments, INP t_timing_inf Timing, INP t_chan_width_dist Chans)
void CheckArch (INP t_arch Arch, INP boolean TimingEnabled)
void CheckOptions (INP t_options Options, INP boolean TimingEnabled)
void ShowSetup (INP t_options Options, INP t_arch Arch, INP boolean TimingEnabled, INP enum e_operation Operation, INP struct s_file_name_opts FileNameOpts, INP struct s_placer_opts PlacerOpts, INP struct s_annealing_sched AnnealSched, INP struct s_router_opts RouterOpts, INP struct s_det_routing_arch RoutingArch, INP t_segment_inf *Segments, INP t_timing_inf Timing)

Function Documentation

void CheckArch ( INP t_arch  Arch,
INP boolean  TimingEnabled 
)

Definition at line 19 of file CheckArch.c.

{
        CheckSwitches(Arch, TimingEnabled);
        CheckSegments(Arch);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void CheckOptions ( INP t_options  Options,
INP boolean  TimingEnabled 
)

Checks that options don't conflict and that options aren't specified that may conflict.

Definition at line 14 of file CheckOptions.c.

{
    boolean TimingPlacer;
    boolean TimingRouter;
        boolean default_flow;

        default_flow = (Options.Count[OT_ROUTE] == 0 && Options.Count[OT_PLACE] == 0 && Options.Count[OT_PACK] == 0 && Options.Count[OT_TIMING_ANALYZE_ONLY_WITH_NET_DELAY] == 0);
    const struct s_TokenPair *Cur;
    enum e_OptionBaseToken Yes;

    /* Check that all filenames were given */
        if((NULL == Options.CircuitName) ||
       (NULL == Options.ArchFile))
        {
            printf(ERRTAG "Not enough args. Need at least 'vpr "
                   "<archfile> <circuit_name>'\n");
            exit(1);
        }

    /* Check that options aren't over specified */
    Cur = OptionBaseTokenList;
    while(Cur->Str)
        {
            if(Options.Count[Cur->Enum] > 1)
                {
                    printf(ERRTAG "Parameter '%s' was specified more than "
                           "once on command line.\n", Cur->Str);
                    exit(1);
                }
            ++Cur;
        }

        /* Todo: Add in checks for packer   */

    /* Check for conflicting parameters and determine if placer and 
     * router are on. */
    
    if(Options.Count[OT_TIMING_ANALYZE_ONLY_WITH_NET_DELAY] && (Options.Count[OT_PACK] || Options.Count[OT_PLACE] || Options.Count[OT_ROUTE]))
        {
            printf(ERRTAG "'cluster'/'route'/'place', and "
                   "'timing_analysis_only_with_net_delay' are mutually "
                   "exclusive flags\n");
            exit(1);
        }

    /* If placing and timing is enabled, default to a timing placer */
    TimingPlacer = ((Options.Count[OT_PLACE] || default_flow) && TimingEnabled);
    if(Options.Count[OT_PLACE_ALGORITHM] > 0)
        {
            if((PATH_TIMING_DRIVEN_PLACE != Options.PlaceAlgorithm) &&
               (NET_TIMING_DRIVEN_PLACE != Options.PlaceAlgorithm))
                {
                    /* Turn off the timing placer if they request a different placer */
                    TimingPlacer = FALSE;
                }
        }

    /* If routing and timing is enabled, default to a timing router */
    TimingRouter = ((Options.Count[OT_ROUTE] || default_flow) && TimingEnabled);
    if(Options.Count[OT_ROUTER_ALGORITHM] > 0)
        {
            if(TIMING_DRIVEN != Options.RouterAlgorithm)
                {
                    /* Turn off the timing router if they request a different router */
                    TimingRouter = FALSE;
                }
        }

    Yes = OT_BASE_UNKNOWN;
    if(Options.Count[OT_SEED] > 0)
        {
            Yes = OT_SEED;
        }
    if(Options.Count[OT_INNER_NUM] > 0)
        {
            Yes = OT_INNER_NUM;
        }
    if(Options.Count[OT_INIT_T] > 0)
        {
            Yes = OT_INIT_T;
        }
    if(Options.Count[OT_ALPHA_T] > 0)
        {
            Yes = OT_ALPHA_T;
        }
    if(Options.Count[OT_EXIT_T] > 0)
        {
            Yes = OT_EXIT_T;
        }
    if(Options.Count[OT_FIX_PINS] > 0)
        {
            Yes = OT_FIX_PINS;
        }
    if(Options.Count[OT_PLACE_ALGORITHM] > 0)
        {
            Yes = OT_PLACE_ALGORITHM;
        }
    if(Options.Count[OT_PLACE_COST_TYPE] > 0)
        {
            Yes = OT_PLACE_COST_TYPE;
        }
    if(Options.Count[OT_PLACE_COST_EXP] > 0)
        {
            Yes = OT_PLACE_COST_EXP;
        }
    if(Options.Count[OT_PLACE_CHAN_WIDTH] > 0)
        {
            Yes = OT_PLACE_CHAN_WIDTH;
        }
    if(Options.Count[OT_NUM_REGIONS] > 0)
        {
            Yes = OT_NUM_REGIONS;
        }
    if(Options.Count[OT_ENABLE_TIMING_COMPUTATIONS] > 0)
        {
            Yes = OT_ENABLE_TIMING_COMPUTATIONS;
        }
    if(Options.Count[OT_BLOCK_DIST] > 0)
        {
            Yes = OT_BLOCK_DIST;
        }
    /* Make sure if place is off none of those options were given */
    if((Options.Count[OT_PLACE] == 0) && !default_flow && (Yes < OT_BASE_UNKNOWN))
        {
            Cur = OptionBaseTokenList;
            while(Cur->Str)
                {
                    if(Yes == Cur->Enum)
                        {
                            printf(ERRTAG
                                   "Option '%s' is not allowed when placement is "
                                   "not run.\n", Cur->Str);
                            exit(1);
                        }
                    ++Cur;
                }
        }

    Yes = OT_BASE_UNKNOWN;
    if(Options.Count[OT_TIMING_TRADEOFF] > 0)
        {
            Yes = OT_TIMING_TRADEOFF;
        }
    if(Options.Count[OT_RECOMPUTE_CRIT_ITER] > 0)
        {
            Yes = OT_RECOMPUTE_CRIT_ITER;
        }
    if(Options.Count[OT_INNER_LOOP_RECOMPUTE_DIVIDER] > 0)
        {
            Yes = OT_INNER_LOOP_RECOMPUTE_DIVIDER;
        }
    if(Options.Count[OT_TD_PLACE_EXP_FIRST] > 0)
        {
            Yes = OT_TD_PLACE_EXP_FIRST;
        }
    if(Options.Count[OT_TD_PLACE_EXP_LAST] > 0)
        {
            Yes = OT_TD_PLACE_EXP_LAST;
        }
    /* Make sure if place is off none of those options were given */
    if((FALSE == TimingPlacer) && (Yes < OT_BASE_UNKNOWN))
        {
            Cur = OptionBaseTokenList;
            while(Cur->Str)
                {
                    if(Yes == Cur->Enum)
                        {
                            printf(ERRTAG
                                   "Option '%s' is not allowed when timing placement is "
                                   "not used.\n", Cur->Str);
                            exit(1);
                        }
                    ++Cur;
                }
        }

    Yes = OT_BASE_UNKNOWN;
    if(Options.Count[OT_ROUTE_TYPE] > 0)
        {
            Yes = OT_ROUTE_TYPE;
        }
    if(Options.Count[OT_ROUTE_CHAN_WIDTH] > 0)
        {
            Yes = OT_ROUTE_CHAN_WIDTH;
        }
    if(Options.Count[OT_ROUTER_ALGORITHM] > 0)
        {
            Yes = OT_ROUTER_ALGORITHM;
        }
    if(Options.Count[OT_MAX_ROUTER_ITERATIONS] > 0)
        {
            Yes = OT_MAX_ROUTER_ITERATIONS;
        }
    if(Options.Count[OT_INITIAL_PRES_FAC] > 0)
        {
            Yes = OT_INITIAL_PRES_FAC;
        }
    if(Options.Count[OT_FIRST_ITER_PRES_FAC] > 0)
        {
            Yes = OT_FIRST_ITER_PRES_FAC;
        }
    if(Options.Count[OT_PRES_FAC_MULT] > 0)
        {
            Yes = OT_PRES_FAC_MULT;
        }
    if(Options.Count[OT_ACC_FAC] > 0)
        {
            Yes = OT_ACC_FAC;
        }
    if(Options.Count[OT_BB_FACTOR] > 0)
        {
            Yes = OT_BB_FACTOR;
        }
    if(Options.Count[OT_BASE_COST_TYPE] > 0)
        {
            Yes = OT_BASE_COST_TYPE;
        }
    if(Options.Count[OT_BEND_COST] > 0)
        {
            Yes = OT_BEND_COST;
        }
    if(Options.Count[OT_BASE_COST_TYPE] > 0)
        {
            Yes = OT_BASE_COST_TYPE;
        }
    if(Options.Count[OT_ASTAR_FAC] > 0)
        {
            Yes = OT_ASTAR_FAC;
        }
    Yes = OT_BASE_UNKNOWN;
    if(Options.Count[OT_MAX_CRITICALITY] > 0)
        {
            Yes = OT_MAX_CRITICALITY;
        }
    if(Options.Count[OT_CRITICALITY_EXP] > 0)
        {
            Yes = OT_CRITICALITY_EXP;
        }
    /* Make sure if timing router is off none of those options were given */
    if((FALSE == TimingRouter) && (Yes < OT_BASE_UNKNOWN))
        {
            Cur = OptionBaseTokenList;
            while(Cur->Str)
                {
                    if(Yes == Cur->Enum)
                        {
                            printf(ERRTAG
                                   "Option '%s' is not allowed when timing router is "
                                   "not used.\n", Cur->Str);
                            exit(1);
                        }
                    ++Cur;
                }
        }
}

Here is the caller graph for this function:

void CheckSetup ( INP enum e_operation  Operation,
INP struct s_placer_opts  PlacerOpts,
INP struct s_annealing_sched  AnnealSched,
INP struct s_router_opts  RouterOpts,
INP struct s_det_routing_arch  RoutingArch,
INP t_segment_inf Segments,
INP t_timing_inf  Timing,
INP t_chan_width_dist  Chans 
)

Definition at line 11 of file CheckSetup.c.

{
    int i;
    int Tmp;

    if((NONLINEAR_CONG == PlacerOpts.place_cost_type) &&
       (!PlacerOpts.doPlacement || !RouterOpts.doRouting) &&
       (PLACE_ALWAYS == PlacerOpts.place_freq))
        {
            printf(ERRTAG "Replacing using the nonlinear congestion option "
                   "for each channel width makes sense only for full "
                   "place and route.\n");
            exit(1);
        }

    if((NONLINEAR_CONG == PlacerOpts.place_cost_type) &&
       (BOUNDING_BOX_PLACE != PlacerOpts.place_algorithm))
        {

            /* Note that this may work together, but I have not tested it */
            printf(ERRTAG
                   "Cannot use non-linear placement only supported with "
                   "bounding box placement\n");
            exit(1);
        }

    if((GLOBAL == RouterOpts.route_type) &&
       (TIMING_DRIVEN == RouterOpts.router_algorithm))
        {

            printf(ERRTAG "The global router does not support timing-drvien "
                   "routing.\n");
            exit(1);
        }

    if((GLOBAL == RouterOpts.route_type) &&
       (BOUNDING_BOX_PLACE != PlacerOpts.place_algorithm))
        {

            /* Works, but very weird.  Can't optimize timing well, since you're
             * not doing proper architecture delay modelling. */
            printf(WARNTAG
                   "Using global routing with timing-driven placement. "
                   "This is allowed, but strange, and circuit speed will suffer.\n");
        }

    if((FALSE == Timing.timing_analysis_enabled) &&
       ((PlacerOpts.place_algorithm == NET_TIMING_DRIVEN_PLACE) ||
        (PlacerOpts.place_algorithm == PATH_TIMING_DRIVEN_PLACE)))
        {

            /* May work, not tested */
            printf(ERRTAG
                   "Timing analysis must be enabled for timing-driven placement\n");
            exit(1);
        }

    if(!PlacerOpts.doPlacement && (USER == PlacerOpts.pad_loc_type))
        {
            printf(ERRTAG "A pad location file requires that placement is enabled.\n");
            exit(1);
        }

    if(RouterOpts.doRouting)
        {
            if((TIMING_DRIVEN == RouterOpts.router_algorithm) &&
               (FALSE == Timing.timing_analysis_enabled))
                {
                    printf(ERRTAG
                           "Cannot perform timing-driven routing when timing "
                           "analysis is disabled.\n");
                    exit(1);
                }

            if((FALSE == Timing.timing_analysis_enabled) &&
               (DEMAND_ONLY != RouterOpts.base_cost_type))
                {
                    printf(ERRTAG
                           "base_cost_type must be demand_only when timing "
                           "analysis is disabled.\n");
                    exit(1);
                }
        }

    if((TIMING_ANALYSIS_ONLY == Operation) &&
       (FALSE == Timing.timing_analysis_enabled))
        {
            printf(ERRTAG
                   "-timing_analyze_only_with_net_delay option requires "
                   "that timing analysis not be disabled.\n");
            exit(1);
        }

    if((NONLINEAR_CONG == PlacerOpts.place_cost_type) &&
       ((PlacerOpts.num_regions > nx) || (PlacerOpts.num_regions > ny)))
        {
            printf(ERRTAG "Cannot use more regions than clbs in "
                   "placement cost function.\n");
            exit(1);
        }

    if(DETAILED == RouterOpts.route_type)
        {
            if((Chans.chan_x_dist.type != UNIFORM) ||
               (Chans.chan_y_dist.type != UNIFORM) ||
               (Chans.chan_x_dist.peak != Chans.chan_y_dist.peak) ||
               (Chans.chan_x_dist.peak != Chans.chan_width_io))
                {
                    printf(ERRTAG "Detailed routing currently only supported "
                           "on FPGAs with all channels of equal width.\n");
                    exit(1);
                }
        }

    for(i = 0; i < RoutingArch.num_segment; ++i)
        {
            Tmp = Segments[i].opin_switch;
            if(FALSE == switch_inf[Tmp].buffered)
                {
                    printf(ERRTAG "opin_switch (#%d) of segment type #%d "
                           "is not buffered.\n", Tmp, i);
                    exit(1);
                }
        }

    if(UNI_DIRECTIONAL == RoutingArch.directionality)
        {
            if((RouterOpts.fixed_channel_width != NO_FIXED_CHANNEL_WIDTH) &&
               (RouterOpts.fixed_channel_width % 2 > 0))
                {
                    printf(ERRTAG
                           "Routing channel width must be even for unidirectional\n");
                    exit(1);
                }
            if((PlacerOpts.place_chan_width != NO_FIXED_CHANNEL_WIDTH) &&
               (PlacerOpts.place_chan_width % 2 > 0))
                {
                    printf(ERRTAG
                           "Place channel width must be even for unidirectional\n");
                    exit(1);
                }
        }
}

Here is the caller graph for this function:

boolean IsTimingEnabled ( INP t_options  Options)

Determines whether timing analysis should be on or off. Unless otherwise specified, always default to timing.

Definition at line 814 of file SetupVPR.c.

{
    /* First priority to the '--timing_analysis' flag */
    if(Options.Count[OT_TIMING_ANALYSIS])
        {
            return Options.TimingAnalysis;
        }
    return TRUE;
}

Here is the caller graph for this function:

void SetupVPR ( INP t_options  Options,
INP boolean  TimingEnabled,
OUTP struct s_file_name_opts FileNameOpts,
OUTP t_arch Arch,
OUTP enum e_operation Operation,
OUTP t_model **  user_models,
OUTP t_model **  library_models,
OUTP struct s_packer_opts PackerOpts,
OUTP struct s_placer_opts PlacerOpts,
OUTP struct s_annealing_sched AnnealSched,
OUTP struct s_router_opts RouterOpts,
OUTP struct s_det_routing_arch RoutingArch,
OUTP t_segment_inf **  Segments,
OUTP t_timing_inf Timing,
OUTP boolean ShowGraphics,
OUTP int *  GraphPause 
)

Sets VPR parameters and defaults. Does not do any error checking as this should have been done by the various input checkers

Definition at line 45 of file SetupVPR.c.

{
        int i, j, len;

        
        /* init default filenames */
        if(Options.BlifFile == NULL) {
                len = strlen(Options.CircuitName) + 6; /* circuit_name.blif/0*/
                if(Options.OutFilePrefix != NULL) {
                        len += strlen(Options.OutFilePrefix);
                }
                Options.BlifFile = my_calloc(len,sizeof(char));
                if(Options.OutFilePrefix == NULL) {
                        sprintf(Options.BlifFile, "%s.blif", Options.CircuitName);
                } else {
                        sprintf(Options.BlifFile, "%s%s.blif", Options.OutFilePrefix, Options.CircuitName);
                }
        }
        
        if(Options.NetFile == NULL) {
                len = strlen(Options.CircuitName) + 5; /* circuit_name.net/0*/
                if(Options.OutFilePrefix != NULL) {
                        len += strlen(Options.OutFilePrefix);
                }
                Options.NetFile = my_calloc(len,sizeof(char));
                if(Options.OutFilePrefix == NULL) {
                        sprintf(Options.NetFile, "%s.net", Options.CircuitName);
                } else {
                        sprintf(Options.NetFile, "%s%s.net", Options.OutFilePrefix, Options.CircuitName);
                }
        }

        if(Options.PlaceFile == NULL) {
                len = strlen(Options.CircuitName) + 7; /* circuit_name.place/0*/
                if(Options.OutFilePrefix != NULL) {
                        len += strlen(Options.OutFilePrefix);
                }
                Options.PlaceFile = my_calloc(len,sizeof(char));
                if(Options.OutFilePrefix == NULL) {
                        sprintf(Options.PlaceFile, "%s.place", Options.CircuitName);
                } else {
                        sprintf(Options.PlaceFile, "%s%s.place", Options.OutFilePrefix, Options.CircuitName);
                }
        }

        if(Options.RouteFile == NULL) {
                len = strlen(Options.CircuitName) + 7; /* circuit_name.route/0*/
                if(Options.OutFilePrefix != NULL) {
                        len += strlen(Options.OutFilePrefix);
                }
                Options.RouteFile = my_calloc(len,sizeof(char));
                if(Options.OutFilePrefix == NULL) {
                        sprintf(Options.RouteFile, "%s.route", Options.CircuitName);
                } else {
                        sprintf(Options.RouteFile, "%s%s.route", Options.OutFilePrefix, Options.CircuitName);
                }
        }

        FileNameOpts->CircuitName = Options.CircuitName;
        FileNameOpts->ArchFile = Options.ArchFile;
        FileNameOpts->BlifFile = Options.BlifFile;
        FileNameOpts->NetFile = Options.NetFile;
        FileNameOpts->PlaceFile = Options.PlaceFile;
        FileNameOpts->RouteFile = Options.RouteFile;    
        FileNameOpts->OutFilePrefix = Options.OutFilePrefix;    

    SetupOperation(Options, Operation);
    SetupPlacerOpts(Options, TimingEnabled, PlacerOpts);
    SetupAnnealSched(Options, AnnealSched);
    SetupRouterOpts(Options, TimingEnabled, RouterOpts);

    XmlReadArch(Options.ArchFile, TimingEnabled, Arch,
                &type_descriptors, &num_types);

        *user_models = Arch->models;
        *library_models = Arch->model_library;
        
        /* TODO: this is inelegant, I should be populating this information in XmlReadArch */
        EMPTY_TYPE = NULL;
        FILL_TYPE = NULL;
        IO_TYPE = NULL;
        for(i = 0; i < num_types; i++) {
                if(strcmp(type_descriptors[i].name, "<EMPTY>") == 0) {
                        EMPTY_TYPE = &type_descriptors[i];
                } else if(strcmp(type_descriptors[i].name, "io") == 0) {
                        IO_TYPE = &type_descriptors[i];
                } else {
                        for(j = 0; j < type_descriptors[i].num_grid_loc_def; j++) {
                                if(type_descriptors[i].grid_loc_def[j].grid_loc_type == FILL) {
                                        assert(FILL_TYPE == NULL);
                                        FILL_TYPE = &type_descriptors[i];
                                }
                        }
                }

        }
        assert(EMPTY_TYPE != NULL && FILL_TYPE != NULL && IO_TYPE != NULL);


    *Segments = Arch->Segments;
    RoutingArch->num_segment = Arch->num_segments;

    SetupSwitches(*Arch, RoutingArch, Arch->Switches, Arch->num_switches);
    SetupRoutingArch(*Arch, RoutingArch);
    SetupTiming(Options, *Arch, TimingEnabled, *Operation,
                *PlacerOpts, *RouterOpts, Timing);
        SetupPackerOpts(Options, TimingEnabled, *Arch, Options.NetFile, PackerOpts);

    /* init global variables */
        OutFilePrefix = Options.OutFilePrefix;
    grid_logic_tile_area = Arch->grid_logic_tile_area;
    ipin_mux_trans_size = Arch->ipin_mux_trans_size;


    /* Set seed for pseudo-random placement, default seed to 1 */
    PlacerOpts->seed = 1;
    if(Options.Count[OT_SEED])
        {
            PlacerOpts->seed = Options.Seed;
        }
    my_srandom(PlacerOpts->seed);

        
        printf("Building complex block graph \n");
        alloc_and_load_all_pb_graphs();
        #ifdef DUMP_PB_GRAPH
                echo_pb_graph("pb_graph.echo");
        #endif


    *GraphPause = 1;            /* DEFAULT */
    if(Options.Count[OT_AUTO])
        {
            *GraphPause = Options.GraphPause;
        }
#ifdef NO_GRAPHICS
    *ShowGraphics = FALSE;      /* DEFAULT */
#else /* NO_GRAPHICS */
    *ShowGraphics = TRUE;       /* DEFAULT */
    if(Options.Count[OT_NODISP])
        {
            *ShowGraphics = FALSE;
        }
#endif /* NO_GRAPHICS */

#ifdef CREATE_ECHO_FILES
    EchoArch("arch.echo", type_descriptors, num_types, Arch);
#endif
        
}

Here is the call graph for this function:

Here is the caller graph for this function:

void ShowSetup ( INP t_options  Options,
INP t_arch  Arch,
INP boolean  TimingEnabled,
INP enum e_operation  Operation,
INP struct s_file_name_opts  FileNameOpts,
INP struct s_placer_opts  PlacerOpts,
INP struct s_annealing_sched  AnnealSched,
INP struct s_router_opts  RouterOpts,
INP struct s_det_routing_arch  RoutingArch,
INP t_segment_inf Segments,
INP t_timing_inf  Timing 
)

Definition at line 24 of file ShowSetup.c.

{
    int i, j, num_p_inputs, num_p_outputs;
        int *num_blocks_type; 
        num_blocks_type = my_calloc(num_types, sizeof(int));

    printf("Timing analysis: %s\n", (TimingEnabled ? "ON" : "OFF"));
    printf("\n");

        printf("Circuit netlist file: %s\n", FileNameOpts.NetFile);
        printf("Circuit placement file: %s\n", FileNameOpts.PlaceFile);
        printf("Circuit routing file: %s\n", FileNameOpts.RouteFile);

    ShowOperation(Operation);
        printf("Placer: %s\n", (PlacerOpts.doPlacement ? "ENABLED" : "DISABLED"));
        printf("Router: %s\n", (RouterOpts.doRouting ? "ENABLED" : "DISABLED"));
    
        if(PlacerOpts.doPlacement) {
                ShowPlacerOpts(Options, PlacerOpts, AnnealSched);
        }
    if(RouterOpts.doRouting)
        {
            ShowRouterOpts(RouterOpts);
        }

    if(DETAILED == RouterOpts.route_type)
                ShowRoutingArch(RoutingArch);

    printf("\n");
    printf("Netlist num_nets:  %d\n", num_nets);
    printf("Netlist num_blocks:  %d\n", num_blocks);

        for(i = 0; i < num_types; i++)
        {
                num_blocks_type[i] = 0;
        }
    /* Count I/O input and output pads */
    num_p_inputs = 0;
    num_p_outputs = 0;

        for(i = 0; i < num_blocks; i++)
        {
                num_blocks_type[block[i].type->index]++;
                if(block[i].type == IO_TYPE)
                {
                    for(j = 0; j < IO_TYPE->num_pins; j++)
                        {
                            if(block[i].nets[j] != OPEN)
                                {
                                    if(IO_TYPE->
                                       class_inf[IO_TYPE->pin_class[j]].
                                       type == DRIVER)
                                        {
                                            num_p_inputs++;
                                        }
                                    else
                                        {
                                            assert(IO_TYPE->
                                                   class_inf[IO_TYPE->
                                                             pin_class[j]].
                                                   type == RECEIVER);
                                            num_p_outputs++;
                                        }
                                }
                        }
                }
        }

        for(i = 0; i < num_types; i++)
        {
                if(IO_TYPE != &type_descriptors[i]) {
                        printf("Netlist %s blocks:  %d\n", type_descriptors[i].name, num_blocks_type[i]);
                }
        }

        /* Print out each block separately instead */
    printf("Netlist inputs pins:  %d\n", num_p_inputs);
    printf("Netlist output pins:  %d\n", num_p_outputs);
    printf("\n");
        free(num_blocks_type);
}

Here is the call graph for this function:

Here is the caller graph for this function: