SRC/rr_graph.c File Reference

#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"
Include dependency graph for rr_graph.c:

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 booleanalloc_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_detailsalloc_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_vptrrr_mem_chunk_list_head = NULL
static int chunk_bytes_avail = 0
static char * chunk_next_avail_mem = NULL

Define Documentation

#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 Documentation

typedef struct s_mux t_mux

Function Documentation

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

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 
)

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

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]

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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]

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

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]

Here is the caller graph for this function:

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 }

Here is the caller graph for this function:

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 }

Here is the caller graph for this function:

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 }

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:


Variable Documentation

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.


Generated on Tue Jan 5 15:26:24 2010 for VPR5.0 by  doxygen 1.6.1