VPR-6.0

vpr/SRC/pack/output_blif.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_blif.h"
Include dependency graph for output_blif.c:

Go to the source code of this file.

Defines

#define LINELENGTH   1024
#define TABLENGTH   1

Functions

static void print_string (char *str_ptr, int *column, FILE *fpout)
static void print_net_name (int inet, int *column, FILE *fpout)
static int find_fanin_rr_node (t_pb *cur_pb, enum PORTS type, int rr_node_index)
static void print_primitive (FILE *fpout, int iblk)
static void print_pb (FILE *fpout, t_pb *pb, int clb_index)
static void print_clusters (t_block *clb, int num_clusters, FILE *fpout)
void output_blif (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 19 of file output_blif.c.

#define TABLENGTH   1

Definition at line 20 of file output_blif.c.


Function Documentation

static int find_fanin_rr_node ( t_pb cur_pb,
enum PORTS  type,
int  rr_node_index 
) [static]

finds first fanin rr_node

Definition at line 82 of file output_blif.c.

                                                                                {
        t_pb *parent, *sibling, *child;
        int net_num, irr_node;
        int i, j, k, ichild_type, ichild_inst;
        int hack_empty_route_through;
        t_pb_graph_node *hack_empty_pb_graph_node;

        hack_empty_route_through = OPEN;

        net_num = rr_node[rr_node_index].net_num;

        parent = cur_pb->parent_pb;

        if(net_num == OPEN) {
                return OPEN;
        }

        if (type == IN_PORT) {
                /* check parent inputs for valid connection */
                for(i = 0; i < parent->pb_graph_node->num_input_ports; i++) {
                        for(j = 0; j < parent->pb_graph_node->num_input_pins[i]; j++) {
                                irr_node = parent->pb_graph_node->input_pins[i][j].pin_count_in_cluster;
                                if(rr_node[irr_node].net_num == net_num) {
                                        if(cur_pb->pb_graph_node->pb_type->model && strcmp(cur_pb->pb_graph_node->pb_type->model->name, MODEL_LATCH) == 0) {
                                                /* HACK: latches are special becuase LUTs can be set to route-through mode for them 
                                                   I will assume that the input to a LATCH can always come from a parent input pin
                                                   this only works for hierarchical soft logic structures that follow LUT -> LATCH design
                                                   must do it better later
                                                */
                                                return irr_node;
                                        }
                                        hack_empty_route_through = irr_node;
                                        for(k = 0; k < rr_node[irr_node].num_edges; k++) {
                                                if(rr_node[irr_node].edges[k] == rr_node_index) {
                                                        return irr_node;
                                                }
                                        }
                                }
                        }
                }
                /* check parent clocks for valid connection */
                for(i = 0; i < parent->pb_graph_node->num_clock_ports; i++) {
                        for(j = 0; j < parent->pb_graph_node->num_clock_pins[i]; j++) {
                                irr_node = parent->pb_graph_node->clock_pins[i][j].pin_count_in_cluster;
                                if(rr_node[irr_node].net_num == net_num) {
                                        for(k = 0; k < rr_node[irr_node].num_edges; k++) {
                                                if(rr_node[irr_node].edges[k] == rr_node_index) {
                                                        return irr_node;
                                                }
                                        }
                                }
                        }
                }
                /* check siblings for connection */
                if(parent) {
                        for(ichild_type = 0; ichild_type < parent->pb_graph_node->pb_type->modes[parent->mode].num_pb_type_children; ichild_type++) {
                                for(ichild_inst = 0; ichild_inst < parent->pb_graph_node->pb_type->modes[parent->mode].pb_type_children[ichild_type].num_pb; ichild_inst++) {
                                        if(parent->child_pbs[ichild_type] && parent->child_pbs[ichild_type][ichild_inst].name != NULL) {
                                                sibling = &parent->child_pbs[ichild_type][ichild_inst];
                                                for(i = 0; i < sibling->pb_graph_node->num_output_ports; i++) {
                                                        for(j = 0; j < sibling->pb_graph_node->num_output_pins[i]; j++) {
                                                                irr_node = sibling->pb_graph_node->output_pins[i][j].pin_count_in_cluster;
                                                                if(rr_node[irr_node].net_num == net_num) {
                                                                        for(k = 0; k < rr_node[irr_node].num_edges; k++) {
                                                                                if(rr_node[irr_node].edges[k] == rr_node_index) {
                                                                                        return irr_node;
                                                                                }
                                                                        }
                                                                }
                                                        }
                                                }                                               
                                        } else {
                                                /* hack just in case routing is down through an empty cluster */
                                                hack_empty_pb_graph_node = &parent->pb_graph_node->child_pb_graph_nodes[ichild_type][0][ichild_inst];
                                                for(i = 0; i < hack_empty_pb_graph_node->num_output_ports; i++) {
                                                        for(j = 0; j < hack_empty_pb_graph_node->num_output_pins[i]; j++) {
                                                                irr_node = hack_empty_pb_graph_node->output_pins[i][j].pin_count_in_cluster;
                                                                if(rr_node[irr_node].net_num == net_num) {
                                                                        for(k = 0; k < rr_node[irr_node].num_edges; k++) {
                                                                                if(rr_node[irr_node].edges[k] == rr_node_index) {
                                                                                        return irr_node;
                                                                                }
                                                                        }
                                                                }
                                                        }
                                                }                       
                                        }
                                }
                        }
                }
        } else {
                assert(type == OUT_PORT);
                
                /* check children for connection */
                for(ichild_type = 0; ichild_type < cur_pb->pb_graph_node->pb_type->modes[cur_pb->mode].num_pb_type_children; ichild_type++) {
                        for(ichild_inst = 0; ichild_inst < cur_pb->pb_graph_node->pb_type->modes[cur_pb->mode].pb_type_children[ichild_type].num_pb; ichild_inst++) {
                                if(cur_pb->child_pbs[ichild_type] && cur_pb->child_pbs[ichild_type][ichild_inst].name != NULL) {
                                        child = &cur_pb->child_pbs[ichild_type][ichild_inst];
                                        for(i = 0; i < child->pb_graph_node->num_output_ports; i++) {
                                                for(j = 0; j < child->pb_graph_node->num_output_pins[i]; j++) {
                                                        irr_node = child->pb_graph_node->output_pins[i][j].pin_count_in_cluster;
                                                        if(rr_node[irr_node].net_num == net_num) {
                                                                for(k = 0; k < rr_node[irr_node].num_edges; k++) {
                                                                        if(rr_node[irr_node].edges[k] == rr_node_index) {
                                                                                return irr_node;
                                                                        }
                                                                }
                                                                hack_empty_route_through = irr_node;
                                                        }
                                                }
                                        }                                               
                                }
                        }
                }

                /* If not in children, check current pb inputs for valid connection */
                for(i = 0; i < cur_pb->pb_graph_node->num_input_ports; i++) {
                        for(j = 0; j < cur_pb->pb_graph_node->num_input_pins[i]; j++) {
                                irr_node = cur_pb->pb_graph_node->input_pins[i][j].pin_count_in_cluster;
                                if(rr_node[irr_node].net_num == net_num) {
                                        hack_empty_route_through = irr_node;
                                        for(k = 0; k < rr_node[irr_node].num_edges; k++) {
                                                if(rr_node[irr_node].edges[k] == rr_node_index) {
                                                        return irr_node;
                                                }
                                        }
                                }
                        }
                }
        }

        /* TODO: Once I find a way to output routing in empty blocks then code should never reach here, for now, return OPEN */
        printf("Can't find connecting net %s #%d for pb %s type %s\n", vpack_net[net_num].name, net_num, 
                cur_pb->name, cur_pb->pb_graph_node->pb_type->name);
                
        assert(hack_empty_route_through != OPEN);
        return hack_empty_route_through;
}

Here is the caller graph for this function:

void output_blif ( 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 403 of file output_blif.c.

{


    FILE *fpout;
    int bnum, column;
        struct s_linked_vptr *p_io_removed;

        fpout = my_fopen(out_fname, "w", 0);

        column = 0;
        fprintf(fpout, ".model %s\n", blif_circuit_name);
                

        /* Print out all input and output pads. */
        fprintf(fpout, "\n.inputs ");
    for(bnum = 0; bnum < num_logical_blocks; bnum++)
        {       
                if(logical_block[bnum].type == VPACK_INPAD) {
                        print_string(logical_block[bnum].name, &column, fpout);
                }
        }
        p_io_removed = circuit_p_io_removed;
        while(p_io_removed) {
                print_string((char*)p_io_removed->data_vptr, &column, fpout);
                p_io_removed = p_io_removed->next;
        }

        column = 0;
        fprintf(fpout, "\n.outputs ");
        for(bnum = 0; bnum < num_logical_blocks; bnum++)
        {       
                if(logical_block[bnum].type == VPACK_OUTPAD) {
                        /* remove output prefix "out:" */
                        print_string(logical_block[bnum].name + 4, &column, fpout);
                }
        }

        column = 0;

        fprintf(fpout, "\n\n");
        
        print_clusters(clb, num_clusters, fpout);
        fprintf(fpout, "\n.end\n");

    fclose(fpout);
}

Here is the call graph for this function:

Here is the caller graph for this function:

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 379 of file output_blif.c.

{
    int icluster;
    
        for(icluster = 0; icluster < num_clusters; icluster++)
        {
                rr_node = clb[icluster].pb->rr_graph;
#if 0
                dump_rr_graph("cluster_rr_graph.echo"); 
#endif
                if(clb[icluster].type != IO_TYPE)
                        print_pb(fpout, clb[icluster].pb, icluster);
        }
}

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,
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 67 of file output_blif.c.

{
    char *str_ptr;

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

    print_string(str_ptr, column, fpout);
}

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  clb_index 
) [static]

Definition at line 305 of file output_blif.c.

                                                            {

        int column;
        int i, j;
        const t_pb_type *pb_type;
        t_mode *mode;
        int in_port_index, out_port_index, node_index;

        pb_type = pb->pb_graph_node->pb_type;
        mode = &pb_type->modes[pb->mode];
        column = 0;     
        if(pb_type->num_modes == 0) {
                print_primitive(fpout, pb->logical_block);
        } else {
                in_port_index = 0;
                out_port_index = 0;
                for(i = 0; i < pb_type->num_ports; i++) {
                        if(!pb_type->ports[i].is_clock) {
                                for(j = 0; j < pb_type->ports[i].num_pins; j++) {
                                        /* print .blif buffer to represent routing */
                                        column = 0;
                                        if(pb_type->ports[i].type == OUT_PORT) {
                                                node_index = pb->pb_graph_node->output_pins[out_port_index][j].pin_count_in_cluster;
                                                if(rr_node[node_index].net_num != OPEN) {
                                                        fprintf(fpout, ".names clb_%d_rr_node_%d ",
                                                                clb_index, find_fanin_rr_node(pb, pb_type->ports[i].type, node_index));
                                                        if(pb->parent_pb) {
                                                                fprintf(fpout, "clb_%d_rr_node_%d ", clb_index, node_index);
                                                        } else {
                                                                print_net_name(rr_node[node_index].net_num, &column, fpout);
                                                        }
                                                        fprintf(fpout, "\n1 1\n");
                                                }
                
                                        } else { 
                                                node_index = pb->pb_graph_node->input_pins[in_port_index][j].pin_count_in_cluster;
                                                if(rr_node[node_index].net_num != OPEN) {
                                                
                                                        fprintf(fpout, ".names ");
                                                        if(pb->parent_pb) {
                                                                fprintf(fpout, "clb_%d_rr_node_%d ", clb_index, find_fanin_rr_node(pb, pb_type->ports[i].type, node_index));
                                                        } else {
                                                                print_net_name(rr_node[node_index].net_num, &column, fpout);
                                                        }
                                                        fprintf(fpout, "clb_%d_rr_node_%d", clb_index, node_index);
                                                        fprintf(fpout, "\n1 1\n");
                                                }
                                        }
                                }
                        }
                        if(pb_type->ports[i].type == OUT_PORT) {
                                out_port_index++;
                        } else {
                                in_port_index++;
                        }                               
                }
                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], clb_index);
                                } else {
                                        /* do nothing for now, we'll print something later if needed */
                                }
                        }
                }
        }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_primitive ( FILE *  fpout,
int  iblk 
) [static]

