VPR-6.0
|
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "util.h"
#include "hash.h"
#include "vpr_types.h"
#include "vpr_utils.h"
#include "ReadLine.h"
#include "globals.h"
#include "ezxml.h"
#include "read_xml_util.h"
#include "read_netlist.h"
#include "pb_type_graph.h"
#include "cluster_legality.h"
#include "token.h"
#include "rr_graph.h"
Go to the source code of this file.
Functions | |
static void | processPorts (INOUTP ezxml_t Parent, INOUTP t_pb *pb, INOUTP t_rr_node *rr_graph, INOUTP int *ncount, INOUTP struct s_hash **nhash) |
static void | processPb (INOUTP ezxml_t Parent, INOUTP t_pb *pb, INOUTP t_rr_node *rr_graph, INOUTP int *ncount, INOUTP struct s_hash **nhash, INOUTP int *num_primitives) |
static void | processComplexBlock (INOUTP ezxml_t Parent, INOUTP t_block *cb, INP int index, INOUTP int *ncount, INOUTP struct s_hash **nhash, INOUTP int *num_primitives, INP const t_arch *arch) |
static struct s_net * | alloc_and_init_netlist_from_hash (INP int ncount, INOUTP struct s_hash **nhash) |
static int | add_net_to_hash (INOUTP struct s_hash **nhash, INP char *net_name, INOUTP int *ncount) |
static void | load_external_nets_and_cb (INP int num_blocks, INP struct s_block block_list[], INP int ncount, INP struct s_net nlist[], OUTP int *ext_ncount, OUTP struct s_net **ext_nets, INP char **circuit_globals) |
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) |
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) |
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) |
static void | count_internal_cb_rr_graph_net_nums (INP t_rr_node *cur_rr_node, INP t_rr_node *rr_graph) |
static void | mark_constant_generators (INP int num_blocks, INP struct s_block block_list[], INP int ncount, INOUTP struct s_net nlist[]) |
static void | mark_constant_generators_rec (INP t_pb *pb, INP t_rr_node *rr_graph, INOUTP struct s_net nlist[]) |
static void | restore_logical_block_from_saved_block (INP int iblk, INP t_pb *pb) |
void | read_netlist (INP const char *net_file, INP const t_arch *arch, OUTP int *num_blocks, OUTP struct s_block *block_list[], OUTP int *num_nets, OUTP struct s_net *net_list[]) |
static void | processPorts (INOUTP ezxml_t Parent, INOUTP t_pb *pb, t_rr_node *rr_graph, INOUTP int *ncount, INOUTP struct s_hash **nhash) |
static int | count_sinks_internal_cb_rr_graph_net_nums (INP t_rr_node *cur_rr_node, INP t_rr_node *rr_graph) |
void | free_logical_blocks () |
void | free_logical_nets () |
Author: Jason Luu Date: May 2009
Read a circuit netlist in XML format and populate the netlist data structures for VPR
Definition in file read_netlist.c.
static int add_net_to_hash | ( | INOUTP struct s_hash ** | nhash, |
INP char * | net_name, | ||
INOUTP int * | ncount | ||
) | [static] |
Adds net to hashtable of nets. If the net is "open", then this is a keyword so do not add it. If the net already exists, increase the count on that net
Definition at line 516 of file read_netlist.c.
{ struct s_hash *hash_value; if(strcmp(net_name, "open") == 0) { return OPEN; } hash_value = insert_in_hash_table(nhash, net_name, *ncount); if(hash_value->count == 1) { assert(*ncount == hash_value->index); (*ncount)++; } return hash_value->index; }
static struct s_net * alloc_and_init_netlist_from_hash | ( | INP int | ncount, |
INOUTP struct s_hash ** | nhash | ||
) | [static, read] |
Allocates memory for nets and loads the name of the net so that it can be identified and loaded with more complete information later
ncount | - number of nets in the hashtable of nets |
nhash | - hashtable of nets |
Definition at line 485 of file read_netlist.c.
{ struct s_net *nlist; struct s_hash_iterator hash_iter; struct s_hash *curr_net; int i; nlist = my_calloc(ncount, sizeof(struct s_net)); hash_iter = start_hash_table_iterator(); curr_net = get_next_hash(nhash, &hash_iter); while(curr_net != NULL) { assert(nlist[curr_net->index].name == NULL); nlist[curr_net->index].name = my_strdup(curr_net->name); nlist[curr_net->index].num_sinks = curr_net->count - 1; nlist[curr_net->index].node_block = my_malloc(curr_net->count * sizeof(int)); nlist[curr_net->index].node_block_pin = my_malloc(curr_net->count * sizeof(int)); nlist[curr_net->index].is_global = FALSE; for(i = 0; i < curr_net->count; i++) { nlist[curr_net->index].node_block[i] = OPEN; nlist[curr_net->index].node_block_pin[i] = OPEN; } curr_net = get_next_hash(nhash, &hash_iter); } return nlist; }
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 | ||
) | [static] |
allocate space to store nets internal to cb. two pass algorithm, pass 1 count and allocate # nets, pass 2 determine # sinks
Definition at line 976 of file read_netlist.c.
{ int i, j, k; const t_pb_type *pb_type; int num_sinks; pb_type = pb_graph_node->pb_type; if(pb_graph_node->parent_pb_graph_node == NULL) { /* determine nets driven from inputs at top level */ top_level->num_local_nets = 0; if(pass == 1) top_level->local_nets = NULL; for(i = 0; i < pb_graph_node->num_input_ports; i++) { for(j = 0; j < pb_graph_node->num_input_pins[i]; j++) { if(rr_graph[pb_graph_node->input_pins[i][j].pin_count_in_cluster].net_num != OPEN) { if(pass == 2) { 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); top_level->local_nets[top_level->num_local_nets].num_sinks = num_sinks; top_level->local_nets[top_level->num_local_nets].node_block = my_calloc(num_sinks, sizeof(int)); top_level->local_nets[top_level->num_local_nets].node_block_port = my_calloc(num_sinks, sizeof(int)); top_level->local_nets[top_level->num_local_nets].node_block_pin = my_calloc(num_sinks, sizeof(int)); } top_level->num_local_nets++; } } } for(i = 0; i < pb_graph_node->num_clock_ports; i++) { for(j = 0; j < pb_graph_node->num_clock_pins[i]; j++) { if(rr_graph[pb_graph_node->clock_pins[i][j].pin_count_in_cluster].net_num != OPEN) { if(pass == 2) { 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); top_level->local_nets[top_level->num_local_nets].num_sinks = num_sinks; top_level->local_nets[top_level->num_local_nets].node_block = my_calloc(num_sinks, sizeof(int)); top_level->local_nets[top_level->num_local_nets].node_block_port = my_calloc(num_sinks, sizeof(int)); top_level->local_nets[top_level->num_local_nets].node_block_pin = my_calloc(num_sinks, sizeof(int)); } top_level->num_local_nets++; } } } } if(pb_type->blif_model != NULL) { /* This is a terminal node so it might drive nets, find and map the rr_graph path for those nets */ for(i = 0; i < pb_graph_node->num_output_ports; i++) { for(j = 0; j < pb_graph_node->num_output_pins[i]; j++) { if(rr_graph[pb_graph_node->output_pins[i][j].pin_count_in_cluster].net_num != OPEN) { if(pass == 2) { 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); top_level->local_nets[top_level->num_local_nets].num_sinks = num_sinks; top_level->local_nets[top_level->num_local_nets].node_block = my_calloc(num_sinks, sizeof(int)); top_level->local_nets[top_level->num_local_nets].node_block_port = my_calloc(num_sinks, sizeof(int)); top_level->local_nets[top_level->num_local_nets].node_block_pin = my_calloc(num_sinks, sizeof(int)); } top_level->num_local_nets++; } } } } else { /* Recurse down to primitives */ for(i = 0; i < pb_type->num_modes; i++) { for(j = 0; j < pb_type->modes[i].num_pb_type_children; j++) { for(k = 0; k < pb_type->modes[i].pb_type_children[j].num_pb; k++) { alloc_internal_cb_nets(top_level, &pb_graph_node->child_pb_graph_nodes[i][j][k], rr_graph, pass); } } } } if(pb_graph_node->parent_pb_graph_node == NULL) { /* at top level */ if(pass == 1) { top_level->local_nets = my_calloc(top_level->num_local_nets, sizeof(struct s_net)); } } }
static void count_internal_cb_rr_graph_net_nums | ( | INP t_rr_node * | cur_rr_node, |
INP t_rr_node * | rr_graph | ||
) | [static] |
static int count_sinks_internal_cb_rr_graph_net_nums | ( | INP t_rr_node * | cur_rr_node, |
INP t_rr_node * | rr_graph | ||
) | [static] |
Recursive function that fills rr_graph of cb with net numbers starting at the given rr_node
Definition at line 842 of file read_netlist.c.
{ int i; int count = 0; for(i = 0; i < cur_rr_node->num_edges; i++) { if(&rr_graph[rr_graph[cur_rr_node->edges[i]].prev_node] == cur_rr_node) { 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); count += count_sinks_internal_cb_rr_graph_net_nums(&rr_graph[cur_rr_node->edges[i]], rr_graph); } } if(count == 0) { return 1; /* terminal node */ } else { return count; } }
void free_logical_blocks | ( | ) |
Free logical blocks of netlist
Definition at line 1142 of file read_netlist.c.
{ int iblk, i; t_model_ports *port; struct s_linked_vptr *tvptr, *next; for (iblk=0;iblk<num_logical_blocks;iblk++) { port = logical_block[iblk].model->inputs; i = 0; while(port) { if(!port->is_clock) { free(logical_block[iblk].input_nets[i]); if(logical_block[iblk].input_net_tnodes) { if(logical_block[iblk].input_net_tnodes[i]) free(logical_block[iblk].input_net_tnodes[i]); } i++; } port = port->next; } if(logical_block[iblk].input_net_tnodes) { free(logical_block[iblk].input_net_tnodes); } free(logical_block[iblk].input_nets); port = logical_block[iblk].model->outputs; i = 0; while(port) { free(logical_block[iblk].output_nets[i]); if(logical_block[iblk].output_net_tnodes) { if(logical_block[iblk].output_net_tnodes[i]) free(logical_block[iblk].output_net_tnodes[i]); } i++; port = port->next; } if(logical_block[iblk].output_net_tnodes) { free(logical_block[iblk].output_net_tnodes); } free(logical_block[iblk].output_nets); free(logical_block[iblk].name); tvptr = logical_block[iblk].truth_table; while(tvptr != NULL) { if(tvptr->data_vptr) free(tvptr->data_vptr); next = tvptr->next; free(tvptr); tvptr = next; } } free(logical_block); }
void free_logical_nets | ( | ) |
Free logical blocks of netlist
Definition at line 1194 of file read_netlist.c.
{ int inet; for (inet=0;inet<num_logical_nets;inet++) { free(vpack_net[inet].name); free(vpack_net[inet].node_block); free(vpack_net[inet].node_block_port); free(vpack_net[inet].node_block_pin); } free(vpack_net); }
static void load_external_nets_and_cb | ( | INP int | num_blocks, |
INP struct s_block | block_list[], | ||
INP int | ncount, | ||
INP struct s_net | nlist[], | ||
OUTP int * | ext_ncount, | ||
OUTP struct s_net ** | ext_nets, | ||
INP char ** | circuit_globals | ||
) | [static] |
This function updates the nets list and the connections between that list and the complex block
Definition at line 710 of file read_netlist.c.
{ int i, j, k, ipin; struct s_hash **ext_nhash; t_rr_node *rr_graph; t_pb_graph_pin *pb_graph_pin; int *count; int netnum, num_tokens; *ext_ncount = 0; ext_nhash = alloc_hash_table(); /* Assumes that complex block pins are ordered inputs, outputs, globals */ /* Determine the external nets of complex block */ for(i = 0; i < num_blocks; i++) { ipin = 0; if(block_list[i].type->pb_type->num_input_pins + block_list[i].type->pb_type->num_output_pins + block_list[i].type->pb_type->num_clock_pins != block_list[i].type->num_pins / block_list[i].type->capacity) { assert(0); } /* First determine nets external to complex blocks */ assert(block_list[i].type->pb_type->num_input_pins + block_list[i].type->pb_type->num_output_pins + block_list[i].type->pb_type->num_clock_pins == block_list[i].type->num_pins / block_list[i].type->capacity); rr_graph = block_list[i].pb->rr_graph; for(j = 0; j < block_list[i].pb->pb_graph_node->num_input_ports; j++) { for(k = 0; k < block_list[i].pb->pb_graph_node->num_input_pins[j]; k++) { pb_graph_pin = &block_list[i].pb->pb_graph_node->input_pins[j][k]; assert(pb_graph_pin->pin_count_in_cluster == ipin); if(rr_graph[pb_graph_pin->pin_count_in_cluster].net_num != OPEN) { 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); } else { block_list[i].nets[ipin] = OPEN; } ipin++; } } for(j = 0; j < block_list[i].pb->pb_graph_node->num_output_ports; j++) { for(k = 0; k < block_list[i].pb->pb_graph_node->num_output_pins[j]; k++) { pb_graph_pin = &block_list[i].pb->pb_graph_node->output_pins[j][k]; assert(pb_graph_pin->pin_count_in_cluster == ipin); if(rr_graph[pb_graph_pin->pin_count_in_cluster].net_num != OPEN) { 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); } else { block_list[i].nets[ipin] = OPEN; } ipin++; } } for(j = 0; j < block_list[i].pb->pb_graph_node->num_clock_ports; j++) { for(k = 0; k < block_list[i].pb->pb_graph_node->num_clock_pins[j]; k++) { pb_graph_pin = &block_list[i].pb->pb_graph_node->clock_pins[j][k]; assert(pb_graph_pin->pin_count_in_cluster == ipin); if(rr_graph[pb_graph_pin->pin_count_in_cluster].net_num != OPEN) { 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); } else { block_list[i].nets[ipin] = OPEN; } ipin++; } } for(j = ipin; j < block_list[i].type->num_pins; j++) { block_list[i].nets[ipin] = OPEN; } } /* alloc and partially load the list of external nets */ (*ext_nets) = alloc_and_init_netlist_from_hash(*ext_ncount, ext_nhash); /* Load global nets */ num_tokens = CountTokens(circuit_globals); for(i = 0; i < *ext_ncount; i++) { for(j = 0; j < num_tokens; j++) { if(strcmp(circuit_globals[j], (*ext_nets)[i].name) == 0) { (*ext_nets)[i].is_global = TRUE; } } } count = my_calloc(*ext_ncount, sizeof(int)); /* complete load of external nets so that each net points back to the blocks */ for(i = 0; i < num_blocks; i++) { ipin = 0; rr_graph = block_list[i].pb->rr_graph; for(j = 0; j < block_list[i].type->num_pins; j++) { netnum = block_list[i].nets[j]; if(netnum != OPEN) { if(RECEIVER == block_list[i].type->class_inf[block_list[i].type->pin_class[j]].type) { count[netnum]++; assert(count[netnum] <= (*ext_nets)[netnum].num_sinks); (*ext_nets)[netnum].node_block[count[netnum]] = i; (*ext_nets)[netnum].node_block_pin[count[netnum]] = j; if((*ext_nets)[netnum].is_global != block_list[i].type->is_global_pin[j]) { if((*ext_nets)[netnum].is_global) { printf(ERRTAG "Netlist attempts to connect global net %s to non global pin %d of block %s #%d\n", (*ext_nets)[netnum].name, j, block_list[i].name, j); } else { printf(ERRTAG "Netlist attempts to connect non-global net %s to global pin %d of block %s #%d\n", (*ext_nets)[netnum].name, j, block_list[i].name, j); } exit(1); } } else { assert(DRIVER == block_list[i].type->class_inf[block_list[i].type->pin_class[j]].type); assert((*ext_nets)[netnum].node_block[0] == OPEN); (*ext_nets)[netnum].node_block[0] = i; (*ext_nets)[netnum].node_block_pin[0] = j; } } } } free(count); free_hash_table(ext_nhash); }
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 | ||
) | [static] |
Load internal cb nets and fill rr_graph of cb with net numbers
Definition at line 887 of file read_netlist.c.
{ int i, j, k; const t_pb_type *pb_type; int temp, size; struct s_net * nets; pb_type = pb_graph_node->pb_type; nets = top_level->local_nets; temp = 0; if(pb_graph_node->parent_pb_graph_node == NULL) { /* determine nets driven from inputs at top level */ *curr_net = 0; for(i = 0; i < pb_graph_node->num_input_ports; i++) { for(j = 0; j < pb_graph_node->num_input_pins[i]; j++) { if(rr_graph[pb_graph_node->input_pins[i][j].pin_count_in_cluster].net_num != OPEN) { 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); assert(temp == nets[*curr_net].num_sinks); temp = 0; size = strlen(pb_graph_node->pb_type->name) + pb_graph_node->placement_index/10 + i / 10 + j /10 + pb_graph_node->input_pins[i][j].pin_count_in_cluster/10 + 26; nets[*curr_net].name = my_calloc(size, sizeof(char)); sprintf(nets[*curr_net].name, "%s[%d].input[%d][%d].pin[%d]", pb_graph_node->pb_type->name, pb_graph_node->placement_index, i, j, pb_graph_node->input_pins[i][j].pin_count_in_cluster); (*curr_net)++; } } } for(i = 0; i < pb_graph_node->num_clock_ports; i++) { for(j = 0; j < pb_graph_node->num_clock_pins[i]; j++) { if(rr_graph[pb_graph_node->clock_pins[i][j].pin_count_in_cluster].net_num != OPEN) { 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); assert(temp == nets[*curr_net].num_sinks); temp = 0; nets[*curr_net].is_global = TRUE; size = strlen(pb_graph_node->pb_type->name) + pb_graph_node->placement_index/10 + i / 10 + j /10 + pb_graph_node->clock_pins[i][j].pin_count_in_cluster/10 + 26; nets[*curr_net].name = my_calloc(size, sizeof(char)); sprintf(nets[*curr_net].name, "%s[%d].clock[%d][%d].pin[%d]", pb_graph_node->pb_type->name, pb_graph_node->placement_index, i, j, pb_graph_node->clock_pins[i][j].pin_count_in_cluster); (*curr_net)++; } } } } if(pb_type->blif_model != NULL) { /* This is a terminal node so it might drive nets, find and map the rr_graph path for those nets */ for(i = 0; i < pb_graph_node->num_output_ports; i++) { for(j = 0; j < pb_graph_node->num_output_pins[i]; j++) { if(rr_graph[pb_graph_node->output_pins[i][j].pin_count_in_cluster].net_num != OPEN) { 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); assert(temp == nets[*curr_net].num_sinks); temp = 0; size = strlen(pb_graph_node->pb_type->name) + pb_graph_node->placement_index/10 + i / 10 + j /10 + pb_graph_node->output_pins[i][j].pin_count_in_cluster/10 + 26; nets[*curr_net].name = my_calloc(size, sizeof(char)); sprintf(nets[*curr_net].name, "%s[%d].output[%d][%d].pin[%d]", pb_graph_node->pb_type->name, pb_graph_node->placement_index, i, j, pb_graph_node->output_pins[i][j].pin_count_in_cluster); (*curr_net)++; } } } } else { /* Recurse down to primitives */ for(i = 0; i < pb_type->num_modes; i++) { for(j = 0; j < pb_type->modes[i].num_pb_type_children; j++) { for(k = 0; k < pb_type->modes[i].pb_type_children[j].num_pb; k++) { load_internal_cb_nets(top_level, &pb_graph_node->child_pb_graph_nodes[i][j][k], rr_graph, curr_net); } } } } if(pb_graph_node->parent_pb_graph_node == NULL) { /* at top level */ assert(*curr_net == top_level->num_local_nets); } }
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 | ||
) | [static] |
Recursive function that fills rr_graph of cb with net numbers starting at the given rr_node
Definition at line 860 of file read_netlist.c.
{ int i; boolean terminal; terminal = TRUE; for(i = 0; i < cur_rr_node->num_edges; i++) { if(&rr_graph[rr_graph[cur_rr_node->edges[i]].prev_node] == cur_rr_node) { /* TODO: If multiple edges to same node (should not happen in reasonable design) this always selects the last edge, need to be smart about it in future (ie. select fastest edge */ 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); rr_graph[cur_rr_node->edges[i]].net_num = cur_rr_node->net_num; rr_graph[cur_rr_node->edges[i]].prev_edge = i; load_internal_cb_rr_graph_net_nums(&rr_graph[cur_rr_node->edges[i]], rr_graph, nets, curr_net, curr_sink); terminal = FALSE; } } if(terminal == TRUE) { /* Since the routing node index is known, assign that instead of the more obscure node block */ nets[*curr_net].node_block[*curr_sink] = cur_rr_node->pb_graph_pin->pin_count_in_cluster; nets[*curr_net].node_block_pin[*curr_sink] = OPEN; nets[*curr_net].node_block_port[*curr_sink] = OPEN; (*curr_sink)++; } }
static void mark_constant_generators | ( | INP int | num_blocks, |
INP struct s_block | block_list[], | ||
INP int | ncount, | ||
INOUTP struct s_net | nlist[] | ||
) | [static] |
Definition at line 1051 of file read_netlist.c.
{ int i; for(i = 0; i < num_blocks; i++) { mark_constant_generators_rec(block_list[i].pb, block_list[i].pb->rr_graph, nlist); } }
static void mark_constant_generators_rec | ( | INP t_pb * | pb, |
INP t_rr_node * | rr_graph, | ||
INOUTP struct s_net | nlist[] | ||
) | [static] |
Definition at line 1062 of file read_netlist.c.
{ int i, j; t_pb_type *pb_type; boolean const_gen; if(pb->pb_graph_node->pb_type->blif_model == NULL) { for(i = 0; i < pb->pb_graph_node->pb_type->modes[pb->mode].num_pb_type_children; i++) { pb_type = &(pb->pb_graph_node->pb_type->modes[pb->mode].pb_type_children[i]); for(j = 0; j < pb_type->num_pb; j++) { if(pb->child_pbs[i][j].name != NULL) { mark_constant_generators_rec(&(pb->child_pbs[i][j]), rr_graph, nlist); } } } } else if( strcmp(pb->pb_graph_node->pb_type->name, "inpad") != 0) { const_gen = TRUE; for(i = 0; i < pb->pb_graph_node->num_input_ports && const_gen == TRUE; i++) { for(j = 0; j < pb->pb_graph_node->num_input_pins[i] && const_gen == TRUE; j++) { if(rr_graph[pb->pb_graph_node->input_pins[i][j].pin_count_in_cluster].net_num != OPEN) { const_gen = FALSE; } } } for(i = 0; i < pb->pb_graph_node->num_clock_ports && const_gen == TRUE; i++) { for(j = 0; j < pb->pb_graph_node->num_clock_pins[i] && const_gen == TRUE; j++) { if(rr_graph[pb->pb_graph_node->clock_pins[i][j].pin_count_in_cluster].net_num != OPEN) { const_gen = FALSE; } } } if(const_gen == TRUE) { printf("%s is a constant generator \n", pb->name); for(i = 0; i < pb->pb_graph_node->num_output_ports; i++) { for(j = 0; j < pb->pb_graph_node->num_output_pins[i]; j++) { if(rr_graph[pb->pb_graph_node->output_pins[i][j].pin_count_in_cluster].net_num != OPEN) { nlist[rr_graph[pb->pb_graph_node->output_pins[i][j].pin_count_in_cluster].net_num].is_const_gen = TRUE; } } } } } }
static void processComplexBlock | ( | INOUTP ezxml_t | Parent, |
INOUTP t_block * | cb, | ||
INP int | index, | ||
INOUTP int * | ncount, | ||
INOUTP struct s_hash ** | nhash, | ||
INOUTP int * | num_primitives, | ||
INP const t_arch * | arch | ||
) | [static] |
XML parser to populate CLB info and to update nets with the nets of this CLB
Parent | - XML tag for this CLB |
clb | - Array of CLBs in the netlist |
index | - index of the CLB to allocate and load information into |
ncount | - number of nets recorded thus far in all CLBs |
nhash | - hashtable of all nets recorded thus far in all CLBs |
Definition at line 227 of file read_netlist.c.
{ const char *Prop; boolean found; int num_tokens = 0; t_token *tokens; int i; const t_pb_type * pb_type = NULL; /* parse cb attributes */ cb[index].pb = my_calloc(1, sizeof(t_pb)); Prop = FindProperty(Parent, "name", TRUE); cb[index].name = my_strdup(Prop); cb[index].pb->name = my_strdup(Prop); ezxml_set_attr(Parent, "name", NULL); Prop = FindProperty(Parent, "instance", TRUE); tokens = GetTokensFromString(Prop, &num_tokens); ezxml_set_attr(Parent, "instance", NULL); if(num_tokens != 4 || tokens[0].type != TOKEN_STRING || tokens[1].type != TOKEN_OPEN_SQUARE_BRACKET || tokens[2].type != TOKEN_INT || tokens[3].type != TOKEN_CLOSE_SQUARE_BRACKET) { printf(ERRTAG "[Line %d] Unknown syntax for instance %s in %s. Expected pb_type[instance_number]\n", Parent->line, Prop, Parent->name); exit(1); } assert(my_atoi(tokens[2].data) == index); found = FALSE; for(i = 0; i < num_types; i++) { if(strcmp(type_descriptors[i].name, tokens[0].data) == 0) { cb[index].type = &type_descriptors[i]; pb_type = cb[index].type->pb_type; found = TRUE; break; } } if(!found) { printf(ERRTAG "[Line %d] Unknown cb type %s for cb %s #%d\n", Parent->line, Prop, cb[index].name, index); exit(1); } /* Parse all pbs and CB internal nets*/ cb[index].pb->logical_block = OPEN; cb[index].pb->pb_graph_node = cb[index].type->pb_graph_head; rr_node = my_calloc(cb[index].type->pb_graph_head->total_pb_pins, sizeof(t_rr_node)); alloc_and_load_rr_graph_for_pb_graph_node(cb[index].pb->pb_graph_node, arch, 0); cb[index].pb->rr_graph = rr_node; num_rr_nodes = cb[index].pb->pb_graph_node->total_pb_pins; Prop = FindProperty(Parent, "mode", TRUE); ezxml_set_attr(Parent, "mode", NULL); found = FALSE; for(i = 0; i < pb_type->num_modes; i++) { if(strcmp(Prop, pb_type->modes[i].name) == 0) { cb[index].pb->mode = i; found = TRUE; } } if(!found) { printf(ERRTAG "[Line %d] Unknown mode %s for cb %s #%d\n", Parent->line, Prop, cb[index].name, index); exit(1); } processPb(Parent, cb[index].pb, cb[index].pb->rr_graph, ncount, nhash, num_primitives); cb[index].nets = my_malloc(cb[index].type->num_pins * sizeof(int)); for(i = 0; i < cb[index].type->num_pins; i++ ) { cb[index].nets[i] = OPEN; } alloc_internal_cb_nets(cb[index].pb, cb[index].pb->pb_graph_node, cb[index].pb->rr_graph, 1); alloc_internal_cb_nets(cb[index].pb, cb[index].pb->pb_graph_node, cb[index].pb->rr_graph, 2); i = 0; load_internal_cb_nets(cb[index].pb, cb[index].pb->pb_graph_node, cb[index].pb->rr_graph, &i); freeTokens(tokens, num_tokens); #if 0 /* 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 */ for(i = 0; i < cb[index].pb->num_local_nets; i++) { printf("local net %s: ", cb[index].pb->name); for(j = 0; j <= cb[index].pb->local_nets[i].num_sinks; j++) { printf("%d ", cb[index].pb->local_nets[i].node_block[j]); } printf("\n"); } #endif }
static void processPb | ( | INOUTP ezxml_t | Parent, |
INOUTP t_pb * | pb, | ||
INOUTP t_rr_node * | rr_graph, | ||
INOUTP int * | ncount, | ||
INOUTP struct s_hash ** | nhash, | ||
INOUTP int * | num_primitives | ||
) | [static] |
XML parser to populate pb info and to update internal nets of the parent CLB
Parent | - XML tag for this pb_type |
pb | - physical block to use |
ncount | - number of all internal subblock nets recorded thus far in this CLB |
nhash | - hashtable of all internal subblock nets recorded thus far in this CLBs |
Definition at line 327 of file read_netlist.c.
{ ezxml_t Cur, Prev, lookahead; const char *Prop; const char *instance_type; int i, j, pb_index; boolean found; const t_pb_type *pb_type; t_token *tokens; int num_tokens; Cur = FindElement(Parent, "inputs", TRUE); processPorts(Cur, pb, rr_graph, ncount, nhash); FreeNode(Cur); Cur = FindElement(Parent, "outputs", TRUE); processPorts(Cur, pb, rr_graph, ncount, nhash); FreeNode(Cur); Cur = FindElement(Parent, "globals", TRUE); processPorts(Cur, pb, rr_graph, ncount, nhash); FreeNode(Cur); pb_type = pb->pb_graph_node->pb_type; if(pb_type->num_modes == 0) { pb->logical_block = *num_primitives; /* TODO: This info is not yet used. Intention was to use later for error checking */ if(saved_logical_blocks != NULL) { restore_logical_block_from_saved_block(*num_primitives, pb); } (*num_primitives)++; } else { /* process children of child if exists */ pb->child_pbs = my_calloc(pb_type->modes[pb->mode].num_pb_type_children, sizeof(t_pb*)); for(i = 0; i < pb_type->modes[pb->mode].num_pb_type_children; i++) { pb->child_pbs[i] = my_calloc(pb_type->modes[pb->mode].pb_type_children[i].num_pb, sizeof(t_pb)); } /* Populate info for each physical block */ Cur = Parent->child; while(Cur) { if(0 == strcmp(Cur->name, "block")) { CheckElement(Cur, "block"); instance_type = FindProperty(Cur, "instance", TRUE); tokens = GetTokensFromString(instance_type, &num_tokens); ezxml_set_attr(Cur, "instance", NULL); if(num_tokens != 4 || tokens[0].type != TOKEN_STRING || tokens[1].type != TOKEN_OPEN_SQUARE_BRACKET || tokens[2].type != TOKEN_INT || tokens[3].type != TOKEN_CLOSE_SQUARE_BRACKET) { printf(ERRTAG "[Line %d] Unknown syntax for instance %s in %s. Expected pb_type[instance_number]\n", Cur->line, instance_type, Cur->name); exit(1); } found = FALSE; pb_index = OPEN; for(i = 0; i < pb_type->modes[pb->mode].num_pb_type_children; i++) { if(strcmp(pb_type->modes[pb->mode].pb_type_children[i].name, tokens[0].data) == 0) { if(my_atoi(tokens[2].data) >= pb_type->modes[pb->mode].pb_type_children[i].num_pb) { printf(ERRTAG "[Line %d] Instance number exceeds # of pb available for instance %s in %s.\n", Cur->line, instance_type, Cur->name); exit(1); } pb_index = my_atoi(tokens[2].data); if(pb->child_pbs[i][pb_index].pb_graph_node != NULL) { 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); exit(1); } pb->child_pbs[i][pb_index].pb_graph_node = &pb->pb_graph_node->child_pb_graph_nodes[pb->mode][i][pb_index]; found = TRUE; break; } } if(!found) { printf(ERRTAG "[Line %d] Unknown pb type %s\n", Cur->line, instance_type); exit(1); } Prop = FindProperty(Cur, "name", TRUE); ezxml_set_attr(Cur, "name", NULL); if(0 != strcmp(Prop, "open")) { pb->child_pbs[i][pb_index].name = my_strdup(Prop); /* Parse all pbs and CB internal nets*/ pb->child_pbs[i][pb_index].logical_block = OPEN; Prop = FindProperty(Cur, "mode", FALSE); if(Prop) { ezxml_set_attr(Cur, "mode", NULL); } pb->child_pbs[i][pb_index].mode = 0; found = FALSE; for(j = 0; j < pb->child_pbs[i][pb_index].pb_graph_node->pb_type->num_modes; j++) { if(strcmp(Prop, pb->child_pbs[i][pb_index].pb_graph_node->pb_type->modes[j].name) == 0) { pb->child_pbs[i][pb_index].mode = j; found = TRUE; } } if(!found && pb->child_pbs[i][pb_index].pb_graph_node->pb_type->num_modes != 0) { printf(ERRTAG "[Line %d] Unknown mode %s for cb %s #%d\n", Cur->line, Prop, pb->child_pbs[i][pb_index].name, pb_index); exit(1); } pb->child_pbs[i][pb_index].parent_pb = pb; pb->child_pbs[i][pb_index].rr_graph = pb->rr_graph; processPb(Cur, &pb->child_pbs[i][pb_index], rr_graph, ncount, nhash, num_primitives); } else { /* physical block has no used primitives but it may have used routing */ pb->child_pbs[i][pb_index].name = NULL; pb->child_pbs[i][pb_index].logical_block = OPEN; lookahead = FindElement(Cur, "outputs", FALSE); if(lookahead != NULL) { lookahead = FindElement(lookahead, "port", TRUE); Prop = FindProperty(Cur, "mode", FALSE); if(Prop) { ezxml_set_attr(Cur, "mode", NULL); } pb->child_pbs[i][pb_index].mode = 0; found = FALSE; for(j = 0; j < pb->child_pbs[i][pb_index].pb_graph_node->pb_type->num_modes; j++) { if(strcmp(Prop, pb->child_pbs[i][pb_index].pb_graph_node->pb_type->modes[j].name) == 0) { pb->child_pbs[i][pb_index].mode = j; found = TRUE; } } if(!found && pb->child_pbs[i][pb_index].pb_graph_node->pb_type->num_modes != 0) { printf(ERRTAG "[Line %d] Unknown mode %s for cb %s #%d\n", Cur->line, Prop, pb->child_pbs[i][pb_index].name, pb_index); exit(1); } pb->child_pbs[i][pb_index].parent_pb = pb; pb->child_pbs[i][pb_index].rr_graph = pb->rr_graph; processPb(Cur, &pb->child_pbs[i][pb_index], rr_graph, ncount, nhash, num_primitives); } } Prev = Cur; Cur = Cur->next; FreeNode(Prev); freeTokens(tokens, num_tokens); } else { Cur = Cur->next; } } } }
static void processPorts | ( | INOUTP ezxml_t | Parent, |
INOUTP t_pb * | pb, | ||
t_rr_node * | rr_graph, | ||
INOUTP int * | ncount, | ||
INOUTP struct s_hash ** | nhash | ||
) | [static] |
Definition at line 531 of file read_netlist.c.
{ int i, j, in_port, out_port, clock_port, num_tokens; ezxml_t Cur, Prev; const char *Prop; char **pins; char *port_name, *interconnect_name; int rr_node_index; t_pb_graph_pin *** pin_node; int *num_ptrs, num_sets; boolean found; Cur = Parent->child; while(Cur) { if(0 == strcmp(Cur->name, "port")) { CheckElement(Cur, "port"); Prop = FindProperty(Cur, "name", TRUE); ezxml_set_attr(Cur, "name", NULL); in_port = out_port = clock_port = 0; found = FALSE; for(i = 0; i < pb->pb_graph_node->pb_type->num_ports; i++) { if(0 == strcmp(pb->pb_graph_node->pb_type->ports[i].name, Prop)) { found = TRUE; break; } if(pb->pb_graph_node->pb_type->ports[i].is_clock && pb->pb_graph_node->pb_type->ports[i].type == IN_PORT) { clock_port++; } else if(!pb->pb_graph_node->pb_type->ports[i].is_clock && pb->pb_graph_node->pb_type->ports[i].type == IN_PORT) { in_port++; } else { assert(pb->pb_graph_node->pb_type->ports[i].type == OUT_PORT); out_port++; } } if(!found) { 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); exit(1); } pins = GetNodeTokens(Cur); num_tokens = CountTokens(pins); if(0 == strcmp(Parent->name, "inputs")) { if(num_tokens != pb->pb_graph_node->num_input_pins[in_port]) { 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); exit(1); } } else if(0 == strcmp(Parent->name, "outputs")) { if(num_tokens != pb->pb_graph_node->num_output_pins[out_port]) { 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); exit(1); } } else { if(num_tokens != pb->pb_graph_node->num_clock_pins[clock_port]) { 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); exit(1); } } if(0 == strcmp(Parent->name, "inputs") || 0 == strcmp(Parent->name, "globals")) { if(pb->parent_pb == NULL) { /* top-level, connections are nets to route */ for(i = 0; i < num_tokens; i++) { if(0 == strcmp(Parent->name, "inputs")) rr_node_index = pb->pb_graph_node->input_pins[in_port][i].pin_count_in_cluster; else rr_node_index = pb->pb_graph_node->clock_pins[clock_port][i].pin_count_in_cluster; rr_graph[rr_node_index].net_num = add_net_to_hash(nhash, pins[i], ncount); } } else { for(i = 0; i < num_tokens; i++) { if(0 == strcmp(pins[i], "open")) { continue; } interconnect_name = strstr(pins[i], "->"); *interconnect_name = '\0'; interconnect_name += 2; port_name = pins[i]; pin_node = alloc_and_load_port_pin_ptrs_from_string(pb->pb_graph_node->parent_pb_graph_node, pb->pb_graph_node->parent_pb_graph_node->child_pb_graph_nodes[pb->parent_pb->mode], port_name, &num_ptrs, &num_sets, TRUE, TRUE); assert(num_sets == 1 && num_ptrs[0] == 1); if(0 == strcmp(Parent->name, "inputs")) rr_node_index = pb->pb_graph_node->input_pins[in_port][i].pin_count_in_cluster; else rr_node_index = pb->pb_graph_node->clock_pins[clock_port][i].pin_count_in_cluster; rr_graph[rr_node_index].prev_node = pin_node[0][0]->pin_count_in_cluster; found = FALSE; for(j = 0; j < pin_node[0][0]->num_output_edges; j++) { if(0 == strcmp(interconnect_name, pin_node[0][0]->output_edges[j]->interconnect->name)) { found = TRUE; break; } } for(j = 0; j < num_sets; j++) { free(pin_node[j]); } free(pin_node); free(num_ptrs); if(!found) { printf(ERRTAG "[Line %d] Unknown interconnect %s connecting to pin %s\n", Cur->line, interconnect_name, port_name); exit(1); } } } } if(0 == strcmp(Parent->name, "outputs")) { if(pb->pb_graph_node->pb_type->num_modes == 0) { /* primitives are drivers of nets */ for(i = 0; i < num_tokens; i++) { rr_node_index = pb->pb_graph_node->output_pins[out_port][i].pin_count_in_cluster; rr_graph[rr_node_index].net_num = add_net_to_hash(nhash, pins[i], ncount); } } else { for(i = 0; i < num_tokens; i++) { if(0 == strcmp(pins[i], "open")) { continue; } interconnect_name = strstr(pins[i], "->"); *interconnect_name = '\0'; interconnect_name += 2; port_name = pins[i]; pin_node = alloc_and_load_port_pin_ptrs_from_string(pb->pb_graph_node, pb->pb_graph_node->child_pb_graph_nodes[pb->mode], port_name, &num_ptrs, &num_sets, TRUE, TRUE); assert(num_sets == 1 && num_ptrs[0] == 1); rr_node_index = pb->pb_graph_node->output_pins[out_port][i].pin_count_in_cluster; rr_graph[rr_node_index].prev_node = pin_node[0][0]->pin_count_in_cluster; found = FALSE; for(j = 0; j < pin_node[0][0]->num_output_edges; j++) { if(0 == strcmp(interconnect_name, pin_node[0][0]->output_edges[j]->interconnect->name)) { found = TRUE; rr_graph[rr_node_index].fan_in++; rr_graph[pin_node[0][0]->pin_count_in_cluster].edges[j] = rr_node_index; break; } } for(j = 0; j < num_sets; j++) { free(pin_node[j]); } free(pin_node); free(num_ptrs); if(!found) { printf(ERRTAG "[Line %d] Unknown interconnect %s connecting to pin %s\n", Cur->line, interconnect_name, port_name); exit(1); } interconnect_name -= 2; *interconnect_name = '-'; } } } FreeTokens(&pins); Prev = Cur; Cur = Cur->next; FreeNode(Prev); } else { Cur = Cur->next; } } }
static void processPorts | ( | INOUTP ezxml_t | Parent, |
INOUTP t_pb * | pb, | ||
INOUTP t_rr_node * | rr_graph, | ||
INOUTP int * | ncount, | ||
INOUTP struct s_hash ** | nhash | ||
) | [static] |
void read_netlist | ( | INP const char * | net_file, |
INP const t_arch * | arch, | ||
OUTP int * | num_blocks, | ||
OUTP struct s_block * | block_list[], | ||
OUTP int * | num_nets, | ||
OUTP struct s_net * | net_list[] | ||
) |
Initializes the block_list with info from a netlist
net_file | - Name of the netlist file to read |
num_blocks | - number of CLBs in netlist |
block_list | - array of blocks in netlist [0..num_blocks - 1] |
num_nets | - number of nets in netlist |
net_list | - nets in netlist [0..num_nets - 1] |
Definition at line 77 of file read_netlist.c.
{ ezxml_t Cur, Prev, Top; int i, j; const char *Prop; int bcount; struct s_block *blist; int ncount, ext_ncount; struct s_net *nlist, *ext_nlist; struct s_hash **nhash; char **circuit_inputs, **circuit_outputs, **circuit_globals; int Count, Len; int num_primitives = 0; /* Parse the file */ printf("Begin parsing packed FPGA netlist file\n"); Top = ezxml_parse_file(net_file); if(NULL == Top) { printf(ERRTAG "Unable to load netlist file '%s'.\n", net_file); exit(1); } printf("Finished parsing packed FPGA netlist file\n"); /* Root node should be block */ CheckElement(Top, "block"); /* Check top-level netlist attributes */ Prop = FindProperty(Top, "name", TRUE); printf("Netlist generated from file %s\n", Prop); ezxml_set_attr(Top, "name", NULL); Prop = FindProperty(Top, "instance", TRUE); if(strcmp(Prop, "FPGA_packed_netlist[0]") != 0) { printf(ERRTAG "[Line %d] Expected instance to be \"FPGA_packed_netlist[0]\", found %s", Top->line, Prop); exit(1); } ezxml_set_attr(Top, "instance", NULL); /* Parse top-level netlist I/Os */ Cur = FindElement(Top, "inputs", TRUE); circuit_inputs = GetNodeTokens(Cur); FreeNode(Cur); Cur = FindElement(Top, "outputs", TRUE); circuit_outputs = GetNodeTokens(Cur); FreeNode(Cur); Cur = FindElement(Top, "globals", TRUE); CountTokensInString(Cur->txt, &Count, &Len); if(Count > 0) { circuit_globals = GetNodeTokens(Cur); } else { circuit_globals = NULL; } FreeNode(Cur); /* Parse all CLB blocks and all nets*/ bcount = CountChildren(Top, "block", 1); blist = my_calloc(bcount, sizeof(t_block)); nhash = alloc_hash_table(); ncount = 0; logical_block = my_calloc(num_saved_logical_blocks, sizeof(t_logical_block)); num_logical_blocks = num_saved_logical_blocks; Cur = Top->child; i = 0; while(Cur) { if(0 == strcmp(Cur->name, "block")) { CheckElement(Cur, "block"); processComplexBlock(Cur, blist, i, &ncount, nhash, &num_primitives, arch); Prev = Cur; Cur = Cur->next; FreeNode(Prev); i++; } else { Cur = Cur->next; } } assert(i == bcount); if(saved_logical_blocks != NULL) { assert(num_primitives == num_saved_logical_blocks); } nlist = alloc_and_init_netlist_from_hash(ncount, nhash); mark_constant_generators(bcount, blist, ncount, nlist); load_external_nets_and_cb(bcount, blist, ncount, nlist, &ext_ncount, &ext_nlist, circuit_globals); /* TODO: create this function later check_top_IO_matches_IO_blocks(circuit_inputs, circuit_outputs, circuit_globals, blist, bcount); */ free_hash_table(nhash); FreeTokens(&circuit_inputs); FreeTokens(&circuit_outputs); if(circuit_globals) FreeTokens(&circuit_globals); FreeNode(Top); /* load mapping between external nets and all nets */ /* jluu TODO: Should use local variables here then assign to globals later, clean up later */ vpack_net = nlist; num_logical_nets = ncount; clb_to_vpack_net_mapping = my_malloc(ext_ncount * sizeof(int)); vpack_to_clb_net_mapping = my_malloc(ncount * sizeof(int)); for(i = 0; i < ncount; i++) { vpack_to_clb_net_mapping[i] = OPEN; } for(i = 0; i < ext_ncount; i++) { for(j = 0; j < ncount; j++) { if(strcmp(ext_nlist[i].name, nlist[j].name) == 0) { clb_to_vpack_net_mapping[i] = j; vpack_to_clb_net_mapping[j] = i; break; } } assert(j != ncount); } if(saved_logical_blocks != NULL) { free(saved_logical_blocks); saved_logical_blocks = NULL; free(saved_logical_nets); saved_logical_nets = NULL; } /* Return blocks and nets */ *num_blocks = bcount; *block_list = blist; *num_nets = ext_ncount; *net_list = ext_nlist; }
static void restore_logical_block_from_saved_block | ( | INP int | iblk, |
INP t_pb * | pb | ||
) | [static] |
create logical block properties from saved block
Definition at line 1107 of file read_netlist.c.
{ int i; for(i = 0; i < num_saved_logical_blocks; i++) { if(pb->pb_graph_node->pb_type->model == saved_logical_blocks[i].model) { if(saved_logical_blocks[i].name != NULL && strcmp(pb->name, saved_logical_blocks[i].name) == 0) { break; } } } assert(i != num_saved_logical_blocks); logical_block[iblk].name = saved_logical_blocks[i].name; logical_block[iblk].clb_index = UNDEFINED; logical_block[iblk].clock_net = saved_logical_blocks[i].clock_net; logical_block[iblk].clock_net_tnode = NULL; logical_block[iblk].index = iblk; logical_block[iblk].input_net_tnodes = saved_logical_blocks[i].input_net_tnodes; logical_block[iblk].input_nets = saved_logical_blocks[i].input_nets; logical_block[iblk].model = saved_logical_blocks[i].model; logical_block[iblk].output_net_tnodes = saved_logical_blocks[i].output_net_tnodes; logical_block[iblk].output_nets = saved_logical_blocks[i].output_nets; logical_block[iblk].pb = pb; logical_block[iblk].truth_table = saved_logical_blocks[i].truth_table; logical_block[iblk].type = saved_logical_blocks[i].type; logical_block[iblk].used_input_pins = saved_logical_blocks[i].used_input_pins; saved_logical_blocks[i].name = NULL; saved_logical_blocks[i].input_net_tnodes = NULL; saved_logical_blocks[i].input_nets = NULL; saved_logical_blocks[i].output_net_tnodes = NULL; saved_logical_blocks[i].output_nets = NULL; saved_logical_blocks[i].truth_table = NULL; }