VPR-6.0

vpr/SRC/pack/pb_type_graph.c

Go to the documentation of this file.
00001 /**
00002  * @file
00003  *
00004  * Jason Luu
00005  * July 17, 2009
00006  * pb_graph creates the internal routing edges that join together the different
00007  * pb_types modes within a pb_type
00008  */
00009 
00010 #include <stdio.h>
00011 #include <assert.h>
00012 #include <string.h>
00013 
00014 #include "util.h"
00015 #include "token.h"
00016 #include "arch_types.h"
00017 #include "vpr_types.h"
00018 #include "globals.h"
00019 #include "vpr_utils.h"
00020 #include "pb_type_graph.h"
00021 #include "pb_type_graph_annotations.h"
00022 
00023 /** variable global to this section that indexes each pb graph pin within a cluster */
00024 static int pin_count_in_cluster;
00025 static struct s_linked_vptr *edges_head;
00026 static struct s_linked_vptr *num_edges_head;
00027 
00028 /* TODO: Software engineering decision needed: Move this file to libarch?
00029 
00030 */
00031 
00032 static int check_pb_graph ();
00033 static void alloc_and_load_pb_graph(INOUTP t_pb_graph_node *pb_graph_node, 
00034                                                                         INP t_pb_graph_node *parent_pb_graph_node,
00035                                                                         INP const t_pb_type *pb_type, 
00036                                                                         INP int index);
00037 
00038 static void alloc_and_load_mode_interconnect(INOUTP t_pb_graph_node *pb_graph_parent_node, 
00039                                                                                         INOUTP t_pb_graph_node **pb_graph_children_nodes,
00040                                                                                         INP const t_mode * mode);
00041 
00042 static boolean realloc_and_load_pb_graph_pin_ptrs_at_var(INP const t_pb_graph_node *pb_graph_parent_node, 
00043                                                                                                         INP t_pb_graph_node **pb_graph_children_nodes,
00044                                                                                                         INP boolean interconnect_error_check,
00045                                                                                                         INP boolean is_input_to_interc,
00046                                                                                                         INP const t_token *tokens,
00047                                                                                                         INOUTP int *token_index, 
00048                                                                                                         INOUTP int *num_pins,
00049                                                                                                         OUTP t_pb_graph_pin ***pb_graph_pins);
00050 
00051 static t_pb_graph_pin * get_pb_graph_pin_from_name(INP const char * port_name, INP const t_pb_graph_node * pb, INP int pin);
00052 
00053 
00054 static void alloc_and_load_complete_interc_edges(INP t_interconnect * interconnect,
00055                                                                                                  INOUTP t_pb_graph_pin *** input_pb_graph_node_pin_ptrs, 
00056                                                                                                  INP int num_input_sets,
00057                                                                                                  INP int *num_input_ptrs,
00058                                                                                                  INOUTP t_pb_graph_pin *** output_pb_graph_node_pin_ptrs,
00059                                                                                                  INP int num_output_sets,
00060                                                                                                  INP int *num_output_ptrs);
00061 
00062 static void alloc_and_load_direct_interc_edges(INP t_interconnect * interconnect, INOUTP t_pb_graph_pin *** input_pb_graph_node_pin_ptrs, 
00063                                                                                                  INP int num_input_sets,
00064                                                                                                  INP int *num_input_ptrs,
00065                                                                                                  INOUTP t_pb_graph_pin *** output_pb_graph_node_pin_ptrs,
00066                                                                                                  INP int num_output_sets,
00067                                                                                                  INP int *num_output_ptrs);
00068 
00069 static void alloc_and_load_mux_interc_edges(INP t_interconnect * interconnect, INOUTP t_pb_graph_pin *** input_pb_graph_node_pin_ptrs, 
00070                                                                                                  INP int num_input_sets,
00071                                                                                                  INP int *num_input_ptrs,
00072                                                                                                  INOUTP t_pb_graph_pin *** output_pb_graph_node_pin_ptrs,
00073                                                                                                  INP int num_output_sets,
00074                                                                                                  INP int *num_output_ptrs);
00075 
00076 static void alloc_and_load_pin_locations_from_pb_graph(t_type_descriptor *type);
00077 
00078 static void echo_pb_rec(INP const t_pb_graph_node *pb, INP int level, INP FILE * fp);
00079 static void echo_pb_pins(INP t_pb_graph_pin **pb_graph_pins, INP int num_ports, INP int level, INP FILE * fp);
00080 static void free_pb_graph(INOUTP t_pb_graph_node *pb_graph_node);
00081 
00082 /**
00083  * Allocate memory into types and load the pb graph with interconnect edges 
00084  */
00085 void alloc_and_load_all_pb_graphs () {
00086         int i, errors;
00087         edges_head = NULL;
00088         num_edges_head = NULL;
00089         for(i = 0; i < num_types; i++) {
00090                 if(type_descriptors[i].pb_type) {
00091                         pin_count_in_cluster = 0;
00092                         type_descriptors[i].pb_graph_head = my_calloc(1, sizeof(t_pb_graph_node));
00093                         alloc_and_load_pb_graph(type_descriptors[i].pb_graph_head, NULL, type_descriptors[i].pb_type, 0);
00094                         type_descriptors[i].pb_graph_head->total_pb_pins = pin_count_in_cluster;
00095                         alloc_and_load_pin_locations_from_pb_graph(&type_descriptors[i]);
00096                 } else {
00097                         type_descriptors[i].pb_graph_head = NULL;
00098                         assert(&type_descriptors[i] == EMPTY_TYPE);
00099                 }
00100         }
00101 
00102         errors = check_pb_graph ();
00103         if(errors > 0) {
00104                 printf("Errors in pb graph");
00105                 exit(1);
00106         }
00107         for(i = 0; i < num_types; i++) {
00108                 if(type_descriptors[i].pb_type) {
00109                         load_pb_graph_pin_to_pin_annotations(type_descriptors[i].pb_graph_head);
00110                 }
00111         }
00112 }
00113 
00114 
00115 /**
00116  * Free pb graph 
00117  */
00118 void free_all_pb_graph_nodes () {
00119         int i;
00120         for(i = 0; i < num_types; i++) {
00121                 if(type_descriptors[i].pb_type) {
00122                         pin_count_in_cluster = 0;
00123                         if(type_descriptors[i].pb_graph_head) {
00124                                 free_pb_graph(type_descriptors[i].pb_graph_head);
00125                         }
00126                 }
00127         }
00128 }
00129 
00130 
00131 /**
00132  * Print out the pb_type graph
00133  */
00134 void echo_pb_graph (char * filename) {
00135         FILE *fp;
00136     int i;
00137 
00138     fp = my_fopen(filename, "w", 0);
00139 
00140     fprintf(fp, "Physical Blocks Graph\n");
00141         fprintf(fp, "--------------------------------------------\n\n");
00142 
00143     for(i = 0; i < num_types; i++)
00144         {
00145                 fprintf(fp, "type %s\n", type_descriptors[i].name);
00146                 if(type_descriptors[i].pb_graph_head)
00147                         echo_pb_rec(type_descriptors[i].pb_graph_head, 1, fp);
00148         }
00149 
00150     fclose(fp);
00151 }
00152 
00153 /**
00154  * check pb_type graph and return the number of errors
00155  */
00156 static int check_pb_graph () {
00157         int num_errors;
00158         /* TODO: Error checks to do 
00159                 1.  All pin and edge connections are bidirectional and match each other
00160                 2.  All pb_type names are unique in a namespace
00161                 3.  All ports are unique in a pb_type
00162                 4.  Number of pb of a pb_type in graph is the same as requested number
00163                 5.  All pins are connected to edges
00164         */
00165         num_errors = 0;
00166 
00167         return num_errors;
00168 }
00169 
00170 static void alloc_and_load_pb_graph(INOUTP t_pb_graph_node *pb_graph_node, 
00171                                                                         INP t_pb_graph_node *parent_pb_graph_node,
00172                                                                         INP const t_pb_type *pb_type, 
00173                                                                         INP int index) {
00174         int i, j, k, i_input, i_output, i_clockport;
00175 
00176         pb_graph_node->placement_index = index;
00177         pb_graph_node->pb_type = pb_type;
00178         pb_graph_node->parent_pb_graph_node = parent_pb_graph_node;
00179 
00180         pb_graph_node->num_input_ports = 0;
00181         pb_graph_node->num_output_ports = 0;
00182         pb_graph_node->num_clock_ports = 0;
00183 
00184         /* Generate ports for pb graph node */
00185         for(i = 0; i < pb_type->num_ports; i++) {
00186                 if(pb_type->ports[i].type == IN_PORT && !pb_type->ports[i].is_clock) {
00187                         pb_graph_node->num_input_ports++;
00188                 } else if(pb_type->ports[i].type == OUT_PORT) {
00189                         assert(!pb_type->ports[i].is_clock);
00190                         pb_graph_node->num_output_ports++;
00191                 } else {
00192                         assert(pb_type->ports[i].is_clock && pb_type->ports[i].type == IN_PORT);
00193                         pb_graph_node->num_clock_ports++;
00194                 } 
00195         }
00196 
00197         pb_graph_node->num_input_pins = my_calloc(pb_graph_node->num_input_ports, sizeof(int));
00198         pb_graph_node->num_output_pins = my_calloc(pb_graph_node->num_output_ports, sizeof(int));
00199         pb_graph_node->num_clock_pins = my_calloc(pb_graph_node->num_clock_ports, sizeof(int));
00200         
00201         pb_graph_node->input_pins = my_calloc(pb_graph_node->num_input_ports, sizeof(t_pb_graph_pin*));
00202         pb_graph_node->output_pins = my_calloc(pb_graph_node->num_output_ports, sizeof(t_pb_graph_pin*));
00203         pb_graph_node->clock_pins = my_calloc(pb_graph_node->num_clock_ports, sizeof(t_pb_graph_pin*));
00204         
00205         i_input = i_output = i_clockport = 0;
00206         for(i = 0; i < pb_type->num_ports; i++) {
00207                 if(pb_type->ports[i].model_port) {
00208                         assert(pb_type->num_modes == 0);
00209                 } else {
00210                         assert(pb_type->num_modes != 0 || pb_type->ports[i].is_clock);
00211                 }
00212                 if(pb_type->ports[i].type == IN_PORT && !pb_type->ports[i].is_clock) {
00213                         pb_graph_node->input_pins[i_input] = my_calloc(pb_type->ports[i].num_pins, sizeof(t_pb_graph_pin));
00214                         pb_graph_node->num_input_pins[i_input] = pb_type->ports[i].num_pins;
00215                         for(j = 0; j < pb_type->ports[i].num_pins; j++) {
00216                                 pb_graph_node->input_pins[i_input][j].input_edges = NULL;
00217                                 pb_graph_node->input_pins[i_input][j].num_input_edges = 0;
00218                                 pb_graph_node->input_pins[i_input][j].output_edges = NULL;
00219                                 pb_graph_node->input_pins[i_input][j].num_output_edges = 0;
00220                                 pb_graph_node->input_pins[i_input][j].pin_number = j;
00221                                 pb_graph_node->input_pins[i_input][j].port = &pb_type->ports[i];
00222                                 pb_graph_node->input_pins[i_input][j].parent_node = pb_graph_node;
00223                                 pb_graph_node->input_pins[i_input][j].pin_count_in_cluster = pin_count_in_cluster;
00224                                 pb_graph_node->input_pins[i_input][j].type = PB_PIN_NORMAL;
00225                                 if(pb_graph_node->pb_type->blif_model != NULL) {
00226                                         if(strcmp(pb_graph_node->pb_type->blif_model, ".output") == 0) {
00227                                                 pb_graph_node->input_pins[i_input][j].type = PB_PIN_OUTPAD;
00228                                         } else if(pb_graph_node->num_clock_ports != 0) {
00229                                                 pb_graph_node->input_pins[i_input][j].type = PB_PIN_SEQUENTIAL;
00230                                         } else {
00231                                                 pb_graph_node->input_pins[i_input][j].type = PB_PIN_TERMINAL;
00232                                         }
00233                                 }
00234                                 pin_count_in_cluster++;
00235                         }
00236                         i_input++;
00237                 } else if(pb_type->ports[i].type == OUT_PORT) {
00238                         pb_graph_node->output_pins[i_output] = my_calloc(pb_type->ports[i].num_pins, sizeof(t_pb_graph_pin));
00239                         pb_graph_node->num_output_pins[i_output] = pb_type->ports[i].num_pins;
00240                         for(j = 0; j < pb_type->ports[i].num_pins; j++) {
00241                                 pb_graph_node->output_pins[i_output][j].input_edges = NULL;
00242                                 pb_graph_node->output_pins[i_output][j].num_input_edges = 0;
00243                                 pb_graph_node->output_pins[i_output][j].output_edges = NULL;
00244                                 pb_graph_node->output_pins[i_output][j].num_output_edges = 0;
00245                                 pb_graph_node->output_pins[i_output][j].pin_number = j;
00246                                 pb_graph_node->output_pins[i_output][j].port = &pb_type->ports[i];
00247                                 pb_graph_node->output_pins[i_output][j].parent_node = pb_graph_node;
00248                                 pb_graph_node->output_pins[i_output][j].pin_count_in_cluster = pin_count_in_cluster;
00249                                 pb_graph_node->output_pins[i_output][j].type = PB_PIN_NORMAL;
00250                                 if(pb_graph_node->pb_type->blif_model != NULL) {
00251                                         if(strcmp(pb_graph_node->pb_type->blif_model, ".input") == 0) {
00252                                                 pb_graph_node->output_pins[i_output][j].type = PB_PIN_INPAD;
00253                                         } else if(pb_graph_node->num_clock_ports != 0) {
00254                                                 pb_graph_node->output_pins[i_output][j].type = PB_PIN_SEQUENTIAL;
00255                                         } else {
00256                                                 pb_graph_node->output_pins[i_output][j].type = PB_PIN_TERMINAL;
00257                                         }
00258                                 }
00259                                 pin_count_in_cluster++;                         
00260                         }
00261                         i_output++;
00262                 } else {
00263                         assert(pb_type->ports[i].is_clock && pb_type->ports[i].type == IN_PORT);
00264                         pb_graph_node->clock_pins[i_clockport] = my_calloc(pb_type->ports[i].num_pins, sizeof(t_pb_graph_pin));
00265                         pb_graph_node->num_clock_pins[i_clockport] = pb_type->ports[i].num_pins;
00266                         for(j = 0; j < pb_type->ports[i].num_pins; j++) {
00267                                 pb_graph_node->clock_pins[i_clockport][j].input_edges = NULL;
00268                                 pb_graph_node->clock_pins[i_clockport][j].num_input_edges = 0;
00269                                 pb_graph_node->clock_pins[i_clockport][j].output_edges = NULL;
00270                                 pb_graph_node->clock_pins[i_clockport][j].num_output_edges = 0;
00271                                 pb_graph_node->clock_pins[i_clockport][j].pin_number = j;
00272                                 pb_graph_node->clock_pins[i_clockport][j].port = &pb_type->ports[i];
00273                                 pb_graph_node->clock_pins[i_clockport][j].parent_node = pb_graph_node;
00274                                 pb_graph_node->clock_pins[i_clockport][j].pin_count_in_cluster = pin_count_in_cluster;
00275                                 pb_graph_node->clock_pins[i_clockport][j].type = PB_PIN_NORMAL;                 
00276                                 if(pb_graph_node->pb_type->blif_model != NULL) {
00277                                         pb_graph_node->clock_pins[i_clockport][j].type = PB_PIN_CLOCK;                  
00278                                 }
00279                                 pin_count_in_cluster++;
00280                         }
00281                         i_clockport++;
00282                 } 
00283         }
00284 
00285         /* Allocate and load child nodes for each mode and create interconnect in each mode */
00286         pb_graph_node->child_pb_graph_nodes = my_calloc(pb_type->num_modes, sizeof(t_pb_graph_node **));
00287         for(i = 0; i < pb_type->num_modes; i++) {
00288                 pb_graph_node->child_pb_graph_nodes[i] = my_calloc(pb_type->modes[i].num_pb_type_children, sizeof(t_pb_graph_node *));
00289                 for(j = 0; j < pb_type->modes[i].num_pb_type_children; j++) {
00290                         pb_graph_node->child_pb_graph_nodes[i][j] = my_calloc(pb_type->modes[i].pb_type_children[j].num_pb, sizeof(t_pb_graph_node));
00291                         for(k = 0; k < pb_type->modes[i].pb_type_children[j].num_pb; k++) {
00292                                 alloc_and_load_pb_graph(&pb_graph_node->child_pb_graph_nodes[i][j][k],
00293                                                                                 pb_graph_node,
00294                                                                                 &pb_type->modes[i].pb_type_children[j],
00295                                                                                 k);
00296                         }
00297                 }
00298         }
00299 
00300         for(i = 0; i < pb_type->num_modes; i++) {
00301                 /* Create interconnect for mode */
00302                 alloc_and_load_mode_interconnect(pb_graph_node, pb_graph_node->child_pb_graph_nodes[i], &pb_type->modes[i]);
00303         }
00304 }       
00305 
00306 
00307 static void free_pb_graph(INOUTP t_pb_graph_node *pb_graph_node) {
00308         int i, j, k;
00309         const t_pb_type *pb_type;
00310         struct s_linked_vptr *cur, *cur_num;
00311         t_pb_graph_edge *edges;
00312 
00313         pb_type = pb_graph_node->pb_type;
00314         
00315         /* Free ports for pb graph node */
00316         for(i = 0; i < pb_graph_node->num_input_ports; i++) {
00317                 for(j = 0; j < pb_graph_node->num_input_pins[i]; j++) {
00318                         if(pb_graph_node->input_pins[i][j].pin_timing)
00319                                 free(pb_graph_node->input_pins[i][j].pin_timing);
00320                         if(pb_graph_node->input_pins[i][j].pin_timing_del_max)
00321                                 free(pb_graph_node->input_pins[i][j].pin_timing_del_max);
00322                         if(pb_graph_node->input_pins[i][j].input_edges)
00323                                 free(pb_graph_node->input_pins[i][j].input_edges);
00324 
00325                         if(pb_graph_node->input_pins[i][j].output_edges)
00326                                 free(pb_graph_node->input_pins[i][j].output_edges);
00327                 }
00328                 free(pb_graph_node->input_pins[i]);             
00329         }
00330         for(i = 0; i < pb_graph_node->num_output_ports; i++) {
00331                 for(j = 0; j < pb_graph_node->num_output_pins[i]; j++) {
00332                         if(pb_graph_node->output_pins[i][j].pin_timing)
00333                                 free(pb_graph_node->output_pins[i][j].pin_timing);
00334                         if(pb_graph_node->output_pins[i][j].pin_timing_del_max)
00335                                 free(pb_graph_node->output_pins[i][j].pin_timing_del_max);
00336                         if(pb_graph_node->output_pins[i][j].input_edges)
00337                                 free(pb_graph_node->output_pins[i][j].input_edges);
00338                         if(pb_graph_node->output_pins[i][j].output_edges)
00339                                 free(pb_graph_node->output_pins[i][j].output_edges);
00340                 }
00341                 free(pb_graph_node->output_pins[i]);            
00342         }
00343         for(i = 0; i < pb_graph_node->num_clock_ports; i++) {
00344                 for(j = 0; j < pb_graph_node->num_clock_pins[i]; j++) {
00345                         if(pb_graph_node->clock_pins[i][j].pin_timing)
00346                                 free(pb_graph_node->clock_pins[i][j].pin_timing);
00347                         if(pb_graph_node->clock_pins[i][j].pin_timing_del_max)
00348                                 free(pb_graph_node->clock_pins[i][j].pin_timing_del_max);
00349                         if(pb_graph_node->clock_pins[i][j].input_edges)
00350                                 free(pb_graph_node->clock_pins[i][j].input_edges);
00351                         if(pb_graph_node->clock_pins[i][j].output_edges)
00352                                 free(pb_graph_node->clock_pins[i][j].output_edges);
00353                 }
00354                 free(pb_graph_node->clock_pins[i]);             
00355         }
00356         free(pb_graph_node->input_pins);
00357         free(pb_graph_node->output_pins);
00358         free(pb_graph_node->clock_pins);
00359 
00360         free(pb_graph_node->num_input_pins);
00361         free(pb_graph_node->num_output_pins);
00362         free(pb_graph_node->num_clock_pins);
00363         
00364         for(i = 0; i < pb_type->num_modes; i++) {
00365                 for(j = 0; j < pb_type->modes[i].num_pb_type_children; j++) {
00366                         for(k = 0; k < pb_type->modes[i].pb_type_children[j].num_pb; k++) {
00367                                 free_pb_graph(&pb_graph_node->child_pb_graph_nodes[i][j][k]);
00368                         }
00369                         free(pb_graph_node->child_pb_graph_nodes[i][j]);
00370                 }               
00371                 free(pb_graph_node->child_pb_graph_nodes[i]);
00372         }
00373         free(pb_graph_node->child_pb_graph_nodes);
00374 
00375         while(edges_head != NULL) {
00376                 cur = edges_head;
00377                 cur_num = num_edges_head;
00378                 edges = (t_pb_graph_edge*) cur->data_vptr;
00379                 for(i = 0; i < (long) cur_num->data_vptr; i++) {
00380                         free(edges[i].input_pins);
00381                         free(edges[i].output_pins);
00382                 }
00383                 edges_head = edges_head->next;
00384                 num_edges_head = num_edges_head->next;
00385                 free(edges);
00386                 free(cur_num);
00387                 free(cur);
00388         }
00389 }       
00390 
00391 /**
00392  * Generate interconnect associated with a mode of operation 
00393  * @param pb_graph_parent_node: parent node of pb in mode
00394  * @param pb_graph_children_nodes: [0..num_pb_type_in_mode-1][0..num_pb]
00395  * @param mode: mode of operation
00396  */
00397 static void alloc_and_load_mode_interconnect(INOUTP t_pb_graph_node *pb_graph_parent_node, 
00398                                                                                         INOUTP t_pb_graph_node **pb_graph_children_nodes,
00399                                                                                         INP const t_mode * mode) {
00400         int i, j;
00401         int *num_input_pb_graph_node_pins, *num_output_pb_graph_node_pins; /* number of pins in a set [0..num_sets-1] */
00402         int num_input_pb_graph_node_sets, num_output_pb_graph_node_sets;
00403         t_pb_graph_pin *** input_pb_graph_node_pins, ***output_pb_graph_node_pins;
00404         for(i = 0; i < mode->num_interconnect; i++) {
00405                 /* determine the interconnect input and output pins */
00406                 input_pb_graph_node_pins = alloc_and_load_port_pin_ptrs_from_string(pb_graph_parent_node, 
00407                                                                                                                    pb_graph_children_nodes,
00408                                                                                                                    mode->interconnect[i].input_string,
00409                                                                                                                    &num_input_pb_graph_node_pins,
00410                                                                                                                    &num_input_pb_graph_node_sets,
00411                                                                                                                    TRUE,
00412                                                                                                                    TRUE);
00413 
00414                 output_pb_graph_node_pins = alloc_and_load_port_pin_ptrs_from_string(pb_graph_parent_node, 
00415                                                                                                                    pb_graph_children_nodes,
00416                                                                                                                    mode->interconnect[i].output_string,
00417                                                                                                                    &num_output_pb_graph_node_pins,
00418                                                                                                                    &num_output_pb_graph_node_sets,
00419                                                                                                                    FALSE,
00420                                                                                                                    TRUE);
00421 
00422                 /* process the interconnect based on its type */
00423                 switch ( mode->interconnect[i].type ) {
00424 
00425                         case COMPLETE_INTERC: 
00426                                 alloc_and_load_complete_interc_edges(&mode->interconnect[i],
00427                                                                                                          input_pb_graph_node_pins,
00428                                                                                                          num_input_pb_graph_node_sets,
00429                                                                                                          num_input_pb_graph_node_pins,
00430                                                                                                          output_pb_graph_node_pins,
00431                                                                                                          num_output_pb_graph_node_sets,
00432                                                                                                          num_output_pb_graph_node_pins);
00433 
00434                         break;
00435 
00436                         case DIRECT_INTERC: 
00437                                 alloc_and_load_direct_interc_edges(&mode->interconnect[i],
00438                                                                                                         input_pb_graph_node_pins,
00439                                                                                                         num_input_pb_graph_node_sets,
00440                                                                                                         num_input_pb_graph_node_pins,
00441                                                                                                         output_pb_graph_node_pins,
00442                                                                                                         num_output_pb_graph_node_sets,
00443                                                                                                         num_output_pb_graph_node_pins);
00444                         break;
00445 
00446                         case MUX_INTERC:
00447                                 alloc_and_load_mux_interc_edges(&mode->interconnect[i],
00448                                                                                                 input_pb_graph_node_pins,
00449                                                                                                 num_input_pb_graph_node_sets,
00450                                                                                                 num_input_pb_graph_node_pins,
00451                                                                                                 output_pb_graph_node_pins,
00452                                                                                                 num_output_pb_graph_node_sets,
00453                                                                                                 num_output_pb_graph_node_pins);
00454 
00455                         break;
00456 
00457                         default : 
00458                                 printf(ERRTAG "Unknown interconnect %d for mode %s in pb_type %s\n", mode->interconnect[i].type,
00459                                         mode->name, pb_graph_parent_node->pb_type->name);
00460                                 printf("\tinput %s output %s\n", mode->interconnect[i].input_string, mode->interconnect[i].output_string);
00461                                 exit(1);
00462                 }
00463                 for(j = 0; j < num_input_pb_graph_node_sets; j++) {
00464                         free(input_pb_graph_node_pins[j]);
00465                 }
00466                 free(input_pb_graph_node_pins);
00467                 for(j = 0; j < num_output_pb_graph_node_sets; j++) {
00468                         free(output_pb_graph_node_pins[j]);
00469                 }
00470                 free(output_pb_graph_node_pins);
00471                 free(num_input_pb_graph_node_pins);
00472                 free(num_output_pb_graph_node_pins);
00473         }
00474 }
00475 
00476 /**
00477  * creates an array of pointers to the pb graph node pins in order from the port string
00478  * @returns t_pb_graph_pin ptr indexed by [0..num_sets_in_port - 1][0..num_ptrs - 1]
00479  */
00480 t_pb_graph_pin *** alloc_and_load_port_pin_ptrs_from_string(INP const t_pb_graph_node *pb_graph_parent_node, 
00481                                                                                                                                   INP t_pb_graph_node **pb_graph_children_nodes,
00482                                                                                                                                   INP const char * port_string,
00483                                                                                                                                   OUTP int ** num_ptrs,
00484                                                                                                                                   OUTP int * num_sets,
00485                                                                                                                                   INP boolean is_input_to_interc,
00486                                                                                                                                   INP boolean interconnect_error_check) {
00487         t_token * tokens;
00488         int num_tokens, curr_set;
00489         int i;
00490         boolean in_squig_bracket, success;
00491         
00492         t_pb_graph_pin ***pb_graph_pins;
00493 
00494         num_tokens = 0;
00495         tokens = GetTokensFromString(port_string, &num_tokens);
00496         *num_sets = 0;
00497         in_squig_bracket = FALSE;
00498         
00499         /* count the number of sets available */
00500         for(i = 0; i < num_tokens; i++) {
00501                 assert(tokens[i].type != TOKEN_NULL);
00502                 if(tokens[i].type == TOKEN_OPEN_SQUIG_BRACKET) {
00503                         if(in_squig_bracket) {
00504                                 printf(ERRTAG "{ inside { in port %s\n", port_string);
00505                                 exit(1);
00506                         }
00507                         in_squig_bracket = TRUE;
00508                 } else if(tokens[i].type == TOKEN_CLOSE_SQUIG_BRACKET) {
00509                         if(!in_squig_bracket) {
00510                                 (*num_sets)++;
00511                                 printf(ERRTAG "No matching '{' for '}' in port %s\n", port_string);
00512                                 exit(1);
00513                         }
00514                         in_squig_bracket = FALSE;
00515                 } else if(tokens[i].type == TOKEN_DOT) {
00516                         if(!in_squig_bracket) {
00517                                 (*num_sets)++;
00518                         }               
00519                 }
00520         }
00521 
00522         if(in_squig_bracket) {
00523                 (*num_sets)++;
00524                 printf(ERRTAG "No matching '{' for '}' in port %s\n", port_string);
00525                 exit(1);
00526         }
00527 
00528         pb_graph_pins = my_calloc(*num_sets, sizeof(t_pb_graph_pin**));
00529         *num_ptrs = my_calloc(*num_sets, sizeof(int));
00530 
00531 
00532         curr_set = 0;
00533         for(i = 0; i < num_tokens; i++) {
00534                 assert(tokens[i].type != TOKEN_NULL);
00535                 if(tokens[i].type == TOKEN_OPEN_SQUIG_BRACKET) {
00536                         if(in_squig_bracket) {
00537                                 printf(ERRTAG "{ inside { in port %s\n", port_string);
00538                                 exit(1);
00539                         }
00540                         in_squig_bracket = TRUE;
00541                 } else if(tokens[i].type == TOKEN_CLOSE_SQUIG_BRACKET) {
00542                         if((*num_ptrs)[curr_set] == 0) {
00543                                 printf(ERRTAG "No data contained in {} in port %s\n", port_string);
00544                                 exit(1);
00545                         }
00546                         if(!in_squig_bracket) {
00547                                 curr_set++;
00548                                 printf(ERRTAG "No matching '{' for '}' in port %s\n", port_string);
00549                                 exit(1);
00550                         }
00551                         in_squig_bracket = FALSE;
00552                 } else if(tokens[i].type == TOKEN_STRING) {
00553 
00554                         success = realloc_and_load_pb_graph_pin_ptrs_at_var(pb_graph_parent_node,
00555                                                                                                                 pb_graph_children_nodes,
00556                                                                                                                 interconnect_error_check,
00557                                                                                                                 is_input_to_interc,
00558                                                                                                                 tokens,
00559                                                                                                                 &i,
00560                                                                                                                 &((*num_ptrs)[curr_set]),
00561                                                                                                                 &pb_graph_pins[curr_set]);
00562 
00563                         if(!success) {
00564                                 printf(ERRTAG "syntax error processing port string %s\n", port_string);
00565                                 exit(1);
00566                         }
00567 
00568                         if(!in_squig_bracket) {
00569                                 curr_set++;
00570                         }               
00571                 }
00572         }
00573         assert(curr_set == *num_sets);
00574         freeTokens(tokens, num_tokens);
00575         return pb_graph_pins;
00576 }
00577 
00578 /**
00579  * Creates edges to connect all input pins to output pins 
00580  */
00581 static void alloc_and_load_complete_interc_edges(INP t_interconnect *interconnect,
00582                                                                                                  INOUTP t_pb_graph_pin *** input_pb_graph_node_pin_ptrs, 
00583                                                                                                  INP int num_input_sets,
00584                                                                                                  INP int *num_input_ptrs,
00585                                                                                                  INOUTP t_pb_graph_pin *** output_pb_graph_node_pin_ptrs,
00586                                                                                                  INP int num_output_sets,
00587                                                                                                  INP int *num_output_ptrs) {
00588         int i_inset, i_outset, i_inpin, i_outpin;
00589         int in_count, out_count;
00590         t_pb_graph_edge *edges;
00591         int i_edge;
00592         struct s_linked_vptr *cur;
00593 
00594 
00595         /* Allocate memory for edges, and reallocate more memory for pins connecting to those edges */
00596         in_count = out_count = 0;
00597         
00598         for(i_inset = 0; i_inset < num_input_sets; i_inset++) {
00599                 in_count += num_input_ptrs[i_inset];
00600         }
00601         for(i_outset = 0; i_outset < num_output_sets; i_outset++) {
00602                 out_count += num_output_ptrs[i_outset];
00603         }
00604 
00605         edges = my_calloc(in_count * out_count, sizeof(t_pb_graph_edge));
00606         cur = my_malloc(sizeof(struct s_linked_vptr));
00607         cur->next = edges_head;
00608         edges_head = cur;
00609         cur->data_vptr = (void *)edges;
00610         cur = my_malloc(sizeof(struct s_linked_vptr));
00611         cur->next = num_edges_head;
00612         num_edges_head = cur;
00613         cur->data_vptr = (void *)((long)in_count * out_count);
00614         
00615 
00616         for(i_inset = 0; i_inset < num_input_sets; i_inset++) {
00617                 for(i_inpin = 0; i_inpin < num_input_ptrs[i_inset]; i_inpin++) {
00618                         input_pb_graph_node_pin_ptrs[i_inset][i_inpin]->output_edges = my_realloc(input_pb_graph_node_pin_ptrs[i_inset][i_inpin]->output_edges, 
00619                                 (input_pb_graph_node_pin_ptrs[i_inset][i_inpin]->num_output_edges + out_count) * sizeof(t_pb_graph_edge *));
00620                 }
00621         }
00622 
00623         for(i_outset = 0; i_outset < num_output_sets; i_outset++) {
00624                 for(i_outpin = 0; i_outpin < num_output_ptrs[i_outset]; i_outpin++) {
00625                         output_pb_graph_node_pin_ptrs[i_outset][i_outpin]->input_edges = my_realloc(output_pb_graph_node_pin_ptrs[i_outset][i_outpin]->input_edges, 
00626                                 (output_pb_graph_node_pin_ptrs[i_outset][i_outpin]->num_input_edges + in_count) * sizeof(t_pb_graph_edge *));
00627                 }
00628         }
00629 
00630         i_edge = 0;
00631 
00632         /* Load connections between pins and record these updates in the edges */
00633         for(i_inset = 0; i_inset < num_input_sets; i_inset++) {
00634                 for(i_inpin = 0; i_inpin < num_input_ptrs[i_inset]; i_inpin++) {
00635                         for(i_outset = 0; i_outset < num_output_sets; i_outset++) {
00636                                 for(i_outpin = 0; i_outpin < num_output_ptrs[i_outset]; i_outpin++) {
00637 
00638                                         input_pb_graph_node_pin_ptrs[i_inset][i_inpin]->output_edges[input_pb_graph_node_pin_ptrs[i_inset][i_inpin]->num_output_edges] = &edges[i_edge];
00639                                         input_pb_graph_node_pin_ptrs[i_inset][i_inpin]->num_output_edges++;
00640                                         output_pb_graph_node_pin_ptrs[i_outset][i_outpin]->input_edges[output_pb_graph_node_pin_ptrs[i_outset][i_outpin]->num_input_edges] = &edges[i_edge];
00641                                         output_pb_graph_node_pin_ptrs[i_outset][i_outpin]->num_input_edges++;
00642 
00643                                         edges[i_edge].num_input_pins = 1;
00644                                         edges[i_edge].input_pins = my_malloc(sizeof(t_pb_graph_pin *));
00645                                         edges[i_edge].input_pins[0] = input_pb_graph_node_pin_ptrs[i_inset][i_inpin];
00646                                         edges[i_edge].num_output_pins = 1;
00647                                         edges[i_edge].output_pins = my_malloc(sizeof(t_pb_graph_pin *));
00648                                         edges[i_edge].output_pins[0] = output_pb_graph_node_pin_ptrs[i_outset][i_outpin];                                       
00649 
00650                                         edges[i_edge].interconnect = interconnect;
00651                                         edges[i_edge].driver_set = i_inset;
00652                                         edges[i_edge].driver_pin = i_inpin;
00653                                         
00654                                         i_edge++;
00655                                 }
00656                         }
00657                 }
00658         }
00659         assert(i_edge == in_count * out_count);
00660 }
00661 
00662 static void alloc_and_load_direct_interc_edges(  INP t_interconnect *interconnect,
00663                                                                                                  INOUTP t_pb_graph_pin *** input_pb_graph_node_pin_ptrs, 
00664                                                                                                  INP int num_input_sets,
00665                                                                                                  INP int *num_input_ptrs,
00666                                                                                                  INOUTP t_pb_graph_pin *** output_pb_graph_node_pin_ptrs,
00667                                                                                                  INP int num_output_sets,
00668                                                                                                  INP int *num_output_ptrs) {
00669 
00670         int i;
00671         t_pb_graph_edge *edges;
00672         struct s_linked_vptr *cur;
00673 
00674         /* Allocate memory for edges */
00675         assert(num_input_sets == 1 && num_output_sets == 1);
00676         if(num_input_ptrs[0] != num_output_ptrs[0]) {
00677                 printf("input ptrs %d output ptrs %d input pin %s output pin %s input_pb_type %s output_pb_type %s\n",
00678                         num_input_ptrs[0], num_output_ptrs[0], input_pb_graph_node_pin_ptrs[0][0]->port->name, output_pb_graph_node_pin_ptrs[0][0]->port->name,
00679                         input_pb_graph_node_pin_ptrs[0][0]->parent_node->pb_type->name, output_pb_graph_node_pin_ptrs[0][0]->parent_node->pb_type->name);
00680         }
00681         assert(num_input_ptrs[0] == num_output_ptrs[0]);
00682         
00683         edges = my_calloc(num_input_ptrs[0], sizeof(t_pb_graph_edge));
00684         cur = my_malloc(sizeof(struct s_linked_vptr));
00685         cur->next = edges_head;
00686         edges_head = cur;
00687         cur->data_vptr = (void *)edges;
00688         cur = my_malloc(sizeof(struct s_linked_vptr));
00689         cur->next = num_edges_head;
00690         num_edges_head = cur;
00691         cur->data_vptr = (void *)((long)num_input_ptrs[0]);
00692         
00693         
00694         /* Reallocate memory for pins and load connections between pins and record these updates in the edges */
00695         for(i = 0; i < num_input_ptrs[0]; i++) {                
00696                 input_pb_graph_node_pin_ptrs[0][i]->output_edges = my_realloc(
00697                         input_pb_graph_node_pin_ptrs[0][i]->output_edges, (input_pb_graph_node_pin_ptrs[0][i]->num_output_edges + 1) * sizeof(t_pb_graph_edge *));
00698                 input_pb_graph_node_pin_ptrs[0][i]->output_edges[input_pb_graph_node_pin_ptrs[0][i]->num_output_edges] = &edges[i];
00699                 input_pb_graph_node_pin_ptrs[0][i]->num_output_edges++;
00700                 
00701                 output_pb_graph_node_pin_ptrs[0][i]->input_edges = my_realloc(
00702                         output_pb_graph_node_pin_ptrs[0][i]->input_edges, (output_pb_graph_node_pin_ptrs[0][i]->num_input_edges + 1) * sizeof(t_pb_graph_edge *));
00703                 output_pb_graph_node_pin_ptrs[0][i]->input_edges[output_pb_graph_node_pin_ptrs[0][i]->num_input_edges] = &edges[i];
00704                 output_pb_graph_node_pin_ptrs[0][i]->num_input_edges++;
00705 
00706                 edges[i].num_input_pins = 1;
00707                 edges[i].input_pins = my_malloc(sizeof(t_pb_graph_pin *));
00708                 edges[i].input_pins[0] = input_pb_graph_node_pin_ptrs[0][i];
00709                 edges[i].num_output_pins = 1;
00710                 edges[i].output_pins = my_malloc(sizeof(t_pb_graph_pin *));
00711                 edges[i].output_pins[0] = output_pb_graph_node_pin_ptrs[0][i];
00712 
00713                 edges[i].interconnect = interconnect;
00714                 edges[i].driver_set = 0;
00715                 edges[i].driver_pin = i;
00716         }
00717 }
00718 
00719 static void alloc_and_load_mux_interc_edges(    INP t_interconnect * interconnect,
00720                                                                                                 INOUTP t_pb_graph_pin *** input_pb_graph_node_pin_ptrs, 
00721                                                                                                  INP int num_input_sets,
00722                                                                                                  INP int *num_input_ptrs,
00723                                                                                                  INOUTP t_pb_graph_pin *** output_pb_graph_node_pin_ptrs,
00724                                                                                                  INP int num_output_sets,
00725                                                                                                  INP int *num_output_ptrs) {
00726         int i_inset, i_inpin, i_outpin;
00727         t_pb_graph_edge *edges;
00728         struct s_linked_vptr *cur;
00729 
00730         /* Allocate memory for edges, and reallocate more memory for pins connecting to those edges */
00731         assert(num_output_sets == 1);
00732 
00733         edges = my_calloc(num_input_sets, sizeof(t_pb_graph_edge));
00734         cur = my_malloc(sizeof(struct s_linked_vptr));
00735         cur->next = edges_head;
00736         edges_head = cur;
00737         cur->data_vptr = (void *)edges;
00738         cur = my_malloc(sizeof(struct s_linked_vptr));
00739         cur->next = num_edges_head;
00740         num_edges_head = cur;
00741         cur->data_vptr = (void *)((long)num_input_sets);
00742         
00743 
00744         for(i_inset = 0; i_inset < num_input_sets; i_inset++) {
00745                 for(i_inpin = 0; i_inpin < num_input_ptrs[i_inset]; i_inpin++) {
00746                         input_pb_graph_node_pin_ptrs[i_inset][i_inpin]->output_edges = my_realloc(input_pb_graph_node_pin_ptrs[i_inset][i_inpin]->output_edges, 
00747                                 (input_pb_graph_node_pin_ptrs[i_inset][i_inpin]->num_output_edges + 1) * sizeof(t_pb_graph_edge *));
00748                 }
00749         }
00750 
00751         for(i_outpin = 0; i_outpin < num_output_ptrs[0]; i_outpin++) {
00752                 output_pb_graph_node_pin_ptrs[0][i_outpin]->input_edges = my_realloc(output_pb_graph_node_pin_ptrs[0][i_outpin]->input_edges, 
00753                         (output_pb_graph_node_pin_ptrs[0][i_outpin]->num_input_edges + num_input_sets) * sizeof(t_pb_graph_edge *));
00754         }
00755 
00756         /* Load connections between pins and record these updates in the edges */
00757         for(i_inset = 0; i_inset < num_input_sets; i_inset++) {
00758                 assert(num_output_ptrs[0] == num_input_ptrs[i_inset]);
00759                 edges[i_inset].input_pins = my_calloc(num_output_ptrs[0], sizeof(t_pb_graph_pin *));
00760                 edges[i_inset].output_pins = my_calloc(num_output_ptrs[0], sizeof(t_pb_graph_pin *));
00761                 edges[i_inset].num_input_pins = num_output_ptrs[0];
00762                 edges[i_inset].num_output_pins = num_output_ptrs[0];
00763                 for(i_inpin = 0; i_inpin < num_input_ptrs[i_inset]; i_inpin++) {
00764                         input_pb_graph_node_pin_ptrs[i_inset][i_inpin]->output_edges[input_pb_graph_node_pin_ptrs[i_inset][i_inpin]->num_output_edges] = &edges[i_inset];
00765                         input_pb_graph_node_pin_ptrs[i_inset][i_inpin]->num_output_edges++;
00766                         output_pb_graph_node_pin_ptrs[0][i_inpin]->input_edges[output_pb_graph_node_pin_ptrs[0][i_inpin]->num_input_edges] = &edges[i_inset];
00767                         output_pb_graph_node_pin_ptrs[0][i_inpin]->num_input_edges++;
00768 
00769                         edges[i_inset].input_pins[i_inpin] = input_pb_graph_node_pin_ptrs[i_inset][i_inpin];
00770                         edges[i_inset].output_pins[i_inpin] = output_pb_graph_node_pin_ptrs[0][i_inpin];
00771                         
00772                         assert(i_inpin == 0); /* current does not support bus-based routing, TODO: Support bus based routing */
00773                         edges[i_inset].interconnect = interconnect;
00774                         edges[i_inset].driver_set = i_inset;
00775                         edges[i_inset].driver_pin = i_inpin;
00776                 }
00777         }
00778 }
00779 
00780 
00781 /**
00782  * populate array of pb graph pins for a single variable of type pb_type[int:int].port[int:int]
00783  * @param pb_graph_pins: pointer to array from [0..num_port_pins] of pb_graph_pin pointers
00784  * @param tokens: array of tokens to scan
00785  * @param num_pins: current number of pins in pb_graph_pin array 
00786  */
00787 static boolean realloc_and_load_pb_graph_pin_ptrs_at_var(INP const t_pb_graph_node *pb_graph_parent_node, 
00788                                                                                                         INP t_pb_graph_node **pb_graph_children_nodes,
00789                                                                                                         INP boolean interconnect_error_check,
00790                                                                                                         INP boolean is_input_to_interc,
00791                                                                                                         INP const t_token *tokens,
00792                                                                                                         INOUTP int *token_index, 
00793                                                                                                         INOUTP int *num_pins,
00794                                                                                                         OUTP t_pb_graph_pin ***pb_graph_pins) {
00795 
00796         int i, j, ipin, ipb;
00797         int pb_msb, pb_lsb;
00798         int pin_msb, pin_lsb;
00799         const t_pb_graph_node *pb_node_array;
00800         char *port_name;
00801         t_port *iport;
00802         int add_or_subtract_pb, add_or_subtract_pin;
00803         boolean found;
00804         t_mode *mode = NULL;
00805 
00806         assert(tokens[*token_index].type == TOKEN_STRING);
00807         pb_node_array = NULL;
00808 
00809 
00810         if(pb_graph_children_nodes) 
00811                 mode = pb_graph_children_nodes[0][0].pb_type->parent_mode;
00812 
00813         pb_msb = pb_lsb = OPEN;
00814         pin_msb = pin_lsb = OPEN;
00815 
00816         /* parse pb */
00817         found = FALSE;
00818         if(0 == strcmp(pb_graph_parent_node->pb_type->name, tokens[*token_index].data)) {
00819                 pb_node_array = pb_graph_parent_node;
00820                 pb_msb = pb_lsb = 0;
00821                 found = TRUE;
00822                 (*token_index)++;
00823                 if(tokens[*token_index].type == TOKEN_OPEN_SQUARE_BRACKET) {
00824                         (*token_index)++;
00825                         if(!checkTokenType(tokens[*token_index], TOKEN_INT)) { return FALSE; }
00826                         pb_msb = my_atoi(tokens[*token_index].data);
00827                         (*token_index)++;
00828                         if(!checkTokenType(tokens[*token_index], TOKEN_COLON)) { 
00829                                 if(!checkTokenType(tokens[*token_index], TOKEN_CLOSE_SQUARE_BRACKET)) {
00830                                         return FALSE; 
00831                                 }
00832                                 pb_lsb = pb_msb;
00833                                 (*token_index)++;
00834                         } else {
00835                                 (*token_index)++;
00836                                 if(!checkTokenType(tokens[*token_index], TOKEN_INT)) { return FALSE; }
00837                                 pb_lsb= my_atoi(tokens[*token_index].data);
00838                                 (*token_index)++;
00839                                 if(!checkTokenType(tokens[*token_index], TOKEN_CLOSE_SQUARE_BRACKET)) { return FALSE; }                                 
00840                                 (*token_index)++;
00841                         }
00842                         /* Check to make sure indices from user match internal data structures for the indices of the parent */
00843                         if((pb_lsb != pb_msb) &&  (pb_lsb != pb_graph_parent_node->placement_index)) {
00844                                 printf(ERRTAG "Incorrect placement index for %s, expected index %d\n", 
00845                                         tokens[0].data, pb_graph_parent_node->placement_index);
00846                                 return FALSE;
00847                         }
00848                         pb_lsb = pb_msb = 0; /* Internal representation of parent is always 0 */
00849                 }
00850         } else {
00851                 if(mode == NULL) {
00852                         printf(ERRTAG "pb_graph_parent_node %s failed\n", pb_graph_parent_node->pb_type->name);
00853                 }
00854                 assert(mode);
00855                 for(i = 0; i < mode->num_pb_type_children; i++) {
00856                         assert(&mode->pb_type_children[i] == pb_graph_children_nodes[i][0].pb_type);
00857                         if(0 == strcmp(mode->pb_type_children[i].name, tokens[*token_index].data)) {
00858                                 pb_node_array = pb_graph_children_nodes[i];
00859                                 found = TRUE;
00860                                 (*token_index)++;
00861 
00862                                 if(tokens[*token_index].type == TOKEN_OPEN_SQUARE_BRACKET) {
00863                                         (*token_index)++;
00864                                         if(!checkTokenType(tokens[*token_index], TOKEN_INT)) { return FALSE; }
00865                                         pb_msb = my_atoi(tokens[*token_index].data);
00866                                         (*token_index)++;
00867                                         if(!checkTokenType(tokens[*token_index], TOKEN_COLON)) { 
00868                                                 if(!checkTokenType(tokens[*token_index], TOKEN_CLOSE_SQUARE_BRACKET)) {
00869                                                         return FALSE; 
00870                                                 }
00871                                                 pb_lsb = pb_msb;
00872                                                 (*token_index)++;
00873                                         } else {
00874                                                 (*token_index)++;
00875                                                 if(!checkTokenType(tokens[*token_index], TOKEN_INT)) { return FALSE; }
00876                                                 pb_lsb= my_atoi(tokens[*token_index].data);
00877                                                 (*token_index)++;
00878                                                 if(!checkTokenType(tokens[*token_index], TOKEN_CLOSE_SQUARE_BRACKET)) { return FALSE; }                                 
00879                                                 (*token_index)++;
00880                                         }
00881                                 } else {
00882                                         pb_msb = pb_node_array[0].pb_type->num_pb - 1;
00883                                         pb_lsb = 0;
00884                                 }
00885                                 break;
00886                         }
00887                 }
00888         }
00889 
00890         if(!found) {
00891                 printf(ERRTAG "Unknown pb_type name %s, not defined in namespace of mode %s\n", tokens[*token_index].data, mode->name);
00892                 return FALSE;
00893         }
00894 
00895         found = FALSE;
00896 
00897         if(!checkTokenType(tokens[*token_index], TOKEN_DOT)) { return FALSE; }
00898         (*token_index)++;
00899         if(!checkTokenType(tokens[*token_index], TOKEN_STRING)) { return FALSE; }
00900         
00901         /* parse ports and port pins of pb */
00902         port_name = tokens[*token_index].data;
00903 
00904         (*token_index)++;
00905         if(tokens[*token_index].type == TOKEN_OPEN_SQUARE_BRACKET) {
00906                 (*token_index)++;
00907                 if(!checkTokenType(tokens[*token_index], TOKEN_INT)) { return FALSE; }
00908                 pin_msb = my_atoi(tokens[*token_index].data);
00909                 (*token_index)++;
00910                 if(!checkTokenType(tokens[*token_index], TOKEN_COLON)) { 
00911                         if(!checkTokenType(tokens[*token_index], TOKEN_CLOSE_SQUARE_BRACKET)) {
00912                                 return FALSE; 
00913                         }
00914                         pin_lsb = pin_msb;
00915                         (*token_index)++;
00916                 } else {
00917                         (*token_index)++;
00918                         if(!checkTokenType(tokens[*token_index], TOKEN_INT)) { return FALSE; }
00919                         pin_lsb= my_atoi(tokens[*token_index].data);
00920                         (*token_index)++;
00921                         if(!checkTokenType(tokens[*token_index], TOKEN_CLOSE_SQUARE_BRACKET)) { return FALSE; }                                 
00922                         (*token_index)++;
00923                 }
00924         } else {
00925                 if(get_pb_graph_pin_from_name(port_name, &pb_node_array[pb_lsb], 0) == NULL) {
00926                         printf("failed to find port name %s\n", port_name);
00927                         exit(1);
00928                 }
00929                 iport = get_pb_graph_pin_from_name(port_name, &pb_node_array[pb_lsb], 0)->port;
00930                 pin_msb = iport->num_pins - 1;
00931                 pin_lsb = 0;
00932         }
00933         (*token_index)--;
00934 
00935         if(pb_msb < pb_lsb) {
00936                 add_or_subtract_pb = -1;
00937         } else {
00938                 add_or_subtract_pb = 1;
00939         }
00940 
00941         if(pin_msb < pin_lsb) {
00942                 add_or_subtract_pin = -1;
00943         } else {
00944                 add_or_subtract_pin = 1;
00945         }
00946         *num_pins += (abs(pb_msb - pb_lsb) + 1) * (abs(pin_msb - pin_lsb) + 1);
00947         *pb_graph_pins = my_calloc(*num_pins, sizeof(t_pb_graph_pin *));
00948         i = j = 0;
00949 
00950         ipb = pb_lsb;
00951         
00952         while(ipb != pb_msb + add_or_subtract_pin) {
00953                 ipin = pin_lsb;
00954                 j = 0;
00955                 while(ipin != pin_msb + add_or_subtract_pin) {
00956                         (*pb_graph_pins)[i*(abs(pin_msb - pin_lsb) + 1) + j] = get_pb_graph_pin_from_name(port_name, &pb_node_array[ipb], ipin);
00957                         iport = (*pb_graph_pins)[i*(abs(pin_msb - pin_lsb) + 1) + j]->port;
00958                         if(!iport) { return FALSE; }    
00959 
00960                         /* Error checking before assignment */
00961                         if(interconnect_error_check) {
00962                                 if(pb_node_array == pb_graph_parent_node) {
00963                                         if(is_input_to_interc) {
00964                                                 if(iport->type != IN_PORT) {
00965                                                         printf(ERRTAG "input to interconnect from parent is not an input or clock pin\n");
00966                                                         return FALSE;
00967                                                 }
00968                                         } else {
00969                                                 if(iport->type != OUT_PORT) {
00970                                                         printf(ERRTAG "output from interconnect from parent is not an input or clock pin\n");
00971                                                         return FALSE;
00972                                                 }
00973                                         }
00974                                 } else {
00975                                         if(is_input_to_interc) {
00976                                                 if(iport->type != OUT_PORT) {
00977                                                         printf(ERRTAG "output from interconnect from parent is not an input or clock pin\n");
00978                                                         return FALSE;
00979                                                 }
00980                                         } else {
00981                                                 if(iport->type != IN_PORT) {
00982                                                         printf(ERRTAG "input to interconnect from parent is not an input or clock pin\n");
00983                                                         return FALSE;
00984                                                 }
00985                                         }
00986                                 }
00987                         }       
00988 
00989 
00990                         /* load pb_graph_pin for pin */
00991 
00992                         ipin += add_or_subtract_pin;
00993                         j++;
00994                 }
00995                 i++;
00996                 ipb += add_or_subtract_pb;
00997         }
00998 
00999         assert((abs(pb_msb - pb_lsb) + 1) * (abs(pin_msb - pin_lsb) + 1) == i * j);
01000 
01001         return TRUE;
01002 }
01003 
01004 static t_pb_graph_pin * get_pb_graph_pin_from_name(INP const char * port_name, INP const t_pb_graph_node * pb, INP int pin) {
01005         int i;
01006         
01007         for(i = 0; i < pb->num_input_ports; i++) {
01008                 if(0 == strcmp(port_name, pb->input_pins[i][0].port->name)) {
01009                         if(pin < pb->input_pins[i][0].port->num_pins) {
01010                                 return &pb->input_pins[i][pin];
01011                         } else {
01012                                 return NULL;
01013                         }
01014                 }
01015         }
01016         for(i = 0; i < pb->num_output_ports; i++) {
01017                 if(0 == strcmp(port_name, pb->output_pins[i][0].port->name)) {
01018                         if(pin < pb->output_pins[i][0].port->num_pins) {
01019                                 return &pb->output_pins[i][pin];
01020                         } else {
01021                                 return NULL;
01022                         }
01023                 }
01024         }
01025         for(i = 0; i < pb->num_clock_ports; i++) {
01026                 if(0 == strcmp(port_name, pb->clock_pins[i][0].port->name)) {
01027                         if(pin < pb->clock_pins[i][0].port->num_pins) {
01028                                 return &pb->clock_pins[i][pin];
01029                         } else {
01030                                 return NULL;
01031                         }
01032                 }
01033         }
01034         return NULL;
01035 }
01036 
01037 static void alloc_and_load_pin_locations_from_pb_graph(t_type_descriptor *type) {
01038         int i, j, k, m, icapacity;
01039         int num_sides;
01040         int side_index;
01041         int pin_num;
01042         int count;
01043 
01044         int *num_pb_graph_node_pins; /* number of pins in a set [0..num_sets-1] */
01045         int num_pb_graph_node_sets;
01046         t_pb_graph_pin*** pb_graph_node_pins;
01047 
01048         num_sides = 2 * (type->height + 1);
01049         side_index = 0;
01050         count = 0;
01051         
01052         if(type->pin_location_distribution == E_SPREAD_PIN_DISTR) {
01053                 pin_num = 0;
01054                 /* evenly distribute pins starting at bottom left corner */
01055                 for(j = 0; j < 4; j++) {
01056                         for(i = 0; i < type->height; i++) {
01057                                 if(j == TOP && i != type->height - 1) {
01058                                         continue;
01059                                 }
01060                                 if(j == BOTTOM && i != 0) {
01061                                         continue;
01062                                 }
01063                                 for(k = 0; k < (type->num_pins / num_sides) + 1; k++) {
01064                                         pin_num = side_index + k * num_sides;
01065                                         if(pin_num < type->num_pins) {
01066                                                 type->pinloc[i][j][pin_num] = 1;
01067                                                 type->pin_height[pin_num] = i;
01068                                                 count++;
01069                                         }
01070                                 }
01071                                 side_index++;
01072                         }
01073                 }
01074                 assert(side_index == num_sides);
01075                 assert(count == type->num_pins);
01076         } else {
01077                 assert(type->pin_location_distribution == E_CUSTOM_PIN_DISTR);
01078                 for(i = 0; i < type->height; i++) {
01079                         for(j = 0; j < 4; j++) {                        
01080                                 if(j == TOP && i != type->height - 1) {
01081                                         continue;
01082                                 }
01083                                 if(j == BOTTOM && i != 0) {
01084                                         continue;
01085                                 }
01086                                 for(k = 0; k < type->num_pin_loc_assignments[i][j]; k++) {
01087                                         pb_graph_node_pins = alloc_and_load_port_pin_ptrs_from_string(type->pb_graph_head, 
01088                                                                                                    type->pb_graph_head->child_pb_graph_nodes[0],
01089                                                                                                    type->pin_loc_assignments[i][j][k],
01090                                                                                                    &num_pb_graph_node_pins,
01091                                                                                                    &num_pb_graph_node_sets,
01092                                                                                                    FALSE,
01093                                                                                                    FALSE);
01094                                         assert(num_pb_graph_node_sets == 1);                                    
01095 
01096 
01097                                         for(m = 0; m < num_pb_graph_node_pins[0]; m++) {
01098                                                 pin_num = pb_graph_node_pins[0][m]->pin_count_in_cluster;
01099                                                 assert(pin_num < type->num_pins / type->capacity);
01100                                                 for(icapacity = 0; icapacity < type->capacity; icapacity++) {
01101                                                         type->pinloc[i][j][pin_num + icapacity * type->num_pins / type->capacity] = 1;
01102                                                         type->pin_height[pin_num] = i;
01103                                                         assert(count < type->num_pins);
01104                                                 }                                               
01105                                         }
01106                                         free(pb_graph_node_pins[0]);
01107                                         free(pb_graph_node_pins);
01108                                         free(num_pb_graph_node_pins);
01109                                 }
01110                         }
01111                 }       
01112         }
01113 }
01114 
01115 static void echo_pb_rec(const INP t_pb_graph_node *pb_graph_node, INP int level, INP FILE *fp) {
01116         int i, j, k;
01117 
01118         print_tabs(fp, level);
01119         fprintf(fp, "Physical Block: type \"%s\"  index %d  num_children %d\n", 
01120                 pb_graph_node->pb_type->name, pb_graph_node->placement_index, pb_graph_node->pb_type->num_pb);
01121 
01122         if(pb_graph_node->parent_pb_graph_node) {
01123                 print_tabs(fp, level + 1);
01124                 fprintf(fp, "Parent Block: type \"%s\" index %d \n", pb_graph_node->parent_pb_graph_node->pb_type->name,
01125                         pb_graph_node->parent_pb_graph_node->placement_index);
01126         }
01127         
01128         print_tabs(fp, level);
01129         fprintf(fp, "Input Ports: total ports %d\n", pb_graph_node->num_input_ports);
01130         echo_pb_pins(pb_graph_node->input_pins, pb_graph_node->num_input_ports, level, fp);
01131         print_tabs(fp, level);
01132         fprintf(fp, "Output Ports: total ports %d\n", pb_graph_node->num_output_ports);
01133         echo_pb_pins(pb_graph_node->output_pins, pb_graph_node->num_output_ports, level, fp);
01134         print_tabs(fp, level);
01135         fprintf(fp, "Clock Ports: total ports %d\n", pb_graph_node->num_clock_ports);
01136         echo_pb_pins(pb_graph_node->clock_pins, pb_graph_node->num_clock_ports, level, fp);
01137         if(pb_graph_node->pb_type->num_modes > 0) {
01138                 print_tabs(fp, level);
01139                 fprintf(fp, "Children:\n");
01140         }
01141         for(i = 0; i < pb_graph_node->pb_type->num_modes; i++) {
01142                 for(j = 0; j < pb_graph_node->pb_type->modes[i].num_pb_type_children; j++) {
01143                         for(k = 0; k < pb_graph_node->pb_type->modes[i].pb_type_children[j].num_pb; k++) {
01144                                 echo_pb_rec(&pb_graph_node->child_pb_graph_nodes[i][j][k], level + 1, fp);
01145                         }
01146                 }
01147         }
01148 }
01149 
01150 static void echo_pb_pins(INP t_pb_graph_pin **pb_graph_pins, INP int num_ports, INP int level, INP FILE * fp) {
01151         int i, j, k, m;
01152         t_port *port;
01153 
01154         print_tabs(fp, level);
01155         
01156         for(i = 0; i < num_ports; i++) {
01157                 port = pb_graph_pins[i][0].port;
01158                 print_tabs(fp, level);
01159                 fprintf(fp, "Port \"%s\": num_pins %d type %d parent name \"%s\"\n", 
01160                         port->name, port->num_pins, port->type, port->parent_pb_type->name);    
01161 
01162                 for(j = 0; j < port->num_pins; j++) {
01163                         print_tabs(fp, level + 1);
01164                         assert(j == pb_graph_pins[i][j].pin_number);
01165                         assert(pb_graph_pins[i][j].port == port);
01166                         fprintf(fp, "Pin %d port name \"%s\" num input edges %d num output edges %d parent type \"%s\" parent index %d\n", 
01167                                 pb_graph_pins[i][j].pin_number, pb_graph_pins[i][j].port->name, pb_graph_pins[i][j].num_input_edges, pb_graph_pins[i][j].num_output_edges,
01168                                 pb_graph_pins[i][j].parent_node->pb_type->name, pb_graph_pins[i][j].parent_node->placement_index);      
01169                         for(k = 0; k < pb_graph_pins[i][j].num_input_edges; k++) {
01170                                 print_tabs(fp, level + 2);
01171                                 fprintf(fp, "Input edge %d num inputs %d num outputs %d\n", 
01172                                         k, pb_graph_pins[i][j].input_edges[k]->num_input_pins, pb_graph_pins[i][j].input_edges[k]->num_output_pins);    
01173                                 print_tabs(fp, level + 3);
01174                                 fprintf(fp, "Input edge inputs\n");
01175                                 for(m = 0; m < pb_graph_pins[i][j].input_edges[k]->num_input_pins; m++) {
01176                                         print_tabs(fp, level + 3);
01177                                         fprintf(fp, "pin number %d port_name \"%s\"\n",
01178                                                 pb_graph_pins[i][j].input_edges[k]->input_pins[m]->pin_number, pb_graph_pins[i][j].input_edges[k]->input_pins[m]->port->name);  
01179                                 }
01180                                 print_tabs(fp, level + 3);
01181                                 fprintf(fp, "Input edge outputs\n");
01182                                 for(m = 0; m < pb_graph_pins[i][j].input_edges[k]->num_output_pins; m++) {
01183                                         print_tabs(fp, level + 3);
01184                                         fprintf(fp, "pin number %d port_name \"%s\" parent type \"%s\" parent index %d\n",
01185                                                 pb_graph_pins[i][j].input_edges[k]->output_pins[m]->pin_number, pb_graph_pins[i][j].input_edges[k]->output_pins[m]->port->name,
01186                                                 pb_graph_pins[i][j].input_edges[k]->output_pins[m]->parent_node->pb_type->name,
01187                                                 pb_graph_pins[i][j].input_edges[k]->output_pins[m]->parent_node->placement_index);      
01188                                 }
01189                         }
01190                         for(k = 0; k < pb_graph_pins[i][j].num_output_edges; k++) {
01191                                 print_tabs(fp, level + 2);
01192                                 fprintf(fp, "Output edge %d num inputs %d num outputs %d\n", 
01193                                         k, pb_graph_pins[i][j].output_edges[k]->num_input_pins, pb_graph_pins[i][j].output_edges[k]->num_output_pins);  
01194                                 print_tabs(fp, level + 3);
01195                                 fprintf(fp, "Output edge inputs\n");
01196                                 for(m = 0; m < pb_graph_pins[i][j].output_edges[k]->num_input_pins; m++) {
01197                                         print_tabs(fp, level + 3);
01198                                         fprintf(fp, "pin number %d port_name \"%s\"\n",
01199                                                 pb_graph_pins[i][j].output_edges[k]->input_pins[m]->pin_number, pb_graph_pins[i][j].output_edges[k]->input_pins[m]->port->name);        
01200                                 }
01201                                 print_tabs(fp, level + 3);
01202                                 fprintf(fp, "Output edge outputs\n");
01203                                 for(m = 0; m < pb_graph_pins[i][j].output_edges[k]->num_output_pins; m++) {
01204                                         print_tabs(fp, level + 3);
01205                                         fprintf(fp, "pin number %d port_name \"%s\" parent type \"%s\" parent index %d\n",
01206                                                 pb_graph_pins[i][j].output_edges[k]->output_pins[m]->pin_number, pb_graph_pins[i][j].output_edges[k]->output_pins[m]->port->name,
01207                                                 pb_graph_pins[i][j].output_edges[k]->output_pins[m]->parent_node->pb_type->name,
01208                                                 pb_graph_pins[i][j].output_edges[k]->output_pins[m]->parent_node->placement_index);     
01209                                 }
01210                         }
01211                 }
01212         }
01213 }
01214