VPR-6.0

vpr/SRC/pack/output_clustering.c File Reference

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "util.h"
#include "vpr_types.h"
#include "globals.h"
#include "output_clustering.h"
#include "read_xml_arch_file.h"
Include dependency graph for output_clustering.c:

Go to the source code of this file.

Defines

#define LINELENGTH   1024
#define TAB_LENGTH   4

Functions

static void print_tabs (FILE *fpout, int num_tabs)
static void print_string (char *str_ptr, int *column, int num_tabs, FILE *fpout)
static void print_net_name (int inet, int *column, int num_tabs, FILE *fpout)
static void print_interconnect (int inode, int *column, int num_tabs, FILE *fpout)
static void print_open_pb_graph_node (t_pb_graph_node *pb_graph_node, int pb_index, boolean is_used, int tab_depth, FILE *fpout)
static void print_basic_pb (FILE *fpout, int bnum)
static void print_pb (FILE *fpout, t_pb *pb, int pb_index, int tab_depth)
static void print_clusters (t_block *clb, int num_clusters, FILE *fpout)
static void print_stats (t_block *clb, int num_clusters)
void output_clustering (t_block *clb, int num_clusters, boolean global_clocks, boolean *is_clock, char *out_fname, boolean skip_clustering)

Define Documentation

#define LINELENGTH   1024

Definition at line 18 of file output_clustering.c.

#define TAB_LENGTH   4

Definition at line 19 of file output_clustering.c.


Function Documentation

void output_clustering ( t_block clb,
int  num_clusters,
boolean  global_clocks,
boolean is_clock,
char *  out_fname,
boolean  skip_clustering 
)

This routine dumps out the output netlist in a format suitable for input to vpr. This routine also dumps out the internal structure of the cluster, in essentially a graph based format.

Definition at line 556 of file output_clustering.c.

