From d36a3fa6a338a4b55814212cb36544fc3ec0adfc Mon Sep 17 00:00:00 2001 From: Wolfgang Spraul Date: Fri, 17 Aug 2012 07:01:00 +0200 Subject: [PATCH] autotester, iob pinwire fixes --- autotest.c | 99 ++++++++++++++++++++++++++++++++++--------- autotest_diff.sh | 3 +- control.c | 63 ++++++++++++++++----------- control.h | 14 +++++- helper.h | 2 + model.h | 14 ++++++ model_devices.c | 108 +++++++++++++++++++++++++++++++++++++++++++---- model_ports.c | 53 ----------------------- 8 files changed, 249 insertions(+), 107 deletions(-) diff --git a/autotest.c b/autotest.c index ce975e3..52d1cb3 100644 --- a/autotest.c +++ b/autotest.c @@ -19,6 +19,15 @@ time_t g_start_time; #define AUTOTEST_TMP_DIR "autotest.tmp" +struct test_state +{ + struct fpga_model* model; + // test filenames are: tmp_dir/autotest__.??? + char tmp_dir[256]; + char base_name[256]; + int next_diff_counter; +}; + static int dump_file(const char* path) { char line[1024]; @@ -39,12 +48,65 @@ static int dump_file(const char* path) return 0; } +static int diff_start(struct test_state* tstate, const char* base_name) +{ + strcpy(tstate->base_name, base_name); + tstate->next_diff_counter = 1; + return 0; +} + +static int diff_printf(struct test_state* tstate) +{ + char path[1024], tmp[1024], prior_fp[1024]; + int path_base; + FILE* dest_f = 0; + int rc; + + snprintf(path, sizeof(path), "%s/autotest_%s_%04i", tstate->tmp_dir, + tstate->base_name, tstate->next_diff_counter); + path_base = strlen(path); + if (tstate->next_diff_counter == 1) + strcpy(prior_fp, "/dev/null"); + else { + snprintf(prior_fp, sizeof(prior_fp), "%s/autotest_%s_%04i.fp", + tstate->tmp_dir, tstate->base_name, + tstate->next_diff_counter-1); + } + + strcpy(&path[path_base], ".fp"); + dest_f = fopen(path, "w"); + if (!dest_f) { rc = -1; FAIL(); } + + rc = printf_devices(dest_f, tstate->model, /*config_only*/ 1); + if (rc) FAIL(); + rc = printf_switches(dest_f, tstate->model, /*enabled_only*/ 1); + if (rc) FAIL(); + + fclose(dest_f); + dest_f = 0; + path[path_base] = 0; + snprintf(tmp, sizeof(tmp), "./autotest_diff.sh %s %s.fp >%s.log 2>&1", + prior_fp, path, path); + rc = system(tmp); + if (rc) FAIL(); + + strcpy(&path[path_base], ".diff"); + rc = dump_file(path); + if (rc) FAIL(); + + tstate->next_diff_counter++; + return 0; +fail: + if (dest_f) fclose(dest_f); + return rc; +} + int main(int argc, char** argv) { struct fpga_model model; - FILE* dest_f; struct fpga_device* dev; int iob_y, iob_x, iob_idx, rc; + struct test_state tstate; printf("\n"); printf("O fpgatools automatic test suite. Be welcome and be " @@ -63,11 +125,17 @@ int main(int argc, char** argv) printf("O Done\n"); TIME_AND_MEM(); + tstate.model = &model; + strcpy(tstate.tmp_dir, AUTOTEST_TMP_DIR); + mkdir(tstate.tmp_dir, S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH); + rc = diff_start(&tstate, "and"); + if (rc) FAIL(); + // configure P46 rc = fpga_find_iob(&model, "P46", &iob_y, &iob_x, &iob_idx); - EXIT(rc); + if (rc) FAIL(); dev = fpga_dev(&model, iob_y, iob_x, DEV_IOB, iob_idx); - EXIT(!dev); + if (!dev) { rc = -1; FAIL(); } dev->instantiated = 1; strcpy(dev->iob.istandard, IO_LVCMOS33); dev->iob.bypass_mux = BYPASS_MUX_I; @@ -75,9 +143,9 @@ int main(int argc, char** argv) // configure P48 rc = fpga_find_iob(&model, "P48", &iob_y, &iob_x, &iob_idx); - EXIT(rc); + if (rc) FAIL(); dev = fpga_dev(&model, iob_y, iob_x, DEV_IOB, iob_idx); - EXIT(!dev); + if (!dev) { rc = -1; FAIL(); } dev->instantiated = 1; strcpy(dev->iob.ostandard, IO_LVCMOS33); dev->iob.drive_strength = 12; @@ -85,26 +153,19 @@ int main(int argc, char** argv) dev->iob.slew = SLEW_SLOW; dev->iob.suspend = SUSP_3STATE; + rc = diff_printf(&tstate); + if (rc) goto fail; + // configure logic dev = fpga_dev(&model, /*y*/ 68, /*x*/ 13, DEV_LOGIC, /*LOGIC_X*/ 1); - EXIT(!dev); + if (!dev) { rc = -1; FAIL(); } dev->instantiated = 1; dev->logic.D_used = 1; rc = fpga_set_lut(&model, dev, D6_LUT, "A3", ZTERM); - EXIT(rc); + if (rc) FAIL(); - mkdir(AUTOTEST_TMP_DIR, S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH); - dest_f = fopen(AUTOTEST_TMP_DIR "/test_0001.fp", "w"); - EXIT(!dest_f); - rc = printf_devices(dest_f, &model, /*config_only*/ 1); - EXIT(rc); - rc = printf_switches(dest_f, &model, /*enabled_only*/ 1); - EXIT(rc); - fclose(dest_f); - rc = system("./autotest_diff.sh autotest.tmp/test_0001.fp"); - EXIT(rc); - rc = dump_file(AUTOTEST_TMP_DIR "/test_0001.diff"); - EXIT(rc); + rc = diff_printf(&tstate); + if (rc) goto fail; // todo: start routing, step by step // todo: after each step, printf floorplan diff (test_diff.sh) diff --git a/autotest_diff.sh b/autotest_diff.sh index b90056f..b97fada 100755 --- a/autotest_diff.sh +++ b/autotest_diff.sh @@ -1,2 +1,3 @@ #!/bin/bash -diff -u /dev/null $1 > autotest.tmp/test_0001.diff || true +diff -U 0 $1 $2 > ${2%.*}.fp_diff || true +cat ${2%.*}.fp_diff | sed -e '/^--- /d;/^+++ /d;/^@@ /d' > ${2%.*}.diff diff --git a/control.c b/control.c index 1c5b7d9..f375e45 100644 --- a/control.c +++ b/control.c @@ -16,32 +16,32 @@ struct iob_site static const struct iob_site xc6slx9_iob_top[] = { - { 5, {"P144", "P143", "P142", "P141"}}, - { 7, {"P140", "P139", "P138", "P137"}}, - {12, {"UNB9", "UNB10", "UNB11", "UNB12"}}, - {14, {"UNB13", "UNB14", "UNB15", "UNB16"}}, - {19, {"UNB17", "UNB18", "UNB19", "UNB20"}}, - {21, {"P134", "P133", "P132", "P131"}}, - {25, {"P127", "P126", "P124", "P123"}}, - {29, {"UNB29", "UNB30", "UNB31", "UNB32"}}, - {31, {"UNB33", "UNB34", "P121", "P120"}}, - {36, {"P119", "P118", "P117", "P116"}}, - {38, {"P115", "P114", "P112", "P111"}}, + { 5, {"P144", "P143", "P141", "P142"}}, + { 7, {"P140", "P139", "P137", "P138"}}, + {12, {"UNB9", "UNB10", "UNB12", "UNB11"}}, + {14, {"UNB13", "UNB14", "UNB16", "UNB15"}}, + {19, {"UNB17", "UNB18", "UNB20", "UNB19"}}, + {21, {"P134", "P133", "P131", "P132"}}, + {25, {"P127", "P126", "P123", "P124"}}, + {29, {"UNB29", "UNB30", "UNB32", "UNB31"}}, + {31, {"UNB33", "UNB34", "P120", "P121"}}, + {36, {"P119", "P118", "P116", "P117"}}, + {38, {"P115", "P114", "P111", "P112"}}, }; static const struct iob_site xc6slx9_iob_bottom[] = { - { 5, {"P38", "P39", "P40", "P41"}}, - { 7, {"UNB140", "UNB139", "P43", "P44"}}, - {12, {"P45", "P46", "P47", "P48"}}, - {14, {"UNB132", "UNB131", "UNB130", "UNB129"}}, - {19, {"UNB128", "UNB127", "UNB126", "UNB125"}}, - {21, {"UNB124", "UNB123", "P50", "P51"}}, - {25, {"P55", "P56", "UNB118", "UNB117"}}, - {29, {"UNB116", "UNB115", "UNB114", "UNB113"}}, - {31, {"P57", "P58", "P59", "P60"}}, - {36, {"P61", "P62", "P64", "P65"}}, - {38, {"P66", "P67", "P69", "P70"}}, + { 5, {"P38", "P39", "P41", "P40"}}, + { 7, {"UNB140", "UNB139", "P44", "P43"}}, + {12, {"P45", "P46", "P48", "P47"}}, + {14, {"UNB132", "UNB131", "UNB129", "UNB130"}}, + {19, {"UNB128", "UNB127", "UNB125", "UNB126"}}, + {21, {"UNB124", "UNB123", "P51", "P50"}}, + {25, {"P55", "P56", "UNB117", "UNB118"}}, + {29, {"UNB116", "UNB115", "UNB113", "UNB114"}}, + {31, {"P57", "P58", "P60", "P59"}}, + {36, {"P61", "P62", "P65", "P64"}}, + {38, {"P66", "P67", "P70", "P69"}}, }; static const struct iob_site xc6slx9_iob_left[] = @@ -201,7 +201,7 @@ const char* fpga_iob_sitename(struct fpga_model* model, int y, int x, } struct fpga_device* fpga_dev(struct fpga_model* model, - int y, int x, enum fpgadev_type type, int idx) + int y, int x, enum fpgadev_type type, int type_idx) { struct fpga_tile* tile; int type_count, i; @@ -210,7 +210,7 @@ struct fpga_device* fpga_dev(struct fpga_model* model, type_count = 0; for (i = 0; i < tile->num_devs; i++) { if (tile->devs[i].type == type) { - if (type_count == idx) + if (type_count == type_idx) return &tile->devs[i]; type_count++; } @@ -218,6 +218,21 @@ struct fpga_device* fpga_dev(struct fpga_model* model, return 0; } +int fpga_dev_typecount(struct fpga_model* model, int y, int x, + enum fpgadev_type type, int dev_idx) +{ + struct fpga_tile* tile; + int type_count, i; + + tile = YX_TILE(model, y, x); + type_count = 0; + for (i = 0; i < dev_idx; i++) { + if (tile->devs[i].type == type) + type_count++; + } + return type_count; +} + #define MAX_LUT_LEN 512 int fpga_set_lut(struct fpga_model* model, struct fpga_device* dev, diff --git a/control.h b/control.h index fa3f22c..46b3745 100644 --- a/control.h +++ b/control.h @@ -11,8 +11,20 @@ int fpga_find_iob(struct fpga_model* model, const char* sitename, const char* fpga_iob_sitename(struct fpga_model* model, int y, int x, int idx); +// +// When dealing with devices, there are two indices: +// 1. The index of the device in the device array for that tile. +// 2. The index of the device within devices of the same type in the tile. +// + +// Looks up a device pointer based on the type index. struct fpga_device* fpga_dev(struct fpga_model* model, - int y, int x, enum fpgadev_type type, int idx); + int y, int x, enum fpgadev_type type, int type_idx); + +// Counts how many devices of type 'type' are in the device +// array up to devidx. +int fpga_dev_typecount(struct fpga_model* model, int y, int x, + enum fpgadev_type type, int dev_idx); enum { A6_LUT, B6_LUT, C6_LUT, D6_LUT }; // lut_len can be -1 (ZTERM) diff --git a/helper.h b/helper.h index 4ae85c1..f3e759d 100644 --- a/helper.h +++ b/helper.h @@ -22,6 +22,8 @@ "Internal error in %s:%i\n", __FILE__, __LINE__); exit(1); } #define HERE() fprintf(stderr, "%s:%i\n", __FILE__, __LINE__) +#define FAIL() do { HERE(); goto fail; } while (0) +#define XOUT() do { HERE(); goto xout; } while (0) void printf_help(void); diff --git a/model.h b/model.h index 9049197..b17b0fb 100644 --- a/model.h +++ b/model.h @@ -151,6 +151,9 @@ enum fpga_tile_type #define LAST_POS_IN_ROW 16 // including hclk at 8 #define ROW_SIZE (HALF_ROW+1+HALF_ROW) +#define CENTER_TOP_IOB_O 3 // deduct from center_x +#define CENTER_BOT_IOB_O 1 // add to center_x + // Some offsets that are being deducted from their origin #define BOT_IO_TILES 2 // todo: rename BOT_OUTER_ROW to BOT_OUTER_TERM and BOT_INNER_ROW @@ -326,8 +329,19 @@ enum { ITERM_NONE = 1, ITERM_UNTUNED_25, ITERM_UNTUNED_50, enum { OTERM_NONE = 1, OTERM_UNTUNED_25, OTERM_UNTUNED_50, OTERM_UNTUNED_75 }; +typedef char PINW_NAME[32]; + struct fpgadev_iob { + PINW_NAME pinw_in_O; + PINW_NAME pinw_in_T; + PINW_NAME pinw_out_I; + PINW_NAME pinw_out_PADOUT; + PINW_NAME pinw_out_PCI_RDY; + PINW_NAME pinw_in_DIFFI_IN; + PINW_NAME pinw_in_DIFFO_IN; + PINW_NAME pinw_out_DIFFO_OUT; + int subtype; // IOBM or IOBS IOSTANDARD istandard; IOSTANDARD ostandard; diff --git a/model_devices.c b/model_devices.c index 0ce5bdb..3e5e774 100644 --- a/model_devices.c +++ b/model_devices.c @@ -7,6 +7,7 @@ #include #include "model.h" +#include "control.h" void free_devices(struct fpga_model* model) { @@ -33,26 +34,115 @@ void free_devices(struct fpga_model* model) } } +static int init_iob(struct fpga_model* model, int y, int x, + int idx, int subtype) +{ + struct fpga_tile* tile; + const char* prefix; + int type_idx, rc; + + tile = YX_TILE(model, y, x); + tile->devs[idx].iob.subtype = subtype; + type_idx = fpga_dev_typecount(model, y, x, DEV_IOB, idx); + if (!y) + prefix = "TIOB"; + else if (y == model->y_height - BOT_OUTER_ROW) + prefix = "BIOB"; + else if (x == 0) + prefix = "LIOB"; + else if (x == model->x_width - RIGHT_OUTER_O) + prefix = "RIOB"; + else { + rc = -1; + FAIL(); + } + snprintf(tile->devs[idx].iob.pinw_in_O, + sizeof(tile->devs[idx].iob.pinw_in_O), + "%s_O%i_PINW", prefix, type_idx); + rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_in_O); + if (rc) FAIL(); + snprintf(tile->devs[idx].iob.pinw_in_T, + sizeof(tile->devs[idx].iob.pinw_in_T), + "%s_IBUF%i_PINW", prefix, type_idx); + rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_in_T); + if (rc) FAIL(); + snprintf(tile->devs[idx].iob.pinw_out_I, + sizeof(tile->devs[idx].iob.pinw_out_I), + "%s_T%i_PINW", prefix, type_idx); + rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_out_I); + if (rc) FAIL(); + snprintf(tile->devs[idx].iob.pinw_out_PADOUT, + sizeof(tile->devs[idx].iob.pinw_out_PADOUT), + "%s_PADOUT%i", prefix, type_idx); + rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_out_PADOUT); + if (rc) FAIL(); + snprintf(tile->devs[idx].iob.pinw_in_DIFFI_IN, + sizeof(tile->devs[idx].iob.pinw_in_DIFFI_IN), + "%s_DIFFI_IN%i", prefix, type_idx); + rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_in_DIFFI_IN); + if (rc) FAIL(); + snprintf(tile->devs[idx].iob.pinw_in_DIFFO_IN, + sizeof(tile->devs[idx].iob.pinw_in_DIFFO_IN), + "%s_DIFFO_IN%i", prefix, type_idx); + rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_in_DIFFO_IN); + if (rc) FAIL(); + snprintf(tile->devs[idx].iob.pinw_out_DIFFO_OUT, + sizeof(tile->devs[idx].iob.pinw_out_DIFFO_OUT), + "%s_DIFFO_OUT%i", prefix, type_idx); + rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_out_DIFFO_OUT); + if (rc) FAIL(); + + if (!x && y == model->center_y - CENTER_TOP_IOB_O && type_idx == 1) + strcpy(tile->devs[idx].iob.pinw_out_PCI_RDY, "LIOB_TOP_PCI_RDY0"); + else if (!x && y == model->center_y + CENTER_BOT_IOB_O && type_idx == 0) + strcpy(tile->devs[idx].iob.pinw_out_PCI_RDY, "LIOB_BOT_PCI_RDY0"); + else if (x == model->x_width-RIGHT_OUTER_O && y == model->center_y - CENTER_TOP_IOB_O && type_idx == 0) + strcpy(tile->devs[idx].iob.pinw_out_PCI_RDY, "RIOB_BOT_PCI_RDY0"); + else if (x == model->x_width-RIGHT_OUTER_O && y == model->center_y + CENTER_BOT_IOB_O && type_idx == 1) + strcpy(tile->devs[idx].iob.pinw_out_PCI_RDY, "RIOB_TOP_PCI_RDY1"); + else { + snprintf(tile->devs[idx].iob.pinw_out_PCI_RDY, + sizeof(tile->devs[idx].iob.pinw_out_PCI_RDY), + "%s_PCI_RDY%i", prefix, type_idx); + } + rc = add_connpt_name(model, y, x, tile->devs[idx].iob.pinw_out_PCI_RDY); + if (rc) FAIL(); + return 0; +fail: + return rc; +} + #define DEV_INCREMENT 8 static int add_dev(struct fpga_model* model, int y, int x, int type, int subtype) { - struct fpga_tile* tile = YX_TILE(model, y, x); + struct fpga_tile* tile; + int new_dev_i; + int rc; + + tile = YX_TILE(model, y, x); if (!(tile->num_devs % DEV_INCREMENT)) { void* new_ptr = realloc(tile->devs, (tile->num_devs+DEV_INCREMENT)*sizeof(*tile->devs)); EXIT(!new_ptr); - memset(new_ptr + tile->num_devs * sizeof(*tile->devs), 0, DEV_INCREMENT*sizeof(*tile->devs)); + memset(new_ptr + tile->num_devs * sizeof(*tile->devs), + 0, DEV_INCREMENT*sizeof(*tile->devs)); tile->devs = new_ptr; } - tile->devs[tile->num_devs].type = type; - if (type == DEV_IOB) - tile->devs[tile->num_devs].iob.subtype = subtype; - else if (type == DEV_LOGIC) - tile->devs[tile->num_devs].logic.subtype = subtype; + new_dev_i = tile->num_devs; tile->num_devs++; + + // init new device + tile->devs[new_dev_i].type = type; + if (type == DEV_IOB) { + rc = init_iob(model, y, x, new_dev_i, subtype); + if (rc) FAIL(); + } else if (type == DEV_LOGIC) + tile->devs[new_dev_i].logic.subtype = subtype; return 0; +fail: + return rc; } int init_devices(struct fpga_model* model) @@ -254,14 +344,14 @@ int init_devices(struct fpga_model* model) y = TOP_OUTER_ROW; if ((rc = add_dev(model, y, x, DEV_IOB, IOBM))) goto fail; if ((rc = add_dev(model, y, x, DEV_IOB, IOBS))) goto fail; - if ((rc = add_dev(model, y, x, DEV_IOB, IOBM))) goto fail; if ((rc = add_dev(model, y, x, DEV_IOB, IOBS))) goto fail; + if ((rc = add_dev(model, y, x, DEV_IOB, IOBM))) goto fail; y = model->y_height-BOT_OUTER_ROW; if ((rc = add_dev(model, y, x, DEV_IOB, IOBM))) goto fail; if ((rc = add_dev(model, y, x, DEV_IOB, IOBS))) goto fail; - if ((rc = add_dev(model, y, x, DEV_IOB, IOBM))) goto fail; if ((rc = add_dev(model, y, x, DEV_IOB, IOBS))) goto fail; + if ((rc = add_dev(model, y, x, DEV_IOB, IOBM))) goto fail; } } diff --git a/model_ports.c b/model_ports.c index 7b2e06a..d850928 100644 --- a/model_ports.c +++ b/model_ports.c @@ -8,33 +8,6 @@ #include #include "model.h" -static int add_io_connpts(struct fpga_model* model, int y, int x, const char* prefix, int num_devs) -{ - int i, rc; - - for (i = 0; i < num_devs; i++) { - rc = add_connpt_name(model, y, x, pf("%s_O%i_PINW", prefix, i)); - if (rc) goto xout; - rc = add_connpt_name(model, y, x, pf("%s_IBUF%i_PINW", prefix, i)); - if (rc) goto xout; - rc = add_connpt_name(model, y, x, pf("%s_T%i_PINW", prefix, i)); - if (rc) goto xout; - rc = add_connpt_name(model, y, x, pf("%s_PADOUT%i", prefix, i)); - if (rc) goto xout; - rc = add_connpt_name(model, y, x, pf("%s_DIFFI_IN%i", prefix, i)); - if (rc) goto xout; - rc = add_connpt_name(model, y, x, pf("%s_DIFFO_IN%i", prefix, i)); - if (rc) goto xout; - rc = add_connpt_name(model, y, x, pf("%s_DIFFO_OUT%i", prefix, i)); - if (rc) goto xout; - rc = add_connpt_name(model, y, x, pf("%s_PCI_RDY%i", prefix, i)); - if (rc) goto xout; - } - return 0; -xout: - return rc; -} - enum which_side { TOP_S, BOTTOM_S, RIGHT_S, LEFT_S @@ -221,32 +194,6 @@ int init_ports(struct fpga_model* model) } } - // IO tiles - for (x = LEFT_SIDE_WIDTH; x < model->x_width - RIGHT_SIDE_WIDTH; x++) { - if (YX_TILE(model, 0, x)->type == IO_T) { - rc = add_io_connpts(model, 0 /* y */, x, "TIOB", - 4 /* num_devs */); - if (rc) goto xout; - } - if (YX_TILE(model, model->y_height - BOT_OUTER_ROW, x)->type == IO_B) { - rc = add_io_connpts(model, model->y_height - - BOT_OUTER_ROW, x, "BIOB", 4 /* num_devs */); - if (rc) goto xout; - } - } - for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) { - if (YX_TILE(model, y, 0)->type == IO_L) { - rc = add_io_connpts(model, y, 0 /* x */, "LIOB", - 2 /* num_devs */); - if (rc) goto xout; - } - if (YX_TILE(model, y, model->x_width - RIGHT_OUTER_O)->type == IO_R) { - rc = add_io_connpts(model, y, model->x_width - - RIGHT_OUTER_O, "RIOB", 2 /* num_devs */); - if (rc) goto xout; - } - } - for (x = 0; x < model->x_width; x++) { if (is_atx(X_ROUTING_COL, model, x)) { for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) {