Go to the source code of this file.
Functions | |
boolean | try_route (int width_fac, struct s_router_opts router_opts, struct s_det_routing_arch det_routing_arch, t_segment_inf *segment_inf, t_timing_inf timing_inf, float **net_slack, float **net_delay, t_chan_width_dist chan_width_dist, t_ivec **fb_opins_used_locally, t_mst_edge **mst, boolean *Fc_clipped) |
boolean | feasible_routing (void) |
t_ivec ** | alloc_route_structs (t_subblock_data subblock_data) |
void | free_route_structs (t_ivec **fb_opins_used_locally) |
struct s_trace ** | alloc_saved_routing (t_ivec **fb_opins_used_locally, t_ivec ***saved_clb_opins_used_locally_ptr) |
void | free_saved_routing (struct s_trace **best_routing, t_ivec **saved_clb_opins_used_locally) |
void | save_routing (struct s_trace **best_routing, t_ivec **fb_opins_used_locally, t_ivec **saved_clb_opins_used_locally) |
void | restore_routing (struct s_trace **best_routing, t_ivec **fb_opins_used_locally, t_ivec **saved_clb_opins_used_locally) |
void | get_serial_num (void) |
void | print_route (char *name) |
t_ivec** alloc_route_structs | ( | t_subblock_data | subblock_data | ) |
Definition at line 703 of file route_common.c.
00704 { 00705 00706 /* Allocates the data structures needed for routing. */ 00707 00708 t_ivec **fb_opins_used_locally; 00709 00710 trace_head = (struct s_trace **)my_calloc(num_nets, 00711 sizeof(struct s_trace *)); 00712 trace_tail = (struct s_trace **)my_malloc(num_nets * 00713 sizeof(struct s_trace *)); 00714 00715 heap_size = nx * ny; 00716 heap = (struct s_heap **)my_malloc(heap_size * sizeof(struct s_heap *)); 00717 heap--; /* heap stores from [1..heap_size] */ 00718 heap_tail = 1; 00719 00720 route_bb = (struct s_bb *)my_malloc(num_nets * sizeof(struct s_bb)); 00721 00722 fb_opins_used_locally = 00723 alloc_and_load_clb_opins_used_locally(subblock_data); 00724 00725 return (fb_opins_used_locally); 00726 }
struct s_trace** alloc_saved_routing | ( | t_ivec ** | fb_opins_used_locally, | |
t_ivec *** | saved_clb_opins_used_locally_ptr | |||
) | [read] |
Definition at line 730 of file route_common.c.
00732 { 00733 00734 /* Allocates data structures into which the key routing data can be saved, * 00735 * allowing the routing to be recovered later (e.g. after a another routing * 00736 * is attempted). */ 00737 00738 struct s_trace **best_routing; 00739 t_ivec **saved_clb_opins_used_locally; 00740 int iblk, iclass, num_local_opins; 00741 t_type_ptr type; 00742 00743 best_routing = (struct s_trace **)my_calloc(num_nets, 00744 sizeof(struct s_trace *)); 00745 00746 saved_clb_opins_used_locally = 00747 (t_ivec **) my_malloc(num_blocks * sizeof(t_ivec *)); 00748 00749 for(iblk = 0; iblk < num_blocks; iblk++) 00750 { 00751 type = block[iblk].type; 00752 saved_clb_opins_used_locally[iblk] = 00753 (t_ivec *) my_malloc(type->num_class * sizeof(t_ivec)); 00754 for(iclass = 0; iclass < type->num_class; iclass++) 00755 { 00756 num_local_opins = 00757 fb_opins_used_locally[iblk][iclass].nelem; 00758 saved_clb_opins_used_locally[iblk][iclass].nelem = 00759 num_local_opins; 00760 00761 if(num_local_opins == 0) 00762 { 00763 saved_clb_opins_used_locally[iblk][iclass].list = 00764 NULL; 00765 } 00766 else 00767 { 00768 saved_clb_opins_used_locally[iblk][iclass].list = 00769 (int *)my_malloc(num_local_opins * 00770 sizeof(int)); 00771 } 00772 } 00773 } 00774 00775 *saved_clb_opins_used_locally_ptr = saved_clb_opins_used_locally; 00776 return (best_routing); 00777 }
boolean feasible_routing | ( | void | ) |
Definition at line 337 of file route_common.c.
00338 { 00339 00340 /* This routine checks to see if this is a resource-feasible routing. * 00341 * That is, are all rr_node capacity limitations respected? It assumes * 00342 * that the occupancy arrays are up to date when it is called. */ 00343 00344 int inode; 00345 00346 for(inode = 0; inode < num_rr_nodes; inode++) 00347 if(rr_node[inode].occ > rr_node[inode].capacity) 00348 return (FALSE); 00349 00350 return (TRUE); 00351 }
void free_route_structs | ( | t_ivec ** | fb_opins_used_locally | ) |
Definition at line 864 of file route_common.c.
00865 { 00866 00867 /* Frees the temporary storage needed only during the routing. The * 00868 * final routing result is not freed. */ 00869 int i; 00870 00871 free(heap + 1); 00872 free(route_bb); 00873 00874 heap = NULL; /* Defensive coding: crash hard if I use these. */ 00875 route_bb = NULL; 00876 00877 for(i = 0; i < num_blocks; i++) 00878 { 00879 free_ivec_vector(fb_opins_used_locally[i], 0, 00880 block[i].type->num_class - 1); 00881 } 00882 free(fb_opins_used_locally); 00883 00884 /* NB: Should use my chunk_malloc for tptr, hptr, and mod_ptr structures. * 00885 * I could free everything except the tptrs at the end then. */ 00886 00887 }
Definition at line 891 of file route_common.c.
00893 { 00894 00895 /* Frees the data structures needed to save a routing. */ 00896 int i; 00897 00898 free(best_routing); 00899 for(i = 0; i < num_blocks; i++) 00900 { 00901 free_ivec_vector(saved_clb_opins_used_locally[i], 0, 00902 block[i].type->num_class - 1); 00903 } 00904 free(saved_clb_opins_used_locally); 00905 }
void get_serial_num | ( | void | ) |
Definition at line 210 of file route_common.c.
00211 { 00212 00213 /* This routine finds a "magic cookie" for the routing and prints it. * 00214 * Use this number as a routing serial number to ensure that programming * 00215 * changes do not break the router. */ 00216 00217 int inet, serial_num, inode; 00218 struct s_trace *tptr; 00219 00220 serial_num = 0; 00221 00222 for(inet = 0; inet < num_nets; inet++) 00223 { 00224 00225 /* Global nets will have null trace_heads (never routed) so they * 00226 * are not included in the serial number calculation. */ 00227 00228 tptr = trace_head[inet]; 00229 while(tptr != NULL) 00230 { 00231 inode = tptr->index; 00232 serial_num += 00233 (inet + 1) * (rr_node[inode].xlow * (nx + 1) - 00234 rr_node[inode].yhigh); 00235 00236 serial_num -= rr_node[inode].ptc_num * (inet + 1) * 10; 00237 00238 serial_num -= rr_node[inode].type * (inet + 1) * 100; 00239 serial_num %= 2000000000; /* Prevent overflow */ 00240 tptr = tptr->next; 00241 } 00242 } 00243 printf("Serial number (magic cookie) for the routing is: %d\n", 00244 serial_num); 00245 }
void print_route | ( | char * | name | ) |
Definition at line 1288 of file route_common.c.
01289 { 01290 01291 /* Prints out the routing to file route_file. */ 01292 01293 int inet, inode, ipin, bnum, ilow, jlow, node_block_pin, iclass; 01294 t_rr_type rr_type; 01295 struct s_trace *tptr; 01296 char *name_type[] = 01297 { "SOURCE", "SINK", "IPIN", "OPIN", "CHANX", "CHANY" }; 01298 FILE *fp; 01299 01300 fp = my_fopen(route_file, "w"); 01301 01302 fprintf(fp, "Array size: %d x %d logic blocks.\n", nx, ny); 01303 fprintf(fp, "\nRouting:"); 01304 for(inet = 0; inet < num_nets; inet++) 01305 { 01306 if(net[inet].is_global == FALSE) 01307 { 01308 fprintf(fp, "\n\nNet %d (%s)\n\n", inet, net[inet].name); 01309 tptr = trace_head[inet]; 01310 01311 while(tptr != NULL) 01312 { 01313 inode = tptr->index; 01314 rr_type = rr_node[inode].type; 01315 ilow = rr_node[inode].xlow; 01316 jlow = rr_node[inode].ylow; 01317 01318 fprintf(fp, "%6s (%d,%d) ", name_type[rr_type], 01319 ilow, jlow); 01320 01321 if((ilow != rr_node[inode].xhigh) || (jlow != 01322 rr_node 01323 [inode]. 01324 yhigh)) 01325 fprintf(fp, "to (%d,%d) ", 01326 rr_node[inode].xhigh, 01327 rr_node[inode].yhigh); 01328 01329 switch (rr_type) 01330 { 01331 01332 case IPIN: 01333 case OPIN: 01334 if(grid[ilow][jlow].type == IO_TYPE) 01335 { 01336 fprintf(fp, " Pad: "); 01337 } 01338 else 01339 { /* IO Pad. */ 01340 fprintf(fp, " Pin: "); 01341 } 01342 break; 01343 01344 case CHANX: 01345 case CHANY: 01346 fprintf(fp, " Track: "); 01347 break; 01348 01349 case SOURCE: 01350 case SINK: 01351 if(grid[ilow][jlow].type == IO_TYPE) 01352 { 01353 fprintf(fp, " Pad: "); 01354 } 01355 else 01356 { /* IO Pad. */ 01357 fprintf(fp, " Class: "); 01358 } 01359 break; 01360 01361 default: 01362 printf 01363 ("Error in print_route: Unexpected traceback element " 01364 "type: %d (%s).\n", rr_type, 01365 name_type[rr_type]); 01366 exit(1); 01367 break; 01368 } 01369 01370 fprintf(fp, "%d ", rr_node[inode].ptc_num); 01371 01372 /* Uncomment line below if you're debugging and want to see the switch types * 01373 * used in the routing. */ 01374 /* fprintf (fp, "Switch: %d", tptr->iswitch); */ 01375 01376 fprintf(fp, "\n"); 01377 01378 tptr = tptr->next; 01379 } 01380 } 01381 01382 else 01383 { /* Global net. Never routed. */ 01384 fprintf(fp, "\n\nNet %d (%s): global net connecting:\n\n", 01385 inet, net[inet].name); 01386 01387 for(ipin = 0; ipin <= net[inet].num_sinks; ipin++) 01388 { 01389 bnum = net[inet].node_block[ipin]; 01390 01391 node_block_pin = net[inet].node_block_pin[ipin]; 01392 iclass = 01393 block[bnum].type->pin_class[node_block_pin]; 01394 01395 fprintf(fp, 01396 "Block %s (#%d) at (%d, %d), Pin class %d.\n", 01397 block[bnum].name, bnum, block[bnum].x, 01398 block[bnum].y, iclass); 01399 } 01400 } 01401 } 01402 01403 fclose(fp); 01404 01405 #ifdef CREATE_ECHO_FILES 01406 fp = my_fopen("mem.echo", "w"); 01407 fprintf(fp, "\nNum_heap_allocated: %d Num_trace_allocated: %d\n", 01408 num_heap_allocated, num_trace_allocated); 01409 fprintf(fp, "Num_linked_f_pointer_allocated: %d\n", 01410 num_linked_f_pointer_allocated); 01411 fclose(fp); 01412 #endif /* CREATE_ECHO_FILES */ 01413 01414 }
void restore_routing | ( | struct s_trace ** | best_routing, | |
t_ivec ** | fb_opins_used_locally, | |||
t_ivec ** | saved_clb_opins_used_locally | |||
) |
Definition at line 162 of file route_common.c.
00165 { 00166 00167 /* Deallocates any current routing in trace_head, and replaces it with * 00168 * the routing in best_routing. Best_routing is set to NULL to show that * 00169 * it no longer points to a valid routing. NOTE: trace_tail is not * 00170 * restored -- it is set to all NULLs since it is only used in * 00171 * update_traceback. If you need trace_tail restored, modify this * 00172 * routine. Also restores the locally used opin data. */ 00173 00174 int inet, iblk, ipin, iclass, num_local_opins; 00175 t_type_ptr type; 00176 00177 for(inet = 0; inet < num_nets; inet++) 00178 { 00179 00180 /* Free any current routing. */ 00181 free_traceback(inet); 00182 00183 /* Set the current routing to the saved one. */ 00184 trace_head[inet] = best_routing[inet]; 00185 best_routing[inet] = NULL; /* No stored routing. */ 00186 } 00187 00188 /* Save which OPINs are locally used. */ 00189 00190 for(iblk = 0; iblk < num_blocks; iblk++) 00191 { 00192 type = block[iblk].type; 00193 for(iclass = 0; iclass < type->num_class; iclass++) 00194 { 00195 num_local_opins = 00196 fb_opins_used_locally[iblk][iclass].nelem; 00197 for(ipin = 0; ipin < num_local_opins; ipin++) 00198 { 00199 fb_opins_used_locally[iblk][iclass].list[ipin] = 00200 saved_clb_opins_used_locally[iblk][iclass]. 00201 list[ipin]; 00202 } 00203 } 00204 00205 } 00206 }
void save_routing | ( | struct s_trace ** | best_routing, | |
t_ivec ** | fb_opins_used_locally, | |||
t_ivec ** | saved_clb_opins_used_locally | |||
) |
Definition at line 101 of file route_common.c.
00104 { 00105 00106 /* This routing frees any routing currently held in best routing, * 00107 * then copies over the current routing (held in trace_head), and * 00108 * finally sets trace_head and trace_tail to all NULLs so that the * 00109 * connection to the saved routing is broken. This is necessary so * 00110 * that the next iteration of the router does not free the saved * 00111 * routing elements. Also saves any data about locally used clb_opins, * 00112 * since this is also part of the routing. */ 00113 00114 int inet, iblk, iclass, ipin, num_local_opins; 00115 struct s_trace *tptr, *tempptr; 00116 t_type_ptr type; 00117 00118 for(inet = 0; inet < num_nets; inet++) 00119 { 00120 00121 /* Free any previously saved routing. It is no longer best. */ 00122 tptr = best_routing[inet]; 00123 while(tptr != NULL) 00124 { 00125 tempptr = tptr->next; 00126 free_trace_data(tptr); 00127 tptr = tempptr; 00128 } 00129 00130 /* Save a pointer to the current routing in best_routing. */ 00131 best_routing[inet] = trace_head[inet]; 00132 00133 /* Set the current (working) routing to NULL so the current trace * 00134 * elements won't be reused by the memory allocator. */ 00135 00136 trace_head[inet] = NULL; 00137 trace_tail[inet] = NULL; 00138 } 00139 00140 /* Save which OPINs are locally used. */ 00141 00142 for(iblk = 0; iblk < num_blocks; iblk++) 00143 { 00144 type = block[iblk].type; 00145 for(iclass = 0; iclass < type->num_class; iclass++) 00146 { 00147 num_local_opins = 00148 fb_opins_used_locally[iblk][iclass].nelem; 00149 for(ipin = 0; ipin < num_local_opins; ipin++) 00150 { 00151 saved_clb_opins_used_locally[iblk][iclass]. 00152 list[ipin] = 00153 fb_opins_used_locally[iblk][iclass]. 00154 list[ipin]; 00155 } 00156 } 00157 } 00158 }
boolean try_route | ( | int | width_fac, | |
struct s_router_opts | router_opts, | |||
struct s_det_routing_arch | det_routing_arch, | |||
t_segment_inf * | segment_inf, | |||
t_timing_inf | timing_inf, | |||
float ** | net_slack, | |||
float ** | net_delay, | |||
t_chan_width_dist | chan_width_dist, | |||
t_ivec ** | fb_opins_used_locally, | |||
t_mst_edge ** | mst, | |||
boolean * | Fc_clipped | |||
) |
Definition at line 249 of file route_common.c.
00260 { 00261 00262 /* Attempts a routing via an iterated maze router algorithm. Width_fac * 00263 * specifies the relative width of the channels, while the members of * 00264 * router_opts determine the value of the costs assigned to routing * 00265 * resource node, etc. det_routing_arch describes the detailed routing * 00266 * architecture (connection and switch boxes) of the FPGA; it is used * 00267 * only if a DETAILED routing has been selected. */ 00268 00269 int tmp; 00270 boolean success; 00271 t_graph_type graph_type; 00272 00273 if(router_opts.route_type == GLOBAL) { 00274 graph_type = GRAPH_GLOBAL; 00275 } else { 00276 graph_type = (det_routing_arch.directionality == 00277 BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); 00278 } 00279 00280 /* Set the channel widths */ 00281 00282 init_chan(width_fac, chan_width_dist); 00283 00284 /* Free any old routing graph, if one exists. */ 00285 00286 free_rr_graph(); 00287 00288 /* Set up the routing resource graph defined by this FPGA architecture. */ 00289 00290 build_rr_graph(graph_type, 00291 num_types, type_descriptors, nx, ny, grid, 00292 chan_width_x[0], NULL, 00293 det_routing_arch.switch_block_type, det_routing_arch.Fs, 00294 det_routing_arch.num_segment, det_routing_arch.num_switch, segment_inf, 00295 det_routing_arch.global_route_switch, 00296 det_routing_arch.delayless_switch, timing_inf, 00297 det_routing_arch.wire_to_ipin_switch, 00298 router_opts.base_cost_type, &tmp); 00299 00300 /* Allocate and load some additional rr_graph information needed only by * 00301 * the router. */ 00302 00303 alloc_and_load_rr_node_route_structs(); 00304 00305 init_route_structs(router_opts.bb_factor); 00306 00307 if(router_opts.router_algorithm == BREADTH_FIRST) 00308 { 00309 printf("Confirming Router Algorithm: BREADTH_FIRST.\n"); 00310 success = 00311 try_breadth_first_route(router_opts, fb_opins_used_locally, 00312 width_fac); 00313 } 00314 else if(router_opts.router_algorithm == TIMING_DRIVEN) 00315 { /* TIMING_DRIVEN route */ 00316 printf("Confirming Router Algorithm: TIMING_DRIVEN.\n"); 00317 assert(router_opts.route_type != GLOBAL); 00318 success = 00319 try_timing_driven_route(router_opts, net_slack, net_delay, 00320 fb_opins_used_locally); 00321 } 00322 else 00323 { /* Directed Search Routability Driven */ 00324 printf("Confirming Router Algorithm: DIRECTED_SEARCH.\n"); 00325 success = 00326 try_directed_search_route(router_opts, fb_opins_used_locally, 00327 width_fac, mst); 00328 } 00329 00330 free_rr_node_route_structs(); 00331 00332 return (success); 00333 }