#include <stdio.h>
#include <math.h>
#include <assert.h>
#include <string.h>
#include "util.h"
#include "vpr_types.h"
#include "globals.h"
#include "rr_graph_util.h"
#include "rr_graph.h"
#include "rr_graph2.h"
#include "rr_graph_sbox.h"
#include "check_rr_graph.h"
#include "rr_graph_timing_params.h"
#include "rr_graph_indexed_data.h"
#include "vpr_utils.h"
Go to the source code of this file.
Data Structures | |
struct | s_mux |
struct | s_mux_size_distribution |
Defines | |
#define | REVERSE_OPIN_ORDER |
#define | MUX_SIZE_DIST_DISPLAY |
Typedefs | |
typedef struct s_mux | t_mux |
typedef struct s_mux_size_distribution | t_mux_size_distribution |
Functions | |
static int **** | alloc_and_load_pin_to_track_map (IN enum e_pin_type pin_type, IN int nodes_per_chan, IN int Fc, IN t_type_ptr Type, IN boolean perturb_switch_pattern, IN enum e_directionality directionality) |
static struct s_ivec *** | alloc_and_load_track_to_pin_lookup (IN int ****pin_to_track_map, IN int Fc, IN int height, IN int num_pins, IN int nodes_per_chan) |
static void | build_bidir_rr_opins (IN int i, IN int j, INOUT t_rr_node *rr_node, IN t_ivec ***rr_node_indices, IN int *****opin_to_track_map, IN int *Fc_out, IN boolean *rr_edge_done, IN t_seg_details *seg_details, IN struct s_grid_tile **grid) |
static void | build_unidir_rr_opins (IN int i, IN int j, IN struct s_grid_tile **grid, IN int *Fc_out, IN int nodes_per_chan, IN t_seg_details *seg_details, INOUT int **Fc_xofs, INOUT int **Fc_yofs, INOUT t_rr_node *rr_node, INOUT boolean *rr_edge_done, OUT boolean *Fc_clipped, IN t_ivec ***rr_node_indices) |
static void | alloc_and_load_rr_graph (IN int num_nodes, IN t_rr_node *rr_node, IN int num_seg_types, IN t_seg_details *seg_details, IN boolean *rr_edge_done, IN struct s_ivec ****track_to_ipin_lookup, IN int *****opin_to_track_map, IN struct s_ivec ***switch_block_conn, IN struct s_grid_tile **grid, IN int nx, IN int ny, IN int Fs, IN short *****sblock_pattern, IN int *Fc_out, IN int **Fc_xofs, IN int **Fc_yofs, IN t_ivec ***rr_node_indices, IN int nodes_per_chan, IN enum e_switch_block_type sb_type, IN int delayless_switch, IN enum e_directionality directionality, IN int wire_to_ipin_switch, OUT boolean *Fc_clipped) |
static void | load_uniform_switch_pattern (IN t_type_ptr type, INOUT int ****tracks_connected_to_pin, IN int num_phys_pins, IN int *pin_num_ordering, IN int *side_ordering, IN int *offset_ordering, IN int nodes_per_chan, IN int Fc, IN enum e_directionality directionality) |
static void | load_perturbed_switch_pattern (IN t_type_ptr type, INOUT int ****tracks_connected_to_pin, IN int num_phys_pins, IN int *pin_num_ordering, IN int *side_ordering, IN int *offset_ordering, IN int nodes_per_chan, IN int Fc, IN enum e_directionality directionality) |
static void | check_all_tracks_reach_pins (t_type_ptr type, int ****tracks_connected_to_pin, int nodes_per_chan, int Fc, enum e_pin_type ipin_or_opin) |
static int | track_side (int clb_side) |
static boolean * | alloc_and_load_perturb_ipins (IN int nodes_per_chan, IN int num_types, IN int *Fc_in, IN int *Fc_out, IN enum e_directionality directionality) |
static void | print_rr_node (FILE *fp, t_rr_node *rr_node, int inode) |
static void | build_rr_sinks_sources (IN int i, IN int j, IN t_rr_node *rr_node, IN t_ivec ***rr_node_indices, IN int delayless_switch, IN struct s_grid_tile **grid) |
static void | build_rr_xchan (IN int i, IN int j, IN struct s_ivec ****track_to_ipin_lookup, IN struct s_ivec ***switch_block_conn, IN int cost_index_offset, IN int nodes_per_chan, IN int *opin_mux_size, IN short *****sblock_pattern, IN int Fs_per_side, IN t_seg_details *seg_details, IN t_ivec ***rr_node_indices, IN boolean *rr_edge_done, INOUT t_rr_node *rr_node, IN int wire_to_ipin_switch, IN enum e_directionality directionality) |
static void | build_rr_ychan (IN int i, IN int j, IN struct s_ivec ****track_to_ipin_lookup, IN struct s_ivec ***switch_block_conn, IN int cost_index_offset, IN int nodes_per_chan, IN int *opin_mux_size, IN short *****sblock_pattern, IN int Fs_per_side, IN t_seg_details *seg_details, IN t_ivec ***rr_node_indices, IN boolean *rr_edge_done, INOUT t_rr_node *rr_node, IN int wire_to_ipin_switch, IN enum e_directionality directionality) |
static void | rr_graph_externals (t_timing_inf timing_inf, t_segment_inf *segment_inf, int num_seg_types, int nodes_per_chan, int wire_to_ipin_switch, enum e_base_cost_type base_cost_type) |
void | alloc_and_load_edges_and_switches (IN t_rr_node *rr_node, IN int inode, IN int num_edges, IN boolean *rr_edge_done, IN t_linked_edge *edge_list_head) |
static void | alloc_net_rr_terminals (void) |
static void | alloc_and_load_rr_clb_source (t_ivec ***rr_node_indices) |
static void | load_uniform_opin_switch_pattern_paired (IN int *Fc_out, IN int num_pins, IN int *pins_in_chan_seg, IN int num_wire_inc_muxes, IN int num_wire_dec_muxes, IN int *wire_inc_muxes, IN int *wire_dec_muxes, INOUT t_rr_node *rr_node, INOUT boolean *rr_edge_done, IN t_seg_details *seg_details, OUT boolean *Fc_clipped) |
static int * | get_adj_opins (IN int i, IN int j, OUT int *num_pins, IN t_ivec ***rr_node_indices, IN enum e_rr_type chan_type) |
void | watch_edges (int inode, t_linked_edge *edge_list_head) |
static void | view_mux_size_distribution (t_ivec ***rr_node_indices, int nodes_per_chan, t_seg_details *seg_details_x, t_seg_details *seg_details_y) |
static void | print_distribution (FILE *fptr, t_mux_size_distribution *distr_struct) |
static void | free_type_pin_to_track_map (int *****ipin_to_track_map, t_type_ptr types, int *fc_in) |
static void | free_type_track_to_ipin_map (struct s_ivec ****track_to_pin_map, t_type_ptr types, int nodes_per_chan) |
static t_seg_details * | alloc_and_load_global_route_seg_details (IN int nodes_per_chan, IN int global_route_switch) |
static int * | alloc_and_load_actual_fc (IN int num_types, IN t_type_ptr types, IN int nodes_per_chan, IN boolean is_Fc_out, IN enum e_directionality directionality, OUT boolean *Fc_clipped) |
void | build_rr_graph (IN t_graph_type graph_type, IN int num_types, IN t_type_ptr types, IN int nx, IN int ny, IN struct s_grid_tile **grid, IN int chan_width, IN struct s_chan_width_dist *chan_capacity_inf, IN enum e_switch_block_type sb_type, IN int Fs, IN int num_seg_types, IN int num_switches, IN t_segment_inf *segment_inf, IN int global_route_switch, IN int delayless_switch, IN t_timing_inf timing_inf, IN int wire_to_ipin_switch, IN enum e_base_cost_type base_cost_type, OUT int *Warnings) |
void | free_rr_graph (void) |
void | load_net_rr_terminals (t_ivec ***rr_node_indices) |
static void | build_rr_xchan (IN int i, IN int j, IN struct s_ivec ****track_to_ipin_lookup, IN struct s_ivec ***switch_block_conn, IN int cost_index_offset, IN int nodes_per_chan, IN int *opin_mux_size, IN short *****sblock_pattern, IN int Fs_per_side, IN t_seg_details *seg_details, IN t_ivec ***rr_node_indices, INOUT boolean *rr_edge_done, INOUT t_rr_node *rr_node, IN int wire_to_ipin_switch, IN enum e_directionality directionality) |
void | alloc_and_load_edges_and_switches (IN t_rr_node *rr_node, IN int inode, IN int num_edges, INOUT boolean *rr_edge_done, IN t_linked_edge *edge_list_head) |
static void | load_uniform_switch_pattern (IN t_type_ptr type, INOUT int ****tracks_connected_to_pin, IN int num_phys_pins, IN int *pin_num_ordering, IN int *side_ordering, IN int *offset_ordering, IN int nodes_per_chan, IN int Fc, enum e_directionality directionality) |
static void | load_perturbed_switch_pattern (IN t_type_ptr type, INOUT int ****tracks_connected_to_pin, IN int num_phys_pins, IN int *pin_num_ordering, IN int *side_ordering, IN int *offset_ordering, IN int nodes_per_chan, IN int Fc, enum e_directionality directionality) |
void | dump_rr_graph (IN const char *file_name) |
void | print_rr_indexed_data (FILE *fp, int index) |
Variables | |
static struct s_linked_vptr * | rr_mem_chunk_list_head = NULL |
static int | chunk_bytes_avail = 0 |
static char * | chunk_next_avail_mem = NULL |
#define MUX_SIZE_DIST_DISPLAY |
Definition at line 26 of file rr_graph.c.
#define REVERSE_OPIN_ORDER |
Definition at line 23 of file rr_graph.c.
typedef struct s_mux_size_distribution t_mux_size_distribution |
static int * alloc_and_load_actual_fc | ( | IN int | num_types, | |
IN t_type_ptr | types, | |||
IN int | nodes_per_chan, | |||
IN boolean | is_Fc_out, | |||
IN enum e_directionality | directionality, | |||
OUT boolean * | Fc_clipped | |||
) | [static] |
Definition at line 765 of file rr_graph.c.
00771 { 00772 00773 int i; 00774 int *Result = NULL; 00775 int fac, num_sets; 00776 float Fc; 00777 00778 *Fc_clipped = FALSE; 00779 00780 /* Unidir tracks formed in pairs, otherwise no effect. */ 00781 fac = 1; 00782 if(UNI_DIRECTIONAL == directionality) 00783 { 00784 fac = 2; 00785 } 00786 00787 assert((nodes_per_chan % fac) == 0); 00788 num_sets = nodes_per_chan / fac; 00789 00790 Result = (int *)my_malloc(sizeof(int) * num_types); 00791 00792 for(i = 0; i < num_types; ++i) 00793 { 00794 Fc = (is_Fc_out ? type_descriptors[i]. 00795 Fc_out : type_descriptors[i].Fc_in); 00796 00797 if(type_descriptors[i].is_Fc_frac) 00798 { 00799 Result[i] = fac * nint(num_sets * Fc); 00800 } 00801 else 00802 { 00803 Result[i] = Fc; 00804 } 00805 00806 if(is_Fc_out && type_descriptors[i].is_Fc_out_full_flex) 00807 { 00808 Result[i] = nodes_per_chan; 00809 } 00810 00811 Result[i] = max(Result[i], fac); 00812 if(Result[i] > nodes_per_chan) 00813 { 00814 *Fc_clipped = TRUE; 00815 Result[i] = nodes_per_chan; 00816 } 00817 00818 assert(Result[i] % fac == 0); 00819 } 00820 00821 return Result; 00822 }
void alloc_and_load_edges_and_switches | ( | IN t_rr_node * | rr_node, | |
IN int | inode, | |||
IN int | num_edges, | |||
INOUT boolean * | rr_edge_done, | |||
IN t_linked_edge * | edge_list_head | |||
) |
Definition at line 1667 of file rr_graph.c.
01672 { 01673 01674 /* Sets up all the edge related information for rr_node inode (num_edges, * 01675 * the edges array and the switches array). The edge_list_head points to * 01676 * a list of the num_edges edges and switches to put in the arrays. This * 01677 * linked list is freed by this routine. This routine also resets the * 01678 * rr_edge_done array for the next rr_node (i.e. set it so that no edges * 01679 * are marked as having been seen before). */ 01680 01681 t_linked_edge *list_ptr, *prev_ptr; 01682 int i; 01683 01684 /* Check we aren't overwriting edges */ 01685 assert(rr_node[inode].num_edges < 1); 01686 assert(NULL == rr_node[inode].edges); 01687 assert(NULL == rr_node[inode].switches); 01688 01689 rr_node[inode].num_edges = num_edges; 01690 rr_node[inode].edges = (int *)my_malloc(num_edges * sizeof(int)); 01691 rr_node[inode].switches = (short *)my_malloc(num_edges * sizeof(short)); 01692 01693 i = 0; 01694 list_ptr = edge_list_head; 01695 while(list_ptr && (i < num_edges)) 01696 { 01697 rr_node[inode].edges[i] = list_ptr->edge; 01698 rr_node[inode].switches[i] = list_ptr->iswitch; 01699 01700 ++rr_node[list_ptr->edge].fan_in; 01701 01702 /* Unmark the edge since we are done considering fanout from node. */ 01703 rr_edge_done[list_ptr->edge] = FALSE; 01704 01705 prev_ptr = list_ptr; 01706 list_ptr = list_ptr->next; 01707 ++i; 01708 } 01709 assert(list_ptr == NULL); 01710 assert(i == num_edges); 01711 }
void alloc_and_load_edges_and_switches | ( | IN t_rr_node * | rr_node, | |
IN int | inode, | |||
IN int | num_edges, | |||
IN boolean * | rr_edge_done, | |||
IN t_linked_edge * | edge_list_head | |||
) |
static t_seg_details * alloc_and_load_global_route_seg_details | ( | IN int | nodes_per_chan, | |
IN int | global_route_switch | |||
) | [static] |
Definition at line 731 of file rr_graph.c.
00733 { 00734 t_seg_details *result = NULL; 00735 00736 assert(nodes_per_chan == 1); 00737 result = (t_seg_details *) my_malloc(sizeof(t_seg_details)); 00738 00739 result->index = 0; 00740 result->length = 1; 00741 result->wire_switch = global_route_switch; 00742 result->opin_switch = global_route_switch; 00743 result->longline = FALSE; 00744 result->direction = BI_DIRECTION; 00745 result->Cmetal = 0.0; 00746 result->Rmetal = 0.0; 00747 result->start = 1; 00748 result->drivers = MULTI_BUFFERED; 00749 result->cb = (boolean *) my_malloc(sizeof(boolean) * 1); 00750 result->cb[0] = TRUE; 00751 result->sb = (boolean *) my_malloc(sizeof(boolean) * 2); 00752 result->sb[0] = TRUE; 00753 result->sb[1] = TRUE; 00754 result->group_size = 1; 00755 result->group_start = 0; 00756 00757 return result; 00758 }
static boolean * alloc_and_load_perturb_ipins | ( | IN int | nodes_per_chan, | |
IN int | num_types, | |||
IN int * | Fc_in, | |||
IN int * | Fc_out, | |||
IN enum e_directionality | directionality | |||
) | [static] |
Definition at line 680 of file rr_graph.c.
00685 { 00686 int i; 00687 float Fc_ratio; 00688 boolean *result = NULL; 00689 00690 result = (boolean *) my_malloc(num_types * sizeof(boolean)); 00691 00692 if(BI_DIRECTIONAL == directionality) 00693 { 00694 for(i = 0; i < num_types; ++i) 00695 { 00696 result[i] = FALSE; 00697 00698 if(Fc_in[i] > Fc_out[i]) 00699 { 00700 Fc_ratio = (float)Fc_in[i] / (float)Fc_out[i]; 00701 } 00702 else 00703 { 00704 Fc_ratio = (float)Fc_out[i] / (float)Fc_in[i]; 00705 } 00706 00707 if((Fc_in[i] <= nodes_per_chan - 2) && 00708 (fabs(Fc_ratio - nint(Fc_ratio)) < 00709 (0.5 / (float)nodes_per_chan))) 00710 { 00711 result[i] = TRUE; 00712 } 00713 } 00714 } 00715 else 00716 { 00717 /* Unidirectional routing uses mux balancing patterns and 00718 * thus shouldn't need perturbation. */ 00719 assert(UNI_DIRECTIONAL == directionality); 00720 for(i = 0; i < num_types; ++i) 00721 { 00722 result[i] = FALSE; 00723 } 00724 } 00725 00726 return result; 00727 }
static int **** alloc_and_load_pin_to_track_map | ( | IN enum e_pin_type | pin_type, | |
IN int | nodes_per_chan, | |||
IN int | Fc, | |||
IN t_type_ptr | Type, | |||
IN boolean | perturb_switch_pattern, | |||
IN enum e_directionality | directionality | |||
) | [static] |
Definition at line 1720 of file rr_graph.c.
01726 { 01727 01728 int **num_dir; /* [0..height][0..3] Number of *physical* pins on each side. */ 01729 int ***dir_list; /* [0..height][0..3][0..num_pins-1] list of pins of correct type * 01730 * * on each side. Max possible space alloced for simplicity */ 01731 01732 int i, j, k, iside, ipin, iclass, num_phys_pins, pindex, ioff; 01733 int *pin_num_ordering, *side_ordering, *offset_ordering; 01734 int **num_done_per_dir; /* [0..height][0..3] */ 01735 int ****tracks_connected_to_pin; /* [0..num_pins-1][0..height][0..3][0..Fc-1] */ 01736 01737 /* NB: This wastes some space. Could set tracks_..._pin[ipin][ioff][iside] = 01738 * NULL if there is no pin on that side, or that pin is of the wrong type. 01739 * Probably not enough memory to worry about, esp. as it's temporary. 01740 * If pin ipin on side iside does not exist or is of the wrong type, 01741 * tracks_connected_to_pin[ipin][iside][0] = OPEN. */ 01742 01743 if(Type->num_pins < 1) 01744 { 01745 return NULL; 01746 } 01747 01748 tracks_connected_to_pin = (int ****) 01749 alloc_matrix4(0, Type->num_pins - 1, 01750 0, Type->height - 1, 0, 3, 0, Fc - 1, sizeof(int)); 01751 01752 for(ipin = 0; ipin < Type->num_pins; ipin++) 01753 { 01754 for(ioff = 0; ioff < Type->height; ioff++) 01755 { 01756 for(iside = 0; iside < 4; iside++) 01757 { 01758 for(i = 0; i < Fc; ++i) 01759 { 01760 tracks_connected_to_pin[ipin][ioff][iside][i] = OPEN; /* Unconnected. */ 01761 } 01762 } 01763 } 01764 } 01765 01766 num_dir = (int **)alloc_matrix(0, Type->height - 1, 0, 3, sizeof(int)); 01767 dir_list = 01768 (int ***)alloc_matrix3(0, Type->height - 1, 0, 3, 0, 01769 Type->num_pins - 1, sizeof(int)); 01770 01771 /* Defensive coding. Try to crash hard if I use an unset entry. */ 01772 for(i = 0; i < Type->height; i++) 01773 for(j = 0; j < 4; j++) 01774 for(k = 0; k < Type->num_pins; k++) 01775 dir_list[i][j][k] = (-1); 01776 01777 for(i = 0; i < Type->height; i++) 01778 for(j = 0; j < 4; j++) 01779 num_dir[i][j] = 0; 01780 01781 for(ipin = 0; ipin < Type->num_pins; ipin++) 01782 { 01783 iclass = Type->pin_class[ipin]; 01784 if(Type->class_inf[iclass].type != pin_type) /* Doing either ipins OR opins */ 01785 continue; 01786 01787 /* Pins connecting only to global resources get no switches -> keeps the * 01788 * area model accurate. */ 01789 01790 if(Type->is_global_pin[ipin]) 01791 continue; 01792 for(ioff = 0; ioff < Type->height; ioff++) 01793 { 01794 for(iside = 0; iside < 4; iside++) 01795 { 01796 if(Type->pinloc[ioff][iside][ipin] == 1) 01797 { 01798 dir_list[ioff][iside][num_dir[ioff] 01799 [iside]] = ipin; 01800 num_dir[ioff][iside]++; 01801 } 01802 } 01803 } 01804 } 01805 01806 num_phys_pins = 0; 01807 for(ioff = 0; ioff < Type->height; ioff++) 01808 { 01809 for(iside = 0; iside < 4; iside++) 01810 num_phys_pins += num_dir[ioff][iside]; /* Num. physical pins per type */ 01811 } 01812 num_done_per_dir = 01813 (int **)alloc_matrix(0, Type->height - 1, 0, 3, sizeof(int)); 01814 for(ioff = 0; ioff < Type->height; ioff++) 01815 { 01816 for(iside = 0; iside < 4; iside++) 01817 { 01818 num_done_per_dir[ioff][iside] = 0; 01819 } 01820 } 01821 pin_num_ordering = (int *)my_malloc(num_phys_pins * sizeof(int)); 01822 side_ordering = (int *)my_malloc(num_phys_pins * sizeof(int)); 01823 offset_ordering = (int *)my_malloc(num_phys_pins * sizeof(int)); 01824 01825 /* Connection block I use distributes pins evenly across the tracks * 01826 * of ALL sides of the clb at once. Ensures that each pin connects * 01827 * to spaced out tracks in its connection block, and that the other * 01828 * pins (potentially in other C blocks) connect to the remaining tracks * 01829 * first. Doesn't matter for large Fc, but should make a fairly * 01830 * good low Fc block that leverages the fact that usually lots of pins * 01831 * are logically equivalent. */ 01832 01833 iside = LEFT; 01834 ioff = Type->height - 1; 01835 ipin = 0; 01836 pindex = -1; 01837 01838 while(ipin < num_phys_pins) 01839 { 01840 if(iside == TOP) 01841 { 01842 iside = RIGHT; 01843 } 01844 else if(iside == RIGHT) 01845 { 01846 if(ioff <= 0) 01847 { 01848 iside = BOTTOM; 01849 } 01850 else 01851 { 01852 ioff--; 01853 } 01854 } 01855 else if(iside == BOTTOM) 01856 { 01857 iside = LEFT; 01858 } 01859 else 01860 { 01861 assert(iside == LEFT); 01862 if(ioff >= Type->height - 1) 01863 { 01864 pindex++; 01865 iside = TOP; 01866 } 01867 else 01868 { 01869 ioff++; 01870 } 01871 } 01872 01873 assert(pindex < num_phys_pins); /* Number of physical pins bounds number of logical pins */ 01874 01875 if(num_done_per_dir[ioff][iside] >= num_dir[ioff][iside]) 01876 continue; 01877 pin_num_ordering[ipin] = dir_list[ioff][iside][pindex]; 01878 side_ordering[ipin] = iside; 01879 offset_ordering[ipin] = ioff; 01880 assert(Type->pinloc[ioff][iside][dir_list[ioff][iside][pindex]]); 01881 num_done_per_dir[ioff][iside]++; 01882 ipin++; 01883 } 01884 01885 if(perturb_switch_pattern) 01886 { 01887 load_perturbed_switch_pattern(Type, 01888 tracks_connected_to_pin, 01889 num_phys_pins, 01890 pin_num_ordering, 01891 side_ordering, 01892 offset_ordering, 01893 nodes_per_chan, Fc, directionality); 01894 } 01895 else 01896 { 01897 load_uniform_switch_pattern(Type, 01898 tracks_connected_to_pin, 01899 num_phys_pins, 01900 pin_num_ordering, 01901 side_ordering, 01902 offset_ordering, 01903 nodes_per_chan, Fc, directionality); 01904 } 01905 check_all_tracks_reach_pins(Type, tracks_connected_to_pin, 01906 nodes_per_chan, Fc, pin_type); 01907 01908 /* Free all temporary storage. */ 01909 free_matrix(num_dir, 0, Type->height - 1, 0, sizeof(int)); 01910 free_matrix3(dir_list, 0, Type->height - 1, 0, 3, 0, sizeof(int)); 01911 free_matrix(num_done_per_dir, 0, Type->height - 1, 0, sizeof(int)); 01912 free(pin_num_ordering); 01913 free(side_ordering); 01914 free(offset_ordering); 01915 01916 return tracks_connected_to_pin; 01917 }
static void alloc_and_load_rr_clb_source | ( | t_ivec *** | rr_node_indices | ) | [static] |
Definition at line 1149 of file rr_graph.c.
01150 { 01151 01152 /* Saves the rr_node corresponding to each SOURCE and SINK in each FB * 01153 * in the FPGA. Currently only the SOURCE rr_node values are used, and * 01154 * they are used only to reserve pins for locally used OPINs in the router. * 01155 * [0..num_blocks-1][0..num_class-1]. The values for blocks that are pads * 01156 * are NOT valid. */ 01157 01158 int iblk, i, j, iclass, inode; 01159 int class_low, class_high; 01160 t_rr_type rr_type; 01161 t_type_ptr type; 01162 01163 rr_blk_source = (int **)my_malloc(num_blocks * sizeof(int *)); 01164 01165 for(iblk = 0; iblk < num_blocks; iblk++) 01166 { 01167 type = block[iblk].type; 01168 get_class_range_for_block(iblk, &class_low, &class_high); 01169 rr_blk_source[iblk] = 01170 (int *)my_malloc(type->num_class * sizeof(int)); 01171 for(iclass = 0; iclass < type->num_class; iclass++) 01172 { 01173 if(iclass >= class_low && iclass <= class_high) 01174 { 01175 i = block[iblk].x; 01176 j = block[iblk].y; 01177 01178 if(type->class_inf[iclass].type == DRIVER) 01179 rr_type = SOURCE; 01180 else 01181 rr_type = SINK; 01182 01183 inode = 01184 get_rr_node_index(i, j, rr_type, iclass, 01185 rr_node_indices); 01186 rr_blk_source[iblk][iclass] = inode; 01187 } 01188 else 01189 { 01190 rr_blk_source[iblk][iclass] = OPEN; 01191 } 01192 } 01193 } 01194 }
static void alloc_and_load_rr_graph | ( | IN int | num_nodes, | |
IN t_rr_node * | rr_node, | |||
IN int | num_seg_types, | |||
IN t_seg_details * | seg_details, | |||
IN boolean * | rr_edge_done, | |||
IN struct s_ivec **** | track_to_ipin_lookup, | |||
IN int ***** | opin_to_track_map, | |||
IN struct s_ivec *** | switch_block_conn, | |||
IN struct s_grid_tile ** | grid, | |||
IN int | nx, | |||
IN int | ny, | |||
IN int | Fs, | |||
IN short ***** | sblock_pattern, | |||
IN int * | Fc_out, | |||
IN int ** | Fc_xofs, | |||
IN int ** | Fc_yofs, | |||
IN t_ivec *** | rr_node_indices, | |||
IN int | nodes_per_chan, | |||
IN enum e_switch_block_type | sb_type, | |||
IN int | delayless_switch, | |||
IN enum e_directionality | directionality, | |||
IN int | wire_to_ipin_switch, | |||
OUT boolean * | Fc_clipped | |||
) | [static] |
Definition at line 866 of file rr_graph.c.
00889 { 00890 00891 int i, j; 00892 boolean clipped; 00893 int *opin_mux_size = NULL; 00894 00895 00896 /* If Fc gets clipped, this will be flagged to true */ 00897 *Fc_clipped = FALSE; 00898 00899 /* Connection SINKS and SOURCES to their pins. */ 00900 for(i = 0; i <= (nx + 1); i++) 00901 { 00902 for(j = 0; j <= (ny + 1); j++) 00903 { 00904 build_rr_sinks_sources(i, j, rr_node, rr_node_indices, 00905 delayless_switch, grid); 00906 } 00907 } 00908 00909 /* Build opins */ 00910 for(i = 0; i <= (nx + 1); ++i) 00911 { 00912 for(j = 0; j <= (ny + 1); ++j) 00913 { 00914 if(BI_DIRECTIONAL == directionality) 00915 { 00916 build_bidir_rr_opins(i, j, rr_node, 00917 rr_node_indices, 00918 opin_to_track_map, Fc_out, 00919 rr_edge_done, seg_details, 00920 grid); 00921 } 00922 else 00923 { 00924 assert(UNI_DIRECTIONAL == directionality); 00925 build_unidir_rr_opins(i, j, grid, Fc_out, 00926 nodes_per_chan, seg_details, 00927 Fc_xofs, Fc_yofs, rr_node, 00928 rr_edge_done, &clipped, 00929 rr_node_indices); 00930 if(clipped) 00931 { 00932 *Fc_clipped = TRUE; 00933 } 00934 } 00935 } 00936 } 00937 00938 /* We make a copy of the current fanin values for the nodes to 00939 * know the number of OPINs driving each mux presently */ 00940 opin_mux_size = (int *)my_malloc(sizeof(int) * num_nodes); 00941 for(i = 0; i < num_nodes; ++i) 00942 { 00943 opin_mux_size[i] = rr_node[i].fan_in; 00944 } 00945 00946 /* Build channels */ 00947 assert(Fs % 3 == 0); 00948 for(i = 0; i <= nx; i++) 00949 { 00950 for(j = 0; j <= ny; j++) 00951 { 00952 if(i > 0) 00953 { 00954 build_rr_xchan(i, j, track_to_ipin_lookup, 00955 switch_block_conn, 00956 CHANX_COST_INDEX_START, 00957 nodes_per_chan, opin_mux_size, 00958 sblock_pattern, Fs / 3, 00959 seg_details, rr_node_indices, 00960 rr_edge_done, rr_node, 00961 wire_to_ipin_switch, 00962 directionality); 00963 } 00964 if(j > 0) 00965 { 00966 build_rr_ychan(i, j, track_to_ipin_lookup, 00967 switch_block_conn, 00968 CHANX_COST_INDEX_START + 00969 num_seg_types, nodes_per_chan, 00970 opin_mux_size, sblock_pattern, 00971 Fs / 3, seg_details, 00972 rr_node_indices, rr_edge_done, 00973 rr_node, wire_to_ipin_switch, 00974 directionality); 00975 } 00976 } 00977 } 00978 free(opin_mux_size); 00979 }
static struct s_ivec *** alloc_and_load_track_to_pin_lookup | ( | IN int **** | pin_to_track_map, | |
IN int | Fc, | |||
IN int | height, | |||
IN int | num_pins, | |||
IN int | nodes_per_chan | |||
) | [static, read] |
Definition at line 2134 of file rr_graph.c.
02139 { 02140 int ipin, iside, itrack, iconn, ioff, pin_counter; 02141 struct s_ivec ***track_to_pin_lookup; 02142 02143 /* [0..nodes_per_chan-1][0..height][0..3]. For each track number it stores a vector 02144 * for each of the four sides. x-directed channels will use the TOP and 02145 * BOTTOM vectors to figure out what clb input pins they connect to above 02146 * and below them, respectively, while y-directed channels use the LEFT 02147 * and RIGHT vectors. Each vector contains an nelem field saying how many 02148 * ipins it connects to. The list[0..nelem-1] array then gives the pin 02149 * numbers. */ 02150 02151 /* Note that a clb pin that connects to a channel on its RIGHT means that * 02152 * that channel connects to a clb pin on its LEFT. The convention used * 02153 * here is always in the perspective of the CLB */ 02154 02155 if(num_pins < 1) 02156 { 02157 return NULL; 02158 } 02159 02160 /* Alloc and zero the the lookup table */ 02161 track_to_pin_lookup = 02162 (struct s_ivec ***)alloc_matrix3(0, nodes_per_chan - 1, 0, 02163 height - 1, 0, 3, 02164 sizeof(struct s_ivec)); 02165 for(itrack = 0; itrack < nodes_per_chan; itrack++) 02166 { 02167 for(ioff = 0; ioff < height; ioff++) 02168 { 02169 for(iside = 0; iside < 4; iside++) 02170 { 02171 track_to_pin_lookup[itrack][ioff][iside].nelem = 02172 0; 02173 track_to_pin_lookup[itrack][ioff][iside].list = 02174 NULL; 02175 } 02176 } 02177 } 02178 02179 /* Counting pass. */ 02180 for(ipin = 0; ipin < num_pins; ipin++) 02181 { 02182 for(ioff = 0; ioff < height; ioff++) 02183 { 02184 for(iside = 0; iside < 4; iside++) 02185 { 02186 if(pin_to_track_map[ipin][ioff][iside][0] == OPEN) 02187 continue; 02188 02189 for(iconn = 0; iconn < Fc; iconn++) 02190 { 02191 itrack = 02192 pin_to_track_map[ipin][ioff][iside] 02193 [iconn]; 02194 track_to_pin_lookup[itrack][ioff][iside]. 02195 nelem++; 02196 } 02197 } 02198 } 02199 } 02200 02201 /* Allocate space. */ 02202 for(itrack = 0; itrack < nodes_per_chan; itrack++) 02203 { 02204 for(ioff = 0; ioff < height; ioff++) 02205 { 02206 for(iside = 0; iside < 4; iside++) 02207 { 02208 track_to_pin_lookup[itrack][ioff][iside].list = NULL; /* Defensive code */ 02209 if(track_to_pin_lookup[itrack][ioff][iside]. 02210 nelem != 0) 02211 { 02212 track_to_pin_lookup[itrack][ioff][iside]. 02213 list = 02214 (int *) 02215 my_malloc(track_to_pin_lookup[itrack] 02216 [ioff][iside].nelem * 02217 sizeof(int)); 02218 track_to_pin_lookup[itrack][ioff][iside]. 02219 nelem = 0; 02220 } 02221 } 02222 } 02223 } 02224 02225 /* Loading pass. */ 02226 for(ipin = 0; ipin < num_pins; ipin++) 02227 { 02228 for(ioff = 0; ioff < height; ioff++) 02229 { 02230 for(iside = 0; iside < 4; iside++) 02231 { 02232 if(pin_to_track_map[ipin][ioff][iside][0] == OPEN) 02233 continue; 02234 02235 for(iconn = 0; iconn < Fc; iconn++) 02236 { 02237 itrack = 02238 pin_to_track_map[ipin][ioff][iside] 02239 [iconn]; 02240 pin_counter = 02241 track_to_pin_lookup[itrack][ioff] 02242 [iside].nelem; 02243 track_to_pin_lookup[itrack][ioff][iside]. 02244 list[pin_counter] = ipin; 02245 track_to_pin_lookup[itrack][ioff][iside]. 02246 nelem++; 02247 } 02248 } 02249 } 02250 } 02251 02252 return track_to_pin_lookup; 02253 }
static void alloc_net_rr_terminals | ( | void | ) | [static] |
Definition at line 1095 of file rr_graph.c.
01096 { 01097 int inet; 01098 01099 net_rr_terminals = (int **)my_malloc(num_nets * sizeof(int *)); 01100 01101 for(inet = 0; inet < num_nets; inet++) 01102 { 01103 net_rr_terminals[inet] = 01104 (int *)my_chunk_malloc((net[inet].num_sinks + 1) * 01105 sizeof(int), &rr_mem_chunk_list_head, 01106 &chunk_bytes_avail, 01107 &chunk_next_avail_mem); 01108 } 01109 }
static void build_bidir_rr_opins | ( | IN int | i, | |
IN int | j, | |||
INOUT t_rr_node * | rr_node, | |||
IN t_ivec *** | rr_node_indices, | |||
IN int ***** | opin_to_track_map, | |||
IN int * | Fc_out, | |||
IN boolean * | rr_edge_done, | |||
IN t_seg_details * | seg_details, | |||
IN struct s_grid_tile ** | grid | |||
) | [static] |
Definition at line 984 of file rr_graph.c.
00993 { 00994 00995 int ipin, inode, num_edges, Fc, ofs; 00996 t_type_ptr type; 00997 struct s_linked_edge *edge_list, *next; 00998 00999 /* OPIN edges need to be done at once so let the offset 0 01000 * block do the work. */ 01001 if(grid[i][j].offset > 0) 01002 { 01003 return; 01004 } 01005 01006 type = grid[i][j].type; 01007 Fc = Fc_out[type->index]; 01008 01009 for(ipin = 0; ipin < type->num_pins; ++ipin) 01010 { 01011 /* We only are working with opins so skip non-drivers */ 01012 if(type->class_inf[type->pin_class[ipin]].type != DRIVER) 01013 { 01014 continue; 01015 } 01016 01017 num_edges = 0; 01018 edge_list = NULL; 01019 01020 for(ofs = 0; ofs < type->height; ++ofs) 01021 { 01022 num_edges += 01023 get_bidir_opin_connections(i, j + ofs, ipin, 01024 &edge_list, 01025 opin_to_track_map, Fc, 01026 rr_edge_done, 01027 rr_node_indices, 01028 seg_details); 01029 } 01030 01031 inode = get_rr_node_index(i, j, OPIN, ipin, rr_node_indices); 01032 alloc_and_load_edges_and_switches(rr_node, inode, num_edges, 01033 rr_edge_done, edge_list); 01034 while(edge_list != NULL) { 01035 next = edge_list->next; 01036 free(edge_list); 01037 edge_list = next; 01038 } 01039 } 01040 }
void build_rr_graph | ( | IN t_graph_type | graph_type, | |
IN int | num_types, | |||
IN t_type_ptr | types, | |||
IN int | nx, | |||
IN int | ny, | |||
IN struct s_grid_tile ** | grid, | |||
IN int | chan_width, | |||
IN struct s_chan_width_dist * | chan_capacity_inf, | |||
IN enum e_switch_block_type | sb_type, | |||
IN int | Fs, | |||
IN int | num_seg_types, | |||
IN int | num_switches, | |||
IN t_segment_inf * | segment_inf, | |||
IN int | global_route_switch, | |||
IN int | delayless_switch, | |||
IN t_timing_inf | timing_inf, | |||
IN int | wire_to_ipin_switch, | |||
IN enum e_base_cost_type | base_cost_type, | |||
OUT int * | Warnings | |||
) |
Definition at line 280 of file rr_graph.c.
00299 { 00300 /* Temp structures used to build graph */ 00301 int nodes_per_chan, i, j; 00302 t_seg_details *seg_details = NULL; 00303 int *Fc_in = NULL; 00304 int *Fc_out = NULL; 00305 00306 int *****opin_to_track_map = NULL; /* [0..num_types-1][0..num_pins-1][0..height][0..3][0..Fc-1] */ 00307 int *****ipin_to_track_map = NULL; /* [0..num_types-1][0..num_pins-1][0..height][0..3][0..Fc-1] */ 00308 t_ivec ****track_to_ipin_lookup = NULL; /* [0..num_types-1][0..nodes_per_chan-1][0..height][0..3] */ 00309 t_ivec ***switch_block_conn = NULL; 00310 short *****unidir_sb_pattern = NULL; 00311 boolean *rr_edge_done = NULL; 00312 boolean is_global_graph; 00313 boolean Fc_clipped; 00314 boolean use_full_seg_groups; 00315 boolean *perturb_ipins = NULL; 00316 enum e_directionality directionality; 00317 int **Fc_xofs = NULL; /* [0..ny-1][0..nx-1] */ 00318 int **Fc_yofs = NULL; /* [0..nx-1][0..ny-1] */ 00319 00320 rr_node_indices = NULL; 00321 rr_node = NULL; 00322 num_rr_nodes = 0; 00323 00324 /* Reset warning flag */ 00325 *Warnings = RR_GRAPH_NO_WARN; 00326 00327 /* Decode the graph_type */ 00328 is_global_graph = FALSE; 00329 if(GRAPH_GLOBAL == graph_type) 00330 { 00331 is_global_graph = TRUE; 00332 } 00333 use_full_seg_groups = FALSE; 00334 if(GRAPH_UNIDIR_TILEABLE == graph_type) 00335 { 00336 use_full_seg_groups = TRUE; 00337 } 00338 directionality = UNI_DIRECTIONAL; 00339 if(GRAPH_BIDIR == graph_type) 00340 { 00341 directionality = BI_DIRECTIONAL; 00342 } 00343 if(is_global_graph) 00344 { 00345 directionality = BI_DIRECTIONAL; 00346 } 00347 00348 00349 /* Global routing uses a single longwire track */ 00350 nodes_per_chan = (is_global_graph ? 1 : chan_width); 00351 assert(nodes_per_chan > 0); 00352 00353 00354 00355 /* START SEG_DETAILS */ 00356 if(is_global_graph) 00357 { 00358 /* Sets up a single unit length segment type for global routing. */ 00359 seg_details = 00360 alloc_and_load_global_route_seg_details(nodes_per_chan, 00361 global_route_switch); 00362 } 00363 else 00364 { 00365 /* Setup segments including distrubuting tracks and staggering. 00366 * If use_full_seg_groups is specified, nodes_per_chan may be 00367 * changed. Warning should be singled to caller if this happens. */ 00368 seg_details = alloc_and_load_seg_details(&nodes_per_chan, 00369 max(nx, ny), 00370 num_seg_types, 00371 segment_inf, 00372 use_full_seg_groups, 00373 is_global_graph, 00374 directionality); 00375 if((is_global_graph ? 1 : chan_width) != nodes_per_chan) 00376 { 00377 *Warnings |= RR_GRAPH_WARN_CHAN_WIDTH_CHANGED; 00378 } 00379 #ifdef CREATE_ECHO_FILES 00380 dump_seg_details(seg_details, nodes_per_chan, "seg_details.txt"); 00381 #endif /* CREATE_ECHO_FILES */ 00382 } 00383 /* END SEG_DETAILS */ 00384 00385 00386 00387 /* START FC */ 00388 /* Determine the actual value of Fc */ 00389 if(is_global_graph) 00390 { 00391 Fc_in = (int *)my_malloc(sizeof(int) * num_types); 00392 Fc_out = (int *)my_malloc(sizeof(int) * num_types); 00393 for(i = 0; i < num_types; ++i) 00394 { 00395 Fc_in[i] = 1; 00396 Fc_out[i] = 1; 00397 } 00398 } 00399 else 00400 { 00401 Fc_clipped = FALSE; 00402 Fc_in = 00403 alloc_and_load_actual_fc(num_types, types, nodes_per_chan, 00404 FALSE, directionality, &Fc_clipped); 00405 if(Fc_clipped) 00406 { 00407 *Warnings |= RR_GRAPH_WARN_FC_CLIPPED; 00408 } 00409 Fc_clipped = FALSE; 00410 Fc_out = 00411 alloc_and_load_actual_fc(num_types, types, nodes_per_chan, 00412 TRUE, directionality, &Fc_clipped); 00413 if(Fc_clipped) 00414 { 00415 *Warnings |= RR_GRAPH_WARN_FC_CLIPPED; 00416 } 00417 00418 00419 #ifdef VERBOSE 00420 for(i = 1; i < num_types; ++i) 00421 { /* Skip "<EMPTY>" */ 00422 if(type_descriptors[i].is_Fc_out_full_flex) 00423 { 00424 printf 00425 ("Fc Actual Values: Type = %s, Fc_out = full, Fc_in = %d.\n", 00426 type_descriptors[i].name, Fc_input[i]); 00427 } 00428 else 00429 { 00430 printf 00431 ("Fc Actual Values: Type = %s, Fc_out = %d, Fc_in = %d.\n", 00432 type_descriptors[i].name, Fc_output[i], 00433 Fc_input[i]); 00434 } 00435 } 00436 #endif /* VERBOSE */ 00437 } 00438 00439 perturb_ipins = 00440 alloc_and_load_perturb_ipins(nodes_per_chan, num_types, Fc_in, 00441 Fc_out, directionality); 00442 /* END FC */ 00443 00444 00445 /* Alloc node lookups, count nodes, alloc rr nodes */ 00446 num_rr_nodes = 0; 00447 rr_node_indices = 00448 alloc_and_load_rr_node_indices(nodes_per_chan, nx, ny, &num_rr_nodes, 00449 seg_details); 00450 rr_node = (t_rr_node *) my_malloc(sizeof(t_rr_node) * num_rr_nodes); 00451 memset(rr_node, 0, sizeof(t_rr_node) * num_rr_nodes); 00452 rr_edge_done = (boolean *) my_malloc(sizeof(boolean) * num_rr_nodes); 00453 memset(rr_edge_done, 0, sizeof(boolean) * num_rr_nodes); 00454 00455 /* These are data structures used by the the unidir opin mapping. */ 00456 if(UNI_DIRECTIONAL == directionality) 00457 { 00458 Fc_xofs = (int **)alloc_matrix(0, ny, 0, nx, sizeof(int)); 00459 Fc_yofs = (int **)alloc_matrix(0, nx, 0, ny, sizeof(int)); 00460 for(i = 0; i <= nx; ++i) 00461 { 00462 for(j = 0; j <= ny; ++j) 00463 { 00464 Fc_xofs[j][i] = 0; 00465 Fc_yofs[i][j] = 0; 00466 } 00467 } 00468 } 00469 00470 00471 00472 /* START SB LOOKUP */ 00473 /* Alloc and load the switch block lookup */ 00474 if(is_global_graph) 00475 { 00476 assert(nodes_per_chan == 1); 00477 switch_block_conn = 00478 alloc_and_load_switch_block_conn(1, SUBSET, 3); 00479 } 00480 else if(BI_DIRECTIONAL == directionality) 00481 { 00482 switch_block_conn = 00483 alloc_and_load_switch_block_conn(nodes_per_chan, sb_type, Fs); 00484 } 00485 else 00486 { 00487 assert(UNI_DIRECTIONAL == directionality); 00488 00489 unidir_sb_pattern = 00490 alloc_sblock_pattern_lookup(nx, ny, nodes_per_chan); 00491 for(i = 0; i <= nx; i++) 00492 { 00493 for(j = 0; j <= ny; j++) 00494 { 00495 load_sblock_pattern_lookup(i, j, nodes_per_chan, 00496 seg_details, Fs, 00497 sb_type, 00498 unidir_sb_pattern); 00499 } 00500 } 00501 } 00502 /* END SB LOOKUP */ 00503 00504 00505 00506 /* START IPIN MAP */ 00507 /* Create ipin map lookups */ 00508 ipin_to_track_map = (int *****)my_malloc(sizeof(int ****) * num_types); 00509 track_to_ipin_lookup = 00510 (struct s_ivec ****)my_malloc(sizeof(struct s_ivec ***) * num_types); 00511 for(i = 0; i < num_types; ++i) 00512 { 00513 ipin_to_track_map[i] = alloc_and_load_pin_to_track_map(RECEIVER, 00514 nodes_per_chan, 00515 Fc_in[i], 00516 &types[i], 00517 perturb_ipins 00518 [i], 00519 directionality); 00520 track_to_ipin_lookup[i] = 00521 alloc_and_load_track_to_pin_lookup(ipin_to_track_map[i], 00522 Fc_in[i], types[i].height, 00523 types[i].num_pins, 00524 nodes_per_chan); 00525 } 00526 /* END IPIN MAP */ 00527 00528 00529 00530 /* START OPIN MAP */ 00531 /* Create opin map lookups */ 00532 if(BI_DIRECTIONAL == directionality) 00533 { 00534 opin_to_track_map = 00535 (int *****)my_malloc(sizeof(int ****) * num_types); 00536 for(i = 0; i < num_types; ++i) 00537 { 00538 opin_to_track_map[i] = 00539 alloc_and_load_pin_to_track_map(DRIVER, 00540 nodes_per_chan, 00541 Fc_out[i], &types[i], 00542 FALSE, 00543 directionality); 00544 } 00545 } 00546 /* END OPIN MAP */ 00547 00548 /* UDSD Modifications by WMF begin */ 00549 /* I'm adding 2 new fields to t_rr_node, and I want them initialized to 0. */ 00550 for(i = 0; i < num_rr_nodes; i++) 00551 { 00552 rr_node[i].num_wire_drivers = 0; 00553 rr_node[i].num_opin_drivers = 0; 00554 } 00555 00556 00557 alloc_and_load_rr_graph(num_rr_nodes, rr_node, num_seg_types, 00558 seg_details, rr_edge_done, 00559 track_to_ipin_lookup, opin_to_track_map, 00560 switch_block_conn, grid, nx, 00561 ny, Fs, unidir_sb_pattern, Fc_out, Fc_xofs, 00562 Fc_yofs, rr_node_indices, nodes_per_chan, 00563 sb_type, delayless_switch, directionality, 00564 wire_to_ipin_switch, &Fc_clipped); 00565 00566 00567 #if 0 00568 #ifdef MUX_SIZE_DIST_DISPLAY 00569 if(UNI_DIRECTIONAL == directionality) 00570 { 00571 view_mux_size_distribution(rr_node_indices, nodes_per_chan, 00572 seg_details, seg_details); 00573 } 00574 #endif 00575 #endif 00576 00577 /* Update rr_nodes capacities if global routing */ 00578 if(graph_type == GLOBAL) { 00579 for(i = 0; i < num_rr_nodes; i++) { 00580 if(rr_node[i].type == CHANX || rr_node[i].type == CHANY) { 00581 rr_node[i].capacity = chan_width; 00582 } 00583 } 00584 } 00585 00586 rr_graph_externals(timing_inf, segment_inf, num_seg_types, 00587 nodes_per_chan, wire_to_ipin_switch, base_cost_type); 00588 00589 #ifdef CREATE_ECHO_FILES 00590 dump_rr_graph("rr_graph.echo"); 00591 #endif /* CREATE_ECHO_FILES */ 00592 00593 check_rr_graph(graph_type, num_types, types, nx, ny, 00594 grid, nodes_per_chan, Fs, num_seg_types, num_switches, segment_inf, 00595 global_route_switch, delayless_switch, 00596 wire_to_ipin_switch, seg_details, Fc_in, Fc_out, 00597 rr_node_indices, opin_to_track_map, ipin_to_track_map, 00598 track_to_ipin_lookup, switch_block_conn, perturb_ipins); 00599 00600 /* Free all temp structs */ 00601 if(seg_details) 00602 { 00603 free_seg_details(seg_details, nodes_per_chan); 00604 seg_details = NULL; 00605 } 00606 if(Fc_in) 00607 { 00608 free(Fc_in); 00609 Fc_in = NULL; 00610 } 00611 if(Fc_out) 00612 { 00613 free(Fc_out); 00614 Fc_out = NULL; 00615 } 00616 if(perturb_ipins) 00617 { 00618 free(perturb_ipins); 00619 perturb_ipins = NULL; 00620 } 00621 if(switch_block_conn) 00622 { 00623 free_switch_block_conn(switch_block_conn, nodes_per_chan); 00624 switch_block_conn = NULL; 00625 } 00626 if(rr_edge_done) 00627 { 00628 free(rr_edge_done); 00629 rr_edge_done = NULL; 00630 } 00631 if(Fc_xofs) 00632 { 00633 free_matrix(Fc_xofs, 0, ny, 0, sizeof(int)); 00634 Fc_xofs = NULL; 00635 } 00636 if(Fc_yofs) 00637 { 00638 free_matrix(Fc_yofs, 0, nx, 0, sizeof(int)); 00639 Fc_yofs = NULL; 00640 } 00641 if(unidir_sb_pattern) 00642 { 00643 free_sblock_pattern_lookup(unidir_sb_pattern); 00644 unidir_sb_pattern = NULL; 00645 } 00646 if(opin_to_track_map) { 00647 for(i = 0; i < num_types; ++i) 00648 { 00649 free_matrix4(opin_to_track_map[i], 0, types[i].num_pins - 1, 00650 0, types[i].height - 1, 0, 3, 0, sizeof(int)); 00651 } 00652 free(opin_to_track_map); 00653 } 00654 00655 free_type_pin_to_track_map(ipin_to_track_map, types, Fc_in); 00656 free_type_track_to_ipin_map(track_to_ipin_lookup, types, nodes_per_chan); 00657 }
static void build_rr_sinks_sources | ( | IN int | i, | |
IN int | j, | |||
IN t_rr_node * | rr_node, | |||
IN t_ivec *** | rr_node_indices, | |||
IN int | delayless_switch, | |||
IN struct s_grid_tile ** | grid | |||
) | [static] |
Definition at line 1197 of file rr_graph.c.
01203 { 01204 01205 /* Loads IPIN, SINK, SOURCE, and OPIN. 01206 * Loads IPIN to SINK edges, and SOURCE to OPIN edges */ 01207 01208 int ipin, iclass, inode, pin_num, to_node, num_edges; 01209 int num_class, num_pins; 01210 t_type_ptr type; 01211 struct s_class *class_inf; 01212 int *pin_class; 01213 01214 /* Since we share nodes within a large block, only 01215 * start tile can initialize sinks, sources, and pins */ 01216 if(grid[i][j].offset > 0) 01217 return; 01218 01219 type = grid[i][j].type; 01220 num_class = type->num_class; 01221 class_inf = type->class_inf; 01222 num_pins = type->num_pins; 01223 pin_class = type->pin_class; 01224 01225 /* SINKS and SOURCE to OPIN edges */ 01226 for(iclass = 0; iclass < num_class; iclass++) 01227 { 01228 if(class_inf[iclass].type == DRIVER) 01229 { /* SOURCE */ 01230 inode = 01231 get_rr_node_index(i, j, SOURCE, iclass, 01232 rr_node_indices); 01233 01234 num_edges = class_inf[iclass].num_pins; 01235 rr_node[inode].num_edges = num_edges; 01236 rr_node[inode].edges = 01237 (int *)my_malloc(num_edges * sizeof(int)); 01238 rr_node[inode].switches = 01239 (short *)my_malloc(num_edges * sizeof(short)); 01240 01241 for(ipin = 0; ipin < class_inf[iclass].num_pins; ipin++) 01242 { 01243 pin_num = class_inf[iclass].pinlist[ipin]; 01244 to_node = 01245 get_rr_node_index(i, j, OPIN, pin_num, 01246 rr_node_indices); 01247 rr_node[inode].edges[ipin] = to_node; 01248 rr_node[inode].switches[ipin] = delayless_switch; 01249 01250 ++rr_node[to_node].fan_in; 01251 } 01252 01253 rr_node[inode].cost_index = SOURCE_COST_INDEX; 01254 rr_node[inode].type = SOURCE; 01255 } 01256 else 01257 { /* SINK */ 01258 assert(class_inf[iclass].type == RECEIVER); 01259 inode = 01260 get_rr_node_index(i, j, SINK, iclass, 01261 rr_node_indices); 01262 01263 /* NOTE: To allow route throughs through clbs, change the lines below to * 01264 * make an edge from the input SINK to the output SOURCE. Do for just the * 01265 * special case of INPUTS = class 0 and OUTPUTS = class 1 and see what it * 01266 * leads to. If route throughs are allowed, you may want to increase the * 01267 * base cost of OPINs and/or SOURCES so they aren't used excessively. */ 01268 01269 /* Initialize to unconnected to fix values */ 01270 rr_node[inode].num_edges = 0; 01271 rr_node[inode].edges = NULL; 01272 rr_node[inode].switches = NULL; 01273 01274 rr_node[inode].cost_index = SINK_COST_INDEX; 01275 rr_node[inode].type = SINK; 01276 } 01277 01278 /* Things common to both SOURCEs and SINKs. */ 01279 rr_node[inode].capacity = class_inf[iclass].num_pins; 01280 rr_node[inode].occ = 0; 01281 rr_node[inode].xlow = i; 01282 rr_node[inode].xhigh = i; 01283 rr_node[inode].ylow = j; 01284 rr_node[inode].yhigh = j + type->height - 1; 01285 rr_node[inode].R = 0; 01286 rr_node[inode].C = 0; 01287 rr_node[inode].ptc_num = iclass; 01288 rr_node[inode].direction = OPEN; 01289 rr_node[inode].drivers = OPEN; 01290 } 01291 01292 /* Connect IPINS to SINKS and dummy for OPINS */ 01293 for(ipin = 0; ipin < num_pins; ipin++) 01294 { 01295 iclass = pin_class[ipin]; 01296 01297 if(class_inf[iclass].type == RECEIVER) 01298 { 01299 inode = 01300 get_rr_node_index(i, j, IPIN, ipin, rr_node_indices); 01301 to_node = 01302 get_rr_node_index(i, j, SINK, iclass, 01303 rr_node_indices); 01304 01305 rr_node[inode].num_edges = 1; 01306 rr_node[inode].edges = (int *)my_malloc(sizeof(int)); 01307 rr_node[inode].switches = 01308 (short *)my_malloc(sizeof(short)); 01309 01310 rr_node[inode].edges[0] = to_node; 01311 rr_node[inode].switches[0] = delayless_switch; 01312 01313 ++rr_node[to_node].fan_in; 01314 01315 rr_node[inode].cost_index = IPIN_COST_INDEX; 01316 rr_node[inode].type = IPIN; 01317 } 01318 else 01319 { 01320 assert(class_inf[iclass].type == DRIVER); 01321 01322 inode = 01323 get_rr_node_index(i, j, OPIN, ipin, rr_node_indices); 01324 01325 rr_node[inode].num_edges = 0; 01326 rr_node[inode].edges = NULL; 01327 01328 rr_node[inode].switches = NULL; 01329 01330 rr_node[inode].cost_index = OPIN_COST_INDEX; 01331 rr_node[inode].type = OPIN; 01332 } 01333 01334 /* Common to both DRIVERs and RECEIVERs */ 01335 rr_node[inode].capacity = 1; 01336 rr_node[inode].occ = 0; 01337 rr_node[inode].xlow = i; 01338 rr_node[inode].xhigh = i; 01339 rr_node[inode].ylow = j; 01340 rr_node[inode].yhigh = j + type->height - 1; 01341 rr_node[inode].C = 0; 01342 rr_node[inode].R = 0; 01343 rr_node[inode].ptc_num = ipin; 01344 rr_node[inode].direction = OPEN; 01345 rr_node[inode].drivers = OPEN; 01346 } 01347 }
static void build_rr_xchan | ( | IN int | i, | |
IN int | j, | |||
IN struct s_ivec **** | track_to_ipin_lookup, | |||
IN struct s_ivec *** | switch_block_conn, | |||
IN int | cost_index_offset, | |||
IN int | nodes_per_chan, | |||
IN int * | opin_mux_size, | |||
IN short ***** | sblock_pattern, | |||
IN int | Fs_per_side, | |||
IN t_seg_details * | seg_details, | |||
IN t_ivec *** | rr_node_indices, | |||
INOUT boolean * | rr_edge_done, | |||
INOUT t_rr_node * | rr_node, | |||
IN int | wire_to_ipin_switch, | |||
IN enum e_directionality | directionality | |||
) | [static] |
Definition at line 1352 of file rr_graph.c.
01367 { 01368 01369 /* Loads up all the routing resource nodes in the x-directed channel * 01370 * segments starting at (i,j). */ 01371 01372 int itrack, istart, iend, num_edges, inode, length; 01373 struct s_linked_edge *edge_list, *next; 01374 01375 01376 for(itrack = 0; itrack < nodes_per_chan; itrack++) 01377 { 01378 istart = get_seg_start(seg_details, itrack, j, i); 01379 iend = get_seg_end(seg_details, itrack, istart, j, nx); 01380 01381 if(i > istart) 01382 continue; /* Not the start of this segment. */ 01383 01384 edge_list = NULL; 01385 01386 /* First count number of edges and put the edges in a linked list. */ 01387 num_edges = 0; 01388 01389 num_edges += get_track_to_ipins(istart, j, itrack, 01390 &edge_list, 01391 rr_node_indices, 01392 track_to_ipin_lookup, 01393 seg_details, 01394 CHANX, nx, 01395 wire_to_ipin_switch, 01396 directionality); 01397 01398 if(j > 0) 01399 { 01400 num_edges += get_track_to_tracks(j, istart, itrack, CHANX, 01401 j, CHANY, nx, 01402 nodes_per_chan, 01403 opin_mux_size, 01404 Fs_per_side, 01405 sblock_pattern, 01406 &edge_list, 01407 seg_details, 01408 directionality, 01409 rr_node_indices, 01410 rr_edge_done, 01411 switch_block_conn); 01412 } 01413 01414 if(j < ny) 01415 { 01416 num_edges += get_track_to_tracks(j, istart, itrack, CHANX, 01417 j + 1, CHANY, nx, 01418 nodes_per_chan, 01419 opin_mux_size, 01420 Fs_per_side, 01421 sblock_pattern, 01422 &edge_list, 01423 seg_details, 01424 directionality, 01425 rr_node_indices, 01426 rr_edge_done, 01427 switch_block_conn); 01428 } 01429 01430 if(istart > 1) 01431 { 01432 num_edges += get_track_to_tracks(j, istart, itrack, CHANX, 01433 istart - 1, CHANX, nx, 01434 nodes_per_chan, 01435 opin_mux_size, 01436 Fs_per_side, 01437 sblock_pattern, 01438 &edge_list, 01439 seg_details, 01440 directionality, 01441 rr_node_indices, 01442 rr_edge_done, 01443 switch_block_conn); 01444 } 01445 01446 if(iend < nx) 01447 { 01448 num_edges += get_track_to_tracks(j, istart, itrack, CHANX, 01449 iend + 1, CHANX, nx, 01450 nodes_per_chan, 01451 opin_mux_size, 01452 Fs_per_side, 01453 sblock_pattern, 01454 &edge_list, 01455 seg_details, 01456 directionality, 01457 rr_node_indices, 01458 rr_edge_done, 01459 switch_block_conn); 01460 } 01461 01462 01463 inode = get_rr_node_index(i, j, CHANX, itrack, rr_node_indices); 01464 alloc_and_load_edges_and_switches(rr_node, inode, num_edges, 01465 rr_edge_done, edge_list); 01466 01467 while(edge_list != NULL) { 01468 next = edge_list->next; 01469 free(edge_list); 01470 edge_list = next; 01471 } 01472 01473 /* Edge arrays have now been built up. Do everything else. */ 01474 rr_node[inode].cost_index = 01475 cost_index_offset + seg_details[itrack].index; 01476 rr_node[inode].occ = 0; 01477 01478 rr_node[inode].capacity = 1; /* GLOBAL routing handled elsewhere */ 01479 01480 rr_node[inode].xlow = istart; 01481 rr_node[inode].xhigh = iend; 01482 rr_node[inode].ylow = j; 01483 rr_node[inode].yhigh = j; 01484 01485 length = iend - istart + 1; 01486 rr_node[inode].R = length * seg_details[itrack].Rmetal; 01487 rr_node[inode].C = length * seg_details[itrack].Cmetal; 01488 01489 rr_node[inode].ptc_num = itrack; 01490 rr_node[inode].type = CHANX; 01491 rr_node[inode].direction = seg_details[itrack].direction; 01492 rr_node[inode].drivers = seg_details[itrack].drivers; 01493 } 01494 }
static void build_rr_xchan | ( | IN int | i, | |
IN int | j, | |||
IN struct s_ivec **** | track_to_ipin_lookup, | |||
IN struct s_ivec *** | switch_block_conn, | |||
IN int | cost_index_offset, | |||
IN int | nodes_per_chan, | |||
IN int * | opin_mux_size, | |||
IN short ***** | sblock_pattern, | |||
IN int | Fs_per_side, | |||
IN t_seg_details * | seg_details, | |||
IN t_ivec *** | rr_node_indices, | |||
IN boolean * | rr_edge_done, | |||
INOUT t_rr_node * | rr_node, | |||
IN int | wire_to_ipin_switch, | |||
IN enum e_directionality | directionality | |||
) | [static] |
static void build_rr_ychan | ( | IN int | i, | |
IN int | j, | |||
IN struct s_ivec **** | track_to_ipin_lookup, | |||
IN struct s_ivec *** | switch_block_conn, | |||
IN int | cost_index_offset, | |||
IN int | nodes_per_chan, | |||
IN int * | opin_mux_size, | |||
IN short ***** | sblock_pattern, | |||
IN int | Fs_per_side, | |||
IN t_seg_details * | seg_details, | |||
IN t_ivec *** | rr_node_indices, | |||
IN boolean * | rr_edge_done, | |||
INOUT t_rr_node * | rr_node, | |||
IN int | wire_to_ipin_switch, | |||
IN enum e_directionality | directionality | |||
) | [static] |
Definition at line 1500 of file rr_graph.c.
01515 { 01516 01517 /* Loads up all the routing resource nodes in the y-directed channel * 01518 * segments starting at (i,j). */ 01519 01520 int itrack, istart, iend, num_edges, inode, length; 01521 struct s_linked_edge *edge_list, *next; 01522 01523 01524 for(itrack = 0; itrack < nodes_per_chan; itrack++) 01525 { 01526 istart = get_seg_start(seg_details, itrack, i, j); 01527 iend = get_seg_end(seg_details, itrack, istart, i, ny); 01528 01529 if(j > istart) 01530 continue; /* Not the start of this segment. */ 01531 01532 edge_list = NULL; 01533 01534 /* First count number of edges and put the edges in a linked list. */ 01535 num_edges = 0; 01536 01537 num_edges += get_track_to_ipins(istart, i, itrack, 01538 &edge_list, 01539 rr_node_indices, 01540 track_to_ipin_lookup, 01541 seg_details, 01542 CHANY, ny, 01543 wire_to_ipin_switch, 01544 directionality); 01545 01546 if(i > 0) 01547 { 01548 num_edges += get_track_to_tracks(i, istart, itrack, CHANY, 01549 i, CHANX, ny, 01550 nodes_per_chan, 01551 opin_mux_size, 01552 Fs_per_side, 01553 sblock_pattern, 01554 &edge_list, 01555 seg_details, 01556 directionality, 01557 rr_node_indices, 01558 rr_edge_done, 01559 switch_block_conn); 01560 } 01561 01562 if(i < nx) 01563 { 01564 num_edges += get_track_to_tracks(i, istart, itrack, CHANY, 01565 i + 1, CHANX, ny, 01566 nodes_per_chan, 01567 opin_mux_size, 01568 Fs_per_side, 01569 sblock_pattern, 01570 &edge_list, 01571 seg_details, 01572 directionality, 01573 rr_node_indices, 01574 rr_edge_done, 01575 switch_block_conn); 01576 } 01577 01578 if(istart > 1) 01579 { 01580 num_edges += get_track_to_tracks(i, istart, itrack, CHANY, 01581 istart - 1, CHANY, ny, 01582 nodes_per_chan, 01583 opin_mux_size, 01584 Fs_per_side, 01585 sblock_pattern, 01586 &edge_list, 01587 seg_details, 01588 directionality, 01589 rr_node_indices, 01590 rr_edge_done, 01591 switch_block_conn); 01592 } 01593 01594 if(iend < ny) 01595 { 01596 num_edges += get_track_to_tracks(i, istart, itrack, CHANY, 01597 iend + 1, CHANY, ny, 01598 nodes_per_chan, 01599 opin_mux_size, 01600 Fs_per_side, 01601 sblock_pattern, 01602 &edge_list, 01603 seg_details, 01604 directionality, 01605 rr_node_indices, 01606 rr_edge_done, 01607 switch_block_conn); 01608 } 01609 01610 01611 inode = get_rr_node_index(i, j, CHANY, itrack, rr_node_indices); 01612 alloc_and_load_edges_and_switches(rr_node, inode, num_edges, 01613 rr_edge_done, edge_list); 01614 01615 while(edge_list != NULL) { 01616 next = edge_list->next; 01617 free(edge_list); 01618 edge_list = next; 01619 } 01620 01621 /* Edge arrays have now been built up. Do everything else. */ 01622 rr_node[inode].cost_index = 01623 cost_index_offset + seg_details[itrack].index; 01624 rr_node[inode].occ = 0; 01625 01626 rr_node[inode].capacity = 1; /* GLOBAL routing handled elsewhere */ 01627 01628 rr_node[inode].xlow = i; 01629 rr_node[inode].xhigh = i; 01630 rr_node[inode].ylow = istart; 01631 rr_node[inode].yhigh = iend; 01632 01633 length = iend - istart + 1; 01634 rr_node[inode].R = length * seg_details[itrack].Rmetal; 01635 rr_node[inode].C = length * seg_details[itrack].Cmetal; 01636 01637 rr_node[inode].ptc_num = itrack; 01638 rr_node[inode].type = CHANY; 01639 rr_node[inode].direction = seg_details[itrack].direction; 01640 rr_node[inode].drivers = seg_details[itrack].drivers; 01641 } 01642 }
static void build_unidir_rr_opins | ( | IN int | i, | |
IN int | j, | |||
IN struct s_grid_tile ** | grid, | |||
IN int * | Fc_out, | |||
IN int | nodes_per_chan, | |||
IN t_seg_details * | seg_details, | |||
INOUT int ** | Fc_xofs, | |||
INOUT int ** | Fc_yofs, | |||
INOUT t_rr_node * | rr_node, | |||
INOUT boolean * | rr_edge_done, | |||
OUT boolean * | Fc_clipped, | |||
IN t_ivec *** | rr_node_indices | |||
) | [static] |
Definition at line 2377 of file rr_graph.c.
02389 { 02390 /* This routine returns a list of the opins rr_nodes on each 02391 * side/offset of the block. You must free the result with 02392 * free_matrix. */ 02393 02394 t_type_ptr type; 02395 int ipin, iclass, ofs, chan, seg, max_len, inode; 02396 enum e_side side; 02397 t_rr_type chan_type; 02398 t_linked_edge *edge_list = NULL, *next; 02399 boolean clipped, vert, pos_dir; 02400 int num_edges; 02401 int **Fc_ofs; 02402 02403 *Fc_clipped = FALSE; 02404 02405 /* Only the base block of a set should use this function */ 02406 if(grid[i][j].offset > 0) 02407 { 02408 return; 02409 } 02410 02411 type = grid[i][j].type; 02412 02413 /* Go through each pin and find its fanout. */ 02414 for(ipin = 0; ipin < type->num_pins; ++ipin) 02415 { 02416 /* Skip global pins and ipins */ 02417 iclass = type->pin_class[ipin]; 02418 if(type->class_inf[iclass].type != DRIVER) 02419 { 02420 continue; 02421 } 02422 if(type->is_global_pin[ipin]) 02423 { 02424 continue; 02425 } 02426 02427 num_edges = 0; 02428 edge_list = NULL; 02429 for(ofs = 0; ofs < type->height; ++ofs) 02430 { 02431 for(side = 0; side < 4; ++side) 02432 { 02433 /* Can't do anything if pin isn't at this location */ 02434 if(0 == type->pinloc[ofs][side][ipin]) 02435 { 02436 continue; 02437 } 02438 02439 /* Figure out the chan seg at that side. 02440 * side is the side of the logic or io block. */ 02441 vert = ((side == TOP) || (side == BOTTOM)); 02442 pos_dir = ((side == TOP) || (side == RIGHT)); 02443 chan_type = (vert ? CHANX : CHANY); 02444 chan = (vert ? (j + ofs) : i); 02445 seg = (vert ? i : (j + ofs)); 02446 max_len = (vert ? ny : nx); 02447 Fc_ofs = (vert ? Fc_xofs : Fc_yofs); 02448 if(FALSE == pos_dir) 02449 { 02450 --chan; 02451 } 02452 02453 /* Skip the location if there is no channel. */ 02454 if(chan < 0) 02455 { 02456 continue; 02457 } 02458 if(seg < 1) 02459 { 02460 continue; 02461 } 02462 if(seg > (vert ? ny : nx)) 02463 { 02464 continue; 02465 } 02466 if(chan > (vert ? nx : ny)) 02467 { 02468 continue; 02469 } 02470 02471 /* Get the list of opin to mux connections for that chan seg. */ 02472 num_edges += 02473 get_unidir_opin_connections(chan, seg, 02474 Fc_out[type-> 02475 index], 02476 chan_type, 02477 seg_details, 02478 &edge_list, 02479 Fc_ofs, 02480 rr_edge_done, 02481 max_len, 02482 nodes_per_chan, 02483 rr_node_indices, 02484 &clipped); 02485 if(clipped) 02486 { 02487 *Fc_clipped = TRUE; 02488 } 02489 } 02490 } 02491 02492 /* Add the edges */ 02493 inode = get_rr_node_index(i, j, OPIN, ipin, rr_node_indices); 02494 alloc_and_load_edges_and_switches(rr_node, inode, num_edges, 02495 rr_edge_done, edge_list); 02496 while(edge_list != NULL) { 02497 next = edge_list->next; 02498 free(edge_list); 02499 edge_list = next; 02500 } 02501 } 02502 }
static void check_all_tracks_reach_pins | ( | t_type_ptr | type, | |
int **** | tracks_connected_to_pin, | |||
int | nodes_per_chan, | |||
int | Fc, | |||
enum e_pin_type | ipin_or_opin | |||
) | [static] |
Definition at line 2075 of file rr_graph.c.
02080 { 02081 02082 /* Checks that all tracks can be reached by some pin. */ 02083 02084 int iconn, iside, itrack, ipin, ioff; 02085 int *num_conns_to_track; /* [0..nodes_per_chan-1] */ 02086 02087 assert(nodes_per_chan > 0); 02088 02089 num_conns_to_track = (int *)my_calloc(nodes_per_chan, sizeof(int)); 02090 02091 for(ipin = 0; ipin < type->num_pins; ipin++) 02092 { 02093 for(ioff = 0; ioff < type->height; ioff++) 02094 { 02095 for(iside = 0; iside < 4; iside++) 02096 { 02097 if(tracks_connected_to_pin[ipin][ioff][iside][0] 02098 != OPEN) 02099 { /* Pin exists */ 02100 for(iconn = 0; iconn < Fc; iconn++) 02101 { 02102 itrack = 02103 tracks_connected_to_pin[ipin] 02104 [ioff][iside][iconn]; 02105 num_conns_to_track[itrack]++; 02106 } 02107 } 02108 } 02109 } 02110 } 02111 02112 for(itrack = 0; itrack < nodes_per_chan; itrack++) 02113 { 02114 if(num_conns_to_track[itrack] <= 0) 02115 { 02116 printf 02117 ("Warning (check_all_tracks_reach_pins): track %d does not \n" 02118 "\tconnect to any FB ", itrack); 02119 02120 if(ipin_or_opin == DRIVER) 02121 printf("OPINs.\n"); 02122 else 02123 printf("IPINs.\n"); 02124 } 02125 } 02126 02127 free(num_conns_to_track); 02128 }
void dump_rr_graph | ( | IN const char * | file_name | ) |
Definition at line 2259 of file rr_graph.c.
02260 { 02261 02262 int inode; 02263 FILE *fp; 02264 02265 fp = my_fopen(file_name, "w"); 02266 02267 for(inode = 0; inode < num_rr_nodes; inode++) 02268 { 02269 print_rr_node(fp, rr_node, inode); 02270 fprintf(fp, "\n"); 02271 } 02272 02273 #if 0 02274 fprintf(fp, "\n\n%d rr_indexed_data entries.\n\n", num_rr_indexed_data); 02275 02276 for(index = 0; index < num_rr_indexed_data; index++) 02277 { 02278 print_rr_indexed_data(fp, index); 02279 fprintf(fp, "\n"); 02280 } 02281 #endif 02282 02283 fclose(fp); 02284 }
void free_rr_graph | ( | void | ) |
Definition at line 1045 of file rr_graph.c.
01046 { 01047 int i; 01048 01049 /* Frees all the routing graph data structures, if they have been * 01050 * allocated. I use rr_mem_chunk_list_head as a flag to indicate * 01051 * whether or not the graph has been allocated -- if it is not NULL, * 01052 * a routing graph exists and can be freed. Hence, you can call this * 01053 * routine even if you're not sure of whether a rr_graph exists or not. */ 01054 01055 if(rr_mem_chunk_list_head == NULL) /* Nothing to free. */ 01056 return; 01057 01058 free_chunk_memory(rr_mem_chunk_list_head); /* Frees ALL "chunked" data */ 01059 rr_mem_chunk_list_head = NULL; /* No chunks allocated now. */ 01060 chunk_bytes_avail = 0; /* 0 bytes left in current "chunk". */ 01061 chunk_next_avail_mem = NULL; /* No current chunk. */ 01062 01063 /* Before adding any more free calls here, be sure the data is NOT chunk * 01064 * allocated, as ALL the chunk allocated data is already free! */ 01065 01066 free(net_rr_terminals); 01067 01068 for(i = 0; i < num_rr_nodes; i++) { 01069 if(rr_node[i].edges != NULL) { 01070 free(rr_node[i].edges); 01071 } 01072 if(rr_node[i].switches != NULL) { 01073 free(rr_node[i].switches); 01074 } 01075 } 01076 01077 assert(rr_node_indices); 01078 free_rr_node_indices(rr_node_indices); 01079 free(rr_node); 01080 free(rr_indexed_data); 01081 for(i = 0; i < num_blocks; i++) 01082 { 01083 free(rr_blk_source[i]); 01084 } 01085 free(rr_blk_source); 01086 rr_blk_source = NULL; 01087 net_rr_terminals = NULL; 01088 rr_node = NULL; 01089 rr_node_indices = NULL; 01090 rr_indexed_data = NULL; 01091 }
static void free_type_pin_to_track_map | ( | int ***** | ipin_to_track_map, | |
t_type_ptr | types, | |||
int * | fc_in | |||
) | [static] |
Definition at line 853 of file rr_graph.c.
00854 { 00855 int i; 00856 for(i = 0; i < num_types; i++) { 00857 free_matrix4(ipin_to_track_map[i], 0, types[i].num_pins - 1, 00858 0, types[i].height - 1, 0, 3, 0, sizeof(int)); 00859 } 00860 free(ipin_to_track_map); 00861 }
static void free_type_track_to_ipin_map | ( | struct s_ivec **** | track_to_pin_map, | |
t_type_ptr | types, | |||
int | nodes_per_chan | |||
) | [static] |
Definition at line 826 of file rr_graph.c.
00827 { 00828 int i, itrack, ioff, iside; 00829 for(i = 0; i < num_types; i++) { 00830 if(track_to_pin_map[i] != NULL) { 00831 for(itrack = 0; itrack < nodes_per_chan; itrack++) 00832 { 00833 for(ioff = 0; ioff < types[i].height; ioff++) 00834 { 00835 for(iside = 0; iside < 4; iside++) 00836 { 00837 if(track_to_pin_map[i][itrack][ioff][iside].list != NULL) { 00838 free(track_to_pin_map[i][itrack][ioff][iside].list); 00839 } 00840 } 00841 } 00842 } 00843 free_matrix3(track_to_pin_map[i], 0, nodes_per_chan - 1, 0, 00844 types[i].height - 1, 0, 00845 sizeof(struct s_ivec)); 00846 } 00847 } 00848 free(track_to_pin_map); 00849 }
static int* get_adj_opins | ( | IN int | i, | |
IN int | j, | |||
OUT int * | num_pins, | |||
IN t_ivec *** | rr_node_indices, | |||
IN enum e_rr_type | chan_type | |||
) | [static] |
void load_net_rr_terminals | ( | t_ivec *** | rr_node_indices | ) |
Definition at line 1113 of file rr_graph.c.
01114 { 01115 01116 /* Allocates and loads the net_rr_terminals data structure. For each net * 01117 * it stores the rr_node index of the SOURCE of the net and all the SINKs * 01118 * of the net. [0..num_nets-1][0..num_pins-1]. Entry [inet][pnum] stores * 01119 * the rr index corresponding to the SOURCE (opin) or SINK (ipin) of pnum. */ 01120 01121 int inet, ipin, inode, iblk, i, j, k, node_block_pin, iclass; 01122 t_type_ptr type; 01123 01124 for(inet = 0; inet < num_nets; inet++) 01125 { 01126 for(ipin = 0; ipin <= net[inet].num_sinks; ipin++) 01127 { 01128 iblk = net[inet].node_block[ipin]; 01129 i = block[iblk].x; 01130 j = block[iblk].y; 01131 k = block[iblk].z; 01132 type = block[iblk].type; 01133 01134 /* In the routing graph, each (x, y) location has unique pins on it 01135 * so when there is capacity, blocks are packed and their pin numbers 01136 * are offset to get their actual rr_node */ 01137 node_block_pin = net[inet].node_block_pin[ipin]; 01138 01139 iclass = type->pin_class[node_block_pin]; 01140 01141 inode = get_rr_node_index(i, j, (ipin == 0 ? SOURCE : SINK), /* First pin is driver */ 01142 iclass, rr_node_indices); 01143 net_rr_terminals[inet][ipin] = inode; 01144 } 01145 } 01146 }
static void load_perturbed_switch_pattern | ( | IN t_type_ptr | type, | |
INOUT int **** | tracks_connected_to_pin, | |||
IN int | num_phys_pins, | |||
IN int * | pin_num_ordering, | |||
IN int * | side_ordering, | |||
IN int * | offset_ordering, | |||
IN int | nodes_per_chan, | |||
IN int | Fc, | |||
enum e_directionality | directionality | |||
) | [static] |
Definition at line 2001 of file rr_graph.c.
02010 { 02011 02012 /* Loads the tracks_connected_to_pin array with an unevenly distributed * 02013 * set of switches across the channel. This is done for inputs when * 02014 * Fc_input = Fc_output to avoid creating "pin domains" -- certain output * 02015 * pins being able to talk only to certain input pins because their switch * 02016 * patterns exactly line up. Distribute Fc/2 + 1 switches over half the * 02017 * channel and Fc/2 - 1 switches over the other half to make the switch * 02018 * pattern different from the uniform one of the outputs. Also, have half * 02019 * the pins put the "dense" part of their connections in the first half of * 02020 * the channel and the other half put the "dense" part in the second half, * 02021 * to make sure each track can connect to about the same number of ipins. */ 02022 02023 int i, j, ipin, iside, itrack, ihalf, iconn, ioff; 02024 int Fc_dense, Fc_sparse, Fc_half[2]; 02025 float f_track, spacing_dense, spacing_sparse, spacing[2]; 02026 float step_size; 02027 02028 assert(directionality == BI_DIRECTIONAL); 02029 02030 step_size = (float)nodes_per_chan / (float)(Fc * num_phys_pins); 02031 02032 Fc_dense = (Fc / 2) + 1; 02033 Fc_sparse = Fc - Fc_dense; /* Works for even or odd Fc */ 02034 02035 spacing_dense = (float)nodes_per_chan / (float)(2 * Fc_dense); 02036 spacing_sparse = (float)nodes_per_chan / (float)(2 * Fc_sparse); 02037 02038 for(i = 0; i < num_phys_pins; i++) 02039 { 02040 ipin = pin_num_ordering[i]; 02041 iside = side_ordering[i]; 02042 ioff = offset_ordering[i]; 02043 02044 /* Flip every pin to balance switch density */ 02045 spacing[i % 2] = spacing_dense; 02046 Fc_half[i % 2] = Fc_dense; 02047 spacing[(i + 1) % 2] = spacing_sparse; 02048 Fc_half[(i + 1) % 2] = Fc_sparse; 02049 02050 f_track = i * step_size; /* Start point. Staggered from pin to pin */ 02051 iconn = 0; 02052 02053 for(ihalf = 0; ihalf < 2; ihalf++) 02054 { /* For both dense and sparse halves. */ 02055 for(j = 0; j < Fc_half[ihalf]; ++j) 02056 { 02057 itrack = (int)f_track; 02058 02059 /* Can occasionally get wraparound due to floating point rounding. 02060 This is okay because the starting position > 0 when this occurs 02061 so connection is valid and fine */ 02062 itrack = itrack % nodes_per_chan; 02063 tracks_connected_to_pin[ipin][ioff][iside][iconn] 02064 = itrack; 02065 02066 f_track += spacing[ihalf]; 02067 iconn++; 02068 } 02069 } 02070 } /* End for all physical pins. */ 02071 }
static void load_perturbed_switch_pattern | ( | IN t_type_ptr | type, | |
INOUT int **** | tracks_connected_to_pin, | |||
IN int | num_phys_pins, | |||
IN int * | pin_num_ordering, | |||
IN int * | side_ordering, | |||
IN int * | offset_ordering, | |||
IN int | nodes_per_chan, | |||
IN int | Fc, | |||
IN enum e_directionality | directionality | |||
) | [static] |
static void load_uniform_opin_switch_pattern_paired | ( | IN int * | Fc_out, | |
IN int | num_pins, | |||
IN int * | pins_in_chan_seg, | |||
IN int | num_wire_inc_muxes, | |||
IN int | num_wire_dec_muxes, | |||
IN int * | wire_inc_muxes, | |||
IN int * | wire_dec_muxes, | |||
INOUT t_rr_node * | rr_node, | |||
INOUT boolean * | rr_edge_done, | |||
IN t_seg_details * | seg_details, | |||
OUT boolean * | Fc_clipped | |||
) | [static] |
Definition at line 2505 of file rr_graph.c.
02516 { 02517 02518 /* Directionality is assumed to be uni-directional */ 02519 02520 /* Make turn-based assignment to avoid overlap when Fc_ouput is low. This is a bipartite 02521 * matching problem. Out of "num_wire_muxes" muxes "Fc_output" of them is assigned 02522 * to each outpin (total "num_pins" of them); assignment is uniform (spacing - spreadout) 02523 * and staggered to avoid overlap when Fc_output is low. */ 02524 02525 /* The natural order wires muxes are stored in wire_muxes is alternating in directionality 02526 * already (by my implementation), so no need to do anything extra to avoid directional bias */ 02527 02528 /* TODO: Due to spacing, it's possible to have directional bias: all Fc_out wires connected 02529 * to one opin goes in either INC or DEC -> whereas I want a mix of both. 02530 * SOLUTION: Use quantization of 2 to ensure that if an opin connects to one wire, it 02531 * must also connect to its companion wire, which runs in the opposite direction. This 02532 * means instead of having num_wire_muxes as the matching set, pick out the INC wires 02533 * in num_wires_muxes as the matching set (the DEC wires are their companions) April 17, 2007 02534 * NEWS: That solution does not work, as treating wires in groups will lead to serious 02535 * abnormal patterns (conns crossing multiple blocks) for W nonquantized to multiples of 2L. 02536 * So, I'm chaning that approach to a new one that avoids directional bias: I will separate 02537 * the INC muxes and DEC muxes into two sets. Each set is uniformly assigned to opins with 02538 * Fc_output/2; this should be identical as before for normal cases and contains all conns 02539 * in the same chan segment for the nonquantized cases. */ 02540 02541 /* Finally, separated the two approaches: 1. Take all wire muxes and assign them to opins 02542 * one at a time (load_uniform_opin_switch_pattern) 2. Take pairs (by companion) 02543 * of wire muxes and assign them to opins a pair at a time (load_uniform_opin_switch_pattern_paired). 02544 * The first is used for fringe channel segments (ends of channels, where 02545 * there are lots of muxes due to partial wire segments) and the second is used in core */ 02546 02547 /* float spacing, step_size, f_mux; */ 02548 int ipin, iconn, num_edges, init_mux; 02549 int from_node, to_node, to_track; 02550 int xlow, ylow; 02551 t_linked_edge *edge_list; 02552 int *wire_muxes; 02553 int k, num_wire_muxes, Fc_output_per_side, CurFc; 02554 int count_inc, count_dec; 02555 t_type_ptr type; 02556 02557 *Fc_clipped = FALSE; 02558 02559 count_inc = count_dec = 0; 02560 02561 for(ipin = 0; ipin < num_pins; ipin++) 02562 { 02563 from_node = pins_in_chan_seg[ipin]; 02564 xlow = rr_node[from_node].xlow; 02565 ylow = rr_node[from_node].ylow; 02566 type = grid[xlow][ylow].type; 02567 edge_list = NULL; 02568 num_edges = 0; 02569 02570 /* Assigning the INC muxes first, then DEC muxes */ 02571 for(k = 0; k < 2; ++k) 02572 { 02573 if(k == 0) 02574 { 02575 num_wire_muxes = num_wire_inc_muxes; 02576 wire_muxes = wire_inc_muxes; 02577 } 02578 else 02579 { 02580 num_wire_muxes = num_wire_dec_muxes; 02581 wire_muxes = wire_dec_muxes; 02582 } 02583 02584 /* Half the Fc will be assigned for each direction. */ 02585 assert(Fc_out[type->index] % 2 == 0); 02586 Fc_output_per_side = Fc_out[type->index] / 2; 02587 02588 /* Clip the demand. Make sure to use a new variable so 02589 * on the second pass it is not clipped. */ 02590 CurFc = Fc_output_per_side; 02591 if(Fc_output_per_side > num_wire_muxes) 02592 { 02593 *Fc_clipped = TRUE; 02594 CurFc = num_wire_muxes; 02595 } 02596 02597 if(k == 0) 02598 { 02599 init_mux = (count_inc) % num_wire_muxes; 02600 count_inc += CurFc; 02601 } 02602 else 02603 { 02604 init_mux = (count_dec) % num_wire_muxes; 02605 count_dec += CurFc; 02606 } 02607 02608 for(iconn = 0; iconn < CurFc; iconn++) 02609 { 02610 /* FINALLY, make the outpin to mux connection */ 02611 /* Latest update: I'm not using Uniform Pattern, but a similarly staggered pattern */ 02612 to_node = 02613 wire_muxes[(init_mux + 02614 iconn) % num_wire_muxes]; 02615 02616 rr_node[to_node].num_opin_drivers++; /* keep track of mux size */ 02617 to_track = rr_node[to_node].ptc_num; 02618 02619 if(FALSE == rr_edge_done[to_node]) 02620 { 02621 /* Use of alloc_and_load_edges_and_switches 02622 * must be accompanied by rr_edge_done check. */ 02623 rr_edge_done[to_node] = TRUE; 02624 edge_list = 02625 insert_in_edge_list(edge_list, 02626 to_node, 02627 seg_details 02628 [to_track]. 02629 wire_switch); 02630 num_edges++; 02631 } 02632 } 02633 } 02634 02635 if(num_edges < 1) 02636 { 02637 printf 02638 ("Error: opin %d at (%d,%d) does not connect to any " 02639 "tracks.\n", rr_node[from_node].ptc_num, 02640 rr_node[from_node].xlow, rr_node[from_node].ylow); 02641 exit(1); 02642 } 02643 02644 alloc_and_load_edges_and_switches(rr_node, from_node, num_edges, 02645 rr_edge_done, edge_list); 02646 } 02647 }
static void load_uniform_switch_pattern | ( | IN t_type_ptr | type, | |
INOUT int **** | tracks_connected_to_pin, | |||
IN int | num_phys_pins, | |||
IN int * | pin_num_ordering, | |||
IN int * | side_ordering, | |||
IN int * | offset_ordering, | |||
IN int | nodes_per_chan, | |||
IN int | Fc, | |||
enum e_directionality | directionality | |||
) | [static] |
Definition at line 1923 of file rr_graph.c.
01932 { 01933 01934 /* Loads the tracks_connected_to_pin array with an even distribution of * 01935 * switches across the tracks for each pin. For example, each pin connects * 01936 * to every 4.3rd track in a channel, with exactly which tracks a pin * 01937 * connects to staggered from pin to pin. */ 01938 01939 int i, j, ipin, iside, ioff, itrack, k; 01940 float f_track, fc_step; 01941 int group_size; 01942 float step_size; 01943 01944 /* Uni-directional drive is implemented to ensure no directional bias and this means 01945 * two important comments noted below */ 01946 /* 1. Spacing should be (W/2)/(Fc/2), and step_size should be spacing/(num_phys_pins), 01947 * and lay down 2 switches on an adjacent pair of tracks at a time to ensure 01948 * no directional bias. Basically, treat W (even) as W/2 pairs of tracks, and 01949 * assign switches to a pair at a time. Can do this because W is guaranteed to 01950 * be even-numbered; however same approach cannot be applied to Fc_out pattern 01951 * when L > 1 and W <> 2L multiple. 01952 * 01953 * 2. This generic pattern should be considered the tileable physical layout, 01954 * meaning all track # here are physical #'s, 01955 * so later must use vpr_to_phy conversion to find actual logical #'s to connect. 01956 * This also means I will not use get_output_block_companion_track to ensure 01957 * no bias, since that describes a logical # -> that would confuse people. */ 01958 01959 step_size = (float)nodes_per_chan / (float)(Fc * num_phys_pins); 01960 01961 if(directionality == BI_DIRECTIONAL) 01962 { 01963 group_size = 1; 01964 } 01965 else 01966 { 01967 assert(directionality == UNI_DIRECTIONAL); 01968 group_size = 2; 01969 } 01970 01971 assert((nodes_per_chan % group_size == 0) && (Fc % group_size == 0)); 01972 01973 fc_step = (float)nodes_per_chan / (float)Fc; 01974 01975 for(i = 0; i < num_phys_pins; i++) 01976 { 01977 ipin = pin_num_ordering[i]; 01978 iside = side_ordering[i]; 01979 ioff = offset_ordering[i]; 01980 01981 /* Bi-directional treats each track separately, uni-directional works with pairs of tracks */ 01982 for(j = 0; j < (Fc / group_size); j++) 01983 { 01984 f_track = (i * step_size) + (j * fc_step); 01985 itrack = ((int)f_track) * group_size; 01986 01987 /* Catch possible floating point round error */ 01988 itrack = min(itrack, nodes_per_chan - group_size); 01989 01990 /* Assign the group of tracks for the Fc pattern */ 01991 for(k = 0; k < group_size; ++k) 01992 { 01993 tracks_connected_to_pin[ipin][ioff][iside] 01994 [group_size * j + k] = itrack + k; 01995 } 01996 } 01997 } 01998 }
static void load_uniform_switch_pattern | ( | IN t_type_ptr | type, | |
INOUT int **** | tracks_connected_to_pin, | |||
IN int | num_phys_pins, | |||
IN int * | pin_num_ordering, | |||
IN int * | side_ordering, | |||
IN int * | offset_ordering, | |||
IN int | nodes_per_chan, | |||
IN int | Fc, | |||
IN enum e_directionality | directionality | |||
) | [static] |
static void print_distribution | ( | FILE * | fptr, | |
t_mux_size_distribution * | distr_struct | |||
) | [static] |
Definition at line 3043 of file rr_graph.c.
03045 { 03046 int *distr; 03047 int k; 03048 float sum; 03049 boolean zeros; 03050 03051 distr = distr_struct->distr; 03052 fprintf(fptr, 03053 "For Sblocks containing %d MUXes, the MUX size distribution is:\n", 03054 distr_struct->mux_count); 03055 fprintf(fptr, "\t\t\tSize\t\t\tFrequency (percent)\n"); 03056 03057 sum = 0.0; 03058 for(k = 0; k <= distr_struct->max_index; k++) 03059 sum += distr[k]; 03060 03061 zeros = TRUE; 03062 for(k = 0; k <= distr_struct->max_index; k++) 03063 { 03064 if(zeros && (distr[k] == 0)) 03065 { 03066 /* do nothing for leading string of zeros */ 03067 } 03068 else 03069 { 03070 zeros = FALSE; /* leading string of zeros ended */ 03071 fprintf(fptr, "\t\t\t%d\t\t\t%d (%.2f%%)\n", k, distr[k], 03072 (float)distr[k] / sum * 100.0); 03073 } 03074 } 03075 fprintf(fptr, "\nEnd of this Sblock MUX size distribution.\n"); 03076 03077 }
void print_rr_indexed_data | ( | FILE * | fp, | |
int | index | |||
) |
Definition at line 2354 of file rr_graph.c.
02356 { 02357 02358 fprintf(fp, "Index: %d\n", index); 02359 02360 fprintf(fp, "ortho_cost_index: %d ", 02361 rr_indexed_data[index].ortho_cost_index); 02362 fprintf(fp, "base_cost: %g ", rr_indexed_data[index].saved_base_cost); 02363 fprintf(fp, "saved_base_cost: %g\n", 02364 rr_indexed_data[index].saved_base_cost); 02365 02366 fprintf(fp, "Seg_index: %d ", rr_indexed_data[index].seg_index); 02367 fprintf(fp, "inv_length: %g\n", rr_indexed_data[index].inv_length); 02368 02369 fprintf(fp, "T_linear: %g ", rr_indexed_data[index].T_linear); 02370 fprintf(fp, "T_quadratic: %g ", rr_indexed_data[index].T_quadratic); 02371 fprintf(fp, "C_load: %g\n", rr_indexed_data[index].C_load); 02372 }
static void print_rr_node | ( | FILE * | fp, | |
t_rr_node * | rr_node, | |||
int | inode | |||
) | [static] |
Definition at line 2289 of file rr_graph.c.
02292 { 02293 02294 static const char *name_type[] = { 02295 "SOURCE", "SINK", "IPIN", "OPIN", "CHANX", "CHANY" 02296 }; 02297 static const char *direction_name[] = { 02298 "OPEN", "INC_DIRECTION", "DEC_DIRECTION", "BI_DIRECTION" 02299 }; 02300 static const char *drivers_name[] = { 02301 "OPEN", "MULTI_BUFFER", "MULTI_MUXED", "MULTI_MERGED", "SINGLE" 02302 }; 02303 02304 t_rr_type rr_type; 02305 int iconn; 02306 02307 rr_type = rr_node[inode].type; 02308 02309 /* Make sure we don't overrun const arrays */ 02310 assert(rr_type < (sizeof(name_type) / sizeof(char *))); 02311 assert((rr_node[inode].direction + 1) < 02312 (sizeof(direction_name) / sizeof(char *))); 02313 assert((rr_node[inode].drivers + 1) < 02314 (sizeof(drivers_name) / sizeof(char *))); 02315 02316 fprintf(fp, "Node: %d %s ", inode, name_type[rr_type]); 02317 if((rr_node[inode].xlow == rr_node[inode].xhigh) && 02318 (rr_node[inode].ylow == rr_node[inode].yhigh)) 02319 { 02320 fprintf(fp, "(%d, %d) ", rr_node[inode].xlow, 02321 rr_node[inode].ylow); 02322 } 02323 else 02324 { 02325 fprintf(fp, "(%d, %d) to (%d, %d) ", rr_node[inode].xlow, 02326 rr_node[inode].ylow, rr_node[inode].xhigh, 02327 rr_node[inode].yhigh); 02328 } 02329 fprintf(fp, "Ptc_num: %d ", rr_node[inode].ptc_num); 02330 fprintf(fp, "Direction: %s ", 02331 direction_name[rr_node[inode].direction + 1]); 02332 fprintf(fp, "Drivers: %s ", drivers_name[rr_node[inode].drivers + 1]); 02333 fprintf(fp, "\n"); 02334 02335 fprintf(fp, "%d edge(s):", rr_node[inode].num_edges); 02336 for(iconn = 0; iconn < rr_node[inode].num_edges; iconn++) 02337 fprintf(fp, " %d", rr_node[inode].edges[iconn]); 02338 fprintf(fp, "\n"); 02339 02340 fprintf(fp, "Switch types:"); 02341 for(iconn = 0; iconn < rr_node[inode].num_edges; iconn++) 02342 fprintf(fp, " %d", rr_node[inode].switches[iconn]); 02343 fprintf(fp, "\n"); 02344 02345 fprintf(fp, "Occ: %d Capacity: %d\n", rr_node[inode].occ, 02346 rr_node[inode].capacity); 02347 fprintf(fp, "R: %g C: %g\n", rr_node[inode].R, rr_node[inode].C); 02348 fprintf(fp, "Cost_index: %d\n", rr_node[inode].cost_index); 02349 }
static void rr_graph_externals | ( | t_timing_inf | timing_inf, | |
t_segment_inf * | segment_inf, | |||
int | num_seg_types, | |||
int | nodes_per_chan, | |||
int | wire_to_ipin_switch, | |||
enum e_base_cost_type | base_cost_type | |||
) | [static] |
Definition at line 661 of file rr_graph.c.
00667 { 00668 add_rr_graph_C_from_switches(timing_inf.C_ipin_cblock); 00669 alloc_and_load_rr_indexed_data(segment_inf, num_seg_types, 00670 rr_node_indices, nodes_per_chan, 00671 wire_to_ipin_switch, base_cost_type); 00672 00673 alloc_net_rr_terminals(); 00674 load_net_rr_terminals(rr_node_indices); 00675 alloc_and_load_rr_clb_source(rr_node_indices); 00676 }
static int track_side | ( | int | clb_side | ) | [static] |
static void view_mux_size_distribution | ( | t_ivec *** | rr_node_indices, | |
int | nodes_per_chan, | |||
t_seg_details * | seg_details_x, | |||
t_seg_details * | seg_details_y | |||
) | [static] |
Definition at line 2660 of file rr_graph.c.
02664 { 02665 02666 int i, j, itrack, seg_num, chan_num, max_len; 02667 int start, end, inode, max_value, min_value; 02668 int array_count, k, num_muxes; 02669 short direction, side; 02670 float *percent_range_array; 02671 float percent_range, percent_range_sum, avg_percent_range; 02672 float std_dev_percent_range, deviation_f; 02673 int range, *range_array, global_max_range; 02674 float avg_range, range_sum, std_dev_range; 02675 t_seg_details *seg_details; 02676 t_mux *new_mux, *sblock_mux_list_head, *current, *next; 02677 02678 #ifdef ENABLE_DUMP 02679 FILE *dump_file_per_sblock, *dump_file; 02680 #endif /* ENABLE_DUMP */ 02681 t_mux_size_distribution *distr_list, *distr_current, *new_distribution, 02682 *distr_next; 02683 02684 #ifdef ENABLE_DUMP 02685 dump_file = my_fopen("mux_size_dump.txt", "w"); 02686 dump_file_per_sblock = my_fopen("mux_size_per_sblock_dump.txt", "w"); 02687 #endif /* ENABLE_DUMP */ 02688 02689 sblock_mux_list_head = NULL; 02690 percent_range_array = 02691 (float *)my_malloc((nx - 1) * (ny - 1) * sizeof(float)); 02692 range_array = (int *)my_malloc((nx - 1) * (ny - 1) * sizeof(int)); 02693 array_count = 0; 02694 percent_range_sum = 0.0; 02695 range_sum = 0.0; 02696 global_max_range = 0; 02697 min_value = 0; 02698 max_value = 0; 02699 seg_num = 0; 02700 chan_num = 0; 02701 direction = 0; 02702 seg_details = 0; 02703 max_len = 0; 02704 distr_list = NULL; 02705 02706 /* With the specified range, I'm only looking at core sblocks */ 02707 for(j = (ny - 1); j > 0; j--) 02708 { 02709 for(i = 1; i < nx; i++) 02710 { 02711 num_muxes = 0; 02712 for(side = 0; side < 4; side++) 02713 { 02714 switch (side) 02715 { 02716 case LEFT: 02717 seg_num = i; 02718 chan_num = j; 02719 direction = DEC_DIRECTION; /* only DEC have muxes in that sblock */ 02720 seg_details = seg_details_x; 02721 max_len = nx; 02722 break; 02723 02724 case RIGHT: 02725 seg_num = i + 1; 02726 chan_num = j; 02727 direction = INC_DIRECTION; 02728 seg_details = seg_details_x; 02729 max_len = nx; 02730 break; 02731 02732 case TOP: 02733 seg_num = j + 1; 02734 chan_num = i; 02735 direction = INC_DIRECTION; 02736 seg_details = seg_details_y; 02737 max_len = ny; 02738 break; 02739 02740 case BOTTOM: 02741 seg_num = j; 02742 chan_num = i; 02743 direction = DEC_DIRECTION; 02744 seg_details = seg_details_y; 02745 max_len = ny; 02746 break; 02747 02748 default: 02749 assert(FALSE); 02750 } 02751 02752 assert(nodes_per_chan > 0); 02753 for(itrack = 0; itrack < nodes_per_chan; itrack++) 02754 { 02755 start = 02756 get_seg_start(seg_details, itrack, 02757 seg_num, chan_num); 02758 end = 02759 get_seg_end(seg_details, itrack, 02760 start, chan_num, max_len); 02761 02762 if((seg_details[itrack].direction == 02763 direction) && (((start == seg_num) 02764 && (direction == 02765 INC_DIRECTION)) 02766 || ((end == seg_num) 02767 && (direction == 02768 DEC_DIRECTION)))) 02769 { /* mux found */ 02770 num_muxes++; 02771 if(side == LEFT || side == RIGHT) 02772 { /* CHANX */ 02773 inode = 02774 get_rr_node_index 02775 (seg_num, chan_num, 02776 CHANX, itrack, 02777 rr_node_indices); 02778 } 02779 else 02780 { 02781 assert((side == TOP) || (side == BOTTOM)); /* CHANY */ 02782 inode = 02783 get_rr_node_index 02784 (chan_num, seg_num, 02785 CHANY, itrack, 02786 rr_node_indices); 02787 } 02788 02789 new_mux = (t_mux *) 02790 my_malloc(sizeof(t_mux)); 02791 new_mux->size = 02792 rr_node[inode]. 02793 num_wire_drivers + 02794 rr_node[inode]. 02795 num_opin_drivers; 02796 new_mux->next = NULL; 02797 02798 /* insert in linked list, descending */ 02799 if(sblock_mux_list_head == NULL) 02800 { 02801 /* first entry */ 02802 sblock_mux_list_head = 02803 new_mux; 02804 } 02805 else if(sblock_mux_list_head-> 02806 size < new_mux->size) 02807 { 02808 /* insert before head */ 02809 new_mux->next = 02810 sblock_mux_list_head; 02811 sblock_mux_list_head = 02812 new_mux; 02813 } 02814 else 02815 { 02816 /* insert after head */ 02817 current = 02818 sblock_mux_list_head; 02819 next = current->next; 02820 02821 while((next != NULL) 02822 && (next->size > 02823 new_mux->size)) 02824 { 02825 current = next; 02826 next = 02827 current->next; 02828 } 02829 02830 if(next == NULL) 02831 { 02832 current->next = 02833 new_mux; 02834 } 02835 else 02836 { 02837 new_mux->next = 02838 current->next; 02839 current->next = 02840 new_mux; 02841 } 02842 } 02843 /* end of insert in linked list */ 02844 } 02845 } 02846 } /* end of mux searching over all four sides of sblock */ 02847 /* now sblock_mux_list_head holds a linked list of all muxes in this sblock */ 02848 02849 current = sblock_mux_list_head; 02850 02851 #ifdef ENABLE_DUMP 02852 fprintf(dump_file_per_sblock, 02853 "sblock at (%d, %d) has mux sizes: {", i, j); 02854 #endif /* ENABLE_DUMP */ 02855 02856 if(current != NULL) 02857 { 02858 max_value = min_value = current->size; 02859 } 02860 while(current != NULL) 02861 { 02862 if(max_value < current->size) 02863 max_value = current->size; 02864 if(min_value > current->size) 02865 min_value = current->size; 02866 02867 #ifdef ENABLE_DUMP 02868 fprintf(dump_file_per_sblock, "%d ", 02869 current->size); 02870 fprintf(dump_file, "%d\n", current->size); 02871 #endif /* ENABLE_DUMP */ 02872 02873 current = current->next; 02874 } 02875 02876 #ifdef ENABLE_DUMP 02877 fprintf(dump_file_per_sblock, "}\n\tmax: %d\tmin:%d", 02878 max_value, min_value); 02879 #endif /* ENABLE_DUMP */ 02880 02881 range = max_value - min_value; 02882 percent_range = ((float)range) / ((float)min_value); 02883 02884 if(global_max_range < range) 02885 global_max_range = range; 02886 02887 #ifdef ENABLE_DUMP 02888 fprintf(dump_file_per_sblock, 02889 "\t\trange: %d\t\tpercent range:%.2f\n", 02890 range, percent_range); 02891 #endif /* ENABLE_DUMP */ 02892 02893 percent_range_array[array_count] = percent_range; 02894 range_array[array_count] = range; 02895 02896 percent_range_sum += percent_range; 02897 range_sum += range; 02898 02899 array_count++; 02900 02901 /* I will use a distribution for each (core) sblock type. 02902 * There are more than 1 type of sblocks, 02903 * when quantization of W to 2L multiples is not observed. */ 02904 02905 02906 02907 distr_current = distr_list; 02908 while(distr_current != NULL 02909 && distr_current->mux_count != num_muxes) 02910 { 02911 distr_current = distr_current->next; 02912 } 02913 02914 if(distr_current == NULL) 02915 { 02916 /* Create a distribution for the new sblock type, 02917 * and put it as head of linked list by convention */ 02918 02919 new_distribution = (t_mux_size_distribution *) 02920 my_malloc(sizeof(t_mux_size_distribution)); 02921 new_distribution->mux_count = num_muxes; 02922 new_distribution->max_index = max_value; 02923 new_distribution->distr = 02924 (int *)my_calloc(max_value + 1, sizeof(int)); 02925 02926 /* filling in the distribution */ 02927 current = sblock_mux_list_head; 02928 while(current != NULL) 02929 { 02930 assert(current->size <= 02931 new_distribution->max_index); 02932 new_distribution->distr[current->size]++; 02933 current = current->next; 02934 } 02935 02936 /* add it to head */ 02937 new_distribution->next = distr_list; 02938 distr_list = new_distribution; 02939 } 02940 else 02941 { 02942 /* distr_current->mux_count == num_muxes so add this sblock's mux sizes in this distribution */ 02943 current = sblock_mux_list_head; 02944 02945 while(current != NULL) 02946 { 02947 if(current->size > 02948 distr_current->max_index) 02949 { 02950 /* needs to realloc to expand the distribution array to hold the new large-valued data */ 02951 distr_current->distr = 02952 my_realloc(distr_current-> 02953 distr, 02954 (current->size + 02955 1) * sizeof(int)); 02956 02957 /* initializing the newly allocated elements */ 02958 for(k = 02959 (distr_current->max_index + 02960 1); k <= current->size; k++) 02961 distr_current->distr[k] = 0; 02962 02963 distr_current->max_index = 02964 current->size; 02965 distr_current->distr[current-> 02966 size]++; 02967 } 02968 else 02969 { 02970 distr_current->distr[current-> 02971 size]++; 02972 } 02973 current = current->next; 02974 } 02975 } 02976 02977 /* done - now free memory */ 02978 current = sblock_mux_list_head; 02979 while(current != NULL) 02980 { 02981 next = current->next; 02982 free(current); 02983 current = next; 02984 } 02985 sblock_mux_list_head = NULL; 02986 } 02987 } 02988 02989 avg_percent_range = (float)percent_range_sum / array_count; 02990 avg_range = (float)range_sum / array_count; 02991 02992 percent_range_sum = 0.0; 02993 range_sum = 0.0; 02994 for(k = 0; k < array_count; k++) 02995 { 02996 deviation_f = (percent_range_array[k] - avg_percent_range); 02997 percent_range_sum += deviation_f * deviation_f; 02998 02999 deviation_f = ((float)range_array[k] - avg_range); 03000 range_sum += deviation_f * deviation_f; 03001 } 03002 std_dev_percent_range = 03003 sqrt(percent_range_sum / ((float)array_count - 1.0)); 03004 std_dev_range = sqrt(range_sum / ((float)array_count - 1.0)); 03005 printf("==== MUX size statistics ====\n"); 03006 printf("max range of mux size within a sblock is; %d\n", 03007 global_max_range); 03008 printf("average range of mux size within a sblock is; %.2f\n", avg_range); 03009 printf("std dev of range of mux size within a sblock is; %.2f\n", 03010 std_dev_range); 03011 printf 03012 ("average percent range of mux size within a sblock is; %.2f%%\n", 03013 avg_percent_range * 100.0); 03014 printf 03015 ("std dev of percent range of mux size within a sblock is; %.2f%%\n", 03016 std_dev_percent_range * 100.0); 03017 03018 printf(" -- Detailed MUX size distribution by sblock type -- \n"); 03019 distr_current = distr_list; 03020 while(distr_current != NULL) 03021 { 03022 print_distribution(stdout, distr_current); 03023 03024 /* free */ 03025 distr_next = distr_current->next; 03026 03027 free(distr_current->distr); 03028 free(distr_current); 03029 03030 distr_current = distr_next; 03031 } 03032 03033 free(percent_range_array); 03034 free(range_array); 03035 #ifdef ENABLE_DUMP 03036 fclose(dump_file_per_sblock); 03037 fclose(dump_file); 03038 #endif /* ENABLE_DUMP */ 03039 }
void watch_edges | ( | int | inode, | |
t_linked_edge * | edge_list_head | |||
) |
Definition at line 1645 of file rr_graph.c.
01647 { 01648 t_linked_edge *list_ptr; 01649 int i, to_node; 01650 01651 list_ptr = edge_list_head; 01652 i = 0; 01653 01654 printf("!!! Watching Node %d !!!!\n", inode); 01655 print_rr_node(stdout, rr_node, inode); 01656 printf("Currently connects to: \n"); 01657 while(list_ptr != NULL) 01658 { 01659 to_node = list_ptr->edge; 01660 print_rr_node(stdout, rr_node, to_node); 01661 list_ptr = list_ptr->next; 01662 i++; 01663 } 01664 }
int chunk_bytes_avail = 0 [static] |
Definition at line 55 of file rr_graph.c.
char* chunk_next_avail_mem = NULL [static] |
Definition at line 56 of file rr_graph.c.
struct s_linked_vptr* rr_mem_chunk_list_head = NULL [static] |
Definition at line 51 of file rr_graph.c.