Merge branch 'multimode_clb' into tileable_routing
This commit is contained in:
commit
a3670bb752
|
@ -81,6 +81,10 @@ char* sdc_constrain_cb_file_name = "cb.sdc";
|
||||||
char* sdc_constrain_sb_file_name = "sb.sdc";
|
char* sdc_constrain_sb_file_name = "sb.sdc";
|
||||||
char* sdc_clock_period_file_name = "clb_clock.sdc";
|
char* sdc_clock_period_file_name = "clb_clock.sdc";
|
||||||
char* sdc_constrain_pb_type_file_name = "clb_constraints.sdc";
|
char* sdc_constrain_pb_type_file_name = "clb_constraints.sdc";
|
||||||
|
char* sdc_break_vertical_sbs_file_name = "break_horizontal_sbs.sdc"; /* We break the vertical to read the horizontal */
|
||||||
|
char* sdc_break_horizontal_sbs_file_name = "break_vertical_sbs.sdc"; /* We break the horizontal to read the vertical */
|
||||||
|
char* sdc_restore_vertical_sbs_file_name = "restore_horizontal_sbs.sdc"; /* We break the vertical to read the horizontal */
|
||||||
|
char* sdc_restore_horizontal_sbs_file_name = "restore_vertical_sbs.sdc"; /* We break the horizontal to read the vertical */
|
||||||
|
|
||||||
char* verilog_mux_basis_posfix = "_basis";
|
char* verilog_mux_basis_posfix = "_basis";
|
||||||
char* verilog_mux_special_basis_posfix = "_special_basis";
|
char* verilog_mux_special_basis_posfix = "_special_basis";
|
||||||
|
|
|
@ -71,6 +71,10 @@ extern char* sdc_constrain_routing_chan_file_name;
|
||||||
extern char* sdc_constrain_cb_file_name;
|
extern char* sdc_constrain_cb_file_name;
|
||||||
extern char* sdc_constrain_sb_file_name;
|
extern char* sdc_constrain_sb_file_name;
|
||||||
extern char* sdc_constrain_pb_type_file_name;
|
extern char* sdc_constrain_pb_type_file_name;
|
||||||
|
extern char* sdc_break_vertical_sbs_file_name;
|
||||||
|
extern char* sdc_break_horizontal_sbs_file_name;
|
||||||
|
extern char* sdc_restore_vertical_sbs_file_name;
|
||||||
|
extern char* sdc_restore_horizontal_sbs_file_name;
|
||||||
|
|
||||||
extern char* verilog_mux_basis_posfix;
|
extern char* verilog_mux_basis_posfix;
|
||||||
extern char* verilog_mux_special_basis_posfix;
|
extern char* verilog_mux_special_basis_posfix;
|
||||||
|
|
|
@ -83,6 +83,7 @@ char* gen_verilog_one_routing_report_timing_Lwire_dir_path(char* report_timing_p
|
||||||
|
|
||||||
static
|
static
|
||||||
char* gen_verilog_one_routing_report_timing_rpt_name(char* report_timing_path,
|
char* gen_verilog_one_routing_report_timing_rpt_name(char* report_timing_path,
|
||||||
|
char* direction,
|
||||||
int L_wire,
|
int L_wire,
|
||||||
int path_id) {
|
int path_id) {
|
||||||
char* ret = NULL;
|
char* ret = NULL;
|
||||||
|
@ -90,28 +91,38 @@ char* gen_verilog_one_routing_report_timing_rpt_name(char* report_timing_path,
|
||||||
|
|
||||||
/* The report will be named after L<lenght>_path<ID>*/
|
/* The report will be named after L<lenght>_path<ID>*/
|
||||||
ret = (char*) my_malloc (sizeof(char) * (strlen(formatted_path)
|
ret = (char*) my_malloc (sizeof(char) * (strlen(formatted_path)
|
||||||
|
+ 1 + strlen(direction)
|
||||||
+ 1 + strlen(my_itoa(L_wire))
|
+ 1 + strlen(my_itoa(L_wire))
|
||||||
+ 5 + strlen(my_itoa(path_id))
|
+ 5 + strlen(my_itoa(path_id))
|
||||||
+ 5));
|
+ 5));
|
||||||
|
|
||||||
sprintf(ret,
|
sprintf(ret,
|
||||||
"%sL%d_path%d.rpt",
|
"%sL%d_%s_path%d.rpt",
|
||||||
formatted_path, L_wire, path_id);
|
formatted_path, L_wire, direction, path_id);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
FILE* create_wireL_report_timing_tcl_file_handler(t_trpt_opts trpt_opts,
|
FILE* create_wireL_report_timing_tcl_file_handler(t_trpt_opts trpt_opts,
|
||||||
|
char* direction,
|
||||||
int L_wire) {
|
int L_wire) {
|
||||||
FILE* fp = NULL;
|
FILE* fp = NULL;
|
||||||
char* sdc_dir_path = NULL;
|
char* sdc_dir_path = NULL;
|
||||||
char* L_wire_str = (char*) my_malloc(sizeof(char) * (1 + strlen(my_itoa(L_wire)) + 2));
|
char* L_wire_str = (char*) my_malloc(sizeof(char) * (1 + strlen(my_itoa(L_wire)) + 2));
|
||||||
char* descr = NULL;
|
char* descr = NULL;
|
||||||
char* sdc_fname = NULL;
|
char* sdc_fname = NULL;
|
||||||
|
char* tmp_direction;
|
||||||
|
|
||||||
sprintf(L_wire_str, "L%d_", L_wire);
|
sprintf(L_wire_str, "L%d_", L_wire);
|
||||||
|
tmp_direction = (char*) my_malloc(sizeof(char) * (strlen(direction) + 2));
|
||||||
|
sprintf(tmp_direction, "%s_", direction);
|
||||||
|
|
||||||
|
sdc_dir_path = (char*) my_malloc(sizeof(char) *
|
||||||
|
(strlen(gen_verilog_one_routing_report_timing_Lwire_dir_path(trpt_opts.sdc_dir,L_wire)) + 1
|
||||||
|
+ strlen(direction) + 1));
|
||||||
|
// sprintf(sdc_dir_path, "%s%s/",
|
||||||
|
// gen_verilog_one_routing_report_timing_Lwire_dir_path(trpt_opts.sdc_dir, L_wire), direction);
|
||||||
sdc_dir_path = gen_verilog_one_routing_report_timing_Lwire_dir_path(trpt_opts.sdc_dir, L_wire);
|
sdc_dir_path = gen_verilog_one_routing_report_timing_Lwire_dir_path(trpt_opts.sdc_dir, L_wire);
|
||||||
|
|
||||||
/* Create dir path*/
|
/* Create dir path*/
|
||||||
|
@ -119,6 +130,7 @@ FILE* create_wireL_report_timing_tcl_file_handler(t_trpt_opts trpt_opts,
|
||||||
|
|
||||||
/* Create the file handler */
|
/* Create the file handler */
|
||||||
sdc_fname = my_strcat(sdc_dir_path, L_wire_str);
|
sdc_fname = my_strcat(sdc_dir_path, L_wire_str);
|
||||||
|
sdc_fname = my_strcat(sdc_fname, tmp_direction);
|
||||||
sdc_fname = my_strcat(sdc_fname, trpt_routing_file_name);
|
sdc_fname = my_strcat(sdc_fname, trpt_routing_file_name);
|
||||||
|
|
||||||
/* Create a file*/
|
/* Create a file*/
|
||||||
|
@ -134,7 +146,7 @@ FILE* create_wireL_report_timing_tcl_file_handler(t_trpt_opts trpt_opts,
|
||||||
descr = (char*)my_malloc(sizeof(char) * (strlen("Report Timing for L-")
|
descr = (char*)my_malloc(sizeof(char) * (strlen("Report Timing for L-")
|
||||||
+ strlen(my_itoa(L_wire))
|
+ strlen(my_itoa(L_wire))
|
||||||
+ strlen(" wires") + 1));
|
+ strlen(" wires") + 1));
|
||||||
sprintf(descr, "Report Timing for L-%d wires", L_wire);
|
sprintf(descr, "Report Timing for L-%d %s wires", L_wire, direction);
|
||||||
|
|
||||||
/* Generate SDC header */
|
/* Generate SDC header */
|
||||||
dump_verilog_sdc_file_header(fp, descr);
|
dump_verilog_sdc_file_header(fp, descr);
|
||||||
|
@ -144,6 +156,7 @@ FILE* create_wireL_report_timing_tcl_file_handler(t_trpt_opts trpt_opts,
|
||||||
my_free(sdc_dir_path);
|
my_free(sdc_dir_path);
|
||||||
my_free(L_wire_str);
|
my_free(L_wire_str);
|
||||||
my_free(sdc_fname);
|
my_free(sdc_fname);
|
||||||
|
my_free(tmp_direction);
|
||||||
|
|
||||||
return fp;
|
return fp;
|
||||||
}
|
}
|
||||||
|
@ -154,6 +167,7 @@ FILE* create_wireL_report_timing_tcl_file_handler(t_trpt_opts trpt_opts,
|
||||||
static
|
static
|
||||||
t_llist* get_wire_L_counter_in_llist(t_llist* rr_path_cnt,
|
t_llist* get_wire_L_counter_in_llist(t_llist* rr_path_cnt,
|
||||||
t_trpt_opts trpt_opts,
|
t_trpt_opts trpt_opts,
|
||||||
|
char* direction,
|
||||||
int L_wire,
|
int L_wire,
|
||||||
t_wireL_cnt** ret_cnt) {
|
t_wireL_cnt** ret_cnt) {
|
||||||
t_llist* temp = rr_path_cnt;
|
t_llist* temp = rr_path_cnt;
|
||||||
|
@ -176,7 +190,7 @@ t_llist* get_wire_L_counter_in_llist(t_llist* rr_path_cnt,
|
||||||
temp_cnt = (t_wireL_cnt*)my_malloc(sizeof(t_wireL_cnt));
|
temp_cnt = (t_wireL_cnt*)my_malloc(sizeof(t_wireL_cnt));
|
||||||
/* Initialization */
|
/* Initialization */
|
||||||
temp_cnt->L_wire = L_wire;
|
temp_cnt->L_wire = L_wire;
|
||||||
temp_cnt->file_handler = create_wireL_report_timing_tcl_file_handler(trpt_opts, L_wire);
|
temp_cnt->file_handler = create_wireL_report_timing_tcl_file_handler(trpt_opts, direction, L_wire);
|
||||||
temp_cnt->cnt = 0;
|
temp_cnt->cnt = 0;
|
||||||
temp->dptr = (void*)temp_cnt;
|
temp->dptr = (void*)temp_cnt;
|
||||||
/* Prepare the counter to return */
|
/* Prepare the counter to return */
|
||||||
|
@ -610,7 +624,6 @@ void verilog_generate_report_timing_one_sb_thru_segments(FILE* fp,
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Report timing for the downstream segements, from a SB output to an adjacent SB input */
|
/* Report timing for the downstream segements, from a SB output to an adjacent SB input */
|
||||||
verilog_generate_one_report_timing_sb_to_sb(fp, src_sb, src_rr_node,
|
verilog_generate_one_report_timing_sb_to_sb(fp, src_sb, src_rr_node,
|
||||||
des_sb, des_rr_node);
|
des_sb, des_rr_node);
|
||||||
|
@ -805,6 +818,7 @@ void dump_verilog_one_sb_wire_segemental_report_timing(FILE* fp,
|
||||||
t_rr_node* drive_rr_node,
|
t_rr_node* drive_rr_node,
|
||||||
t_rr_node* src_rr_node,
|
t_rr_node* src_rr_node,
|
||||||
t_rr_node* des_rr_node,
|
t_rr_node* des_rr_node,
|
||||||
|
char* direction,
|
||||||
int path_cnt) {
|
int path_cnt) {
|
||||||
int L_wire;
|
int L_wire;
|
||||||
int cur_sb_x, cur_sb_y;
|
int cur_sb_x, cur_sb_y;
|
||||||
|
@ -831,22 +845,20 @@ void dump_verilog_one_sb_wire_segemental_report_timing(FILE* fp,
|
||||||
L_wire = get_rr_node_wire_length(src_rr_node);
|
L_wire = get_rr_node_wire_length(src_rr_node);
|
||||||
|
|
||||||
/* Get report name */
|
/* Get report name */
|
||||||
rpt_name = gen_verilog_one_routing_report_timing_rpt_name(fpga_verilog_opts.report_timing_path,
|
rpt_name = gen_verilog_one_routing_report_timing_rpt_name(fpga_verilog_opts.report_timing_path, direction,
|
||||||
L_wire, path_cnt);
|
L_wire, path_cnt);
|
||||||
|
|
||||||
/* Start printing report timing info */
|
/* Start printing report timing info */
|
||||||
fprintf(fp, "# L%d wire, Path ID: %d\n",
|
fprintf(fp, "# L%d wire, Path ID: %d\n",
|
||||||
L_wire,
|
L_wire,
|
||||||
path_cnt);
|
path_cnt);
|
||||||
/* Report timing for the SB MUX delay, from the drive_rr_node to the wire_rr_node */
|
fprintf(fp, "report_timing -from ");
|
||||||
verilog_generate_one_report_timing_within_sb(fp, src_sb,
|
|
||||||
drive_rr_node,
|
/* output instance name */
|
||||||
src_rr_node);
|
fprintf(fp, "%s/",
|
||||||
if (NULL != rpt_name) {
|
src_sb.gen_sb_verilog_instance_name());
|
||||||
fprintf(fp, " > %s\n", rpt_name);
|
/* Find which side the ending pin locates, and determine the coordinate */
|
||||||
} else {
|
dump_verilog_one_sb_routing_pin(fp, src_sb, drive_rr_node);
|
||||||
fprintf(fp, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Switch depends on the type of des_rr_node */
|
/* Switch depends on the type of des_rr_node */
|
||||||
switch(des_rr_node->type) {
|
switch(des_rr_node->type) {
|
||||||
|
@ -969,89 +981,188 @@ void dump_verilog_one_sb_wire_segemental_report_timing(FILE* fp,
|
||||||
RRGSB begin_sb = device_rr_gsb.get_gsb(begin_sb_coordinator);
|
RRGSB begin_sb = device_rr_gsb.get_gsb(begin_sb_coordinator);
|
||||||
/* If this is the ending point, we add a ending segment */
|
/* If this is the ending point, we add a ending segment */
|
||||||
if (ix == end_sb_x - 1) {
|
if (ix == end_sb_x - 1) {
|
||||||
verilog_generate_report_timing_one_sb_ending_segments(fp,
|
switch (des_rr_node->type) {
|
||||||
begin_sb, src_rr_node,
|
case IPIN:
|
||||||
des_rr_node,
|
/* Get the coordinate of ending CB */
|
||||||
rpt_name);
|
next_cb = get_chan_rr_node_ending_cb(src_rr_node, des_rr_node);
|
||||||
|
fprintf(fp, " -to ");
|
||||||
|
/* output instance name */
|
||||||
|
fprintf(fp, "%s/",
|
||||||
|
gen_verilog_one_cb_instance_name(next_cb));
|
||||||
|
/* output pin name */
|
||||||
|
fprintf(fp, "%s",
|
||||||
|
gen_verilog_routing_channel_one_midout_name( next_cb,
|
||||||
|
src_rr_node->ptc_num));
|
||||||
|
|
||||||
continue;
|
fprintf(fp, " -point_to_point");
|
||||||
|
fprintf(fp, " -unconstrained");
|
||||||
|
break;
|
||||||
|
case CHANX:
|
||||||
|
case CHANY:
|
||||||
|
/* Get the coordinate of ending SB */
|
||||||
|
next_sb_coordinator = get_chan_node_ending_sb_coordinator(src_rr_node, des_rr_node);
|
||||||
|
next_sb = device_rr_gsb.get_gsb(next_sb_coordinator);
|
||||||
|
|
||||||
|
fprintf(fp, " -to ");
|
||||||
|
|
||||||
|
/* output instance name */
|
||||||
|
fprintf(fp, "%s/",
|
||||||
|
next_sb.gen_sb_verilog_instance_name());
|
||||||
|
/* Find which side the ending pin locates, and determine the coordinate */
|
||||||
|
dump_verilog_one_sb_chan_pin(fp, next_sb, src_rr_node, IN_PORT);
|
||||||
|
|
||||||
|
fprintf(fp, " -point_to_point");
|
||||||
|
fprintf(fp, " -unconstrained");
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Report timing for the downstream segements, from a SB output to an adjacent CB input */
|
|
||||||
DeviceCoordinator end_sb_coordinator(ix + 1, cur_sb_y);
|
|
||||||
RRGSB end_sb = device_rr_gsb.get_gsb(end_sb_coordinator);
|
|
||||||
verilog_generate_report_timing_one_sb_thru_segments(fp,
|
|
||||||
begin_sb, src_rr_node,
|
|
||||||
end_sb, src_rr_node,
|
|
||||||
rpt_name);
|
|
||||||
}
|
}
|
||||||
} else if ((INC_DIRECTION == src_rr_node->direction)
|
} else if ((INC_DIRECTION == src_rr_node->direction)
|
||||||
&&(CHANY == src_rr_node->type)) {
|
&&(CHANY == src_rr_node->type)) {
|
||||||
/* Follow the graph above, go through Y channel */
|
/* Follow the graph above, go through Y channel */
|
||||||
for (int iy = src_sb.get_sb_y(); iy < end_sb_y; iy++) {
|
for (int iy = src_sb.get_sb_y(); iy < end_sb_y; iy++) {
|
||||||
DeviceCoordinator begin_sb_coordinator(cur_sb_x, iy);
|
DeviceCoordinator begin_sb_coordinator(cur_sb_x, iy);
|
||||||
RRGSB begin_sb = device_rr_gsb.get_gsb(begin_sb_coordinator);
|
RRGSB begin_sb = device_rr_gsb.get_gsb(begin_sb_coordinator);
|
||||||
/* If this is the ending point, we add a ending segment */
|
/* If this is the ending point, we add a ending segment */
|
||||||
if (iy == end_sb_y - 1) {
|
if (iy == end_sb_y - 1) {
|
||||||
verilog_generate_report_timing_one_sb_ending_segments(fp,
|
switch (des_rr_node->type) {
|
||||||
begin_sb, src_rr_node,
|
case IPIN:
|
||||||
des_rr_node,
|
/* Get the coordinate of ending CB */
|
||||||
rpt_name);
|
next_cb = get_chan_rr_node_ending_cb(src_rr_node, des_rr_node);
|
||||||
continue;
|
fprintf(fp, " -to ");
|
||||||
|
/* output instance name */
|
||||||
|
fprintf(fp, "%s/",
|
||||||
|
gen_verilog_one_cb_instance_name(next_cb));
|
||||||
|
/* output pin name */
|
||||||
|
fprintf(fp, "%s",
|
||||||
|
gen_verilog_routing_channel_one_midout_name( next_cb,
|
||||||
|
src_rr_node->ptc_num));
|
||||||
|
|
||||||
|
fprintf(fp, " -point_to_point");
|
||||||
|
fprintf(fp, " -unconstrained");
|
||||||
|
break;
|
||||||
|
case CHANX:
|
||||||
|
case CHANY:
|
||||||
|
/* Get the coordinate of ending SB */
|
||||||
|
next_sb_coordinator = get_chan_node_ending_sb_coordinator(src_rr_node, des_rr_node);
|
||||||
|
next_sb = device_rr_gsb.get_gsb(next_sb_coordinator);
|
||||||
|
|
||||||
|
fprintf(fp, " -to ");
|
||||||
|
|
||||||
|
/* output instance name */
|
||||||
|
fprintf(fp, "%s/",
|
||||||
|
next_sb.gen_sb_verilog_instance_name());
|
||||||
|
/* Find which side the ending pin locates, and determine the coordinate */
|
||||||
|
dump_verilog_one_sb_chan_pin(fp, next_sb, src_rr_node, IN_PORT);
|
||||||
|
|
||||||
|
fprintf(fp, " -point_to_point");
|
||||||
|
fprintf(fp, " -unconstrained");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Report timing for the downstream segements, from a SB output to an adjacent CB input */
|
|
||||||
DeviceCoordinator end_sb_coordinator(cur_sb_x, iy + 1);
|
|
||||||
RRGSB end_sb = device_rr_gsb.get_gsb(end_sb_coordinator);
|
|
||||||
verilog_generate_report_timing_one_sb_thru_segments(fp,
|
|
||||||
begin_sb, src_rr_node,
|
|
||||||
end_sb, src_rr_node,
|
|
||||||
rpt_name);
|
|
||||||
}
|
}
|
||||||
} else if ((DEC_DIRECTION == src_rr_node->direction)
|
} else if ((DEC_DIRECTION == src_rr_node->direction)
|
||||||
&&(CHANX == src_rr_node->type)) {
|
&&(CHANX == src_rr_node->type)) {
|
||||||
/* Follow the graph above, go through X channel */
|
/* Follow the graph above, go through X channel */
|
||||||
for (int ix = src_sb.get_sb_x() - 1; ix > end_sb_x; ix--) {
|
for (int ix = src_sb.get_sb_x() - 1; ix > end_sb_x; ix--) {
|
||||||
DeviceCoordinator begin_sb_coordinator(ix, cur_sb_y);
|
DeviceCoordinator begin_sb_coordinator(ix, cur_sb_y);
|
||||||
RRGSB begin_sb = device_rr_gsb.get_gsb(begin_sb_coordinator);
|
RRGSB begin_sb = device_rr_gsb.get_gsb(begin_sb_coordinator);
|
||||||
/* If this is the ending point, we add a ending segment */
|
/* If this is the ending point, we add a ending segment */
|
||||||
if (ix == end_sb_x + 1) {
|
if (ix == end_sb_x + 1) {
|
||||||
verilog_generate_report_timing_one_sb_ending_segments(fp,
|
switch (des_rr_node->type) {
|
||||||
begin_sb, src_rr_node,
|
case IPIN:
|
||||||
des_rr_node,
|
/* Get the coordinate of ending CB */
|
||||||
rpt_name);
|
next_cb = get_chan_rr_node_ending_cb(src_rr_node, des_rr_node);
|
||||||
continue;
|
fprintf(fp, " -to ");
|
||||||
|
/* output instance name */
|
||||||
|
fprintf(fp, "%s/",
|
||||||
|
gen_verilog_one_cb_instance_name(next_cb));
|
||||||
|
/* output pin name */
|
||||||
|
fprintf(fp, "%s",
|
||||||
|
gen_verilog_routing_channel_one_midout_name( next_cb,
|
||||||
|
src_rr_node->ptc_num));
|
||||||
|
|
||||||
|
fprintf(fp, " -point_to_point");
|
||||||
|
fprintf(fp, " -unconstrained");
|
||||||
|
break;
|
||||||
|
case CHANX:
|
||||||
|
case CHANY:
|
||||||
|
/* Get the coordinate of ending SB */
|
||||||
|
next_sb_coordinator = get_chan_node_ending_sb_coordinator(src_rr_node, des_rr_node);
|
||||||
|
next_sb = device_rr_gsb.get_gsb(next_sb_coordinator);
|
||||||
|
|
||||||
|
fprintf(fp, " -to ");
|
||||||
|
|
||||||
|
/* output instance name */
|
||||||
|
fprintf(fp, "%s/",
|
||||||
|
next_sb.gen_sb_verilog_instance_name());
|
||||||
|
/* Find which side the ending pin locates, and determine the coordinate */
|
||||||
|
dump_verilog_one_sb_chan_pin(fp, next_sb, src_rr_node, IN_PORT);
|
||||||
|
|
||||||
|
fprintf(fp, " -point_to_point");
|
||||||
|
fprintf(fp, " -unconstrained");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Report timing for the downstream segements, from a SB output to an adjacent CB input */
|
|
||||||
DeviceCoordinator end_sb_coordinator(ix - 1, cur_sb_y);
|
|
||||||
RRGSB end_sb = device_rr_gsb.get_gsb(end_sb_coordinator);
|
|
||||||
verilog_generate_report_timing_one_sb_thru_segments(fp,
|
|
||||||
begin_sb, src_rr_node,
|
|
||||||
end_sb, src_rr_node,
|
|
||||||
rpt_name);
|
|
||||||
}
|
}
|
||||||
} else if ((DEC_DIRECTION == src_rr_node->direction)
|
} else if ((DEC_DIRECTION == src_rr_node->direction)
|
||||||
&&(CHANY == src_rr_node->type)) {
|
&&(CHANY == src_rr_node->type)) {
|
||||||
/* Follow the graph above, go through Y channel */
|
/* Follow the graph above, go through Y channel */
|
||||||
for (int iy = src_sb.get_sb_y() - 1; iy > end_sb_y; iy--) {
|
for (int iy = src_sb.get_sb_y() - 1; iy > end_sb_y; iy--) {
|
||||||
DeviceCoordinator begin_sb_coordinator(cur_sb_x, iy);
|
DeviceCoordinator begin_sb_coordinator(cur_sb_x, iy);
|
||||||
RRGSB begin_sb = device_rr_gsb.get_gsb(begin_sb_coordinator);
|
RRGSB begin_sb = device_rr_gsb.get_gsb(begin_sb_coordinator);
|
||||||
/* If this is the ending point, we add a ending segment */
|
/* If this is the ending point, we add a ending segment */
|
||||||
if (iy == end_sb_y + 1) {
|
if (iy == end_sb_y + 1) {
|
||||||
verilog_generate_report_timing_one_sb_ending_segments(fp,
|
switch (des_rr_node->type) {
|
||||||
begin_sb, src_rr_node,
|
case IPIN:
|
||||||
des_rr_node,
|
/* Get the coordinate of ending CB */
|
||||||
rpt_name);
|
next_cb = get_chan_rr_node_ending_cb(src_rr_node, des_rr_node);
|
||||||
continue;
|
fprintf(fp, " -to ");
|
||||||
|
/* output instance name */
|
||||||
|
fprintf(fp, "%s/",
|
||||||
|
gen_verilog_one_cb_instance_name(next_cb));
|
||||||
|
/* output pin name */
|
||||||
|
fprintf(fp, "%s",
|
||||||
|
gen_verilog_routing_channel_one_midout_name( next_cb,
|
||||||
|
src_rr_node->ptc_num));
|
||||||
|
|
||||||
|
fprintf(fp, " -point_to_point");
|
||||||
|
fprintf(fp, " -unconstrained");
|
||||||
|
break;
|
||||||
|
case CHANX:
|
||||||
|
case CHANY:
|
||||||
|
/* Get the coordinate of ending SB */
|
||||||
|
next_sb_coordinator = get_chan_node_ending_sb_coordinator(src_rr_node, des_rr_node);
|
||||||
|
next_sb = device_rr_gsb.get_gsb(next_sb_coordinator);
|
||||||
|
|
||||||
|
fprintf(fp, " -to ");
|
||||||
|
|
||||||
|
/* output instance name */
|
||||||
|
fprintf(fp, "%s/",
|
||||||
|
next_sb.gen_sb_verilog_instance_name());
|
||||||
|
/* Find which side the ending pin locates, and determine the coordinate */
|
||||||
|
dump_verilog_one_sb_chan_pin(fp, next_sb, src_rr_node, IN_PORT);
|
||||||
|
|
||||||
|
fprintf(fp, " -point_to_point");
|
||||||
|
fprintf(fp, " -unconstrained");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Report timing for the downstream segements, from a SB output to an adjacent CB input */
|
|
||||||
DeviceCoordinator end_sb_coordinator(cur_sb_x, iy - 1);
|
|
||||||
RRGSB end_sb = device_rr_gsb.get_gsb(end_sb_coordinator);
|
|
||||||
verilog_generate_report_timing_one_sb_thru_segments(fp,
|
|
||||||
begin_sb, src_rr_node,
|
|
||||||
end_sb, src_rr_node,
|
|
||||||
rpt_name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (NULL != rpt_name) {
|
||||||
|
fprintf(fp, " > %s\n", rpt_name);
|
||||||
|
} else {
|
||||||
|
fprintf(fp, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
/* Free */
|
/* Free */
|
||||||
my_free(rpt_name);
|
my_free(rpt_name);
|
||||||
|
|
||||||
|
@ -1069,6 +1180,7 @@ void dump_verilog_one_sb_wire_segemental_report_timing(FILE* fp,
|
||||||
t_rr_node* drive_rr_node,
|
t_rr_node* drive_rr_node,
|
||||||
t_rr_node* src_rr_node,
|
t_rr_node* src_rr_node,
|
||||||
t_rr_node* des_rr_node,
|
t_rr_node* des_rr_node,
|
||||||
|
char* direction,
|
||||||
int path_cnt) {
|
int path_cnt) {
|
||||||
int L_wire;
|
int L_wire;
|
||||||
int ix, iy;
|
int ix, iy;
|
||||||
|
@ -1095,7 +1207,7 @@ void dump_verilog_one_sb_wire_segemental_report_timing(FILE* fp,
|
||||||
L_wire = get_rr_node_wire_length(src_rr_node);
|
L_wire = get_rr_node_wire_length(src_rr_node);
|
||||||
|
|
||||||
/* Get report name */
|
/* Get report name */
|
||||||
rpt_name = gen_verilog_one_routing_report_timing_rpt_name(fpga_verilog_opts.report_timing_path,
|
rpt_name = gen_verilog_one_routing_report_timing_rpt_name(fpga_verilog_opts.report_timing_path, direction,
|
||||||
L_wire, path_cnt);
|
L_wire, path_cnt);
|
||||||
|
|
||||||
/* Start printing report timing info */
|
/* Start printing report timing info */
|
||||||
|
@ -2717,7 +2829,7 @@ void verilog_generate_sb_report_timing(t_trpt_opts sdc_opts,
|
||||||
|
|
||||||
if (NULL == fp) {
|
if (NULL == fp) {
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
vpr_printf(TIO_MESSAGE_ERROR,
|
||||||
"(FILE:%s,LINE[%d])Failure in create SDC constraints %s",
|
"(FILE:%s,LINE[%d])Failure in creating SDC constraints %s",
|
||||||
__FILE__, __LINE__, sdc_fname);
|
__FILE__, __LINE__, sdc_fname);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -2784,6 +2896,7 @@ void verilog_generate_one_routing_segmental_report_timing(FILE* fp,
|
||||||
const RRGSB& rr_sb,
|
const RRGSB& rr_sb,
|
||||||
t_rr_node* wire_rr_node,
|
t_rr_node* wire_rr_node,
|
||||||
t_rr_node* LL_rr_node,
|
t_rr_node* LL_rr_node,
|
||||||
|
char* direction,
|
||||||
int* path_cnt) {
|
int* path_cnt) {
|
||||||
int num_end_rr_nodes = 0;
|
int num_end_rr_nodes = 0;
|
||||||
t_rr_node** end_rr_node = NULL;
|
t_rr_node** end_rr_node = NULL;
|
||||||
|
@ -2813,6 +2926,7 @@ void verilog_generate_one_routing_segmental_report_timing(FILE* fp,
|
||||||
wire_rr_node->drive_rr_nodes[iedge],
|
wire_rr_node->drive_rr_nodes[iedge],
|
||||||
wire_rr_node,
|
wire_rr_node,
|
||||||
end_rr_node[jedge],
|
end_rr_node[jedge],
|
||||||
|
direction,
|
||||||
*path_cnt);
|
*path_cnt);
|
||||||
/* Update counter */
|
/* Update counter */
|
||||||
(*path_cnt)++;
|
(*path_cnt)++;
|
||||||
|
@ -2840,6 +2954,7 @@ void verilog_generate_one_routing_segmental_report_timing(FILE* fp,
|
||||||
t_sb* cur_sb_info,
|
t_sb* cur_sb_info,
|
||||||
t_rr_node* wire_rr_node,
|
t_rr_node* wire_rr_node,
|
||||||
t_rr_node* LL_rr_node,
|
t_rr_node* LL_rr_node,
|
||||||
|
char* direction,
|
||||||
int* path_cnt) {
|
int* path_cnt) {
|
||||||
int iedge, jedge;
|
int iedge, jedge;
|
||||||
int num_end_rr_nodes = 0;
|
int num_end_rr_nodes = 0;
|
||||||
|
@ -2870,6 +2985,7 @@ void verilog_generate_one_routing_segmental_report_timing(FILE* fp,
|
||||||
wire_rr_node->drive_rr_nodes[iedge],
|
wire_rr_node->drive_rr_nodes[iedge],
|
||||||
wire_rr_node,
|
wire_rr_node,
|
||||||
end_rr_node[jedge],
|
end_rr_node[jedge],
|
||||||
|
direction,
|
||||||
*path_cnt);
|
*path_cnt);
|
||||||
/* Update counter */
|
/* Update counter */
|
||||||
(*path_cnt)++;
|
(*path_cnt)++;
|
||||||
|
@ -2881,7 +2997,7 @@ void verilog_generate_one_routing_segmental_report_timing(FILE* fp,
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//BC TODO
|
|
||||||
static
|
static
|
||||||
void verilog_generate_routing_report_timing(t_trpt_opts trpt_opts,
|
void verilog_generate_routing_report_timing(t_trpt_opts trpt_opts,
|
||||||
t_rr_node* LL_rr_node,
|
t_rr_node* LL_rr_node,
|
||||||
|
@ -2898,6 +3014,9 @@ void verilog_generate_routing_report_timing(t_trpt_opts trpt_opts,
|
||||||
vpr_printf(TIO_MESSAGE_INFO,
|
vpr_printf(TIO_MESSAGE_INFO,
|
||||||
"Generating TCL script to report timing for routing wires\n");
|
"Generating TCL script to report timing for routing wires\n");
|
||||||
|
|
||||||
|
vpr_printf(TIO_MESSAGE_INFO,
|
||||||
|
"Generating TCL script to report timing for routing wires horizontal\n");
|
||||||
|
/* Start with horizontal SBs*/
|
||||||
/* We start from a SB[x][y] */
|
/* We start from a SB[x][y] */
|
||||||
for (ix = 0; ix < (nx + 1); ix++) {
|
for (ix = 0; ix < (nx + 1); ix++) {
|
||||||
for (iy = 0; iy < (ny + 1); iy++) {
|
for (iy = 0; iy < (ny + 1); iy++) {
|
||||||
|
@ -2915,10 +3034,13 @@ void verilog_generate_routing_report_timing(t_trpt_opts trpt_opts,
|
||||||
if (1 == cur_sb_info->chan_rr_node[side][itrack]->num_drive_rr_nodes) {
|
if (1 == cur_sb_info->chan_rr_node[side][itrack]->num_drive_rr_nodes) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (CHANY == cur_sb_info->chan_rr_node[side][itrack]->type) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
/* Check if L_wire exists in the linked list */
|
/* Check if L_wire exists in the linked list */
|
||||||
L_wire = get_rr_node_wire_length(cur_sb_info->chan_rr_node[side][itrack]);
|
L_wire = get_rr_node_wire_length(cur_sb_info->chan_rr_node[side][itrack]);
|
||||||
/* Get counter */
|
/* Get counter */
|
||||||
rr_path_cnt = get_wire_L_counter_in_llist(rr_path_cnt, trpt_opts, L_wire, &wireL_cnt);
|
rr_path_cnt = get_wire_L_counter_in_llist(rr_path_cnt, trpt_opts, "horizontal", L_wire, &wireL_cnt);
|
||||||
path_cnt = wireL_cnt->cnt;
|
path_cnt = wireL_cnt->cnt;
|
||||||
fp = wireL_cnt->file_handler;
|
fp = wireL_cnt->file_handler;
|
||||||
/* This is a new L-wire, create the file handler and the mkdir command to the TCL script */
|
/* This is a new L-wire, create the file handler and the mkdir command to the TCL script */
|
||||||
|
@ -2927,21 +3049,21 @@ void verilog_generate_routing_report_timing(t_trpt_opts trpt_opts,
|
||||||
gen_verilog_one_routing_report_timing_Lwire_dir_path(fpga_verilog_opts.report_timing_path, L_wire));
|
gen_verilog_one_routing_report_timing_Lwire_dir_path(fpga_verilog_opts.report_timing_path, L_wire));
|
||||||
}
|
}
|
||||||
/* Restore the disable_timing for the SB outputs on the path */
|
/* Restore the disable_timing for the SB outputs on the path */
|
||||||
fprintf(fp, "# Restore disable timing for the following Switch Block output:\n");
|
/*fprintf(fp, "# Restore disable timing for the following Switch Block output:\n");
|
||||||
restore_disable_timing_one_sb_output(fp,
|
restore_disable_timing_one_sb_output(fp,
|
||||||
cur_sb_info,
|
cur_sb_info,
|
||||||
cur_sb_info->chan_rr_node[side][itrack]);
|
cur_sb_info->chan_rr_node[side][itrack]);
|
||||||
fprintf(fp, "# Report timing for all the paths using this output:\n");
|
fprintf(fp, "# Report timing for all the paths using this output:\n");*/
|
||||||
/* Dump report_timing command */
|
/* Dump report_timing command */
|
||||||
verilog_generate_one_routing_segmental_report_timing(fp, fpga_verilog_opts,
|
verilog_generate_one_routing_segmental_report_timing(fp, fpga_verilog_opts,
|
||||||
cur_sb_info,
|
cur_sb_info,
|
||||||
cur_sb_info->chan_rr_node[side][itrack],
|
cur_sb_info->chan_rr_node[side][itrack],
|
||||||
LL_rr_node, &path_cnt);
|
LL_rr_node, "horizontal", &path_cnt);
|
||||||
/* Disable the timing again */
|
/* Disable the timing again */
|
||||||
fprintf(fp, "# Set disable timing for the following Switch Block output:\n");
|
/*fprintf(fp, "# Set disable timing for the following Switch Block output:\n");
|
||||||
set_disable_timing_one_sb_output(fp,
|
set_disable_timing_one_sb_output(fp,
|
||||||
cur_sb_info,
|
cur_sb_info,
|
||||||
cur_sb_info->chan_rr_node[side][itrack]);
|
cur_sb_info->chan_rr_node[side][itrack]);*/
|
||||||
/* Update the wire L*/
|
/* Update the wire L*/
|
||||||
update_wire_L_counter_in_llist(rr_path_cnt, L_wire, path_cnt);
|
update_wire_L_counter_in_llist(rr_path_cnt, L_wire, path_cnt);
|
||||||
}
|
}
|
||||||
|
@ -2949,6 +3071,70 @@ void verilog_generate_routing_report_timing(t_trpt_opts trpt_opts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* close file*/
|
||||||
|
fclose_wire_L_file_handler_in_llist(rr_path_cnt);
|
||||||
|
/* Need to reset the different variables */
|
||||||
|
cur_sb_info = NULL;
|
||||||
|
rr_path_cnt = NULL;
|
||||||
|
wireL_cnt = NULL;
|
||||||
|
path_cnt = 0;
|
||||||
|
|
||||||
|
vpr_printf(TIO_MESSAGE_INFO,
|
||||||
|
"Generating TCL script to report timing for routing wires vertical\n");
|
||||||
|
/* Start with vertical SBs*/
|
||||||
|
/* We start from a SB[x][y] */
|
||||||
|
for (ix = 0; ix < (nx + 1); ix++) {
|
||||||
|
for (iy = 0; iy < (ny + 1); iy++) {
|
||||||
|
cur_sb_info = &(sb_info[ix][iy]);
|
||||||
|
for (side = 0; side < cur_sb_info->num_sides; side++) {
|
||||||
|
for (itrack = 0; itrack < cur_sb_info->chan_width[side]; itrack++) {
|
||||||
|
assert((CHANX == cur_sb_info->chan_rr_node[side][itrack]->type)
|
||||||
|
||(CHANY == cur_sb_info->chan_rr_node[side][itrack]->type));
|
||||||
|
/* We only care the output port and it should indicate a SB mux */
|
||||||
|
if ( (OUT_PORT != cur_sb_info->chan_rr_node_direction[side][itrack])
|
||||||
|
|| (FALSE != check_drive_rr_node_imply_short(*cur_sb_info, cur_sb_info->chan_rr_node[side][itrack], side))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Bypass if we have only 1 driving node */
|
||||||
|
if (1 == cur_sb_info->chan_rr_node[side][itrack]->num_drive_rr_nodes) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (CHANX == cur_sb_info->chan_rr_node[side][itrack]->type) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Check if L_wire exists in the linked list */
|
||||||
|
L_wire = get_rr_node_wire_length(cur_sb_info->chan_rr_node[side][itrack]);
|
||||||
|
/* Get counter */
|
||||||
|
rr_path_cnt = get_wire_L_counter_in_llist(rr_path_cnt, trpt_opts, "vertical", L_wire, &wireL_cnt);
|
||||||
|
path_cnt = wireL_cnt->cnt;
|
||||||
|
fp = wireL_cnt->file_handler;
|
||||||
|
/* This is a new L-wire, create the file handler and the mkdir command to the TCL script */
|
||||||
|
if (0 == path_cnt) {
|
||||||
|
fprintf(fp, "exec mkdir -p %s\n",
|
||||||
|
gen_verilog_one_routing_report_timing_Lwire_dir_path(fpga_verilog_opts.report_timing_path, L_wire));
|
||||||
|
}
|
||||||
|
/* Restore the disable_timing for the SB outputs on the path */
|
||||||
|
/*fprintf(fp, "# Restore disable timing for the following Switch Block output:\n");
|
||||||
|
restore_disable_timing_one_sb_output(fp,
|
||||||
|
cur_sb_info,
|
||||||
|
cur_sb_info->chan_rr_node[side][itrack]);*/
|
||||||
|
fprintf(fp, "# Report timing for all the paths using this output:\n");
|
||||||
|
/* Dump report_timing command */
|
||||||
|
verilog_generate_one_routing_segmental_report_timing(fp, fpga_verilog_opts,
|
||||||
|
cur_sb_info,
|
||||||
|
cur_sb_info->chan_rr_node[side][itrack],
|
||||||
|
LL_rr_node, "vertical", &path_cnt);
|
||||||
|
/* Disable the timing again */
|
||||||
|
/*fprintf(fp, "# Set disable timing for the following Switch Block output:\n");
|
||||||
|
set_disable_timing_one_sb_output(fp,
|
||||||
|
cur_sb_info,
|
||||||
|
cur_sb_info->chan_rr_node[side][itrack]);*/
|
||||||
|
/* Update the wire L*/
|
||||||
|
update_wire_L_counter_in_llist(rr_path_cnt, L_wire, path_cnt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/* close file*/
|
/* close file*/
|
||||||
fclose_wire_L_file_handler_in_llist(rr_path_cnt);
|
fclose_wire_L_file_handler_in_llist(rr_path_cnt);
|
||||||
|
|
||||||
|
@ -2993,7 +3179,7 @@ void verilog_generate_routing_wire_report_timing(t_trpt_opts trpt_opts,
|
||||||
/* Check if L_wire exists in the linked list */
|
/* Check if L_wire exists in the linked list */
|
||||||
L_wire = get_rr_node_wire_length(rr_sb.get_chan_node(side_manager.get_side(), itrack));
|
L_wire = get_rr_node_wire_length(rr_sb.get_chan_node(side_manager.get_side(), itrack));
|
||||||
/* Get counter */
|
/* Get counter */
|
||||||
rr_path_cnt = get_wire_L_counter_in_llist(rr_path_cnt, trpt_opts, L_wire, &wireL_cnt);
|
rr_path_cnt = get_wire_L_counter_in_llist(rr_path_cnt, trpt_opts, "horizontal", L_wire, &wireL_cnt);
|
||||||
path_cnt = wireL_cnt->cnt;
|
path_cnt = wireL_cnt->cnt;
|
||||||
fp = wireL_cnt->file_handler;
|
fp = wireL_cnt->file_handler;
|
||||||
/* This is a new L-wire, create the file handler and the mkdir command to the TCL script */
|
/* This is a new L-wire, create the file handler and the mkdir command to the TCL script */
|
||||||
|
@ -3002,21 +3188,21 @@ void verilog_generate_routing_wire_report_timing(t_trpt_opts trpt_opts,
|
||||||
gen_verilog_one_routing_report_timing_Lwire_dir_path(fpga_verilog_opts.report_timing_path, L_wire));
|
gen_verilog_one_routing_report_timing_Lwire_dir_path(fpga_verilog_opts.report_timing_path, L_wire));
|
||||||
}
|
}
|
||||||
/* Restore the disable_timing for the SB outputs on the path */
|
/* Restore the disable_timing for the SB outputs on the path */
|
||||||
fprintf(fp, "# Restore disable timing for the following Switch Block output:\n");
|
/*fprintf(fp, "# Restore disable timing for the following Switch Block output:\n");
|
||||||
restore_disable_timing_one_sb_output(fp,
|
restore_disable_timing_one_sb_output(fp,
|
||||||
rr_sb,
|
rr_sb,
|
||||||
rr_sb.get_chan_node(side_manager.get_side(), itrack));
|
rr_sb.get_chan_node(side_manager.get_side(), itrack));*/
|
||||||
fprintf(fp, "# Report timing for all the paths using this output:\n");
|
fprintf(fp, "# Report timing for all the paths using this output:\n");
|
||||||
/* Dump report_timing command */
|
/* Dump report_timing command */
|
||||||
verilog_generate_one_routing_segmental_report_timing(fp, fpga_verilog_opts,
|
verilog_generate_one_routing_segmental_report_timing(fp, fpga_verilog_opts,
|
||||||
rr_sb,
|
rr_sb,
|
||||||
rr_sb.get_chan_node(side_manager.get_side(), itrack),
|
rr_sb.get_chan_node(side_manager.get_side(), itrack),
|
||||||
LL_rr_node, &path_cnt);
|
LL_rr_node, "horizontal", &path_cnt);
|
||||||
/* Disable the timing again */
|
/* Disable the timing again */
|
||||||
fprintf(fp, "# Set disable timing for the following Switch Block output:\n");
|
/*fprintf(fp, "# Set disable timing for the following Switch Block output:\n");
|
||||||
set_disable_timing_one_sb_output(fp,
|
set_disable_timing_one_sb_output(fp,
|
||||||
rr_sb,
|
rr_sb,
|
||||||
rr_sb.get_chan_node(side_manager.get_side(), itrack));
|
rr_sb.get_chan_node(side_manager.get_side(), itrack));*/
|
||||||
/* Update the wire L*/
|
/* Update the wire L*/
|
||||||
update_wire_L_counter_in_llist(rr_path_cnt, L_wire, path_cnt);
|
update_wire_L_counter_in_llist(rr_path_cnt, L_wire, path_cnt);
|
||||||
}
|
}
|
||||||
|
@ -3064,7 +3250,7 @@ void verilog_generate_report_timing(t_sram_orgz_info* cur_sram_orgz_info,
|
||||||
verilog_generate_sb_report_timing(trpt_opts, arch, LL_rr_node);
|
verilog_generate_sb_report_timing(trpt_opts, arch, LL_rr_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Part 3. Report timing for routing segments of SB wires */
|
/* Part 4. Report timing for routing segments of SB wires */
|
||||||
if (TRUE == trpt_opts.report_routing_timing) {
|
if (TRUE == trpt_opts.report_routing_timing) {
|
||||||
if (TRUE == trpt_opts.compact_routing_hierarchy) {
|
if (TRUE == trpt_opts.compact_routing_hierarchy) {
|
||||||
verilog_generate_routing_wire_report_timing(trpt_opts,
|
verilog_generate_routing_wire_report_timing(trpt_opts,
|
||||||
|
|
|
@ -2503,6 +2503,137 @@ void verilog_generate_sdc_input_output_delays(FILE* fp,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void verilog_generate_wire_report_timing_blockage_direction(FILE* fp,
|
||||||
|
char* direction,
|
||||||
|
char* enable,
|
||||||
|
int LL_nx, int LL_ny) {
|
||||||
|
|
||||||
|
int ix, iy;
|
||||||
|
int side, itrack, inode;
|
||||||
|
t_sb* cur_sb_info = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
/* Check the file handler */
|
||||||
|
if (NULL == fp) {
|
||||||
|
vpr_printf(TIO_MESSAGE_ERROR,
|
||||||
|
"(FILE:%s,LINE[%d])Invalid file handler for SDC generation",
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print comments */
|
||||||
|
fprintf(fp,
|
||||||
|
"####################################\n");
|
||||||
|
fprintf(fp,
|
||||||
|
"### Disable for %s Switch blocks ###\n",
|
||||||
|
direction);
|
||||||
|
fprintf(fp,
|
||||||
|
"####################################\n");
|
||||||
|
/* We start from a SB[x][y] */
|
||||||
|
for (ix = 0; ix < (LL_nx + 1); ix++) {
|
||||||
|
for (iy = 0; iy < (LL_ny + 1); iy++) {
|
||||||
|
cur_sb_info = &(sb_info[ix][iy]);
|
||||||
|
for (side = 0; side < cur_sb_info->num_sides; side++) {
|
||||||
|
switch (side) {
|
||||||
|
case TOP:
|
||||||
|
case BOTTOM:
|
||||||
|
if( 0 != strcmp("VERTICAL",direction)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (itrack = 0; itrack < cur_sb_info->chan_width[side]; itrack++) {
|
||||||
|
assert((CHANX == cur_sb_info->chan_rr_node[side][itrack]->type)
|
||||||
|
||(CHANY == cur_sb_info->chan_rr_node[side][itrack]->type));
|
||||||
|
if (0 == cur_sb_info->chan_rr_node[side][itrack]->fan_in) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (OUT_PORT != cur_sb_info->chan_rr_node_direction[side][itrack]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (0 == strcmp("DISABLE",enable) ) {
|
||||||
|
fprintf(fp, "set_disable_timing ");
|
||||||
|
}
|
||||||
|
if (0 == strcmp("RESTORE",enable) ) {
|
||||||
|
fprintf(fp, "reset_disable_timing ");
|
||||||
|
}
|
||||||
|
fprintf(fp, "%s/",
|
||||||
|
gen_verilog_one_sb_instance_name(cur_sb_info));
|
||||||
|
dump_verilog_one_sb_chan_pin(fp, cur_sb_info,
|
||||||
|
cur_sb_info->chan_rr_node[side][itrack],
|
||||||
|
OUT_PORT);
|
||||||
|
fprintf(fp, "\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LEFT:
|
||||||
|
case RIGHT:
|
||||||
|
if( 0 != strcmp("HORIZONTAL",direction)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (itrack = 0; itrack < cur_sb_info->chan_width[side]; itrack++) {
|
||||||
|
assert((CHANX == cur_sb_info->chan_rr_node[side][itrack]->type)
|
||||||
|
||(CHANY == cur_sb_info->chan_rr_node[side][itrack]->type));
|
||||||
|
if (0 == cur_sb_info->chan_rr_node[side][itrack]->fan_in) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (OUT_PORT != cur_sb_info->chan_rr_node_direction[side][itrack]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (0 == strcmp("DISABLE",enable) ) {
|
||||||
|
fprintf(fp, "set_disable_timing ");
|
||||||
|
}
|
||||||
|
if (0 == strcmp("RESTORE",enable) ) {
|
||||||
|
fprintf(fp, "reset_disable_timing ");
|
||||||
|
}
|
||||||
|
fprintf(fp, "%s/",
|
||||||
|
gen_verilog_one_sb_instance_name(cur_sb_info));
|
||||||
|
dump_verilog_one_sb_chan_pin(fp, cur_sb_info,
|
||||||
|
cur_sb_info->chan_rr_node[side][itrack],
|
||||||
|
OUT_PORT);
|
||||||
|
fprintf(fp, "\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void verilog_generate_sdc_wire_report_timing_blockage(t_sdc_opts sdc_opts,
|
||||||
|
int LL_nx, int LL_ny) {
|
||||||
|
|
||||||
|
FILE* fp = NULL;
|
||||||
|
char* sdc_fname = NULL;
|
||||||
|
|
||||||
|
/* Create the vertical file */
|
||||||
|
/* Break */
|
||||||
|
sdc_fname = my_strcat(sdc_opts.sdc_dir, sdc_break_vertical_sbs_file_name);
|
||||||
|
fp = fopen(sdc_fname, "w");
|
||||||
|
verilog_generate_wire_report_timing_blockage_direction(fp, "VERTICAL", "DISABLE", LL_nx, LL_ny);
|
||||||
|
fclose(fp);
|
||||||
|
/* Restore */
|
||||||
|
sdc_fname = my_strcat(sdc_opts.sdc_dir, sdc_restore_vertical_sbs_file_name);
|
||||||
|
fp = fopen(sdc_fname, "w");
|
||||||
|
verilog_generate_wire_report_timing_blockage_direction(fp, "VERTICAL", "RESTORE", LL_nx, LL_ny);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
/* Create the horizontal file */
|
||||||
|
|
||||||
|
sdc_fname = my_strcat(sdc_opts.sdc_dir, sdc_break_horizontal_sbs_file_name);
|
||||||
|
fp = fopen(sdc_fname, "w");
|
||||||
|
verilog_generate_wire_report_timing_blockage_direction(fp, "HORIZONTAL", "DISABLE", LL_nx, LL_ny);
|
||||||
|
fclose(fp);
|
||||||
|
sdc_fname = my_strcat(sdc_opts.sdc_dir, sdc_restore_horizontal_sbs_file_name);
|
||||||
|
fp = fopen(sdc_fname, "w");
|
||||||
|
verilog_generate_wire_report_timing_blockage_direction(fp, "HORIZONTAL", "RESTORE", LL_nx, LL_ny);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void verilog_generate_sdc_pnr(t_sram_orgz_info* cur_sram_orgz_info,
|
void verilog_generate_sdc_pnr(t_sram_orgz_info* cur_sram_orgz_info,
|
||||||
char* sdc_dir,
|
char* sdc_dir,
|
||||||
t_arch arch,
|
t_arch arch,
|
||||||
|
@ -2544,6 +2675,9 @@ void verilog_generate_sdc_pnr(t_sram_orgz_info* cur_sram_orgz_info,
|
||||||
verilog_generate_sdc_constrain_sbs(sdc_opts,
|
verilog_generate_sdc_constrain_sbs(sdc_opts,
|
||||||
LL_nx, LL_ny);
|
LL_nx, LL_ny);
|
||||||
}
|
}
|
||||||
|
/* Generate sdc files to help get the timing report on Lwires */
|
||||||
|
verilog_generate_sdc_wire_report_timing_blockage(sdc_opts,
|
||||||
|
LL_nx, LL_ny);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Part 4. Output routing constraints for Connection Blocks */
|
/* Part 4. Output routing constraints for Connection Blocks */
|
||||||
|
@ -2650,5 +2784,3 @@ void verilog_generate_sdc_analysis(t_sram_orgz_info* cur_sram_orgz_info,
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -41,4 +41,10 @@ void dump_sdc_pb_graph_pin_muxes(FILE* fp,
|
||||||
t_rr_graph* rr_graph,
|
t_rr_graph* rr_graph,
|
||||||
t_pb_graph_pin pb_graph_pin);
|
t_pb_graph_pin pb_graph_pin);
|
||||||
|
|
||||||
|
/*void verilog_generate_wire_report_timing_blockage_direction(FILE* fp,
|
||||||
|
char* direction,
|
||||||
|
int LL_nx, int LL_ny);
|
||||||
|
|
||||||
|
void verilog_generate_sdc_wire_report_timing_blockage(t_sdc_opts sdc_opts,
|
||||||
|
int LL_nx, int LL_ny);*/
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue