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

📄 path_delay.c

📁 用于学术研究的FPGA布局布线软件VPR
💻 C
📖 第 1 页 / 共 4 页
字号:
	}    /* First pass, load the subblock input pins to output pins without connecting edges to output pins.     * If the subblock is used in sequential mode (i.e. is clocked), the two clock pin nodes.       * Connect edges to output pins and take care of constant generators in second pass     */    for(isub = 0; isub < num_subs; isub++)	{	    has_outputs = FALSE;	    for(opin = 0; opin < type->max_subblock_outputs; opin++)		{		    if(sub_pin_to_tnode[isub][SUB_OUTPUT][opin] != OPEN)			{			    has_outputs = TRUE;			}		}	    if(!has_outputs && type != IO_TYPE)		{		/* Empty, so skip */		    continue;		}	    if(sub_inf[isub].clock != OPEN)		{		/* Sequential mode */		    inode = sub_pin_to_tnode[isub][SUB_CLOCK][clk_pin];		    /* Each output of a subblock has a flip-flop sink and source */		    for(opin = 0; opin < type->max_subblock_outputs; opin++)			{			    if(sub_inf[isub].outputs[opin] != OPEN)				{				    /* First node is the clock input pin; it feeds the sequential output */				    tnode[inode].num_edges = 1;				    tnode[inode].out_edges = (t_tedge *)					my_chunk_malloc(sizeof(t_tedge),							&tedge_ch_list_head,							&tedge_ch_bytes_avail,							&tedge_ch_next_avail);				    tnode_descript[inode].type = FF_SOURCE;				    tnode_descript[inode].ipin = OPEN;				    tnode_descript[inode].isubblk = isub;				    tnode_descript[inode].iblk = iblk;				    /* Now create the "sequential sink" -- i.e. the FF input node. */				    inode++;				    tnode[inode].num_edges = 0;				    tnode[inode].out_edges = NULL;				    tnode_descript[inode].type = FF_SINK;				    tnode_descript[inode].ipin = OPEN;				    tnode_descript[inode].isubblk = isub;				    tnode_descript[inode].iblk = iblk;				    inode++;				}			}		}	    /* Build and hook up subblock inputs. */	    for(ipin = 0; ipin < type->max_subblock_inputs; ipin++)		{		    inode = sub_pin_to_tnode[isub][SUB_INPUT][ipin];		    if(inode != OPEN)			{	/* tnode exists -> pin is used */			    if(type == IO_TYPE)				{	/* Output pad */				    tnode[inode].num_edges = 1;				    opin = 0;				    tnode[inode].out_edges = (t_tedge *)					my_chunk_malloc(sizeof(t_tedge),							&tedge_ch_list_head,							&tedge_ch_bytes_avail,							&tedge_ch_next_avail);				    tnode_descript[inode].type = OUTPAD_IPIN;				    tnode[inode + 1].num_edges = 0;				    tnode[inode + 1].out_edges = NULL;				    tedge = tnode[inode].out_edges;				    tedge[0].to_node = inode + 1;				    /* For output pads, use subblock combinational time 				     * and sequential in for timing (treat as register) */				    tedge[0].Tdel =					type->type_timing_inf.					T_subblock[isub].T_comb[ipin][opin] +					type->type_timing_inf.					T_subblock[isub].T_seq_in[opin];				    tnode_descript[inode + 1].type =					OUTPAD_SINK;				    tnode_descript[inode + 1].ipin = OPEN;				    tnode_descript[inode + 1].isubblk = isub;				    tnode_descript[inode + 1].iblk = iblk;				}			    else				{				    tnode[inode].num_edges =					num_opin_used_in_sblk[isub];				    tnode[inode].out_edges =					(t_tedge *)					my_chunk_malloc(num_opin_used_in_sblk							[isub] *							sizeof(t_tedge),							&tedge_ch_list_head,							&tedge_ch_bytes_avail,							&tedge_ch_next_avail);				    tnode[inode].num_edges =					num_opin_used_in_sblk[isub];				    tnode_descript[inode].type = SUBBLK_IPIN;				}			    tnode_descript[inode].ipin = ipin;			    tnode_descript[inode].isubblk = isub;			    tnode_descript[inode].iblk = iblk;			}		}	}			/* End for each subblock */    /* Second pass load the input pins to output pins array */    /* Load the output pins edge arrays. */    for(isub = 0; isub < num_subs; isub++)	{	    used_opin_count = 0;	    for(opin = 0; opin < type->max_subblock_outputs; opin++)		{		    if(sub_pin_to_tnode[isub][SUB_OUTPUT][opin] == OPEN)			{	/* Empty, so skip */			    continue;			}		    for(ipin = 0; ipin < type->max_subblock_inputs; ipin++)			{	/* sblk opin to sblk ipin */			    from_pin = sub_inf[isub].inputs[ipin];			    /* Not OPEN and comes from local subblock output? */			    if(from_pin >= type->num_pins)				{				    /* Convention for numbering netlist pins.				     * Internal connections are numbered subblock_index + subblock_output_index + num_pins				     */				    from_sub =					(from_pin -					 type->num_pins) /					type->max_subblock_outputs;				    from_opin =					(from_pin -					 type->num_pins) %					type->max_subblock_outputs;				    inode =					sub_pin_to_tnode[from_sub][SUB_OUTPUT]					[from_opin];				    to_node =					sub_pin_to_tnode[isub][SUB_INPUT]					[ipin];				    tedge = tnode[inode].out_edges;				    iedge = next_sblk_opin_edge[from_sub]					[from_opin]++;				    tedge[iedge].to_node = to_node;				    tedge[iedge].Tdel =					type->type_timing_inf.					T_sblk_opin_to_sblk_ipin;				}			}		    from_pin = sub_inf[isub].clock;	/* sblk opin to sblk clock */		    /* Not OPEN and comes from local subblock output? */		    if(from_pin >= type->num_pins)			{			    from_sub =				(from_pin -				 type->num_pins) / type->max_subblock_outputs;			    from_opin =				(from_pin -				 type->num_pins) % type->max_subblock_outputs;			    inode = sub_pin_to_tnode[from_sub][SUB_OUTPUT]				[from_opin];			    /* Feeds seq. output, one ff per output pin */			    to_node =				sub_pin_to_tnode[isub][SUB_CLOCK][clk_pin] +				2 * used_opin_count;			    tedge = tnode[inode].out_edges;			    iedge =				next_sblk_opin_edge[from_sub][from_opin]++;			    tedge[iedge].to_node = to_node;			    /* NB: Could make sblk opin to clk delay parameter; not worth it right now. */			    tedge[iedge].Tdel =				type->type_timing_inf.				T_sblk_opin_to_sblk_ipin;			}		    to_pin = sub_inf[isub].outputs[opin];		    if(to_pin != OPEN)			{	/* sblk opin goes to fb opin? */			    /* Check that FB pin connects to something ->     *			     * not just a mandatory BLE to FB opin connection */			    if(block[iblk].nets[to_pin] != OPEN)				{				    to_node = node_block_pin_to_tnode[to_pin];				    inode = sub_pin_to_tnode[isub][SUB_OUTPUT]					[opin];				    tedge = tnode[inode].out_edges;				    iedge = next_sblk_opin_edge[isub][opin]++;				    tedge[iedge].to_node = to_node;				    tedge[iedge].Tdel =					type->type_timing_inf.					T_sblk_opin_to_fb_opin;				}			}		    used_opin_count++;		}	}    /* Now load the subblock input pins and, if the subblock is used in        *     * sequential mode (i.e. is clocked), the two clock pin nodes for the output pin.              */    for(isub = 0; isub < num_subs; isub++)	{	    used_opin_count = 0;	    for(opin = 0; opin < type->max_subblock_outputs; opin++)		{		    if(sub_pin_to_tnode[isub][SUB_OUTPUT][opin] == OPEN)	/* Empty, so skip */			continue;		    /* Begin loading */		    if(sub_inf[isub].clock == OPEN)			{	/* Combinational mode */			    to_node =				sub_pin_to_tnode[isub][SUB_OUTPUT][opin];			    sink_delay = 0;			}		    else			{	/* Sequential mode.  Load two clock nodes. */			    inode =				sub_pin_to_tnode[isub][SUB_CLOCK][clk_pin] +				2 * used_opin_count;			    /* First node is the clock input pin; it feeds the sequential output */			    tedge = tnode[inode].out_edges;			    tedge[0].to_node =				sub_pin_to_tnode[isub][SUB_OUTPUT][opin];			    tedge[0].Tdel =				type->type_timing_inf.T_subblock[isub].				T_seq_out[opin];			    /* Now create the "sequential sink" -- i.e. the FF input node. */			    inode++;			    to_node = inode;			    sink_delay =				type->type_timing_inf.T_subblock[isub].				T_seq_in[opin];			}		    /* Build and hook up subblock inputs. */		    has_inputs = FALSE;		    for(ipin = 0; ipin < type->max_subblock_inputs; ipin++)			{			    inode = sub_pin_to_tnode[isub][SUB_INPUT][ipin];			    if(inode != OPEN)				{	/* tnode exists -> pin is used */				    has_inputs = TRUE;				    tedge = tnode[inode].out_edges;				    tedge[used_opin_count].to_node = to_node;				    tedge[used_opin_count].Tdel =					sink_delay +					type->type_timing_inf.					T_subblock[isub].T_comb[ipin][opin];				}			}		    if(!has_inputs && type != IO_TYPE)			{	/* Constant generator.  Give fake input. */			    inode =				sub_pin_to_tnode[isub][SUB_OUTPUT][opin] + 1;			    tnode[inode].num_edges = 1;			    tnode[inode].out_edges =				(t_tedge *) my_chunk_malloc(sizeof(t_tedge),							    &tedge_ch_list_head,							    &tedge_ch_bytes_avail,							    &tedge_ch_next_avail);			    tedge = tnode[inode].out_edges;			    tedge[used_opin_count].to_node = to_node;			    /* Want constants generated early so they never affect the critical path. */			    tedge[used_opin_count].Tdel =				T_CONSTANT_GENERATOR;			    tnode_descript[inode].type = CONSTANT_GEN_SOURCE;			    tnode_descript[inode].ipin = OPEN;			    tnode_descript[inode].isubblk = isub;			    tnode_descript[inode].iblk = iblk;			}		    used_opin_count++;		}	}    free_matrix(next_sblk_opin_edge, 0, type->max_subblocks - 1, 0,		sizeof(int));    free(num_opin_used_in_sblk);}static booleanis_global_clock(int iblk,		int sub,		int subpin,		int *num_subblocks_per_block,		t_subblock ** subblock_inf){/* Returns TRUE if the net driven by this block (which must be an INPAD) is  *   (1) a global signal, and (2) used as a clock input to at least one block.    Assumes that there is only one subblock in an IO */    int inet, ipin, to_blk, to_pin, isub;    t_type_ptr type = block[iblk].type;    assert(type == IO_TYPE);    inet = block[iblk].nets[subblock_inf[iblk][sub].outputs[subpin]];    assert(inet != OPEN);    if(!net[inet].is_global)	return (FALSE);    for(ipin = 1; ipin < (net[inet].num_sinks + 1); ipin++)	{	    to_blk = net[inet].node_block[ipin];	    to_pin = net[inet].node_block_pin[ipin];	    for(isub = 0; isub < num_subblocks_per_block[to_blk]; isub++)		{		    if(subblock_inf[to_blk][isub].clock == to_pin)			return (TRUE);		}	}    return (FALSE);}voidload_timing_graph_net_delays(float **net_delay){/* Sets the delays of the inter-FB nets to the values specified by          * * net_delay[0..num_nets-1][1..num_pins-1].  These net delays should have    * * been allocated and loaded with the net_delay routines.  This routine      * * marks the corresponding edges in the timing graph with the proper delay.  */    int inet, ipin, inode;    t_tedge *tedge;    for(inet = 0; inet < num_nets; inet++)	{	    inode = net_to_driver_tnode[inet];	    tedge = tnode[inode].out_edges;/* Note that the edges of a tnode corresponding to a FB or INPAD opin must  * * be in the same order as the pins of the net driven by the tnode.          */	    for(ipin = 1; ipin < (net[inet].num_sinks + 1); ipin++)		tedge[ipin - 1].Tdel = net_delay[inet][ipin];	}}voidfree_timing_graph(float **net_slack){/* Frees the timing graph data. */    if(tedge_ch_list_head == NULL)	{	    printf("Error in free_timing_graph: No timing graph to free.\n");	    exit(1);	}    free_chunk_memory(tedge_ch_list_head);    free(tnode);    free(tnode_descript);    free(net_to_driver_tnode);    free_ivec_vector(tnodes_at_level, 0, num_tnode_levels - 1);    free(net_slack);    tedge_ch_list_head = NULL;    tedge_ch_bytes_avail = 0;    tedge_ch_next_avail = NULL;    tnode = NULL;    tnode_descript = NULL;    num_tnodes = 0;    net_to_driver_tnode = NULL;    tnodes_at_level = NULL;    num_tnode_levels = 0;}voidprint_net_slack(char *fname,		float **net_slack){/* Prints the net slacks into a file.                                     */    int inet, ipin;    FILE *fp;    fp = my_fopen(fname, "w");    fprintf(fp, "Net #\tSlacks\n\n");

⌨️ 快捷键说明

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