diff --git a/control.c b/control.c index 9d392ad..cba4cd6 100644 --- a/control.c +++ b/control.c @@ -263,10 +263,10 @@ int fpga_set_lut(struct fpga_model* model, struct fpga_device* dev, } int fpga_connpt_find(struct fpga_model* model, int y, int x, - str16_t name_i, int* connpt_dests_o) + str16_t name_i, int* connpt_dests_o, int* num_dests) { struct fpga_tile* tile; - int i, num_dests; + int i; tile = YX_TILE(model, y, x); for (i = 0; i < tile->num_conn_point_names; i++) { @@ -275,15 +275,18 @@ int fpga_connpt_find(struct fpga_model* model, int y, int x, } if (i >= tile->num_conn_point_names) { HERE(); goto fail; } - - *connpt_dests_o = tile->conn_point_names[i*2]; - if (i < tile->num_conn_point_names-1) - num_dests = tile->conn_point_names[(i+1)*2] - *connpt_dests_o; - else - num_dests = tile->num_conn_point_dests - *connpt_dests_o; - return num_dests; + if (num_dests) { + *num_dests = (i < tile->num_conn_point_names-1) + ? tile->conn_point_names[(i+1)*2] + - tile->conn_point_names[i*2] + : tile->num_conn_point_dests + - tile->conn_point_names[i*2]; + } + if (connpt_dests_o) + *connpt_dests_o = tile->conn_point_names[i*2]; + return i; fail: - return 0; + return NO_CONN; } void fpga_conn_dest(struct fpga_model* model, int y, int x, @@ -348,6 +351,28 @@ swidx_t fpga_switch_backtofirst(struct fpga_model* model, int y, int x, return fpga_switch_search(model, y, x, last, /*search_beg*/ 0, from_to); } +swidx_t fpga_switch_lookup(struct fpga_model* model, int y, int x, + str16_t from_str_i, str16_t to_str_i) +{ + int from_connpt_o, to_connpt_o, i; + struct fpga_tile* tile; + + from_connpt_o = fpga_connpt_find(model, y, x, from_str_i, + /*dests_o*/ 0, /*num_dests*/ 0); + to_connpt_o = fpga_connpt_find(model, y, x, to_str_i, + /*dests_o*/ 0, /*num_dests*/ 0); + if (from_connpt_o == NO_CONN || to_connpt_o == NO_CONN) + return NO_SWITCH; + + tile = YX_TILE(model, y, x); + for (i = 0; i < tile->num_switches; i++) { + if (SW_FROM_I(tile->switches[i]) == from_connpt_o + && SW_TO_I(tile->switches[i]) == to_connpt_o) + return i; + } + return NO_SWITCH; +} + #define NUM_CONNPT_BUFS 64 #define CONNPT_BUF_SIZE 128 @@ -628,9 +653,9 @@ int fpga_switch_conns(struct sw_conns* conns) if (end_of_chain_str == STRIDX_NO_ENTRY) { HERE(); goto internal_error; } conns->dest_i = 0; - conns->num_dests = fpga_connpt_find(conns->model, - conns->y, conns->x, end_of_chain_str, - &conns->connpt_dest_start); + fpga_connpt_find(conns->model, conns->y, conns->x, + end_of_chain_str, &conns->connpt_dest_start, + &conns->num_dests); if (conns->num_dests) break; } diff --git a/control.h b/control.h index 1fe6bba..7e64ba7 100644 --- a/control.h +++ b/control.h @@ -31,11 +31,12 @@ enum { A6_LUT, B6_LUT, C6_LUT, D6_LUT }; int fpga_set_lut(struct fpga_model* model, struct fpga_device* dev, int which_lut, const char* lut_str, int lut_len); -// returns the number of outgoing connections for the -// connection point given with 'name', and the connection -// point's first dest offset in connpt_dests_o. +// Returns the connpt index or NO_CONN if the name was not +// found. connpt_dests_o and num_dests are optional and may +// return the offset into the connpt's destination array +// and number of elements there. int fpga_connpt_find(struct fpga_model* model, int y, int x, - str16_t name_i, int* connpt_dests_o); + str16_t name_i, int* connpt_dests_o, int* num_dests); void fpga_conn_dest(struct fpga_model* model, int y, int x, int connpt_dest_idx, int* dest_y, int* dest_x, str16_t* str_i); @@ -56,6 +57,8 @@ swidx_t fpga_switch_next(struct fpga_model* model, int y, int x, swidx_t last, int from_to); swidx_t fpga_switch_backtofirst(struct fpga_model* model, int y, int x, swidx_t last, int from_to); +swidx_t fpga_switch_lookup(struct fpga_model* model, int y, int x, + str16_t from_str_i, str16_t to_str_i); const char* fpga_switch_str(struct fpga_model* model, int y, int x, swidx_t swidx, int from_to); diff --git a/floorplan.c b/floorplan.c index 6a2ee95..8530956 100644 --- a/floorplan.c +++ b/floorplan.c @@ -673,6 +673,158 @@ static enum fpgadev_type to_type(const char* s, int len) 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; + + next_word(s, start, &y_beg, &y_end); + next_word(s, y_end, &x_beg, &x_end); + if (y_end < y_beg+2 || x_end < x_beg+2 + || s[y_beg] != 'y' || s[x_beg] != 'x' + || !all_digits(&s[y_beg+1], y_end-y_beg-1) + || !all_digits(&s[x_beg+1], x_end-x_beg-1)) { + FAIL(EINVAL); + } + *y = to_i(&s[y_beg+1], y_end-y_beg-1); + *x = to_i(&s[x_beg+1], x_end-x_beg-1); + *end = x_end; + return 0; +fail: + return rc; +} + +static void read_sw_line(struct fpga_model* model, const char* line, int start) +{ + int coord_end, y_coord, x_coord; + int from_beg, from_end, from_str_i; + int direction_beg, direction_end, is_bidir; + int to_beg, to_end, to_str_i; + int on_beg, on_end, is_on; + swidx_t sw_idx; + int sw_is_bidir; + char buf[1024]; + + if (coord(line, start, &coord_end, &y_coord, &x_coord)) + return; + + next_word(line, coord_end, &from_beg, &from_end); + next_word(line, from_end, &direction_beg, &direction_end); + next_word(line, direction_end, &to_beg, &to_end); + next_word(line, to_end, &on_beg, &on_end); + + if (from_end <= from_beg || direction_end <= direction_beg + || to_end <= to_beg) { + HERE(); + return; + } + memcpy(buf, &line[from_beg], from_end-from_beg); + buf[from_end-from_beg] = 0; + if (strarray_find(&model->str, buf, &from_str_i) + || from_str_i == STRIDX_NO_ENTRY) { + HERE(); + return; + } + if (!str_cmp(&line[direction_beg], direction_end-direction_beg, + "->", 2)) + is_bidir = 0; + else if (!str_cmp(&line[direction_beg], direction_end-direction_beg, + "<->", 3)) + is_bidir = 1; + else { + HERE(); + return; + } + memcpy(buf, &line[to_beg], to_end-to_beg); + buf[to_end-to_beg] = 0; + if (strarray_find(&model->str, buf, &to_str_i) + || to_str_i == STRIDX_NO_ENTRY) { + HERE(); + return; + } + if (on_end == on_beg) + is_on = 0; + else if (!str_cmp(&line[on_beg], on_end-on_beg, "on", 2)) + is_on = 1; + else { + HERE(); + return; + } + + sw_idx = fpga_switch_lookup(model, y_coord, x_coord, from_str_i, to_str_i); + if (sw_idx == NO_SWITCH) { + HERE(); + return; + } + sw_is_bidir = fpga_switch_is_bidir(model, y_coord, x_coord, sw_idx); + if ((is_bidir && !sw_is_bidir) + || (!is_bidir && sw_is_bidir)) { + HERE(); + return; + } + if (fpga_switch_is_enabled(model, y_coord, x_coord, sw_idx)) + HERE(); + if (is_on) + fpga_switch_enable(model, y_coord, x_coord, sw_idx); +} + +static void read_dev_line(struct fpga_model* model, const char* line, int start) +{ + int coord_end, y_coord, x_coord; + int type_beg, type_end, idx_beg, idx_end; + enum fpgadev_type dev_type; + int dev_idx, words_consumed; + struct fpga_device* dev_ptr; + int next_beg, next_end, second_beg, second_end; + + if (coord(line, start, &coord_end, &y_coord, &x_coord)) + return; + + next_word(line, coord_end, &type_beg, &type_end); + next_word(line, type_end, &idx_beg, &idx_end); + + 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); + return; + } + dev_type = to_type(&line[type_beg], type_end-type_beg); + dev_idx = to_i(&line[idx_beg], idx_end-idx_beg); + dev_ptr = fpga_dev(model, y_coord, x_coord, dev_type, dev_idx); + if (!dev_ptr) { + fprintf(stderr, "error %i: %s", __LINE__, line); + return; + } + + next_end = idx_end; + while (next_word(line, next_end, &next_beg, &next_end), + next_end > next_beg) { + next_word(line, next_end, &second_beg, &second_end); + switch (dev_type) { + case DEV_IOB: + words_consumed = read_IOB_attr(model, dev_ptr, + &line[next_beg], next_end-next_beg, + &line[second_beg], + second_end-second_beg); + break; + case DEV_LOGIC: + words_consumed = read_LOGIC_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; + } + if (!words_consumed) + fprintf(stderr, "error %i w1 %.*s w2 %.*s: %s", + __LINE__, next_end-next_beg, &line[next_beg], + second_end-second_beg, &line[second_beg], line); + else if (words_consumed == 2) + next_end = second_end; + } +} + int read_floorplan(struct fpga_model* model, FILE* f) { char line[1024]; @@ -682,81 +834,13 @@ int read_floorplan(struct fpga_model* model, FILE* f) next_word(line, 0, &beg, &end); if (end == beg) continue; - if (!str_cmp(&line[beg], end-beg, "dev", 3)) { - int y_beg, y_end, x_beg, x_end; - int y_coord, x_coord; - int type_beg, type_end, idx_beg, idx_end; - enum fpgadev_type dev_type; - int dev_idx, words_consumed; - struct fpga_device* dev_ptr; - int next_beg, next_end, second_beg, second_end; - - next_word(line, end, &y_beg, &y_end); - next_word(line, y_end, &x_beg, &x_end); - if (y_end < y_beg+2 || x_end < x_beg+2 - || line[y_beg] != 'y' || line[x_beg] != 'x' - || !all_digits(&line[y_beg+1], y_end-y_beg-1) - || !all_digits(&line[x_beg+1], x_end-x_beg-1)) { - fprintf(stderr, "error %i: %s", __LINE__, line); - continue; - } - y_coord = to_i(&line[y_beg+1], y_end-y_beg-1); - x_coord = to_i(&line[x_beg+1], x_end-x_beg-1); - - next_word(line, x_end, &type_beg, &type_end); - next_word(line, type_end, &idx_beg, &idx_end); - - 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); - continue; - } - dev_type = to_type(&line[type_beg], type_end-type_beg); - dev_idx = to_i(&line[idx_beg], idx_end-idx_beg); - dev_ptr = fpga_dev(model, y_coord, x_coord, dev_type, dev_idx); - if (!dev_ptr) { - fprintf(stderr, "error %i: %s", __LINE__, line); - continue; - } - - next_end = idx_end; - while (next_word(line, next_end, &next_beg, &next_end), - next_end > next_beg) { - next_word(line, next_end, &second_beg, &second_end); - switch (dev_type) { - case DEV_IOB: - words_consumed = read_IOB_attr( - model, dev_ptr, - &line[next_beg], - next_end-next_beg, - &line[second_beg], - second_end-second_beg); - break; - case DEV_LOGIC: - words_consumed = read_LOGIC_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); - goto next_line; - } - if (!words_consumed) - fprintf(stderr, - "error %i w1 %.*s w2 %.*s: %s", - __LINE__, next_end-next_beg, - &line[next_beg], - second_end-second_beg, - &line[second_beg], - line); - else if (words_consumed == 2) - next_end = second_end; - } -next_line: ; + if (end-beg == 2 + && !str_cmp(&line[beg], 2, "sw", 2)) { + read_sw_line(model, line, end); + } + if (end-beg == 3 + && !str_cmp(&line[beg], 3, "dev", 3)) { + read_dev_line(model, line, end); } } return 0;