minor pieces here and there, a little lost right now...

This commit is contained in:
Wolfgang Spraul 2012-10-15 15:37:26 +02:00
parent b25f9daa4a
commit 0c08f07fee
5 changed files with 519 additions and 18 deletions

View File

@ -1681,6 +1681,57 @@ fail:
return rc;
}
static int test_bufg_config(struct test_state* tstate)
{
int dev_y, dev_x, dev_tidx, i, rc;
tstate->diff_to_null = 1;
// todo: not implemented
return 0;
i = 0;
while (1) {
rc = fdev_enum(tstate->model, DEV_BUFGMUX, i++,
&dev_y, &dev_x, &dev_tidx);
if (rc) FAIL(EINVAL);
if (dev_y == -1) break;
rc = fdev_bufgmux(tstate->model, dev_y, dev_x, dev_tidx,
BUFG_CLK_ASYNC, BUFG_DISATTR_LOW, BUFG_SINV_Y);
if (rc) FAIL(rc);
// stub nets for required pins? s-pin?
if ((rc = diff_printf(tstate))) FAIL(rc);
fdev_delete(tstate->model, dev_y, dev_x, DEV_BUFGMUX, dev_tidx);
}
return 0;
fail:
return rc;
}
static int test_bufio_config(struct test_state* tstate)
{
// todo: not implemented
return 0;
}
static int test_pll_config(struct test_state* tstate)
{
// todo: not implemented
return 0;
}
static int test_dcm_config(struct test_state* tstate)
{
// todo: not implemented
return 0;
}
static int test_bscan_config(struct test_state* tstate)
{
// todo: not implemented
return 0;
}
#define DEFAULT_DIFF_EXEC "./autotest_diff.sh"
static void printf_help(const char* argv_0, const char** available_tests)
@ -1711,7 +1762,9 @@ int main(int argc, char** argv)
char param[1024], cmdline_test[1024];
int i, param_skip, rc;
const char* available_tests[] =
{ "logic_cfg", "routing_sw", "io_sw", "iob_cfg", "lut_encoding", 0 };
{ "logic_cfg", "routing_sw", "io_sw", "iob_cfg",
"lut_encoding", "bufg_cfg", "bufio_cfg", "pll_cfg",
"dcm_cfg", "bscan_cfg", 0 };
// flush after every line is better for the autotest
// output, tee, etc.
@ -1840,6 +1893,26 @@ int main(int argc, char** argv)
rc = test_lut_encoding(&tstate);
if (rc) FAIL(rc);
}
if (!strcmp(cmdline_test, "bufg_cfg")) {
rc = test_bufg_config(&tstate);
if (rc) FAIL(rc);
}
if (!strcmp(cmdline_test, "bufio_cfg")) {
rc = test_bufio_config(&tstate);
if (rc) FAIL(rc);
}
if (!strcmp(cmdline_test, "pll_cfg")) {
rc = test_pll_config(&tstate);
if (rc) FAIL(rc);
}
if (!strcmp(cmdline_test, "dcm_cfg")) {
rc = test_dcm_config(&tstate);
if (rc) FAIL(rc);
}
if (!strcmp(cmdline_test, "bscan_cfg")) {
rc = test_bscan_config(&tstate);
if (rc) FAIL(rc);
}
printf("\n");
printf("O Test completed.\n");

View File

@ -200,6 +200,97 @@ const char* fpga_iob_sitename(struct fpga_model* model, int y, int x,
return 0;
}
static void enum_x(struct fpga_model *model, enum fpgadev_type type,
int enum_i, int *y, int x, int *type_idx)
{
int type_count, i, _y;
struct fpga_tile* tile;
type_count = 0;
for (_y = 0; _y < model->y_height; _y++) {
tile = YX_TILE(model, _y, x);
for (i = 0; i < tile->num_devs; i++) {
if (tile->devs[i].type != type)
continue;
if (type_count == enum_i) {
*y = _y;
*type_idx = type_count;
return;
}
type_count++;
}
}
*y = -1;
}
int fdev_enum(struct fpga_model* model, enum fpgadev_type type, int enum_i,
int *y, int *x, int *type_idx)
{
struct fpga_tile* tile;
int i, j, type_count, rc;
CHECK_RC(model);
switch (type) {
case DEV_BUFGMUX:
tile = YX_TILE(model, model->center_y, model->center_x);
if (!tile) FAIL(EINVAL);
type_count = 0;
for (i = 0; i < tile->num_devs; i++) {
if (tile->devs[i].type != DEV_BUFGMUX)
continue;
if (type_count == enum_i) {
*y = model->center_y;
*x = model->center_x;
*type_idx = type_count;
return 0;
}
type_count++;
}
*y = -1;
return 0;
case DEV_BUFIO: {
int yx_pairs[] = {
TOP_OUTER_ROW, model->center_x-CENTER_CMTPLL_O,
model->center_y, LEFT_OUTER_COL,
model->center_y, model->x_width-RIGHT_OUTER_O,
model->y_height-BOT_OUTER_ROW, model->center_x-CENTER_CMTPLL_O };
type_count = 0;
for (i = 0; i < sizeof(yx_pairs)/sizeof(*yx_pairs)/2; i++) {
tile = YX_TILE(model, yx_pairs[i*2], yx_pairs[i*2+1]);
for (j = 0; j < tile->num_devs; j++) {
if (tile->devs[j].type != DEV_BUFIO)
continue;
if (type_count == enum_i) {
*y = yx_pairs[i*2];
*x = yx_pairs[i*2+1];
*type_idx = type_count;
return 0;
}
type_count++;
}
}
*y = -1;
return 0;
}
case DEV_PLL:
case DEV_DCM:
enum_x(model, type, enum_i, y, model->center_x
- CENTER_CMTPLL_O, type_idx);
return 0;
case DEV_BSCAN:
enum_x(model, type, enum_i, y, model->x_width
- RIGHT_IO_DEVS_O, type_idx);
return 0;
default: break;
}
HERE();
*y = -1;
return 0;
fail:
return rc;
}
static const char* dev_str[] = FPGA_DEV_STR;
const char* fdev_type2str(enum fpgadev_type type)
@ -852,6 +943,26 @@ fail:
return rc;
}
int fdev_bufgmux(struct fpga_model* model, int y, int x,
int type_idx, int clk, int disable_attr, int s_inv)
{
struct fpga_device* dev;
int rc;
dev = fdev_p(model, y, x, DEV_BUFGMUX, type_idx);
if (!dev) FAIL(EINVAL);
rc = reset_required_pins(dev);
if (rc) FAIL(rc);
dev->u.bufgmux.clk = clk;
dev->u.bufgmux.disable_attr = disable_attr;
dev->u.bufgmux.s_inv = s_inv;
dev->instantiated = 1;
return 0;
fail:
return rc;
}
static void scan_lut_digits(const char* s, int* digits)
{
int i;

View File

@ -18,13 +18,17 @@ const char* fpga_iob_sitename(struct fpga_model* model, int y, int x,
// 2. The index of the device within devices of the same type in the tile.
//
// If index is past the last device of that type,
// y is returned as -1.
int fdev_enum(struct fpga_model* model, enum fpgadev_type type, int enum_i,
int *y, int *x, int *type_idx);
const char* fdev_type2str(enum fpgadev_type type);
enum fpgadev_type fdev_str2type(const char* str, int len);
// returns 0 if device not found
struct fpga_device* fdev_p(struct fpga_model* model,
int y, int x, enum fpgadev_type type, dev_type_idx_t type_idx);
// Looks up a device index based on the type index.
// returns NO_DEV (-1) if not found
dev_idx_t fpga_dev_idx(struct fpga_model* model,
@ -94,6 +98,9 @@ int fdev_iob_slew(struct fpga_model* model, int y, int x,
int fdev_iob_drive(struct fpga_model* model, int y, int x,
int type_idx, int drive_strength);
int fdev_bufgmux(struct fpga_model* model, int y, int x,
int type_idx, int clk, int disable_attr, int s_inv);
int fdev_set_required_pins(struct fpga_model* model, int y, int x, int type,
int type_idx);
void fdev_print_required_pins(struct fpga_model* model, int y, int x,

View File

@ -184,8 +184,8 @@ static int printf_IOB(FILE* f, struct fpga_model* model,
return 0;
}
static int read_IOB_attr(struct fpga_model* model, struct fpga_device* dev,
const char* w1, int w1_len, const char* w2, int w2_len)
static int read_IOB_attr(struct fpga_model *model, struct fpga_device *dev,
const char *w1, int w1_len, const char *w2, int w2_len)
{
// First the one-word attributes.
if (!str_cmp(w1, w1_len, "O_used", ZTERM)) {
@ -283,7 +283,7 @@ inst_1:
dev->instantiated = 1;
return 1;
inst_2:
dev->instantiated = 2;
dev->instantiated = 1;
return 2;
}
@ -655,6 +655,237 @@ inst_2:
return 2;
}
static int printf_BUFGMUX(FILE* f, struct fpga_model* model,
int y, int x, int config_only)
{
struct fpga_tile *tile;
struct fpgadev_bufgmux *cfg;
char pref[256];
int type_count, i, rc;
tile = YX_TILE(model, y, x);
type_count = 0;
for (i = 0; i < tile->num_devs; i++) {
if (tile->devs[i].type != DEV_BUFGMUX)
continue;
if (config_only && !(tile->devs[i].instantiated)) {
type_count++;
continue;
}
snprintf(pref, sizeof(pref), "dev y%02i x%02i BUFGMUX %i",
y, x, type_count++);
if (!config_only)
fprintf(f, "%s\n", pref);
cfg = &tile->devs[i].u.bufgmux;
switch (cfg->clk) {
case BUFG_CLK_ASYNC:
fprintf(f, "%s clk ASYNC\n", pref);
break;
case BUFG_CLK_SYNC:
fprintf(f, "%s clk SYNC\n", pref);
break;
case 0: break; default: FAIL(EINVAL);
}
switch (cfg->disable_attr) {
case BUFG_DISATTR_LOW:
fprintf(f, "%s disable_attr LOW\n", pref);
break;
case BUFG_DISATTR_HIGH:
fprintf(f, "%s disable_attr HIGH\n", pref);
break;
case 0: break; default: FAIL(EINVAL);
}
switch (cfg->s_inv) {
case BUFG_SINV_N:
fprintf(f, "%s s_inv NO\n", pref);
break;
case BUFG_SINV_Y:
fprintf(f, "%s s_inv YES\n", pref);
break;
case 0: break; default: FAIL(EINVAL);
}
}
return 0;
fail:
return rc;
}
static int read_BUFGMUX_attr(struct fpga_model *model, struct fpga_device *dev,
const char *w1, int w1_len, const char *w2, int w2_len)
{
// BUFGMUX only has 2-word attributes
if (w2_len < 1) return 0;
if (!str_cmp(w1, w1_len, "clk", ZTERM)) {
if (!str_cmp(w2, w2_len, "ASYNC", ZTERM))
dev->u.bufgmux.clk = BUFG_CLK_ASYNC;
else if (!str_cmp(w2, w2_len, "SYNC", ZTERM))
dev->u.bufgmux.clk = BUFG_CLK_SYNC;
else return 0;
goto inst;
}
if (!str_cmp(w1, w1_len, "disable_attr", ZTERM)) {
if (!str_cmp(w2, w2_len, "LOW", ZTERM))
dev->u.bufgmux.disable_attr = BUFG_DISATTR_LOW;
else if (!str_cmp(w2, w2_len, "HIGH", ZTERM))
dev->u.bufgmux.disable_attr = BUFG_DISATTR_HIGH;
else return 0;
goto inst;
}
if (!str_cmp(w1, w1_len, "s_inv", ZTERM)) {
if (!str_cmp(w2, w2_len, "NO", ZTERM))
dev->u.bufgmux.s_inv = BUFG_SINV_N;
else if (!str_cmp(w2, w2_len, "YES", ZTERM))
dev->u.bufgmux.s_inv = BUFG_SINV_Y;
else return 0;
goto inst;
}
return 0;
inst:
dev->instantiated = 1;
return 2;
}
static int printf_BUFIO(FILE* f, struct fpga_model* model,
int y, int x, int config_only)
{
struct fpga_tile *tile;
struct fpgadev_bufio *cfg;
char pref[256];
int type_count, i, rc;
tile = YX_TILE(model, y, x);
type_count = 0;
for (i = 0; i < tile->num_devs; i++) {
if (tile->devs[i].type != DEV_BUFIO)
continue;
if (config_only && !(tile->devs[i].instantiated)) {
type_count++;
continue;
}
snprintf(pref, sizeof(pref), "dev y%02i x%02i BUFGMUX %i",
y, x, type_count++);
if (!config_only)
fprintf(f, "%s\n", pref);
cfg = &tile->devs[i].u.bufio;
if (cfg->divide)
fprintf(f, "%s divide %i\n", pref, cfg->divide);
switch (cfg->divide_bypass) {
case BUFIO_DIVIDEBP_N:
fprintf(f, "%s divide_bypass NO\n", pref);
break;
case BUFIO_DIVIDEBP_Y:
fprintf(f, "%s divide_bypass YES\n", pref);
break;
case 0: break; default: FAIL(EINVAL);
}
switch (cfg->i_inv) {
case BUFIO_IINV_N:
fprintf(f, "%s i_inv NO\n", pref);
break;
case BUFIO_IINV_Y:
fprintf(f, "%s i_inv YES\n", pref);
break;
case 0: break; default: FAIL(EINVAL);
}
}
return 0;
fail:
return rc;
}
static int read_BUFIO_attr(struct fpga_model *model, struct fpga_device *dev,
const char *w1, int w1_len, const char *w2, int w2_len)
{
// BUFIO only has 2-word attributes
if (w2_len < 1) return 0;
if (!str_cmp(w1, w1_len, "divide", ZTERM)) {
dev->u.bufio.divide = to_i(w2, w2_len);
goto inst;
}
if (!str_cmp(w1, w1_len, "divide_bypass", ZTERM)) {
if (!str_cmp(w2, w2_len, "NO", ZTERM))
dev->u.bufio.divide_bypass = BUFIO_DIVIDEBP_N;
else if (!str_cmp(w2, w2_len, "YES", ZTERM))
dev->u.bufio.divide_bypass = BUFIO_DIVIDEBP_Y;
else return 0;
goto inst;
}
if (!str_cmp(w1, w1_len, "i_inv", ZTERM)) {
if (!str_cmp(w2, w2_len, "NO", ZTERM))
dev->u.bufio.i_inv = BUFIO_IINV_N;
else if (!str_cmp(w2, w2_len, "YES", ZTERM))
dev->u.bufio.i_inv = BUFIO_IINV_Y;
else return 0;
goto inst;
}
return 0;
inst:
dev->instantiated = 1;
return 2;
}
static int printf_BSCAN(FILE* f, struct fpga_model* model,
int y, int x, int config_only)
{
struct fpga_tile *tile;
struct fpgadev_bscan *cfg;
char pref[256];
int type_count, i, rc;
tile = YX_TILE(model, y, x);
type_count = 0;
for (i = 0; i < tile->num_devs; i++) {
if (tile->devs[i].type != DEV_BSCAN)
continue;
if (config_only && !(tile->devs[i].instantiated)) {
type_count++;
continue;
}
snprintf(pref, sizeof(pref), "dev y%02i x%02i BUFGMUX %i",
y, x, type_count++);
if (!config_only)
fprintf(f, "%s\n", pref);
cfg = &tile->devs[i].u.bscan;
if (cfg->jtag_chain)
fprintf(f, "%s jtag_chain %i\n", pref, cfg->jtag_chain);
switch (cfg->jtag_test) {
case BSCAN_JTAG_TEST_N:
fprintf(f, "%s jtag_test NO\n", pref);
break;
case BSCAN_JTAG_TEST_Y:
fprintf(f, "%s jtag_test YES\n", pref);
break;
case 0: break; default: FAIL(EINVAL);
}
}
return 0;
fail:
return rc;
}
static int read_BSCAN_attr(struct fpga_model *model, struct fpga_device *dev,
const char *w1, int w1_len, const char *w2, int w2_len)
{
// BSCAN only has 2-word attributes
if (w2_len < 1) return 0;
if (!str_cmp(w1, w1_len, "jtag_chain", ZTERM)) {
dev->u.bscan.jtag_chain = to_i(w2, w2_len);
goto inst;
}
if (!str_cmp(w1, w1_len, "jtag_test", ZTERM)) {
if (!str_cmp(w2, w2_len, "NO", ZTERM))
dev->u.bscan.jtag_test = BSCAN_JTAG_TEST_N;
else if (!str_cmp(w2, w2_len, "YES", ZTERM))
dev->u.bscan.jtag_test = BSCAN_JTAG_TEST_Y;
else return 0;
goto inst;
}
return 0;
inst:
dev->instantiated = 1;
return 2;
}
int printf_devices(FILE* f, struct fpga_model* model, int config_only)
{
int x, y, i, rc;
@ -672,6 +903,24 @@ int printf_devices(FILE* f, struct fpga_model* model, int config_only)
if (rc) goto fail;
}
}
for (x = 0; x < model->x_width; x++) {
for (y = 0; y < model->y_height; y++) {
rc = printf_BUFGMUX(f, model, y, x, config_only);
if (rc) goto fail;
}
}
for (x = 0; x < model->x_width; x++) {
for (y = 0; y < model->y_height; y++) {
rc = printf_BUFIO(f, model, y, x, config_only);
if (rc) goto fail;
}
}
for (x = 0; x < model->x_width; x++) {
for (y = 0; y < model->y_height; y++) {
rc = printf_BSCAN(f, model, y, x, config_only);
if (rc) goto fail;
}
}
for (x = 0; x < model->x_width; x++) {
for (y = 0; y < model->y_height; y++) {
tile = YX_TILE(model, y, x);
@ -679,7 +928,10 @@ int printf_devices(FILE* f, struct fpga_model* model, int config_only)
if (config_only && !(tile->devs[i].instantiated))
continue;
if (tile->devs[i].type == DEV_LOGIC
|| tile->devs[i].type == DEV_IOB)
|| tile->devs[i].type == DEV_IOB
|| tile->devs[i].type == DEV_BUFGMUX
|| tile->devs[i].type == DEV_BUFIO
|| tile->devs[i].type == DEV_BSCAN)
continue; // handled earlier
fprintf(f, "dev y%02i x%02i %s\n", y, x,
fdev_type2str(tile->devs[i].type));
@ -825,13 +1077,6 @@ fail:
return rc;
}
static enum fpgadev_type to_type(const char* s, int len)
{
if (!str_cmp(s, len, "IOB", 3)) return DEV_IOB;
if (!str_cmp(s, len, "LOGIC", 5)) return DEV_LOGIC;
return DEV_NONE;
}
static int coord(const char* s, int start, int* end, int* y, int* x)
{
int y_beg, y_end, x_beg, x_end, rc;
@ -986,14 +1231,17 @@ static void read_dev_line(struct fpga_model* model, const char* line, int start)
if (type_end == type_beg || idx_end == idx_beg
|| !all_digits(&line[idx_beg], idx_end-idx_beg)) {
fprintf(stderr, "error %i: %s", __LINE__, line);
HERE();
return;
}
dev_type = to_type(&line[type_beg], type_end-type_beg);
dev_type = fdev_str2type(&line[type_beg], type_end-type_beg);
dev_type_idx = to_i(&line[idx_beg], idx_end-idx_beg);
dev_idx = fpga_dev_idx(model, y_coord, x_coord, dev_type, dev_type_idx);
if (dev_idx == NO_DEV) {
fprintf(stderr, "error %i: %s", __LINE__, line);
fprintf(stderr, "%s:%i y%02i x%02i dev_type %i "
"dev_type_idx %i dev_idx %i\n",
__FILE__, __LINE__, y_coord, x_coord, dev_type,
dev_type_idx, dev_idx);
return;
}
dev_ptr = FPGA_DEV(model, y_coord, x_coord, dev_idx);
@ -1016,6 +1264,24 @@ static void read_dev_line(struct fpga_model* model, const char* line, int start)
&line[second_beg],
second_end-second_beg);
break;
case DEV_BUFGMUX:
words_consumed = read_BUFGMUX_attr(model, dev_ptr,
&line[next_beg], next_end-next_beg,
&line[second_beg],
second_end-second_beg);
break;
case DEV_BUFIO:
words_consumed = read_BUFIO_attr(model, dev_ptr,
&line[next_beg], next_end-next_beg,
&line[second_beg],
second_end-second_beg);
break;
case DEV_BSCAN:
words_consumed = read_BSCAN_attr(model, dev_ptr,
&line[next_beg], next_end-next_beg,
&line[second_beg],
second_end-second_beg);
break;
default:
fprintf(stderr, "error %i: %s", __LINE__, line);
return;

View File

@ -343,7 +343,7 @@ typedef int dev_type_idx_t;
#define FPGA_DEV(model, y, x, dev_idx) (&YX_TILE(model, y, x)->devs[dev_idx])
//
// logic device
// DEV_LOGIC
//
// M and L device is always at type index 0, X device
@ -444,7 +444,7 @@ struct fpgadev_logic
};
//
// iob device
// DEV_IOB
//
enum { IOBM = 1, IOBS };
@ -493,6 +493,47 @@ struct fpgadev_iob
int out_term;
};
//
// DEV_BUFGMUX
//
enum { BUFG_CLK_ASYNC = 1, BUFG_CLK_SYNC };
enum { BUFG_DISATTR_LOW = 1, BUFG_DISATTR_HIGH };
enum { BUFG_SINV_N = 1, BUFG_SINV_Y };
struct fpgadev_bufgmux
{
int clk;
int disable_attr;
int s_inv;
};
//
// DEV_BUFIO
//
enum { BUFIO_DIVIDEBP_N = 1, BUFIO_DIVIDEBP_Y };
enum { BUFIO_IINV_N = 1, BUFIO_IINV_Y };
struct fpgadev_bufio
{
int divide;
int divide_bypass;
int i_inv;
};
//
// DEV_BSCAN
//
enum { BSCAN_JTAG_TEST_N = 1, BSCAN_JTAG_TEST_Y };
struct fpgadev_bscan
{
int jtag_chain; // 1-4
int jtag_test;
};
//
// fpga_device
//
@ -526,6 +567,9 @@ struct fpga_device
union {
struct fpgadev_logic logic;
struct fpgadev_iob iob;
struct fpgadev_bufgmux bufgmux;
struct fpgadev_bufio bufio;
struct fpgadev_bscan bscan;
} u;
};