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

📄 net_delay.c

📁 用于学术研究的FPGA布局布线软件VPR
💻 C
📖 第 1 页 / 共 2 页
字号:
    linked_rc_edge->iswitch = iswitch;    child_rc->u.child_list = NULL;    child_rc->inode = inode;}static t_rc_node *alloc_rc_node(t_rc_node ** rc_node_free_list_ptr){/* Allocates a new rc_node, from the free list if possible, from the free   * * store otherwise.                                                         */    t_rc_node *rc_node;    rc_node = *rc_node_free_list_ptr;    if(rc_node != NULL)	{	    *rc_node_free_list_ptr = rc_node->u.next;	}    else	{	    rc_node = (t_rc_node *) my_malloc(sizeof(t_rc_node));	}    return (rc_node);}static voidfree_rc_node(t_rc_node * rc_node,	     t_rc_node ** rc_node_free_list_ptr){/* Adds rc_node to the proper free list.          */    rc_node->u.next = *rc_node_free_list_ptr;    *rc_node_free_list_ptr = rc_node;}static t_linked_rc_edge *alloc_linked_rc_edge(t_linked_rc_edge ** rc_edge_free_list_ptr){/* Allocates a new linked_rc_edge, from the free list if possible, from the  * * free store otherwise.                                                     */    t_linked_rc_edge *linked_rc_edge;    linked_rc_edge = *rc_edge_free_list_ptr;    if(linked_rc_edge != NULL)	{	    *rc_edge_free_list_ptr = linked_rc_edge->next;	}    else	{	    linked_rc_edge = (t_linked_rc_edge *) my_malloc(sizeof							    (t_linked_rc_edge));	}    return (linked_rc_edge);}static voidfree_linked_rc_edge(t_linked_rc_edge * rc_edge,		    t_linked_rc_edge ** rc_edge_free_list_ptr){/* Adds the rc_edge to the rc_edge free list.                       */    rc_edge->next = *rc_edge_free_list_ptr;    *rc_edge_free_list_ptr = rc_edge;}static floatload_rc_tree_C(t_rc_node * rc_node){/* Does a post-order traversal of the rc tree to load each node's           * * C_downstream with the proper sum of all the downstream capacitances.     * * This routine calls itself recursively to perform the traversal.          */    t_linked_rc_edge *linked_rc_edge;    t_rc_node *child_node;    int inode;    short iswitch;    float C, C_downstream;    linked_rc_edge = rc_node->u.child_list;    inode = rc_node->inode;    C = rr_node[inode].C;    while(linked_rc_edge != NULL)	{			/* For all children */	    iswitch = linked_rc_edge->iswitch;	    child_node = linked_rc_edge->child;	    C_downstream = load_rc_tree_C(child_node);	    if(switch_inf[iswitch].buffered == FALSE)		C += C_downstream;	    linked_rc_edge = linked_rc_edge->next;	}    rc_node->C_downstream = C;    return (C);}static voidload_rc_tree_T(t_rc_node * rc_node,	       float T_arrival){/* This routine does a pre-order depth-first traversal of the rc tree to    * * compute the Tdel to each node in the rc tree.  The T_arrival is the time * * at which the signal hits the input to this node.  This routine calls     * * itself recursively to perform the traversal.                             */    float Tdel, Rmetal, Tchild;    t_linked_rc_edge *linked_rc_edge;    t_rc_node *child_node;    short iswitch;    int inode;    Tdel = T_arrival;    inode = rc_node->inode;    Rmetal = rr_node[inode].R;/* NB:  rr_node[inode].C gives the capacitance of this node, while          * * rc_node->C_downstream gives the unbuffered downstream capacitance rooted * * at this node, including the C of the node itself.  I want to multiply    * * the C of this node by 0.5 Rmetal, since it's a distributed RC line.      * * Hence 0.5 Rmetal * Cnode is a pessimistic estimate of delay (i.e. end to * * end).  For the downstream capacitance rooted at this node (not including * * the capacitance of the node itself), I assume it is, on average,         * * connected halfway along the line, so I also multiply by 0.5 Rmetal.  To  * * be totally pessimistic I would multiply the downstream part of the       * * capacitance by Rmetal.  Play with this equation if you like.             *//* Rmetal is distributed so x0.5 */    Tdel += 0.5 * rc_node->C_downstream * Rmetal;    rc_node->Tdel = Tdel;/* Now expand the children of this node to load their Tdel values.       */    linked_rc_edge = rc_node->u.child_list;    while(linked_rc_edge != NULL)	{			/* For all children */	    iswitch = linked_rc_edge->iswitch;	    child_node = linked_rc_edge->child;	    Tchild = Tdel + switch_inf[iswitch].R * child_node->C_downstream;	    Tchild += switch_inf[iswitch].Tdel;	/* Intrinsic switch delay. */	    load_rc_tree_T(child_node, Tchild);	    linked_rc_edge = linked_rc_edge->next;	}}static voidload_one_net_delay(float **net_delay,		   int inet,		   t_linked_rc_ptr * rr_node_to_rc_node){/* Loads the net delay array for net inet.  The rc tree for that net must  * * have already been completely built and loaded.                          */    int ipin, inode;    float Tmax;    t_rc_node *rc_node;    t_linked_rc_ptr *linked_rc_ptr, *next_ptr;    for(ipin = 1; ipin < (net[inet].num_sinks + 1); ipin++)	{	    inode = net_rr_terminals[inet][ipin];	    linked_rc_ptr = rr_node_to_rc_node[inode].next;	    rc_node = rr_node_to_rc_node[inode].rc_node;	    Tmax = rc_node->Tdel;	    /* If below only executes when one net connects several times to the      *	     * same SINK.  In this case, I can't tell which net pin each connection   *	     * to this SINK corresponds to (I can just choose arbitrarily).  To make  *	     * sure the timing behaviour converges, I pessimistically set the delay   *	     * for all of the connections to this SINK by this net to be the max. of  *	     * the delays from this net to this SINK.  NB:  This code only occurs     *	     * when a net connect more than once to the same pin class on the same    *	     * logic block.  Only a weird architecture would allow this.              */	    if(linked_rc_ptr != NULL)		{		    /* The first time I hit a multiply-used SINK, I choose the largest delay  *		     * from this net to this SINK and use it for every connection to this     *		     * SINK by this net.                                                      */		    do			{			    rc_node = linked_rc_ptr->rc_node;			    if(rc_node->Tdel > Tmax)				{				    Tmax = rc_node->Tdel;				    rr_node_to_rc_node[inode].rc_node =					rc_node;				}			    next_ptr = linked_rc_ptr->next;			    free(linked_rc_ptr);			    linked_rc_ptr = next_ptr;			}		    while(linked_rc_ptr != NULL);	/* End do while */		    rr_node_to_rc_node[inode].next = NULL;		}	    /* End of if multiply-used SINK */	    net_delay[inet][ipin] = Tmax;	}}static voidload_one_constant_net_delay(float **net_delay,			    int inet,			    float delay_value){/* Sets each entry of the net_delay array for net inet to delay_value.     */    int ipin;    for(ipin = 1; ipin < (net[inet].num_sinks + 1); ipin++)	net_delay[inet][ipin] = delay_value;}static voidfree_rc_tree(t_rc_node * rc_root,	     t_rc_node ** rc_node_free_list_ptr,	     t_linked_rc_edge ** rc_edge_free_list_ptr){/* Puts the rc tree pointed to by rc_root back on the free list.  Depth-     * * first post-order traversal via recursion.                                 */    t_rc_node *rc_node, *child_node;    t_linked_rc_edge *rc_edge, *next_edge;    rc_node = rc_root;    rc_edge = rc_node->u.child_list;    while(rc_edge != NULL)	{			/* For all children */	    child_node = rc_edge->child;	    free_rc_tree(child_node, rc_node_free_list_ptr,			 rc_edge_free_list_ptr);	    next_edge = rc_edge->next;	    free_linked_rc_edge(rc_edge, rc_edge_free_list_ptr);	    rc_edge = next_edge;	}    free_rc_node(rc_node, rc_node_free_list_ptr);}static voidreset_rr_node_to_rc_node(t_linked_rc_ptr * rr_node_to_rc_node,			 int inet){/* Resets the rr_node_to_rc_node mapping entries that were set during       * * construction of the RC tree for net inet.  Any extra linked list entries * * added to deal with a SINK being connected to multiple times have already * * been freed by load_one_net_delay.                                        */    struct s_trace *tptr;    int inode;    tptr = trace_head[inet];    while(tptr != NULL)	{	    inode = tptr->index;	    rr_node_to_rc_node[inode].rc_node = NULL;	    tptr = tptr->next;	}}static voidfree_rc_node_free_list(t_rc_node * rc_node_free_list){/* Really frees (i.e. calls free()) all the rc_nodes on the free list.   */    t_rc_node *rc_node, *next_node;    rc_node = rc_node_free_list;    while(rc_node != NULL)	{	    next_node = rc_node->u.next;	    free(rc_node);	    rc_node = next_node;	}}static voidfree_rc_edge_free_list(t_linked_rc_edge * rc_edge_free_list){/* Really frees (i.e. calls free()) all the rc_edges on the free list.   */    t_linked_rc_edge *rc_edge, *next_edge;    rc_edge = rc_edge_free_list;    while(rc_edge != NULL)	{	    next_edge = rc_edge->next;	    free(rc_edge);	    rc_edge = next_edge;	}}voidprint_net_delay(float **net_delay,		char *fname){/* Dumps the net delays into file fname.   */    FILE *fp;    int inet, ipin;    fp = my_fopen(fname, "w");    for(inet = 0; inet < num_nets; inet++)	{	    fprintf(fp, "Net: %d.\n", inet);	    fprintf(fp, "Delays:");	    for(ipin = 1; ipin < (net[inet].num_sinks + 1); ipin++)		fprintf(fp, " %g", net_delay[inet][ipin]);	    fprintf(fp, "\n\n");	}    fclose(fp);}

⌨️ 快捷键说明

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