/* Initializes the block_list with info from a netlist */ void read_netlist(IN const char* net_file, IN int num_types, IN const struct s_type_descriptor block_types[], IN block_type_ptr IO_type, IN int io_ipin, IN int io_opin, OUT subblock_data_t* subblock_data_ptr, OUT int* num_blocks, OUT block_t* block_list[], OUT int* num_nets, OUT net_t* net_list[]) { int i, j, k, l, m; enum { COUNT, LOAD, MAP, STOP } pass; int line, prev_line; enum special_blk overide; char** block_tokens; char** pin_tokens; char** tokens; subblock_t** slist = NULL; int* scount = NULL; block_type_ptr type = NULL; FILE* infile = my_fopen(net_file, "r"); int bcount = 0; block_t* blist = NULL; int ncount = 0; net_t* nlist = NULL; memset(subblock_data_ptr, 0, sizeof(subblock_data_t)); /* Multi-pass load * COUNT *->count blocks *->count nets * * LOAD *->alloc num_subblocks_per_block list *->allocate s_block list at start *->allocate s_net list at start *->count subblocks per block *->sets block names *->sets block types *->allocs block net lists *->sets net names * * MAP *->fills in s_block:nets list *->fills in subblocks */ for (pass = 0; pass < STOP; ++pass) { rewind(infile); line = 0; i = 0; j = 0; overide = NORMAL; /* Alloc the lists */ if (LOAD == pass) { blist = (block_t*)my_malloc(sizeof(block_t) * bcount); memset(blist, 0, (sizeof(block_t) * bcount)); nlist = (net_t*)my_malloc(sizeof(net_t) * ncount); memset(nlist, 0, (sizeof(net_t) * ncount)); slist = (subblock_t**) my_malloc(sizeof(subblock_t*) * bcount); memset(slist, 0, (sizeof(subblock_t*) * bcount)); scount = (int*)my_malloc(sizeof(int) * bcount); memset(scount, 0, (sizeof(int) * bcount)); } /* Read file line by line */ block_tokens = ReadLineTokens(infile, &line); prev_line = line; while (block_tokens) { /* .global directives have special meaning */ if (0 == strcmp(block_tokens[0], ".global")) { if (MAP == pass) { for (l = 0; l < ncount; ++l) { if (0 == strcmp(nlist[l].name, block_tokens[1])) { nlist[l].is_global = TRUE; break; } } if (l == ncount) { printf(ERRTAG "'%s':%d - '.global' specified an invalid net\n", net_file, prev_line); exit(1); } } /* Don't do any more processing on this */ FreeTokens(&block_tokens); block_tokens = ReadLineTokens(infile, &line); prev_line = line; continue; } pin_tokens = ReadLineTokens(infile, &line); if (CountTokens(block_tokens) != 2) { printf(ERRTAG "'%s':%d - block type line should " "be in form '.type_name block_name'\n", net_file, prev_line); exit(1); } if (NULL == pin_tokens) { printf(ERRTAG "'%s':%d - blocks must be follow by a 'pinlist:' line\n", net_file, line); exit(1); } if (0 != strcmp("pinlist:", pin_tokens[0])) { printf(ERRTAG "'%s':%d - 'pinlist:' line must follow " "block type line\n", net_file, line); exit(1); } type = get_type_by_name(block_tokens[0], num_types, block_types, IO_type, net_file, prev_line, &overide); /* Check if we are overiding the pinlist format for this block */ if (overide) { if (CountTokens(pin_tokens) != 2) { /* 'pinlist:' and name */ printf(ERRTAG "'%s':%d - pinlist for .input and .output should " "only have one item.\n", net_file, line); exit(1); } /* Make a new faked token list with 'pinlist:' and then pin mappings and a null */ tokens = (char**)my_malloc(sizeof(char*) * (type->num_type_pins + 2)); l = strlen(pinlist_str) + 1; k = strlen(pin_tokens[1]) + 1; tokens[0] = (char*)my_malloc(sizeof(char) * (k + l)); memcpy(tokens[0], pinlist_str, l * sizeof(char)); memcpy(tokens[0] + l, pin_tokens[1], k * sizeof(char)); /* Set all other pins to open */ for (k = 0; k < type->num_type_pins; ++k) { tokens[1 + k] = "open"; /* free wont be called on this so is safe */ } tokens[1 + k] = NULL; /* End of token list marker */ /* Set the one pin with the value given */ for (k = 0; k < type->num_type_pins; ++k) { switch (overide) { case INPAD: tokens[1 + io_opin] = (tokens[0] + l); break; case OUTPAD: tokens[1 + io_ipin] = (tokens[0] + l); break; } } FreeTokens(&pin_tokens); pin_tokens = tokens; tokens = NULL; } if (CountTokens(pin_tokens) != (type->num_type_pins + 1)) { printf(ERRTAG "'%s':%d - 'pinlist:' line has %d pins instead of " "expect %d pins.\n", net_file, line, CountTokens(pin_tokens) - 1, type->num_type_pins); exit(1); } /* Load block name and type and alloc net list */ if (LOAD == pass) { blist[i].name = my_strdup(block_tokens[1]); blist[i].block_type = type; blist[i].nets = (int*)my_malloc(sizeof(int) * type->num_type_pins); for (k = 0; k < type->num_type_pins; ++k) { blist[i].nets[k] = OPEN; } } /* Examine pin list to determine nets */ for (k = 0; k < type->num_type_pins; ++k) { if (0 != strcmp("open", pin_tokens[1 + k])) { if (DRIVER == type->class_inf[type->pin_class[k]].type) { if (LOAD == pass) { nlist[j].name = my_strdup(pin_tokens[1 + k]); } if (MAP == pass) { blist[i].nets[k] = j; /* If we are net source we don't need to search */ } ++j; /* This was an active netlist */ } else { if (MAP == pass) { /* Map sinks by doing a linear search to find the net */ blist[i].nets[k] = OPEN; for (l = 0; l < ncount; ++l) { if (0 == strcmp(nlist[l].name, pin_tokens[1 + k])) { blist[i].nets[k] = l; break; } } if (OPEN == blist[i].nets[k]) { printf(ERRTAG "'%s':%d - Net '%s' not found\n", net_file, line, pin_tokens [1 + k]); exit(1); } } } } } /* Allocating subblocks */ if (MAP == pass) { /* All blocks internally have subblocks but I/O subblocks are allocated and loaded elsewhere */ if (scount[i] > 0) { slist[i] = (subblock_t*) my_malloc(sizeof(subblock_t) * scount[i]); for (k = 0; k < scount[i]; ++k) { slist[i][k].name = NULL; slist[i][k].clock = OPEN; slist[i][k].inputs = (int*)my_malloc(sizeof(int) * type->max_subblock_inputs); for (l = 0; l < type->max_subblock_inputs; ++l) { slist[i][k].inputs[l] = OPEN; } slist[i][k].outputs = (int*)my_malloc(sizeof(int) * type->max_subblock_outputs); for (l = 0; l < type->max_subblock_outputs; ++l) { slist[i][k].outputs[l] = OPEN; } } } } /* Ignore subblock data */ tokens = ReadLineTokens(infile, &line); prev_line = line; m = 0; while (tokens && (0 == strcmp(tokens[0], "subblock:"))) { if (CountTokens(tokens) != (type->max_subblock_inputs + type->max_subblock_outputs + 1 + /* clocks */ 2)) { /* 'subblock:', name */ printf("subblock wrong pin count, netlist has %d, architecture as %d on line %d \n" , CountTokens(tokens) - 2, (type->max_subblock_inputs + type->max_subblock_outputs + 1), line); exit(1); } /* Count subblocks given */ if (LOAD == pass) { scount[i]++; } /* Load subblock name */ if (MAP == pass) { assert(i < bcount); assert(m < scount[i]); slist[i][m].name = my_strdup(tokens[1]); for (k = 0; k < type->max_subblock_inputs; ++k) { /* Check prefix and load pin num */ l = 2 + k; if (0 == strncmp("ble_", tokens[l], 4)) { /* Skip the 'ble_' part */ slist[i][m].inputs[k] = type->num_type_pins + my_atoi(tokens[l] + 4); } else if (0 != strcmp("open", tokens[l])) { slist[i][m].inputs[k] = my_atoi(tokens[l]); } } for (k = 0; k < type->max_subblock_outputs; ++k) { l = 2 + type->max_subblock_inputs + k; if (0 != strcmp("open", tokens[l])) { slist[i][m].outputs[k] = my_atoi(tokens[l]); } } l = 2 + type->max_subblock_inputs + type->max_subblock_outputs; if (0 != strcmp("open", tokens[l])) { slist[i][m].clock = my_atoi(tokens[l]); } } ++m; /* Next subblock */ FreeTokens(&tokens); tokens = ReadLineTokens(infile, &line); prev_line = line; } if (pass > COUNT) { /* Check num of subblocks read */ if (scount[i] > type->max_subblocks) { printf("too many subblocks on block [%d] %s\n", i, blist[i].name); exit(1); } } ++i; /* End of this block */ FreeTokens(&block_tokens); FreeTokens(&pin_tokens); block_tokens = tokens; } /* Save counts */ if (COUNT == pass) { bcount = i; ncount = j; } } fclose(infile); /* Builds mappings from each netlist to the blocks contained */ sync_nets_to_blocks(bcount, blist, ncount, nlist); /* Send values back to caller */ *num_blocks = bcount; *block_list = blist; *num_nets = ncount; *net_list = nlist; subblock_data_ptr->subblock_inf = slist; subblock_data_ptr->num_subblocks_per_block = scount; }
void read_trace_file(char *trace_file) { FILE *infile; char **tokens, *coord; int line, i, error; int cur_net, skip_cur_net; struct s_trace *trace, *next; char str[256]; t_rr_type rr_type, prev_rr_type; int x, y, pin, class, pad, track, xhigh, yhigh; trace_head = (struct s_trace **) my_malloc( num_nets * sizeof(struct s_trace *)); trace_tail = (struct s_trace **) my_malloc( num_nets * sizeof(struct s_trace *)); infile = fopen(trace_file, "r"); line = 0; /* Check first line match */ tokens = ReadLineTokens(infile, &line); error = 0; if (NULL == tokens) { error = 1; } for (i = 0; i < 7; ++i) { if (!error) { if (NULL == tokens[i]) { error = 1; break; } } } if (!error) { if ((0 != strcmp(tokens[0], "Array")) || (0 != strcmp(tokens[1], "size:")) || (0 != strcmp(tokens[3], "x")) || (0 != strcmp(tokens[5], "logic")) || (0 != strcmp(tokens[6], "blocks."))) { error = 1; }; if (nx != atoi(tokens[2]) || ny != atoi(tokens[4])) error = 1; } tokens = ReadLineTokens(infile, &line); if (NULL == tokens) { error = 1; } for (i = 0; i < 4; ++i) { if (!error) { if (NULL == tokens[i]) { error = 1; break; } } } if (!error) { if ((0 != strcmp(tokens[0], "T_crit:")) || (0 != strcmp(tokens[2], "Width_fac:"))) { error = 1; }; T_critical_path = atof(tokens[1]); fixed_chan_width = atoi(tokens[3]); } tokens = ReadLineTokens(infile, &line); if (NULL == tokens || 0 != strcmp(tokens[0], "Routing:")) error = 1; if (error) { printf( ERRTAG "'%s' - Bad FPGA size/T_crit/width specification line or header line in routing file\n", trace_file); exit(1); } build_route(fixed_chan_width); /* Begin parsing traces * */ cur_net = OPEN; while (1) { tokens = ReadLineTokens(infile, &line); if (tokens == NULL) { /* Set last net trace_tail */ if (cur_net != OPEN) { trace->next = NULL; trace_tail[cur_net] = trace; } break; } if (0 == strcmp(tokens[0], "Net")) { skip_cur_net = 0; /* Set previous net trace_tail */ if (cur_net != OPEN) { trace->next = NULL; trace_tail[cur_net] = trace; } cur_net = atoi(tokens[1]); trace = (struct s_trace *) my_malloc(sizeof(struct s_trace)); trace_head[cur_net] = trace; strcpy(str, "("); strcat(str, clb_net[cur_net].name); strcat(str, ")\0"); if (0 != strcmp(tokens[2], str) && 0 == strcmp(tokens[3], "global")) { skip_cur_net = 1; trace_head[cur_net] = NULL; trace_tail[cur_net] = NULL; cur_net = OPEN; free(trace); } } else if (!skip_cur_net) { /* rr_resource node of the current net */ if (0 == strcmp(tokens[0], "SOURCE")) { /* SOURCE (x,y) Class: class*/ /* tokens[1] gives coordinates of the routing resource*/ rr_type = SOURCE; coord = strtok(tokens[1], "(,)"); x = atoi(coord); coord = strtok(NULL, "(,)"); y = atoi(coord); if (0 == (strcmp(tokens[2], "Class:"))) { class = atoi(tokens[3]); trace->index = get_rr_node_index(x, y, rr_type, class, rr_node_indices); } else if (0 == (strcmp(tokens[2], "Pad:"))) { pad = atoi(tokens[3]); trace->index = get_rr_node_index(x, y, rr_type, pad, rr_node_indices); } else if (0 == (strcmp(tokens[4], "Class:"))) { class = atoi(tokens[5]); trace->index = get_rr_node_index(x, y, rr_type, class, rr_node_indices); } else { assert(0 == (strcmp(tokens[4], "Pad:"))); pad = atoi(tokens[5]); trace->index = get_rr_node_index(x, y, rr_type, pad, rr_node_indices); } prev_rr_type = SOURCE; continue; } else if (0 == strcmp(tokens[0], "OPIN")) {
void read_place(IN const char *place_file, IN const char *arch_file, IN const char *net_file, IN int nx, IN int ny, IN int num_blocks, INOUT struct s_block block_list[]) { FILE *infile; char **tokens; int line; int i; int error; struct s_block *cur_blk; infile = my_fopen(place_file, "r"); /* Check filenames in first line match */ tokens = ReadLineTokens(infile, &line); error = 0; if(NULL == tokens) { error = 1; } for(i = 0; i < 6; ++i) { if(!error) { if(NULL == tokens[i]) { error = 1; } } } if(!error) { if((0 != strcmp(tokens[0], "Netlist")) || (0 != strcmp(tokens[1], "file:")) || (0 != strcmp(tokens[3], "Architecture")) || (0 != strcmp(tokens[4], "file:"))) { error = 1; }; } if(error) { printf(ERRTAG "'%s' - Bad filename specification line in placement file\n", place_file); exit(1); } if(0 != strcmp(tokens[2], arch_file)) { printf(ERRTAG "'%s' - Architecture file that generated placement (%s) does " "not match current architecture file (%s)\n", place_file, tokens[2], arch_file); exit(1); } if(0 != strcmp(tokens[5], net_file)) { printf(ERRTAG "'%s' - Netlist file that generated placement (%s) does " "not match current netlist file (%s)\n", place_file, tokens[5], net_file); exit(1); } /* Check array size in second line matches */ tokens = ReadLineTokens(infile, &line); error = 0; if(NULL == tokens) { error = 1; } for(i = 0; i < 7; ++i) { if(!error) { if(NULL == tokens[i]) { error = 1; } } } if(!error) { if((0 != strcmp(tokens[0], "Array")) || (0 != strcmp(tokens[1], "size:")) || (0 != strcmp(tokens[3], "x")) || (0 != strcmp(tokens[5], "logic")) || (0 != strcmp(tokens[6], "blocks"))) { error = 1; }; } if(error) { printf(ERRTAG "'%s' - Bad fpga size specification line in placement file\n", place_file); exit(1); } if((my_atoi(tokens[2]) != nx) || (my_atoi(tokens[4]) != ny)) { printf(ERRTAG "'%s' - Current FPGA size (%d x %d) is different from " "size when placement generated (%d x %d)\n", place_file, nx, ny, my_atoi(tokens[2]), my_atoi(tokens[4])); exit(1); } tokens = ReadLineTokens(infile, &line); while(tokens) { /* Linear search to match pad to netlist */ cur_blk = NULL; for(i = 0; i < num_blocks; ++i) { if(0 == strcmp(block_list[i].name, tokens[0])) { cur_blk = (block_list + i); break; } } /* Error if invalid block */ if(NULL == cur_blk) { printf(ERRTAG "'%s':%d - Block in placement file does " "not exist in netlist\n", place_file, line); exit(1); } /* Set pad coords */ cur_blk->x = my_atoi(tokens[1]); cur_blk->y = my_atoi(tokens[2]); cur_blk->z = my_atoi(tokens[3]); /* Get next line */ assert(*tokens); free(*tokens); free(tokens); tokens = ReadLineTokens(infile, &line); } fclose(infile); }