00001 #include <assert.h>
00002 #include "util.h"
00003 #include "vpr_types.h"
00004 #include "globals.h"
00005 #include "path_delay2.h"
00006
00007
00008
00009
00010 t_tnode *tnode;
00011 t_tnode_descript *tnode_descript;
00012 int num_tnodes;
00013
00014
00015
00016 int *net_to_driver_tnode;
00017
00018
00019
00020
00021
00022 struct s_ivec *tnodes_at_level;
00023 int num_tnode_levels;
00024
00025
00026
00027
00028
00029 static int *alloc_and_load_tnode_fanin_and_check_edges(int *num_sinks_ptr);
00030
00031
00032
00033
00034
00035
00036 static int *
00037 alloc_and_load_tnode_fanin_and_check_edges(int *num_sinks_ptr)
00038 {
00039
00040
00041
00042
00043
00044 int inode, iedge, to_node, num_edges, error, num_sinks;
00045 int *tnode_num_fanin;
00046 t_tedge *tedge;
00047
00048 tnode_num_fanin = (int *)my_calloc(num_tnodes, sizeof(int));
00049 error = 0;
00050 num_sinks = 0;
00051
00052 for(inode = 0; inode < num_tnodes; inode++)
00053 {
00054 num_edges = tnode[inode].num_edges;
00055
00056 if(num_edges > 0)
00057 {
00058 tedge = tnode[inode].out_edges;
00059 for(iedge = 0; iedge < num_edges; iedge++)
00060 {
00061 to_node = tedge[iedge].to_node;
00062
00063 if(to_node < 0 || to_node >= num_tnodes)
00064 {
00065 printf
00066 ("Error in alloc_and_load_tnode_fanin_and_check_edges:\n"
00067 "tnode #%d edge #%d goes to illegal node #%d.\n",
00068 inode, iedge, to_node);
00069 error++;
00070 }
00071
00072 tnode_num_fanin[to_node]++;
00073 }
00074 }
00075
00076 else if(num_edges == 0)
00077 {
00078 num_sinks++;
00079 }
00080
00081 else
00082 {
00083 printf
00084 ("Error in alloc_and_load_tnode_fanin_and_check_edges: \n"
00085 "tnode #%d has %d edges.\n", inode, num_edges);
00086 error++;
00087 }
00088
00089 }
00090
00091 if(error != 0)
00092 {
00093 printf("Found %d Errors in the timing graph. Aborting.\n",
00094 error);
00095 exit(1);
00096 }
00097
00098 *num_sinks_ptr = num_sinks;
00099 return (tnode_num_fanin);
00100 }
00101
00102
00103 int
00104 alloc_and_load_timing_graph_levels(void)
00105 {
00106
00107
00108
00109
00110
00111 t_linked_int *free_list_head, *nodes_at_level_head;
00112 int inode, num_at_level, iedge, to_node, num_edges, num_sinks,
00113 num_levels, i;
00114 t_tedge *tedge;
00115
00116
00117
00118
00119 int *tnode_fanin_left;
00120
00121
00122 tnode_fanin_left = alloc_and_load_tnode_fanin_and_check_edges(&num_sinks);
00123
00124 free_list_head = NULL;
00125 nodes_at_level_head = NULL;
00126
00127
00128
00129
00130
00131 tnodes_at_level = (struct s_ivec *)my_malloc((num_tnodes + 1) *
00132 sizeof(struct s_ivec));
00133
00134
00135
00136
00137 num_at_level = 0;
00138
00139 for(inode = 0; inode < num_tnodes; inode++)
00140 {
00141 if(tnode_fanin_left[inode] == 0)
00142 {
00143 num_at_level++;
00144 nodes_at_level_head =
00145 insert_in_int_list(nodes_at_level_head, inode,
00146 &free_list_head);
00147 }
00148 }
00149
00150 alloc_ivector_and_copy_int_list(&nodes_at_level_head, num_at_level,
00151 &tnodes_at_level[0], &free_list_head);
00152
00153 num_levels = 0;
00154
00155 while(num_at_level != 0)
00156 {
00157 num_levels++;
00158 num_at_level = 0;
00159
00160 for(i = 0; i < tnodes_at_level[num_levels - 1].nelem; i++)
00161 {
00162 inode = tnodes_at_level[num_levels - 1].list[i];
00163 tedge = tnode[inode].out_edges;
00164 num_edges = tnode[inode].num_edges;
00165
00166 for(iedge = 0; iedge < num_edges; iedge++)
00167 {
00168 to_node = tedge[iedge].to_node;
00169 tnode_fanin_left[to_node]--;
00170
00171 if(tnode_fanin_left[to_node] == 0)
00172 {
00173 num_at_level++;
00174 nodes_at_level_head =
00175 insert_in_int_list
00176 (nodes_at_level_head, to_node,
00177 &free_list_head);
00178 }
00179 }
00180 }
00181
00182 alloc_ivector_and_copy_int_list(&nodes_at_level_head,
00183 num_at_level,
00184 &tnodes_at_level[num_levels],
00185 &free_list_head);
00186 }
00187
00188 tnodes_at_level =
00189 (struct s_ivec *)my_realloc(tnodes_at_level,
00190 num_levels * sizeof(struct s_ivec));
00191 num_tnode_levels = num_levels;
00192
00193 free(tnode_fanin_left);
00194 free_int_list(&free_list_head);
00195 return (num_sinks);
00196 }
00197
00198
00199 void
00200 check_timing_graph(int num_const_gen,
00201 int num_ff,
00202 int num_sinks)
00203 {
00204
00205
00206
00207
00208
00209
00210
00211 int i, j, num_tnodes_check, ilevel, inet, inode, error, num_p_inputs,
00212 num_p_outputs;
00213
00214 error = 0;
00215 num_tnodes_check = 0;
00216 num_p_inputs = 0;
00217 num_p_outputs = 0;
00218
00219
00220 for(i = 0; i < num_blocks; i++)
00221 {
00222 if(block[i].type == IO_TYPE)
00223 {
00224 for(j = 0; j < IO_TYPE->num_pins; j++)
00225 {
00226 if(block[i].nets[j] != OPEN)
00227 {
00228 if(IO_TYPE->
00229 class_inf[IO_TYPE->pin_class[j]].
00230 type == DRIVER)
00231 {
00232 num_p_inputs++;
00233 }
00234 else
00235 {
00236 assert(IO_TYPE->
00237 class_inf[IO_TYPE->
00238 pin_class[j]].
00239 type == RECEIVER);
00240 num_p_outputs++;
00241 }
00242 }
00243 }
00244 }
00245 }
00246
00247 for(ilevel = 0; ilevel < num_tnode_levels; ilevel++)
00248 num_tnodes_check += tnodes_at_level[ilevel].nelem;
00249
00250 if(num_tnodes_check != num_tnodes)
00251 {
00252 printf
00253 ("Error in check_timing_graph: %d tnodes appear in the tnode level "
00254 "structure. Expected %d.\n", num_tnodes_check, num_tnodes);
00255 printf("Check the netlist for combinational cycles.\n");
00256 error++;
00257 }
00258
00259 if(num_const_gen + num_p_inputs != tnodes_at_level[0].nelem)
00260 {
00261 printf
00262 ("Error in check_timing_graph: %d tnodes are sources (have no "
00263 "inputs -- expected %d.\n", tnodes_at_level[0].nelem,
00264 num_const_gen + num_p_inputs);
00265 error++;
00266 }
00267
00268 if(num_sinks != num_p_outputs + num_ff)
00269 {
00270 printf
00271 ("Error in check_timing_graph: %d tnodes are sinks (have no "
00272 "outputs -- expected %d.\n", num_sinks,
00273 num_ff + num_p_outputs);
00274 error++;
00275 }
00276
00277 for(inet = 0; inet < num_nets; inet++)
00278 {
00279 inode = net_to_driver_tnode[inet];
00280 if(inode < 0 || inode >= num_tnodes)
00281 {
00282 printf("Error in check_timing_graph:\n"
00283 "\tdriver of net %d has a tnode mapping of %d (out of range).\n",
00284 inet, inode);
00285 error++;
00286 }
00287 }
00288
00289 if(error != 0)
00290 {
00291 printf("Found %d Errors in the timing graph. Aborting.\n",
00292 error);
00293 exit(1);
00294 }
00295 }
00296
00297
00298 float
00299 print_critical_path_node(FILE * fp,
00300 t_linked_int * critical_path_node,
00301 t_subblock_data subblock_data)
00302 {
00303
00304
00305
00306
00307 int inode, iblk, ipin, inet, downstream_node;
00308 t_tnode_type type;
00309 static char *tnode_type_names[] = { "INPAD_SOURCE", "INPAD_OPIN",
00310 "OUTPAD_IPIN", "OUTPAD_SINK", "CLB_IPIN", "CLB_OPIN",
00311 "SUBBLK_IPIN", "SUBBLK_OPIN", "FF_SINK", "FF_SOURCE",
00312 "CONSTANT_GEN_SOURCE"
00313 };
00314 t_linked_int *next_crit_node;
00315 float Tdel;
00316
00317 inode = critical_path_node->data;
00318 type = tnode_descript[inode].type;
00319 iblk = tnode_descript[inode].iblk;
00320 ipin = tnode_descript[inode].ipin;
00321
00322 fprintf(fp, "Node: %d %s Block #%d (%s)\n", inode,
00323 tnode_type_names[type], iblk, block[iblk].name);
00324
00325 if(type != INPAD_SOURCE && type != OUTPAD_SINK && type != FF_SINK &&
00326 type != FF_SOURCE && type != CONSTANT_GEN_SOURCE)
00327 {
00328 fprintf(fp, "Pin: %d ", ipin);
00329 }
00330
00331 if(type == SUBBLK_IPIN || type == SUBBLK_OPIN || type == FF_SINK
00332 || type == FF_SOURCE || type == CONSTANT_GEN_SOURCE)
00333 {
00334 fprintf(fp, "Subblock #%d subpin #%d",
00335 tnode_descript[inode].isubblk,
00336 tnode_descript[inode].ipin);
00337 }
00338
00339 if(type != INPAD_SOURCE && type != OUTPAD_SINK)
00340 {
00341 fprintf(fp, "\n");
00342 }
00343
00344 fprintf(fp, "T_arr: %g T_req: %g ", tnode[inode].T_arr,
00345 tnode[inode].T_req);
00346
00347 next_crit_node = critical_path_node->next;
00348 if(next_crit_node != NULL)
00349 {
00350 downstream_node = next_crit_node->data;
00351 Tdel = tnode[downstream_node].T_arr - tnode[inode].T_arr;
00352 fprintf(fp, "Tdel: %g\n", Tdel);
00353 }
00354 else
00355 {
00356 Tdel = 0.;
00357 fprintf(fp, "\n");
00358 }
00359
00360 if(type == FB_OPIN)
00361 {
00362 inet = block[iblk].nets[ipin];
00363 fprintf(fp, "Net to next node: #%d (%s). Pins on net: %d.\n",
00364 inet, net[inet].name, (net[inet].num_sinks + 1));
00365 }
00366
00367 if(type == INPAD_OPIN)
00368 {
00369 ipin =
00370 subblock_data.subblock_inf[iblk][tnode_descript[inode].
00371 isubblk].outputs[ipin];
00372 inet = block[iblk].nets[ipin];
00373 fprintf(fp, "Net to next node: #%d (%s). Pins on net: %d.\n",
00374 inet, net[inet].name, (net[inet].num_sinks + 1));
00375 }
00376
00377 fprintf(fp, "\n");
00378 return (Tdel);
00379 }