VPR-6.0

vpr/SRC/base/read_netlist.c

Go to the documentation of this file.
00001 /**
00002  * @file
00003  *
00004  * Author: Jason Luu
00005  * Date: May 2009
00006  * 
00007  * Read a circuit netlist in XML format and populate the netlist data structures for VPR
00008  */
00009 
00010 #include <stdio.h>
00011 #include <string.h>
00012 #include <assert.h>
00013 #include "util.h"
00014 #include "hash.h"
00015 #include "vpr_types.h"
00016 #include "vpr_utils.h"
00017 #include "ReadLine.h"
00018 #include "globals.h"
00019 #include "ezxml.h"
00020 #include "read_xml_util.h"
00021 #include "read_netlist.h"
00022 #include "pb_type_graph.h"
00023 #include "cluster_legality.h"
00024 #include "token.h"
00025 #include "rr_graph.h"
00026 
00027 static void processPorts(INOUTP ezxml_t Parent, INOUTP t_pb* pb, INOUTP t_rr_node *rr_graph,
00028                                            INOUTP int *ncount, INOUTP struct s_hash **nhash);
00029 
00030 
00031 static void processPb(INOUTP ezxml_t Parent, INOUTP t_pb* pb, INOUTP t_rr_node *rr_graph,
00032                                            INOUTP int *ncount, INOUTP struct s_hash **nhash, INOUTP int *num_primitives);
00033 static void processComplexBlock(INOUTP ezxml_t Parent, INOUTP t_block *cb, INP int index, 
00034                                            INOUTP int *ncount, INOUTP struct s_hash **nhash, 
00035                                            INOUTP int *num_primitives, INP const t_arch *arch);
00036 static struct s_net *alloc_and_init_netlist_from_hash(INP int ncount, INOUTP struct s_hash **nhash);
00037 
00038 static int add_net_to_hash(INOUTP struct s_hash **nhash, INP char *net_name, INOUTP int *ncount);
00039 
00040 static void load_external_nets_and_cb (INP int num_blocks,
00041                                                                                 INP struct s_block block_list[],
00042                                                                                 INP int ncount,
00043                                                                                 INP struct s_net nlist[],
00044                                                                                 OUTP int *ext_ncount, 
00045                                                                                 OUTP struct s_net **ext_nets,
00046                                                                                 INP char **circuit_globals);
00047 
00048 static void load_internal_cb_nets(INOUTP t_pb *top_level, INP t_pb_graph_node *pb_graph_node, INOUTP t_rr_node *rr_graph, INOUTP int * curr_net);
00049 
00050 static void alloc_internal_cb_nets(INOUTP t_pb *top_level, INP t_pb_graph_node *pb_graph_node, INOUTP t_rr_node *rr_graph, INP int pass);
00051 
00052 static void load_internal_cb_rr_graph_net_nums(INP t_rr_node * cur_rr_node, INP t_rr_node * rr_graph, INOUTP struct s_net * nets, INOUTP int * curr_net, INOUTP int * curr_sink);
00053 
00054 static void count_internal_cb_rr_graph_net_nums(INP t_rr_node * cur_rr_node, INP t_rr_node * rr_graph);
00055 
00056 static void mark_constant_generators(INP int num_blocks,
00057                                                                         INP struct s_block block_list[],
00058                                                                         INP int ncount,
00059                                                                         INOUTP struct s_net nlist[]);
00060 
00061 static void mark_constant_generators_rec(INP t_pb *pb,
00062                                                                                  INP t_rr_node *rr_graph,
00063                                                                                 INOUTP struct s_net nlist[]);
00064 
00065 
00066 static void restore_logical_block_from_saved_block(INP int iblk, INP t_pb *pb);
00067 
00068 /**
00069  * Initializes the block_list with info from a netlist 
00070  * @param net_file - Name of the netlist file to read
00071  * @param num_blocks - number of CLBs in netlist 
00072  * @param block_list - array of blocks in netlist [0..num_blocks - 1]
00073  * @param num_nets - number of nets in netlist
00074  * @param net_list - nets in netlist [0..num_nets - 1]
00075  */
00076 void
00077 read_netlist(INP const char *net_file,
00078                          INP const t_arch *arch,
00079                          OUTP int *num_blocks,
00080                          OUTP struct s_block *block_list[],
00081                          OUTP int *num_nets,
00082                          OUTP struct s_net *net_list[])
00083 {
00084         ezxml_t Cur, Prev, Top;
00085         int i, j;
00086         const char *Prop;
00087     int bcount;
00088     struct s_block *blist;
00089     int ncount, ext_ncount;
00090     struct s_net *nlist, *ext_nlist;
00091         struct s_hash **nhash;
00092         char **circuit_inputs, **circuit_outputs, **circuit_globals;
00093         int Count, Len;
00094 
00095         int num_primitives = 0;
00096 
00097         /* Parse the file */ 
00098         printf("Begin parsing packed FPGA netlist file\n");
00099         Top = ezxml_parse_file(net_file);
00100     if(NULL == Top)
00101         {
00102             printf(ERRTAG "Unable to load netlist file '%s'.\n", net_file);
00103                 exit(1);
00104         }
00105         printf("Finished parsing packed FPGA netlist file\n");
00106 
00107         /* Root node should be block */ 
00108         CheckElement(Top, "block");
00109 
00110         /* Check top-level netlist attributes */
00111         Prop = FindProperty(Top, "name", TRUE);
00112         printf("Netlist generated from file %s\n", Prop);
00113         ezxml_set_attr(Top, "name", NULL);
00114 
00115         Prop = FindProperty(Top, "instance", TRUE);
00116         if(strcmp(Prop, "FPGA_packed_netlist[0]") != 0) {
00117                 printf(ERRTAG "[Line %d] Expected instance to be \"FPGA_packed_netlist[0]\", found %s", Top->line, Prop);
00118                 exit(1);
00119         }
00120         ezxml_set_attr(Top, "instance", NULL);
00121 
00122         /* Parse top-level netlist I/Os */
00123         Cur = FindElement(Top, "inputs", TRUE);
00124         circuit_inputs = GetNodeTokens(Cur);
00125         FreeNode(Cur);
00126         Cur = FindElement(Top, "outputs", TRUE);
00127         circuit_outputs = GetNodeTokens(Cur);
00128         FreeNode(Cur);
00129         
00130         Cur = FindElement(Top, "globals", TRUE);
00131         CountTokensInString(Cur->txt, &Count, &Len);
00132         if(Count > 0) {
00133                 circuit_globals = GetNodeTokens(Cur);
00134         } else {
00135                 circuit_globals = NULL;
00136         }
00137         FreeNode(Cur);
00138         
00139         /* Parse all CLB blocks and all nets*/
00140         bcount = CountChildren(Top, "block", 1);
00141         blist = my_calloc(bcount, sizeof(t_block));
00142         nhash = alloc_hash_table();
00143         ncount = 0;
00144 
00145         logical_block = my_calloc(num_saved_logical_blocks, sizeof(t_logical_block));
00146         num_logical_blocks = num_saved_logical_blocks;
00147                 
00148         Cur = Top->child;
00149         i = 0;
00150         while(Cur) {
00151                 if(0 == strcmp(Cur->name, "block"))
00152                 {
00153                         CheckElement(Cur, "block");
00154                         processComplexBlock(Cur, blist, i, &ncount, nhash, &num_primitives, arch);
00155                         Prev = Cur;
00156                         Cur = Cur->next;
00157                         FreeNode(Prev);
00158                         i++;
00159                 } else {
00160                         Cur = Cur->next;
00161                 }
00162         }
00163         assert(i == bcount);
00164         if(saved_logical_blocks != NULL) {
00165                 assert(num_primitives == num_saved_logical_blocks);
00166         }
00167         
00168         nlist = alloc_and_init_netlist_from_hash(ncount, nhash);
00169         mark_constant_generators(bcount, blist, ncount, nlist);
00170         load_external_nets_and_cb(bcount, blist, ncount, nlist, &ext_ncount, &ext_nlist, circuit_globals);
00171 
00172         /* TODO: create this function later
00173                 check_top_IO_matches_IO_blocks(circuit_inputs, circuit_outputs, circuit_globals, blist, bcount);
00174         */
00175 
00176         free_hash_table(nhash);
00177         FreeTokens(&circuit_inputs);
00178         FreeTokens(&circuit_outputs);
00179         if(circuit_globals)
00180                 FreeTokens(&circuit_globals);
00181         FreeNode(Top);
00182 
00183         /* load mapping between external nets and all nets */
00184         /* jluu TODO: Should use local variables here then assign to globals later, clean up later */
00185         vpack_net = nlist;
00186     num_logical_nets = ncount;
00187         clb_to_vpack_net_mapping = my_malloc(ext_ncount * sizeof(int));
00188         vpack_to_clb_net_mapping = my_malloc(ncount * sizeof(int));
00189         for(i = 0; i < ncount; i++) {
00190                 vpack_to_clb_net_mapping[i] = OPEN;
00191         }
00192                 
00193         for(i = 0; i < ext_ncount; i++) {
00194                 for(j = 0; j < ncount; j++) {
00195                         if(strcmp(ext_nlist[i].name, nlist[j].name) == 0) {
00196                                 clb_to_vpack_net_mapping[i] = j;
00197                                 vpack_to_clb_net_mapping[j] = i;
00198                                 break;
00199                         }
00200                 }
00201                 assert(j != ncount);
00202         }
00203 
00204         if(saved_logical_blocks != NULL) {
00205                 free(saved_logical_blocks);
00206                 saved_logical_blocks = NULL;
00207                 free(saved_logical_nets);
00208                 saved_logical_nets = NULL;
00209         }
00210 
00211         /* Return blocks and nets */
00212         *num_blocks = bcount;
00213         *block_list = blist;
00214         *num_nets = ext_ncount;
00215         *net_list = ext_nlist;
00216 }
00217 
00218 
00219 /**
00220  * XML parser to populate CLB info and to update nets with the nets of this CLB 
00221  * @param Parent - XML tag for this CLB
00222  * @param clb - Array of CLBs in the netlist
00223  * @param index - index of the CLB to allocate and load information into
00224  * @param ncount - number of nets recorded thus far in all CLBs
00225  * @param nhash - hashtable of all nets recorded thus far in all CLBs
00226  */
00227 static void processComplexBlock(INOUTP ezxml_t Parent, INOUTP t_block *cb, INP int index, 
00228                                            INOUTP int *ncount, INOUTP struct s_hash **nhash, 
00229                                            INOUTP int *num_primitives, INP const t_arch *arch) {
00230 
00231         const char *Prop;
00232         boolean found;
00233         int num_tokens = 0;
00234         t_token *tokens;
00235         int i;
00236         const t_pb_type * pb_type = NULL;
00237 
00238         /* parse cb attributes */
00239         cb[index].pb = my_calloc(1, sizeof(t_pb));
00240 
00241         Prop = FindProperty(Parent, "name", TRUE);
00242         cb[index].name = my_strdup(Prop);
00243         cb[index].pb->name = my_strdup(Prop);
00244         ezxml_set_attr(Parent, "name", NULL);
00245 
00246         Prop = FindProperty(Parent, "instance", TRUE);
00247         tokens = GetTokensFromString(Prop, &num_tokens);
00248         ezxml_set_attr(Parent, "instance", NULL);
00249         if(num_tokens != 4 ||
00250                 tokens[0].type != TOKEN_STRING ||
00251                 tokens[1].type != TOKEN_OPEN_SQUARE_BRACKET ||
00252                 tokens[2].type != TOKEN_INT ||
00253                 tokens[3].type != TOKEN_CLOSE_SQUARE_BRACKET) {
00254                 printf(ERRTAG "[Line %d] Unknown syntax for instance %s in %s.  Expected pb_type[instance_number]\n",
00255                         Parent->line, Prop, Parent->name);
00256                 exit(1);
00257         }
00258         assert(my_atoi(tokens[2].data) == index);
00259         found = FALSE;
00260         for(i = 0; i < num_types; i++) {
00261                 if(strcmp(type_descriptors[i].name, tokens[0].data) == 0) {
00262                         cb[index].type = &type_descriptors[i];
00263                         pb_type = cb[index].type->pb_type;
00264                         found = TRUE;
00265                         break;
00266                 }
00267         }
00268         if(!found) {
00269                 printf(ERRTAG "[Line %d] Unknown cb type %s for cb %s #%d\n", Parent->line, Prop, cb[index].name, index);
00270                 exit(1);
00271         }
00272                 
00273         /* Parse all pbs and CB internal nets*/
00274         cb[index].pb->logical_block = OPEN;
00275         cb[index].pb->pb_graph_node = cb[index].type->pb_graph_head;
00276         rr_node = my_calloc(cb[index].type->pb_graph_head->total_pb_pins, sizeof(t_rr_node));
00277         alloc_and_load_rr_graph_for_pb_graph_node(cb[index].pb->pb_graph_node, arch, 0);
00278         cb[index].pb->rr_graph = rr_node;
00279         num_rr_nodes = cb[index].pb->pb_graph_node->total_pb_pins;
00280         
00281         Prop = FindProperty(Parent, "mode", TRUE);
00282         ezxml_set_attr(Parent, "mode", NULL);
00283 
00284         found = FALSE;
00285         for(i = 0; i < pb_type->num_modes; i++) {
00286                 if(strcmp(Prop, pb_type->modes[i].name) == 0) {
00287                         cb[index].pb->mode = i;
00288                         found = TRUE;
00289                 }
00290         }
00291         if(!found) {
00292                 printf(ERRTAG "[Line %d] Unknown mode %s for cb %s #%d\n", Parent->line, Prop, cb[index].name, index);
00293                 exit(1);
00294         }
00295 
00296         processPb(Parent, cb[index].pb, cb[index].pb->rr_graph, ncount, nhash, num_primitives);
00297 
00298         cb[index].nets = my_malloc(cb[index].type->num_pins * sizeof(int));
00299         for(i = 0; i < cb[index].type->num_pins; i++ ) {
00300                 cb[index].nets[i] = OPEN;
00301         }
00302         alloc_internal_cb_nets(cb[index].pb, cb[index].pb->pb_graph_node, cb[index].pb->rr_graph, 1);
00303         alloc_internal_cb_nets(cb[index].pb, cb[index].pb->pb_graph_node, cb[index].pb->rr_graph, 2);
00304         i = 0;
00305         load_internal_cb_nets(cb[index].pb, cb[index].pb->pb_graph_node, cb[index].pb->rr_graph, &i);
00306         freeTokens(tokens, num_tokens);
00307 #if 0
00308         /* TODO: may not need local nets anymore, reminder to remove if not used, keeping this around just in case we need to use it in the future */
00309         for(i = 0; i < cb[index].pb->num_local_nets; i++) {
00310                 printf("local net %s: ", cb[index].pb->name);
00311                 for(j = 0; j <= cb[index].pb->local_nets[i].num_sinks; j++) {
00312                         printf("%d ", cb[index].pb->local_nets[i].node_block[j]);
00313                 }
00314                 printf("\n");
00315         }
00316 #endif
00317 }
00318 
00319 
00320 /**
00321  * XML parser to populate pb info and to update internal nets of the parent CLB
00322  * @param Parent - XML tag for this pb_type
00323  * @param pb - physical block to use
00324  * @param ncount - number of all internal subblock nets recorded thus far in this CLB
00325  * @param nhash - hashtable of all internal subblock nets recorded thus far in this CLBs
00326  */
00327 static void processPb(INOUTP ezxml_t Parent, INOUTP t_pb* pb, INOUTP t_rr_node *rr_graph,
00328                                            INOUTP int *ncount, INOUTP struct s_hash **nhash, INOUTP int *num_primitives) {
00329         ezxml_t Cur, Prev, lookahead;
00330         const char *Prop;
00331         const char *instance_type;
00332         int i, j, pb_index;
00333         boolean found;
00334         const t_pb_type *pb_type;
00335         t_token *tokens;
00336         int num_tokens;
00337 
00338         Cur = FindElement(Parent, "inputs", TRUE);
00339         processPorts(Cur, pb, rr_graph, ncount, nhash);
00340         FreeNode(Cur);
00341         Cur = FindElement(Parent, "outputs", TRUE);
00342         processPorts(Cur, pb, rr_graph, ncount, nhash);
00343         FreeNode(Cur);
00344         Cur = FindElement(Parent, "globals", TRUE);
00345         processPorts(Cur, pb, rr_graph, ncount, nhash);
00346         FreeNode(Cur);
00347         
00348 
00349         pb_type = pb->pb_graph_node->pb_type;
00350         if(pb_type->num_modes == 0) {
00351                 pb->logical_block = *num_primitives;
00352                 /* TODO: This info is not yet used.  Intention was to use later for error checking */
00353                 if(saved_logical_blocks != NULL) {
00354                         restore_logical_block_from_saved_block(*num_primitives, pb);
00355                 }
00356                 (*num_primitives)++;            
00357         } else {
00358                 /* process children of child if exists */
00359         
00360                 pb->child_pbs = my_calloc(pb_type->modes[pb->mode].num_pb_type_children, sizeof(t_pb*));
00361                 for(i = 0; i < pb_type->modes[pb->mode].num_pb_type_children; i++) {
00362                         pb->child_pbs[i] = my_calloc(pb_type->modes[pb->mode].pb_type_children[i].num_pb, sizeof(t_pb));
00363                 }
00364 
00365                 /* Populate info for each physical block  */
00366                 Cur = Parent->child;
00367                 while(Cur) {
00368                         if(0 == strcmp(Cur->name, "block"))
00369                         {
00370                                 CheckElement(Cur, "block");
00371 
00372                                 instance_type = FindProperty(Cur, "instance", TRUE);
00373                                 tokens = GetTokensFromString(instance_type, &num_tokens);
00374                                 ezxml_set_attr(Cur, "instance", NULL);
00375                                 if(num_tokens != 4 ||
00376                                         tokens[0].type != TOKEN_STRING ||
00377                                         tokens[1].type != TOKEN_OPEN_SQUARE_BRACKET ||
00378                                         tokens[2].type != TOKEN_INT ||
00379                                         tokens[3].type != TOKEN_CLOSE_SQUARE_BRACKET) {
00380                                         printf(ERRTAG "[Line %d] Unknown syntax for instance %s in %s.  Expected pb_type[instance_number]\n",
00381                                                 Cur->line, instance_type, Cur->name);
00382                                         exit(1);
00383                                 }
00384                                 
00385                                 found = FALSE;
00386                                 pb_index = OPEN;
00387                                 for(i = 0; i < pb_type->modes[pb->mode].num_pb_type_children; i++) {
00388                                         if(strcmp(pb_type->modes[pb->mode].pb_type_children[i].name, tokens[0].data) == 0) {
00389                                                 if(my_atoi(tokens[2].data) >= pb_type->modes[pb->mode].pb_type_children[i].num_pb) {
00390                                                         printf(ERRTAG "[Line %d] Instance number exceeds # of pb available for instance %s in %s.\n",
00391                                                                 Cur->line, instance_type, Cur->name);
00392                                                         exit(1);
00393                                                 }
00394                                                 pb_index = my_atoi(tokens[2].data);
00395                                                 if(pb->child_pbs[i][pb_index].pb_graph_node != NULL) {
00396                                                         printf(ERRTAG "[Line %d] node is used by two different blocks %s and %s\n", Cur->line, instance_type, pb->child_pbs[i][pb_index].name);
00397                                                         exit(1);
00398                                                 }
00399                                                 pb->child_pbs[i][pb_index].pb_graph_node = &pb->pb_graph_node->child_pb_graph_nodes[pb->mode][i][pb_index];
00400                                                 found = TRUE;
00401                                                 break;
00402                                         }
00403                                 }
00404                                 if(!found) {
00405                                         printf(ERRTAG "[Line %d] Unknown pb type %s\n", Cur->line, instance_type);
00406                                         exit(1);
00407                                 }
00408                                         
00409                                 Prop = FindProperty(Cur, "name", TRUE);
00410                                 ezxml_set_attr(Cur, "name", NULL);
00411                                 if(0 != strcmp(Prop, "open")) {
00412                                         pb->child_pbs[i][pb_index].name = my_strdup(Prop);
00413                                         
00414                                         /* Parse all pbs and CB internal nets*/
00415                                         pb->child_pbs[i][pb_index].logical_block = OPEN;
00416                                         
00417                                         Prop = FindProperty(Cur, "mode", FALSE);
00418                                         if(Prop) {
00419                                                 ezxml_set_attr(Cur, "mode", NULL);
00420                                         }
00421                                         pb->child_pbs[i][pb_index].mode = 0;
00422                                         found = FALSE;
00423                                         for(j = 0; j < pb->child_pbs[i][pb_index].pb_graph_node->pb_type->num_modes; j++) {
00424                                                 if(strcmp(Prop, pb->child_pbs[i][pb_index].pb_graph_node->pb_type->modes[j].name) == 0) {
00425                                                         pb->child_pbs[i][pb_index].mode = j;
00426                                                         found = TRUE;
00427                                                 }
00428                                         }
00429                                         if(!found && pb->child_pbs[i][pb_index].pb_graph_node->pb_type->num_modes != 0) {
00430                                                 printf(ERRTAG "[Line %d] Unknown mode %s for cb %s #%d\n", Cur->line, Prop, pb->child_pbs[i][pb_index].name, pb_index);
00431                                                 exit(1);
00432                                         }
00433                                         pb->child_pbs[i][pb_index].parent_pb = pb;
00434                                         pb->child_pbs[i][pb_index].rr_graph = pb->rr_graph;
00435                                 
00436                                         processPb(Cur, &pb->child_pbs[i][pb_index], rr_graph, ncount, nhash, num_primitives);
00437                                 } else {
00438                                         /* physical block has no used primitives but it may have used routing */
00439                                         pb->child_pbs[i][pb_index].name = NULL;
00440                                         pb->child_pbs[i][pb_index].logical_block = OPEN;
00441                                         lookahead = FindElement(Cur, "outputs", FALSE);
00442                                         if(lookahead != NULL) {
00443                                                 lookahead = FindElement(lookahead, "port", TRUE);
00444                                                 Prop = FindProperty(Cur, "mode", FALSE);
00445                                                 if(Prop) {
00446                                                         ezxml_set_attr(Cur, "mode", NULL);
00447                                                 }
00448                                                 pb->child_pbs[i][pb_index].mode = 0;
00449                                                 found = FALSE;
00450                                                 for(j = 0; j < pb->child_pbs[i][pb_index].pb_graph_node->pb_type->num_modes; j++) {
00451                                                         if(strcmp(Prop, pb->child_pbs[i][pb_index].pb_graph_node->pb_type->modes[j].name) == 0) {
00452                                                                 pb->child_pbs[i][pb_index].mode = j;
00453                                                                 found = TRUE;
00454                                                         }
00455                                                 }
00456                                                 if(!found && pb->child_pbs[i][pb_index].pb_graph_node->pb_type->num_modes != 0) {
00457                                                         printf(ERRTAG "[Line %d] Unknown mode %s for cb %s #%d\n", Cur->line, Prop, pb->child_pbs[i][pb_index].name, pb_index);
00458                                                         exit(1);
00459                                                 }
00460                                                 pb->child_pbs[i][pb_index].parent_pb = pb;
00461                                                 pb->child_pbs[i][pb_index].rr_graph = pb->rr_graph;
00462                                                 processPb(Cur, &pb->child_pbs[i][pb_index], rr_graph, ncount, nhash, num_primitives);                           
00463                                         }
00464                                 }
00465                                 Prev = Cur;
00466                                 Cur = Cur->next;
00467                                 FreeNode(Prev);
00468                                 freeTokens(tokens, num_tokens);
00469                         } else {
00470                                 Cur = Cur->next;
00471                         }
00472                 }
00473         }
00474 }
00475 
00476 
00477 
00478 /**
00479  * Allocates memory for nets and loads the name of the net so that it can be identified and loaded with
00480  * more complete information later
00481  * @param ncount - number of nets in the hashtable of nets
00482  * @param nhash - hashtable of nets
00483  * @return array of nets stored in hashtable
00484  */
00485 static struct s_net *alloc_and_init_netlist_from_hash(INP int ncount, INOUTP struct s_hash **nhash) {
00486         struct s_net *nlist;
00487         struct s_hash_iterator hash_iter;
00488         struct s_hash *curr_net;
00489         int i;
00490         
00491         nlist = my_calloc(ncount, sizeof(struct s_net));
00492 
00493         hash_iter = start_hash_table_iterator();
00494         curr_net = get_next_hash(nhash, &hash_iter);    
00495         while(curr_net != NULL) {
00496                 assert(nlist[curr_net->index].name == NULL);
00497                 nlist[curr_net->index].name = my_strdup(curr_net->name);
00498                 nlist[curr_net->index].num_sinks = curr_net->count - 1;
00499 
00500                 nlist[curr_net->index].node_block = my_malloc(curr_net->count * sizeof(int));
00501                 nlist[curr_net->index].node_block_pin = my_malloc(curr_net->count * sizeof(int));
00502                 nlist[curr_net->index].is_global = FALSE;
00503                 for(i = 0; i < curr_net->count; i++) {
00504                         nlist[curr_net->index].node_block[i] = OPEN;
00505                         nlist[curr_net->index].node_block_pin[i] = OPEN;
00506                 }
00507                 curr_net = get_next_hash(nhash, &hash_iter);
00508         }
00509         return nlist;
00510 }
00511 
00512 /**
00513  * Adds net to hashtable of nets.  If the net is "open", then this is a keyword so do not add it.  
00514  * If the net already exists, increase the count on that net 
00515  */
00516 static int add_net_to_hash(INOUTP struct s_hash **nhash, INP char *net_name, INOUTP int *ncount) {
00517         struct s_hash *hash_value;
00518 
00519         if(strcmp(net_name, "open") == 0) {
00520                 return OPEN;
00521         }
00522 
00523         hash_value = insert_in_hash_table(nhash, net_name, *ncount);
00524         if(hash_value->count == 1) {
00525                 assert(*ncount == hash_value->index);
00526                 (*ncount)++;
00527         }
00528         return hash_value->index;
00529 }
00530 
00531 static void processPorts(INOUTP ezxml_t Parent, INOUTP t_pb* pb, t_rr_node *rr_graph,
00532                                            INOUTP int *ncount, INOUTP struct s_hash **nhash) {
00533 
00534         int i, j, in_port, out_port, clock_port, num_tokens;
00535         ezxml_t Cur, Prev;
00536         const char *Prop;
00537         char **pins;
00538         char *port_name, *interconnect_name;
00539         int rr_node_index;
00540         t_pb_graph_pin *** pin_node;
00541         int *num_ptrs, num_sets;
00542         boolean found;
00543 
00544         Cur = Parent->child;
00545         while(Cur) {
00546                 if(0 == strcmp(Cur->name, "port"))
00547                 {
00548                         CheckElement(Cur, "port");
00549 
00550                         Prop = FindProperty(Cur, "name", TRUE);
00551                         ezxml_set_attr(Cur, "name", NULL);
00552                         
00553                         in_port = out_port = clock_port = 0;
00554                         found = FALSE;
00555                         for(i = 0; i < pb->pb_graph_node->pb_type->num_ports; i++) {
00556                                 if(0 == strcmp(pb->pb_graph_node->pb_type->ports[i].name, Prop)) {
00557                                         found = TRUE;
00558                                         break;
00559                                 }
00560                                 if(pb->pb_graph_node->pb_type->ports[i].is_clock && pb->pb_graph_node->pb_type->ports[i].type == IN_PORT) {
00561                                         clock_port++;
00562                                 } else if(!pb->pb_graph_node->pb_type->ports[i].is_clock && pb->pb_graph_node->pb_type->ports[i].type == IN_PORT) {
00563                                         in_port++;
00564                                 } else {
00565                                         assert(pb->pb_graph_node->pb_type->ports[i].type == OUT_PORT);
00566                                         out_port++;
00567                                 }
00568                         }       
00569                         if(!found) {
00570                                 printf(ERRTAG "[Line %d] Unknown port %s for pb %s[%d]\n", Cur->line, Prop, pb->pb_graph_node->pb_type->name, pb->pb_graph_node->placement_index);
00571                                 exit(1);
00572                         }
00573 
00574                         pins = GetNodeTokens(Cur);
00575                         num_tokens = CountTokens(pins);
00576                         if(0 == strcmp(Parent->name, "inputs")) {
00577                                 if(num_tokens != pb->pb_graph_node->num_input_pins[in_port]) {
00578                                         printf(ERRTAG "[Line %d] Incorrect # pins %d found for port %s for pb %s[%d]\n", Cur->line, num_tokens, Prop, pb->pb_graph_node->pb_type->name, pb->pb_graph_node->placement_index);
00579                                         exit(1);
00580                                 }
00581                         } else if(0 == strcmp(Parent->name, "outputs")) {
00582                                 if(num_tokens != pb->pb_graph_node->num_output_pins[out_port]) {
00583                                         printf(ERRTAG "[Line %d] Incorrect # pins %d found for port %s for pb %s[%d]\n", Cur->line, num_tokens, Prop, pb->pb_graph_node->pb_type->name, pb->pb_graph_node->placement_index);
00584                                         exit(1);
00585                                 }
00586                         } else {
00587                                 if(num_tokens != pb->pb_graph_node->num_clock_pins[clock_port]) {
00588                                         printf(ERRTAG "[Line %d] Incorrect # pins %d found for port %s for pb %s[%d]\n", Cur->line, num_tokens, Prop, pb->pb_graph_node->pb_type->name, pb->pb_graph_node->placement_index);
00589                                         exit(1);
00590                                 }
00591                         } 
00592                         if(0 == strcmp(Parent->name, "inputs") || 0 == strcmp(Parent->name, "globals")) {
00593                                 if(pb->parent_pb == NULL) {
00594                                         /* top-level, connections are nets to route */
00595                                         for(i = 0; i < num_tokens; i++) {
00596                                                 if(0 == strcmp(Parent->name, "inputs"))
00597                                                         rr_node_index = pb->pb_graph_node->input_pins[in_port][i].pin_count_in_cluster;
00598                                                 else
00599                                                         rr_node_index = pb->pb_graph_node->clock_pins[clock_port][i].pin_count_in_cluster;
00600                                                 rr_graph[rr_node_index].net_num = add_net_to_hash(nhash, pins[i], ncount);
00601                                         }
00602                                 } else {
00603                                         for(i = 0; i < num_tokens; i++) {
00604                                                 if(0 == strcmp(pins[i], "open")) {
00605                                                         continue;
00606                                                 }
00607                                                 interconnect_name = strstr(pins[i], "->");
00608                                                 *interconnect_name = '\0';
00609                                                 interconnect_name += 2;
00610                                                 port_name = pins[i];
00611                                                 pin_node =  alloc_and_load_port_pin_ptrs_from_string(pb->pb_graph_node->parent_pb_graph_node, 
00612                                                                                                                                                         pb->pb_graph_node->parent_pb_graph_node->child_pb_graph_nodes[pb->parent_pb->mode],
00613                                                                                                                                                         port_name,
00614                                                                                                                                                         &num_ptrs,
00615                                                                                                                                                         &num_sets,
00616                                                                                                                                                         TRUE,
00617                                                                                                                                                         TRUE);
00618                                                 assert(num_sets == 1 && num_ptrs[0] == 1);
00619                                                 if(0 == strcmp(Parent->name, "inputs"))
00620                                                         rr_node_index = pb->pb_graph_node->input_pins[in_port][i].pin_count_in_cluster;
00621                                                 else
00622                                                         rr_node_index = pb->pb_graph_node->clock_pins[clock_port][i].pin_count_in_cluster;
00623                                                 rr_graph[rr_node_index].prev_node = pin_node[0][0]->pin_count_in_cluster;
00624                                                 found = FALSE;
00625                                                 for(j = 0; j < pin_node[0][0]->num_output_edges; j++) {
00626                                                         if(0 == strcmp(interconnect_name, pin_node[0][0]->output_edges[j]->interconnect->name)) {
00627                                                                 found = TRUE;
00628                                                                 break;
00629                                                         }
00630                                                 }
00631                                                 for(j = 0; j < num_sets; j++) {
00632                                                         free(pin_node[j]);
00633                                                 }
00634                                                 free(pin_node);
00635                                                 free(num_ptrs);
00636                                                 if(!found) {
00637                                                         printf(ERRTAG "[Line %d] Unknown interconnect %s connecting to pin %s\n", Cur->line, interconnect_name, port_name);
00638                                                         exit(1);
00639                                                 }
00640                                         }
00641                                 }
00642                         }
00643 
00644                         if(0 == strcmp(Parent->name, "outputs")) {
00645                                 if(pb->pb_graph_node->pb_type->num_modes == 0) {
00646                                         /* primitives are drivers of nets */
00647                                         for(i = 0; i < num_tokens; i++) {
00648                                                 rr_node_index = pb->pb_graph_node->output_pins[out_port][i].pin_count_in_cluster;
00649                                                 rr_graph[rr_node_index].net_num = add_net_to_hash(nhash, pins[i], ncount);
00650                                         }
00651                                 } else {
00652                                         for(i = 0; i < num_tokens; i++) {
00653                                                 if(0 == strcmp(pins[i], "open")) {
00654                                                         continue;
00655                                                 }
00656                                                 interconnect_name = strstr(pins[i], "->");
00657                                                 *interconnect_name = '\0';
00658                                                 interconnect_name += 2;
00659                                                 port_name = pins[i];
00660                                                 pin_node =  alloc_and_load_port_pin_ptrs_from_string(pb->pb_graph_node, 
00661                                                                                                                                                         pb->pb_graph_node->child_pb_graph_nodes[pb->mode],
00662                                                                                                                                                         port_name,
00663                                                                                                                                                         &num_ptrs,
00664                                                                                                                                                         &num_sets,
00665                                                                                                                                                         TRUE,
00666                                                                                                                                                         TRUE);
00667                                                 assert(num_sets == 1 && num_ptrs[0] == 1);
00668                                                 rr_node_index = pb->pb_graph_node->output_pins[out_port][i].pin_count_in_cluster;
00669                                                 rr_graph[rr_node_index].prev_node = pin_node[0][0]->pin_count_in_cluster;
00670                                                 found = FALSE;
00671                                                 for(j = 0; j < pin_node[0][0]->num_output_edges; j++) {
00672                                                         if(0 == strcmp(interconnect_name, pin_node[0][0]->output_edges[j]->interconnect->name)) {
00673                                                                 found = TRUE;
00674                                                                 rr_graph[rr_node_index].fan_in++;
00675                                                                 rr_graph[pin_node[0][0]->pin_count_in_cluster].edges[j] = rr_node_index;
00676                                                                 break;
00677                                                         }
00678                                                 }               
00679                                                 for(j = 0; j < num_sets; j++) {
00680                                                         free(pin_node[j]);
00681                                                 }
00682                                                 free(pin_node);
00683                                                 free(num_ptrs);
00684                                                 if(!found) {
00685                                                         printf(ERRTAG "[Line %d] Unknown interconnect %s connecting to pin %s\n", Cur->line, interconnect_name, port_name);
00686                                                         exit(1);
00687                                                 }
00688                                                 interconnect_name -= 2;
00689                                                 *interconnect_name = '-';
00690                                         }
00691                                 }
00692                         }
00693 
00694                         FreeTokens(&pins);
00695 
00696                         Prev = Cur;
00697                         Cur = Cur->next;
00698                         FreeNode(Prev);
00699                 } else {
00700                         Cur = Cur->next;
00701                 }
00702         }
00703 }
00704 
00705 
00706 /**  
00707  * This function updates the nets list and the connections between that list and the complex block
00708  */
00709 static void
00710 load_external_nets_and_cb(INP int num_blocks,
00711                     INP struct s_block block_list[],
00712                     INP int ncount,
00713                         INP struct s_net nlist[],
00714                         OUTP int *ext_ncount, 
00715                         OUTP struct s_net **ext_nets,
00716                         INP char **circuit_globals)
00717 {
00718     int i, j, k, ipin;
00719         struct s_hash **ext_nhash;
00720         t_rr_node *rr_graph;
00721         t_pb_graph_pin *pb_graph_pin;
00722         int *count;
00723         int netnum, num_tokens;
00724 
00725 
00726         *ext_ncount = 0;
00727         ext_nhash = alloc_hash_table();
00728 
00729         /* Assumes that complex block pins are ordered inputs, outputs, globals */
00730 
00731         /* Determine the external nets of complex block */
00732         for(i = 0; i < num_blocks; i++) {
00733                 ipin = 0;
00734                 if(block_list[i].type->pb_type->num_input_pins + 
00735                         block_list[i].type->pb_type->num_output_pins + 
00736                         block_list[i].type->pb_type->num_clock_pins != block_list[i].type->num_pins / block_list[i].type->capacity) {
00737 
00738                         assert(0);
00739                 }
00740                         
00741 
00742                 /* First determine nets external to complex blocks */
00743                 assert(block_list[i].type->pb_type->num_input_pins + 
00744                         block_list[i].type->pb_type->num_output_pins + 
00745                         block_list[i].type->pb_type->num_clock_pins == block_list[i].type->num_pins / block_list[i].type->capacity);
00746 
00747                 rr_graph = block_list[i].pb->rr_graph;
00748                 for(j = 0; j < block_list[i].pb->pb_graph_node->num_input_ports; j++) {
00749                         for(k = 0; k < block_list[i].pb->pb_graph_node->num_input_pins[j]; k++) {
00750                                 pb_graph_pin = &block_list[i].pb->pb_graph_node->input_pins[j][k];
00751                                 assert(pb_graph_pin->pin_count_in_cluster == ipin);
00752                                 if(rr_graph[pb_graph_pin->pin_count_in_cluster].net_num != OPEN) {
00753                                         block_list[i].nets[ipin] = add_net_to_hash(ext_nhash, nlist[rr_graph[pb_graph_pin->pin_count_in_cluster].net_num].name, ext_ncount);
00754                                 } else {
00755                                         block_list[i].nets[ipin] = OPEN;
00756                                 }                               
00757                                 ipin++;
00758                         }
00759                 }
00760                 for(j = 0; j < block_list[i].pb->pb_graph_node->num_output_ports; j++) {
00761                         for(k = 0; k < block_list[i].pb->pb_graph_node->num_output_pins[j]; k++) {
00762                                 pb_graph_pin = &block_list[i].pb->pb_graph_node->output_pins[j][k];
00763                                 assert(pb_graph_pin->pin_count_in_cluster == ipin);
00764                                 if(rr_graph[pb_graph_pin->pin_count_in_cluster].net_num != OPEN) {
00765                                         block_list[i].nets[ipin] = add_net_to_hash(ext_nhash, nlist[rr_graph[pb_graph_pin->pin_count_in_cluster].net_num].name, ext_ncount);
00766                                 } else {
00767                                         block_list[i].nets[ipin] = OPEN;
00768                                 }
00769                                 ipin++;
00770                         }
00771                 }
00772                 for(j = 0; j < block_list[i].pb->pb_graph_node->num_clock_ports; j++) {
00773                         for(k = 0; k < block_list[i].pb->pb_graph_node->num_clock_pins[j]; k++) {
00774                                 pb_graph_pin = &block_list[i].pb->pb_graph_node->clock_pins[j][k];
00775                                 assert(pb_graph_pin->pin_count_in_cluster == ipin);
00776                                 if(rr_graph[pb_graph_pin->pin_count_in_cluster].net_num != OPEN) {
00777                                         block_list[i].nets[ipin] = add_net_to_hash(ext_nhash, nlist[rr_graph[pb_graph_pin->pin_count_in_cluster].net_num].name, ext_ncount);
00778                                 } else {
00779                                         block_list[i].nets[ipin] = OPEN;
00780                                 }
00781                                 ipin++;
00782                         }
00783                 }
00784                 for(j = ipin; j < block_list[i].type->num_pins; j++) {
00785                         block_list[i].nets[ipin] = OPEN;
00786                 }
00787         }
00788 
00789         /* alloc and partially load the list of external nets */
00790         (*ext_nets) = alloc_and_init_netlist_from_hash(*ext_ncount, ext_nhash);
00791         /* Load global nets */
00792         num_tokens = CountTokens(circuit_globals);
00793         for(i = 0; i < *ext_ncount; i++) {
00794                 for(j = 0; j < num_tokens; j++) {
00795                         if(strcmp(circuit_globals[j], (*ext_nets)[i].name) == 0) {
00796                                 (*ext_nets)[i].is_global = TRUE;
00797                         }
00798                 }
00799         }
00800         count = my_calloc(*ext_ncount, sizeof(int));
00801 
00802     /* complete load of external nets so that each net points back to the blocks */
00803         for(i = 0; i < num_blocks; i++) {
00804                 ipin = 0;
00805                 rr_graph = block_list[i].pb->rr_graph;
00806                 for(j = 0; j < block_list[i].type->num_pins; j++) {
00807                         netnum = block_list[i].nets[j];
00808                         if(netnum != OPEN) {
00809                                 if(RECEIVER == block_list[i].type->class_inf[block_list[i].type->pin_class[j]].type)
00810                                 {
00811                                         count[netnum]++;
00812                                         assert(count[netnum] <= (*ext_nets)[netnum].num_sinks);
00813                                     (*ext_nets)[netnum].node_block[count[netnum]] = i;
00814                                     (*ext_nets)[netnum].node_block_pin[count[netnum]] = j;
00815 
00816                                         if((*ext_nets)[netnum].is_global != block_list[i].type->is_global_pin[j]) {
00817                                                 if((*ext_nets)[netnum].is_global) {
00818                                                         printf(ERRTAG "Netlist attempts to connect global net %s to non global pin %d of block %s #%d\n",
00819                                                                 (*ext_nets)[netnum].name, j, block_list[i].name, j);
00820                                                 } else {
00821                                                         printf(ERRTAG "Netlist attempts to connect non-global net %s to global pin %d of block %s #%d\n",
00822                                                                 (*ext_nets)[netnum].name, j, block_list[i].name, j);
00823                                                 }
00824                                                 exit(1);
00825                                         }
00826                                 }
00827                             else
00828                                 {
00829                                     assert(DRIVER == block_list[i].type->class_inf[block_list[i].type->pin_class[j]].type);
00830                                         assert((*ext_nets)[netnum].node_block[0] == OPEN);
00831                                     (*ext_nets)[netnum].node_block[0] = i;
00832                                     (*ext_nets)[netnum].node_block_pin[0] = j;
00833                                 }
00834                         }                       
00835                 }
00836         }
00837         free(count);
00838         free_hash_table(ext_nhash);
00839 }
00840 
00841 /** Recursive function that fills rr_graph of cb with net numbers starting at the given rr_node */
00842 static int count_sinks_internal_cb_rr_graph_net_nums(INP t_rr_node * cur_rr_node, INP t_rr_node * rr_graph) {
00843         int i;
00844         int count = 0;
00845 
00846         for(i = 0; i < cur_rr_node->num_edges; i++) {
00847                 if(&rr_graph[rr_graph[cur_rr_node->edges[i]].prev_node] == cur_rr_node) {
00848                         assert(rr_graph[cur_rr_node->edges[i]].net_num == OPEN || rr_graph[cur_rr_node->edges[i]].net_num == cur_rr_node->net_num);
00849                         count += count_sinks_internal_cb_rr_graph_net_nums(&rr_graph[cur_rr_node->edges[i]], rr_graph);
00850                 }
00851         }
00852         if(count == 0) {
00853                 return 1; /* terminal node */
00854         } else {
00855                 return count;
00856         }
00857 }
00858 
00859 /** Recursive function that fills rr_graph of cb with net numbers starting at the given rr_node */
00860 static void load_internal_cb_rr_graph_net_nums(INP t_rr_node * cur_rr_node, INP t_rr_node * rr_graph, INOUTP struct s_net * nets, INOUTP int * curr_net, INOUTP int * curr_sink) {
00861         int i;
00862 
00863         boolean terminal;
00864         terminal = TRUE;
00865 
00866         for(i = 0; i < cur_rr_node->num_edges; i++) {
00867                 if(&rr_graph[rr_graph[cur_rr_node->edges[i]].prev_node] == cur_rr_node) {
00868                         /* TODO: If multiple edges to same node (should not happen in reasonable design) this always
00869                         selects the last edge, need to be smart about it in future (ie. select fastest edge */
00870                         assert(rr_graph[cur_rr_node->edges[i]].net_num == OPEN || rr_graph[cur_rr_node->edges[i]].net_num == cur_rr_node->net_num);
00871                         rr_graph[cur_rr_node->edges[i]].net_num = cur_rr_node->net_num;
00872                         rr_graph[cur_rr_node->edges[i]].prev_edge = i;
00873                         load_internal_cb_rr_graph_net_nums(&rr_graph[cur_rr_node->edges[i]], rr_graph, nets, curr_net, curr_sink);
00874                         terminal = FALSE;
00875                 }
00876         }
00877         if(terminal == TRUE) {
00878                 /* Since the routing node index is known, assign that instead of the more obscure node block */
00879                 nets[*curr_net].node_block[*curr_sink] = cur_rr_node->pb_graph_pin->pin_count_in_cluster;
00880                 nets[*curr_net].node_block_pin[*curr_sink] = OPEN;
00881                 nets[*curr_net].node_block_port[*curr_sink] = OPEN;
00882                 (*curr_sink)++;
00883         }
00884 }
00885 
00886 /** Load internal cb nets and fill rr_graph of cb with net numbers */
00887 static void load_internal_cb_nets(INOUTP t_pb *top_level, INP t_pb_graph_node *pb_graph_node, INOUTP t_rr_node *rr_graph, INOUTP int * curr_net) {
00888         int i, j, k;
00889         const t_pb_type *pb_type;
00890         int temp, size;
00891         struct s_net * nets;
00892 
00893         pb_type = pb_graph_node->pb_type;
00894 
00895         nets = top_level->local_nets;
00896 
00897         temp = 0;
00898 
00899         if(pb_graph_node->parent_pb_graph_node == NULL) { /* determine nets driven from inputs at top level */
00900                 *curr_net = 0;
00901                 for(i = 0; i < pb_graph_node->num_input_ports; i++) {
00902                         for(j = 0; j < pb_graph_node->num_input_pins[i]; j++) {
00903                                 if(rr_graph[pb_graph_node->input_pins[i][j].pin_count_in_cluster].net_num != OPEN) {
00904                                         load_internal_cb_rr_graph_net_nums(&rr_graph[pb_graph_node->input_pins[i][j].pin_count_in_cluster], rr_graph, nets, curr_net, &temp);
00905                                         assert(temp == nets[*curr_net].num_sinks);
00906                                         temp = 0;
00907                                         size = strlen(pb_graph_node->pb_type->name) + 
00908                                                 pb_graph_node->placement_index/10 + 
00909                                                 i / 10 + j /10 + pb_graph_node->input_pins[i][j].pin_count_in_cluster/10 + 
00910                                                 26;
00911                                         nets[*curr_net].name = my_calloc(size, sizeof(char));
00912                                         sprintf(nets[*curr_net].name, "%s[%d].input[%d][%d].pin[%d]", pb_graph_node->pb_type->name,
00913                                                 pb_graph_node->placement_index, i, j, pb_graph_node->input_pins[i][j].pin_count_in_cluster);
00914                                         (*curr_net)++;
00915                                 }
00916                         }
00917                 }
00918                 for(i = 0; i < pb_graph_node->num_clock_ports; i++) {
00919                         for(j = 0; j < pb_graph_node->num_clock_pins[i]; j++) {
00920                                 if(rr_graph[pb_graph_node->clock_pins[i][j].pin_count_in_cluster].net_num != OPEN) {
00921                                         load_internal_cb_rr_graph_net_nums(&rr_graph[pb_graph_node->clock_pins[i][j].pin_count_in_cluster], rr_graph, nets, curr_net, &temp);
00922                                         assert(temp == nets[*curr_net].num_sinks);
00923                                         temp = 0;
00924                                         nets[*curr_net].is_global = TRUE;
00925                                         size = strlen(pb_graph_node->pb_type->name) + 
00926                                                 pb_graph_node->placement_index/10 + 
00927                                                 i / 10 + j /10 + pb_graph_node->clock_pins[i][j].pin_count_in_cluster/10 + 
00928                                                 26;
00929                                         nets[*curr_net].name = my_calloc(size, sizeof(char));
00930                                         sprintf(nets[*curr_net].name, "%s[%d].clock[%d][%d].pin[%d]", pb_graph_node->pb_type->name,
00931                                                 pb_graph_node->placement_index, i, j, pb_graph_node->clock_pins[i][j].pin_count_in_cluster);
00932                                         (*curr_net)++;
00933                                 }
00934                         }
00935                 }
00936         }
00937 
00938         if(pb_type->blif_model != NULL) {
00939                 /* This is a terminal node so it might drive nets, find and map the rr_graph path for those nets */
00940                 for(i = 0; i < pb_graph_node->num_output_ports; i++) {
00941                         for(j = 0; j < pb_graph_node->num_output_pins[i]; j++) {
00942                                 if(rr_graph[pb_graph_node->output_pins[i][j].pin_count_in_cluster].net_num != OPEN) {
00943                                         load_internal_cb_rr_graph_net_nums(&rr_graph[pb_graph_node->output_pins[i][j].pin_count_in_cluster], rr_graph, nets, curr_net, &temp);
00944                                         assert(temp == nets[*curr_net].num_sinks);
00945                                         temp = 0;
00946                                         size = strlen(pb_graph_node->pb_type->name) + 
00947                                                 pb_graph_node->placement_index/10 + 
00948                                                 i / 10 + j /10 + pb_graph_node->output_pins[i][j].pin_count_in_cluster/10 + 
00949                                                 26;
00950                                         nets[*curr_net].name = my_calloc(size, sizeof(char));
00951                                         sprintf(nets[*curr_net].name, "%s[%d].output[%d][%d].pin[%d]", pb_graph_node->pb_type->name,
00952                                                 pb_graph_node->placement_index, i, j, pb_graph_node->output_pins[i][j].pin_count_in_cluster);
00953                                         (*curr_net)++;
00954                                 }
00955                         }
00956                 }
00957         } else {
00958                 /* Recurse down to primitives */
00959                 for(i = 0; i < pb_type->num_modes; i++) {
00960                         for(j = 0; j < pb_type->modes[i].num_pb_type_children; j++) {
00961                                 for(k = 0; k < pb_type->modes[i].pb_type_children[j].num_pb; k++) {
00962                                         load_internal_cb_nets(top_level, &pb_graph_node->child_pb_graph_nodes[i][j][k], rr_graph, curr_net);
00963                                 }
00964                         }
00965                 }
00966         }
00967 
00968         if(pb_graph_node->parent_pb_graph_node == NULL) { /* at top level */
00969                 assert(*curr_net == top_level->num_local_nets);
00970         }
00971 }
00972 
00973 /** allocate space to store nets internal to cb.
00974  *  two pass algorithm, pass 1 count and allocate # nets, pass 2 determine # sinks
00975  */
00976 static void alloc_internal_cb_nets(INOUTP t_pb *top_level, INP t_pb_graph_node *pb_graph_node, INOUTP t_rr_node *rr_graph, INP int pass) {
00977         int i, j, k;
00978         const t_pb_type *pb_type;
00979         int num_sinks;
00980         
00981         pb_type = pb_graph_node->pb_type;
00982 
00983         if(pb_graph_node->parent_pb_graph_node == NULL) { /* determine nets driven from inputs at top level */
00984                 top_level->num_local_nets = 0;
00985                 if(pass == 1)
00986                         top_level->local_nets = NULL;
00987                 for(i = 0; i < pb_graph_node->num_input_ports; i++) {
00988                         for(j = 0; j < pb_graph_node->num_input_pins[i]; j++) {
00989                                 if(rr_graph[pb_graph_node->input_pins[i][j].pin_count_in_cluster].net_num != OPEN) {
00990                                         if(pass == 2) {
00991                                                 num_sinks = count_sinks_internal_cb_rr_graph_net_nums(&rr_graph[pb_graph_node->input_pins[i][j].pin_count_in_cluster], rr_graph);
00992                                                 top_level->local_nets[top_level->num_local_nets].num_sinks = num_sinks;
00993                                                 top_level->local_nets[top_level->num_local_nets].node_block = my_calloc(num_sinks, sizeof(int));
00994                                                 top_level->local_nets[top_level->num_local_nets].node_block_port = my_calloc(num_sinks, sizeof(int));
00995                                                 top_level->local_nets[top_level->num_local_nets].node_block_pin = my_calloc(num_sinks, sizeof(int));
00996                                         }
00997                                         top_level->num_local_nets++;
00998                                 }
00999                         }
01000                 }
01001                 for(i = 0; i < pb_graph_node->num_clock_ports; i++) {
01002                         for(j = 0; j < pb_graph_node->num_clock_pins[i]; j++) {
01003                                 if(rr_graph[pb_graph_node->clock_pins[i][j].pin_count_in_cluster].net_num != OPEN) {
01004                                         if(pass == 2) {
01005                                                 num_sinks = count_sinks_internal_cb_rr_graph_net_nums(&rr_graph[pb_graph_node->clock_pins[i][j].pin_count_in_cluster], rr_graph);
01006                                                 top_level->local_nets[top_level->num_local_nets].num_sinks = num_sinks;
01007                                                 top_level->local_nets[top_level->num_local_nets].node_block = my_calloc(num_sinks, sizeof(int));
01008                                                 top_level->local_nets[top_level->num_local_nets].node_block_port = my_calloc(num_sinks, sizeof(int));
01009                                                 top_level->local_nets[top_level->num_local_nets].node_block_pin = my_calloc(num_sinks, sizeof(int));
01010                                         }
01011                                         top_level->num_local_nets++;
01012                                 }
01013                         }
01014                 }
01015         }
01016 
01017         if(pb_type->blif_model != NULL) {
01018                 /* This is a terminal node so it might drive nets, find and map the rr_graph path for those nets */
01019                 for(i = 0; i < pb_graph_node->num_output_ports; i++) {
01020                         for(j = 0; j < pb_graph_node->num_output_pins[i]; j++) {
01021                                 if(rr_graph[pb_graph_node->output_pins[i][j].pin_count_in_cluster].net_num != OPEN) {
01022                                         if(pass == 2) {
01023                                                 num_sinks = count_sinks_internal_cb_rr_graph_net_nums(&rr_graph[pb_graph_node->output_pins[i][j].pin_count_in_cluster], rr_graph);
01024                                                 top_level->local_nets[top_level->num_local_nets].num_sinks = num_sinks;
01025                                                 top_level->local_nets[top_level->num_local_nets].node_block = my_calloc(num_sinks, sizeof(int));
01026                                                 top_level->local_nets[top_level->num_local_nets].node_block_port = my_calloc(num_sinks, sizeof(int));
01027                                                 top_level->local_nets[top_level->num_local_nets].node_block_pin = my_calloc(num_sinks, sizeof(int));
01028                                         }
01029                                         top_level->num_local_nets++;
01030                                 }
01031                         }
01032                 }
01033         } else {
01034                 /* Recurse down to primitives */
01035                 for(i = 0; i < pb_type->num_modes; i++) {
01036                         for(j = 0; j < pb_type->modes[i].num_pb_type_children; j++) {
01037                                 for(k = 0; k < pb_type->modes[i].pb_type_children[j].num_pb; k++) {
01038                                         alloc_internal_cb_nets(top_level, &pb_graph_node->child_pb_graph_nodes[i][j][k], rr_graph, pass);
01039                                 }
01040                         }
01041                 }
01042         }
01043 
01044         if(pb_graph_node->parent_pb_graph_node == NULL) { /* at top level */
01045                 if(pass == 1) {
01046                         top_level->local_nets = my_calloc(top_level->num_local_nets, sizeof(struct s_net));
01047                 }
01048         }
01049 }
01050 
01051 static void mark_constant_generators(INP int num_blocks,
01052                                                                         INP struct s_block block_list[],
01053                                                                         INP int ncount,
01054                                                                         INOUTP struct s_net nlist[]) {                                                          
01055         int i;
01056         for(i = 0; i < num_blocks; i++) {
01057                 mark_constant_generators_rec(block_list[i].pb, block_list[i].pb->rr_graph, nlist);
01058         }
01059 }
01060 
01061 
01062 static void mark_constant_generators_rec(INP t_pb *pb,
01063                                                                                  INP t_rr_node *rr_graph,
01064                                                                                  INOUTP struct s_net nlist[]) {
01065         int i, j;
01066         t_pb_type *pb_type;
01067         boolean const_gen;
01068         if(pb->pb_graph_node->pb_type->blif_model == NULL) {
01069                 for(i = 0; i < pb->pb_graph_node->pb_type->modes[pb->mode].num_pb_type_children; i++) {
01070                         pb_type = &(pb->pb_graph_node->pb_type->modes[pb->mode].pb_type_children[i]);
01071                         for(j = 0; j < pb_type->num_pb; j++) {
01072                                 if(pb->child_pbs[i][j].name != NULL) {
01073                                         mark_constant_generators_rec(&(pb->child_pbs[i][j]), rr_graph, nlist);
01074                                 }
01075                         }
01076                 }
01077         } else if( strcmp(pb->pb_graph_node->pb_type->name, "inpad") != 0) {
01078                 const_gen = TRUE;
01079                 for(i = 0; i < pb->pb_graph_node->num_input_ports && const_gen == TRUE; i++) {
01080                         for(j = 0; j < pb->pb_graph_node->num_input_pins[i] && const_gen == TRUE; j++) {
01081                                 if(rr_graph[pb->pb_graph_node->input_pins[i][j].pin_count_in_cluster].net_num != OPEN) {
01082                                         const_gen = FALSE;
01083                                 }
01084                         }
01085                 }
01086                 for(i = 0; i < pb->pb_graph_node->num_clock_ports && const_gen == TRUE; i++) {
01087                         for(j = 0; j < pb->pb_graph_node->num_clock_pins[i] && const_gen == TRUE; j++) {
01088                                 if(rr_graph[pb->pb_graph_node->clock_pins[i][j].pin_count_in_cluster].net_num != OPEN) {
01089                                         const_gen = FALSE;
01090                                 }
01091                         }
01092                 }
01093                 if(const_gen == TRUE) {
01094                         printf("%s is a constant generator \n", pb->name);
01095                         for(i = 0; i < pb->pb_graph_node->num_output_ports; i++) {
01096                                 for(j = 0; j < pb->pb_graph_node->num_output_pins[i]; j++) {
01097                                         if(rr_graph[pb->pb_graph_node->output_pins[i][j].pin_count_in_cluster].net_num != OPEN) {
01098                                                 nlist[rr_graph[pb->pb_graph_node->output_pins[i][j].pin_count_in_cluster].net_num].is_const_gen = TRUE;
01099                                         }
01100                                 }
01101                         }
01102                 }
01103         }
01104 }
01105 
01106 /** create logical block properties from saved block */
01107 static void restore_logical_block_from_saved_block(INP int iblk, INP t_pb *pb) {
01108         int i;
01109         for(i = 0; i < num_saved_logical_blocks; i++) {
01110                 if(pb->pb_graph_node->pb_type->model == saved_logical_blocks[i].model) {
01111                         if(saved_logical_blocks[i].name != NULL && strcmp(pb->name, saved_logical_blocks[i].name) == 0) {
01112                                 break;
01113                         }
01114                 }
01115         }
01116         assert(i != num_saved_logical_blocks);
01117         logical_block[iblk].name = saved_logical_blocks[i].name;
01118         logical_block[iblk].clb_index = UNDEFINED;
01119         logical_block[iblk].clock_net = saved_logical_blocks[i].clock_net;
01120         logical_block[iblk].clock_net_tnode = NULL;
01121         logical_block[iblk].index = iblk;
01122         logical_block[iblk].input_net_tnodes = saved_logical_blocks[i].input_net_tnodes;
01123         logical_block[iblk].input_nets = saved_logical_blocks[i].input_nets;
01124         logical_block[iblk].model = saved_logical_blocks[i].model;
01125         logical_block[iblk].output_net_tnodes = saved_logical_blocks[i].output_net_tnodes;
01126         logical_block[iblk].output_nets = saved_logical_blocks[i].output_nets;
01127         logical_block[iblk].pb = pb;
01128         logical_block[iblk].truth_table = saved_logical_blocks[i].truth_table;
01129         logical_block[iblk].type = saved_logical_blocks[i].type;
01130         logical_block[iblk].used_input_pins = saved_logical_blocks[i].used_input_pins;
01131 
01132         saved_logical_blocks[i].name = NULL;
01133         saved_logical_blocks[i].input_net_tnodes = NULL;
01134         saved_logical_blocks[i].input_nets = NULL;
01135         saved_logical_blocks[i].output_net_tnodes = NULL;
01136         saved_logical_blocks[i].output_nets = NULL;
01137         saved_logical_blocks[i].truth_table = NULL;
01138 }
01139 
01140 
01141 /** Free logical blocks of netlist */
01142 void free_logical_blocks() {
01143         int iblk, i;
01144         t_model_ports *port;
01145         struct s_linked_vptr *tvptr, *next;
01146 
01147         for (iblk=0;iblk<num_logical_blocks;iblk++) {
01148                 port = logical_block[iblk].model->inputs;
01149                 i = 0;
01150                 while(port) {
01151                         if(!port->is_clock) {
01152                                 free(logical_block[iblk].input_nets[i]);
01153                                 if(logical_block[iblk].input_net_tnodes) {
01154                                         if(logical_block[iblk].input_net_tnodes[i])
01155                                                 free(logical_block[iblk].input_net_tnodes[i]);
01156                                 }
01157                                 i++;
01158                         }
01159                         port = port->next;
01160                 }
01161                 if(logical_block[iblk].input_net_tnodes) {
01162                         free(logical_block[iblk].input_net_tnodes);
01163                 }
01164                 free(logical_block[iblk].input_nets);
01165                 port = logical_block[iblk].model->outputs;
01166                 i = 0;
01167                 while(port) {
01168                         free(logical_block[iblk].output_nets[i]);
01169                         if(logical_block[iblk].output_net_tnodes) {
01170                                 if(logical_block[iblk].output_net_tnodes[i])
01171                                         free(logical_block[iblk].output_net_tnodes[i]);
01172                         }
01173                         i++;
01174                         port = port->next;
01175                 }
01176                 if(logical_block[iblk].output_net_tnodes) {
01177                         free(logical_block[iblk].output_net_tnodes);
01178                 }
01179                 free(logical_block[iblk].output_nets);
01180                 free(logical_block[iblk].name);
01181                 tvptr = logical_block[iblk].truth_table;
01182                 while(tvptr != NULL) {
01183                         if(tvptr->data_vptr)
01184                                 free(tvptr->data_vptr);
01185                         next = tvptr->next;
01186                         free(tvptr);
01187                         tvptr = next;
01188                 }
01189         }
01190         free(logical_block);
01191 }
01192 
01193 /** Free logical blocks of netlist */
01194 void free_logical_nets() {
01195         int inet;
01196         
01197         for (inet=0;inet<num_logical_nets;inet++) {
01198                 free(vpack_net[inet].name);
01199                 free(vpack_net[inet].node_block);
01200                 free(vpack_net[inet].node_block_port);
01201                 free(vpack_net[inet].node_block_pin);
01202         }
01203         free(vpack_net);
01204 }
01205