static void print_interconnect(int inode, int *column, int num_tabs, FILE * fpout) { /* 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. */ 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 = (char*)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 = (char*)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); } }
static void print_pb(FILE *fpout, t_pb * pb, int clb_index) { int column; int i, j, k; 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"); if (pb->parent_pb == NULL) { for (k = 1; k <= vpack_net[rr_node[node_index].net_num].num_sinks; k++) { /* output pads pre-pended with "out:", must remove */ if (logical_block[vpack_net[rr_node[node_index].net_num].node_block[k]].type == VPACK_OUTPAD && strcmp( logical_block[vpack_net[rr_node[node_index].net_num].node_block[k]].name + 4, vpack_net[rr_node[node_index].net_num].name) != 0) { fprintf(fpout, ".names clb_%d_rr_node_%d %s", clb_index, find_fanin_rr_node(pb, pb_type->ports[i].type, node_index), logical_block[vpack_net[rr_node[node_index].net_num].node_block[k]].name + 4); 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_pb(FILE *fpout, t_pb * pb, int pb_index, int tab_depth) { 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<clocks>\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</clocks>\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"); }