📄 path_delay.c
字号:
tnode_descript[inode].ipin = out_pin; tnode_descript[inode].isubblk = isub; tnode_descript[inode].iblk = iblk; } }/* Load the output pins edge arrays. */ for (isub=0;isub<num_subs;isub++) { for (ipin=0;ipin<subblock_lut_size;ipin++) { /* sblk opin to sblk ipin */ from_pin = sub_inf[isub].inputs[ipin]; /* Not OPEN and comes from local subblock output? */ if (from_pin >= pins_per_clb) { inode = sub_pin_to_tnode[from_pin - pins_per_clb][out_pin]; to_node = sub_pin_to_tnode[isub][ipin]; tedge = tnode[inode].out_edges; iedge = next_sblk_opin_edge[from_pin - pins_per_clb]++; tedge[iedge].to_node = to_node; tedge[iedge].Tdel = 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 >= pins_per_clb) { inode = sub_pin_to_tnode[from_pin - pins_per_clb][out_pin]; to_node = sub_pin_to_tnode[isub][clk_pin]; /* Feeds seq. output */ tedge = tnode[inode].out_edges; iedge = next_sblk_opin_edge[from_pin - pins_per_clb]++; tedge[iedge].to_node = to_node; /* NB: Could make sblk opin to clk delay parameter; not worth it right now. */ tedge[iedge].Tdel = T_sblk_opin_to_sblk_ipin; } to_pin = sub_inf[isub].output; if (to_pin != OPEN) { /* sblk opin goes to clb opin? */ /* Check that CLB pin connects to something -> * * not just a mandatory BLE to CLB opin connection */ if (block[iblk].nets[to_pin] != OPEN) { to_node = blk_pin_to_tnode[to_pin]; inode = sub_pin_to_tnode[isub][out_pin]; tedge = tnode[inode].out_edges; iedge = next_sblk_opin_edge[isub]++; tedge[iedge].to_node = to_node; tedge[iedge].Tdel = T_sblk_opin_to_clb_opin; } } }/* Now build the subblock input pins and, if the subblock is used in * * sequential mode (i.e. is clocked), the two clock pin nodes. */ for (isub=0;isub<num_subs;isub++) { if (sub_pin_to_tnode[isub][out_pin] == OPEN) /* Empty, so skip */ continue; if (sub_inf[isub].clock == OPEN) { /* Combinational mode */ to_node = sub_pin_to_tnode[isub][out_pin]; ipin_to_sink_Tdel = T_subblock[isub].T_comb; } else { /* Sequential mode. Build two clock nodes. */ /* First node is the clock input pin; it feeds the sequential output */ inode = sub_pin_to_tnode[isub][clk_pin]; 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[0].to_node = sub_pin_to_tnode[isub][out_pin]; tedge[0].Tdel = T_subblock[isub].T_seq_out; 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; /* Subblock inputs connect to this node. */ to_node = inode; ipin_to_sink_Tdel = T_subblock[isub].T_seq_in; } /* Build and hook up subblock inputs. */ has_inputs = FALSE; for (ipin=0;ipin<subblock_lut_size;ipin++) { inode = sub_pin_to_tnode[isub][ipin]; if (inode != OPEN) { /* tnode exists -> pin is used */ has_inputs = TRUE; 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[0].to_node = to_node; tedge[0].Tdel = ipin_to_sink_Tdel; tnode_descript[inode].type = SUBBLK_IPIN; tnode_descript[inode].ipin = ipin; tnode_descript[inode].isubblk = isub; tnode_descript[inode].iblk = iblk; } }#define T_CONSTANT_GENERATOR -1000 /* Essentially -ve infinity */ if (!has_inputs) { /* Constant generator. Give fake input. */ inode = sub_pin_to_tnode[isub][out_pin] + 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[0].to_node = to_node;/* Want constants generated early so they never affect the critical path. */ tedge[0].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; } } /* End for each subblock */}static void build_ipad_tnodes (int iblk, int **block_pin_to_tnode, float T_ipad, int *num_subblocks_per_block, t_subblock **subblock_inf) {/* Builds the two tnodes corresponding to an input pad, and hooks them into * * the timing graph. */ int to_node, inode; t_tedge *tedge;/* First node: input node to the pad -> nothing comes into this. Second * * node is the output node of the pad, that has edges to CLB ipins. */ inode = block_pin_to_tnode[iblk][0]; to_node = block_pin_to_tnode[iblk][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[0].to_node = to_node; /* By definition, global clocks from pads arrive at T = 0. The earliest any * * clock can arrive at any flip flop is T = 0, and the fastest global clock * * from a pad should have zero delay on its edges so it does get to the * * flip flop clock pin at T = 0. */ if (is_global_clock (iblk, num_subblocks_per_block, subblock_inf)) tedge[0].Tdel = 0.; else tedge[0].Tdel = T_ipad; tnode_descript[inode].type = INPAD_SOURCE; tnode_descript[inode].ipin = OPEN; tnode_descript[inode].isubblk = OPEN; tnode_descript[inode].iblk = iblk;/* Now do pad output. */ build_block_output_tnode (to_node, iblk, 0, block_pin_to_tnode); tnode_descript[to_node].type = INPAD_OPIN; tnode_descript[to_node].ipin = 0; tnode_descript[to_node].isubblk = OPEN; tnode_descript[to_node].iblk = iblk;}static boolean is_global_clock (int iblk, 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. */ int inet, ipin, to_blk, to_pin, isub; inet = block[iblk].nets[0]; if (!is_global[inet]) return (FALSE); for (ipin=1;ipin<net[inet].num_pins;ipin++) { to_blk = net[inet].blocks[ipin]; to_pin = net[inet].blk_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);}static void build_opad_tnodes (int *blk_pin_to_tnode, float T_opad, int iblk) {/* Builds the two tnodes in an output pad and connects them up. */ int to_node, inode; t_tedge *tedge;/* First node: input node to the pad -> will be driven some net. Second * * node is the output node of the pad, which connects to nothing. */ inode = blk_pin_to_tnode[0]; to_node = blk_pin_to_tnode[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[0].to_node = to_node; tedge[0].Tdel = T_opad; tnode_descript[inode].type = OUTPAD_IPIN; tnode_descript[inode].ipin = 0; tnode_descript[inode].isubblk = OPEN; tnode_descript[inode].iblk = iblk; tnode[to_node].num_edges = 0; tnode[to_node].out_edges = NULL; tnode_descript[to_node].type = OUTPAD_SINK; tnode_descript[to_node].ipin = OPEN; tnode_descript[to_node].isubblk = OPEN; tnode_descript[to_node].iblk = iblk;}void load_timing_graph_net_delays (float **net_delay) {/* Sets the delays of the inter-CLB 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 CLB 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_pins;ipin++) tedge[ipin-1].Tdel = net_delay[inet][ipin]; }}void free_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;}void print_net_slack (char *fname, float **net_slack) {/* Prints the net slacks into a file. */ int inet, ipin; FILE *fp; fp = my_fopen (fname, "w", 0); fprintf (fp, "Net #\tSlacks\n\n"); for (inet=0;inet<num_nets;inet++) { fprintf (fp, "%5d", inet); for (ipin=1;ipin<net[inet].num_pins;ipin++) { fprintf (fp, "\t%g", net_slack[inet][ipin]); } fprintf (fp, "\n"); }}void print_timing_graph (char *fname) {/* Prints the timing graph into a file. */ FILE *fp; int inode, iedge, ilevel, i; t_tedge *tedge; t_tnode_type itype; char *tnode_type_names[] = {"INPAD_SOURCE", "INPAD_OPIN", "OUTPAD_IPIN", "OUTPAD_SINK", "CLB_IPIN", "CLB_OPIN", "SUBBLK_IPIN", "SUBBLK_OPIN", "FF_SINK", "FF_SOURCE",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -