105 float constraint,
int num_multicycles,
boolean domain_level_from,
boolean domain_level_to,
106 boolean make_copies);
108 static boolean regex_match (
char *
string,
char *pattern);
118 int source_clock_domain, sink_clock_domain, iinput, ioutput, icc, isource, isink;
135 vpr_printf(TIO_MESSAGE_INFO,
"Timing analysis off; using default timing constraints.\n");
140 if ((
sdc = fopen(timing_inf.
SDCFile,
"r")) == NULL) {
142 vpr_printf(TIO_MESSAGE_INFO,
"SDC file '%s' blank or not found.\n", timing_inf.
SDCFile);
164 vpr_printf(TIO_MESSAGE_INFO,
"SDC file '%s' blank or not found.\n", timing_inf.
SDCFile);
176 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] Input %s is associated with an unconstrained clock %s.\n",
186 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] Output %s is associated with an unconstrained clock %s.\n",
198 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] Token %s is not a constrained clock.\n",
206 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] Token %s is not a constrained clock.\n",
218 for (source_clock_domain = 0; source_clock_domain < g_sdc->
num_constrained_clocks; source_clock_domain++) {
243 vpr_printf(TIO_MESSAGE_INFO,
"SDC file '%s' parsed successfully.\n",
245 vpr_printf(TIO_MESSAGE_INFO,
"%d clocks (including virtual clocks), %d inputs and %d outputs were constrained.\n",
259 int source_clock_domain, sink_clock_domain;
279 vpr_printf(TIO_MESSAGE_INFO,
"Defaulting to: constrain all %d inputs and %d outputs on a virtual external clock.\n",
281 vpr_printf(TIO_MESSAGE_INFO,
"Optimize this virtual clock to run as fast as possible.\n");
284 vpr_printf(TIO_MESSAGE_INFO,
"Defaulting to: constrain all %d inputs and %d outputs on the netlist clock.\n",
286 vpr_printf(TIO_MESSAGE_INFO,
"Optimize this clock to run as fast as possible.\n");
306 for (source_clock_domain = 0; source_clock_domain < g_sdc->
num_constrained_clocks; source_clock_domain++) {
318 vpr_printf(TIO_MESSAGE_INFO,
"Defaulting to: constrain all %d inputs and %d outputs on a virtual external clock;\n",
320 vpr_printf(TIO_MESSAGE_INFO,
"\tcut paths between netlist clock domains; and\n");
321 vpr_printf(TIO_MESSAGE_INFO,
"\toptimize all clocks to run as fast as possible.\n");
330 int iblock, i, clock_net;
337 assert(clock_net !=
OPEN);
373 int iblock, i, clock_net;
382 assert(clock_net !=
OPEN);
406 int iblock, iinput, ioutput;
452 #define SDC_TOKENS " \t\n{}[]"
454 char * ptr, ** from_list = NULL, ** to_list = NULL, * clock_name;
455 float clock_period, rising_edge, falling_edge, max_delay;
456 int iclock, iio, num_exclusive_groups = 0,
457 num_from = 0, num_to = 0, num_multicycles, i, j;
459 boolean found, domain_level_from =
FALSE, domain_level_to =
FALSE;
472 if (strcmp(ptr,
"create_clock") == 0) {
478 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] Create_clock must be directly followed by '-period'.\n",
485 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] A number must follow '-period'.\n",
489 clock_period = (float) strtod(ptr, NULL);
492 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] Clock(s) not specified.\n",
496 if (strcmp(ptr,
"-waveform") == 0) {
501 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] First token following '-waveform' should be rising edge, but is not a number.\n",
504 rising_edge = (float) strtod(ptr, NULL);
507 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] Second token following '-waveform' should be falling edge, but is not a number.\n",
511 falling_edge = (float) strtod(ptr, NULL);
514 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] Clock(s) not specified.\n",
522 falling_edge = clock_period / 2.0;
525 if (strcmp(ptr,
"-name") == 0) {
532 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] Virtual clock name not specified.\n",
554 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] More than one virtual clock name is specified after '-name'.\n",
592 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] Clock name or regular expression does not correspond to any nets.\n",
594 vpr_printf(TIO_MESSAGE_ERROR,
"If you'd like to create a virtual clock, use the '-name' keyword.\n");
601 if (fabs(rising_edge - falling_edge) - clock_period/2.0 >
EPSILON) {
602 vpr_printf(TIO_MESSAGE_WARNING,
"Clock %s does not have 50%% duty cycle.\n",
608 }
else if (strcmp(ptr,
"set_clock_groups") == 0) {
612 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_clock_groups must be directly followed by '-exclusive'.\n",
618 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_clock_groups '-exclusive' must be followed by lists of clock names or regular expressions each starting with the '-group' command.\n",
633 exclusive_groups[num_exclusive_groups - 1].
clock_names = NULL;
642 exclusive_groups[num_exclusive_groups - 1].clock_names, ++exclusive_groups[num_exclusive_groups - 1].num_clock_names *
sizeof(
char *));
643 exclusive_groups[num_exclusive_groups - 1].
clock_names
652 exclusive_groups[num_exclusive_groups - 1].clock_names, ++exclusive_groups[num_exclusive_groups - 1].num_clock_names *
sizeof(
char *));
653 exclusive_groups[num_exclusive_groups - 1].
clock_names
660 if (num_exclusive_groups < 2) {
661 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] At least two '-group' commands required.",
672 for (i = 0; i < num_exclusive_groups; i++) {
673 for (j = 0; j < num_exclusive_groups; j++) {
683 for (i = 0; i < num_exclusive_groups; i++) {
685 free(exclusive_groups[i].clock_names[j]);
687 free(exclusive_groups[i].clock_names);
689 free (exclusive_groups);
693 }
else if (strcmp(ptr,
"set_false_path") == 0) {
697 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_false_path must be directly followed by '-from <clock/flip-flop_list>'.\n",
702 if (strcmp(ptr,
"get_clocks") == 0) {
703 domain_level_from =
TRUE;
705 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_false_path must be directly followed by '-from <clock/flip-flop_list>'.\n",
713 from_list = (
char **)
my_realloc(from_list, ++num_from *
sizeof(
char *));
714 from_list[num_from - 1] =
my_strdup(ptr);
718 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_false_path requires '-to <clock/flip-flop_list>' after '-from <clock/flip-flop_list>'.\n",
722 }
while (strcmp(ptr,
"-to") != 0);
725 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_false_path requires '-to <clock/flip-flop_list>' after '-from <clock/flip-flop_list>'.\n",
729 if (strcmp(ptr,
"get_clocks") == 0) {
730 domain_level_to =
TRUE;
732 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_false_path must be directly followed by '-from <clock/flip-flop_list>'.\n",
740 to_list = (
char **)
my_realloc(to_list, ++num_to *
sizeof(
char *));
751 from_list = NULL, to_list = NULL;
755 }
else if (strcmp(ptr,
"set_max_delay") == 0) {
762 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] Token following set_max_delay should be a delay value, but is not a number.\n",
766 max_delay = (float) strtod(ptr, NULL);
769 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_max_delay requires '-from <clock/flip-flop_list>' after max_delay.\n",
774 if (strcmp(ptr,
"get_clocks") == 0) {
775 domain_level_from =
TRUE;
777 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_max_delay requires '-from <clock/flip-flop_list>' after max_delay.\n",
785 from_list = (
char **)
my_realloc(from_list, ++num_from *
sizeof(
char *));
786 from_list[num_from - 1] =
my_strdup(ptr);
790 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_max_delay requires '-to <clock/flip-flop_list>' after '-from <clock/flip-flop_list>'.\n",
794 }
while (strcmp(ptr,
"-to") != 0);
797 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_max_delay requires '-to <clock/flip-flop_list>' after '-from <clock/flip-flop_list>'.\n",
801 if (strcmp(ptr,
"get_clocks") == 0) {
802 domain_level_to =
TRUE;
804 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_max_delay requires '-to <clock/flip-flop_list>' after '-from <clock/flip-flop_list>'.\n",
812 to_list = (
char **)
my_realloc(to_list, ++num_to *
sizeof(
char *));
821 from_list = NULL, to_list = NULL;
825 }
else if (strcmp(ptr,
"set_multicycle_path") == 0) {
834 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_multicycle_path must be directly followed by '-setup'.\n",
840 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_multicycle_path requires '-from <clock/flip-flop_list>' after '-setup'.\n",
845 if (strcmp(ptr,
"get_clocks") == 0) {
846 domain_level_from =
TRUE;
848 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_multicycle_path '-setup' must be followed by '-from <clock/flip-flop_list>'.\n",
856 from_list = (
char **)
my_realloc(from_list, ++num_from *
sizeof(
char *));
857 from_list[num_from - 1] =
my_strdup(ptr);
861 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_multicycle_path requires '-to <clock/flip-flop_list>' after '-from <clock/flip-flop_list>'.\n",
865 }
while (strcmp(ptr,
"-to") != 0);
868 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_multicycle_path requires '-to <clock/flip-flop_list>' after '-from <clock/flip-flop_list>'.\n",
872 if (strcmp(ptr,
"get_clocks") == 0) {
873 domain_level_to =
TRUE;
875 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_multicycle_path requires '-to <clock/flip-flop_list>' after '-from <clock/flip-flop_list>'.\n",
883 to_list = (
char **)
my_realloc(to_list, ++num_to *
sizeof(
char *));
889 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_multicycle_path requires num_multicycles after '-to <clock/flip-flop_list>'.\n",
894 num_multicycles = (int) strtod(ptr, NULL);
899 num_multicycles, domain_level_from, domain_level_to,
FALSE);
903 from_list = NULL, to_list = NULL;
907 }
else if (strcmp(ptr,
"set_input_delay") == 0) {
914 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_input_delay must be directly followed by '-clock <virtual or netlist clock name>'.\n",
928 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_input_delay '-clock <virtual or netlist clock name>' must be directly followed by '-max <maximum_input_delay>'.\n",
935 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] Token following '-max' should be a delay value, but is not a number.\n",
939 max_delay = (float) strtod(ptr, NULL);
942 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_input_delay requires a [get_ports {...}] command following '-max <max_input_delay>'.\n",
976 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] Output name or regular expression \"%s\" does not correspond to any nets.\n",
982 }
else if (strcmp(ptr,
"set_output_delay") == 0) {
989 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_output_delay must be directly followed by '-clock <virtual or netlist clock name>'.\n",
1003 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_output_delay -clock <virtual or netlist clock name> must be directly followed by '-max <maximum_output_delay>'.\n",
1010 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] Token following '-max' should be a delay value, but is not a number.\n",
1014 max_delay = (float) strtod(ptr, NULL);
1017 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] set_output_delay requires a [get_ports {...}] command following '-max <max_output_delay>'.\n",
1051 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] Output name or regular expression \"%s\" does not correspond to any nets.\n",
1058 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] Incorrect or unsupported syntax near start of line.\n",
1068 int i, len, num_decimal_points = 0;
1070 for (i = 0; i < len; i++) {
1071 if ((ptr[i] <
'0' || ptr[i] >
'9')) {
1072 if (ptr[i] !=
'.') {
1075 num_decimal_points++;
1076 if (num_decimal_points > 1) {
1099 int icc, isource, isink;
1116 float constraint,
int num_multicycles,
boolean domain_level_from,
boolean domain_level_to,
1117 boolean make_copies) {
1130 int num_constraints, i;
1132 if (domain_level_from) {
1133 if (domain_level_to) {
1141 if (domain_level_to) {
1154 (*constraint_array)[num_constraints - 1].source_list = (
char **)
my_malloc(num_from *
sizeof(
char *));
1155 (*constraint_array)[num_constraints - 1].sink_list = (
char **)
my_malloc(num_to *
sizeof(
char *));
1156 for (i = 0; i < num_from; i++) {
1157 (*constraint_array)[num_constraints - 1].source_list[i] =
my_strdup(from_list[i]);
1159 for (i = 0; i < num_to; i++) {
1160 (*constraint_array)[num_constraints - 1].sink_list[i] =
my_strdup(to_list[i]);
1164 (*constraint_array)[num_constraints - 1].source_list = from_list;
1165 (*constraint_array)[num_constraints - 1].sink_list = to_list;
1167 (*constraint_array)[num_constraints - 1].num_source = num_from;
1168 (*constraint_array)[num_constraints - 1].num_sink = num_to;
1169 (*constraint_array)[num_constraints - 1].constraint = constraint;
1170 (*constraint_array)[num_constraints - 1].num_multicycles = num_multicycles;
1171 (*constraint_array)[num_constraints - 1].file_line_number =
file_line_number;
1178 int source_period, sink_period, source_rising_edge, sink_rising_edge, lcm_period, num_source_edges, num_sink_edges,
1179 * source_edges, * sink_edges, i, j, time, constraint_as_int;
1186 return source_domain.
period;
1197 source_period =
static_cast<int>(source_domain.
period * 1000);
1198 sink_period =
static_cast<int>(sink_domain.
period * 1000);
1199 source_rising_edge =
static_cast<int>(source_domain.
rising_edge * 1000);
1200 sink_rising_edge =
static_cast<int>(sink_domain.
rising_edge * 1000);
1204 for (lcm_period = 1; lcm_period % source_period != 0 || lcm_period % sink_period != 0; lcm_period++)
1209 num_source_edges = lcm_period/source_period + 1;
1210 num_sink_edges = lcm_period/sink_period + 1;
1212 source_edges = (
int *)
my_malloc((num_source_edges + 1) *
sizeof(int));
1213 sink_edges = (
int *)
my_malloc((num_sink_edges + 1) *
sizeof(int));
1215 for (i = 0, time = source_rising_edge; i < num_source_edges + 1; i++) {
1216 source_edges[i] = time;
1217 time += source_period;
1220 for (i = 0, time = sink_rising_edge; i < num_sink_edges + 1; i++) {
1221 sink_edges[i] = time;
1222 time += sink_period;
1229 constraint_as_int = INT_MAX;
1231 for (i = 0; i < num_source_edges + 1; i++) {
1232 for (j = 0; j < num_sink_edges + 1; j++) {
1233 if (sink_edges[j] > source_edges[i]) {
1234 constraint_as_int =
std::min(constraint_as_int, sink_edges[j] - source_edges[i]);
1241 constraint = constraint_as_int / 1000.;
1249 static boolean regex_match (
char *
string,
char * regular_expression) {
1255 assert(
string && regular_expression);
1261 if (strstr(
string, regular_expression) && strcmp(
string, regular_expression) != 0)
1264 if (strcmp(regular_expression,
"*") == 0)
1271 else if (strcmp(error,
"No match") == 0)
1274 vpr_printf(TIO_MESSAGE_ERROR,
"[SDC line %d] Error matching regular expression \"%s\".\n",
1300 if (!constraint_array)
return;
1302 for (i = 0; i < num_constraints; i++) {
1303 for (j = 0; j < constraint_array[i].
num_source; j++) {
1304 free(constraint_array[i].source_list[j]);
1307 for (j = 0; j < constraint_array[i].
num_sink; j++) {
1308 free(constraint_array[i].sink_list[j]);
1309 constraint_array[i].
sink_list[j] = NULL;
1311 free(constraint_array[i].source_list);
1312 free(constraint_array[i].sink_list);
1314 free(constraint_array);
1315 constraint_array = NULL;
1321 for (i = 0; i < num_ios; i++) {
1322 free(io_array[i].name);
1323 free(io_array[i].clock_name);
1332 for (i = 0; i < num_clocks; i++) {
1333 free(clock_array[i].name);
static void count_netlist_clocks_as_constrained_clocks(void)
static void free_clock_constraint(t_clock *&clock_array, int num_clocks)
void ** alloc_matrix(int nrmin, int nrmax, int ncmin, int ncmax, size_t elsize)
struct s_sdc_clock t_sdc_clock
void free_override_constraint(t_override_constraint *&constraint_array, int num_constraints)
static void count_netlist_ios_as_constrained_ios(char *clock_name, float io_delay)
const char * slre_match(enum slre_option options, const char *re, const char *buf, int buf_len,...)
void free_matrix(void *vptr, int nrmin, int nrmax, int ncmin, size_t elsize)
boolean timing_analysis_enabled
void * my_calloc(size_t nelem, size_t size)
float ** domain_constraint
static boolean is_number(char *ptr)
int num_constrained_outputs
static boolean regex_match(char *string, char *pattern)
t_override_constraint * fc_constraints
void read_sdc(t_timing_inf timing_inf)
static void * my_malloc(int ibytes)
t_override_constraint * cf_constraints
int num_constrained_inputs
static boolean get_sdc_tok(char *buf)
int num_constrained_clocks
static void add_override_constraint(char **from_list, int num_from, char **to_list, int num_to, float constraint, int num_multicycles, boolean domain_level_from, boolean domain_level_to, boolean make_copies)
static void use_default_timing_constraints(void)
static float calculate_constraint(t_sdc_clock source_domain, t_sdc_clock sink_domain)
void free_sdc_related_structs(void)
char * my_strtok(char *ptr, const char *tokens, FILE *fp, char *buf)
static int find_constrained_clock(char *ptr)
t_clock * constrained_clocks
static void free_io_constraint(t_io *&io_array, int num_ios)
static void alloc_and_load_netlist_clocks_and_ios(void)
enum logical_block_types type
struct s_sdc_exclusive_group t_sdc_exclusive_group
static void * my_realloc(void *memblk, int ibytes)
static int find_cc_constraint(char *source_clock_domain, char *sink_clock_domain)
t_io * constrained_outputs
char * my_fgets(char *buf, int max_size, FILE *fp)
t_override_constraint * ff_constraints
t_override_constraint * cc_constraints
t_timing_constraints * g_sdc
char * my_strdup(const char *str)
#define HUGE_NEGATIVE_FLOAT
t_io * constrained_inputs
struct s_logical_block * logical_block