|
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"
Include dependency graph for read_netlist.c: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;
}
Here is the call graph for this function:
Here is the caller graph for this function:| 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;
}
Here is the call graph for this function:
Here is the caller graph for this function:| 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));
}
}
}
Here is the call graph for this function:
Here is the caller graph for this function:| 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;
}
}
Here is the caller graph for this function:| 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);
}
Here is the caller graph for this function:| 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);
}
Here is the caller graph for this function:| 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);
}
Here is the call graph for this function:
Here is the caller graph for this function:| 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);
}
}
Here is the call graph for this function:
Here is the caller graph for this function:| 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)++;
}
}
Here is the caller graph for this function:| 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);
}
}
Here is the call graph for this function:
Here is the caller graph for this function:| 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;
}
}
}
}
}
}
Here is the caller graph for this function:| 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
}
Here is the call graph for this function:
Here is the caller graph for this function:| 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;
}
}
}
}
Here is the call graph for this function:
Here is the caller graph for this function:| 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;
}
}
}
Here is the call graph for this function:| 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] |
Here is the caller graph for this function:| 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;
}
Here is the call graph for this function:
Here is the caller graph for this function:| 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;
}
Here is the caller graph for this function: