VPR-6.0
|
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