⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 route_common.c

📁 fpga设计评估软件
💻 C
📖 第 1 页 / 共 3 页
字号:
#include <math.h>#include <stdio.h>#include "util.h"#include "vpr_types.h"#include "globals.h" #include "route_export.h"#include "route_common.h"#include "route_tree_timing.h"#include "route_timing.h"#include "route_breadth_first.h"#include "place_and_route.h"#include "rr_graph.h"/***************** Variables shared only by route modules *******************/t_rr_node_route_inf *rr_node_route_inf = NULL;       /* [0..num_rr_nodes-1] */struct s_bb *route_bb = NULL; /* [0..num_nets-1]. Limits area in which each  */                              /* net must be routed.                         *//**************** Static variables local to route_common.c ******************/static struct s_heap **heap;  /* Indexed from [1..heap_size] */static int heap_size;   /* Number of slots in the heap array */static int heap_tail;   /* Index of first unused slot in the heap array *//* For managing my own list of currently free heap data structures.     */static struct s_heap *heap_free_head = NULL; /* For managing my own list of currently free trace data structures.    */static struct s_trace *trace_free_head = NULL;#ifdef DEBUG static int num_trace_allocated = 0;   /* To watch for memory leaks. */ static int num_heap_allocated = 0; static int num_linked_f_pointer_allocated = 0;#endifstatic struct s_linked_f_pointer *rr_modified_head = NULL;static struct s_linked_f_pointer *linked_f_pointer_free_head = NULL;/*  The numbering relation between the channels and clbs is:               * *                                                                         * *  |   IO    | chan_   |   CLB      | chan_   |   CLB     |               * *  |clb[0][2]| y[0][2] | clb[1][2]  | y[1][2] |  clb[2][2]|               * *  +-------- +         +------------+         +-----------+               * *                                                           } capacity in * *   No channel          chan_x[1][1]          chan_x[2][1]  } chan_width  * *                                                           } _x[1]       * *  +---------+         +------------+         +-----------+               * *  |         | chan_   |            | chan_   |           |               * *  |  IO     | y[0][1] |    CLB     | y[1][1] |   CLB     |               * *  |clb[0][1]|         |  clb[1][1] |         | clb[2][1] |               * *  |         |         |            |         |           |               * *  +---------+         +------------+         +-----------+               * *                                                           } capacity in * *                      chan_x[1][0]           chan_x[2][0]  } chan_width  *  *                                                           } _x[0]       * *                      +------------+         +-----------+               * *              No      |            | No      |           |               * *            Channel   |    IO      | Channel |   IO      |               * *                      |  clb[1][0] |         | clb[2][0] |               * *                      |            |         |           |               * *                      +------------+         +-----------+               * *                                                                         * *             {=======}              {=======}                            * *            Capacity in            Capacity in                           * *          chan_width_y[0]        chan_width_y[1]                         * *                                                                         *//******************** Subroutines local to route_common.c *******************/static void free_trace_data (struct s_trace *tptr);static void load_route_bb (int bb_factor); static struct s_trace *alloc_trace_data (void); static void add_to_heap (struct s_heap *hptr);static struct s_heap *alloc_heap_data (void);static struct s_linked_f_pointer *alloc_linked_f_pointer (void);static t_ivec **alloc_and_load_clb_opins_used_locally (t_subblock_data         subblock_data);static void adjust_one_rr_occ_and_pcost (int inode, int add_or_sub, float            pres_fac);/************************** Subroutine definitions ***************************/void save_routing (struct s_trace **best_routing, t_ivec         **clb_opins_used_locally, t_ivec **saved_clb_opins_used_locally) {/* This routing frees any routing currently held in best routing,       * * then copies over the current routing (held in trace_head), and       * * finally sets trace_head and trace_tail to all NULLs so that the      * * connection to the saved routing is broken.  This is necessary so     * * that the next iteration of the router does not free the saved        * * routing elements.  Also saves any data about locally used clb_opins, * * since this is also part of the routing.                              */ int inet, iblk, iclass, ipin, num_local_opins; struct s_trace *tptr, *tempptr; for (inet=0;inet<num_nets;inet++) {/* Free any previously saved routing.  It is no longer best. */    tptr = best_routing[inet];    while (tptr != NULL) {       tempptr = tptr->next;       free_trace_data (tptr);       tptr = tempptr;    }/* Save a pointer to the current routing in best_routing. */    best_routing[inet] = trace_head[inet];/* Set the current (working) routing to NULL so the current trace       * * elements won't be reused by the memory allocator.                    */    trace_head[inet] = NULL;    trace_tail[inet] = NULL; }/* Save which OPINs are locally used.                           */  for (iblk=0;iblk<num_blocks;iblk++) {    for (iclass=0;iclass<num_class;iclass++) {       num_local_opins = clb_opins_used_locally[iblk][iclass].nelem;       for (ipin=0;ipin<num_local_opins;ipin++) {          saved_clb_opins_used_locally[iblk][iclass].list[ipin] =               clb_opins_used_locally[iblk][iclass].list[ipin];       }    } }}void restore_routing (struct s_trace **best_routing, t_ivec        **clb_opins_used_locally, t_ivec **saved_clb_opins_used_locally) {/* Deallocates any current routing in trace_head, and replaces it with    * * the routing in best_routing.  Best_routing is set to NULL to show that * * it no longer points to a valid routing.  NOTE:  trace_tail is not      * * restored -- it is set to all NULLs since it is only used in            * * update_traceback.  If you need trace_tail restored, modify this        * * routine.  Also restores the locally used opin data.                    */ int inet, iblk, ipin, iclass, num_local_opins; for (inet=0;inet<num_nets;inet++) {   /* Free any current routing. */    free_traceback (inet);  /* Set the current routing to the saved one. */   trace_head[inet] = best_routing[inet];   best_routing[inet] = NULL;          /* No stored routing. */ }/* Save which OPINs are locally used.                           */ for (iblk=0;iblk<num_blocks;iblk++) {    for (iclass=0;iclass<num_class;iclass++) {       num_local_opins = clb_opins_used_locally[iblk][iclass].nelem;       for (ipin=0;ipin<num_local_opins;ipin++) {          clb_opins_used_locally[iblk][iclass].list[ipin] =                saved_clb_opins_used_locally[iblk][iclass].list[ipin];       }     } }}void get_serial_num (void) {/* This routine finds a "magic cookie" for the routing and prints it.    * * Use this number as a routing serial number to ensure that programming * * changes do not break the router.                                      */ int inet, serial_num, inode; struct s_trace *tptr; serial_num = 0; for (inet=0;inet<num_nets;inet++) {/* Global nets will have null trace_heads (never routed) so they * * are not included in the serial number calculation.            */    tptr = trace_head[inet];    while (tptr != NULL) {       inode = tptr->index;       serial_num += (inet+1) * (rr_node[inode].xlow * (nx+1) -                       rr_node[inode].yhigh);       serial_num -= rr_node[inode].ptc_num * (inet+1) * 10;       serial_num -= rr_node[inode].type * (inet+1) * 100;       serial_num %= 2000000000;  /* Prevent overflow */       tptr = tptr->next;    } } printf ("Serial number (magic cookie) for the routing is: %d\n",    serial_num);}boolean try_route (int width_fac, struct s_router_opts router_opts, struct        s_det_routing_arch det_routing_arch, t_segment_inf *segment_inf,         t_timing_inf timing_inf, float **net_slack, float **net_delay,        t_chan_width_dist chan_width_dist, t_ivec **clb_opins_used_locally) {/* Attempts a routing via an iterated maze router algorithm.  Width_fac * * specifies the relative width of the channels, while the members of   * * router_opts determine the value of the costs assigned to routing     * * resource node, etc.  det_routing_arch describes the detailed routing * * architecture (connection and switch boxes) of the FPGA; it is used   * * only if a DETAILED routing has been selected.                        */ boolean success; printf("\nAttempting routing with a width factor (usually maximum channel "); printf("width) of %d.\n",width_fac);/* Set the channel widths */ init_chan (width_fac, chan_width_dist);/* Free any old routing graph, if one exists. */ free_rr_graph ();/* Set up the routing resource graph defined by this FPGA architecture. */ build_rr_graph (router_opts.route_type, det_routing_arch, segment_inf,                 timing_inf, router_opts.base_cost_type); free_rr_graph_internals (router_opts.route_type, det_routing_arch, segment_inf,                 timing_inf, router_opts.base_cost_type);/* Allocate and load some additional rr_graph information needed only by * * the router.                                                           */ alloc_and_load_rr_node_route_structs (); init_route_structs (router_opts.bb_factor); if (router_opts.router_algorithm == BREADTH_FIRST)     success = try_breadth_first_route (router_opts, clb_opins_used_locally);  else    /* TIMING_DRIVEN route */    success = try_timing_driven_route (router_opts, net_slack, net_delay,                 clb_opins_used_locally); free_rr_node_route_structs (); return (success);}boolean feasible_routing (void) {/* This routine checks to see if this is a resource-feasible routing.      * * That is, are all rr_node capacity limitations respected?  It assumes    * * that the occupancy arrays are up to date when it is called.             */ int inode; for (inode=0;inode<num_rr_nodes;inode++)     if (rr_node[inode].occ > rr_node[inode].capacity)       return (FALSE); return (TRUE);}void pathfinder_update_one_cost (struct s_trace *route_segment_start,      int add_or_sub, float pres_fac) {/* This routine updates the occupancy and pres_cost of the rr_nodes that are * * affected by the portion of the routing of one net that starts at          * * route_segment_start.  If route_segment_start is trace_head[inet], the     * * cost of all the nodes in the routing of net inet are updated.  If         * * add_or_sub is -1 the net (or net portion) is ripped up, if it is 1 the    * * net is added to the routing.  The size of pres_fac determines how severly * * oversubscribed rr_nodes are penalized.                                    */ struct s_trace *tptr; int inode, occ, capacity; tptr = route_segment_start; if (tptr == NULL)        /* No routing yet. */    return; while (1) {    inode = tptr->index;    occ = rr_node[inode].occ + add_or_sub;    capacity = rr_node[inode].capacity;    rr_node[inode].occ = occ;/* pres_cost is Pn in the Pathfinder paper. I set my pres_cost according to * * the overuse that would result from having ONE MORE net use this routing  * * node.                                                                    */    if (occ < capacity) {       rr_node_route_inf[inode].pres_cost = 1.;    }    else {       rr_node_route_inf[inode].pres_cost = 1. + (occ + 1 - capacity) *                                                 pres_fac;    }    if (rr_node[inode].type == SINK) {       tptr = tptr->next;             /* Skip next segment. */       if (tptr == NULL)          break;    }    tptr = tptr->next;  }   /* End while loop -- did an entire traceback. */}void pathfinder_update_cost (float pres_fac, float acc_fac) {/* This routine recomputes the pres_cost and acc_cost of each routing        * * resource for the pathfinder algorithm after all nets have been routed.    * * It updates the accumulated cost to by adding in the number of extra       * * signals sharing a resource right now (i.e. after each complete iteration) * * times acc_fac.  It also updates pres_cost, since pres_fac may have        * * changed.  THIS ROUTINE ASSUMES THE OCCUPANCY VALUES IN RR_NODE ARE UP TO  * * DATE.                                                                     */ int inode, occ, capacity;  for (inode=0;inode<num_rr_nodes;inode++) {    occ = rr_node[inode].occ;    capacity = rr_node[inode].capacity;        if (occ > capacity) {       rr_node_route_inf[inode].acc_cost += (occ - capacity) * acc_fac;       rr_node_route_inf[inode].pres_cost = 1. + (occ + 1 - capacity) *                                             pres_fac;    }/* If occ == capacity, we don't need to increase acc_cost, but a change    * * in pres_fac could have made it necessary to recompute the cost anyway.  */    else if (occ == capacity) {       rr_node_route_inf[inode].pres_cost = 1. + pres_fac;    } }}    void init_route_structs (int bb_factor) {/* Call this before you route any nets.  It frees any old traceback and   * * sets the list of rr_nodes touched to empty.                            */ int i; for (i=0;i<num_nets;i++)    free_traceback (i); load_route_bb (bb_factor);/* Check that things that should have been emptied after the last routing * * really were.                                                           */  if (rr_modified_head != NULL) {    printf ("Error in init_route_structs.  List of modified rr nodes is \n"            "not empty.\n");    exit (1); } if (heap_tail != 1) {    printf ("Error in init_route_structs.  Heap is not empty.\n");    exit (1); }}struct s_trace *update_traceback (struct s_heap *hptr, int inet) {/* This routine adds the most recently finished wire segment to the         * * traceback linked list.  The first connection starts with the net SOURCE  * * and begins at the structure pointed to by trace_head[inet]. Each         * * connection ends with a SINK.  After each SINK, the next connection       * * begins (if the net has more than 2 pins).  The first element after the   * * SINK gives the routing node on a previous piece of the routing, which is * * the link from the existing net to this new piece of the net.             * * In each traceback I start at the end of a path and trace back through    * * its predecessors to the beginning.  I have stored information on the     * * predecesser of each node to make traceback easy -- this sacrificies some * * memory for easier code maintenance.  This routine returns a pointer to   * * the first "new" node in the traceback (node not previously in trace).    */  struct s_trace *tptr, *prevptr, *temptail, *ret_ptr; int inode; short iedge;#ifdef DEBUG t_rr_type rr_type;#endif inode = hptr->index;#ifdef DEBUG   rr_type = rr_node[inode].type;   if (rr_type != SINK) {      printf("Error in update_traceback.  Expected type = SINK (%d).\n",         SINK);      printf("Got type = %d while tracing back net %d.\n", rr_type, inet);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -