📄 rr_graph2.c
字号:
xconn_to_right = TRUE; /* The connection goes RIGHT from xchan to ychan */ else xconn_to_right = 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_y[from_track].wire_switch;/* For each unit-length piece of wire in the segment, I add the things it * * would connect to diagonally above and diagonally below it. This is * * important -- for some switch boxes, the connection from (i,j) to (i+1,j) * * and the connection from (i,j+1) to (i+1,j), for example, would lead to * * connections to different tracks in the (i+1,j) channel. In this case, * * the code below will connect to ALL the tracks that two unit length * * segments at (i,j) and (i,j+1) would have connected to in (i+1,j). */ for (j=from_jstart;j<=from_jend;j++) { /* Diagonal connection to below (from ychan to xchan) */ is_y_sbox = is_sbox (j, from_i, from_track, seg_details_y, FALSE); conn_tracks = get_switch_box_tracks (from_i, j, from_track, CHANY, to_i, j-1, CHANX, 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_x_sbox = is_sbox (to_i, j-1, to_track, seg_details_x, xconn_to_right); to_node_switch = seg_details_x[to_track].wire_switch; get_switch_type (is_y_sbox, is_x_sbox, from_node_switch, to_node_switch, switch_types); if (switch_types[0] != OPEN) { to_node = get_rr_node_index (to_i, j-1, CHANX, 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 above (from ychan to xchan) */ is_y_sbox = is_sbox (j, from_i, from_track, seg_details_y, TRUE); conn_tracks = get_switch_box_tracks (from_i, j, from_track, CHANY, to_i, j, CHANX, 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_x_sbox = is_sbox (to_i, j, to_track, seg_details_x, xconn_to_right); to_node_switch = seg_details_x[to_track].wire_switch; get_switch_type (is_y_sbox, is_x_sbox, from_node_switch, to_node_switch, switch_types); if (switch_types[0] != OPEN) { to_node = get_rr_node_index (to_i, j, CHANX, 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_xtrack_to_xtrack (int from_i, int j, 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, enum e_switch_block_type switch_block_type) {/* Returns the number of edges between the specified channel segments. * * Also updates edge_list_ptr to point at the new (extended) linked list * * of edges and switch types. */ boolean is_from_sbox, is_to_sbox, from_goes_right, to_goes_right; int to_track, to_node, iconn, num_conn; int from_node_switch, to_node_switch; short switch_types[2]; struct s_ivec conn_tracks; if (from_i < to_i) { from_goes_right = TRUE; to_goes_right = FALSE; } else { from_goes_right = FALSE; to_goes_right = TRUE; } num_conn = 0; from_node_switch = seg_details_x[from_track].wire_switch; is_from_sbox = is_sbox (from_i, j, from_track, seg_details_x, from_goes_right); conn_tracks = get_switch_box_tracks (from_i, j, from_track, CHANX, to_i, j, CHANX, 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_to_sbox = is_sbox (to_i, j, to_track, seg_details_x, to_goes_right); to_node_switch = seg_details_x[to_track].wire_switch; get_switch_type (is_from_sbox, is_to_sbox, from_node_switch, to_node_switch, switch_types); if (switch_types[0] != OPEN) { to_node = get_rr_node_index (to_i, j, CHANX, to_track, nodes_per_chan, rr_node_indices); /* No need to check for repeats with the current switch boxes. */ *edge_list_ptr = insert_in_edge_list (*edge_list_ptr, to_node, switch_types[0], &free_edge_list_head); num_conn++; if (switch_types[1] != OPEN) { *edge_list_ptr = insert_in_edge_list (*edge_list_ptr, to_node, switch_types[1], &free_edge_list_head); num_conn++; } } } return (num_conn);}int get_ytrack_to_ytrack (int i, 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_y, enum e_switch_block_type switch_block_type) { /* Returns the number of edges between the specified channel segments. * * Also updates edge_list_ptr to point at the new (extended) linked list * * of edges and switch types. */ boolean is_from_sbox, is_to_sbox, from_goes_up, to_goes_up; int to_track, to_node, iconn, num_conn; int from_node_switch, to_node_switch; short switch_types[2]; struct s_ivec conn_tracks;if (from_j < to_j) { from_goes_up = TRUE; to_goes_up = FALSE; } else { from_goes_up = FALSE; to_goes_up = TRUE; } num_conn = 0; from_node_switch = seg_details_y[from_track].wire_switch; is_from_sbox = is_sbox (from_j, i, from_track, seg_details_y, from_goes_up); conn_tracks = get_switch_box_tracks (i, from_j, from_track, CHANY, 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_to_sbox = is_sbox (to_j, i, to_track, seg_details_y, to_goes_up); to_node_switch = seg_details_y[to_track].wire_switch; get_switch_type (is_from_sbox, is_to_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); /* No need to check for repeats with the current switch boxes. */ *edge_list_ptr = insert_in_edge_list (*edge_list_ptr, to_node, switch_types[0], &free_edge_list_head); num_conn++; if (switch_types[1] != OPEN) { *edge_list_ptr = insert_in_edge_list (*edge_list_ptr, to_node, switch_types[1], &free_edge_list_head); num_conn++; } } } return (num_conn);}boolean is_sbox (int seg_num, int chan_num, int itrack, t_seg_details *seg_details, boolean above_or_right) {/* Returns TRUE if the specified segment has a switch box at the specified * * location, FALSE otherwise. The switch box is from the specified segment * * to the left (for chanx) or below (for chany) unless above_or_right is * * TRUE. */ int seg_offset, start, length; boolean longline; length = seg_details[itrack].length; start = seg_details[itrack].start; longline = seg_details[itrack].longline;/* NB: Periodicity is length for normal segments, length + 1 for long lines. */ if (!longline) { seg_offset = (seg_num + chan_num - start + length) % length; seg_offset += above_or_right; /* Add one if conn. is above or to right */ } else { /* Is a longline */ seg_offset = (seg_num + chan_num - start + above_or_right) % (length + 1); } return (seg_details[itrack].sb[seg_offset]);}static void get_switch_type (boolean is_from_sbox, boolean is_to_sbox, short from_node_switch, short to_node_switch, short switch_types[2]) {/* This routine looks at whether the from_node and to_node want a switch, * * and what type of switch is used to connect *to* each type of node * * (from_node_switch and to_node_switch). It decides what type of switch, * * if any, should be used to go from from_node to to_node. If no switch * * should be inserted (i.e. no connection), it returns OPEN. Its returned * * values are in the switch_types array. It needs to return an array * * because one topology (a buffer in the forward direction and a pass * * transistor in the backward direction) results in *two* switches. */ switch_types[0] = OPEN; /* No switch */ switch_types[1] = OPEN; if (!is_from_sbox && !is_to_sbox) { /* No connection wanted in either dir */ switch_types[0] = OPEN; } else if (is_from_sbox && !is_to_sbox) { /* Only forward connection wanted */ switch_types[0] = to_node_switch; /* Type of switch to go *to* to_node */ } else if (!is_from_sbox && is_to_sbox) {/* Only backward connection desired. We're deciding whether or not to put * * in the forward connection. Put it in if the backward connection uses * * a bidirectional (pass transistor) switch. Remember that the backward * * connection uses a from_node_switch type of switch. */ if (switch_inf[from_node_switch].buffered == FALSE) { switch_types[0] = from_node_switch; } } else {/* Both a forward and a backward connection desired. If the switch types * * desired for the two connection are different, we have to reconcile them. */ if (from_node_switch == to_node_switch) { switch_types[0] = to_node_switch; } else { /* Different switch types. Reconcile. */ if (switch_inf[to_node_switch].buffered) { switch_types[0] = to_node_switch; if (switch_inf[from_node_switch].buffered == FALSE) { /* Buffer in forward direction, pass transistor in backward. Put * * in *two* edges. */ switch_types[1] = from_node_switch; } } else { /* Forward connection is a pass transistor. */ if (switch_inf[from_node_switch].buffered) { switch_types[0] = to_node_switch; } else { /* Both forward and backward connections use pass transistors. * * use whichever one is larger, since you'll only physically * * build one switch. */ if (switch_inf[to_node_switch].R < switch_inf[from_node_switch].R) { switch_types[0] = to_node_switch; } else if (switch_inf[from_node_switch].R < switch_inf[to_node_switch].R) { switch_types[0] = from_node_switch; } else { /* Two pass transistors have the same R, but are have different * * switch indices. Use the one with lower index (arbitrarily), * * to ensure both switches are of the same type (since you can * * only physically build one). I'm being pretty dogmatic here. */ if (to_node_switch < from_node_switch) { switch_types[0] = to_node_switch; } else { switch_types[0] = from_node_switch; } } } } } /* End switch types are different */ } /* End both forward and backward connection desired. */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -