cleanup, wires, new_fp prints static connections
This commit is contained in:
parent
9ecc9d7475
commit
ae2438cca0
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -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
|
||||
|
|
12
Makefile
12
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
|
||||
|
|
2
README
2
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
|
||||
|
|
179
model.c
179
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;
|
||||
|
|
35
model.h
35
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,
|
||||
|
|
106
new_floorplan.c
106
new_floorplan.c
|
@ -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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#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 <lists all wires connected together statically in a long line>
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
fail:
|
||||
return EXIT_FAILURE;
|
||||
}
|
405
new_fp.c
Normal file
405
new_fp.c
Normal file
|
@ -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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#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 <lists all wires connected together statically in a long line>
|
||||
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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user