📄 main.c
字号:
if (router_opts->fixed_channel_width >= MAX_CHANNEL_WIDTH) { printf ("Error: -router_chan_width value must be less than %d." "\n", MAX_CHANNEL_WIDTH); exit (1); } i += 2; continue; } if (strcmp(argv[i],"-route_only") == 0) { if (*operation == PLACE_ONLY) { printf("Error: Both -route_only and -place_only specified.\n"); exit (1); } *operation = ROUTE_ONLY; placer_opts->place_freq = PLACE_NEVER; i++; continue; } if (strcmp(argv[i],"-place_only") == 0) { if (*operation == ROUTE_ONLY) { printf("Error: Both -route_only and -place_only specified.\n"); exit (1); } *operation = PLACE_ONLY; i++; continue; } if (strcmp(argv[i],"-verify_binary_search") == 0) { *verify_binary_search = TRUE; i++; continue; } printf("Error: Unrecognized flag: %s. Aborting.\n",argv[i]); exit(1); } /* End of giant while loop. */ /* Check for illegal options combinations. */ if (placer_opts->place_cost_type == NONLINEAR_CONG && *operation != PLACE_AND_ROUTE && do_one_nonlinear_place == FALSE) { printf("Error: Replacing using the nonlinear congestion option\n"); printf(" for each channel width makes sense only for full " "place and route.\n"); exit (1); } if (placer_opts->place_cost_type == NONLINEAR_CONG && (placer_opts->place_algorithm == NET_TIMING_DRIVEN_PLACE || placer_opts->place_algorithm == PATH_TIMING_DRIVEN_PLACE)) { /*note that this may work together, but I have not tested it */ printf("Error: Cannot use nonlinear placement with \n" " timing driven placement\n"); exit(1); } if (router_opts->route_type == GLOBAL && (placer_opts->place_algorithm == NET_TIMING_DRIVEN_PLACE || placer_opts->place_algorithm == PATH_TIMING_DRIVEN_PLACE)) { /* Works, but very weird. Can't optimize timing well, since you're * not doing proper architecture delay modelling. */ printf("Warning: Using global routing with timing-driven placement.\n"); printf("\tThis is allowed, but strange, and circuit speed will suffer.\n"); } if ( *timing_analysis_enabled == FALSE && (placer_opts->place_algorithm == NET_TIMING_DRIVEN_PLACE || placer_opts->place_algorithm == PATH_TIMING_DRIVEN_PLACE)) { /*may work, not tested*/ printf("Error: timing analysis must be enabled for timing-driven placement\n"); exit (1); } if (*operation == ROUTE_ONLY && placer_opts->pad_loc_type == USER) { printf ("Error: You cannot specify both a full placement file and \n"); printf (" a pad location file.\n"); exit (1); } if (router_opts->fixed_channel_width != NO_FIXED_CHANNEL_WIDTH && *verify_binary_search) { printf ("Error: Routing on a fixed channel width (%d tracks) " "specified.\n", router_opts->fixed_channel_width); printf (" There is no binary search to verify, so you \n" " cannot specify -verify_binary_search option.\n"); exit (1); } if (*operation == ROUTE_ONLY || *operation == PLACE_AND_ROUTE) { if (router_opts->router_algorithm == TIMING_DRIVEN && *timing_analysis_enabled == FALSE) { printf ("Error: Cannot perform timing-driven routing when timing " "analysis is disabled.\n"); exit (1); } if (*timing_analysis_enabled == FALSE && router_opts->base_cost_type != DEMAND_ONLY) { printf ("Error: base_cost_type must be demand_only when timing " "analysis is disabled.\n"); exit (1); } } if (*operation == TIMING_ANALYSIS_ONLY && *timing_analysis_enabled == FALSE) { printf ("Error: -timing_analyze_only_with_net_delay option requires\n" "\tthat timing analysis not be disabled.\n"); exit (1); } /* Now echo back the options the user has selected. */ printf("\nGeneral Options:\n"); if (*aspect_ratio != 1.) { printf("\tFPGA will have a width/length ratio of %g.\n", *aspect_ratio); } if (*user_sized == TRUE) { printf("\tThe FPGA size has been specified by the user.\n"); /* If one of nx or ny was unspecified, compute it from the other and * * the aspect ratio. If both are unspecified, wait till the netlist * * is read and compute the smallest possible nx and ny in read_arch. */ if (ny == 0) { ny = (float) nx / (float) *aspect_ratio; } else if (nx == 0) { nx = ny * *aspect_ratio; } else if (*aspect_ratio != 1 && *aspect_ratio != nx / ny) { printf("\nError: User-specified size and aspect ratio do\n"); printf("not match. Note that aspect ratio does not have to\n"); printf("be specified if both nx and ny are specified.\n"); exit (1); } } if (*full_stats == TRUE) { printf("\tA full statistical report will be printed.\n"); } if (*operation == ROUTE_ONLY) { printf ("\tRouting will be performed on an existing placement.\n"); } else if (*operation == PLACE_ONLY) { printf ("\tThe circuit will be placed but not routed.\n"); } else if (*operation == PLACE_AND_ROUTE) { printf ("\tThe circuit will be placed and routed.\n"); } else if (*operation == TIMING_ANALYSIS_ONLY) { printf ("\tOnly timing analysis (assuming a constant net delay) will " "be performed.\n"); } if (*operation == PLACE_ONLY || *operation == PLACE_AND_ROUTE) { printf("\nPlacer Options:\n"); if (placer_opts->place_algorithm == NET_TIMING_DRIVEN_PLACE) printf("\tPlacement algorithm is net_timing_driven\n"); if (placer_opts->place_algorithm == PATH_TIMING_DRIVEN_PLACE) printf("\tPlacement algorithm is path_timing_driven\n"); if (placer_opts->place_algorithm == NET_TIMING_DRIVEN_PLACE || placer_opts->place_algorithm == PATH_TIMING_DRIVEN_PLACE) { printf("\tTradeoff between bounding box and critical path: %g\n",placer_opts->timing_tradeoff); printf("\tLower bound assumes block distance: %d\n",placer_opts->block_dist); printf("\tRecomputing criticalities every %d temperature changes\n", placer_opts->recompute_crit_iter); printf("\tInner loop computes criticalities every move_lim/%d moves\n", placer_opts->inner_loop_recompute_divider); printf("\tExponent starting value used in timing-driven cost function is %g\n", placer_opts->td_place_exp_first); printf("\tExponent final value used in timing-driven cost function is %g\n", placer_opts->td_place_exp_last); } else if (placer_opts->place_algorithm == BOUNDING_BOX_PLACE) { printf("\tPlacement algorithm is bounding_box\n"); if (placer_opts->enable_timing_computations) { printf("\tPlacement algorithm will generate timing estimates\n" "\t(estimates do not affect the placement in bounding_box mode)\n"); } } if (annealing_sched->type == AUTO_SCHED) { printf("\tAutomatic annealing schedule selected.\n"); printf("\tNumber of moves in the inner loop is (num_blocks)^4/3 " "* %g\n", annealing_sched->inner_num); } else { printf("\tUser annealing schedule selected with:\n"); printf("\tInitial Temperature: %g\n",annealing_sched->init_t); printf("\tExit (Final) Temperature: %g\n",annealing_sched->exit_t); printf("\tTemperature Reduction factor (alpha_t): %g\n", annealing_sched->alpha_t); printf("\tNumber of moves in the inner loop is (num_blocks)^4/3 * " "%g\n", annealing_sched->inner_num); } if (placer_opts->place_cost_type == NONLINEAR_CONG) { printf("\tPlacement cost type is nonlinear congestion.\n"); printf("\tCongestion will be determined on a %d x %d array.\n", placer_opts->num_regions, placer_opts->num_regions); if (do_one_nonlinear_place == TRUE) { placer_opts->place_freq = PLACE_ONCE; printf("\tPlacement will be performed once.\n"); printf("\tPlacement channel width factor = %d.\n", placer_opts->place_chan_width); } else { placer_opts->place_freq = PLACE_ALWAYS; printf("\tCircuit will be replaced for each channel width " "attempted.\n"); } } else if (placer_opts->place_cost_type == LINEAR_CONG) { placer_opts->place_freq = PLACE_ONCE; printf("\tPlacement cost type is linear congestion.\n"); printf("\tPlacement will be performed once.\n"); printf("\tPlacement channel width factor = %d.\n", placer_opts->place_chan_width); printf("\tExponent used in placement cost: %g\n", placer_opts->place_cost_exp); } if (placer_opts->pad_loc_type == RANDOM) { printf("\tPlacer will fix the IO pins in a random configuration.\n"); } else if (placer_opts->pad_loc_type == USER) { printf ("\tPlacer will fix the IO pins as specified by file %s.\n", placer_opts->pad_loc_file); } /* The default bend_cost for DETAILED routing is 0, while the default for * * GLOBAL routing is 1. */ if (bend_cost_set == FALSE && router_opts->route_type == DETAILED) router_opts->bend_cost = 0.; /*needed when computing placement lookup matricies*/ /* Default base_cost_type is DELAY_NORMALIZED for timing_driven routing */ if (!base_cost_type_set && router_opts->router_algorithm == TIMING_DRIVEN) router_opts->base_cost_type = DELAY_NORMALIZED; /*needed when computing placement lookup matricies*/ printf("\tInitial random seed: %d\n", seed); my_srandom(seed); } /* End of echo placement options. */ if (*operation == ROUTE_ONLY || *operation == PLACE_AND_ROUTE) { printf("\nRouting Options:\n"); if (router_opts->route_type == GLOBAL) printf("\tOnly GLOBAL routing will be performed.\n"); else printf("\tCombined GLOBAL + DETAILED routing will be performed.\n"); if (router_opts->router_algorithm == BREADTH_FIRST) printf ("\tRouter algorithm: breadth first.\n"); else printf ("\tRouter algorithm: timing driven.\n"); printf("\tThe router will try at most %d iterations.\n", router_opts->max_router_iterations); printf("\tRoutings can go at most %d channels outside their " "bounding box.\n", router_opts->bb_factor); /* The default bend_cost for DETAILED routing is 0, while the default for * * GLOBAL routing is 1. */ if (bend_cost_set == FALSE && router_opts->route_type == DETAILED) router_opts->bend_cost = 0.; printf("\tCost of a bend (bend_cost) is %g.\n", router_opts->bend_cost); printf("\tFirst iteration sharing penalty factor (first_iter_pres_fac):" " %g\n", router_opts->first_iter_pres_fac); printf("\tInitial (2nd iter.) sharing penalty factor (initial_pres_fac):" " %g\n", router_opts->initial_pres_fac); printf("\tSharing penalty growth factor (pres_fac_mult): %g\n", router_opts->pres_fac_mult); printf("\tAccumulated sharing penalty factor (acc_fac): %g\n", router_opts->acc_fac); /* Default base_cost_type is DELAY_NORMALIZED for timing_driven routing */ if (!base_cost_type_set && router_opts->router_algorithm == TIMING_DRIVEN) router_opts->base_cost_type = DELAY_NORMALIZED; printf ("\tBase_cost_type: "); if (router_opts->base_cost_type == INTRINSIC_DELAY) printf ("intrinsic delay.\n"); else if (router_opts->base_cost_type == DELAY_NORMALIZED) printf ("delay normalized.\n"); else if (router_opts->base_cost_type == DEMAND_ONLY) printf ("demand only.\n"); if (router_opts->router_algorithm == TIMING_DRIVEN) { printf ("\tSearch aggressiveness factor (astar_fac): %g\n", router_opts->astar_fac); printf ("\tMaximum sink criticality (max_criticality): %g\n", router_opts->max_criticality); printf ("\tExponent for criticality computation (criticality_exp): " "%g\n", router_opts->criticality_exp); } if (router_opts->fixed_channel_width == NO_FIXED_CHANNEL_WIDTH) { printf ("\tRouter will find the minimum number of tracks " "required to route.\n"); } else { printf ("\tRouter will attempt routing only with a channel width" " factor of %d.\n", router_opts->fixed_channel_width); } if (*verify_binary_search) { /* Router will ensure routings with 1, 2, and 3 tracks fewer than the * * best found by the binary search will not succeed. Normally only * * verify that best - 1 tracks does not succeed. */ printf("\tRouter will verify that binary search yields min. " "channel width.\n"); } } /* End of echo router options. */ if (*operation == TIMING_ANALYSIS_ONLY) { printf ("\tNet delay value for timing analysis: %g (s)\n", *constant_net_delay); } printf("\n");}static void get_input (char *net_file, char *arch_file, int place_cost_type, int num_regions, float aspect_ratio, boolean user_sized, enum e_route_type route_type, struct s_det_routing_arch *det_routing_arch, t_segment_inf **segment_inf_ptr, t_timing_inf *timing_inf_ptr, t_subblock_data *subblock_data_ptr, t_chan_width_dist *chan_width_dist_ptr) { /* This subroutine reads in the netlist and architecture files, initializes * * some data structures and does any error checks that require knowledge of * * both the algorithms to be used and the FPGA architecture. */ printf("Reading the FPGA architectural description from %s.\n", arch_file); read_arch (arch_file, route_type, det_routing_arch, segment_inf_ptr, timing_inf_ptr, subblock_data_ptr, chan_width_dist_ptr); printf("Successfully read %s.\n",arch_file); printf("Pins per clb: %d. Pads per row/column: %d.\n", pins_per_clb, io_rat); printf("Subblocks per clb: %d. Subblock LUT size: %d.\n", subblock_data_ptr->max_subblocks_per_block, subblock_data_ptr->subblock_lut_size); if (route_type == DETAILED) { if (det_routing_arch->Fc_type == ABSOLUTE) printf("Fc value is absolute number of tracks.\n"); else printf("Fc value is fraction of tracks in a channel.\n"); printf("Fc_output: %g. Fc_input: %g. Fc_pad: %g.\n", det_routing_arch->Fc_output, det_routing_arch->Fc_input, det_routing_arch->Fc_pad); if (det_routing_arch->switch_block_type == SUBSET) printf("Switch block type: Subset.\n"); else if (det_routing_arch->switch_block_type == WILTON) printf("Switch_block_type: WILTON.\n"); else printf ("Switch_block_type: UNIVERSAL.\n"); printf ("Distinct types of segments: %d.\n", det_routing_arch->num_segment); printf ("Distinct types of user-specified switches: %d.\n", det_routing_arch->num_switch - 2); } printf ("\n"); printf("Reading the circuit netlist from %s.\n",net_file); read_net (net_file, subblock_data_ptr); printf("Successfully read %s.\n", net_file); printf("%d blocks, %d nets, %d global nets.\n", num_blocks, num_nets, num_globals); printf("%d clbs, %d inputs, %d outputs.\n", num_clbs, num_p_inputs, num_p_outputs); /* Set up some physical FPGA data structures that need to * * know num_blocks. */ init_arch(aspect_ratio, user_sized); printf("The circuit will be mapped into a %d x %d array of clbs.\n\n", nx, ny); if (place_cost_type == NONLINEAR_CONG && (num_regions > nx || num_regions > ny)) { printf("Error: Cannot use more regions than clbs in placement cost " "function.\n"); exit(1); } }static int read_int_option (int argc, char *argv[], int iarg) { /* This routine returns the value in argv[iarg+1]. This value must exist * * and be an integer, or an error message is printed and the program * * exits. */ int value, num_read; num_read = 0; /* Does value exist for this option? */ if (argc > iarg+1) num_read = sscanf(argv[iarg+1],"%d",&value); /* Value exists and was a proper int? */ if (num_read != 1) { printf("Error: %s option requires an integer parameter.\n\n", argv[iarg]); exit(1); } return (value);}static float read_float_option (int argc, char *argv[], int iarg) { /* This routine returns the value in argv[iarg+1]. This value must exist * * and be a float, or an error message is printed and the program exits. */ int num_read; float value; num_read = 0; /* Does value exist for this option? */ if (argc > iarg+1) num_read = sscanf(argv[iarg+1],"%f",&value); /* Value exists and was a proper float? */ if (num_read != 1) { printf("Error: %s option requires a float parameter.\n\n", argv[iarg]); exit(1); } return (value); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -