00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include <assert.h>
00029 #include "util.h"
00030 #include "globals.h"
00031 #include "netlist_utils.h"
00032 #include "errors.h"
00033 #include "read_xml_arch_file.h"
00034 #include "read_netlist.h"
00035 #include "ReadLine.h"
00036 #include "string_cache.h"
00037
00038 #ifdef VPR5
00039 enum special_blk { NORMAL = 0, INPAD, OUTPAD };
00040 enum pass { DRIVERS = 0, DRIVEN, STOP };
00041
00042 static FILE *net_file;
00043 int linenum;
00044
00045 char *netlist_one_string = "ONE_VCC_CNS";
00046 char *netlist_zero_string = "ZERO_GND_ZERO";
00047
00048 nnode_t * add_block (char *node_name, char **pin_tokens, t_type_ptr type, short pass, netlist_t *netlist);
00049 static void add_io_node_and_driver ( short io_type, netlist_t *netlist, char *io_pin_name);
00050 void add_subblock_to_node(nnode_t *current_block, char ***token_list, int num_subblocks, t_type_ptr type);
00051
00052 void FreeTokens ( char ***TokensPtr);
00053 int CountTokens ( char **Tokens);
00054 char ** ReadLineTokens ( FILE * InFile, int *LineNum);
00055
00056 static t_type_ptr get_type_by_name (
00057 const char *name,
00058 int ntypes,
00059 const struct s_type_descriptor block_types[],
00060 t_type_ptr IO_type,
00061 const char *net_filename,
00062 int line,
00063 enum special_blk *overide);
00064
00065
00066
00067
00068 netlist_t *
00069 read_netlist (
00070 const char *net_filename,
00071 int ntypes,
00072 const struct s_type_descriptor block_types[],
00073 t_type_ptr IO_type)
00074 {
00075 int i;
00076 int num_blocks, subblock_count;
00077 int prev_line;
00078 enum special_blk overide;
00079 char **block_tokens;
00080 char **pin_tokens;
00081 char **tokens;
00082 t_type_ptr type = NULL;
00083 netlist_t *netlist = allocate_netlist();
00084 npin_t *new_pin;
00085 enum pass pass;
00086
00087
00088
00089 netlist->zero_net = allocate_nnet();
00090 netlist->gnd_node = allocate_nnode();
00091 netlist->gnd_node->type = GND_NODE;
00092 allocate_more_node_output_pins(netlist->gnd_node, 1);
00093 add_output_port_information(netlist->gnd_node, 1);
00094 new_pin = allocate_npin();
00095 add_a_output_pin_to_node_spot_idx(netlist->gnd_node, new_pin, 0);
00096 add_a_driver_pin_to_net(netlist->zero_net, new_pin);
00097 netlist->gnd_node->name = netlist_zero_string;
00098 netlist->zero_net->name = netlist_zero_string;
00099
00100 netlist->one_net = allocate_nnet();
00101 netlist->vcc_node = allocate_nnode();
00102 netlist->vcc_node->type = VCC_NODE;
00103 allocate_more_node_output_pins(netlist->vcc_node, 1);
00104 add_output_port_information(netlist->vcc_node, 1);
00105 new_pin = allocate_npin();
00106 add_a_output_pin_to_node_spot_idx(netlist->vcc_node, new_pin, 0);
00107 add_a_driver_pin_to_net(netlist->one_net, new_pin);
00108 netlist->vcc_node->name = netlist_one_string;
00109 netlist->one_net->name = netlist_one_string;
00110
00111
00112 net_file = fopen (net_filename, "r");
00113
00114 for (pass = 0; pass < STOP; ++pass)
00115 {
00116 rewind (net_file);
00117 linenum = 0;
00118 num_blocks = 0;
00119 overide = NORMAL;
00120
00121
00122 block_tokens = ReadLineTokens (net_file, &linenum);
00123 prev_line = linenum;
00124 while (block_tokens)
00125 {
00126
00127 if (0 == strcmp (block_tokens[0], ".global"))
00128 {
00129 if (pass == DRIVEN)
00130 {
00131
00132 mark_clock_node (netlist, block_tokens[1]);
00133 }
00134
00135
00136 FreeTokens (&block_tokens);
00137 block_tokens = ReadLineTokens (net_file, &linenum);
00138 prev_line = linenum;
00139 continue;
00140 }
00141
00142
00143 pin_tokens = ReadLineTokens (net_file, &linenum);
00144
00145 if (CountTokens (block_tokens) != 2)
00146 {
00147 error_message(NETLIST_FILE_ERROR, prev_line, -1, "'%s':%d - block type linenum should " "be in form '.type_name block_name'\n", net_filename, prev_line);
00148 }
00149 if (NULL == pin_tokens)
00150 {
00151 error_message(NETLIST_FILE_ERROR, prev_line, -1, "'%s':%d - blocks must be follow by a 'pinlist:' linenum\n", net_filename, linenum);
00152 }
00153 if (0 != strcmp ("pinlist:", pin_tokens[0]))
00154 {
00155 error_message(NETLIST_FILE_ERROR, prev_line, -1, "'%s':%d - 'pinlist:' linenum must follow " "block type linenum\n", net_filename, linenum);
00156 }
00157
00158 type = get_type_by_name (block_tokens[0], ntypes, block_types, IO_type, net_filename, prev_line, &overide);
00159
00160
00161 if (overide)
00162 {
00163 if (CountTokens (pin_tokens) != 2)
00164 {
00165 error_message(NETLIST_FILE_ERROR, prev_line, -1,"'%s':%d - pinlist for .input and .output should " "only have one item.\n", net_filename, linenum);
00166 }
00167 if (pass == DRIVERS)
00168 {
00169 switch (overide)
00170 {
00171 case INPAD:
00172 add_io_node_and_driver (INPUT_NODE, netlist, block_tokens[1]);
00173 break;
00174 case OUTPAD:
00175 add_io_node_and_driver (OUTPUT_NODE, netlist, block_tokens[1]);
00176 break;
00177 default:
00178 break;
00179 }
00180 }
00181
00182
00183 tokens = ReadLineTokens (net_file, &linenum);
00184 }
00185 else
00186 {
00187 nnode_t *current_block;
00188 char ***tokens_list = NULL;
00189
00190 if (CountTokens (pin_tokens) != (type->num_pins + 1))
00191 {
00192 error_message(NETLIST_FILE_ERROR, prev_line, -1, "'%s':%d - 'pinlist:' linenum has %d pins instead of " "expect %d pins.\n", net_filename, linenum, CountTokens (pin_tokens) - 1, type->num_pins);
00193 }
00194
00195
00196 current_block = add_block (block_tokens[1], pin_tokens, type, pass, netlist);
00197
00198
00199 tokens = ReadLineTokens (net_file, &linenum);
00200 prev_line = linenum;
00201 subblock_count = 0;
00202 while (tokens && (0 == strcmp (tokens[0], "subblock:")))
00203 {
00204
00205 if (DRIVEN == pass)
00206 {
00207 tokens_list = (char ***)realloc(tokens_list, sizeof(char**)*(subblock_count+1));
00208 tokens_list[subblock_count] = tokens;
00209 }
00210
00211 ++subblock_count;
00212
00213 tokens = ReadLineTokens (net_file, &linenum);
00214 prev_line = linenum;
00215 }
00216
00217
00218 if (DRIVEN == pass)
00219 {
00220 add_subblock_to_node(current_block, tokens_list, subblock_count, type);
00221
00222
00223 for (i = 0; i < subblock_count; i++)
00224 {
00225 FreeTokens (&tokens_list[i]);
00226 }
00227 if (tokens_list != NULL)
00228 {
00229 free(tokens_list);
00230 }
00231 }
00232 }
00233
00234 num_blocks++;
00235
00236 FreeTokens (&block_tokens);
00237 FreeTokens (&pin_tokens);
00238
00239
00240 block_tokens = tokens;
00241 }
00242 }
00243
00244 fclose (net_file);
00245
00246 return netlist;
00247 }
00248
00249
00250
00251
00252 static void
00253 add_io_node_and_driver (
00254 short io_type,
00255 netlist_t *netlist,
00256 char *io_pin_name
00257 )
00258 {
00259 long sc_spot;
00260 nnode_t *new_node;
00261 npin_t *node_output_pin;
00262 nnet_t *new_net;
00263
00264
00265 new_node = allocate_nnode();
00266
00267 new_node->related_ast_node = NULL;
00268 new_node->type = io_type;
00269
00270
00271 new_node->name = make_full_ref_name(NULL, NULL, NULL, io_pin_name, -1);
00272
00273
00274 add_node_to_netlist(netlist, new_node, -1);
00275
00276 if (io_type == INPUT_NODE)
00277 {
00278
00279 allocate_more_node_output_pins(new_node, 1);
00280 add_output_port_information(new_node, 1);
00281
00282
00283 node_output_pin = allocate_npin();
00284 add_a_output_pin_to_node_spot_idx(new_node, node_output_pin, 0);
00285
00286
00287 new_net = allocate_nnet();
00288 new_net->name = new_node->name;
00289 add_a_driver_pin_to_net(new_net, node_output_pin);
00290
00291
00292 sc_spot = sc_add_string(netlist->nets_sc, new_node->name);
00293 if (netlist->nets_sc->data[sc_spot] != NULL)
00294 {
00295 error_message(NETLIST_ERROR, linenum, -1, "Two netlist outputs with the same name (%s)\n", new_node->name);
00296 }
00297 netlist->nets_sc->data[sc_spot] = (void*)new_net;
00298 }
00299 else if (io_type == OUTPUT_NODE)
00300 {
00301
00302 allocate_more_node_input_pins(new_node, 1);
00303 add_input_port_information(new_node, 1);
00304
00305
00306 sc_spot = sc_add_string(netlist->out_pins_sc, io_pin_name);
00307 if (netlist->out_pins_sc->data[sc_spot] != NULL)
00308 {
00309 error_message(NETLIST_ERROR, linenum, -1, "Two outputs pins with the same name (%s)\n", io_pin_name);
00310 }
00311 netlist->out_pins_sc->data[sc_spot] = (void*)new_node;
00312 }
00313 }
00314
00315
00316
00317
00318 nnode_t *
00319 add_block (char *node_name, char **pin_tokens, t_type_ptr type, short pass, netlist_t *netlist)
00320 {
00321 long sc_spot;
00322 nnode_t *new_node;
00323 npin_t *node_output_pin;
00324 nnet_t *new_net;
00325 int num_input_pins = 0;
00326 int num_output_pins = 0;
00327 npin_t *node_input_pin = NULL;
00328 nnet_t *driver_net;
00329 int k;
00330
00331
00332 if ((sc_spot = sc_lookup_string(netlist->nodes_sc, node_name)) == -1)
00333 {
00334 new_node = allocate_nnode();
00335
00336 new_node->related_ast_node = NULL;
00337 new_node->type = NETLIST_FUNCTION;
00338
00339
00340 new_node->name = make_full_ref_name(NULL, NULL, NULL, node_name, -1);
00341
00342
00343 add_node_to_netlist(netlist, new_node, -1);
00344 }
00345 else
00346 {
00347
00348 new_node = ((nnode_t*)netlist->nodes_sc->data[sc_spot]);
00349 }
00350
00351
00352 for (k = 1; k < type->num_pins+1; ++k)
00353 {
00354 if (DRIVER == type->class_inf[type->pin_class[k-1]].type)
00355 {
00356 if (pass == DRIVERS)
00357 {
00358 oassert(k >= type->num_receivers+1);
00359 oassert(k-1-type->num_receivers == num_output_pins);
00360
00361 allocate_more_node_output_pins(new_node, 1);
00362 add_output_port_information(new_node, 1);
00363
00364 if (0 != strcmp ("open", pin_tokens[k]))
00365 {
00366
00367 node_output_pin = allocate_npin();
00368 add_a_output_pin_to_node_spot_idx(new_node, node_output_pin, num_output_pins);
00369
00370
00371 new_net = allocate_nnet();
00372 new_net->name = strdup(pin_tokens[k]);
00373 add_a_driver_pin_to_net(new_net, node_output_pin);
00374
00375
00376 if ((sc_spot = sc_lookup_string(netlist->out_pins_sc, pin_tokens[k])) != -1)
00377 {
00378
00379 nnode_t *output_node = (nnode_t*)netlist->out_pins_sc->data[sc_spot];
00380 npin_t *node_input_pin;
00381
00382
00383 node_input_pin = allocate_npin();
00384
00385 add_a_fanout_pin_to_net(new_net, node_input_pin);
00386
00387 add_a_input_pin_to_node_spot_idx(output_node, node_input_pin, 0);
00388
00389
00390 sc_spot = sc_add_string(netlist->nets_sc, pin_tokens[k]);
00391 if (netlist->nets_sc->data[sc_spot] != NULL)
00392 {
00393 error_message(NETLIST_ERROR, linenum, -1, "Two netlist outputs with the same name (%s)\n", pin_tokens[k]);
00394 }
00395 netlist->nets_sc->data[sc_spot] = (void*)new_net;
00396 }
00397 else
00398 {
00399
00400 sc_spot = sc_add_string(netlist->nets_sc, pin_tokens[k]);
00401 if (netlist->nets_sc->data[sc_spot] != NULL)
00402 {
00403 error_message(NETLIST_ERROR, linenum, -1, "Two netlist outputs with the same name (%s)\n", pin_tokens[k]);
00404 }
00405 netlist->nets_sc->data[sc_spot] = (void*)new_net;
00406 }
00407 }
00408
00409 num_output_pins ++;
00410 }
00411 }
00412 else
00413 {
00414 if (pass == DRIVEN)
00415 {
00416
00417 allocate_more_node_input_pins(new_node, 1);
00418 add_input_port_information(new_node, 1);
00419
00420 if (0 != strcmp ("open", pin_tokens[k]))
00421 {
00422
00423 if ((sc_spot = sc_lookup_string(netlist->nets_sc, pin_tokens[k])) == -1)
00424 {
00425 error_message(NETLIST_ERROR, linenum, -1, "Netlist input does not exist (%s)\n", pin_tokens[k]);
00426 }
00427 driver_net = (nnet_t*)netlist->nets_sc->data[sc_spot];
00428
00429 node_input_pin = allocate_npin();
00430 node_input_pin->name = strdup(pin_tokens[k]);
00431
00432 add_a_fanout_pin_to_net(driver_net, node_input_pin);
00433
00434 add_a_input_pin_to_node_spot_idx(new_node, node_input_pin, num_input_pins);
00435 }
00436
00437 num_input_pins ++;
00438 }
00439 }
00440 }
00441
00442 return new_node;
00443 }
00444
00445
00446
00447
00448 void
00449 add_subblock_to_node(nnode_t *current_block, char ***tokens_list, int num_subblocks, t_type_ptr type)
00450 {
00451 int i, j, k;
00452 nnode_t **subblock_nodes = (nnode_t**)malloc(sizeof(nnode_t*)*num_subblocks);
00453 npin_t *node_output_pin;
00454 nnet_t *new_net;
00455 int live_index_count;
00456 int *input_idx = (int*)malloc(sizeof(int)*current_block->num_input_pins);
00457 int *output_idx = (int*)malloc(sizeof(int)*current_block->num_output_pins);
00458
00459
00460 current_block->internal_netlist = allocate_netlist();
00461 current_block->internal_netlist->type = type;
00462
00463
00464 live_index_count = 0;
00465 for (i = 0; i < current_block->num_input_pins; i++)
00466 {
00467 if (current_block->input_pins[i] != NULL)
00468 {
00469 nnode_t *new_input_node;
00470
00471
00472 new_input_node = allocate_nnode();
00473
00474 new_input_node->related_ast_node = NULL;
00475 new_input_node->type = INPUT_NODE;
00476
00477 new_input_node->name = make_full_ref_name(NULL, NULL, NULL, current_block->input_pins[i]->net->name, -1);
00478
00479
00480 add_node_to_netlist(current_block->internal_netlist, new_input_node, -1);
00481
00482
00483 allocate_more_node_output_pins(new_input_node, 1);
00484 add_output_port_information(new_input_node, 1);
00485
00486
00487 node_output_pin = allocate_npin();
00488 add_a_output_pin_to_node_spot_idx(new_input_node, node_output_pin, 0);
00489
00490
00491 new_net = allocate_nnet();
00492 new_net->name = new_input_node->name;
00493 add_a_driver_pin_to_net(new_net, node_output_pin);
00494
00495
00496 input_idx[i] = live_index_count;
00497 live_index_count++;
00498 }
00499 else
00500 {
00501 input_idx[i] = -1;
00502 }
00503 }
00504 live_index_count = 0;
00505 for (i = 0; i < current_block->num_output_pins; i++)
00506 {
00507 if (current_block->output_pins[i] != NULL)
00508 {
00509 nnode_t *new_output_node;
00510 char *output_name = (char*)malloc(sizeof(char)*(strlen(current_block->output_pins[i]->net->name)+1+4));
00511 sprintf(output_name, "out:%s", current_block->output_pins[i]->net->name);
00512
00513
00514 new_output_node = allocate_nnode();
00515
00516 new_output_node->related_ast_node = NULL;
00517 new_output_node->type = OUTPUT_NODE;
00518
00519 new_output_node->name = make_full_ref_name(NULL, NULL, NULL, output_name, -1);
00520
00521
00522 add_node_to_netlist(current_block->internal_netlist, new_output_node, -1);
00523
00524
00525 allocate_more_node_input_pins(new_output_node, 1);
00526 add_input_port_information(new_output_node, 1);
00527
00528
00529 output_idx[i] = live_index_count;
00530 live_index_count++;
00531 }
00532 else
00533 {
00534 output_idx[i] = -1;
00535 }
00536 }
00537
00538
00539 for (i = 0; i < num_subblocks; i++)
00540 {
00541 subblock_nodes[i] = allocate_nnode();
00542
00543 subblock_nodes[i]->name = strdup(tokens_list[i][1]);
00544
00545 allocate_more_node_input_pins(subblock_nodes[i], type->max_subblock_inputs + 1);
00546 allocate_more_node_output_pins(subblock_nodes[i], type->max_subblock_outputs);
00547
00548
00549 for (j = 0; j < type->max_subblock_outputs; j++)
00550 {
00551
00552 node_output_pin = allocate_npin();
00553 add_a_output_pin_to_node_spot_idx(subblock_nodes[i], node_output_pin, j);
00554
00555
00556 new_net = allocate_nnet();
00557 add_a_driver_pin_to_net(new_net, node_output_pin);
00558 }
00559
00560
00561 add_node_to_netlist(current_block->internal_netlist, subblock_nodes[i], -1);
00562 }
00563
00564 for (i = 0; i < num_subblocks; i++)
00565 {
00566 int idx;
00567
00568 for (k = 0; k < type->max_subblock_inputs; ++k)
00569 {
00570
00571 idx = 2 + k;
00572 if (0 == strncmp ("ble_", tokens_list[i][idx], 4))
00573 {
00574
00575 int ble_idx = atoi(tokens_list[i][idx] + 4);
00576 npin_t *node_input_pin = allocate_npin();
00577
00578 oassert(subblock_nodes[ble_idx]->num_output_pins == 1);
00579
00580
00581 add_a_fanout_pin_to_net(subblock_nodes[ble_idx]->output_pins[0]->net, node_input_pin);
00582
00583 add_a_input_pin_to_node_spot_idx(subblock_nodes[i], node_input_pin, k);
00584 }
00585 else if (0 != strcmp ("open", tokens_list[i][idx]))
00586 {
00587
00588 int in_idx = input_idx[atoi(tokens_list[i][idx])];
00589 oassert(in_idx < type->num_receivers);
00590 oassert(in_idx != -1);
00591
00592 npin_t *node_input_pin = allocate_npin();
00593
00594
00595 add_a_fanout_pin_to_net(current_block->internal_netlist->top_input_nodes[in_idx]->output_pins[0]->net, node_input_pin);
00596
00597 add_a_input_pin_to_node_spot_idx(subblock_nodes[i], node_input_pin, k);
00598 }
00599 }
00600 for (k = 0; k < type->max_subblock_outputs; ++k)
00601 {
00602 idx = 2 + type->max_subblock_inputs + k;
00603 if (0 != strcmp ("open", tokens_list[i][idx]))
00604 {
00605
00606 int pin_idx = atoi(tokens_list[i][idx]) - type->num_receivers;
00607 int out_idx = output_idx[pin_idx];
00608 nnode_t *output_node;
00609 npin_t *node_input_pin;
00610 oassert(out_idx < type->num_drivers);
00611
00612 if (current_block->output_pins[pin_idx] == NULL)
00613 {
00614
00615 continue;
00616 }
00617
00618 oassert(out_idx != -1);
00619
00620 output_node = current_block->internal_netlist->top_output_nodes[out_idx];
00621
00622
00623 node_input_pin = allocate_npin();
00624
00625 add_a_fanout_pin_to_net(subblock_nodes[i]->output_pins[k]->net, node_input_pin);
00626
00627 add_a_input_pin_to_node_spot_idx(output_node, node_input_pin, k);
00628 }
00629 }
00630 idx = 2 + type->max_subblock_inputs + type->max_subblock_outputs;
00631 if (0 != strcmp ("open", tokens_list[i][idx]))
00632 {
00633 int clock_idx = input_idx[atoi (tokens_list[i][idx]) - (type->num_receivers + type->num_drivers)];
00634 npin_t *node_input_pin = allocate_npin();
00635 oassert(clock_idx != -1);
00636
00637
00638 add_a_fanout_pin_to_net(current_block->internal_netlist->top_input_nodes[clock_idx]->output_pins[0]->net, node_input_pin);
00639
00640 add_a_input_pin_to_node_spot_idx(subblock_nodes[i], node_input_pin, type->max_subblock_inputs);
00641 }
00642 }
00643
00644
00645 free(output_idx);
00646 free(input_idx);
00647 }
00648
00649
00650
00651
00652
00653 static t_type_ptr
00654 get_type_by_name (
00655 const char *name,
00656 int ntypes,
00657 const struct s_type_descriptor block_types[],
00658 t_type_ptr IO_type,
00659 const char *net_filename,
00660 int line,
00661 enum special_blk *overide)
00662 {
00663
00664
00665 int i;
00666
00667
00668
00669
00670 *overide = NORMAL;
00671
00672
00673 if (0 == strcmp (".input", name))
00674 {
00675 *overide = INPAD;
00676 return IO_type;
00677 }
00678 if (0 == strcmp (".output", name))
00679 {
00680 *overide = OUTPAD;
00681 return IO_type;
00682 }
00683
00684
00685
00686 for (i = 0; i < ntypes; ++i)
00687 {
00688 if (0 == strcmp (block_types[i].name, name))
00689 {
00690 return (block_types + i);
00691 }
00692 }
00693
00694
00695 error_message(NETLIST_FILE_ERROR, line, -1, "'%s':%d - Invalid block type '%s'\n", net_filename, line, name);
00696 exit (1);
00697 }
00698 #endif