VPR-6.0
|
#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"
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 LINELENGTH 1024 |
Definition at line 19 of file output_blif.c.
#define TABLENGTH 1 |
Definition at line 20 of file output_blif.c.
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; }
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); }
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); } }
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); }
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 */ } } } } }
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); } } }
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; }