148 #define NUM_BUCKETS 5
176 static void update_slacks(
t_slack * slacks,
int source_clock_domain,
int sink_clock_domain,
float criticality_denom,
177 boolean update_slack);
182 float inter_cluster_net_delay);
187 boolean is_prepacked,
boolean is_final_analysis,
long * max_critical_input_paths_ptr,
188 long * max_critical_output_paths_ptr);
191 static void do_path_counting(
float criticality_denom);
198 #ifndef PATH_COUNTING
200 long max_critical_output_paths);
253 boolean do_process_constraints =
FALSE;
256 vpr_printf(TIO_MESSAGE_ERROR,
"in alloc_and_load_timing_graph: An old timing graph still exists.\n");
274 do_process_constraints =
TRUE;
279 if (do_process_constraints)
282 if (f_timing_stats == NULL)
303 boolean do_process_constraints =
FALSE;
306 vpr_printf(TIO_MESSAGE_ERROR,
"in alloc_and_load_timing_graph: An old timing graph still exists.\n");
314 inter_cluster_net_delay);
330 do_process_constraints =
TRUE;
335 if (do_process_constraints)
338 if (f_timing_stats == NULL)
361 slacks->path_criticality[inet] = (
float *)
my_chunk_malloc((timing_nets[inet].
num_sinks + 1) *
sizeof(float), &tedge_ch);
375 int inet, ipin, inode;
385 for (ipin = 1; ipin < (timing_nets[inet].
num_sinks + 1); ipin++)
386 tedge[ipin - 1].Tdel = net_delay[inet][ipin];
395 vpr_printf(TIO_MESSAGE_ERROR,
"in free_timing_graph: No timing graph to free.\n");
401 if (tnode[0].prepacked_data) {
404 for (inode = 0; inode <
num_tnodes; inode++) {
405 free(tnode[inode].prepacked_data);
415 free(slacks->path_criticality);
429 if(f_timing_stats != NULL) {
431 free(f_timing_stats->
cpd[i]);
434 free(f_timing_stats->
cpd);
436 free(f_timing_stats);
438 f_timing_stats = NULL;
441 void print_slack(
float ** slack,
boolean slack_is_normalized,
const char *fname) {
445 int inet, iedge, ibucket, driver_tnode, num_edges, num_unused_slacks = 0;
449 total_slack = 0, total_negative_slack = 0, bucket_size, slk;
454 if (slack_is_normalized) {
455 fprintf(fp,
"The following slacks have been normalized to be non-negative by "
456 "relaxing the required times to the maximum arrival time.\n\n");
463 for (iedge = 0; iedge < num_edges; iedge++) {
464 slk = slack[inet][iedge + 1];
466 max_slack =
std::max(max_slack, slk);
467 min_slack =
std::min(min_slack, slk);
470 total_negative_slack -= slk;
479 fprintf(fp,
"Largest slack in design: %g\n", max_slack);
481 fprintf(fp,
"Largest slack in design: --\n");
485 fprintf(fp,
"Smallest slack in design: %g\n", min_slack);
487 fprintf(fp,
"Smallest slack in design: --\n");
490 fprintf(fp,
"Total slack in design: %g\n", total_slack);
491 fprintf(fp,
"Total negative slack: %g\n", total_negative_slack);
493 if (max_slack - min_slack >
EPSILON) {
495 for (ibucket = 0; ibucket <
NUM_BUCKETS; ibucket++) {
496 slacks_in_bucket[ibucket] = 0;
500 bucket_size = (max_slack - min_slack)/NUM_BUCKETS;
507 for (iedge = 0; iedge < num_edges; iedge++) {
508 slk = slack[inet][iedge + 1];
511 ibucket =
std::min(NUM_BUCKETS - 1, (
int) ((slk - min_slack)/bucket_size));
512 assert(ibucket >= 0 && ibucket < NUM_BUCKETS);
513 slacks_in_bucket[ibucket]++;
519 fprintf(fp,
"\n\nRange\t\t");
520 for (ibucket = 0; ibucket <
NUM_BUCKETS; ibucket++) {
521 fprintf(fp,
"%.1e to ", min_slack);
522 min_slack += bucket_size;
523 fprintf(fp,
"%.1e\t", min_slack);
525 fprintf(fp,
"Not analysed");
526 fprintf(fp,
"\nSlacks in range\t\t");
527 for (ibucket = 0; ibucket <
NUM_BUCKETS; ibucket++) {
528 fprintf(fp,
"%d\t\t\t", slacks_in_bucket[ibucket]);
530 fprintf(fp,
"%d", num_unused_slacks);
534 fprintf(fp,
"\n\nNet #\tDriver_tnode\tto_node\tSlack\n\n");
538 num_edges = tnode[driver_tnode].
num_edges;
540 slk = slack[inet][1];
542 fprintf(fp,
"%5d\t%5d\t\t%5d\t%g\n", inet, driver_tnode, tedge[0].to_node, slk);
544 fprintf(fp,
"%5d\t%5d\t\t%5d\t--\n", inet, driver_tnode, tedge[0].to_node);
546 for (iedge = 1; iedge < num_edges; iedge++) {
547 slk = slack[inet][iedge+1];
549 fprintf(fp,
"\t\t\t%5d\t%g\n", tedge[iedge].to_node, slk);
551 fprintf(fp,
"\t\t\t%5d\t--\n", tedge[iedge].to_node);
563 int inet, iedge, driver_tnode, num_edges;
569 if (criticality_is_normalized) {
570 fprintf(fp,
"Timing criticalities have been normalized to be non-negative by "
571 "relaxing the required times to the maximum arrival time.\n\n");
580 fprintf(fp,
"\n\nNet #\tDriver_tnode\t to_node\tTiming criticality"
588 num_edges = tnode[driver_tnode].
num_edges;
591 fprintf(fp,
"\n%5d\t%5d\t\t%5d\t\t%.6f", inet, driver_tnode, tedge[0].to_node, slacks->
timing_criticality[inet][1]);
593 fprintf(fp,
"\t\t%g", slacks->path_criticality[inet][1]);
595 for (iedge = 1; iedge < num_edges; iedge++) {
596 fprintf(fp,
"\n\t\t\t%5d\t\t%.6f", tedge[iedge].to_node, slacks->
timing_criticality[inet][iedge+1]);
598 fprintf(fp,
"\t\t%g", slacks->path_criticality[inet][iedge+1]);
612 int inet, iedge, num_edges, ibucket, criticalities_in_bucket[
NUM_BUCKETS];
614 total_criticality = 0, bucket_size;
620 for (iedge = 0; iedge < num_edges; iedge++) {
621 crit = criticality[inet][iedge + 1];
622 max_criticality =
std::max(max_criticality, crit);
623 min_criticality =
std::min(min_criticality, crit);
624 total_criticality += crit;
628 fprintf(fp,
"Largest %s in design: %g\n", singular_name, max_criticality);
629 fprintf(fp,
"Smallest %s in design: %g\n", singular_name, min_criticality);
630 fprintf(fp,
"Total %s in design: %g\n", singular_name, total_criticality);
632 if (max_criticality - min_criticality >
EPSILON) {
634 for (ibucket = 0; ibucket <
NUM_BUCKETS; ibucket++) {
635 criticalities_in_bucket[ibucket] = 0;
639 bucket_size = (max_criticality - min_criticality)/NUM_BUCKETS;
646 for (iedge = 0; iedge < num_edges; iedge++) {
647 crit = criticality[inet][iedge + 1];
649 ibucket =
std::min(NUM_BUCKETS - 1, (
int) ((crit - min_criticality)/bucket_size));
650 assert(ibucket >= 0 && ibucket < NUM_BUCKETS);
651 criticalities_in_bucket[ibucket]++;
656 fprintf(fp,
"\nRange\t\t");
657 for (ibucket = 0; ibucket <
NUM_BUCKETS; ibucket++) {
658 fprintf(fp,
"%.1e to ", min_criticality);
659 min_criticality += bucket_size;
660 fprintf(fp,
"%.1e\t", min_criticality);
662 fprintf(fp,
"\n%s in range\t\t", capitalized_plural_name);
663 for (ibucket = 0; ibucket <
NUM_BUCKETS; ibucket++) {
664 fprintf(fp,
"%d\t\t\t", criticalities_in_bucket[ibucket]);
674 int inet, iedge, driver_tnode, num_edges;
680 fprintf(fp,
"Net #\tDriver_tnode\tto_node\tDelay\n\n");
684 num_edges = tnode[driver_tnode].
num_edges;
686 fprintf(fp,
"%5d\t%5d\t\t%5d\t%g\n", inet, driver_tnode, tedge[0].to_node, net_delay[inet][1]);
687 for (iedge = 1; iedge < num_edges; iedge++) {
688 fprintf(fp,
"\t\t\t%5d\t%g\n", tedge[iedge].to_node, net_delay[inet][iedge+1]);
695 #ifndef PATH_COUNTING
703 fprintf(fp,
"inode ");
707 fprintf(fp,
"Critical input paths Critical output paths ");
709 fprintf(fp,
"Normalized slack Normalized Tarr Normalized total crit paths\n");
710 for (inode = 0; inode <
num_tnodes; inode++) {
711 fprintf(fp,
"%d\t", inode);
720 fprintf(fp,
"--\t\t\t--\t\t\t");
722 fprintf(fp,
"--\t\t--\t\t--\n");
733 int num_nodes_in_block;
735 int iblock, irr_node;
736 int inet, dport, dpin, dblock, dnode;
737 int normalized_pin, normalization;
740 int num_dangling_pins;
751 num_nodes_in_block = 0;
753 if (
block[i].pb->rr_graph[j].net_num !=
OPEN) {
759 num_nodes_in_block += 2;
761 num_nodes_in_block++;
774 if (
block[i].pb->rr_graph[j].net_num !=
OPEN) {
775 assert(tnode[inode].pb_graph_pin == NULL);
782 num_dangling_pins = 0;
795 iblock = tnode[i].
block;
796 switch (tnode[i].type) {
826 dnode = local_rr_graph[irr_node].
edges[j];
827 if ((local_rr_graph[dnode].prev_node == irr_node)
828 && (j == local_rr_graph[dnode].prev_edge)) {
839 for (j = 0; j < local_rr_graph[irr_node].
num_edges; j++) {
840 dnode = local_rr_graph[irr_node].
edges[j];
841 if ((local_rr_graph[dnode].prev_node == irr_node)
842 && (j == local_rr_graph[dnode].
prev_edge)) {
878 for (j = 0; j < tnode[i].
num_edges; j++) {
886 assert(tnode[i].out_edges[k].to_node !=
OPEN);
891 if (tnode[i].num_edges == 0) {
902 assert(local_rr_graph[irr_node].net_num !=
OPEN);
904 assert(inet !=
OPEN);
923 && dpin ==
OPEN; k++) {
924 if (normalized_pin >= count
926 +
block[dblock].pb->pb_graph_node->num_input_pins[k]
928 dpin = normalized_pin - count;
938 && dpin ==
OPEN; k++) {
944 && dpin ==
OPEN; k++) {
945 if (normalized_pin >= count
947 +
block[dblock].pb->pb_graph_node->num_clock_pins[k]
949 dpin = normalized_pin - count;
955 assert(dpin !=
OPEN);
961 assert(dpin !=
OPEN);
969 assert(inet !=
OPEN);
981 vpr_printf(TIO_MESSAGE_ERROR,
"Consistency check failed: Unknown tnode type %d.\n", tnode[i].type);
986 if(num_dangling_pins > 0) {
987 vpr_printf(TIO_MESSAGE_WARNING,
"Unconnected logic in design, number of dangling tnodes = %d\n", num_dangling_pins);
996 float inter_cluster_net_delay) {
1030 model_port = model->
inputs;
1031 while (model_port) {
1033 for (k = 0; k < model_port->
size; k++) {
1042 model_port = model_port->
next;
1048 while (model_port) {
1049 for (k = 0; k < model_port->
size; k++) {
1055 model_port = model_port->
next;
1064 for (inode = 0; inode <
num_tnodes; inode++) {
1080 tnode[inode].
block = i;
1086 tnode[inode].num_edges *
sizeof(
t_tedge),
1094 tnode[inode + 1].
block = i;
1103 tnode[inode].
block = i;
1111 tnode[inode + 1].
block = i;
1118 while (model_port) {
1121 for (k = 0; k < model_port->
size; k++) {
1126 tnode[inode].
block = i;
1135 tnode[inode].num_edges *
sizeof(
t_tedge),
1153 tnode[inode + 1].
block = i;
1159 model_port = model_port->
next;
1163 model_port = model->
inputs;
1164 while (model_port) {
1168 for (k = 0; k < model_port->
size; k++) {
1173 tnode[inode].
block = i;
1186 to_pb_graph_pin = from_pb_graph_pin->
pin_timing[m];
1210 tnode[inode + 1].
block = i;
1220 tnode[inode].
block = i;
1230 model_port = model_port->
next;
1234 assert(inode == num_tnodes);
1245 switch (tnode[i].type) {
1253 assert(inet !=
OPEN);
1260 tnode[i].out_edges[j - 1].Tdel = inter_cluster_net_delay;
1265 tnode[i].out_edges[j - 1].to_node =
1270 tnode[i].out_edges[j - 1].to_node =
1286 vpr_printf(TIO_MESSAGE_ERROR,
"Consistency check failed: Unknown tnode type %d.\n", tnode[i].type);
1302 tnode[i].
block = iblock;
1305 if (tnode[i].pb_graph_pin->parent_node->pb_type->blif_model == NULL) {
1307 if (tnode[i].pb_graph_pin->parent_node->parent_pb_graph_node == NULL) {
1308 if (tnode[i].pb_graph_pin->port->
type ==
IN_PORT) {
1328 tnode[i + 1].
block = iblock;
1331 assert(tnode[i].pb_graph_pin->port->
type ==
IN_PORT);
1340 tnode[i + 1].
block = iblock;
1345 if (tnode[i].pb_graph_pin->port->
type ==
IN_PORT) {
1354 tnode[i + 1].
block = iblock;
1367 tnode[i + 1].
block = iblock;
1375 if (tnode[i].pb_graph_pin->port->
type ==
IN_PORT) {
1393 int inode, iedge, ilevel, i;
1396 const char *tnode_type_names[] = {
"TN_INPAD_SOURCE",
"TN_INPAD_OPIN",
"TN_OUTPAD_IPIN",
1398 "TN_OUTPAD_SINK",
"TN_CB_IPIN",
"TN_CB_OPIN",
"TN_INTERMEDIATE_NODE",
1399 "TN_PRIMITIVE_IPIN",
"TN_PRIMITIVE_OPIN",
"TN_FF_IPIN",
"TN_FF_OPIN",
"TN_FF_SINK",
1400 "TN_FF_SOURCE",
"TN_FF_CLOCK",
"TN_CONSTANT_GEN_SOURCE" };
1405 fprintf(fp,
"Node #\tType\t\tipin\tiblk\tDomain\tSkew\tI/O Delay\t# edges\t"
1406 "to_node Tdel\n\n");
1408 for (inode = 0; inode <
num_tnodes; inode++) {
1409 fprintf(fp,
"%d\t", inode);
1411 itype = tnode[inode].
type;
1412 fprintf(fp,
"%-15.15s\t", tnode_type_names[itype]);
1414 if (tnode[inode].pb_graph_pin != NULL) {
1415 fprintf(fp,
"%d\t%d\t",
1416 tnode[inode].pb_graph_pin->pin_count_in_cluster,
1417 tnode[inode].
block);
1419 fprintf(fp,
"\t%d\t", tnode[inode].
block);
1423 fprintf(fp,
"%d\t%.3e\t\t", tnode[inode].clock_domain, tnode[inode].clock_delay);
1425 fprintf(fp,
"%d\t\t%.3e\t", tnode[inode].clock_domain, tnode[inode].out_edges[0].Tdel);
1428 fprintf(fp,
"%d\t\t%.3e\t", tnode[inode].clock_domain, tnode[inode-1].out_edges[0].Tdel);
1430 fprintf(fp,
"\t\t\t\t");
1433 fprintf(fp,
"%d", tnode[inode].num_edges);
1437 if (tnode[inode].num_edges > 0) {
1438 fprintf(fp,
"\t%4d\t%7.3g", tedge[0].to_node, tedge[0].Tdel);
1439 for (iedge = 1; iedge < tnode[inode].
num_edges; iedge++) {
1440 fprintf(fp,
"\n\t\t\t\t\t\t\t\t\t\t%4d\t%7.3g", tedge[iedge].to_node, tedge[iedge].Tdel);
1449 fprintf(fp,
"\n\nLevel: %d Num_nodes: %d\nNodes:", ilevel,
1456 fprintf(fp,
"\n\nNet #\tNet_to_driver_tnode\n");
1464 fprintf(fp,
"\n\nNode #\t\tT_arr\t\tT_req"
1465 #ifdef PATH_COUNTING
1466 "\tForward weight\tBackward weight"
1470 for (inode = 0; inode <
num_tnodes; inode++) {
1472 fprintf(fp,
"%d\t%12g", inode, tnode[inode].T_arr);
1474 fprintf(fp,
"%d\t\t -", inode);
1477 fprintf(fp,
"\t%12g", tnode[inode].T_req);
1479 fprintf(fp,
"\t\t -");
1481 #ifdef PATH_COUNTING
1482 fprintf(fp,
"\t%12g\t%12g\n", tnode[inode].forward_weight, tnode[inode].backward_weight);
1503 int source_clock_domain, sink_clock_domain, inode, ilevel, num_at_level, i,
1504 num_edges, iedge, to_node, icf, ifc, iff;
1514 for (inode = 0; inode <
num_tnodes; inode++) {
1520 constraint_used[sink_clock_domain] =
FALSE;
1525 for (i = 0; i < num_at_level; i++) {
1527 if (tnode[inode].clock_domain == source_clock_domain) {
1528 tnode[inode].
T_arr = 0.;
1535 for (i = 0; i < num_at_level; i++) {
1539 if (num_edges == 0) {
1543 if (sink_clock_domain != -1) {
1544 constraint_used[sink_clock_domain] =
TRUE;
1549 for (iedge = 0; iedge < num_edges; iedge++) {
1550 to_node = tedge[iedge].
to_node;
1551 tnode[to_node].
T_arr = 0.;
1562 if (!constraint_used[sink_clock_domain]) {
1568 free(constraint_used);
1698 int i, j, source_clock_domain, sink_clock_domain, inode, inet, ipin;
1700 #if defined PATH_COUNTING || SLACK_DEFINITION == 'S'
1701 int iedge, num_edges;
1704 #ifdef PATH_COUNTING
1712 float criticality_denom;
1716 long max_critical_output_paths, max_critical_input_paths;
1719 #if SLACK_DEFINITION == 'S'
1728 for (inode = 0; inode <
num_tnodes; inode++) {
1729 if (tnode[inode].type ==
TN_PRIMITIVE_OPIN && tnode[inode].pb_graph_pin != NULL) {
1748 for (ipin = 1; ipin <= timing_nets[inet].
num_sinks; ipin++) {
1751 #ifdef PATH_COUNTING
1752 slacks->path_criticality[inet][ipin] = 0.;
1765 #ifndef PATH_COUNTING
1768 for (inode = 0; inode <
num_tnodes; inode++) {
1776 if (do_lut_input_balancing) {
1794 is_prepacked, is_final_analysis, &max_critical_input_paths, &max_critical_output_paths);
1795 #ifdef PATH_COUNTING
1797 do_path_counting(criticality_denom);
1803 update_slacks(slacks, source_clock_domain, sink_clock_domain, criticality_denom, update_slack);
1805 #ifndef PATH_COUNTING
1812 #if SLACK_DEFINITION == 'S'
1814 criticality_denom_global =
std::max(criticality_denom_global, criticality_denom);
1820 #ifdef PATH_COUNTING
1825 num_edges = timing_nets[inet].
num_sinks;
1826 for (iedge = 0; iedge < num_edges; iedge++) {
1827 max_path_criticality =
std::max(max_path_criticality, slacks->path_criticality[inet][iedge + 1]);
1832 num_edges = timing_nets[inet].
num_sinks;
1833 for (iedge = 0; iedge < num_edges; iedge++) {
1834 slacks->path_criticality[inet][iedge + 1] /= max_path_criticality;
1840 #if SLACK_DEFINITION == 'S'
1841 if (!is_final_analysis) {
1846 smallest_slack_in_design =
std::min(smallest_slack_in_design, f_timing_stats->
least_slack[i][j]);
1851 if (smallest_slack_in_design < 0) {
1853 num_edges = timing_nets[inet].
num_sinks;
1854 for (iedge = 0; iedge < num_edges; iedge++) {
1855 slacks->
slack[inet][iedge + 1] -= smallest_slack_in_design;
1866 num_edges = timing_nets[inet].
num_sinks;
1867 for (iedge = 0; iedge < num_edges; iedge++) {
1879 int inode, num_at_level, i, ilevel, num_edges, iedge, to_node;
1883 for (inode = 0; inode <
num_tnodes; inode++) {
1889 for (i = 0; i < num_at_level; i++) {
1898 tnode[inode].
T_arr = 0.;
1906 for (i = 0; i < num_at_level; i++) {
1912 for (iedge = 0; iedge < num_edges; iedge++) {
1913 to_node = tedge[iedge].
to_node;
1927 boolean is_prepacked,
boolean is_final_analysis,
long * max_critical_input_paths_ptr,
1928 long * max_critical_output_paths_ptr) {
1937 int inode, num_at_level, i, total, ilevel, num_edges, iedge, to_node, icf;
1942 int num_dangling_nodes;
1944 long max_critical_input_paths = 0, max_critical_output_paths = 0;
1950 for (inode = 0; inode <
num_tnodes; inode++) {
1955 #ifndef PATH_COUNTING
1958 for (inode = 0; inode <
num_tnodes; inode++) {
1966 for (i = 0; i < num_at_level; i++) {
1969 if (tnode[inode].clock_domain == source_clock_domain) {
1979 tnode[inode].
T_arr = 0.;
1991 total += num_at_level;
1993 for (i = 0; i < num_at_level; i++) {
2003 #ifndef PATH_COUNTING
2004 if (is_prepacked && ilevel == 0) {
2012 for (iedge = 0; iedge < num_edges; iedge++) {
2013 to_node = tedge[iedge].
to_node;
2014 if (fabs(tnode[to_node].T_arr - (tnode[inode].T_arr + tedge[iedge].Tdel)) <
EPSILON) {
2019 }
else if (tnode[to_node].T_arr < (tnode[inode].T_arr + tedge[iedge].Tdel)) {
2026 if (tnode[to_node].prepacked_data->num_critical_input_paths > max_critical_input_paths) {
2032 for (iedge = 0; iedge < num_edges; iedge++) {
2033 to_node = tedge[iedge].
to_node;
2044 max_Tarr =
std::max(max_Tarr, tnode[to_node].T_arr);
2049 assert(total == num_tnodes);
2050 num_dangling_nodes = 0;
2053 for (ilevel = num_tnode_levels - 1; ilevel >= 0; ilevel--) {
2056 for (i = 0; i < num_at_level; i++) {
2062 vpr_printf(TIO_MESSAGE_ERROR,
"Timing graph started on unexpected node %s.%s[%d].\n",
2063 tnode[inode].pb_graph_pin->parent_node->pb_type->name,
2066 vpr_printf(TIO_MESSAGE_ERROR,
"This is a VPR internal error, contact VPR development team.\n");
2071 vpr_printf(TIO_MESSAGE_ERROR,
"Timing graph discovered unexpected edge to node %s.%s[%d].\n",
2072 tnode[inode].pb_graph_pin->parent_node->pb_type->name,
2075 vpr_printf(TIO_MESSAGE_ERROR,
"This is a VPR internal error, contact VPR development team.\n");
2085 if (num_edges == 0) {
2093 vpr_printf(TIO_MESSAGE_WARNING,
"Pin on block %s.%s[%d] not used\n",
2095 tnode[inode].prepacked_data->model_port_ptr->name,
2098 num_dangling_nodes++;
2104 if (tnode[inode].clock_domain != sink_clock_domain) {
2127 #if SLACK_DEFINITION == 'R'
2141 if (is_final_analysis) {
2144 tnode[inode].
T_req =
std::max(constraint + tnode[inode].clock_delay, max_Tarr);
2161 f_timing_stats->
cpd[source_clock_domain][sink_clock_domain] =
2162 std::max(f_timing_stats->
cpd[source_clock_domain][sink_clock_domain],
2165 #ifndef PATH_COUNTING
2192 for (iedge = 0; iedge < num_edges && !found; iedge++) {
2193 to_node = tedge[iedge].
to_node;
2207 for (iedge = 0; iedge < num_edges; iedge++) {
2208 to_node = tedge[iedge].
to_node;
2209 Tdel = tedge[iedge].
Tdel;
2210 T_req = tnode[to_node].
T_req;
2211 tnode[inode].
T_req =
std::min(tnode[inode].T_req, T_req - Tdel);
2217 if (tnode[to_node].num_edges == 0 && tnode[to_node].clock_domain == sink_clock_domain) {
2218 f_timing_stats->
least_slack[source_clock_domain][sink_clock_domain] =
2220 (T_req - Tdel - tnode[inode].
T_arr));
2223 #ifndef PATH_COUNTING
2231 for (iedge = 0; iedge < num_edges; iedge++) {
2232 to_node = tedge[iedge].
to_node;
2236 if (fabs(tnode[to_node].T_req - (tnode[inode].T_req + tedge[iedge].Tdel)) <
EPSILON) {
2241 if (tnode[to_node].prepacked_data->num_critical_output_paths > max_critical_output_paths) {
2253 if (max_critical_input_paths_ptr && max_critical_output_paths_ptr) {
2254 *max_critical_input_paths_ptr = max_critical_input_paths;
2255 *max_critical_output_paths_ptr = max_critical_output_paths;
2258 if(num_dangling_nodes > 0 && (is_final_analysis || is_prepacked)) {
2259 vpr_printf(TIO_MESSAGE_WARNING,
"%d unused pins \n", num_dangling_nodes);
2266 #ifdef PATH_COUNTING
2267 static void do_path_counting(
float criticality_denom) {
2274 int inode, num_at_level, i, ilevel, num_edges, iedge, to_node;
2276 float forward_local_slack, backward_local_slack, discount;
2279 for (inode = 0; inode <
num_tnodes; inode++) {
2280 tnode[inode].forward_weight = 0;
2281 tnode[inode].backward_weight = 0;
2286 for (i = 0; i < num_at_level; i++) {
2288 tnode[inode].forward_weight = 1.;
2295 for (i = 0; i < num_at_level; i++) {
2302 for (iedge = 0; iedge < num_edges; iedge++) {
2303 to_node = tedge[iedge].
to_node;
2307 forward_local_slack = tnode[to_node].
T_arr - tnode[inode].
T_arr - tedge[iedge].
Tdel;
2308 discount = pow((
float) DISCOUNT_FUNCTION_BASE, -1 * forward_local_slack / criticality_denom);
2309 tnode[to_node].forward_weight += discount * tnode[inode].forward_weight;
2316 for (ilevel = num_tnode_levels - 1; ilevel >= 0; ilevel--) {
2319 for (i = 0; i < num_at_level; i++) {
2325 if (num_edges == 0) {
2326 tnode[inode].backward_weight = 1.;
2329 for (iedge = 0; iedge < num_edges; iedge++) {
2330 to_node = tedge[iedge].
to_node;
2334 backward_local_slack = tnode[to_node].
T_req - tnode[inode].
T_req - tedge[iedge].
Tdel;
2335 discount = pow((
float) DISCOUNT_FUNCTION_BASE, -1 * backward_local_slack / criticality_denom);
2336 tnode[inode].backward_weight += discount * tnode[to_node].backward_weight;
2344 static void update_slacks(
t_slack * slacks,
int source_clock_domain,
int sink_clock_domain,
float criticality_denom,
2345 boolean update_slack) {
2361 int inet, iedge, inode, to_node, num_edges;
2363 float T_arr, Tdel, T_req, slk, timing_criticality;
2367 T_arr = tnode[inode].
T_arr;
2377 for (iedge = 0; iedge < num_edges; iedge++) {
2378 to_node = tedge[iedge].
to_node;
2383 Tdel = tedge[iedge].
Tdel;
2384 T_req = tnode[to_node].
T_req;
2388 slk = T_req - T_arr - Tdel;
2389 if (slk < slacks->slack[inet][iedge + 1]) {
2392 slacks->
slack[inet][iedge + 1] = slk;
2396 #if SLACK_DEFINITION == 'R'
2399 timing_criticality = 1 - (T_req - T_arr - Tdel)/criticality_denom;
2403 #ifdef PATH_COUNTING
2407 #if PATH_COUNTING == 'S'
2408 slacks->path_criticality[inet][iedge + 1] =
max(slacks->path_criticality[inet][iedge + 1],
2409 (tnode[inode].forward_weight + tnode[to_node].backward_weight) *
2410 pow((
float) FINAL_DISCOUNT_FUNCTION_BASE, timing_criticality - 1));
2411 #elif PATH_COUNTING == 'P'
2412 slacks->path_criticality[inet][iedge + 1] =
max(slacks->path_criticality[inet][iedge + 1],
2413 tnode[inode].forward_weight * tnode[to_node].backward_weight *
2414 pow((
float) FINAL_DISCOUNT_FUNCTION_BASE, timing_criticality - 1));
2415 #elif PATH_COUNTING == 'L'
2416 slacks->path_criticality[inet][iedge + 1] =
max(slacks->path_criticality[inet][iedge + 1],
2417 log(tnode[inode].forward_weight * tnode[to_node].backward_weight) *
2418 pow((
float) FINAL_DISCOUNT_FUNCTION_BASE, timing_criticality - 1));
2419 #elif PATH_COUNTING == 'R'
2420 slacks->path_criticality[inet][iedge + 1] =
max(slacks->path_criticality[inet][iedge + 1],
2421 log(tnode[inode].forward_weight) * log(tnode[to_node].backward_weight) *
2422 pow((
float) FINAL_DISCOUNT_FUNCTION_BASE, timing_criticality - 1));
2437 fprintf(fp,
"# LUT_Name\tinput_pin_mapping\n");
2439 for (inode = 0; inode <
num_tnodes; inode++) {
2441 if (tnode[inode].type ==
TN_PRIMITIVE_OPIN && tnode[inode].pb_graph_pin != NULL) {
2446 fprintf(fp,
"%s", pb->
name);
2464 int non_global_nets_on_crit_path, global_nets_on_crit_path;
2465 int tnodes_on_crit_path, inode, iblk, inet;
2467 float total_net_delay, total_logic_delay, Tdel;
2470 critical_path_node = critical_path_head;
2474 non_global_nets_on_crit_path = 0;
2475 global_nets_on_crit_path = 0;
2476 tnodes_on_crit_path = 0;
2477 total_net_delay = 0.;
2478 total_logic_delay = 0.;
2480 while (critical_path_node != NULL) {
2482 inode = critical_path_node->
data;
2483 type = tnode[inode].
type;
2484 tnodes_on_crit_path++;
2490 non_global_nets_on_crit_path++;
2492 global_nets_on_crit_path++;
2494 total_net_delay += Tdel;
2496 total_logic_delay += Tdel;
2499 critical_path_node = critical_path_node->
next;
2502 fprintf(fp,
"\nTnodes on critical path: %d Non-global nets on critical path: %d."
2503 "\n", tnodes_on_crit_path, non_global_nets_on_crit_path);
2504 fprintf(fp,
"Global nets on critical path: %d.\n", global_nets_on_crit_path);
2505 fprintf(fp,
"Total logic delay: %g (s) Total net delay: %g (s)\n",
2506 total_logic_delay, total_net_delay);
2508 vpr_printf(TIO_MESSAGE_INFO,
"Nets on critical path: %d normal, %d global.\n",
2509 non_global_nets_on_crit_path, global_nets_on_crit_path);
2511 vpr_printf(TIO_MESSAGE_INFO,
"Total logic delay: %g (s), total net delay: %g (s)\n",
2512 total_logic_delay, total_net_delay);
2527 t_linked_int *critical_path_head, *curr_crit_node, *prev_crit_node;
2528 int inode, iedge, to_node, num_at_level_zero, i, j, crit_node =
OPEN, num_edges;
2547 if (min_slack > f_timing_stats->
least_slack[i][j]) {
2549 source_clock_domain = i;
2550 sink_clock_domain = j;
2566 for (i = 0; i < num_at_level_zero; i++) {
2569 slack = tnode[inode].
T_req - tnode[inode].
T_arr;
2570 if (slack < min_slack) {
2577 critical_path_head->
data = crit_node;
2578 assert(crit_node !=
OPEN);
2579 prev_crit_node = critical_path_head;
2585 while (num_edges != 0) {
2587 prev_crit_node->
next = curr_crit_node;
2591 for (iedge = 0; iedge < num_edges; iedge++) {
2592 to_node = tedge[iedge].
to_node;
2594 slack = tnode[to_node].
T_req - tnode[to_node].
T_arr;
2595 if (slack < min_slack) {
2596 crit_node = to_node;
2602 curr_crit_node->
data = crit_node;
2603 prev_crit_node = curr_crit_node;
2607 prev_crit_node->
next = NULL;
2608 return (critical_path_head);
2617 int inet, ipin, iblk;
2620 iblk = tnode[inode].
block;
2621 tnode_type = tnode[inode].
type;
2626 assert(inet !=
OPEN);
2637 float constant_net_delay_value) {
2676 #ifndef PATH_COUNTING
2678 long max_critical_output_paths) {
2685 assert(criticality_denom != 0);
2690 for (inode = 0; inode <
num_tnodes; inode++) {
2694 (tnode[inode].
T_req - tnode[inode].
T_arr)/criticality_denom);
2696 tnode[inode].
T_arr/criticality_denom);
2699 ((
float) max_critical_input_paths + max_critical_output_paths));
2713 boolean *assigned = NULL;
2714 int fastest_unassigned_pin, most_crit_tnode, most_crit_pin;
2715 float min_delay, highest_T_arr, balanced_T_arr;
2718 tnode[to_node].
T_arr =
std::max(tnode[to_node].T_arr, tnode[from_node].T_arr + Tdel);
2721 if (do_lut_input_balancing && tnode[to_node].type ==
TN_PRIMITIVE_OPIN && tnode[to_node].pb_graph_pin != NULL) {
2727 assert(tnode[from_node].
block == tnode[to_node].
block);
2741 if (rebalance ==
TRUE) {
2743 balanced_T_arr =
OPEN;
2752 fastest_unassigned_pin =
OPEN;
2756 if (fastest_unassigned_pin ==
OPEN) {
2757 fastest_unassigned_pin = j;
2760 fastest_unassigned_pin = j;
2765 assert(fastest_unassigned_pin !=
OPEN);
2768 most_crit_tnode =
OPEN;
2769 highest_T_arr =
OPEN;
2770 most_crit_pin =
OPEN;
2773 if (input_tnode != NULL && assigned[j] ==
FALSE) {
2774 if (most_crit_tnode ==
OPEN) {
2776 highest_T_arr = input_tnode->
T_arr;
2778 }
else if (highest_T_arr < input_tnode->T_arr) {
2780 highest_T_arr = input_tnode->
T_arr;
2786 if (most_crit_tnode ==
OPEN) {
2789 assert(tnode[most_crit_tnode].num_edges == 1);
2792 assigned[most_crit_pin] =
TRUE;
2793 if (balanced_T_arr < min_delay + highest_T_arr) {
2794 balanced_T_arr = min_delay + highest_T_arr;
2799 if (balanced_T_arr !=
OPEN) {
2800 tnode[to_node].
T_arr = balanced_T_arr;
2821 int i, iclock, inode, num_at_level, clock_index, input_index, output_index;
2832 for (i = 0; i < num_at_level; i++) {
2836 if ((clock_index =
find_clock(net_name)) != -1) {
2850 }
else if ((input_index =
find_input(net_name)) != -1) {
2853 assert(clock_index != -1);
2868 for (inode = 0; inode <
num_tnodes; inode++) {
2876 if (output_index != -1) {
2879 assert(clock_index != -1);
2896 for (inode = 0; inode <
num_tnodes; inode++) {
2920 assert(tnode[inode].clock_domain != -1);
2925 for (iedge = 0; iedge < tnode[inode].
num_edges; iedge++) {
2926 to_node = tedge[iedge].
to_node;
2941 t_pb * physical_block;
2944 logic_block = tnode[inode].
block;
2948 physical_block =
block[logic_block].
pb;
2962 t_pb_graph_pin * ff_source_or_sink_pb_graph_pin, * clock_pb_graph_pin;
2964 logic_block = tnode[inode].
block;
2969 ff_source_or_sink_pb_graph_pin = tnode[inode].
pb_graph_pin;
2970 parent_pb_graph_node = ff_source_or_sink_pb_graph_pin->
parent_node;
2974 clock_pb_graph_pin = &parent_pb_graph_node->
clock_pins[0][0];
2977 assert(ff_clock_tnode != NULL);
2979 return ff_clock_tnode;
3021 int icf, isource, isink;
3040 return node -
tnode;
3053 #ifndef PATH_COUNTING
3064 int source_clock_domain, sink_clock_domain;
3071 if (least_slack_in_design > f_timing_stats->
least_slack[source_clock_domain][sink_clock_domain]) {
3072 least_slack_in_design = f_timing_stats->
least_slack[source_clock_domain][sink_clock_domain];
3073 critical_path_delay = f_timing_stats->
cpd[source_clock_domain][sink_clock_domain];
3078 return critical_path_delay * 1e9;
3087 int source_clock_domain, sink_clock_domain, clock_domain, fanout, total_fanout = 0,
3088 num_netlist_clocks_with_intra_domain_paths = 0;
3090 double fanout_weighted_geomean_period = 1.;
3098 if (least_slack_in_design > f_timing_stats->
least_slack[source_clock_domain][sink_clock_domain]) {
3099 least_slack_in_design = f_timing_stats->
least_slack[source_clock_domain][sink_clock_domain];
3100 critical_path_delay = f_timing_stats->
cpd[source_clock_domain][sink_clock_domain];
3107 vpr_printf(TIO_MESSAGE_INFO,
"Final critical path: %g ns\n", 1e9 * critical_path_delay);
3111 vpr_printf(TIO_MESSAGE_INFO,
"Final critical path: %g ns\n", 1e9 * critical_path_delay);
3116 vpr_printf(TIO_MESSAGE_INFO,
"f_max: %g MHz\n", 1e-6 / critical_path_delay);
3121 vpr_printf(TIO_MESSAGE_INFO,
"Least slack in design: %g ns\n", 1e9 * least_slack_in_design);
3128 vpr_printf(TIO_MESSAGE_INFO,
"Minimum possible clock period to meet each constraint (including skew effects):\n");
3132 vpr_printf(TIO_MESSAGE_INFO,
"%s to %s: %g ns (%g MHz)\n",
3135 1e9 * f_timing_stats->
cpd[source_clock_domain][source_clock_domain],
3136 1e-6 / f_timing_stats->
cpd[source_clock_domain][source_clock_domain]);
3138 vpr_printf(TIO_MESSAGE_INFO,
"%s to %s: --\n",
3145 if (source_clock_domain == sink_clock_domain)
continue;
3148 vpr_printf(TIO_MESSAGE_INFO,
"\t%s to %s: %g ns (%g MHz)\n",
3151 1e9 * f_timing_stats->
cpd[source_clock_domain][sink_clock_domain],
3152 1e-6 / f_timing_stats->
cpd[source_clock_domain][sink_clock_domain]);
3154 vpr_printf(TIO_MESSAGE_INFO,
"\t%s to %s: --\n",
3164 vpr_printf(TIO_MESSAGE_INFO,
"Least slack per constraint:\n");
3168 vpr_printf(TIO_MESSAGE_INFO,
"%s to %s: %g ns\n",
3171 1e9 * f_timing_stats->
least_slack[source_clock_domain][source_clock_domain]);
3173 vpr_printf(TIO_MESSAGE_INFO,
"%s to %s: --\n",
3179 if (source_clock_domain == sink_clock_domain)
continue;
3182 vpr_printf(TIO_MESSAGE_INFO,
"\t%s to %s: %g ns\n",
3185 1e9 * f_timing_stats->
least_slack[source_clock_domain][sink_clock_domain]);
3187 vpr_printf(TIO_MESSAGE_INFO,
"\t%s to %s: --\n",
3199 geomean_period *= f_timing_stats->
cpd[clock_domain][clock_domain];
3201 fanout_weighted_geomean_period *= pow((
double) f_timing_stats->
cpd[clock_domain][clock_domain], fanout);
3202 total_fanout += fanout;
3203 num_netlist_clocks_with_intra_domain_paths++;
3208 geomean_period = pow(geomean_period, (
float) 1/num_netlist_clocks_with_intra_domain_paths);
3209 fanout_weighted_geomean_period = pow(fanout_weighted_geomean_period, (
double) 1/total_fanout);
3212 vpr_printf(TIO_MESSAGE_INFO,
"Geometric mean intra-domain period: %g ns (%g MHz)\n",
3213 1e9 * geomean_period, 1e-6 / geomean_period);
3214 vpr_printf(TIO_MESSAGE_INFO,
"Fanout-weighted geomean intra-domain period: %g ns (%g MHz)\n",
3215 1e9 * fanout_weighted_geomean_period, 1e-6 / fanout_weighted_geomean_period);
3226 int source_clock_domain, sink_clock_domain, i, j;
3228 int max_clock_name_length = INT_MIN;
3236 clock_name_length[sink_clock_domain] = strlen(clock_name);
3237 if (clock_name_length[sink_clock_domain] > max_clock_name_length) {
3238 max_clock_name_length = clock_name_length[sink_clock_domain];
3245 fprintf(fp,
"Timing constraints in ns (source clock domains down left side, sink along top).\n"
3246 "A value of -1.00 means the pair of source and sink domains will not be analysed.\n\n");
3259 print_spaces(fp, max_clock_name_length + 4 - clock_name_length[source_clock_domain]);
3268 free(clock_name_length);
3271 fprintf(fp,
"\nList of constrained inputs (note: constraining a clock net input has no effect):\n");
3273 fprintf(fp,
"Input name %s on clock %s with input delay %.2f ns\n",
3277 fprintf(fp,
"\nList of constrained outputs:\n");
3279 fprintf(fp,
"Output name %s on clock %s with output delay %.2f ns\n",
3284 fprintf(fp,
"\nList of override constraints (non-default constraints created by set_false_path, set_clock_groups, \nset_max_delay, and set_multicycle_path):\n");
3287 fprintf(fp,
"Clock domain");
3291 fprintf(fp,
" to clock domain");
3303 fprintf(fp,
"Clock domain");
3307 fprintf(fp,
" to flip-flop");
3319 fprintf(fp,
"Flip-flop");
3323 fprintf(fp,
" to clock domain");
3335 fprintf(fp,
"Flip-flop");
3339 fprintf(fp,
" to flip-flop");
3355 for ( ; num_spaces > 0; num_spaces--) {
3372 fprintf(fp,
".inputs ");
3379 while (p_io_removed) {
3380 fprintf(fp,
"\\\n%s ", (
char *) p_io_removed->
data_vptr);
3381 p_io_removed = p_io_removed->
next;
3386 fprintf(fp,
".outputs ");
3394 fprintf(fp,
".names unconn\n");
3395 fprintf(fp,
" 0\n\n");
3407 for (j = 0; j < tnode[i].
num_edges; j++) {
3408 fprintf(fp,
".names tnode_%d tnode_%d\n", i,
3409 tnode[i].out_edges[j].to_node);
3410 fprintf(fp,
"1 1\n\n");
3415 fprintf(fp,
".end\n\n");
3419 fprintf(fp,
".model %s\n", models->
name);
3420 fprintf(fp,
".inputs ");
3423 if (port->
size > 1) {
3424 for (j = 0; j < port->
size; j++) {
3425 fprintf(fp,
"%s[%d] ", port->
name, j);
3428 fprintf(fp,
"%s ", port->
name);
3433 fprintf(fp,
".outputs ");
3436 if (port->
size > 1) {
3437 for (j = 0; j < port->
size; j++) {
3438 fprintf(fp,
"%s[%d] ", port->
name, j);
3441 fprintf(fp,
"%s ", port->
name);
3445 fprintf(fp,
"\n.blackbox\n.end\n\n");
3446 fprintf(fp,
"\n\n");
3447 models = models->
next;
3464 fprintf(fpout,
".names %s tnode_%d\n",
logical_block[iblk].name,
3467 fprintf(fpout,
".names %s tnode_%d\n",
logical_block[iblk].name,
3470 fprintf(fpout,
"1 1\n\n");
3474 fprintf(fpout,
".names tnode_%d %s\n",
3479 fprintf(fpout,
".names tnode_%d %s\n",
3483 fprintf(fpout,
"1 1\n\n");
3485 fprintf(fpout,
".latch ");
3493 assert(port->
size == 1);
3494 for (j = 0; j < port->
size; j++) {
3496 fprintf(fpout,
"tnode_%d ",
3511 assert(port->
size == 1);
3512 for (j = 0; j < port->
size; j++) {
3516 fprintf(fpout,
"latch_%s re ",
3531 for (j = 0; j < port->
size; j++) {
3533 fprintf(fpout,
"tnode_%d 0\n\n",
3548 fprintf(fpout,
"tnode_%d ",
3555 fprintf(fpout,
"tnode_%d 0\n\n",
3558 assert(node !=
OPEN);
3559 fprintf(fpout,
".names latch_%s tnode_%d\n",
logical_block[iblk].name,
3561 fprintf(fpout,
"1 1\n\n");
3563 fprintf(fpout,
".names ");
3571 for (j = 0; j < port->
size; j++) {
3573 fprintf(fpout,
"tnode_%d ",
3587 assert(port->
size == 1);
3590 assert(node !=
OPEN);
3597 assert(
logical_block[iblk].pb->pb_graph_node->num_input_ports == 1);
3603 if (irr_graph[
logical_block[iblk].pb->pb_graph_node->input_pins[0][j].pin_count_in_cluster].
net_num
3606 fprintf(fpout,
"tnode_%d ",
3612 assert(j <
logical_block[iblk].pb->pb_graph_node->num_input_pins[0]);
3616 logical_block[iblk].pb->pb_graph_node->num_output_ports == 1);
3618 logical_block[iblk].pb->pb_graph_node->num_output_pins[0] == 1);
3623 assert(node !=
OPEN);
3625 while (truth_table) {
3626 fprintf(fpout,
"%s\n", (
char*) truth_table->
data_vptr);
3627 truth_table = truth_table->
next;
3629 fprintf(fpout,
"\n");
3630 fprintf(fpout,
".names lut_%s tnode_%d\n",
logical_block[iblk].name,
3632 fprintf(fpout,
"1 1\n\n");
3641 for (j = 0; j < port->
size; j++) {
3643 if (port->
size > 1) {
3644 fprintf(fpout,
"\\\n%s[%d]=tnode_%d ",
3648 fprintf(fpout,
"\\\n%s=tnode_%d ", port->
name,
3652 if (port->
size > 1) {
3653 fprintf(fpout,
"\\\n%s[%d]=unconn ", port->
name,
3656 fprintf(fpout,
"\\\n%s=unconn ", port->
name);
3668 for (j = 0; j < port->
size; j++) {
3670 if (port->
size > 1) {
3671 fprintf(fpout,
"\\\n%s[%d]=%s ", port->
name, j,
3674 fprintf(fpout,
"\\\n%s=%s ", port->
name,
3678 if (port->
size > 1) {
3679 fprintf(fpout,
"\\\n%s[%d]=unconn_%d_%s_%d ",
3680 port->
name, j, iblk, port->
name, j);
3682 fprintf(fpout,
"\\\n%s=unconn_%d_%s ", port->
name,
3695 assert(port->
size == 1);
3697 fprintf(fpout,
"\\\n%s=tnode_%d ", port->
name,
3700 fprintf(fpout,
"\\\n%s=unconn ", port->
name);
3707 fprintf(fpout,
"\n\n");
3712 for (j = 0; j < port->
size; j++) {
3714 fprintf(fpout,
".names %s tnode_%d\n",
3717 fprintf(fpout,
"1 1\n\n");
3731 fprintf(fpout,
"\\\n%s[%d]=tnode_%d ",
3736 fprintf(fpout,
"\\\n%s=tnode_%d ",
3742 fprintf(fpout,
"\\\n%s[%d]=unconn ",
3746 fprintf(fpout,
"\\\n%s=unconn ",
3757 fprintf(fpout,
"\\\n%s[%d]=%s ",
3766 int node_index = irr_graph[pin_count].
net_num;
3768 fprintf(fpout,
"\\\n%s=%s ", port_name, node_name);
3772 fprintf(fpout,
"\\\n%s[%d]=unconn ",
3776 fprintf(fpout,
"\\\n%s=unconn ",
3787 fprintf(fpout,
"\\\n%s[%d]=tnode_%d ",
3792 fprintf(fpout,
"\\\n%s=tnode_%d ",
3798 fprintf(fpout,
"\\\n%s[%d]=unconn ",
3802 fprintf(fpout,
"\\\n%s=unconn ",
3809 fprintf(fpout,
"\n\n");
3815 fprintf(fpout,
".names %s tnode_%d\n",
3818 fprintf(fpout,
"1 1\n\n");
static int find_cf_constraint(char *source_clock_name, char *sink_ff_name)
static void alloc_and_load_tnodes_from_prepacked_netlist(float block_delay, float inter_cluster_net_delay)
struct s_ivec * tnodes_at_level
void print_timing_stats(void)
t_pb_graph_pin * get_pb_graph_node_pin_from_model_port_pin(t_model_ports *model_port, int model_pin, t_pb_graph_node *pb_graph_node)
void check_timing_graph(int num_sinks)
t_pb_graph_pin ** clock_pins
FILE * my_fopen(const char *fname, const char *flag, int prompt)
static t_tnode * find_ff_clock_tnode(int inode, boolean is_prepacked)
static int num_timing_nets
t_model_ports * model_port
void print_timing_graph_as_blif(const char *fname, t_model *models)
void free_override_constraint(t_override_constraint *&constraint_array, int num_constraints)
long num_critical_output_paths
long num_critical_input_paths
struct s_linked_vptr * circuit_p_io_removed
struct s_rr_node * rr_graph
static t_slack * alloc_slacks(void)
float pb_max_internal_delay
float * pin_timing_del_max
static void do_lut_rebalancing()
float get_critical_path_delay(void)
t_pb_graph_pin ** output_pins
static int find_input(char *net_name)
static float ** net_delay
struct s_pb_graph_edge ** output_edges
static void print_primitive_as_blif(FILE *fpout, int iblk)
void * my_chunk_malloc(size_t size, t_chunk *chunk_info)
boolean timing_analysis_enabled
static t_timing_stats * f_timing_stats
void * my_calloc(size_t nelem, size_t size)
void get_tnode_block_and_output_net(int inode, int *iblk_ptr, int *inet_ptr)
struct s_model_ports * next
static void load_tnode(INP t_pb_graph_pin *pb_graph_pin, INP int iblock, INOUTP int *inode, INP t_timing_inf timing_inf)
const t_pb_type * pbtype_max_internal_delay
struct s_linked_vptr * truth_table
t_linked_int * allocate_and_load_critical_path(void)
void print_critical_path(const char *fname)
void do_timing_analysis(t_slack *slacks, boolean is_prepacked, boolean do_lut_input_balancing, boolean is_final_analysis)
float ** domain_constraint
void print_clustering_timing_info(const char *fname)
struct s_pb_graph_pin ** pin_timing
t_pb_graph_pin ** output_pins
struct s_pb ** rr_node_to_pb_mapping
struct s_linked_vptr * chunk_ptr_head
static void propagate_clock_domain_and_skew(int inode)
enum e_pb_graph_pin_type type
boolean getEchoEnabled(void)
int num_constrained_outputs
t_prepacked_tnode_data * prepacked_data
static void load_clock_domain_and_clock_and_io_delay(boolean is_prepacked)
static void print_spaces(FILE *fp, int num_spaces)
struct s_tnode * clock_net_tnode
static float do_timing_analysis_for_constraint(int source_clock_domain, int sink_clock_domain, boolean is_prepacked, boolean is_final_analysis, long *max_critical_input_paths_ptr, long *max_critical_output_paths_ptr)
t_override_constraint * fc_constraints
t_slack * alloc_and_load_pre_packing_timing_graph(float block_delay, float inter_cluster_net_delay, t_model *models, t_timing_inf timing_inf)
#define HUGE_POSITIVE_FLOAT
void read_sdc(t_timing_inf timing_inf)
float normalized_total_critical_paths
static void * my_malloc(int ibytes)
t_override_constraint * cf_constraints
void do_constant_net_delay_timing_analysis(t_timing_inf timing_inf, float constant_net_delay_value)
struct s_tnode *** input_net_tnodes
void print_lut_remapping(const char *fname)
int * vpack_to_clb_net_mapping
int num_constrained_inputs
void free_ivec_vector(struct s_ivec *ivec_vector, int nrmin, int nrmax)
boolean has_valid_normalized_T_arr(int inode)
struct s_pb_graph_node * parent_node
static void process_constraints(void)
static t_chunk net_delay_ch
static void update_slacks(t_slack *slacks, int source_clock_domain, int sink_clock_domain, float criticality_denom, boolean update_slack)
void free_int_list(t_linked_int **int_list_head_ptr)
int num_constrained_clocks
static void print_timing_constraint_info(const char *fname)
static void alloc_and_load_tnodes(t_timing_inf timing_inf)
boolean isEchoFileEnabled(enum e_echo_files echo_option)
static int get_tnode_index(t_tnode *node)
static int * f_net_to_driver_tnode
struct s_linked_vptr * next
void free_net_delay(float **net_delay, t_chunk *chunk_list_ptr)
t_clock * constrained_clocks
t_pb_graph_pin * pb_graph_pin
float ** alloc_net_delay(t_chunk *chunk_list_ptr, struct s_net *nets, int n_nets)
t_slack * alloc_and_load_timing_graph(t_timing_inf timing_inf)
static void alloc_timing_stats(void)
void print_criticality(t_slack *slacks, boolean criticality_is_normalized, const char *fname)
struct s_pb_type * pb_type
static struct s_net * timing_nets
static void update_normalized_costs(float T_arr_max_this_domain, long max_critical_input_paths, long max_critical_output_paths)
void load_constant_net_delay(float **net_delay, float delay_value, struct s_net *nets, int n_nets)
void free_timing_stats(void)
static void print_global_criticality_stats(FILE *fp, float **criticality, const char *singular_name, const char *capitalized_plural_name)
float ** timing_criticality
static boolean has_valid_T_req(int inode)
t_pb_graph_pin * pb_graph_pin
t_model_ports * model_port_ptr
static int find_clock(char *net_name)
t_io * constrained_outputs
void print_slack(float **slack, boolean slack_is_normalized, const char *fname)
t_override_constraint * ff_constraints
struct s_linked_int * next
void print_timing_graph(const char *fname)
float print_critical_path_node(FILE *fp, t_linked_int *critical_path_node)
static int find_output(char *net_name)
t_override_constraint * cc_constraints
struct s_tnode *** output_net_tnodes
char * getEchoFileName(enum e_echo_files echo_option)
static char * find_tnode_net_name(int inode, boolean is_prepacked)
t_timing_constraints * g_sdc
void free_chunk_memory(t_chunk *chunk_info)
t_pb_graph_node * pb_graph_node
static void set_and_balance_arrival_time(int to_node, int from_node, float Tdel, boolean do_lut_input_balancing)
void free_timing_graph(t_slack *slacks)
#define HUGE_NEGATIVE_FLOAT
void print_net_delay(float **net_delay, const char *fname)
void load_timing_graph_net_delays(float **net_delay)
t_io * constrained_inputs
static boolean has_valid_T_arr(int inode)
t_pb_graph_pin ** input_pins
struct s_logical_block * logical_block
int alloc_and_load_timing_graph_levels(void)