SRC/path_delay.h File Reference

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

Go to the source code of this file.

Functions

float ** alloc_and_load_timing_graph (t_timing_inf timing_inf, t_subblock_data subblock_data)
t_linked_intallocate_and_load_critical_path (void)
void load_timing_graph_net_delays (float **net_delay)
float load_net_slack (float **net_slack, float target_cycle_time)
void free_timing_graph (float **net_slack)
void print_timing_graph (char *fname)
void print_net_slack (char *fname, float **net_slack)
void print_critical_path (char *fname, t_subblock_data subblock_data)
void get_tnode_block_and_output_net (int inode, int *iblk_ptr, int *inet_ptr)
void do_constant_net_delay_timing_analysis (t_timing_inf timing_inf, t_subblock_data subblock_data, float constant_net_delay_value)

Function Documentation

float** alloc_and_load_timing_graph ( t_timing_inf  timing_inf,
t_subblock_data  subblock_data 
)

Definition at line 158 of file path_delay.c.

00160 {
00161 
00162 /* This routine builds the graph used for timing analysis.  Every fb or    *
00163  * subblock pin is a timing node (tnode).  The connectivity between pins is *
00164  * represented by timing edges (tedges).  All delay is marked on edges, not *
00165  * on nodes.  This routine returns an array that will store slack values:   *
00166  * net_slack[0..num_nets-1][1..num_pins-1].                                 */
00167 
00168 /* The two arrays below are valid only for FBs, not pads.                  */
00169     int i;
00170     int **num_uses_of_fb_ipin;  /* [0..num_blocks-1][0..type->num_pins-1]       */
00171     int ***num_uses_of_sblk_opin;       /* [0..num_blocks-1][0..type->num_subblocks][0..type->max_subblock_outputs] */
00172 
00173 /* Array for mapping from a pin on a block to a tnode index. For pads, only *
00174  * the first two pin locations are used (input to pad is first, output of   *
00175  * pad is second).  For fbs, all OPEN pins on the fb have their mapping   *
00176  * set to OPEN so I won't use it by mistake.                                */
00177 
00178     int **block_pin_to_tnode;   /* [0..num_blocks-1][0..num_pins-1]      */
00179 
00180 
00181 /* Array for mapping from a pin on a subblock to a tnode index.  Unused     *
00182  * or nonexistent subblock pins have their mapping set to OPEN.             *
00183  * [0..num_blocks-1][0..num_subblocks_per_block-1][0..NUM_SUB_PIN_TYPES][0..total_subblock_pins-1]  */
00184 
00185     int ****snode_block_pin_to_tnode;
00186 
00187     int num_sinks;
00188     float **net_slack;          /* [0..num_nets-1][1..num_pins-1]. */
00189 
00190 /************* End of variable declarations ********************************/
00191 
00192     if(tedge_ch_list_head != NULL)
00193         {
00194             printf("Error in alloc_and_load_timing_graph:\n"
00195                    "\tAn old timing graph still exists.\n");
00196             exit(1);
00197         }
00198 
00199 /* If either of the checks below ever fail, change the definition of        *
00200  * tnode_descript to use ints instead of shorts for isubblk or ipin.        */
00201 
00202     for(i = 0; i < num_types; i++)
00203         {
00204             if(type_descriptors[i].num_pins > MAX_SHORT)
00205                 {
00206                     printf
00207                         ("Error in alloc_and_load_timing_graph: pins for type %s is %d."
00208                          "\tWill cause short overflow in tnode_descript.\n",
00209                          type_descriptors[i].name,
00210                          type_descriptors[i].num_pins);
00211                     exit(1);
00212                 }
00213 
00214             if(type_descriptors[i].max_subblocks > MAX_SHORT)
00215                 {
00216                     printf
00217                         ("Error in alloc_and_load_timing_graph: max_subblocks_per_block"
00218                          "\tis %d -- will cause short overflow in tnode_descript.\n",
00219                          type_descriptors[i].max_subblocks);
00220                     exit(1);
00221                 }
00222         }
00223 
00224     alloc_and_load_fanout_counts(&num_uses_of_fb_ipin,
00225                                  &num_uses_of_sblk_opin, subblock_data);
00226 
00227     num_tnodes = alloc_and_load_pin_mappings(&block_pin_to_tnode,
00228                                              &snode_block_pin_to_tnode,
00229                                              subblock_data,
00230                                              num_uses_of_sblk_opin);
00231 
00232     alloc_and_load_tnodes_and_net_mapping(num_uses_of_fb_ipin,
00233                                           num_uses_of_sblk_opin,
00234                                           block_pin_to_tnode,
00235                                           snode_block_pin_to_tnode,
00236                                           subblock_data, timing_inf);
00237 
00238     num_sinks = alloc_and_load_timing_graph_levels();
00239 
00240     check_timing_graph(subblock_data.num_const_gen, subblock_data.num_ff,
00241                        num_sinks);
00242 
00243     free_fanout_counts(num_uses_of_fb_ipin, num_uses_of_sblk_opin);
00244     free_pin_mappings(block_pin_to_tnode, snode_block_pin_to_tnode,
00245                       subblock_data.num_subblocks_per_block);
00246 
00247     net_slack = alloc_net_slack();
00248     return (net_slack);
00249 }

Here is the call graph for this function:

Here is the caller graph for this function:

t_linked_int* allocate_and_load_critical_path ( void   ) 

Definition at line 1551 of file path_delay.c.

01552 {
01553 
01554 /* Finds the critical path and puts a list of the tnodes on the critical    *
01555  * path in a linked list, from the path SOURCE to the path SINK.            */
01556 
01557     t_linked_int *critical_path_head, *curr_crit_node, *prev_crit_node;
01558     int inode, iedge, to_node, num_at_level, i, crit_node, num_edges;
01559     float min_slack, slack;
01560     t_tedge *tedge;
01561 
01562     num_at_level = tnodes_at_level[0].nelem;
01563     min_slack = HUGE_FLOAT;
01564     crit_node = OPEN;           /* Stops compiler warnings. */
01565 
01566     for(i = 0; i < num_at_level; i++)
01567         {                       /* Path must start at SOURCE (no inputs) */
01568             inode = tnodes_at_level[0].list[i];
01569             slack = tnode[inode].T_req - tnode[inode].T_arr;
01570 
01571             if(slack < min_slack)
01572                 {
01573                     crit_node = inode;
01574                     min_slack = slack;
01575                 }
01576         }
01577 
01578     critical_path_head = (t_linked_int *) my_malloc(sizeof(t_linked_int));
01579     critical_path_head->data = crit_node;
01580     prev_crit_node = critical_path_head;
01581     num_edges = tnode[crit_node].num_edges;
01582 
01583     while(num_edges != 0)
01584         {                       /* Path will end at SINK (no fanout) */
01585             curr_crit_node = (t_linked_int *) my_malloc(sizeof(t_linked_int));
01586             prev_crit_node->next = curr_crit_node;
01587             tedge = tnode[crit_node].out_edges;
01588             min_slack = HUGE_FLOAT;
01589 
01590             for(iedge = 0; iedge < num_edges; iedge++)
01591                 {
01592                     to_node = tedge[iedge].to_node;
01593                     slack = tnode[to_node].T_req - tnode[to_node].T_arr;
01594 
01595                     if(slack < min_slack)
01596                         {
01597                             crit_node = to_node;
01598                             min_slack = slack;
01599                         }
01600                 }
01601 
01602             curr_crit_node->data = crit_node;
01603             prev_crit_node = curr_crit_node;
01604             num_edges = tnode[crit_node].num_edges;
01605         }
01606 
01607     prev_crit_node->next = NULL;
01608     return (critical_path_head);
01609 }

Here is the call graph for this function:

Here is the caller graph for this function:

void do_constant_net_delay_timing_analysis ( t_timing_inf  timing_inf,
t_subblock_data  subblock_data,
float  constant_net_delay_value 
)

Definition at line 1644 of file path_delay.c.

01647 {
01648 
01649 /* Does a timing analysis (simple) where it assumes that each net has a      *
01650  * constant delay value.  Used only when operation == TIMING_ANALYSIS_ONLY.  */
01651 
01652     struct s_linked_vptr *net_delay_chunk_list_head;
01653     float **net_delay, **net_slack;
01654 
01655     float T_crit;
01656 
01657     net_slack = alloc_and_load_timing_graph(timing_inf, subblock_data);
01658     net_delay = alloc_net_delay(&net_delay_chunk_list_head);
01659 
01660     load_constant_net_delay(net_delay, constant_net_delay_value);
01661     load_timing_graph_net_delays(net_delay);
01662     T_crit = load_net_slack(net_slack, 0);
01663 
01664     printf("\n");
01665     printf("\nCritical Path: %g (s)\n", T_crit);
01666 
01667 #ifdef CREATE_ECHO_FILES
01668     print_critical_path("critical_path.echo", subblock_data);
01669     print_timing_graph("timing_graph.echo");
01670     print_net_slack("net_slack.echo", net_slack);
01671     print_net_delay(net_delay, "net_delay.echo");
01672 #endif /* CREATE_ECHO_FILES */
01673 
01674     free_timing_graph(net_slack);
01675     free_net_delay(net_delay, &net_delay_chunk_list_head);
01676 }

Here is the call graph for this function:

Here is the caller graph for this function:

void free_timing_graph ( float **  net_slack  ) 

Definition at line 1217 of file path_delay.c.

01218 {
01219 
01220 /* Frees the timing graph data. */
01221 
01222     if(tedge_ch_list_head == NULL)
01223         {
01224             printf("Error in free_timing_graph: No timing graph to free.\n");
01225             exit(1);
01226         }
01227 
01228     free_chunk_memory(tedge_ch_list_head);
01229     free(tnode);
01230     free(tnode_descript);
01231     free(net_to_driver_tnode);
01232     free_ivec_vector(tnodes_at_level, 0, num_tnode_levels - 1);
01233     free(net_slack);
01234 
01235     tedge_ch_list_head = NULL;
01236     tedge_ch_bytes_avail = 0;
01237     tedge_ch_next_avail = NULL;
01238 
01239     tnode = NULL;
01240     tnode_descript = NULL;
01241     num_tnodes = 0;
01242     net_to_driver_tnode = NULL;
01243     tnodes_at_level = NULL;
01244     num_tnode_levels = 0;
01245 }

Here is the call graph for this function:

Here is the caller graph for this function:

void get_tnode_block_and_output_net ( int  inode,
int *  iblk_ptr,
int *  inet_ptr 
)

Definition at line 1613 of file path_delay.c.

01616 {
01617 
01618 /* Returns the index of the block that this tnode is part of.  If the tnode *
01619  * is a FB_OPIN or INPAD_OPIN (i.e. if it drives a net), the net index is  *
01620  * returned via inet_ptr.  Otherwise inet_ptr points at OPEN.               */
01621 
01622     int inet, ipin, iblk;
01623     t_tnode_type tnode_type;
01624 
01625     iblk = tnode_descript[inode].iblk;
01626     tnode_type = tnode_descript[inode].type;
01627 
01628     if(tnode_type == FB_OPIN || tnode_type == INPAD_OPIN)
01629         {
01630             ipin = tnode_descript[inode].ipin;
01631             inet = block[iblk].nets[ipin];
01632         }
01633     else
01634         {
01635             inet = OPEN;
01636         }
01637 
01638     *iblk_ptr = iblk;
01639     *inet_ptr = inet;
01640 }

Here is the caller graph for this function:

float load_net_slack ( float **  net_slack,
float  target_cycle_time 
)

Definition at line 1345 of file path_delay.c.

01347 {
01348 
01349 /* Determines the slack of every source-sink pair of block pins in the      *
01350  * circuit.  The timing graph must have already been built.  target_cycle_  *
01351  * time is the target delay for the circuit -- if 0, the target_cycle_time  *
01352  * is set to the critical path found in the timing graph.  This routine     *
01353  * loads net_slack, and returns the current critical path delay.            */
01354 
01355     float T_crit, T_arr, Tdel, T_cycle, T_req;
01356     int inode, ilevel, num_at_level, i, num_edges, iedge, to_node;
01357     t_tedge *tedge;
01358 
01359 /* Reset all arrival times to -ve infinity.  Can't just set to zero or the   *
01360  * constant propagation (constant generators work at -ve infinity) won't     *
01361  * work.                                                                     */
01362 
01363     for(inode = 0; inode < num_tnodes; inode++)
01364         tnode[inode].T_arr = T_CONSTANT_GENERATOR;
01365 
01366 /* Compute all arrival times with a breadth-first analysis from inputs to   *
01367  * outputs.  Also compute critical path (T_crit).                           */
01368 
01369     T_crit = 0.;
01370 
01371 /* Primary inputs arrive at T = 0. */
01372 
01373     num_at_level = tnodes_at_level[0].nelem;
01374     for(i = 0; i < num_at_level; i++)
01375         {
01376             inode = tnodes_at_level[0].list[i];
01377             tnode[inode].T_arr = 0.;
01378         }
01379 
01380     for(ilevel = 0; ilevel < num_tnode_levels; ilevel++)
01381         {
01382             num_at_level = tnodes_at_level[ilevel].nelem;
01383 
01384             for(i = 0; i < num_at_level; i++)
01385                 {
01386                     inode = tnodes_at_level[ilevel].list[i];
01387                     T_arr = tnode[inode].T_arr;
01388                     num_edges = tnode[inode].num_edges;
01389                     tedge = tnode[inode].out_edges;
01390                     T_crit = max(T_crit, T_arr);
01391 
01392                     for(iedge = 0; iedge < num_edges; iedge++)
01393                         {
01394                             to_node = tedge[iedge].to_node;
01395                             Tdel = tedge[iedge].Tdel;
01396                             tnode[to_node].T_arr =
01397                                 max(tnode[to_node].T_arr, T_arr + Tdel);
01398                         }
01399                 }
01400 
01401         }
01402 
01403     if(target_cycle_time > 0.)  /* User specified target cycle time */
01404         T_cycle = target_cycle_time;
01405     else                        /* Otherwise, target = critical path */
01406         T_cycle = T_crit;
01407 
01408 /* Compute the required arrival times with a backward breadth-first analysis *
01409  * from sinks (output pads, etc.) to primary inputs.                         */
01410 
01411     for(ilevel = num_tnode_levels - 1; ilevel >= 0; ilevel--)
01412         {
01413             num_at_level = tnodes_at_level[ilevel].nelem;
01414 
01415             for(i = 0; i < num_at_level; i++)
01416                 {
01417                     inode = tnodes_at_level[ilevel].list[i];
01418                     num_edges = tnode[inode].num_edges;
01419 
01420                     if(num_edges == 0)
01421                         {       /* sink */
01422                             tnode[inode].T_req = T_cycle;
01423                         }
01424                     else
01425                         {
01426                             tedge = tnode[inode].out_edges;
01427                             to_node = tedge[0].to_node;
01428                             Tdel = tedge[0].Tdel;
01429                             T_req = tnode[to_node].T_req - Tdel;
01430 
01431                             for(iedge = 1; iedge < num_edges; iedge++)
01432                                 {
01433                                     to_node = tedge[iedge].to_node;
01434                                     Tdel = tedge[iedge].Tdel;
01435                                     T_req =
01436                                         min(T_req,
01437                                             tnode[to_node].T_req - Tdel);
01438                                 }
01439 
01440                             tnode[inode].T_req = T_req;
01441                         }
01442                 }
01443         }
01444 
01445     compute_net_slacks(net_slack);
01446 
01447     return (T_crit);
01448 }

Here is the call graph for this function:

Here is the caller graph for this function:

void load_timing_graph_net_delays ( float **  net_delay  ) 

Definition at line 1191 of file path_delay.c.

01192 {
01193 
01194 /* Sets the delays of the inter-FB nets to the values specified by          *
01195  * net_delay[0..num_nets-1][1..num_pins-1].  These net delays should have    *
01196  * been allocated and loaded with the net_delay routines.  This routine      *
01197  * marks the corresponding edges in the timing graph with the proper delay.  */
01198 
01199     int inet, ipin, inode;
01200     t_tedge *tedge;
01201 
01202     for(inet = 0; inet < num_nets; inet++)
01203         {
01204             inode = net_to_driver_tnode[inet];
01205             tedge = tnode[inode].out_edges;
01206 
01207 /* Note that the edges of a tnode corresponding to a FB or INPAD opin must  *
01208  * be in the same order as the pins of the net driven by the tnode.          */
01209 
01210             for(ipin = 1; ipin < (net[inet].num_sinks + 1); ipin++)
01211                 tedge[ipin - 1].Tdel = net_delay[inet][ipin];
01212         }
01213 }

Here is the caller graph for this function:

void print_critical_path ( char *  fname,
t_subblock_data  subblock_data 
)

Definition at line 1480 of file path_delay.c.

01482 {
01483 
01484 /* Prints out the critical path to a file.  */
01485 
01486     t_linked_int *critical_path_head, *critical_path_node;
01487     FILE *fp;
01488     int non_global_nets_on_crit_path, global_nets_on_crit_path;
01489     int tnodes_on_crit_path, inode, iblk, inet;
01490     t_tnode_type type;
01491     float total_net_delay, total_logic_delay, Tdel;
01492 
01493     critical_path_head = allocate_and_load_critical_path();
01494     critical_path_node = critical_path_head;
01495 
01496     fp = my_fopen(fname, "w");
01497 
01498     non_global_nets_on_crit_path = 0;
01499     global_nets_on_crit_path = 0;
01500     tnodes_on_crit_path = 0;
01501     total_net_delay = 0.;
01502     total_logic_delay = 0.;
01503 
01504     while(critical_path_node != NULL)
01505         {
01506             Tdel =
01507                 print_critical_path_node(fp, critical_path_node,
01508                                          subblock_data);
01509             inode = critical_path_node->data;
01510             type = tnode_descript[inode].type;
01511             tnodes_on_crit_path++;
01512 
01513             if(type == INPAD_OPIN || type == FB_OPIN)
01514                 {
01515                     get_tnode_block_and_output_net(inode, &iblk, &inet);
01516 
01517                     if(!net[inet].is_global)
01518                         non_global_nets_on_crit_path++;
01519                     else
01520                         global_nets_on_crit_path++;
01521 
01522                     total_net_delay += Tdel;
01523                 }
01524             else
01525                 {
01526                     total_logic_delay += Tdel;
01527                 }
01528 
01529             critical_path_node = critical_path_node->next;
01530         }
01531 
01532     fprintf(fp,
01533             "\nTnodes on crit. path: %d  Non-global nets on crit. path: %d."
01534             "\n", tnodes_on_crit_path, non_global_nets_on_crit_path);
01535     fprintf(fp, "Global nets on crit. path: %d.\n", global_nets_on_crit_path);
01536     fprintf(fp, "Total logic delay: %g (s)  Total net delay: %g (s)\n",
01537             total_logic_delay, total_net_delay);
01538 
01539     printf("Nets on crit. path: %d normal, %d global.\n",
01540            non_global_nets_on_crit_path, global_nets_on_crit_path);
01541 
01542     printf("Total logic delay: %g (s)  Total net delay: %g (s)\n",
01543            total_logic_delay, total_net_delay);
01544 
01545     fclose(fp);
01546     free_int_list(&critical_path_head);
01547 }

Here is the call graph for this function:

Here is the caller graph for this function:

void print_net_slack ( char *  fname,
float **  net_slack 
)

Definition at line 1249 of file path_delay.c.

01251 {
01252 
01253 /* Prints the net slacks into a file.                                     */
01254 
01255     int inet, ipin;
01256     FILE *fp;
01257 
01258     fp = my_fopen(fname, "w");
01259 
01260     fprintf(fp, "Net #\tSlacks\n\n");
01261 
01262     for(inet = 0; inet < num_nets; inet++)
01263         {
01264             fprintf(fp, "%5d", inet);
01265             for(ipin = 1; ipin < (net[inet].num_sinks + 1); ipin++)
01266                 {
01267                     fprintf(fp, "\t%g", net_slack[inet][ipin]);
01268                 }
01269             fprintf(fp, "\n");
01270         }
01271 }

Here is the call graph for this function:

Here is the caller graph for this function:

void print_timing_graph ( char *  fname  ) 

Definition at line 1275 of file path_delay.c.

01276 {
01277 
01278 /* Prints the timing graph into a file.           */
01279 
01280     FILE *fp;
01281     int inode, iedge, ilevel, i;
01282     t_tedge *tedge;
01283     t_tnode_type itype;
01284     char *tnode_type_names[] = { "INPAD_SOURCE", "INPAD_OPIN",
01285         "OUTPAD_IPIN", "OUTPAD_SINK", "FB_IPIN", "FB_OPIN",
01286         "SUBBLK_IPIN", "SUBBLK_OPIN", "FF_SINK", "FF_SOURCE",
01287         "CONSTANT_GEN_SOURCE"
01288     };
01289 
01290 
01291     fp = my_fopen(fname, "w");
01292 
01293     fprintf(fp, "num_tnodes: %d\n", num_tnodes);
01294     fprintf(fp, "Node #\tType\t\tipin\tisubblk\tiblk\t# edges\t"
01295             "Edges (to_node, Tdel)\n\n");
01296 
01297     for(inode = 0; inode < num_tnodes; inode++)
01298         {
01299             fprintf(fp, "%d\t", inode);
01300 
01301             itype = tnode_descript[inode].type;
01302             fprintf(fp, "%-15.15s\t", tnode_type_names[itype]);
01303 
01304             fprintf(fp, "%d\t%d\t%d\t", tnode_descript[inode].ipin,
01305                     tnode_descript[inode].isubblk,
01306                     tnode_descript[inode].iblk);
01307 
01308             fprintf(fp, "%d\t", tnode[inode].num_edges);
01309             tedge = tnode[inode].out_edges;
01310             for(iedge = 0; iedge < tnode[inode].num_edges; iedge++)
01311                 {
01312                     fprintf(fp, "\t(%4d,%7.3g)", tedge[iedge].to_node,
01313                             tedge[iedge].Tdel);
01314                 }
01315             fprintf(fp, "\n");
01316         }
01317 
01318     fprintf(fp, "\n\nnum_tnode_levels: %d\n", num_tnode_levels);
01319 
01320     for(ilevel = 0; ilevel < num_tnode_levels; ilevel++)
01321         {
01322             fprintf(fp, "\n\nLevel: %d  Num_nodes: %d\nNodes:", ilevel,
01323                     tnodes_at_level[ilevel].nelem);
01324             for(i = 0; i < tnodes_at_level[ilevel].nelem; i++)
01325                 fprintf(fp, "\t%d", tnodes_at_level[ilevel].list[i]);
01326         }
01327 
01328     fprintf(fp, "\n");
01329     fprintf(fp, "\n\nNet #\tNet_to_driver_tnode\n");
01330 
01331     for(i = 0; i < num_nets; i++)
01332         fprintf(fp, "%4d\t%6d\n", i, net_to_driver_tnode[i]);
01333 
01334     fprintf(fp, "\n\nNode #\t\tT_arr\t\tT_req\n\n");
01335 
01336     for(inode = 0; inode < num_tnodes; inode++)
01337         fprintf(fp, "%d\t%12g\t%12g\n", inode, tnode[inode].T_arr,
01338                 tnode[inode].T_req);
01339 
01340     fclose(fp);
01341 }

Here is the call graph for this function:

Here is the caller graph for this function:


Generated on Tue Jan 5 15:25:55 2010 for VPR5.0 by  doxygen 1.6.1