#SWITCHBOX = MODIFIED #include "util.h" #include "vpr_types.h" #include "rr_graph_sbox.h" /* Modified by Steve Wilton, October 1998 */ /* Switch box: * * TOP (CHANY) * * | | | | | | * * +-----------+ * * --| |-- * * --| |-- * * LEFT --| |-- RIGHT * * (CHANX)--| |--(CHANX) * * --| |-- * * --| |-- * * +-----------+ * * | | | | | | * * BOTTOM (CHANY) */ /* [0..3][0..3][0..nodes_per_chan-1]. Structure below is indexed as: * * [from_side][to_side][from_track]. That yields an integer vector (ivec) * * of the tracks to which from_track connects in the proper to_location. * * For simple switch boxes this is overkill, but it will allow complicated * * switch boxes with Fs > 3, etc. without trouble. */ static struct s_ivec *****switch_block_conn; static int get_simple_switch_block_track (enum e_side from_side, enum e_side to_side, int from_track, enum e_switch_block_type switch_block_type, int nodes_per_chan,int xpos, int ypos, int nx,int ny, t_seg_details *seg_details_x, t_seg_details *seg_details_y); static enum e_side get_sbox_side (int get_i, int get_j, t_rr_type get_type, int comp_i, int comp_j); static int *end_translation_table; static int num_trans_table; static void init_trans_table(int xpos, int ypos, int nodes_per_chan, int nx, int ny, t_seg_details *seg_details_x, t_seg_details *seg_details_y) { int track,horizend,vertend,istart,iend; end_translation_table = (int *)malloc(sizeof(int)*nodes_per_chan); num_trans_table = 0; for (track=0;track no connection. */ switch_block_conn[xpos][ypos][from_side][to_side][from_track].nelem = 0; switch_block_conn[xpos][ypos][from_side][to_side][from_track].list = NULL; } } } } free_trans_table(); } } } void free_switch_block_conn (int sizex, int sizey,int nodes_per_chan) { /* Frees the switch_block_conn data structure. */ free_ivec_matrix5 (switch_block_conn, 0,sizex,0,sizey,0, 3, 0, 3, 0, nodes_per_chan - 1); } #define SBOX_ERROR -1 static int get_simple_switch_block_track (enum e_side from_side, enum e_side to_side, int from_track, enum e_switch_block_type switch_block_type, int nodes_per_chan, int xpos, int ypos,int nx,int ny, t_seg_details *seg_details_x, t_seg_details *seg_details_y) { /* This routine returns the track number to which the from_track should * * connect. It supports three simple, Fs = 3, switch blocks. */ /* In this, every track connects to every other track at right angles to it */ int to_track,trackend,transtrack; to_track = SBOX_ERROR; /* Can check to see if it's not set later. */ if ((switch_block_type == SUBSET)) { /* NB: Global routing uses SUBSET too */ to_track = from_track; } /* See S. Wilton Phd thesis, U of T, 1996 p. 103 for details on following. */ else if ((switch_block_type == WILTON)) { if (from_side == LEFT) { if (to_side == RIGHT) { /* CHANX to CHANX */ to_track = from_track; } else if (to_side == TOP) { /* from CHANX to CHANY */ to_track = (nodes_per_chan - from_track) % nodes_per_chan; } else if (to_side == BOTTOM) { to_track = (nodes_per_chan + from_track -1) % nodes_per_chan; } } else if (from_side == RIGHT) { if (to_side == LEFT) { /* CHANX to CHANX */ to_track = from_track; } else if (to_side == TOP) { /* from CHANX to CHANY */ to_track = (nodes_per_chan + from_track - 1) % nodes_per_chan; } else if (to_side == BOTTOM) { to_track = (2 * nodes_per_chan - 2 - from_track) % nodes_per_chan; } } else if (from_side == BOTTOM) { if (to_side == TOP) { /* CHANY to CHANY */ to_track = from_track; } else if (to_side == LEFT) { /* from CHANY to CHANX */ to_track = (from_track + 1) % nodes_per_chan; } else if (to_side == RIGHT) { to_track = (2 * nodes_per_chan - 2 - from_track) % nodes_per_chan; } } else if (from_side == TOP) { if (to_side == BOTTOM) { /* CHANY to CHANY */ to_track = from_track; } else if (to_side == LEFT) { /* from CHANY to CHANX */ to_track = (nodes_per_chan - from_track) % nodes_per_chan; } else if (to_side == RIGHT) { to_track = (from_track + 1) % nodes_per_chan; } } } /* End switch_block_type == WILTON case. */ else if (switch_block_type == WILTON3) { /* this switch block, the connections depend on whether this wire ends or goes right through this switch block. */ trackend = pos_in_trans_table(from_track); if (from_side == LEFT) { if (to_side == RIGHT) { /* CHANX to CHANX */ to_track = from_track; } else if (to_side == TOP) { /* from CHANX to CHANY */ if (trackend != -1) { to_track = trans_track((num_trans_table - trackend) % num_trans_table); } else { to_track = from_track; } } else if (to_side == BOTTOM) { if (trackend != -1) { to_track = trans_track((num_trans_table + trackend -1) % num_trans_table); } else { to_track = from_track; } } } else if (from_side == RIGHT) { if (to_side == LEFT) { /* CHANX to CHANX */ to_track = from_track; } else if (to_side == TOP) { /* from CHANX to CHANY */ if (trackend != -1) { to_track = trans_track((num_trans_table + trackend - 1) % num_trans_table); } else { to_track = from_track; } } else if (to_side == BOTTOM) { if (trackend != -1) { to_track = trans_track((2 * num_trans_table - 2 - trackend) % num_trans_table); } else { to_track = from_track; } } } else if (from_side == BOTTOM) { if (to_side == TOP) { /* CHANY to CHANY */ to_track = from_track; } else if (to_side == LEFT) { /* from CHANY to CHANX */ if (trackend != -1) { to_track = trans_track((trackend + 1) % num_trans_table); } else { to_track = from_track; } } else if (to_side == RIGHT) { if (trackend != -1) { to_track = trans_track((2 * num_trans_table - 2 - trackend) % num_trans_table); } else { to_track = from_track; } } } else if (from_side == TOP) { if (to_side == BOTTOM) { /* CHANY to CHANY */ to_track = from_track; } else if (to_side == LEFT) { /* from CHANY to CHANX */ if (trackend != -1) { to_track = trans_track((num_trans_table - trackend) % num_trans_table); } else { to_track = from_track; } } else if (to_side == RIGHT) { if (trackend != -1) { to_track = trans_track((trackend + 1) % num_trans_table); } else { to_track = from_track; } } } } /* End switch_block_type == WILTON3 case. */ else if (switch_block_type == UNIVERSAL) { if (from_side == LEFT) { if (to_side == RIGHT) { /* CHANX to CHANX */ to_track = from_track; } else if (to_side == TOP) { /* from CHANX to CHANY */ to_track = nodes_per_chan - 1 - from_track; } else if (to_side == BOTTOM) { to_track = from_track; } } else if (from_side == RIGHT) { if (to_side == LEFT) { /* CHANX to CHANX */ to_track = from_track; } else if (to_side == TOP) { /* from CHANX to CHANY */ to_track = from_track; } else if (to_side == BOTTOM) { to_track = nodes_per_chan - 1 - from_track; } } else if (from_side == BOTTOM) { if (to_side == TOP) { /* CHANY to CHANY */ to_track = from_track; } else if (to_side == LEFT) { /* from CHANY to CHANX */ to_track = from_track; } else if (to_side == RIGHT) { to_track = nodes_per_chan - 1 - from_track; } } else if (from_side == TOP) { if (to_side == BOTTOM) { /* CHANY to CHANY */ to_track = from_track; } else if (to_side == LEFT) { /* from CHANY to CHANX */ to_track = nodes_per_chan - 1 - from_track; } else if (to_side == RIGHT) { to_track = from_track; } } } /* End switch_block_type == UNIVERSAL case. */ if (to_track == SBOX_ERROR) { printf("Error in get_simple_switch_block_track. Unexpected connection.\n" "from_side: %d to_side: %d switch_block_type: %d.\n", from_side, to_side, switch_block_type); exit (1); } return (to_track); } struct s_ivec get_switch_box_tracks (int from_i, int from_j, int from_track, t_rr_type from_type, int to_i, int to_j, t_rr_type to_type, enum e_switch_block_type switch_block_type, int nodes_per_chan) { /* Returns a vector of the tracks to which from_track at (from_i, from_j) * * should connect at (to_i, to_j). */ enum e_side from_side, to_side; int xpos, ypos; from_side = get_sbox_side (from_i, from_j, from_type, to_i, to_j); to_side = get_sbox_side (to_i, to_j, to_type, from_i, from_j); xpos = (to_i < from_i) ? to_i : from_i; ypos = (to_j < from_j) ? to_j : from_j; return (switch_block_conn[xpos][ypos][from_side][to_side][from_track]); } static enum e_side get_sbox_side (int get_i, int get_j, t_rr_type get_type, int comp_i, int comp_j) { /* Returns the side of the switch box that the get_node is on, as compared * * to the comp (comparison) node. */ enum e_side side; if (get_type == CHANX) { if (get_i > comp_i) { side = RIGHT; } else { side = LEFT; } } else if (get_type == CHANY) { if (get_j > comp_j) { side = TOP; } else { side = BOTTOM; } } else { printf ("Error in get_sbox_side. Unexpected get_type: %d.\n", get_type); exit (1); } return (side); }