Definition at line 221 of file output_blif.c.

                                                   {
        t_pb *pb;
        int clb_index;
        int i, j, column, node_index;
        int in_port_index, out_port_index, clock_port_index;
        struct s_linked_vptr *truth_table;
        const t_pb_type *pb_type;

        pb = logical_block[iblk].pb;
        pb_type = pb->pb_graph_node->pb_type;
        clb_index = logical_block[iblk].clb_index;


        column = 7;
        if(logical_block[iblk].type == VPACK_INPAD || logical_block[iblk].type == VPACK_OUTPAD) {
                /* do nothing */
        } else if(logical_block[iblk].type == VPACK_LATCH) {
                fprintf(fpout, ".latch ");
                
                in_port_index = 0;
                out_port_index = 0;
                clock_port_index = 0;
                for(i = 0; i < pb_type->num_ports; i++) {
                        if(pb_type->ports[i].type == IN_PORT && pb_type->ports[i].is_clock == FALSE) {
                                assert(pb_type->ports[i].num_pins == 1);
                                assert(logical_block[iblk].input_nets[i][0] != OPEN);
                                node_index = pb->pb_graph_node->input_pins[in_port_index][0].pin_count_in_cluster;
                                fprintf(fpout, "clb_%d_rr_node_%d ", clb_index, find_fanin_rr_node(pb, pb_type->ports[i].type, node_index));
                                in_port_index++;
                        }
                }
                for(i = 0; i < pb_type->num_ports; i++) {
                        if(pb_type->ports[i].type == OUT_PORT) {
                                assert(pb_type->ports[i].num_pins == 1 && out_port_index == 0);
                                node_index = pb->pb_graph_node->output_pins[out_port_index][0].pin_count_in_cluster;
                                fprintf(fpout, "clb_%d_rr_node_%d re ", clb_index, node_index);
                                out_port_index++;
                        }
                }
                for(i = 0; i < pb_type->num_ports; i++) {
                        if(pb_type->ports[i].type == IN_PORT && pb_type->ports[i].is_clock == TRUE) {
                                assert(logical_block[iblk].clock_net != OPEN);
                                node_index = pb->pb_graph_node->clock_pins[clock_port_index][0].pin_count_in_cluster;
                                fprintf(fpout, "clb_%d_rr_node_%d 2", clb_index, find_fanin_rr_node(pb, pb_type->ports[i].type, node_index));
                                clock_port_index++;
                        }
                }
                fprintf(fpout, "\n");                           
        } else if(logical_block[iblk].type == VPACK_COMB) {
                if(strcmp(logical_block[iblk].model->name, ".names")) {
                        fprintf(fpout, ".names ");
                        in_port_index = 0;
                        out_port_index = 0;
                        for(i = 0; i < pb_type->num_ports; i++) {
                                if(pb_type->ports[i].type == IN_PORT && pb_type->ports[i].is_clock == FALSE) {
                                        for(j = 0; j < pb_type->ports[i].num_pins; j++) {
                                                if(logical_block[iblk].input_nets[i][j] != OPEN) {
                                                        node_index = pb->pb_graph_node->input_pins[in_port_index][j].pin_count_in_cluster;
                                                        fprintf(fpout, "clb_%d_rr_node_%d ", clb_index, find_fanin_rr_node(pb, pb_type->ports[i].type, node_index));
                                                }
                                        }
                                        in_port_index++;
                                }
                        }
                        for(i = 0; i < pb_type->num_ports; i++) {
                                if(pb_type->ports[i].type == OUT_PORT) {
                                        for(j = 0; j < pb_type->ports[i].num_pins; j++) {
                                                node_index = pb->pb_graph_node->output_pins[out_port_index][j].pin_count_in_cluster;
                                                fprintf(fpout, "clb_%d_rr_node_%d\n", clb_index, node_index);
                                        }
                                        out_port_index++;
                                }
                        }
                        truth_table = logical_block[iblk].truth_table;
                        while(truth_table) {
                                fprintf(fpout, "%s\n", (char *)truth_table->data_vptr);
                                truth_table = truth_table->next;
                        }
                } else {
                        assert(0);
                }
        }
}

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,
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 33 of file output_blif.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");
            *column = TABLENGTH;
        }

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

Here is the caller graph for this function: