📄 rr_graph2.c
字号:
/* Returns the segment number (coordinate along the channel) at which this * * segment ends. For a segment spanning clbs from 1 to 4, seg_end is 4. * * max_end is the maximum dimension of the FPGA in this direction -- * * either nx or ny. */ int seg_end, length, norm_start; length = seg_details[itrack].length; if (seg_start != 1) { seg_end = min (seg_start + length - 1, max_end); } else if (seg_details[itrack].longline) { seg_end = max_end; } else { /* Short segment, at the left edge of array. */ norm_start = seg_details[itrack].start; seg_end = length - (length + 1 + chan_num - norm_start) % length; } return (seg_end);}int get_xtrack_to_clb_ipin_edges (int tr_istart, int tr_iend, int tr_j, int itrack, int iside, t_linked_edge **edge_list_ptr, struct s_ivec **tracks_to_clb_ipin, int nodes_per_chan, int **rr_node_indices, t_seg_details *seg_details_x, int wire_to_ipin_switch) {/* This routine counts how many connections should be made from this segment * * to the clbs above (TOP) or below (BOTTOM) it. It also adds them to the * * edge linked list and updates edge_list_ptr. */ int clb_j, iconn, num_conn, max_conn, i, ipin, to_node; t_linked_edge *edge_list_head;/* Side is from the *track's* perspective */ if (iside == BOTTOM) { clb_j = tr_j; } else if (iside == TOP) { clb_j = tr_j + 1; } else { printf ("Error in get_xtrack_to_clb_ipin_edges: Unknown iside: %d.\n", iside); exit (1); } edge_list_head = *edge_list_ptr; num_conn = 0; max_conn = tracks_to_clb_ipin[itrack][iside].nelem; for (i=tr_istart;i<=tr_iend;i++) { if (is_cbox (i, tr_j, itrack, seg_details_x)) { for (iconn=0;iconn<max_conn;iconn++) { ipin = tracks_to_clb_ipin[itrack][iside].list[iconn]; to_node = get_rr_node_index (i, clb_j, IPIN, ipin, nodes_per_chan, rr_node_indices); edge_list_head = insert_in_edge_list (edge_list_head, to_node, wire_to_ipin_switch, &free_edge_list_head); } num_conn += max_conn; } } *edge_list_ptr = edge_list_head; return (num_conn);}int get_ytrack_to_clb_ipin_edges (int tr_jstart, int tr_jend, int tr_i, int itrack, int iside, t_linked_edge **edge_list_ptr, struct s_ivec **tracks_to_clb_ipin, int nodes_per_chan, int **rr_node_indices, t_seg_details *seg_details_y, int wire_to_ipin_switch) {/* This routine counts how many connections should be made from this segment * * to the clbs to the LEFT or RIGHT of it. It also adds them to the edge * * linked list and updates edge_list_ptr. */ int clb_i, iconn, num_conn, max_conn, j, ipin, to_node; t_linked_edge *edge_list_head;/* Side is from the *track's* perspective */ if (iside == LEFT) { clb_i = tr_i; } else if (iside == RIGHT) { clb_i = tr_i + 1; } else { printf ("Error in get_ytrack_to_clb_ipin_edges: Unknown iside: %d.\n", iside); exit (1); } edge_list_head = *edge_list_ptr; num_conn = 0; max_conn = tracks_to_clb_ipin[itrack][iside].nelem; for (j=tr_jstart;j<=tr_jend;j++) { if (is_cbox (j, tr_i, itrack, seg_details_y)) { for (iconn=0;iconn<max_conn;iconn++) { ipin = tracks_to_clb_ipin[itrack][iside].list[iconn]; to_node = get_rr_node_index (clb_i, j, IPIN, ipin, nodes_per_chan, rr_node_indices); edge_list_head = insert_in_edge_list (edge_list_head, to_node, wire_to_ipin_switch, &free_edge_list_head); } num_conn += max_conn; } } *edge_list_ptr = edge_list_head; return (num_conn); }int get_xtrack_to_pad_edges (int tr_istart, int tr_iend, int tr_j, int pad_j, int itrack, t_linked_edge **edge_list_ptr, struct s_ivec *tracks_to_pads, int nodes_per_chan, int **rr_node_indices, t_seg_details *seg_details_x, int wire_to_ipin_switch) {/* This routine counts how many connections should be made from this segment * * to the row of pads above or below it. It also adds these edges to the * * edge list and updates edge_list_ptr to point to the new list head. */ int iconn, ipad, to_node, num_conn, max_conn, i; t_linked_edge *edge_list_head; edge_list_head = *edge_list_ptr; num_conn = 0; max_conn = tracks_to_pads[itrack].nelem; for (i=tr_istart;i<=tr_iend;i++) { if (is_cbox (i, tr_j, itrack, seg_details_x)) { for (iconn=0;iconn<max_conn;iconn++) { ipad = tracks_to_pads[itrack].list[iconn]; to_node = get_rr_node_index (i, pad_j, IPIN, ipad, nodes_per_chan, rr_node_indices); edge_list_head = insert_in_edge_list (edge_list_head, to_node, wire_to_ipin_switch, &free_edge_list_head); } num_conn += max_conn; } } *edge_list_ptr = edge_list_head; return (num_conn);}int get_ytrack_to_pad_edges (int tr_jstart, int tr_jend, int tr_i, int pad_i, int itrack, t_linked_edge **edge_list_ptr, struct s_ivec *tracks_to_pads, int nodes_per_chan, int **rr_node_indices, t_seg_details *seg_details_y, int wire_to_ipin_switch) {/* This routine counts how many connections should be made from this segment * * to the row of pads to the left or right of it. Additionally, if rr_edges * * isn't NULL, it will also load the edges array. Make sure rr_edges points * * at the next free spot to put an edge in this case. */ int iconn, ipad, to_node, num_conn, max_conn, j; t_linked_edge *edge_list_head; edge_list_head = *edge_list_ptr; num_conn = 0; max_conn = tracks_to_pads[itrack].nelem; for (j=tr_jstart;j<=tr_jend;j++) { if (is_cbox (j, tr_i, itrack, seg_details_y)) { for (iconn=0;iconn<tracks_to_pads[itrack].nelem;iconn++) { ipad = tracks_to_pads[itrack].list[iconn]; to_node = get_rr_node_index (pad_i, j, IPIN, ipad, nodes_per_chan, rr_node_indices); edge_list_head = insert_in_edge_list (edge_list_head, to_node, wire_to_ipin_switch, &free_edge_list_head); } num_conn += max_conn; } } *edge_list_ptr = edge_list_head; return (num_conn);}int get_xtrack_to_ytracks (int from_istart, int from_iend, int from_j, int from_track, int to_j, t_linked_edge **edge_list_ptr, int nodes_per_chan, int **rr_node_indices, t_seg_details *seg_details_x, t_seg_details *seg_details_y, enum e_switch_block_type switch_block_type) {/* Counts how many connections should be made from this segment to the y- * * segments in the adjacent channels at to_j. It returns the number of * * connections, and updates edge_list_ptr to point at the head of the * * (extended) linked list giving the nodes to which this segment connects * * and the switch type used to connect to each. * * * * An edge is added from this segment to a y-segment if: * * (1) this segment should have a switch box at that location, or * * (2) the y-segment to which it would connect has a switch box, and the * * switch type of that y-segment is unbuffered (bidirectional pass * * transistor). * * * * If the switch in each direction is a pass transistor (unbuffered), both * * switches are marked as being of the types of the larger (lower R) pass * * transistor. Note that this code implicitly assumes the routing is * * bidirectional (a switch in each direction). */ int num_conn, to_node, i, to_track, iconn; int from_node_switch, to_node_switch; short switch_types[2]; boolean is_x_sbox, is_y_sbox, yconn_to_above; t_linked_edge *edge_list_head; struct s_ivec conn_tracks; num_conn = 0; edge_list_head = *edge_list_ptr; if (to_j <= from_j) yconn_to_above = TRUE; /* The connection goes up from ychan to xchan. */ else yconn_to_above = FALSE;/* Recall: this is the type of switch to use on switches that go *to* this * * node (i.e. the output side is on the from_node). */ from_node_switch = seg_details_x[from_track].wire_switch;/* For each unit-length piece of wire in the segment, I add the things it * * would connect to diagonally to the right and diagonally to the left of * * it. This is important -- for some switch boxes, the connection from * * (i,j) to (i,j+1) and the connection from (i+1,j) to (i,j+1), for example, * * would lead to connections to different tracks in the (i,j+1) channel. In * * this case, the code below will connect to ALL the tracks that two unit * * length segments at (i,j) and (i+1,j) would have connected to in (i,j+1). */ for (i=from_istart;i<=from_iend;i++) { /* Diagonal connection to left (from xchan to ychan) */ is_x_sbox = is_sbox (i, from_j, from_track, seg_details_x, FALSE); conn_tracks = get_switch_box_tracks (i, from_j, from_track, CHANX, i-1, to_j, CHANY, switch_block_type, nodes_per_chan); /* For all the tracks we connect to in that channel ... */ for (iconn=0;iconn<conn_tracks.nelem;iconn++) { to_track = conn_tracks.list[iconn]; is_y_sbox = is_sbox (to_j, i-1, to_track, seg_details_y, yconn_to_above); to_node_switch = seg_details_y[to_track].wire_switch; get_switch_type (is_x_sbox, is_y_sbox, from_node_switch, to_node_switch, switch_types); if (switch_types[0] != OPEN) { to_node = get_rr_node_index (i-1, to_j, CHANY, to_track, nodes_per_chan, rr_node_indices); if (!rr_edge_done[to_node]) { /* Not a repeat edge. */ num_conn++; rr_edge_done[to_node] = TRUE; edge_list_head = insert_in_edge_list (edge_list_head, to_node, switch_types[0], &free_edge_list_head); if (switch_types[1] != OPEN) { /* A second edge. */ edge_list_head = insert_in_edge_list (edge_list_head, to_node, switch_types[1], &free_edge_list_head); num_conn++; } } } } /* Diagonal connection to right (from xchan to ychan) */ is_x_sbox = is_sbox (i, from_j, from_track, seg_details_x, TRUE); conn_tracks = get_switch_box_tracks (i, from_j, from_track, CHANX, i, to_j, CHANY, switch_block_type, nodes_per_chan); /* For all the tracks we connect to in that channel ... */ for (iconn=0;iconn<conn_tracks.nelem;iconn++) { to_track = conn_tracks.list[iconn]; is_y_sbox = is_sbox (to_j, i, to_track, seg_details_y, yconn_to_above); to_node_switch = seg_details_y[to_track].wire_switch; get_switch_type (is_x_sbox, is_y_sbox, from_node_switch, to_node_switch, switch_types); if (switch_types[0] != OPEN) { to_node = get_rr_node_index (i, to_j, CHANY, to_track, nodes_per_chan, rr_node_indices); if (!rr_edge_done[to_node]) { /* Not a repeat edge. */ num_conn++; rr_edge_done[to_node] = TRUE; edge_list_head = insert_in_edge_list (edge_list_head, to_node, switch_types[0], &free_edge_list_head); if (switch_types[1] != OPEN) { /* A second edge */ edge_list_head = insert_in_edge_list (edge_list_head, to_node, switch_types[1], &free_edge_list_head); num_conn++; } } } } } /* End for length of segment. */ *edge_list_ptr = edge_list_head; return (num_conn);}int get_ytrack_to_xtracks (int from_jstart, int from_jend, int from_i, int from_track, int to_i, t_linked_edge **edge_list_ptr, int nodes_per_chan, int **rr_node_indices, t_seg_details *seg_details_x, t_seg_details *seg_details_y, enum e_switch_block_type switch_block_type) { /* Counts how many connections should be made from this segment to the x- * * segments in the adjacent channels at to_i. It returns the number of * * connections, and updates edge_list_ptr to point at the head of the * * (extended) linked list giving the nodes to which this segment connects * * and the switch type used to connect to each. * * * * An edge is added from this segment to an x-segment if: * * (1) this segment should have a switch box at that location, or * * (2) the x-segment to which it would connect has a switch box, and the * * switch type of that x-segment is unbuffered (bidirectional pass * * transistor). * * * * If the switch in each direction is a pass transistor (unbuffered), both * * switches are marked as being of the types of the larger (lower R) pass * * transistor. Note that this code implicitly assumes the routing is * * bidirectional (a switch in each direction). */ int num_conn, to_node, j, to_track, iconn; int from_node_switch, to_node_switch; short switch_types[2]; boolean is_x_sbox, is_y_sbox, xconn_to_right; t_linked_edge *edge_list_head; struct s_ivec conn_tracks; num_conn = 0; edge_list_head = *edge_list_ptr; if (to_i <= from_i)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -