minor pieces here and there, a little lost right now...
This commit is contained in:
parent
b25f9daa4a
commit
0c08f07fee
75
autotest.c
75
autotest.c
|
@ -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");
|
||||
|
|
111
libs/control.c
111
libs/control.c
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
294
libs/floorplan.c
294
libs/floorplan.c
|
@ -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;
|
||||
|
|
48
libs/model.h
48
libs/model.h
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user