diff --git a/vpr7_x2p/libarchfpga/SRC/physical_types.h b/vpr7_x2p/libarchfpga/SRC/physical_types.h index 81de09866..e9fb0745e 100644 --- a/vpr7_x2p/libarchfpga/SRC/physical_types.h +++ b/vpr7_x2p/libarchfpga/SRC/physical_types.h @@ -924,6 +924,10 @@ typedef struct s_direct_inf { int y_offset; int z_offset; int line; + /* Aurelien: point to point support in direct connection from directlist */ + enum e_point2point_interconnection_type interconnection_type; + enum e_point2point_interconnection_dir x_dir; + enum e_point2point_interconnection_dir y_dir; /* Xifan Tang: FPGA-SPICE support */ char* spice_model_name; t_spice_model* spice_model; diff --git a/vpr7_x2p/libarchfpga/SRC/read_xml_arch_file.c b/vpr7_x2p/libarchfpga/SRC/read_xml_arch_file.c index d852e07dd..55a05bba9 100644 --- a/vpr7_x2p/libarchfpga/SRC/read_xml_arch_file.c +++ b/vpr7_x2p/libarchfpga/SRC/read_xml_arch_file.c @@ -3578,6 +3578,9 @@ static void ProcessDirects(INOUTP ezxml_t Parent, OUTP t_direct_inf **Directs, const char *direct_name; const char *from_pin_name; const char *to_pin_name; + const char *point2point_type; + const char *x_dir; + const char *y_dir; ezxml_t Node; @@ -3632,6 +3635,77 @@ static void ProcessDirects(INOUTP ezxml_t Parent, OUTP t_direct_inf **Directs, ezxml_set_attr(Node, "y_offset", NULL); ezxml_set_attr(Node, "z_offset", NULL); + // Aurelien: Read point to point connection parameters + if((!FindProperty(Node, "interconnection_type", FALSE)) || + (0 == strcmp(FindProperty(Node, "interconnection_type", FALSE), "NONE"))) { + (*Directs)[i].interconnection_type = NO_P2P; + } else if(0 == strcmp(FindProperty(Node, "interconnection_type", FALSE), "column")) { + (*Directs)[i].interconnection_type = P2P_DIRECT_COLUMN; + } else if(0 == strcmp(FindProperty(Node, "interconnection_type", FALSE), "row")) { + (*Directs)[i].interconnection_type = P2P_DIRECT_ROW; + } else { + (*Directs)[i].interconnection_type = NUM_POINT2POINT_INTERCONNECT_TYPE; + vpr_printf(TIO_MESSAGE_ERROR, + "Invalid point to point connection '%s' in directlist. '%s' value should be '%s', '%s' or '%s' !\n", + (*Directs)[i].name, + "interconnection_type", + "column", + "row", + "NONE" ); + exit(1); + } + if((P2P_DIRECT_COLUMN == (*Directs)[i].interconnection_type) || + (P2P_DIRECT_ROW == (*Directs)[i].interconnection_type)){ + if(0 == strcmp(FindProperty(Node, "x_dir", TRUE), "positive")){ + (*Directs)[i].x_dir = POSITIVE_DIR; + } else if(0 == strcmp(FindProperty(Node, "x_dir", TRUE), "negative")){ + (*Directs)[i].x_dir = NEGATIVE_DIR; + } else { + (*Directs)[i].x_dir = NUM_POINT2POINT_INTERCONNECT_DIR; + vpr_printf(TIO_MESSAGE_ERROR, + "Invalid point to point connection '%s' in directlist. '%s' value should be '%s' or '%s' !\n", + (*Directs)[i].name, + "x_dir", + "positive", + "negative" ); + } + if(0 == strcmp(FindProperty(Node, "y_dir", TRUE), "positive")){ + (*Directs)[i].y_dir = POSITIVE_DIR; + } else if(0 == strcmp(FindProperty(Node, "y_dir", TRUE), "negative")){ + (*Directs)[i].y_dir = NEGATIVE_DIR; + } else { + (*Directs)[i].y_dir = NUM_POINT2POINT_INTERCONNECT_DIR; + vpr_printf(TIO_MESSAGE_ERROR, + "Invalid point to point connection '%s' in directlist. '%s' value should be '%s' or '%s' !\n", + (*Directs)[i].name, + "y_dir", + "positive", + "negative" ); + } + } else { + if(NULL == FindProperty(Node, "x_dir", FALSE)){ + (*Directs)[i].x_dir = NUM_POINT2POINT_INTERCONNECT_DIR; + } else if(0 == strcmp(FindProperty(Node, "x_dir", FALSE), "positive")){ + (*Directs)[i].x_dir = POSITIVE_DIR; + } else if(0 == strcmp(FindProperty(Node, "x_dir", FALSE), "negative")){ + (*Directs)[i].x_dir = NEGATIVE_DIR; + } else { + (*Directs)[i].x_dir = NUM_POINT2POINT_INTERCONNECT_DIR; + } + if(NULL == FindProperty(Node, "y_dir", FALSE)){ + (*Directs)[i].y_dir = NUM_POINT2POINT_INTERCONNECT_DIR; + } else if(0 == strcmp(FindProperty(Node, "y_dir", FALSE), "positive")){ + (*Directs)[i].y_dir = POSITIVE_DIR; + } else if(0 == strcmp(FindProperty(Node, "y_dir", FALSE), "negative")){ + (*Directs)[i].y_dir = NEGATIVE_DIR; + } else { + (*Directs)[i].y_dir = NUM_POINT2POINT_INTERCONNECT_DIR; + } + } + ezxml_set_attr(Node, "x_dir", NULL); + ezxml_set_attr(Node, "y_dir", NULL); + ezxml_set_attr(Node, "interconnection_type", NULL); + /* Check that the direct chain connection is not zero in both direction */ if ((*Directs)[i].x_offset == 0 && (*Directs)[i].y_offset == 0) { vpr_printf(TIO_MESSAGE_ERROR, diff --git a/vpr7_x2p/libarchfpga/SRC/spice_types.h b/vpr7_x2p/libarchfpga/SRC/spice_types.h index 542f5bcbd..26f30b164 100644 --- a/vpr7_x2p/libarchfpga/SRC/spice_types.h +++ b/vpr7_x2p/libarchfpga/SRC/spice_types.h @@ -5,6 +5,20 @@ #include "linkedlist.h" #include "circuit_library.h" +/* Aurelien: point to point connection */ +enum e_point2point_interconnection_type { + NO_P2P, + P2P_DIRECT_COLUMN, + P2P_DIRECT_ROW, + NUM_POINT2POINT_INTERCONNECT_TYPE +}; + +enum e_point2point_interconnection_dir { + POSITIVE_DIR, + NEGATIVE_DIR, + NUM_POINT2POINT_INTERCONNECT_DIR +}; + /* Xifan TANG: Spice support*/ enum e_spice_tech_lib_type { SPICE_LIB_INDUSTRY, diff --git a/vpr7_x2p/vpr/SRC/base/vpr_types.h b/vpr7_x2p/vpr/SRC/base/vpr_types.h index 4b039d5c8..820ee7126 100755 --- a/vpr7_x2p/vpr/SRC/base/vpr_types.h +++ b/vpr7_x2p/vpr/SRC/base/vpr_types.h @@ -1123,6 +1123,10 @@ typedef struct s_clb_to_clb_directs { t_type_descriptor *to_clb_type; int to_clb_pin_start_index; int to_clb_pin_end_index; + /* Aurelien: point to point support in direct connection from directlist */ + enum e_point2point_interconnection_type interconnection_type; + enum e_point2point_interconnection_dir x_dir; + enum e_point2point_interconnection_dir y_dir; /* Xifan Tang: add useful addition info to this struct */ int x_offset; int y_offset; diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_top_netlist_utils.c b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_top_netlist_utils.c index a06b8d35b..0bb9cff78 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_top_netlist_utils.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_top_netlist_utils.c @@ -39,6 +39,7 @@ #include "verilog_decoder.h" #include "verilog_top_netlist_utils.h" + /* Local Subroutines declaration */ /******** Subroutines ***********/ @@ -959,7 +960,7 @@ void dump_verilog_one_clb2clb_direct(FILE* fp, } return; -} +} /* Apply CLB to CLB direct connections to a Verilog netlist */ @@ -990,12 +991,12 @@ void dump_verilog_clb2clb_directs(FILE* fp, */ for (idirect = 0; idirect < num_directs; idirect++) { /* Bypass unmatch types */ - if (grid[ix][iy].type != direct[idirect].from_clb_type) { - continue; - } /* Apply x/y_offset */ to_clb_x = ix + direct[idirect].x_offset; to_clb_y = iy + direct[idirect].y_offset; + if (grid[ix][iy].type != direct[idirect].from_clb_type) { + continue; + } /* see if the destination CLB is in the bound */ if ((FALSE == is_grid_coordinate_in_range(0, nx, to_clb_x)) ||(FALSE == is_grid_coordinate_in_range(0, ny, to_clb_y))) { @@ -1006,21 +1007,157 @@ void dump_verilog_clb2clb_directs(FILE* fp, continue; } */ - /* Check if the to_clb_type matches */ - if (grid[to_clb_x][to_clb_y].type != direct[idirect].to_clb_type) { - continue; - } /* Bypass x/y_offset = 1 * since it may be addressed in Connection blocks if (1 == (x_offset + y_offset)) { continue; } */ - /* Now we can print a direct connection with the spice models */ - dump_verilog_one_clb2clb_direct(fp, - ix, iy, - to_clb_x, to_clb_y, - &direct[idirect]); + + /* Check if the to_clb_type matches */ + if (grid[to_clb_x][to_clb_y].type == direct[idirect].to_clb_type) { + /* Now we can print a direct connection with the spice models */ + dump_verilog_one_clb2clb_direct(fp, + ix, iy, + to_clb_x, to_clb_y, + &direct[idirect]); + /* Check if we can make a point to point connection between direct connection */ + }else if((P2P_DIRECT_COLUMN == direct[idirect].interconnection_type) || + (P2P_DIRECT_ROW == direct[idirect].interconnection_type)){ + /* Check in which case we are to adapt coordinates */ + if((P2P_DIRECT_COLUMN == direct[idirect].interconnection_type) && + (POSITIVE_DIR == direct[idirect].x_dir) && + (POSITIVE_DIR == direct[idirect].y_dir)){ // Bottom to Top on Right + if (grid[ix][iy].type == direct[idirect].from_clb_type) { + to_clb_x = ix + 1; + to_clb_y = ny + 1; + do{ // Find next available type + to_clb_y --; // Scan types from Top to Bottom + if(0 > to_clb_y){ // If scan fails scan the column on the Right until match or no more column + to_clb_x ++; + to_clb_y = ny; + } + } while((grid[to_clb_x][to_clb_y].type != direct[idirect].to_clb_type) && + (nx > to_clb_x)); + } + } else if((P2P_DIRECT_COLUMN == direct[idirect].interconnection_type) && + (POSITIVE_DIR == direct[idirect].x_dir) && + (NEGATIVE_DIR == direct[idirect].y_dir)){ // Top to Bottom on Right + if (grid[ix][iy].type != direct[idirect].from_clb_type) { + to_clb_x = ix + 1; + to_clb_y = -1; + do{ // Find next available type + to_clb_y ++; // Scan types from Bottom to Top + if(ny < to_clb_y){ // If scan fails scan the column on the Right until match or no more column + to_clb_x ++; + to_clb_y = 0; + } + } while((grid[to_clb_x][to_clb_y].type != direct[idirect].to_clb_type) && + (nx >= to_clb_x)); + } + } else if((P2P_DIRECT_COLUMN == direct[idirect].interconnection_type) && + (NEGATIVE_DIR == direct[idirect].x_dir) && + (NEGATIVE_DIR == direct[idirect].y_dir)){ // Top to Bottom on Left + if (grid[ix][iy].type != direct[idirect].from_clb_type) { + to_clb_x = ix - 1; + to_clb_y = -1; + do{ // Find next available type + to_clb_y ++; // Scan types from Bottom to Top + if(ny < to_clb_y){ // If scan fails scan the column on the Left until match or no more column + to_clb_x --; + to_clb_y = 0; + } + } while((grid[to_clb_x][to_clb_y].type != direct[idirect].to_clb_type) && + (0 <= to_clb_x)); + } + } else if((P2P_DIRECT_COLUMN == direct[idirect].interconnection_type) && + (NEGATIVE_DIR == direct[idirect].x_dir) && + (POSITIVE_DIR == direct[idirect].y_dir)){ // Bottom to Top on Left + if (grid[ix][iy].type != direct[idirect].from_clb_type) { + to_clb_x = ix - 1; + to_clb_y = ny + 1; + do{ // Find next available type + to_clb_y --; // Scan types from Top to Bottom + if(0 > to_clb_y){ // If scan fails scan the column on the Left until match or no more column + to_clb_x --; + to_clb_y = ny; + } + } while((grid[to_clb_x][to_clb_y].type != direct[idirect].to_clb_type) && + (0 <= to_clb_x)); + } + } else if((P2P_DIRECT_ROW == direct[idirect].interconnection_type) && + (POSITIVE_DIR == direct[idirect].x_dir) && + (POSITIVE_DIR == direct[idirect].y_dir)){ // Left to Right Above + if (grid[ix][iy].type != direct[idirect].from_clb_type) { + to_clb_x = nx + 1; + to_clb_y = iy + 1; + do{ // Find next available type + to_clb_x --; // Scan types from Right to Left + if(0 > to_clb_x){ // If scan fails scan the row above until match or no more row + to_clb_x = nx; + to_clb_y ++; + } + } while((grid[to_clb_x][to_clb_y].type != direct[idirect].to_clb_type) && + (ny >= to_clb_y)); + } + } else if((P2P_DIRECT_ROW == direct[idirect].interconnection_type) && + (POSITIVE_DIR == direct[idirect].x_dir) && + (NEGATIVE_DIR == direct[idirect].y_dir)){ // Left to Right Below + if (grid[ix][iy].type != direct[idirect].from_clb_type) { + to_clb_x = nx + 1; + to_clb_y = iy - 1; + do{ // Find next available type + to_clb_x --; // Scan types from Right to Left + if(0 > to_clb_x){ // If scan fails scan the row below until match or no more row + to_clb_x = nx; + to_clb_y --; + } + } while((grid[to_clb_x][to_clb_y].type != direct[idirect].to_clb_type) && + (0 <= to_clb_y)); + } + } else if((P2P_DIRECT_ROW == direct[idirect].interconnection_type) && + (NEGATIVE_DIR == direct[idirect].x_dir) && + (NEGATIVE_DIR == direct[idirect].y_dir)){ // Right to Left Below + if (grid[ix][iy].type != direct[idirect].from_clb_type) { + to_clb_x = -1; + to_clb_y = iy - 1; + do{ // Find next available type + to_clb_x ++; // Scan types from Left to Right + if(nx < to_clb_x){ // If scan fails scan the row below until match or no more row + to_clb_x = 0; + to_clb_y --; + } + } while((grid[to_clb_x][to_clb_y].type != direct[idirect].to_clb_type) && + (0 <= to_clb_y)); + } + } else if((P2P_DIRECT_ROW == direct[idirect].interconnection_type) && + (NEGATIVE_DIR == direct[idirect].x_dir) && + (POSITIVE_DIR == direct[idirect].y_dir)){ // Right to Left Above + if (grid[ix][iy].type != direct[idirect].from_clb_type) { + to_clb_x = -1; + to_clb_y = iy + 1; + do{ // Find next available type + to_clb_x ++; // Scan types from Left to Right + if(nx < to_clb_x){ // If scan fails scan the row below until match or no more row + to_clb_x = 0; + to_clb_y ++; + } + } while((grid[to_clb_x][to_clb_y].type != direct[idirect].to_clb_type) && + (ny >= to_clb_y)); + } + } + if(grid[to_clb_x][to_clb_y].type == direct[idirect].from_clb_type){ + /* Now we can print a direct connection with the spice models */ + fprintf(fp, " //----- Point to Point from grid_%d__%d_ to grid_%d__%d_ -----\n", ix, iy, + to_clb_x, to_clb_y); + dump_verilog_one_clb2clb_direct(fp, + ix, iy, + to_clb_x, to_clb_y, + &direct[idirect]); + fprintf(fp, " //----- END Point to Point from grid_%d__%d_ to grid_%d__%d_ -----\n", ix, iy, + to_clb_x, to_clb_y); + } + } } } } diff --git a/vpr7_x2p/vpr/SRC/util/vpr_utils.c b/vpr7_x2p/vpr/SRC/util/vpr_utils.c index 93ef9fe24..049eef7c5 100755 --- a/vpr7_x2p/vpr/SRC/util/vpr_utils.c +++ b/vpr7_x2p/vpr/SRC/util/vpr_utils.c @@ -1245,7 +1245,10 @@ t_clb_to_clb_directs * alloc_and_load_clb_to_clb_directs(INP const t_direct_inf vpr_printf(TIO_MESSAGE_ERROR, "[LINE %d] Range mismatch from %s to %s.\n", directs[i].line, directs[i].from_pin, directs[i].to_pin); exit(1); } - + /* Aurelien: assign point to point parameters */ + clb_to_clb_directs[i].interconnection_type = directs[i].interconnection_type; + clb_to_clb_directs[i].x_dir = directs[i].x_dir; + clb_to_clb_directs[i].y_dir = directs[i].y_dir; /* Xifan Tang: assign values to x,y,z_offset */ clb_to_clb_directs[i].x_offset = directs[i].x_offset; clb_to_clb_directs[i].y_offset = directs[i].y_offset;