{

    FILE *fpout;
    int bnum, netnum, column;

    fpout = fopen(out_fname, "w");

        fprintf(fpout, "<block name=\"%s\" instance=\"FPGA_packed_netlist[0]\">\n", out_fname);
        fprintf(fpout, "\t<inputs>\n\t\t");

        column = 2*TAB_LENGTH; /* Organize whitespace to ident data inside block */
    for(bnum = 0; bnum < num_logical_blocks; bnum++)
        {       
                if(logical_block[bnum].type == VPACK_INPAD) {
                        print_string(logical_block[bnum].name, &column, 2, fpout);
                }
        }
        fprintf(fpout, "\n\t</inputs>\n");
        fprintf(fpout, "\n\t<outputs>\n\t\t");

        column = 2*TAB_LENGTH;
    for(bnum = 0; bnum < num_logical_blocks; bnum++)
        {       
                if(logical_block[bnum].type == VPACK_OUTPAD) {
                        print_string(logical_block[bnum].name, &column, 2, fpout);
                }
        }
        fprintf(fpout, "\n\t</outputs>\n");

        column = 2*TAB_LENGTH;
    if(global_clocks)
        {
                fprintf(fpout, "\n\t<globals>\n\t\t");
    
            for(netnum = 0; netnum < num_logical_nets; netnum++)
                {
                    if(is_clock[netnum])
                        {
                                print_string(vpack_net[netnum].name, &column, 2, fpout);
                        }
                }
                fprintf(fpout, "\n\t</globals>\n\n");
        }

/* Print out all input and output pads. */

    for(bnum = 0; bnum < num_logical_blocks; bnum++)
        {
            switch (logical_block[bnum].type)
                {
                case VPACK_INPAD:
                case VPACK_OUTPAD:
                case VPACK_COMB:
                case VPACK_LATCH:
                    if(skip_clustering)
                        {
                                assert(0);
                        }
                    break;

                case VPACK_EMPTY:
                    printf("Error in output_netlist -- logical_block %d is VPACK_EMPTY.\n",
                           bnum);
                    exit(1);
                    break;

                default:
                    printf
                        ("Error in output_netlist.  Unexpected type %d for logical_block"
                         "%d.\n", logical_block[bnum].type, bnum);
                }
        }

    if(skip_clustering == FALSE)
                print_clusters(clb, num_clusters, fpout);

        fprintf(fpout, "</block>\n\n");

    fclose(fpout);

        print_stats(clb, num_clusters);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_basic_pb ( FILE *  fpout,
int  bnum 
) [static]

Prints out the pb connectivity. Used only when the -no_clustering option is selected -- prints out basically redundant connection info for a VPACK_LUT + FF logic logical_block.

Definition at line 285 of file output_clustering.c.

{
        assert(0);
}
static void print_clusters ( t_block clb,
int  num_clusters,
FILE *  fpout 
) [static]

Prints out one cluster (clb). Both the external pins and the internal connections are printed out.

Definition at line 416 of file output_clustering.c.

{
    int icluster;

        for(icluster = 0; icluster < num_clusters; icluster++)
        {
                rr_node = clb[icluster].pb->rr_graph;
                
                /* TODO: Must do check that total CLB pins match top-level pb pins, perhaps check this earlier? */

                print_pb(fpout, clb[icluster].pb, icluster, 1);
        }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_interconnect ( int  inode,
int *  column,
int  num_tabs,
FILE *  fpout 
) [static]

This routine prints out the vpack_net name (or open) and limits the length of a line to LINELENGTH characters by using \ to continue lines. net_num is the index of the vpack_net to be printed, while column points to the current printing column (column is both used and updated by this routine). fpout is the output file pointer.

Definition at line 99 of file output_clustering.c.

{

    char *str_ptr, *name;
        int prev_node, prev_edge;
        int len;

        if(rr_node[inode].net_num == OPEN) {
                print_string("open", column, num_tabs, fpout);
        } else {
                str_ptr = NULL;
                prev_node = rr_node[inode].prev_node;
                prev_edge = rr_node[inode].prev_edge;

                if(prev_node == OPEN && 
                        rr_node[inode].pb_graph_pin->port->parent_pb_type->num_modes == 0 &&
                        rr_node[inode].pb_graph_pin->port->type == OUT_PORT) { /* This is a primitive output */
                        print_net_name(rr_node[inode].net_num, column, num_tabs, fpout);
                } else {
                        name = rr_node[prev_node].pb_graph_pin->output_edges[prev_edge]->interconnect->name;
                        if(rr_node[prev_node].pb_graph_pin->port->parent_pb_type->depth >= rr_node[inode].pb_graph_pin->port->parent_pb_type->depth) {
                                /* Connections from siblings or children should have an explicit index, connections from parent does not need an explicit index */
                                len = strlen(rr_node[prev_node].pb_graph_pin->parent_node->pb_type->name) + 
                                        rr_node[prev_node].pb_graph_pin->parent_node->placement_index / 10 +
                                        strlen(rr_node[prev_node].pb_graph_pin->port->name) + 
                                        rr_node[prev_node].pb_graph_pin->pin_number / 10 +
                                        strlen(name) + 11;
                                str_ptr = my_malloc(len * sizeof(char));
                                sprintf(str_ptr, "%s[%d].%s[%d]->%s ", rr_node[prev_node].pb_graph_pin->parent_node->pb_type->name, 
                                        rr_node[prev_node].pb_graph_pin->parent_node->placement_index,
                                        rr_node[prev_node].pb_graph_pin->port->name, 
                                        rr_node[prev_node].pb_graph_pin->pin_number,
                                        name);
                        } else {
                                len = strlen(rr_node[prev_node].pb_graph_pin->parent_node->pb_type->name) + 
                                        strlen(rr_node[prev_node].pb_graph_pin->port->name) + 
                                        rr_node[prev_node].pb_graph_pin->pin_number / 10 +
                                        strlen(name) + 8;
                                str_ptr = my_malloc(len * sizeof(char));
                                sprintf(str_ptr, "%s.%s[%d]->%s ", rr_node[prev_node].pb_graph_pin->parent_node->pb_type->name, 
                                        rr_node[prev_node].pb_graph_pin->port->name, 
                                        rr_node[prev_node].pb_graph_pin->pin_number,
                                        name);
                        }                       
                        print_string(str_ptr, column, num_tabs, fpout);
                }
                if(str_ptr)
                        free(str_ptr);
        }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_net_name ( int  inet,
int *  column,
int  num_tabs,
FILE *  fpout 
) [static]

This routine prints out the vpack_net name (or open) and limits the length of a line to LINELENGTH characters by using \ to continue lines. net_num is the index of the vpack_net to be printed, while column points to the current printing column (column is both used and updated by this routine). fpout is the output file pointer.

Definition at line 75 of file output_clustering.c.

{

    char *str_ptr;

    if(inet == OPEN)
                str_ptr = "open";
    else
                str_ptr = vpack_net[inet].name;

    print_string(str_ptr, column, num_tabs, fpout);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_open_pb_graph_node ( t_pb_graph_node pb_graph_node,
int  pb_index,
boolean  is_used,
int  tab_depth,
FILE *  fpout 
) [static]

Definition at line 153 of file output_clustering.c.

                                                                                                                                  {
        int column = 0;
        int i, j, k, m;
        const t_pb_type * pb_type, * child_pb_type;
        t_mode * mode = NULL;
        int prev_edge, prev_node;
        t_pb_graph_pin *pb_graph_pin;
        int mode_of_edge, port_index, node_index;

        mode_of_edge = UNDEFINED;

        pb_type = pb_graph_node->pb_type;

        print_tabs(fpout, tab_depth);

        if(is_used) {
                /* Determine mode if applicable */
                port_index = 0;                 
                for(i = 0; i < pb_type->num_ports; i++) {
                        if(pb_type->ports[i].type == OUT_PORT) {
                                assert(!pb_type->ports[i].is_clock);
                                for(j = 0; j < pb_type->ports[i].num_pins; j++) {
                                        node_index = pb_graph_node->output_pins[port_index][j].pin_count_in_cluster;
                                        if(pb_type->num_modes > 0 && rr_node[node_index].net_num != OPEN) {
                                                prev_edge = rr_node[node_index].prev_edge;
                                                prev_node = rr_node[node_index].prev_node;
                                                pb_graph_pin = rr_node[prev_node].pb_graph_pin;
                                                mode_of_edge = pb_graph_pin->output_edges[prev_edge]->interconnect->parent_mode_index;
                                                assert(mode == NULL || &pb_type->modes[mode_of_edge] == mode);
                                                mode = &pb_type->modes[mode_of_edge];
                                        }
                                }
                                port_index++;
                        }
                }

                assert(mode != NULL && mode_of_edge != UNDEFINED);
                fprintf(fpout, "<block name=\"open\" instance=\"%s[%d]\" mode=\"%s\">\n", pb_graph_node->pb_type->name, pb_index, mode->name);

                print_tabs(fpout, tab_depth);
                fprintf(fpout, "\t<inputs>\n");
                port_index = 0;
                for(i = 0; i < pb_type->num_ports; i++) {
                        if(!pb_type->ports[i].is_clock && pb_type->ports[i].type == IN_PORT) {
                                print_tabs(fpout, tab_depth);
                                fprintf(fpout, "\t\t<port name=\"%s\">", pb_graph_node->pb_type->ports[i].name);
                                for(j = 0; j < pb_type->ports[i].num_pins; j++) {
                                        node_index = pb_graph_node->input_pins[port_index][j].pin_count_in_cluster;
                                        print_interconnect(node_index, &column, tab_depth + 2, fpout);
                                }
                                fprintf(fpout, "</port>\n");
                                port_index++;
                        }
                }
                print_tabs(fpout, tab_depth);
                fprintf(fpout, "\t</inputs>\n");
                
                column = tab_depth * TAB_LENGTH + 8;    /* Next column I will write to. */
                print_tabs(fpout, tab_depth);
                fprintf(fpout, "\t<outputs>\n");
                port_index = 0;                 
                for(i = 0; i < pb_type->num_ports; i++) {
                        if(pb_type->ports[i].type == OUT_PORT) {
                                print_tabs(fpout, tab_depth);
                                fprintf(fpout, "\t\t<port name=\"%s\">", pb_graph_node->pb_type->ports[i].name);
                                assert(!pb_type->ports[i].is_clock);
                                for(j = 0; j < pb_type->ports[i].num_pins; j++) {
                                        node_index = pb_graph_node->output_pins[port_index][j].pin_count_in_cluster;
                                        print_interconnect(node_index, &column, tab_depth + 2, fpout);
                                }
                                fprintf(fpout, "</port>\n");                    
                                port_index++;
                        }
                }
                print_tabs(fpout, tab_depth);
                fprintf(fpout, "\t</outputs>\n");

                column = tab_depth * TAB_LENGTH + 8;    /* Next column I will write to. */
                print_tabs(fpout, tab_depth);
                fprintf(fpout, "\t<globals>\n");
                port_index = 0;                 
                for(i = 0; i < pb_type->num_ports; i++) {
                        if(pb_type->ports[i].is_clock && pb_type->ports[i].type == IN_PORT) {
                                print_tabs(fpout, tab_depth);
                                fprintf(fpout, "\t\t<port name=\"%s\">", pb_graph_node->pb_type->ports[i].name);
                                for(j = 0; j < pb_type->ports[i].num_pins; j++) {
                                        node_index = pb_graph_node->clock_pins[port_index][j].pin_count_in_cluster;
                                        print_interconnect(node_index, &column, tab_depth + 2, fpout);
                                }
                                fprintf(fpout, "</port>\n");
                                port_index++;
                        }
                }
                print_tabs(fpout, tab_depth);
                fprintf(fpout, "\t</globals>\n");

                if(pb_type->num_modes > 0) {
                        for(i = 0; i < mode->num_pb_type_children; i++) {
                                child_pb_type = &mode->pb_type_children[i];
                                for(j = 0; j < mode->pb_type_children[i].num_pb; j++) {
                                        port_index = 0;
                                        is_used = FALSE;
                                        for(k = 0; k < child_pb_type->num_ports && !is_used; k++) {
                                                if(child_pb_type->ports[k].type == OUT_PORT) {
                                                        for(m = 0; m < child_pb_type->ports[k].num_pins; m++) {
                                                                node_index = pb_graph_node->child_pb_graph_nodes[mode_of_edge][i][j].output_pins[port_index][m].pin_count_in_cluster;
                                                                if(rr_node[node_index].net_num != OPEN) {
                                                                        is_used = TRUE;
                                                                        break;
                                                                }
                                                        }
                                                        port_index++;
                                                }
                                        }
                                        print_open_pb_graph_node(&pb_graph_node->child_pb_graph_nodes[mode_of_edge][i][j], j, is_used, tab_depth+1, fpout);
                                }
                        }
                }
                        
                print_tabs(fpout, tab_depth);
                fprintf(fpout, "</block>\n");
        } else {
                fprintf(fpout, "<block name=\"open\" instance=\"%s[%d]\"/>\n", pb_graph_node->pb_type->name, pb_index);
        }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_pb ( FILE *  fpout,
t_pb pb,
int  pb_index,
int  tab_depth 
) [static]

Definition at line 293 of file output_clustering.c.

                                                                          {

        int column;
        int i, j, k, m;
        const t_pb_type *pb_type, *child_pb_type;
        t_pb_graph_node *pb_graph_node;
        t_mode *mode;
        int port_index, node_index;
        boolean is_used;

        pb_type = pb->pb_graph_node->pb_type;
        pb_graph_node = pb->pb_graph_node;
        mode = &pb_type->modes[pb->mode];
        column = tab_depth * TAB_LENGTH + 8;    /* Next column I will write to. */
        print_tabs(fpout, tab_depth);
        if(pb_type->num_modes == 0) {
                fprintf(fpout, "<block name=\"%s\" instance=\"%s[%d]\">\n", pb->name, pb_type->name, pb_index);
        } else {
                fprintf(fpout, "<block name=\"%s\" instance=\"%s[%d]\" mode=\"%s\">\n", pb->name, pb_type->name, pb_index, mode->name);
        }
        
        print_tabs(fpout, tab_depth);
        fprintf(fpout, "\t<inputs>\n");
        port_index = 0;
        for(i = 0; i < pb_type->num_ports; i++) {
                if(!pb_type->ports[i].is_clock && pb_type->ports[i].type == IN_PORT) {
                        print_tabs(fpout, tab_depth);
                        fprintf(fpout, "\t\t<port name=\"%s\">", pb_graph_node->pb_type->ports[i].name);
                        for(j = 0; j < pb_type->ports[i].num_pins; j++) {
                                node_index = pb->pb_graph_node->input_pins[port_index][j].pin_count_in_cluster;
                                if(pb_type->parent_mode == NULL) {
                                        print_net_name(rr_node[node_index].net_num, &column, tab_depth, fpout);
                                } else {
                                        print_interconnect(node_index, &column, tab_depth + 2, fpout);
                                }
                        }
                        fprintf(fpout, "</port>\n");
                        port_index++;
                }
        }
        print_tabs(fpout, tab_depth);
        fprintf(fpout, "\t</inputs>\n");
        
        column = tab_depth * TAB_LENGTH + 8;    /* Next column I will write to. */
        print_tabs(fpout, tab_depth);
        fprintf(fpout, "\t<outputs>\n");
        port_index = 0;                 
        for(i = 0; i < pb_type->num_ports; i++) {
                if(pb_type->ports[i].type == OUT_PORT) {
                        assert(!pb_type->ports[i].is_clock);
                        print_tabs(fpout, tab_depth);
                        fprintf(fpout, "\t\t<port name=\"%s\">", pb_graph_node->pb_type->ports[i].name);
                        for(j = 0; j < pb_type->ports[i].num_pins; j++) {
                                node_index = pb->pb_graph_node->output_pins[port_index][j].pin_count_in_cluster;
                                print_interconnect(node_index, &column, tab_depth + 2, fpout);                          
                        }
                        fprintf(fpout, "</port>\n");
                        port_index++;
                }
        }
        print_tabs(fpout, tab_depth);
        fprintf(fpout, "\t</outputs>\n");

        column = tab_depth * TAB_LENGTH + 8;    /* Next column I will write to. */
        print_tabs(fpout, tab_depth);
        fprintf(fpout, "\t<globals>\n");
        port_index = 0;                 
        for(i = 0; i < pb_type->num_ports; i++) {
                if(pb_type->ports[i].is_clock && pb_type->ports[i].type == IN_PORT) {
                        print_tabs(fpout, tab_depth);
                        fprintf(fpout, "\t\t<port name=\"%s\">", pb_graph_node->pb_type->ports[i].name);
                        for(j = 0; j < pb_type->ports[i].num_pins; j++) {
                                node_index = pb->pb_graph_node->clock_pins[port_index][j].pin_count_in_cluster;
                                if(pb_type->parent_mode == NULL) {
                                        print_net_name(rr_node[node_index].net_num, &column, tab_depth, fpout);
                                } else {
                                        print_interconnect(node_index, &column, tab_depth + 2, fpout);
                                }
                        }
                        fprintf(fpout, "</port>\n");
                        port_index++;
                }
        }
        print_tabs(fpout, tab_depth);
        fprintf(fpout, "\t</globals>\n");

        if(pb_type->num_modes > 0) {
                for(i = 0; i < mode->num_pb_type_children; i++) {
                        for(j = 0; j < mode->pb_type_children[i].num_pb; j++) {
                                /* If child pb is not used but routing is used, I must print things differently */
                                if((pb->child_pbs[i] != NULL) && 
                                        (pb->child_pbs[i][j].name != NULL)) {
                                        print_pb(fpout, &pb->child_pbs[i][j], j, tab_depth + 1);
                                } else {
                                        is_used = FALSE;
                                        child_pb_type = &mode->pb_type_children[i];
                                        port_index = 0;
                                                
                                        for(k = 0; k < child_pb_type->num_ports && !is_used; k++) {
                                                if(child_pb_type->ports[k].type == OUT_PORT) {
                                                        for(m = 0; m < child_pb_type->ports[k].num_pins; m++) {
                                                                node_index = pb_graph_node->child_pb_graph_nodes[pb->mode][i][j].output_pins[port_index][m].pin_count_in_cluster;
                                                                if(rr_node[node_index].net_num != OPEN) {
                                                                        is_used = TRUE;
                                                                        break;
                                                                }
                                                        }
                                                        port_index++;
                                                }
                                        }
                                        print_open_pb_graph_node(&pb_graph_node->child_pb_graph_nodes[pb->mode][i][j], j, is_used, tab_depth+1, fpout);
                                }
                        }
                }
        }
        print_tabs(fpout, tab_depth);
        fprintf(fpout, "</block>\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_stats ( t_block clb,
int  num_clusters 
) [static]

Prints out one cluster (clb). Both the external pins and the internal connections are printed out.

Definition at line 437 of file output_clustering.c.

                             {

    int ipin, icluster, itype, inet, iblk, num_pins, i;
        int MAX_LUT_INPUTS;
        int unabsorbable_ffs, total_ffs;
        int num_luts_total;
        int total_nets_absorbed;
    boolean* nets_absorbed;
        
        int *num_clb_types, *num_clb_inputs_used, *num_clb_outputs_used, *num_lut_of_size;
        
        nets_absorbed = NULL;
        num_clb_types = num_clb_inputs_used = num_clb_outputs_used = NULL;

        num_clb_types = (int*)my_calloc(num_types, sizeof(int));
        num_clb_inputs_used = (int*)my_calloc(num_types, sizeof(int));
        num_clb_outputs_used = (int*)my_calloc(num_types, sizeof(int));

        MAX_LUT_INPUTS = 0;
        for(iblk = 0; iblk < num_logical_blocks; iblk++) {
                if(strcmp(logical_block[iblk].model->name, "names") == 0) {
                        MAX_LUT_INPUTS = logical_block[iblk].model->inputs->size;
                        break;
                }
        }
        num_lut_of_size = (int*)my_calloc(MAX_LUT_INPUTS + 1, sizeof(int));

        
        nets_absorbed = (boolean *)my_calloc(num_logical_nets, sizeof(boolean));
        for(inet = 0; inet < num_logical_nets; inet++) {
                nets_absorbed[inet] = TRUE;
        }

        unabsorbable_ffs = 0;
        total_ffs = 0;
        for(iblk = 0; iblk < num_logical_blocks; iblk++) {
                if(strcmp(logical_block[iblk].model->name, "names") == 0) {
                        num_pins = 0;
                        for(ipin = 0; ipin < logical_block[iblk].model->inputs->size; ipin++) {
                                if(logical_block[iblk].input_nets[0][ipin] != OPEN) {
                                        num_pins++;
                                }
                        }
                        num_lut_of_size[num_pins]++;
                } else if(strcmp(logical_block[iblk].model->name, "latch") == 0) {
                        if(vpack_net[logical_block[iblk].input_nets[0][0]].num_sinks > 1 ||
                                strcmp(logical_block[vpack_net[logical_block[iblk].input_nets[0][0]].node_block[0]].model->name, "names") != 0) {
                                        unabsorbable_ffs++;
                        }
                        total_ffs++;
                }
        }
        printf("\n");
        num_luts_total = 0;
        for(i = 0; i <= MAX_LUT_INPUTS; i++) {
                printf("%d LUTs of size %d\n", num_lut_of_size[i], i);
                num_luts_total += num_lut_of_size[i];
        }
        printf("%d LUTs in input netlist\n", num_luts_total);
        printf("%d FFs in input netlist\n", total_ffs);
        printf("%d FFs in input netlist not absorbable\n", unabsorbable_ffs);


        /* Counters used only for statistics purposes. */

    for(icluster = 0; icluster < num_clusters; icluster++)
        {
                for(ipin = 0; ipin < clb[icluster].type->num_pins; ipin++) {
                        if(clb[icluster].nets[ipin] != OPEN) {
                                nets_absorbed[clb[icluster].nets[ipin]] = FALSE;
                                if(clb[icluster].type->class_inf[clb[icluster].type->pin_class[ipin]].type == RECEIVER) {
                                        num_clb_inputs_used[clb[icluster].type->index]++;
                                } else if(clb[icluster].type->class_inf[clb[icluster].type->pin_class[ipin]].type == DRIVER){
                                        num_clb_outputs_used[clb[icluster].type->index]++;
                                }
                        }
                }               
                num_clb_types[clb[icluster].type->index]++;
        }

        for(itype = 0; itype < num_types; itype++) {
                if(num_clb_types[itype] == 0) {
                        printf("\t%s: # blocks %d, avg # input + clock pins used %g, avg # output pins used %g\n", 
                                type_descriptors[itype].name,
                                num_clb_types[itype],
                            0.0,
                                0.0);
                } else {
                        printf("\t%s: # blocks %d, avg # input + clock pins used %g, avg # output pins used %g\n", 
                                type_descriptors[itype].name,
                                num_clb_types[itype],
                            (float)num_clb_inputs_used[itype] / (float)num_clb_types[itype],
                                (float)num_clb_outputs_used[itype] / (float)num_clb_types[itype]);
                }
        }
        
        total_nets_absorbed = 0;
        for(inet = 0; inet < num_logical_nets; inet++) {
                if(nets_absorbed[inet] == TRUE) {
                        total_nets_absorbed++;
                }
        }
    printf("Absorbed logical nets %d out of %d nets, %d nets not absorbed\n", total_nets_absorbed, num_logical_nets, num_logical_nets - total_nets_absorbed);
        free(nets_absorbed);
        free(num_lut_of_size);
        free(num_clb_types);
        free(num_clb_inputs_used);
        free(num_clb_outputs_used);
        /* TODO: print more stats */
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_string ( char *  str_ptr,
int *  column,
int  num_tabs,
FILE *  fpout 
) [static]

Prints string without making any lines longer than LINELENGTH. Column points to the column in which the next character will go (both used and updated), and fpout points to the output file.

Definition at line 38 of file output_clustering.c.

{

    int len;

    len = strlen(str_ptr);
    if(len + 3 > LINELENGTH)
        {
            printf
                ("Error in print_string: String %s is too long for desired\n"
                 "maximum line length.\n", str_ptr);
            exit(1);
        }

    if(*column + len + 2 > LINELENGTH)
        {
            fprintf(fpout, "\n");
                print_tabs(fpout, num_tabs);
            *column = num_tabs * TAB_LENGTH;
        }

    fprintf(fpout, "%s ", str_ptr);
    *column += len + 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_tabs ( FILE *  fpout,
int  num_tabs 
) [static]

Definition at line 26 of file output_clustering.c.

                                                  {
        int i;
        for(i = 0; i < num_tabs; i++) {
                fprintf(fpout, "\t");
        }
}

Here is the caller graph for this function: