SRC/rr_graph_timing_params.c File Reference

#include <assert.h>
#include "util.h"
#include "vpr_types.h"
#include "globals.h"
#include "rr_graph.h"
#include "rr_graph_util.h"
#include "rr_graph2.h"
#include "rr_graph_timing_params.h"
Include dependency graph for rr_graph_timing_params.c:

Go to the source code of this file.

Functions

void add_rr_graph_C_from_switches (float C_ipin_cblock)

Function Documentation

void add_rr_graph_C_from_switches ( float  C_ipin_cblock  ) 

Definition at line 16 of file rr_graph_timing_params.c.

00017 {
00018 
00019 /* This routine finishes loading the C elements of the rr_graph. It assumes *
00020  * that when you call it the CHANX and CHANY nodes have had their C set to  *
00021  * their metal capacitance, and everything else has C set to 0.  The graph  *
00022  * connectivity (edges, switch types etc.) must all be loaded too.  This    *
00023  * routine will add in the capacitance on the CHANX and CHANY nodes due to: *
00024  *                                                                          *
00025  * 1) The output capacitance of the switches coming from OPINs;             *
00026  * 2) The input and output capacitance of the switches between the various  *
00027  *    wiring (CHANX and CHANY) segments; and                                *
00028  * 3) The input capacitance of the buffers separating routing tracks from   *
00029  *    the connection block inputs.                                          */
00030 
00031 
00032     int inode, iedge, switch_index, to_node, maxlen;
00033     int icblock, isblock, iseg_low, iseg_high;
00034     float Cin, Cout;
00035     t_rr_type from_rr_type, to_rr_type;
00036     boolean *cblock_counted;    /* [0..max(nx,ny)] -- 0th element unused. */
00037     float *buffer_Cin;          /* [0..max(nx,ny)] */
00038     boolean buffered;
00039     float *Couts_to_add;        /* UDSD */
00040 
00041     maxlen = max(nx, ny) + 1;
00042     cblock_counted = (boolean *) my_calloc(maxlen, sizeof(boolean));
00043     buffer_Cin = (float *)my_calloc(maxlen, sizeof(float));
00044 
00045     for(inode = 0; inode < num_rr_nodes; inode++)
00046         {
00047 
00048             from_rr_type = rr_node[inode].type;
00049 
00050             if(from_rr_type == CHANX || from_rr_type == CHANY)
00051                 {
00052 
00053                     for(iedge = 0; iedge < rr_node[inode].num_edges; iedge++)
00054                         {
00055 
00056                             to_node = rr_node[inode].edges[iedge];
00057                             to_rr_type = rr_node[to_node].type;
00058 
00059                             if(to_rr_type == CHANX || to_rr_type == CHANY)
00060                                 {
00061 
00062                                     switch_index =
00063                                         rr_node[inode].switches[iedge];
00064                                     Cin = switch_inf[switch_index].Cin;
00065                                     Cout = switch_inf[switch_index].Cout;
00066                                     buffered =
00067                                         switch_inf[switch_index].buffered;
00068 
00069                                     /* If both the switch from inode to to_node and the switch from *
00070                                      * to_node back to inode use bidirectional switches (i.e. pass  *
00071                                      * transistors), there will only be one physical switch for     *
00072                                      * both edges.  Hence, I only want to count the capacitance of  *
00073                                      * that switch for one of the two edges.  (Note:  if there is   *
00074                                      * a pass transistor edge from x to y, I always build the graph *
00075                                      * so that there is a corresponding edge using the same switch  *
00076                                      * type from y to x.) So, I arbitrarily choose to add in the    *
00077                                      * capacitance in that case of a pass transistor only when      *
00078                                      * processing the the lower inode number.                       *
00079                                      * If an edge uses a buffer I always have to add in the output  *
00080                                      * capacitance.  I assume that buffers are shared at the same   *
00081                                      * (i,j) location, so only one input capacitance needs to be    *
00082                                      * added for all the buffered switches at that location.  If    *
00083                                      * the buffers at that location have different sizes, I use the *
00084                                      * input capacitance of the largest one.                        */
00085 
00086                                     if(!buffered && inode < to_node)
00087                                         {       /* Pass transistor. */
00088                                             rr_node[inode].C += Cin;
00089                                             rr_node[to_node].C += Cout;
00090                                         }
00091 
00092                                     else if(buffered)
00093                                         {
00094                                             /* Prevent double counting of capacitance for UDSD */
00095                                             if(rr_node[to_node].drivers !=
00096                                                SINGLE)
00097                                                 {
00098                                                     /* For multiple-driver architectures the output capacitance can
00099                                                      * be added now since each edge is actually a driver */
00100                                                     rr_node[to_node].C +=
00101                                                         Cout;
00102                                                 }
00103                                             isblock =
00104                                                 seg_index_of_sblock(inode,
00105                                                                     to_node);
00106                                             buffer_Cin[isblock] =
00107                                                 max(buffer_Cin[isblock], Cin);
00108                                         }
00109 
00110                                 }
00111                             /* End edge to CHANX or CHANY node. */
00112                             else if(to_rr_type == IPIN)
00113                                 {
00114 
00115                                     /* Code below implements sharing of the track to connection     *
00116                                      * box buffer.  I assume there is one such buffer at every      *
00117                                      * segment of the wire at which at least one logic block input  *
00118                                      * connects.                                                    */
00119 
00120                                     icblock =
00121                                         seg_index_of_cblock(from_rr_type,
00122                                                             to_node);
00123                                     if(cblock_counted[icblock] == FALSE)
00124                                         {
00125                                             rr_node[inode].C += C_ipin_cblock;
00126                                             cblock_counted[icblock] = TRUE;
00127                                         }
00128                                 }
00129                         }       /* End loop over all edges of a node. */
00130 
00131                     /* Reset the cblock_counted and buffer_Cin arrays, and add buf Cin. */
00132 
00133                     /* Method below would be faster for very unpopulated segments, but I  *
00134                      * think it would be slower overall for most FPGAs, so commented out. */
00135 
00136                     /*   for (iedge=0;iedge<rr_node[inode].num_edges;iedge++) {
00137                      * to_node = rr_node[inode].edges[iedge];
00138                      * if (rr_node[to_node].type == IPIN) {
00139                      * icblock = seg_index_of_cblock (from_rr_type, to_node);
00140                      * cblock_counted[icblock] = FALSE;
00141                      * }
00142                      * }     */
00143 
00144                     if(from_rr_type == CHANX)
00145                         {
00146                             iseg_low = rr_node[inode].xlow;
00147                             iseg_high = rr_node[inode].xhigh;
00148                         }
00149                     else
00150                         {       /* CHANY */
00151                             iseg_low = rr_node[inode].ylow;
00152                             iseg_high = rr_node[inode].yhigh;
00153                         }
00154 
00155                     for(icblock = iseg_low; icblock <= iseg_high; icblock++)
00156                         {
00157                             cblock_counted[icblock] = FALSE;
00158                         }
00159 
00160                     for(isblock = iseg_low - 1; isblock <= iseg_high;
00161                         isblock++)
00162                         {
00163                             rr_node[inode].C += buffer_Cin[isblock];    /* Biggest buf Cin at loc */
00164                             buffer_Cin[isblock] = 0.;
00165                         }
00166 
00167                 }
00168             /* End node is CHANX or CHANY */
00169             else if(from_rr_type == OPIN)
00170                 {
00171 
00172                     for(iedge = 0; iedge < rr_node[inode].num_edges; iedge++)
00173                         {
00174                             switch_index = rr_node[inode].switches[iedge];
00175                             /* UDSD by ICK Start */
00176                             to_node = rr_node[inode].edges[iedge];
00177                             to_rr_type = rr_node[to_node].type;
00178                             assert(to_rr_type == CHANX
00179                                    || to_rr_type == CHANY);
00180                             if(rr_node[to_node].drivers != SINGLE)
00181                                 {
00182                                     Cout = switch_inf[switch_index].Cout;
00183                                     to_node = rr_node[inode].edges[iedge];      /* Will be CHANX or CHANY */
00184                                     rr_node[to_node].C += Cout;
00185                                 }
00186                         }
00187                 }
00188             /* End node is OPIN. */
00189         }                       /* End for all nodes. */
00190 
00191     /* Now we need to add any cout loads for nets that we previously didn't process
00192      * Current structures only keep switch information from a node to the next node and
00193      * not the reverse.  Therefore I need to go through all the possible edges to figure 
00194      * out what the Cout's should be */
00195     Couts_to_add = (float *)my_calloc(num_rr_nodes, sizeof(float));
00196     for(inode = 0; inode < num_rr_nodes; inode++)
00197         {
00198             for(iedge = 0; iedge < rr_node[inode].num_edges; iedge++)
00199                 {
00200                     switch_index = rr_node[inode].switches[iedge];
00201                     to_node = rr_node[inode].edges[iedge];
00202                     to_rr_type = rr_node[to_node].type;
00203                     if(to_rr_type == CHANX || to_rr_type == CHANY)
00204                         {
00205                             if(rr_node[to_node].drivers == SINGLE)
00206                                 {
00207                                     /* Cout was not added in these cases */
00208                                     if(Couts_to_add[to_node] != 0)
00209                                         {
00210                                             /* We've already found a Cout to add to this node
00211                                              * We could take the max of all possibilities but
00212                                              * instead I will fail if there are conflicting Couts */
00213                                             if(Couts_to_add[to_node] !=
00214                                                switch_inf[switch_index].Cout)
00215                                                 {
00216                                                     printf
00217                                                         ("Error: A single driver resource (%i) is driven by different Cout's (%e!=%e)\n",
00218                                                          to_node,
00219                                                          Couts_to_add
00220                                                          [to_node],
00221                                                          switch_inf
00222                                                          [switch_index].Cout);
00223                                                     exit(1);
00224                                                 }
00225                                         }
00226                                     Couts_to_add[to_node] =
00227                                         switch_inf[switch_index].Cout;
00228 
00229                                 }
00230                         }
00231                 }
00232         }
00233     for(inode = 0; inode < num_rr_nodes; inode++)
00234         {
00235             rr_node[inode].C += Couts_to_add[inode];
00236         }
00237     free(Couts_to_add);
00238     free(cblock_counted);
00239     free(buffer_Cin);
00240 }

Here is the call graph for this function:

Here is the caller graph for this function:


Generated on Tue Jan 5 15:26:33 2010 for VPR5.0 by  doxygen 1.6.1