📄 net_delay.c
字号:
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 + -