From ae2438cca0d573a010c8fab1630186ad520803f3 Mon Sep 17 00:00:00 2001 From: Wolfgang Spraul Date: Thu, 26 Jul 2012 05:26:27 +0200 Subject: [PATCH] cleanup, wires, new_fp prints static connections --- .gitignore | 4 +- Makefile | 12 +- README | 2 +- model.c | 179 ++++++++++++--------- model.h | 35 +++-- new_floorplan.c | 106 ------------- new_fp.c | 405 ++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 538 insertions(+), 205 deletions(-) delete mode 100644 new_floorplan.c create mode 100644 new_fp.c diff --git a/.gitignore b/.gitignore index d8df4bd..166e408 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,5 @@ draw_svg_tiles draw_svg_tiles.o helper.o model.o -new_floorplan -new_floorplan.o +new_fp +new_fp.o diff --git a/Makefile b/Makefile index 504e0d4..4eb03ef 100644 --- a/Makefile +++ b/Makefile @@ -10,13 +10,13 @@ CFLAGS = -Wall -g LDLIBS = -lxml2 -all: bit2txt draw_svg_tiles new_floorplan xc6slx9.svg xc6slx9.fp +all: bit2txt draw_svg_tiles new_fp xc6slx9.svg xc6slx9.fp xc6slx9.svg: draw_svg_tiles ./draw_svg_tiles | xmllint --pretty 1 - > $@ -xc6slx9.fp: new_floorplan - ./new_floorplan > $@ +xc6slx9.fp: new_fp + ./new_fp > $@ bit2txt: bit2txt.o helper.o @@ -26,16 +26,16 @@ helper.o: helper.c helper.h model.o: model.c model.h -new_floorplan.o: new_floorplan.c model.h +new_fp.o: new_fp.c model.h draw_svg_tiles.o: draw_svg_tiles.c model.h draw_svg_tiles: draw_svg_tiles.o model.o -new_floorplan: new_floorplan.o model.o +new_fp: new_fp.o model.o clean: rm -f bit2txt bit2txt.o \ draw_svg_tiles draw_svg_tiles.o \ - new_floorplan new_floorplan.o \ + new_fp new_fp.o \ helper.o model.o diff --git a/README b/README index b8eebd6..a61246b 100644 --- a/README +++ b/README @@ -9,7 +9,7 @@ Design Principles Utilities -- new_floorplan creates an empty .fp floorplan file +- new_fp creates empty .fp floorplan file - draw_svg_tiles draws a simple .svg showing tile types - fp2bit converts .fp floorplan into .bit bitstream - bit2txt dumps .bit bitstream as text diff --git a/model.c b/model.c index 22b81ff..2f78ef0 100644 --- a/model.c +++ b/model.c @@ -237,7 +237,7 @@ int add_conn_uni(struct fpga_model* model, int y1, int x1, const char* name1, in struct fpga_tile* tile1; uint16_t name1_i, name2_i; uint16_t* new_ptr; - int conn_start, num_conns_for_this_wire, rc, i, j; + int conn_start, num_conn_point_dests_for_this_wire, rc, i, j; tile1 = &model->tiles[y1 * model->tile_x_range + x1]; rc = strarray_find_or_add(&model->str, name1, &name1_i); @@ -246,71 +246,71 @@ int add_conn_uni(struct fpga_model* model, int y1, int x1, const char* name1, in if (!rc) return -1; // Search for a connection set under name1. - for (i = 0; i < tile1->num_conn_names; i++) { - if (tile1->conn_names[i*2+1] == name1_i) + for (i = 0; i < tile1->num_conn_point_names; i++) { + if (tile1->conn_point_names[i*2+1] == name1_i) break; } // If this is the first connection under name1, add name1. - if (i >= tile1->num_conn_names) { - if (!(tile1->num_conn_names % CONN_NAMES_INCREMENT)) { - new_ptr = realloc(tile1->conn_names, (tile1->num_conn_names+CONN_NAMES_INCREMENT)*2*sizeof(uint16_t)); + if (i >= tile1->num_conn_point_names) { + if (!(tile1->num_conn_point_names % CONN_NAMES_INCREMENT)) { + new_ptr = realloc(tile1->conn_point_names, (tile1->num_conn_point_names+CONN_NAMES_INCREMENT)*2*sizeof(uint16_t)); if (!new_ptr) { fprintf(stderr, "Out of memory %s:%i\n", __FILE__, __LINE__); return 0; } - tile1->conn_names = new_ptr; + tile1->conn_point_names = new_ptr; } - tile1->conn_names[tile1->num_conn_names*2] = tile1->num_conns; - tile1->conn_names[tile1->num_conn_names*2+1] = name1_i; - tile1->num_conn_names++; + tile1->conn_point_names[tile1->num_conn_point_names*2] = tile1->num_conn_point_dests; + tile1->conn_point_names[tile1->num_conn_point_names*2+1] = name1_i; + tile1->num_conn_point_names++; } - conn_start = tile1->conn_names[i*2]; - if (i+1 >= tile1->num_conn_names) - num_conns_for_this_wire = tile1->num_conns - conn_start; + conn_start = tile1->conn_point_names[i*2]; + if (i+1 >= tile1->num_conn_point_names) + num_conn_point_dests_for_this_wire = tile1->num_conn_point_dests - conn_start; else - num_conns_for_this_wire = tile1->conn_names[(i+1)*2] - conn_start; + num_conn_point_dests_for_this_wire = tile1->conn_point_names[(i+1)*2] - conn_start; // Is the connection made a second time? - for (j = conn_start; j < conn_start + num_conns_for_this_wire; j++) { - if (tile1->conns[j*3] == x2 - && tile1->conns[j*3+1] == y2 - && tile1->conns[j*3+2] == name2_i) { - fprintf(stderr, "Duplicate conn (num_conns %i): y%02i x%02i %s - y%02i x%02i %s.\n", - num_conns_for_this_wire, y1, x1, name1, y2, x2, name2); - for (j = conn_start; j < conn_start + num_conns_for_this_wire; j++) { + for (j = conn_start; j < conn_start + num_conn_point_dests_for_this_wire; j++) { + if (tile1->conn_point_dests[j*3] == x2 + && tile1->conn_point_dests[j*3+1] == y2 + && tile1->conn_point_dests[j*3+2] == name2_i) { + fprintf(stderr, "Duplicate conn (num_conn_point_dests %i): y%02i x%02i %s - y%02i x%02i %s.\n", + num_conn_point_dests_for_this_wire, y1, x1, name1, y2, x2, name2); + for (j = conn_start; j < conn_start + num_conn_point_dests_for_this_wire; j++) { fprintf(stderr, "c%i: y%02i x%02i %s -> y%02i x%02i %s\n", j, y1, x1, name1, - tile1->conns[j*3+1], tile1->conns[j*3], - strarray_lookup(&model->str, tile1->conns[j*3+2])); + tile1->conn_point_dests[j*3+1], tile1->conn_point_dests[j*3], + strarray_lookup(&model->str, tile1->conn_point_dests[j*3+2])); } return 0; } } - if (!(tile1->num_conns % CONNS_INCREMENT)) { - new_ptr = realloc(tile1->conns, (tile1->num_conns+CONNS_INCREMENT)*3*sizeof(uint16_t)); + if (!(tile1->num_conn_point_dests % CONNS_INCREMENT)) { + new_ptr = realloc(tile1->conn_point_dests, (tile1->num_conn_point_dests+CONNS_INCREMENT)*3*sizeof(uint16_t)); if (!new_ptr) { fprintf(stderr, "Out of memory %s:%i\n", __FILE__, __LINE__); return 0; } - tile1->conns = new_ptr; + tile1->conn_point_dests = new_ptr; } - if (tile1->num_conns > j) - memmove(&tile1->conns[(j+1)*3], &tile1->conns[j*3], (tile1->num_conns-j)*3*sizeof(uint16_t)); - tile1->conns[j*3] = x2; - tile1->conns[j*3+1] = y2; - tile1->conns[j*3+2] = name2_i; - tile1->num_conns++; - while (i+1 < tile1->num_conn_names) { - tile1->conn_names[(i+1)*2]++; + if (tile1->num_conn_point_dests > j) + memmove(&tile1->conn_point_dests[(j+1)*3], &tile1->conn_point_dests[j*3], (tile1->num_conn_point_dests-j)*3*sizeof(uint16_t)); + tile1->conn_point_dests[j*3] = x2; + tile1->conn_point_dests[j*3+1] = y2; + tile1->conn_point_dests[j*3+2] = name2_i; + tile1->num_conn_point_dests++; + while (i+1 < tile1->num_conn_point_names) { + tile1->conn_point_names[(i+1)*2]++; i++; } #if DBG_ADD_CONN_UNI - printf("conns for y%02i x%02i %s now:\n", y1, x1, name1); - for (j = conn_start; j < conn_start + num_conns_for_this_wire+1; j++) { + printf("conn_point_dests for y%02i x%02i %s now:\n", y1, x1, name1); + for (j = conn_start; j < conn_start + num_conn_point_dests_for_this_wire+1; j++) { fprintf(stderr, "c%i: y%02i x%02i %s -> y%02i x%02i %s\n", j, y1, x1, name1, - tile1->conns[j*3+1], tile1->conns[j*3], - strarray_lookup(&model->str, tile1->conns[j*3+2])); + tile1->conn_point_dests[j*3+1], tile1->conn_point_dests[j*3], + strarray_lookup(&model->str, tile1->conn_point_dests[j*3+2])); } #endif return 0; @@ -347,16 +347,16 @@ int add_conn_bi_pref(struct fpga_model* model, int y1, int x1, const char* name1 wpref(model->tiles[y2 * model->tile_x_range + x2].flags, name2)); } -int add_conn_range(struct fpga_model* model, add_conn_bi_f add_conn_f, int y1, int x1, const char* name1, int start1, int count, int y2, int x2, const char* name2, int start2) +int add_conn_range(struct fpga_model* model, add_conn_bi_f add_conn_f, int y1, int x1, const char* name1, int start1, int last1, int y2, int x2, const char* name2, int start2) { char buf1[128], buf2[128]; int rc, i; - if (count < 1) + if (last1 <= start1) return (*add_conn_f)(model, y1, x1, name1, y2, x2, name2); - for (i = 0; i < count; i++) { - snprintf(buf1, sizeof(buf1), name1, start1+i); - snprintf(buf2, sizeof(buf2), name2, start2+i); + for (i = start1; i <= last1; i++) { + snprintf(buf1, sizeof(buf1), name1, i); + snprintf(buf2, sizeof(buf2), name2, start2+(i-start1)); rc = (*add_conn_f)(model, y1, x1, buf1, y2, x2, buf2); if (rc) return rc; } @@ -372,7 +372,11 @@ struct w_point // wire point struct w_net { - int wire_count; // if > 0, %i in the name will be incremented this many times + // if !last_inc, no incrementing will happen + // if last_inc > 0, incrementing will happen to + // the %i in the name from 0:last_inc, for a total + // of last_inc+1 wires. + int last_inc; struct w_point pts[8]; }; @@ -386,7 +390,7 @@ int add_conn_net(struct fpga_model* model, struct w_net* net) net->pts[i].y, net->pts[i].x, net->pts[i].name, net->pts[i].start_count, - net->wire_count, + net->pts[i].start_count + net->last_inc, net->pts[j].y, net->pts[j].x, net->pts[j].name, net->pts[j].start_count); @@ -451,23 +455,37 @@ int run_wires(struct fpga_model* model) } } + if (tile[1].flags & TF_LOGIC_XM_DEVICE) { + if ((rc = add_conn_range(model, NOPREF_BI_F, y, x, "LOGICIN_B%i", 0, 62, y, x+1, "CLEXM_LOGICIN_B%i", 0))) goto xout; + } + if (tile[1].flags & TF_LOGIC_XL_DEVICE) { + if ((rc = add_conn_range(model, NOPREF_BI_F, y, x, "LOGICIN_B%i", 0, 35, y, x+1, "CLEXL_LOGICIN_B%i", 0))) goto xout; + if ((rc = add_conn_range(model, NOPREF_BI_F, y, x, "LOGICIN_B%i", 37, 43, y, x+1, "CLEXL_LOGICIN_B%i", 37))) goto xout; + if ((rc = add_conn_range(model, NOPREF_BI_F, y, x, "LOGICIN_B%i", 45, 52, y, x+1, "CLEXL_LOGICIN_B%i", 45))) goto xout; + if ((rc = add_conn_range(model, NOPREF_BI_F, y, x, "LOGICIN_B%i", 54, 60, y, x+1, "CLEXL_LOGICIN_B%i", 54))) goto xout; + } + if (tile[1].flags & TF_IOLOGIC_DELAY_DEV) { + if ((rc = add_conn_range(model, NOPREF_BI_F, y, x, "LOGICIN_B%i", 0, 3, y, x+1, "IOI_LOGICINB%i", 0))) goto xout; + if ((rc = add_conn_range(model, NOPREF_BI_F, y, x, "LOGICIN_B%i", 5, 9, y, x+1, "IOI_LOGICINB%i", 5))) goto xout; + if ((rc = add_conn_range(model, NOPREF_BI_F, y, x, "LOGICIN_B%i", 11, 62, y, x+1, "IOI_LOGICINB%i", 11))) goto xout; + } if (tile->flags & TF_BRAM_COL) { - if ((rc = add_conn_range(model, NOPREF_BI_F, y, x, "LOGICIN_B%i", 0, 63, y, x+1, "INT_INTERFACE_LOGICBIN%i", 0))) goto xout; + if ((rc = add_conn_range(model, NOPREF_BI_F, y, x, "LOGICIN_B%i", 0, 62, y, x+1, "INT_INTERFACE_LOGICBIN%i", 0))) goto xout; if (tile[2].flags & TF_BRAM_DEVICE) { for (i = 0; i < 4; i++) { sprintf(buf, "BRAM_LOGICINB%%i_INT%i", 3-i); - if ((rc = add_conn_range(model, NOPREF_BI_F, y-(3-i), x, "LOGICIN_B%i", 0, 63, y, x+2, buf, 0))) goto xout; - if ((rc = add_conn_range(model, NOPREF_BI_F, y-(3-i), x+1, "INT_INTERFACE_LOGICBIN%i", 0, 63, y, x+2, buf, 0))) goto xout; + if ((rc = add_conn_range(model, NOPREF_BI_F, y-(3-i), x, "LOGICIN_B%i", 0, 62, y, x+2, buf, 0))) goto xout; + if ((rc = add_conn_range(model, NOPREF_BI_F, y-(3-i), x+1, "INT_INTERFACE_LOGICBIN%i", 0, 62, y, x+2, buf, 0))) goto xout; } } } if (tile->flags & TF_MACC_COL) { - if ((rc = add_conn_range(model, NOPREF_BI_F, y, x, "LOGICIN_B%i", 0, 63, y, x+1, "INT_INTERFACE_LOGICBIN%i", 0))) goto xout; + if ((rc = add_conn_range(model, NOPREF_BI_F, y, x, "LOGICIN_B%i", 0, 62, y, x+1, "INT_INTERFACE_LOGICBIN%i", 0))) goto xout; if (tile[2].flags & TF_MACC_DEVICE) { for (i = 0; i < 4; i++) { sprintf(buf, "MACC_LOGICINB%%i_INT%i", 3-i); - if ((rc = add_conn_range(model, NOPREF_BI_F, y-(3-i), x, "LOGICIN_B%i", 0, 63, y, x+2, buf, 0))) goto xout; - if ((rc = add_conn_range(model, NOPREF_BI_F, y-(3-i), x+1, "INT_INTERFACE_LOGICBIN%i", 0, 63, y, x+2, buf, 0))) goto xout; + if ((rc = add_conn_range(model, NOPREF_BI_F, y-(3-i), x, "LOGICIN_B%i", 0, 62, y, x+2, buf, 0))) goto xout; + if ((rc = add_conn_range(model, NOPREF_BI_F, y-(3-i), x+1, "INT_INTERFACE_LOGICBIN%i", 0, 62, y, x+2, buf, 0))) goto xout; } } } @@ -477,14 +495,14 @@ int run_wires(struct fpga_model* model) if (tile->flags & TF_VERT_ROUTING) { if (tile_up1->flags & TF_BELOW_TOPMOST_TILE) { { struct w_net net = { - 4, + 3, {{ "NR1B%i", 0, y, x }, { "NR1B%i", 0, y-1, x }, { "" }}}; if ((rc = add_conn_net(model, &net))) goto xout; } } else if (tile_up1->flags & (TF_ROW_HORIZ_AXSYMM | TF_CHIP_HORIZ_AXSYMM | TF_CHIP_HORIZ_AXSYMM_CENTER)) { { struct w_net net = { - 4, + 3, {{ "NR1B%i", 0, y, x }, { "NR1E%i", 0, y-1, x }, { "NR1E%i", 0, y-2, x }, @@ -492,14 +510,14 @@ int run_wires(struct fpga_model* model) if ((rc = add_conn_net(model, &net))) goto xout; } } else { { struct w_net net = { - 4, + 3, {{ "NR1B%i", 0, y, x }, { "NR1E%i", 0, y-1, x }, { "" }}}; if ((rc = add_conn_net(model, &net))) goto xout; } if (tile->flags & TF_MACC_COL && tile_dn1->flags & TF_ABOVE_BOTTOMMOST_TILE) { { struct w_net net = { - 4, + 3, {{ "NR1E%i", 0, y, x }, { "NR1E%i", 0, y+1, x }, { "" }}}; @@ -512,20 +530,20 @@ int run_wires(struct fpga_model* model) if (tile->flags & TF_VERT_ROUTING) { if (tile_up1->flags & TF_BELOW_TOPMOST_TILE) { { struct w_net net = { - 4, + 3, {{ "NN2B%i", 0, y, x }, { "NN2B%i", 0, y-1, x }, { "" }}}; if ((rc = add_conn_net(model, &net))) goto xout; } { struct w_net net = { - -1, + 0, {{ "NN2E_S0", 0, y, x }, { "NN2E_S0", 0, y-1, x }, { "" }}}; if ((rc = add_conn_net(model, &net))) goto xout; } } else if (tile_up2->flags & TF_BELOW_TOPMOST_TILE) { { struct w_net net = { - 4, + 3, {{ "NN2B%i", 0, y, x }, { "NN2M%i", 0, y-1, x }, { "NN2M%i", 0, y-2, x }, @@ -533,7 +551,7 @@ int run_wires(struct fpga_model* model) if ((rc = add_conn_net(model, &net))) goto xout; } } else if (tile_up1->flags & (TF_ROW_HORIZ_AXSYMM | TF_CHIP_HORIZ_AXSYMM | TF_CHIP_HORIZ_AXSYMM_CENTER)) { { struct w_net net = { - 4, + 3, {{ "NN2B%i", 0, y, x }, { "NN2M%i", 0, y-1, x }, { "NN2M%i", 0, y-2, x }, @@ -545,7 +563,7 @@ int run_wires(struct fpga_model* model) if ((rc = add_conn_bi(model, y, x, "NN2B0", y-2, x, "NN2E_S0"))) goto xout; } else if (tile_up2->flags & (TF_ROW_HORIZ_AXSYMM | TF_CHIP_HORIZ_AXSYMM | TF_CHIP_HORIZ_AXSYMM_CENTER)) { { struct w_net net = { - 4, + 3, {{ "NN2B%i", 0, y, x }, { "NN2M%i", 0, y-1, x }, { "NN2E%i", 0, y-2, x }, @@ -561,7 +579,7 @@ int run_wires(struct fpga_model* model) if ((rc = add_conn_bi(model, y-3, x, "NN2E0", y-1, x, "NN2E_S0"))) goto xout; } else { { struct w_net net = { - 4, + 3, {{ "NN2B%i", 0, y, x }, { "NN2M%i", 0, y-1, x }, { "NN2E%i", 0, y-2, x }, @@ -583,7 +601,7 @@ int run_wires(struct fpga_model* model) if (tile->flags & TF_VERT_ROUTING) { if (tile_dn2->flags & (TF_ROW_HORIZ_AXSYMM|TF_CHIP_HORIZ_AXSYMM|TF_CHIP_HORIZ_AXSYMM_CENTER)) { { struct w_net net = { - 4, + 3, {{ "SS2B%i", 0, y, x }, { "SS2M%i", 0, y+1, x }, { "SS2M%i", 0, y+2, x }, @@ -602,7 +620,7 @@ int run_wires(struct fpga_model* model) if ((rc = add_conn_bi_pref(model, y+2, x, "SS2B3", y+3, x, "SS2E_N3"))) goto xout; } else if (tile_dn1->flags & (TF_ROW_HORIZ_AXSYMM|TF_CHIP_HORIZ_AXSYMM|TF_CHIP_HORIZ_AXSYMM_CENTER)) { { struct w_net net = { - 4, + 3, {{ "SS2B%i", 0, y, x }, { "SS2B%i", 0, y+1, x }, { "SS2M%i", 0, y+2, x }, @@ -614,7 +632,7 @@ int run_wires(struct fpga_model* model) } else if (tile_dn2->flags & TF_ABOVE_BOTTOMMOST_TILE) { if (!(tile->flags & TF_BRAM_COL)) { { struct w_net net = { - 4, + 3, {{ "SS2B%i", 0, y, x }, { "SS2M%i", 0, y+1, x }, { "SS2M%i", 0, y+2, x }, @@ -623,25 +641,25 @@ int run_wires(struct fpga_model* model) } } else if (tile_dn1->flags & TF_ABOVE_BOTTOMMOST_TILE) { if (!(tile->flags & TF_BRAM_COL)) { - if ((rc = add_conn_range(model, PREF_BI_F, y, x, "SS2B%i", 0, 4, y+1, x, "SS2B%i", 0))) goto xout; + if ((rc = add_conn_range(model, PREF_BI_F, y, x, "SS2B%i", 0, 3, y+1, x, "SS2B%i", 0))) goto xout; if ((rc = add_conn_bi_pref(model, y, x, "SS2E_N3", y+1, x, "SS2E_N3"))) goto xout; } } else { if (tile_up1->flags & TF_BELOW_TOPMOST_TILE) { { struct w_net net = { - 4, + 3, {{ "SS2M%i", 0, y-1, x }, { "SS2M%i", 0, y, x }, { "SS2E%i", 0, y+1, x }, { "" }}}; if ((rc = add_conn_net(model, &net))) goto xout; } - if ((rc = add_conn_range(model, PREF_BI_F, y, x, "SS2E%i", 0, 4, y-1, x, "SS2E%i", 0))) goto xout; + if ((rc = add_conn_range(model, PREF_BI_F, y, x, "SS2E%i", 0, 3, y-1, x, "SS2E%i", 0))) goto xout; if ((rc = add_conn_bi_pref(model, y, x, "SS2E3", y-1, x, "SS2E_N3"))) goto xout; if ((rc = add_conn_bi_pref(model, y, x, "SS2E_N3", y-1, x, "SS2M3"))) goto xout; if ((rc = add_conn_bi_pref(model, y, x, "SS2E_N3", y+1, x, "SS2E3"))) goto xout; } { struct w_net net = { - 4, + 3, {{ "SS2B%i", 0, y, x }, { "SS2M%i", 0, y+1, x }, { "SS2E%i", 0, y+2, x }, @@ -731,10 +749,6 @@ int init_tiles(struct fpga_model* model) for (k = model->cfg_rows-1; k >= 0; k--) { row_top_y = 2 /* top IO tiles */ + (model->cfg_rows-1-k)*(8+1/*middle of row clock*/+8); if (k<(model->cfg_rows/2)) row_top_y++; // middle system tiles (center row) - for (l = 0; l < 16; l++) { - tile_i0 = &model->tiles[(row_top_y+(l<8?l:l+1))*tile_columns + i]; - tile_i0->flags |= (model->cfg_columns[j] == 'L' || model->cfg_columns[j] == 'l') ? TF_LOGIC_XL : TF_LOGIC_XM; - } start = ((k == model->cfg_rows-1 && (model->cfg_columns[j] == 'L' || model->cfg_columns[j] == 'M')) ? 2 : 0); end = ((k == 0 && (model->cfg_columns[j] == 'L' || model->cfg_columns[j] == 'M')) ? 14 : 16); for (l = start; l < end; l++) { @@ -743,8 +757,13 @@ int init_tiles(struct fpga_model* model) tile_i0->type = ROUTING; else tile_i0->type = ROUTING_BRK; - tile_i0[1].type - = (model->cfg_columns[j] == 'L' || model->cfg_columns[j] == 'l') ? LOGIC_XL : LOGIC_XM; + if (model->cfg_columns[j] == 'L' || model->cfg_columns[j] == 'l') { + tile_i0[1].flags |= TF_LOGIC_XL_DEVICE; + tile_i0[1].type = LOGIC_XL; + } else { + tile_i0[1].flags |= TF_LOGIC_XM_DEVICE; + tile_i0[1].type = LOGIC_XM; + } } if (model->cfg_columns[j] == 'L' || model->cfg_columns[j] == 'l') { model->tiles[(row_top_y+8)*tile_columns + i].type = HCLK_ROUTING_XL; @@ -786,9 +805,13 @@ int init_tiles(struct fpga_model* model) } if (model->cfg_columns[j] == 'L' || model->cfg_columns[j] == 'M') { model->tiles[2*tile_columns + i + 1].type = IO_OUTER_T; + model->tiles[2*tile_columns + i + 1].flags |= TF_IOLOGIC_DELAY_DEV; model->tiles[3*tile_columns + i + 1].type = IO_INNER_T; + model->tiles[3*tile_columns + i + 1].flags |= TF_IOLOGIC_DELAY_DEV; model->tiles[(tile_rows-4)*tile_columns + i + 1].type = IO_INNER_B; + model->tiles[(tile_rows-4)*tile_columns + i + 1].flags |= TF_IOLOGIC_DELAY_DEV; model->tiles[(tile_rows-3)*tile_columns + i + 1].type = IO_OUTER_B; + model->tiles[(tile_rows-3)*tile_columns + i + 1].flags |= TF_IOLOGIC_DELAY_DEV;; } if (model->cfg_columns[j] == 'L' || model->cfg_columns[j] == 'l') { @@ -903,8 +926,10 @@ int init_tiles(struct fpga_model* model) tile_i0[1].type = (k%2) ? ROUTING_VIA_CARRY : ROUTING_VIA_IO_DCM; else if (l == 15 && k==model->cfg_rows/2) tile_i0[1].type = ROUTING_VIA_REGC; - else + else { tile_i0[1].type = LOGIC_XL; + tile_i0[1].flags |= TF_LOGIC_XL_DEVICE; + } } if (l == 7 || (l == 8 && !(k%2))) { // even row, together with DCM @@ -950,9 +975,13 @@ int init_tiles(struct fpga_model* model) model->tiles[tile_columns + i + 1].type = IO_LOGIC_REG_TERM_T; model->tiles[(tile_rows-2)*tile_columns + i + 1].type = IO_LOGIC_REG_TERM_B; model->tiles[2*tile_columns + i + 1].type = IO_OUTER_T; + model->tiles[2*tile_columns + i + 1].flags |= TF_IOLOGIC_DELAY_DEV; model->tiles[3*tile_columns + i + 1].type = IO_INNER_T; + model->tiles[3*tile_columns + i + 1].flags |= TF_IOLOGIC_DELAY_DEV; model->tiles[(tile_rows-4)*tile_columns + i + 1].type = IO_INNER_B; + model->tiles[(tile_rows-4)*tile_columns + i + 1].flags |= TF_IOLOGIC_DELAY_DEV; model->tiles[(tile_rows-3)*tile_columns + i + 1].type = IO_OUTER_B; + model->tiles[(tile_rows-3)*tile_columns + i + 1].flags |= TF_IOLOGIC_DELAY_DEV; model->tiles[i + 2].type = REG_T; model->tiles[tile_columns + i + 2].type = REG_TERM_T; diff --git a/model.h b/model.h index 2cc2e5d..7e9e83f 100644 --- a/model.h +++ b/model.h @@ -141,6 +141,11 @@ enum fpga_tile_type #define TF_BRAM_COL 0x00010000 #define TF_BRAM_DEVICE 0x00020000 #define TF_MACC_DEVICE 0x00040000 +#define TF_LOGIC_XL_DEVICE 0x00080000 +#define TF_LOGIC_XM_DEVICE 0x00100000 +#define TF_IOLOGIC_DELAY_DEV 0x00200000 + +#define SWITCH_BIDIRECTIONAL 0x40000000 struct fpga_tile { @@ -151,28 +156,28 @@ struct fpga_tile int num_devices; struct fpga_device* devices; - // expect up to 5k connection names per tile + // expect up to 5k connection point names per tile // 2*16 bit per entry - // - index into conns (not multiplied by 3) (16bit) + // - index into conn_point_dests (not multiplied by 3) (16bit) // - hashed string array index (16 bit) - int num_conn_names; // conn_names is 2*num_conn_names 16-bit words - uint16_t* conn_names; // num_conn_names*2 16-bit-words: 16(conn)-16(str) + int num_conn_point_names; // conn_point_names is 2*num_conn_point_names 16-bit words + uint16_t* conn_point_names; // num_conn_point_names*2 16-bit-words: 16(conn)-16(str) - // expect up to 28k connections to other tiles per tile - // 3*16 bit per connection: + // expect up to 28k connection point destinations to other tiles per tile + // 3*16 bit per destination: // - x coordinate of other tile (16bit) // - y coordinate of other tile (16bit) - // - hashed string array index for conn_names name in other tile (16bit) - int num_conns; // conns array is 3*num_conns 16-bit words - uint16_t* conns; // num_conns*3 16-bit words: 16(x)-16(y)-16(conn_name) + // - hashed string array index for conn_point_names name in other tile (16bit) + int num_conn_point_dests; // conn_point_dests array is 3*num_conn_point_dests 16-bit words + uint16_t* conn_point_dests; // num_conn_point_dests*3 16-bit words: 16(x)-16(y)-16(conn_name) - // expect up to 4k connection pairs per tile - // 32bit: 31 off: not in use on: used + // expect up to 4k switches per tile + // 32bit: 31 off: no connection on: connected // 30 off: unidirectional on: bidirectional - // 29:15 from, index into conn_names - // 14:0 to, index into conn_names - int num_connect_pairs; - uint32_t* connect_pairs; + // 29:15 from, index into conn_point_names + // 14:0 to, index into conn_point_names + int num_switches; + uint32_t* switches; }; int fpga_build_model(struct fpga_model* model, diff --git a/new_floorplan.c b/new_floorplan.c deleted file mode 100644 index 0cf052f..0000000 --- a/new_floorplan.c +++ /dev/null @@ -1,106 +0,0 @@ -// -// Author: Wolfgang Spraul -// -// This is free and unencumbered software released into the public domain. -// For details see the UNLICENSE file at the root of the source tree. -// - -#include -#include -#include -#include -#include -#include - -#include "model.h" - -int main(int argc, char** argv) -{ - struct fpga_model model; - struct fpga_tile* tile; - int x, y; - - if (fpga_build_model(&model, XC6SLX9_ROWS, XC6SLX9_COLUMNS, - XC6SLX9_LEFT_WIRING, XC6SLX9_RIGHT_WIRING)) - goto fail; - - printf("fpga_floorplan_format 1\n"); - - // - // What needs to be in the file: - // - all devices, configuration for each device - // probably multiple lines that are adding config strings - // - wires maybe separately, and/or as named connection points - // in tiles? - // - connection pairs that can be enabled/disabled - // - global flags and configuration registers - // - the static data should be optional (unused conn pairs, - // unused devices, wires) - // - // - each line should be in the global namespace, line order - // should not matter - // - file should be easily parsable with bison - // - lines should typically not exceed 80 characters - // - - for (x = 0; x < model.tile_x_range; x++) { - printf("\n"); - for (y = 0; y < model.tile_y_range; y++) { - tile = &model.tiles[y*model.tile_x_range + x]; - - printf("tile y%02i x%02i", y, x); - - if (tile->type == NA && !(tile->flags)) { - printf(" -\n"); - continue; - } - if (tile->type != NA) - printf(" name %s", fpga_tiletype_str(tile->type)); - if (tile->flags) { - int tf = tile->flags; - printf(" flags"); - if (tf & TF_TOPMOST_TILE) { - printf(" %s", MACRO_STR(TF_TOPMOST_TILE)); - tf &= ~TF_TOPMOST_TILE; - } - if (tf & TF_ABOVE_BOTTOMMOST_TILE) { - printf(" %s", MACRO_STR(TF_ABOVE_BOTTOMMOST_TILE)); - tf &= ~TF_ABOVE_BOTTOMMOST_TILE; - } - if (tf & TF_BOTTOMMOST_TILE) { - printf(" %s", MACRO_STR(TF_BOTTOMMOST_TILE)); - tf &= ~TF_BOTTOMMOST_TILE; - } - if (tf & TF_ROW_HORIZ_AXSYMM) { - printf(" %s", MACRO_STR(TF_ROW_HORIZ_AXSYMM)); - tf &= ~TF_ROW_HORIZ_AXSYMM; - } - if (tf & TF_BOTTOM_OF_ROW) { - printf(" %s", MACRO_STR(TF_BOTTOM_OF_ROW)); - tf &= ~TF_BOTTOM_OF_ROW; - } - if (tf & TF_CHIP_HORIZ_AXSYMM) { - printf(" %s", MACRO_STR(TF_CHIP_HORIZ_AXSYMM)); - tf &= ~TF_CHIP_HORIZ_AXSYMM; - } - if (tf & TF_CHIP_VERT_AXSYMM) { - printf(" %s", MACRO_STR(TF_CHIP_VERT_AXSYMM)); - tf &= ~TF_CHIP_VERT_AXSYMM; - } - if (tf & TF_VERT_ROUTING) { - printf(" %s", MACRO_STR(TF_VERT_ROUTING)); - tf &= ~TF_VERT_ROUTING; - } - if (tf) - printf(" 0x%x", tf); - } - printf("\n"); - } - } - // todo: static_conn y%02i-x%02i-name y%02i-x%02i-name - // todo: static_net - return EXIT_SUCCESS; - -fail: - return EXIT_FAILURE; -} diff --git a/new_fp.c b/new_fp.c new file mode 100644 index 0000000..b3b4b1e --- /dev/null +++ b/new_fp.c @@ -0,0 +1,405 @@ +// +// Author: Wolfgang Spraul +// +// This is free and unencumbered software released into the public domain. +// For details see the UNLICENSE file at the root of the source tree. +// + +#include +#include +#include +#include +#include +#include + +#include "model.h" + +#define PRINT_FLAG(f) if (tf & f) { printf (" %s", #f); tf &= ~f; } + +int printf_tiles(struct fpga_model* model); +int printf_static_conns(struct fpga_model* model); + +int main(int argc, char** argv) +{ + struct fpga_model model; + int rc; + + if ((rc = fpga_build_model(&model, XC6SLX9_ROWS, XC6SLX9_COLUMNS, + XC6SLX9_LEFT_WIRING, XC6SLX9_RIGHT_WIRING))) + goto fail; + + printf("fpga_floorplan_format 1\n"); + + // + // What needs to be in the file: + // - all devices, configuration for each device + // probably multiple lines that are adding config strings + // - wires maybe separately, and/or as named connection points + // in tiles? + // - connection pairs that can be enabled/disabled + // - global flags and configuration registers + // - the static data should be optional (unused conn pairs, + // unused devices, wires) + // + // - each line should be in the global namespace, line order + // should not matter + // - file should be easily parsable with bison + // - lines should typically not exceed 80 characters + // + + rc = printf_tiles(&model); + if (rc) goto fail; + + rc = printf_static_conns(&model); + if (rc) goto fail; + + // todo: static_net + return EXIT_SUCCESS; + +fail: + return rc; +} + +int printf_tiles(struct fpga_model* model) +{ + struct fpga_tile* tile; + int x, y; + + for (x = 0; x < model->tile_x_range; x++) { + printf("\n"); + for (y = 0; y < model->tile_y_range; y++) { + tile = &model->tiles[y*model->tile_x_range + x]; + + printf("tile y%02i x%02i", y, x); + + if (tile->type == NA && !(tile->flags)) { + printf(" -\n"); + continue; + } + if (tile->type != NA) + printf(" name %s", fpga_tiletype_str(tile->type)); + if (tile->flags) { + int tf = tile->flags; + printf(" flags"); + + PRINT_FLAG(TF_TOPMOST_TILE); + PRINT_FLAG(TF_BELOW_TOPMOST_TILE); + PRINT_FLAG(TF_ABOVE_BOTTOMMOST_TILE); + PRINT_FLAG(TF_BOTTOMMOST_TILE); + PRINT_FLAG(TF_ROW_HORIZ_AXSYMM); + PRINT_FLAG(TF_BOTTOM_OF_ROW); + PRINT_FLAG(TF_CHIP_HORIZ_AXSYMM); + PRINT_FLAG(TF_CHIP_HORIZ_AXSYMM_CENTER); + PRINT_FLAG(TF_CHIP_VERT_AXSYMM); + PRINT_FLAG(TF_VERT_ROUTING); + PRINT_FLAG(TF_LOGIC_XL); + PRINT_FLAG(TF_LOGIC_XM); + PRINT_FLAG(TF_CENTER); + PRINT_FLAG(TF_LEFT_IO); + PRINT_FLAG(TF_RIGHT_IO); + PRINT_FLAG(TF_MACC_COL); + PRINT_FLAG(TF_BRAM_COL); + PRINT_FLAG(TF_BRAM_DEVICE); + PRINT_FLAG(TF_MACC_DEVICE); + PRINT_FLAG(TF_LOGIC_XL_DEVICE); + PRINT_FLAG(TF_LOGIC_XM_DEVICE); + PRINT_FLAG(TF_IOLOGIC_DELAY_DEV); + + if (tf) + printf(" 0x%x", tf); + } + printf("\n"); + } + } + return 0; +} + +struct conn_printf_data +{ + int src_x, src_y; // src_x is -1 for empty entry + char src_conn_point[41]; + int num_combined_wires; // 0 for no suffix, otherwise 4 for 0:3 etc. + int dest_x, dest_y; + char dest_conn_point[41]; +}; + +#define MAX_CONN_PRINTF_ENTRIES 40000 +static struct conn_printf_data s_conn_printf_buf[MAX_CONN_PRINTF_ENTRIES]; +static int s_conn_printf_entries; + +int sort_by_tile(const void* a, const void* b) +{ + int i, j, non_numeric_result, a_num, b_num; + + struct conn_printf_data* _a = (struct conn_printf_data*) a; + struct conn_printf_data* _b = (struct conn_printf_data*) b; + + if (_a->src_x < 0 && _b->src_x < 0) return 0; + if (_a->src_x < 0) return -1; + if (_b->src_x < 0) return 1; + + if (_a->src_x != _b->src_x) + return _a->src_x - _b->src_x; + if (_a->src_y != _b->src_y) + return _a->src_y - _b->src_y; + if (_a->dest_x != _b->dest_x) + return _a->dest_x - _b->dest_x; + if (_a->dest_y != _b->dest_y) + return _a->dest_y - _b->dest_y; + if (_a->num_combined_wires != _b->num_combined_wires) + return _a->num_combined_wires - _b->num_combined_wires; + for (i = 0; _a->src_conn_point[i]; i++) { + if (_b->src_conn_point[i] != _a->src_conn_point[i]) { + non_numeric_result = _a->src_conn_point[i] - _b->src_conn_point[i]; + + if (_a->src_conn_point[i] < '0' || _a->src_conn_point[i] > '9' + || _b->src_conn_point[i] < '0' || _b->src_conn_point[i] > '9') + return non_numeric_result; + + // go back to beginning of numeric section + while (i && _a->src_conn_point[i-1] >= '0' && _a->src_conn_point[i-1] <= '9') + i--; + if (!i) { + fprintf(stderr, "Error in line %i, a %s b %s\n", __LINE__, _a->src_conn_point, _b->src_conn_point); + return non_numeric_result; + } + + // Are there only digits following in a? + for (j = i; _a->src_conn_point[j]; j++) { + if (_a->src_conn_point[j] < '0' + || _a->src_conn_point[j] > '9') + break; + } + if (_a->src_conn_point[j]) + return non_numeric_result; + + // Are there only digits following in b? + for (j = i; _b->src_conn_point[j]; j++) { + if (_b->src_conn_point[j] < '0' + || _b->src_conn_point[j] > '9') + break; + } + if (_b->src_conn_point[j]) + return non_numeric_result; + + a_num = strtol(&_a->src_conn_point[i], 0 /* endptr */, 10); + b_num = strtol(&_b->src_conn_point[i], 0 /* endptr */, 10); + return a_num - b_num; + } + } + // following is a special version of strcmp(_a->dest_conn_point, _b->dest_conn_point) + // to push '_' before digits. + for (i = 0; _a->dest_conn_point[i]; i++) { + if (_a->dest_conn_point[i] != _b->dest_conn_point[i]) { + // The point here is to get a NN2B0 -> NN2E_S0 before + // a NN2B0 -> NN2E0 so that later wire combinations + // are easier. + if (_a->dest_conn_point[i] >= '0' && _a->dest_conn_point[i] <= '9' + && _b->dest_conn_point[i] == '_') + return 1; + if (_b->dest_conn_point[i] >= '0' && _b->dest_conn_point[i] <= '9' + && _a->dest_conn_point[i] == '_') + return -1; + return _a->dest_conn_point[i] - _b->dest_conn_point[i]; + } + } + return 0; +} + +int find_last_wire_digit(const char* wire_str, int* start_o, int* end_o, int* num) +{ + // There are some known suffixes that may confuse our + // 'last digit' logic so we skip those. + static const char suffix[8][16] = + { "_S0", "_N3", "_INT0", "_INT1", "_INT2", "_INT3", "" }; + int i, suffix_len, right_bound, _end_o, base; + + right_bound = strlen(wire_str); + for (i = 0; suffix[i][0]; i++) { + suffix_len = strlen(suffix[i]); + if (right_bound > suffix_len + && !strcmp(&wire_str[right_bound - suffix_len], + suffix[i])) { + right_bound -= suffix_len; + break; + } + } + _end_o = -1; + for (i = right_bound; i; i--) { + if (wire_str[i-1] >= '0' && wire_str[i-1] <= '9' && _end_o == -1) { + _end_o = i; + continue; + } + if ((wire_str[i-1] < '0' || wire_str[i-1] > '9') && _end_o != -1) { + *start_o = i; + *end_o = _end_o; + *num = 0; + base = 1; + for (i = *end_o - 1; i >= *start_o; i--) { + *num += (wire_str[i] - '0')*base; + base *= 10; + } + return 1; + } + } + return 0; +} + +void sort_and_reduce_printf_buf() +{ + int src_digit_start_o, src_digit_end_o, src_digit; + int dest_digit_start_o, dest_digit_end_o, dest_digit; + int second_src_digit_start_o, second_src_digit_end_o, second_src_digit; + int second_dest_digit_start_o, second_dest_digit_end_o, second_dest_digit; + int i, j, sequence_size; + int sequence[100]; // support up to 100 elements in sequence + char old_suffix[41]; + + if (s_conn_printf_entries < 2) + return; + + // First sort by y/x src, then y/x dest, then src conn point, then + // dest conn points - all in preparation of the numbered wires reduction. + qsort(s_conn_printf_buf, s_conn_printf_entries, + sizeof(s_conn_printf_buf[0]), sort_by_tile); + + // Reduce numbered wire sets. + for (i = 0; i < s_conn_printf_entries-1; i++) { + if (s_conn_printf_buf[i].src_x < 0) + continue; + if (!find_last_wire_digit(s_conn_printf_buf[i].src_conn_point, &src_digit_start_o, &src_digit_end_o, &src_digit) + || !find_last_wire_digit(s_conn_printf_buf[i].dest_conn_point, &dest_digit_start_o, &dest_digit_end_o, &dest_digit)) + continue; + + // Search for a contiguous sequence of increasing numbers, but support + // skipping over unrelated pairs that may be inside our sequence due + // to sorting. + sequence[0] = i; + sequence_size = 1; + for (j = i+1; j < s_conn_printf_entries; j++) { + if (j > sequence[sequence_size-1]+4) // search over at most 4 non-matches + break; + if (s_conn_printf_buf[j].src_x < 0) + continue; + // is the j connection from and to the same tiles as the i connection? + if (s_conn_printf_buf[i].src_x != s_conn_printf_buf[j].src_x + || s_conn_printf_buf[i].src_y != s_conn_printf_buf[j].src_y + || s_conn_printf_buf[i].dest_x != s_conn_printf_buf[j].dest_x + || s_conn_printf_buf[i].dest_y != s_conn_printf_buf[j].dest_y) + continue; + if (!find_last_wire_digit(s_conn_printf_buf[j].src_conn_point, &second_src_digit_start_o, &second_src_digit_end_o, &second_src_digit)) + continue; + if (!find_last_wire_digit(s_conn_printf_buf[j].dest_conn_point, &second_dest_digit_start_o, &second_dest_digit_end_o, &second_dest_digit)) + continue; + if (second_src_digit != src_digit+sequence_size + || second_dest_digit != dest_digit+sequence_size) + continue; + if (src_digit_start_o != second_src_digit_start_o + || strncmp(s_conn_printf_buf[i].src_conn_point, s_conn_printf_buf[j].src_conn_point, src_digit_start_o)) + continue; + if (strcmp(&s_conn_printf_buf[i].src_conn_point[src_digit_end_o], &s_conn_printf_buf[j].src_conn_point[second_src_digit_end_o])) + continue; + if (dest_digit_start_o != second_dest_digit_start_o + || strncmp(s_conn_printf_buf[i].dest_conn_point, s_conn_printf_buf[j].dest_conn_point, dest_digit_start_o)) + continue; + if (strcmp(&s_conn_printf_buf[i].dest_conn_point[dest_digit_end_o], &s_conn_printf_buf[j].dest_conn_point[second_dest_digit_end_o])) + continue; + if (sequence_size >= sizeof(sequence)/sizeof(sequence[0])) { + fprintf(stderr, "Internal error - too long sequence in line %i\n", __LINE__); + break; + } + sequence[sequence_size++] = j; + } + if (sequence_size < 2) + continue; + strcpy(old_suffix, &s_conn_printf_buf[sequence[0]].src_conn_point[src_digit_end_o]); + sprintf(&s_conn_printf_buf[sequence[0]].src_conn_point[src_digit_start_o], "%i:%i%s", src_digit, src_digit+sequence_size-1, old_suffix); + strcpy(old_suffix, &s_conn_printf_buf[sequence[0]].dest_conn_point[dest_digit_end_o]); + sprintf(&s_conn_printf_buf[sequence[0]].dest_conn_point[dest_digit_start_o], "%i:%i%s", dest_digit, dest_digit+sequence_size-1, old_suffix); + s_conn_printf_buf[sequence[0]].num_combined_wires = sequence_size; + for (i = 1; i < sequence_size; i++) + s_conn_printf_buf[sequence[i]].src_x = -1; + i = sequence[0]; + } + + // Second round of sorting, this time the largest numbered wire + // sets are defined and will move up. + qsort(s_conn_printf_buf, s_conn_printf_entries, sizeof(s_conn_printf_buf[0]), + sort_by_tile); +} + +int printf_static_conns(struct fpga_model* model) +{ + struct fpga_tile* tile; + char tmp_line[512]; + const char* conn_point_name_src, *other_tile_connpt_str; + uint16_t other_tile_connpt_str_i; + int x, y, i, j, conn_point_dests_o, num_dests_for_this_conn_point; + int other_tile_x, other_tile_y, first_conn_printed; + + for (x = 0; x < model->tile_x_range; x++) { + for (y = 0; y < model->tile_y_range; y++) { + tile = &model->tiles[y*model->tile_x_range + x]; + + s_conn_printf_entries = 0; + for (i = 0; i < tile->num_conn_point_names; i++) { + conn_point_dests_o = tile->conn_point_names[i*2]; + if (i < tile->num_conn_point_names-1) + num_dests_for_this_conn_point = tile->conn_point_names[(i+1)*2] - conn_point_dests_o; + else + num_dests_for_this_conn_point = tile->num_conn_point_dests - conn_point_dests_o; + if (!num_dests_for_this_conn_point) + continue; + conn_point_name_src = strarray_lookup(&model->str, tile->conn_point_names[i*2+1]); + if (!conn_point_name_src) { + fprintf(stderr, "Cannot lookup src conn point name index %i, x%i y%i i%i\n", + tile->conn_point_names[i*2+1], x, y, i); + continue; + } + for (j = 0; j < num_dests_for_this_conn_point; j++) { + other_tile_x = tile->conn_point_dests[(conn_point_dests_o+j)*3]; + other_tile_y = tile->conn_point_dests[(conn_point_dests_o+j)*3+1]; + other_tile_connpt_str_i = tile->conn_point_dests[(conn_point_dests_o+j)*3+2]; + + other_tile_connpt_str = strarray_lookup(&model->str, other_tile_connpt_str_i); + if (!other_tile_connpt_str) { + fprintf(stderr, "Lookup err line %i, dest pt %i, dest x%i y%i, from x%i y%i j%i num_dests %i src_pt %s\n", + __LINE__, other_tile_connpt_str_i, other_tile_x, other_tile_y, x, y, j, num_dests_for_this_conn_point, conn_point_name_src); + continue; + } + s_conn_printf_buf[s_conn_printf_entries].src_y = y; + s_conn_printf_buf[s_conn_printf_entries].src_x = x; + strcpy(s_conn_printf_buf[s_conn_printf_entries].src_conn_point, conn_point_name_src); + s_conn_printf_buf[s_conn_printf_entries].num_combined_wires = 0; + s_conn_printf_buf[s_conn_printf_entries].dest_y = other_tile_y; + s_conn_printf_buf[s_conn_printf_entries].dest_x = other_tile_x; + strcpy(s_conn_printf_buf[s_conn_printf_entries].dest_conn_point, other_tile_connpt_str); + s_conn_printf_entries++; + } + } + sort_and_reduce_printf_buf(); + first_conn_printed = 0; + for (i = 0; i < s_conn_printf_entries; i++) { + if (s_conn_printf_buf[i].src_x < 0) + continue; + if (!first_conn_printed) { + printf("\n"); + first_conn_printed = 1; + } + sprintf(tmp_line, "static_conn y%02i-x%02i-%s ", + s_conn_printf_buf[i].src_y, + s_conn_printf_buf[i].src_x, + s_conn_printf_buf[i].src_conn_point); + j = strlen(tmp_line); + while (j < 45) + tmp_line[j++] = ' '; + sprintf(&tmp_line[j], "y%02i-x%02i-%s\n", + s_conn_printf_buf[i].dest_y, + s_conn_printf_buf[i].dest_x, + s_conn_printf_buf[i].dest_conn_point); + printf(tmp_line); + } + } + } + return 0; +}