From 332ce17f03d1c2e4ab4c4ad2073511f137143205 Mon Sep 17 00:00:00 2001 From: Baudouin Chauviere Date: Tue, 25 Jun 2019 13:44:41 -0600 Subject: [PATCH] Division between horizontal and vertical analysis --- .../vpr/SRC/fpga_x2p/verilog/verilog_global.c | 4 + .../vpr/SRC/fpga_x2p/verilog/verilog_global.h | 4 + .../fpga_x2p/verilog/verilog_report_timing.c | 387 +++++++++++++----- .../vpr/SRC/fpga_x2p/verilog/verilog_sdc.c | 138 ++++++- .../vpr/SRC/fpga_x2p/verilog/verilog_sdc.h | 6 + 5 files changed, 438 insertions(+), 101 deletions(-) diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_global.c b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_global.c index e0f4b26c9..ab9d935d1 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_global.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_global.c @@ -81,6 +81,10 @@ char* sdc_constrain_cb_file_name = "cb.sdc"; char* sdc_constrain_sb_file_name = "sb.sdc"; char* sdc_clock_period_file_name = "clb_clock.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_special_basis_posfix = "_special_basis"; diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_global.h b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_global.h index 4a204cf30..b9183393c 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_global.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_global.h @@ -71,6 +71,10 @@ extern char* sdc_constrain_routing_chan_file_name; extern char* sdc_constrain_cb_file_name; extern char* sdc_constrain_sb_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_special_basis_posfix; diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_report_timing.c b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_report_timing.c index 2d215d872..2c56693b0 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_report_timing.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_report_timing.c @@ -83,6 +83,7 @@ char* gen_verilog_one_routing_report_timing_Lwire_dir_path(char* report_timing_p static char* gen_verilog_one_routing_report_timing_rpt_name(char* report_timing_path, + char* direction, int L_wire, int path_id) { 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_path*/ ret = (char*) my_malloc (sizeof(char) * (strlen(formatted_path) + + 1 + strlen(direction) + 1 + strlen(my_itoa(L_wire)) + 5 + strlen(my_itoa(path_id)) + 5)); sprintf(ret, - "%sL%d_path%d.rpt", - formatted_path, L_wire, path_id); + "%sL%d_%s_path%d.rpt", + formatted_path, L_wire, direction, path_id); return ret; } static FILE* create_wireL_report_timing_tcl_file_handler(t_trpt_opts trpt_opts, + char* direction, int L_wire) { FILE* fp = NULL; char* sdc_dir_path = NULL; char* L_wire_str = (char*) my_malloc(sizeof(char) * (1 + strlen(my_itoa(L_wire)) + 2)); char* descr = NULL; char* sdc_fname = NULL; + char* tmp_direction; 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); /* Create dir path*/ @@ -119,6 +130,7 @@ FILE* create_wireL_report_timing_tcl_file_handler(t_trpt_opts trpt_opts, /* Create the file handler */ 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); /* 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-") + strlen(my_itoa(L_wire)) + 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 */ 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(L_wire_str); my_free(sdc_fname); + my_free(tmp_direction); return fp; } @@ -154,6 +167,7 @@ FILE* create_wireL_report_timing_tcl_file_handler(t_trpt_opts trpt_opts, static t_llist* get_wire_L_counter_in_llist(t_llist* rr_path_cnt, t_trpt_opts trpt_opts, + char* direction, int L_wire, t_wireL_cnt** ret_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)); /* Initialization */ 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->dptr = (void*)temp_cnt; /* Prepare the counter to return */ @@ -610,7 +624,6 @@ void verilog_generate_report_timing_one_sb_thru_segments(FILE* fp, exit(1); } - /* 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, 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* src_rr_node, t_rr_node* des_rr_node, + char* direction, int path_cnt) { int L_wire; int cur_sb_x, cur_sb_y; @@ -831,22 +845,21 @@ void dump_verilog_one_sb_wire_segemental_report_timing(FILE* fp, L_wire = get_rr_node_wire_length(src_rr_node); /* 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); /* Start printing report timing info */ fprintf(fp, "# L%d wire, Path ID: %d\n", L_wire, path_cnt); - /* Report timing for the SB MUX delay, from the drive_rr_node to the wire_rr_node */ - verilog_generate_one_report_timing_within_sb(fp, src_sb, - drive_rr_node, - src_rr_node); - if (NULL != rpt_name) { - fprintf(fp, " > %s\n", rpt_name); - } else { - fprintf(fp, "\n"); - } + + fprintf(fp, "report_timing -from "); + + /* output instance name */ + fprintf(fp, "%s/", + src_sb.gen_sb_verilog_instance_name()); + /* Find which side the ending pin locates, and determine the coordinate */ + dump_verilog_one_sb_routing_pin(fp, src_sb, src_rr_node); /* Switch depends on the type of des_rr_node */ switch(des_rr_node->type) { @@ -969,89 +982,186 @@ void dump_verilog_one_sb_wire_segemental_report_timing(FILE* fp, RRGSB begin_sb = device_rr_gsb.get_gsb(begin_sb_coordinator); /* If this is the ending point, we add a ending segment */ if (ix == end_sb_x - 1) { - verilog_generate_report_timing_one_sb_ending_segments(fp, - begin_sb, src_rr_node, - des_rr_node, - rpt_name); + switch (des_rr_node->type) { + case IPIN: + /* Get the coordinate of ending CB */ + 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; + } } - /* 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) &&(CHANY == src_rr_node->type)) { - /* Follow the graph above, go through Y channel */ - for (int iy = src_sb.get_sb_y(); iy < end_sb_y; iy++) { - DeviceCoordinator begin_sb_coordinator(cur_sb_x, iy); - RRGSB begin_sb = device_rr_gsb.get_gsb(begin_sb_coordinator); - /* If this is the ending point, we add a ending segment */ - if (iy == end_sb_y - 1) { - verilog_generate_report_timing_one_sb_ending_segments(fp, - begin_sb, src_rr_node, - des_rr_node, - rpt_name); - continue; + /* Follow the graph above, go through Y channel */ + for (int iy = src_sb.get_sb_y(); iy < end_sb_y; iy++) { + DeviceCoordinator begin_sb_coordinator(cur_sb_x, iy); + RRGSB begin_sb = device_rr_gsb.get_gsb(begin_sb_coordinator); + /* If this is the ending point, we add a ending segment */ + if (iy == end_sb_y - 1) { + switch (des_rr_node->type) { + case IPIN: + /* Get the coordinate of ending CB */ + 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)); + + 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) &&(CHANX == src_rr_node->type)) { - /* Follow the graph above, go through X channel */ - for (int ix = src_sb.get_sb_x() - 1; ix > end_sb_x; ix--) { - DeviceCoordinator begin_sb_coordinator(ix, cur_sb_y); - RRGSB begin_sb = device_rr_gsb.get_gsb(begin_sb_coordinator); - /* If this is the ending point, we add a ending segment */ - if (ix == end_sb_x + 1) { - verilog_generate_report_timing_one_sb_ending_segments(fp, - begin_sb, src_rr_node, - des_rr_node, - rpt_name); - continue; + /* Follow the graph above, go through X channel */ + for (int ix = src_sb.get_sb_x() - 1; ix > end_sb_x; ix--) { + DeviceCoordinator begin_sb_coordinator(ix, cur_sb_y); + RRGSB begin_sb = device_rr_gsb.get_gsb(begin_sb_coordinator); + /* If this is the ending point, we add a ending segment */ + if (ix == end_sb_x + 1) { + switch (des_rr_node->type) { + case IPIN: + /* Get the coordinate of ending CB */ + 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)); + + 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) &&(CHANY == src_rr_node->type)) { - /* Follow the graph above, go through Y channel */ - for (int iy = src_sb.get_sb_y() - 1; iy > end_sb_y; iy--) { - DeviceCoordinator begin_sb_coordinator(cur_sb_x, iy); - RRGSB begin_sb = device_rr_gsb.get_gsb(begin_sb_coordinator); - /* If this is the ending point, we add a ending segment */ - if (iy == end_sb_y + 1) { - verilog_generate_report_timing_one_sb_ending_segments(fp, - begin_sb, src_rr_node, - des_rr_node, - rpt_name); - continue; + /* Follow the graph above, go through Y channel */ + for (int iy = src_sb.get_sb_y() - 1; iy > end_sb_y; iy--) { + DeviceCoordinator begin_sb_coordinator(cur_sb_x, iy); + RRGSB begin_sb = device_rr_gsb.get_gsb(begin_sb_coordinator); + /* If this is the ending point, we add a ending segment */ + if (iy == end_sb_y + 1) { + switch (des_rr_node->type) { + case IPIN: + /* Get the coordinate of ending CB */ + 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)); + + 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 */ my_free(rpt_name); @@ -1069,6 +1179,7 @@ void dump_verilog_one_sb_wire_segemental_report_timing(FILE* fp, t_rr_node* drive_rr_node, t_rr_node* src_rr_node, t_rr_node* des_rr_node, + char* direction, int path_cnt) { int L_wire; int ix, iy; @@ -1095,7 +1206,7 @@ void dump_verilog_one_sb_wire_segemental_report_timing(FILE* fp, L_wire = get_rr_node_wire_length(src_rr_node); /* 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); /* Start printing report timing info */ @@ -2717,7 +2828,7 @@ void verilog_generate_sb_report_timing(t_trpt_opts sdc_opts, if (NULL == fp) { 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); exit(1); } @@ -2784,6 +2895,7 @@ void verilog_generate_one_routing_segmental_report_timing(FILE* fp, const RRGSB& rr_sb, t_rr_node* wire_rr_node, t_rr_node* LL_rr_node, + char* direction, int* path_cnt) { int num_end_rr_nodes = 0; t_rr_node** end_rr_node = NULL; @@ -2813,6 +2925,7 @@ void verilog_generate_one_routing_segmental_report_timing(FILE* fp, wire_rr_node->drive_rr_nodes[iedge], wire_rr_node, end_rr_node[jedge], + direction, *path_cnt); /* Update counter */ (*path_cnt)++; @@ -2840,6 +2953,7 @@ void verilog_generate_one_routing_segmental_report_timing(FILE* fp, t_sb* cur_sb_info, t_rr_node* wire_rr_node, t_rr_node* LL_rr_node, + char* direction, int* path_cnt) { int iedge, jedge; int num_end_rr_nodes = 0; @@ -2870,6 +2984,7 @@ void verilog_generate_one_routing_segmental_report_timing(FILE* fp, wire_rr_node->drive_rr_nodes[iedge], wire_rr_node, end_rr_node[jedge], + direction, *path_cnt); /* Update counter */ (*path_cnt)++; @@ -2881,7 +2996,7 @@ void verilog_generate_one_routing_segmental_report_timing(FILE* fp, return; } -//BC TODO + static void verilog_generate_routing_report_timing(t_trpt_opts trpt_opts, t_rr_node* LL_rr_node, @@ -2893,11 +3008,14 @@ void verilog_generate_routing_report_timing(t_trpt_opts trpt_opts, t_sb* cur_sb_info = NULL; t_llist* rr_path_cnt = NULL; t_wireL_cnt* wireL_cnt = NULL; - int path_cnt = 0; + int path_cnt = 0; vpr_printf(TIO_MESSAGE_INFO, "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] */ for (ix = 0; ix < (nx + 1); ix++) { for (iy = 0; iy < (ny + 1); iy++) { @@ -2915,33 +3033,39 @@ 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) { continue; } + if (CHANY == 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, 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; 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, "if {![file exists $%s]} {\n", + gen_verilog_one_routing_report_timing_Lwire_dir_path(fpga_verilog_opts.report_timing_path, L_wire)); fprintf(fp, "exec mkdir -p %s\n", gen_verilog_one_routing_report_timing_Lwire_dir_path(fpga_verilog_opts.report_timing_path, L_wire)); + fprintf(fp, "}\n"); } /* 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, cur_sb_info, 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 */ 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, &path_cnt); + LL_rr_node, "horizontal", &path_cnt); /* 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, cur_sb_info, - cur_sb_info->chan_rr_node[side][itrack]); + 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); } @@ -2949,6 +3073,73 @@ 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, "if {![file exists $%s]} {\n", + gen_verilog_one_routing_report_timing_Lwire_dir_path(fpga_verilog_opts.report_timing_path, L_wire)); + fprintf(fp, "exec mkdir -p %s\n", + gen_verilog_one_routing_report_timing_Lwire_dir_path(fpga_verilog_opts.report_timing_path, L_wire)); + fprintf(fp, "}\n"); + } + /* 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*/ fclose_wire_L_file_handler_in_llist(rr_path_cnt); @@ -2993,7 +3184,7 @@ void verilog_generate_routing_wire_report_timing(t_trpt_opts trpt_opts, /* 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)); /* 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; fp = wireL_cnt->file_handler; /* This is a new L-wire, create the file handler and the mkdir command to the TCL script */ @@ -3002,21 +3193,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)); } /* 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, 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"); /* Dump report_timing command */ verilog_generate_one_routing_segmental_report_timing(fp, fpga_verilog_opts, rr_sb, 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 */ - 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, 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_wire_L_counter_in_llist(rr_path_cnt, L_wire, path_cnt); } @@ -3064,7 +3255,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); } - /* 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.compact_routing_hierarchy) { verilog_generate_routing_wire_report_timing(trpt_opts, diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_sdc.c b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_sdc.c index 033903fe6..2b9a4267e 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_sdc.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_sdc.c @@ -2502,6 +2502,137 @@ void verilog_generate_sdc_input_output_delays(FILE* fp, 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, char* sdc_dir, @@ -2544,6 +2675,9 @@ void verilog_generate_sdc_pnr(t_sram_orgz_info* cur_sram_orgz_info, verilog_generate_sdc_constrain_sbs(sdc_opts, 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 */ @@ -2641,7 +2775,7 @@ void verilog_generate_sdc_analysis(t_sram_orgz_info* cur_sram_orgz_info, /* Apply to Grids */ verilog_generate_sdc_disable_unused_grids(fp, LL_nx, LL_ny, LL_grid, LL_block); verilog_generate_sdc_disable_unused_grids_muxs(fp, LL_nx, LL_ny, LL_grid, LL_block); - + /* Close the file*/ fclose(fp); @@ -2650,5 +2784,3 @@ void verilog_generate_sdc_analysis(t_sram_orgz_info* cur_sram_orgz_info, return; } - - diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_sdc.h b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_sdc.h index 4527e331a..813b1517c 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_sdc.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_sdc.h @@ -41,4 +41,10 @@ void dump_sdc_pb_graph_pin_muxes(FILE* fp, t_rr_graph* rr_graph, 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