some switch work
This commit is contained in:
parent
dc1a40805f
commit
63f16c95d0
2
Makefile
2
Makefile
|
@ -22,7 +22,7 @@ all: new_fp fp2bit bit2fp draw_svg_tiles \
|
||||||
|
|
||||||
autotest: autotest.o $(MODEL_OBJ) floorplan.o control.o helper.o model.h
|
autotest: autotest.o $(MODEL_OBJ) floorplan.o control.o helper.o model.h
|
||||||
|
|
||||||
autotest.c: model.h floorplan.h control.h
|
autotest.o: model.h floorplan.h control.h
|
||||||
|
|
||||||
new_fp: new_fp.o $(MODEL_OBJ) floorplan.o helper.o control.o
|
new_fp: new_fp.o $(MODEL_OBJ) floorplan.o helper.o control.o
|
||||||
|
|
||||||
|
|
18
README
18
README
|
@ -4,15 +4,22 @@ Design Principles
|
||||||
- plain C, no C++
|
- plain C, no C++
|
||||||
- simple Makefiles
|
- simple Makefiles
|
||||||
- text-based file formats
|
- text-based file formats
|
||||||
- no documentation - please read the sources
|
|
||||||
- automatic test suite
|
- automatic test suite
|
||||||
|
- public domain software
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
todo
|
||||||
|
|
||||||
|
FAQ
|
||||||
|
todo
|
||||||
|
|
||||||
Libraries
|
Libraries
|
||||||
|
|
||||||
- libfpga-test test harness for model, control and design
|
- libfpga-test autotest suite
|
||||||
- libfpga-model memory-only representation of an FPGA
|
- libfpga-cores reusable cores
|
||||||
- libfpga-control programmatic access to libfpga-model
|
|
||||||
- libfpga-design larger design elements on top of libfpga-control
|
- libfpga-design larger design elements on top of libfpga-control
|
||||||
|
- libfpga-control programmatic access to libfpga-model
|
||||||
|
- libfpga-model memory-only representation of an FPGA
|
||||||
- libfpga-floorplan reads and writes .fp floorplan files
|
- libfpga-floorplan reads and writes .fp floorplan files
|
||||||
- libfpga-bit reads and writes .bit bitstream files
|
- libfpga-bit reads and writes .bit bitstream files
|
||||||
|
|
||||||
|
@ -40,13 +47,14 @@ TODO (as of 2012-08, expected time to delivery: months to years
|
||||||
* smarter autotester that can remember and verify groups of tests,
|
* smarter autotester that can remember and verify groups of tests,
|
||||||
automatically oversee test execution, etc.
|
automatically oversee test execution, etc.
|
||||||
* 3 Debian packages: libfpga, libfpga-doc, fpgatools
|
* 3 Debian packages: libfpga, libfpga-doc, fpgatools
|
||||||
* correct auto-crc calculation in .bit file
|
* auto-crc calculation in .bit file
|
||||||
* many more cases in logic block configuration
|
* many more cases in logic block configuration
|
||||||
* configuration of bram and macc blocks, bram initialization data
|
* configuration of bram and macc blocks, bram initialization data
|
||||||
* routing switches
|
* routing switches
|
||||||
* many more cases in model of switches and inter-tile connections
|
* many more cases in model of switches and inter-tile connections
|
||||||
* write standard design elements for libfpga-design library
|
* write standard design elements for libfpga-design library
|
||||||
* support lm32 or openrisc core, either via libfpga or iverilog backend
|
* support lm32 or openrisc core, either via libfpga or iverilog backend
|
||||||
|
* ipv6 or vnc in hardware?
|
||||||
* iverilog fpga backend
|
* iverilog fpga backend
|
||||||
|
|
||||||
ChangeLog
|
ChangeLog
|
||||||
|
|
118
autotest.c
118
autotest.c
|
@ -108,18 +108,16 @@ static const char* s_spaces = " ";
|
||||||
static int printf_switchtree(struct fpga_model* model, int y, int x,
|
static int printf_switchtree(struct fpga_model* model, int y, int x,
|
||||||
const char* start, int indent)
|
const char* start, int indent)
|
||||||
{
|
{
|
||||||
int i, idx, conn_to_y, conn_to_x, rc;
|
int i, idx, conn_to_y, conn_to_x, num_dests, connpt_dests_o, rc;
|
||||||
const char* to_str;
|
const char* to_str;
|
||||||
|
|
||||||
printf("%.*sy%02i x%02i %s\n", indent, s_spaces, y, x, start);
|
printf("%.*sy%02i x%02i %s\n", indent, s_spaces, y, x, start);
|
||||||
for (i = 0;; i++) {
|
num_dests = fpga_connpt_lookup(model, y, x, start, &connpt_dests_o);
|
||||||
idx = fpga_conn_dest(model, y, x, start, i);
|
for (i = 0; i < num_dests; i++) {
|
||||||
if (idx == NO_CONN)
|
|
||||||
break;
|
|
||||||
if (!i)
|
if (!i)
|
||||||
printf("%.*s| connects to:\n", indent, s_spaces);
|
printf("%.*s| connects to:\n", indent, s_spaces);
|
||||||
to_str = fpga_conn_to(model, y, x,
|
to_str = fpga_conn_dest(model, y, x,
|
||||||
idx, &conn_to_y, &conn_to_x);
|
connpt_dests_o + i, &conn_to_y, &conn_to_x);
|
||||||
printf("%.*s y%02i x%02i %s\n", indent, s_spaces,
|
printf("%.*s y%02i x%02i %s\n", indent, s_spaces,
|
||||||
conn_to_y, conn_to_x, to_str);
|
conn_to_y, conn_to_x, to_str);
|
||||||
}
|
}
|
||||||
|
@ -151,16 +149,16 @@ static int printf_switchtree(struct fpga_model* model, int y, int x,
|
||||||
fail:
|
fail:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
struct fpga_model model;
|
struct fpga_model model;
|
||||||
struct fpga_device* P46_dev, *P48_dev, *logic_dev;
|
struct fpga_device* P46_dev, *P48_dev, *logic_dev;
|
||||||
int P46_y, P46_x, P46_idx, P48_y, P48_x, P48_idx, i, sw_idx, rc;
|
int P46_y, P46_x, P46_idx, P48_y, P48_x, P48_idx, rc;
|
||||||
const char* str;
|
|
||||||
char tmp_str[128];
|
|
||||||
struct test_state tstate;
|
struct test_state tstate;
|
||||||
const char* conn_to_str;
|
struct sw_chain chain;
|
||||||
int conn_idx, conn_to_y, conn_to_x;
|
struct swchain_conns conns;
|
||||||
|
char tmp_str[128];
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("O fpgatools automatic test suite. Be welcome and be "
|
printf("O fpgatools automatic test suite. Be welcome and be "
|
||||||
|
@ -219,46 +217,74 @@ int main(int argc, char** argv)
|
||||||
if (rc) goto fail;
|
if (rc) goto fail;
|
||||||
|
|
||||||
printf("P46 I pinw %s\n", P46_dev->iob.pinw_out_I);
|
printf("P46 I pinw %s\n", P46_dev->iob.pinw_out_I);
|
||||||
sw_idx = fpga_switch_first(&model, P46_y, P46_x,
|
conns.model = &model;
|
||||||
P46_dev->iob.pinw_out_I, SW_FROM);
|
conns.y = P46_y;
|
||||||
while (sw_idx != NO_SWITCH) {
|
conns.x = P46_x;
|
||||||
str = fpga_switch_str(&model, P46_y, P46_x, sw_idx, SW_TO);
|
conns.start_switch = P46_dev->iob.pinw_out_I;
|
||||||
if (!str) FAIL(EINVAL);
|
while (fpga_switch_conns_enum(&conns) != NO_CONN) {
|
||||||
strcpy(tmp_str, str); // ringbuffer too small for long use
|
|
||||||
printf(" from %s to %s\n", P46_dev->iob.pinw_out_I, tmp_str);
|
if (is_aty(Y_TOP_INNER_IO|Y_BOT_INNER_IO, &model, conns.dest_y)) {
|
||||||
for (i = 0;; i++) {
|
struct swchain_conns conns2;
|
||||||
conn_idx = fpga_conn_dest(&model, P46_y, P46_x, tmp_str, i);
|
|
||||||
if (conn_idx == NO_CONN)
|
printf("conn chain_size %i connpt_o %i num_dests %i i %i y %i x %i str %s\n",
|
||||||
break;
|
conns.chain.chain_size, conns.connpt_dest_start,
|
||||||
conn_to_str = fpga_conn_to(&model, P46_y, P46_x,
|
conns.num_dests, conns.dest_i, conns.dest_y, conns.dest_x, conns.dest_str);
|
||||||
conn_idx, &conn_to_y, &conn_to_x);
|
|
||||||
printf(" %s goes to y%02i x%02i %s\n",
|
strcpy(tmp_str, conns.dest_str);
|
||||||
tmp_str, conn_to_y, conn_to_x, conn_to_str);
|
conns2.model = &model;
|
||||||
if (is_aty(Y_TOP_INNER_IO|Y_BOT_INNER_IO, &model, conn_to_y)) {
|
conns2.y = conns.dest_y;
|
||||||
rc = printf_switchtree(&model, conn_to_y,
|
conns2.x = conns.dest_x;
|
||||||
conn_to_x, conn_to_str, /*indent*/ 3);
|
conns2.start_switch = tmp_str;
|
||||||
if (rc) FAIL(rc);
|
while (fpga_switch_conns_enum(&conns2) != NO_CONN) {
|
||||||
|
if (is_atyx(YX_ROUTING_TILE, &model, conns2.dest_y, conns2.dest_x)) {
|
||||||
|
struct swchain_conns conns3;
|
||||||
|
|
||||||
|
printf("conn2 chain_size %i connpt_o %i num_dests %i i %i y %i x %i str %s\n",
|
||||||
|
conns2.chain.chain_size, conns2.connpt_dest_start,
|
||||||
|
conns2.num_dests, conns2.dest_i, conns2.dest_y, conns2.dest_x, conns2.dest_str);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
rc = printf_switchtree(&model, conns2.dest_y,
|
||||||
|
conns2.dest_x, conns2.dest_str, /*indent*/ 3);
|
||||||
|
if (rc) FAIL(rc);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
strcpy(tmp_str, conns2.dest_str);
|
||||||
|
conns3.model = &model;
|
||||||
|
conns3.y = conns2.dest_y;
|
||||||
|
conns3.x = conns2.dest_x;
|
||||||
|
conns3.start_switch = tmp_str;
|
||||||
|
while (fpga_switch_conns_enum(&conns3) != NO_CONN) {
|
||||||
|
printf("conn3 chain_size %i connpt_o %i num_dests %i i %i y %i x %i str %s\n",
|
||||||
|
conns3.chain.chain_size, conns3.connpt_dest_start,
|
||||||
|
conns3.num_dests, conns3.dest_i, conns3.dest_y, conns3.dest_x, conns3.dest_str);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#if 0
|
||||||
|
rc = printf_switchtree(&model, conns.dest_y,
|
||||||
|
conns.dest_x, conns.dest_str, /*indent*/ 3);
|
||||||
|
if (rc) FAIL(rc);
|
||||||
|
|
||||||
// go through whole tree of what is reachable from that
|
// go through whole tree of what is reachable from that
|
||||||
// switch, look for outside connections that reach to a routing tile
|
// switch, look for outside connections that reach to a routing tile
|
||||||
{ swidx_t idx;
|
chain.model = &model;
|
||||||
swidx_t* parents; int num_parents;
|
chain.y = conns.dest_y;
|
||||||
|
chain.x = conns.dest_x;
|
||||||
idx = fpga_switch_tree(&model, conn_to_y, conn_to_x,
|
chain.start_switch = conns.dest_str;
|
||||||
conn_to_str, SW_FROM, &parents, &num_parents);
|
chain.from_to = SW_FROM;
|
||||||
while (idx != NO_SWITCH) {
|
while (fpga_switch_chain_enum(&chain) != NO_SWITCH) {
|
||||||
printf("idx %i num_parents %i from %s to %s\n",
|
printf("idx %i chain_size %i from %s to %s\n",
|
||||||
idx, num_parents,
|
chain.chain[chain.chain_size-1], chain.chain_size-1,
|
||||||
fpga_switch_str(&model, conn_to_y, conn_to_x, idx, SW_FROM),
|
fpga_switch_str(&model, chain.y, chain.x, chain.chain[chain.chain_size-1], SW_FROM),
|
||||||
fpga_switch_str(&model, conn_to_y, conn_to_x, idx, SW_TO));
|
fpga_switch_str(&model, chain.y, chain.x, chain.chain[chain.chain_size-1], SW_TO));
|
||||||
idx = fpga_switch_tree(&model, conn_to_y, conn_to_x,
|
|
||||||
SW_TREE_NEXT, SW_FROM, &parents, &num_parents);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
sw_idx = fpga_switch_next(&model, P46_y, P46_x, sw_idx, SW_FROM);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("P48 O pinw %s\n", P48_dev->iob.pinw_in_O);
|
printf("P48 O pinw %s\n", P48_dev->iob.pinw_in_O);
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
202
control.c
202
control.c
|
@ -262,11 +262,11 @@ int fpga_set_lut(struct fpga_model* model, struct fpga_device* dev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fpga_conn_dest(struct fpga_model* model, int y, int x,
|
int fpga_connpt_lookup(struct fpga_model* model, int y, int x,
|
||||||
const char* name, int dest_idx)
|
const char* name, int* connpt_dests_o)
|
||||||
{
|
{
|
||||||
struct fpga_tile* tile;
|
struct fpga_tile* tile;
|
||||||
int i, rc, connpt_i, num_dests, conn_point_dests_o;
|
int i, rc, connpt_i, num_dests;
|
||||||
|
|
||||||
rc = strarray_find(&model->str, name, &connpt_i);
|
rc = strarray_find(&model->str, name, &connpt_i);
|
||||||
if (rc) FAIL(rc);
|
if (rc) FAIL(rc);
|
||||||
|
@ -278,22 +278,20 @@ int fpga_conn_dest(struct fpga_model* model, int y, int x,
|
||||||
if (i >= tile->num_conn_point_names)
|
if (i >= tile->num_conn_point_names)
|
||||||
FAIL(EINVAL);
|
FAIL(EINVAL);
|
||||||
|
|
||||||
conn_point_dests_o = tile->conn_point_names[i*2];
|
*connpt_dests_o = tile->conn_point_names[i*2];
|
||||||
if (i < tile->num_conn_point_names-1)
|
if (i < tile->num_conn_point_names-1)
|
||||||
num_dests = tile->conn_point_names[(i+1)*2] - conn_point_dests_o;
|
num_dests = tile->conn_point_names[(i+1)*2] - *connpt_dests_o;
|
||||||
else
|
else
|
||||||
num_dests = tile->num_conn_point_dests - conn_point_dests_o;
|
num_dests = tile->num_conn_point_dests - *connpt_dests_o;
|
||||||
if (dest_idx >= num_dests)
|
return num_dests;
|
||||||
return NO_CONN;
|
|
||||||
return conn_point_dests_o + dest_idx;
|
|
||||||
fail:
|
fail:
|
||||||
return NO_CONN;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NUM_CONN_DEST_BUFS 16
|
#define NUM_CONN_DEST_BUFS 16
|
||||||
#define CONN_DEST_BUF_SIZE 128
|
#define CONN_DEST_BUF_SIZE 128
|
||||||
|
|
||||||
const char* fpga_conn_to(struct fpga_model* model, int y, int x,
|
const char* fpga_conn_dest(struct fpga_model* model, int y, int x,
|
||||||
int connpt_dest_idx, int* dest_y, int* dest_x)
|
int connpt_dest_idx, int* dest_y, int* dest_x)
|
||||||
{
|
{
|
||||||
static char conn_dest_buf[NUM_CONN_DEST_BUFS][CONN_DEST_BUF_SIZE];
|
static char conn_dest_buf[NUM_CONN_DEST_BUFS][CONN_DEST_BUF_SIZE];
|
||||||
|
@ -346,7 +344,8 @@ fail:
|
||||||
return NO_SWITCH;
|
return NO_SWITCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
swidx_t fpga_switch_next(struct fpga_model* model, int y, int x, swidx_t last, int from_to)
|
static swidx_t fpga_switch_search(struct fpga_model* model, int y, int x,
|
||||||
|
swidx_t last, swidx_t search_beg, int from_to)
|
||||||
{
|
{
|
||||||
struct fpga_tile* tile;
|
struct fpga_tile* tile;
|
||||||
int connpt_o, name_i, i;
|
int connpt_o, name_i, i;
|
||||||
|
@ -357,7 +356,7 @@ swidx_t fpga_switch_next(struct fpga_model* model, int y, int x, swidx_t last, i
|
||||||
: SWITCH_TO(tile->switches[last]);
|
: SWITCH_TO(tile->switches[last]);
|
||||||
name_i = tile->conn_point_names[connpt_o*2+1];
|
name_i = tile->conn_point_names[connpt_o*2+1];
|
||||||
|
|
||||||
for (i = last+1; i < tile->num_switches; i++) {
|
for (i = search_beg; i < tile->num_switches; i++) {
|
||||||
connpt_o = (from_to == SW_FROM)
|
connpt_o = (from_to == SW_FROM)
|
||||||
? SWITCH_FROM(tile->switches[i])
|
? SWITCH_FROM(tile->switches[i])
|
||||||
: SWITCH_TO(tile->switches[i]);
|
: SWITCH_TO(tile->switches[i]);
|
||||||
|
@ -367,58 +366,16 @@ swidx_t fpga_switch_next(struct fpga_model* model, int y, int x, swidx_t last, i
|
||||||
return (i >= tile->num_switches) ? NO_SWITCH : i;
|
return (i >= tile->num_switches) ? NO_SWITCH : i;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_SW_PARENTS 32
|
swidx_t fpga_switch_next(struct fpga_model* model, int y, int x,
|
||||||
|
swidx_t last, int from_to)
|
||||||
swidx_t fpga_switch_tree(struct fpga_model* model, int y, int x,
|
|
||||||
const char* name, int from_to, swidx_t** parents, int* num_parents)
|
|
||||||
{
|
{
|
||||||
// the static 'parents' always contain the current
|
return fpga_switch_search(model, y, x, last, last+1, from_to);
|
||||||
// (last) member as their last element, which is
|
}
|
||||||
// not reported back as a parent.
|
|
||||||
static swidx_t s_parents[MAX_SW_PARENTS];
|
|
||||||
static int s_num_parents = 0;
|
|
||||||
|
|
||||||
swidx_t idx;
|
swidx_t fpga_switch_backtofirst(struct fpga_model* model, int y, int x,
|
||||||
|
swidx_t last, int from_to)
|
||||||
*parents = s_parents;
|
{
|
||||||
if (name != SW_TREE_NEXT) {
|
return fpga_switch_search(model, y, x, last, /*search_beg*/ 0, from_to);
|
||||||
idx = fpga_switch_first(model, y, x, name, from_to);
|
|
||||||
if (idx == NO_SWITCH) return NO_SWITCH;
|
|
||||||
s_parents[0] = idx;
|
|
||||||
s_num_parents = 1;
|
|
||||||
*num_parents = 0;
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
if (!s_num_parents) {
|
|
||||||
HERE();
|
|
||||||
return NO_SWITCH;
|
|
||||||
}
|
|
||||||
// first check whether there are children
|
|
||||||
idx = fpga_switch_first(model, y, x,
|
|
||||||
fpga_switch_str(model, y, x, s_parents[s_num_parents-1], !from_to),
|
|
||||||
from_to);
|
|
||||||
if (idx != NO_SWITCH) {
|
|
||||||
if (s_num_parents >= MAX_SW_PARENTS) {
|
|
||||||
HERE();
|
|
||||||
return NO_SWITCH;
|
|
||||||
}
|
|
||||||
s_parents[s_num_parents] = idx;
|
|
||||||
s_num_parents++;
|
|
||||||
*num_parents = s_num_parents - 1;
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
// then check whether there are more members at the same level
|
|
||||||
idx = fpga_switch_next(model, y, x, s_parents[s_num_parents-1],
|
|
||||||
from_to);
|
|
||||||
if (idx != NO_SWITCH) {
|
|
||||||
s_parents[s_num_parents-1] = idx;
|
|
||||||
*num_parents = s_num_parents - 1;
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
// and finally go one level up
|
|
||||||
} while (s_num_parents--); // post-decrement
|
|
||||||
return NO_SWITCH;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NUM_CONNPT_BUFS 16
|
#define NUM_CONNPT_BUFS 16
|
||||||
|
@ -476,3 +433,122 @@ void fpga_switch_disable(struct fpga_model* model, int y, int x,
|
||||||
{
|
{
|
||||||
YX_TILE(model, y, x)->switches[swidx] &= ~SWITCH_ON;
|
YX_TILE(model, y, x)->switches[swidx] &= ~SWITCH_ON;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fpga_switch_chain_enum(struct sw_chain* chain)
|
||||||
|
{
|
||||||
|
swidx_t idx;
|
||||||
|
|
||||||
|
if (chain->start_switch != SW_CHAIN_NEXT) {
|
||||||
|
idx = fpga_switch_first(chain->model, chain->y, chain->x,
|
||||||
|
chain->start_switch, chain->from_to);
|
||||||
|
chain->start_switch = SW_CHAIN_NEXT;
|
||||||
|
if (idx == NO_SWITCH) {
|
||||||
|
chain->chain_size = 0;
|
||||||
|
return NO_SWITCH;
|
||||||
|
}
|
||||||
|
chain->chain[0] = idx;
|
||||||
|
chain->chain_size = 1;
|
||||||
|
|
||||||
|
// at every level, the first round returns all members
|
||||||
|
// at that level, then the second round tries to go
|
||||||
|
// one level down for each member. This sorts the
|
||||||
|
// returned switches in a nice way.
|
||||||
|
chain->first_round = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!chain->chain_size) {
|
||||||
|
HERE(); goto internal_error;
|
||||||
|
}
|
||||||
|
if (chain->first_round) {
|
||||||
|
// first go through all members are present level
|
||||||
|
idx = fpga_switch_next(chain->model, chain->y, chain->x,
|
||||||
|
chain->chain[chain->chain_size-1], chain->from_to);
|
||||||
|
if (idx != NO_SWITCH) {
|
||||||
|
chain->chain[chain->chain_size-1] = idx;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// if there are no more, initiate the second round
|
||||||
|
// looking for children
|
||||||
|
chain->first_round = 0;
|
||||||
|
idx = fpga_switch_backtofirst(chain->model, chain->y, chain->x,
|
||||||
|
chain->chain[chain->chain_size-1], chain->from_to);
|
||||||
|
if (idx == NO_SWITCH) {
|
||||||
|
HERE(); goto internal_error;
|
||||||
|
}
|
||||||
|
chain->chain[chain->chain_size-1] = idx;
|
||||||
|
}
|
||||||
|
// look for children
|
||||||
|
while (1) {
|
||||||
|
idx = fpga_switch_first(chain->model, chain->y, chain->x,
|
||||||
|
fpga_switch_str(chain->model, chain->y, chain->x,
|
||||||
|
chain->chain[chain->chain_size-1], !chain->from_to),
|
||||||
|
chain->from_to);
|
||||||
|
chain->chain[chain->chain_size-1] = fpga_switch_next(
|
||||||
|
chain->model, chain->y, chain->x,
|
||||||
|
chain->chain[chain->chain_size-1], chain->from_to);
|
||||||
|
if (idx != NO_SWITCH) {
|
||||||
|
if (chain->chain_size >= MAX_SW_CHAIN_SIZE) {
|
||||||
|
HERE(); goto internal_error;
|
||||||
|
}
|
||||||
|
chain->first_round = 1; // back to first round at new level
|
||||||
|
chain->chain[chain->chain_size] = idx;
|
||||||
|
chain->chain_size++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
while (chain->chain[chain->chain_size-1] == NO_SWITCH) {
|
||||||
|
if (chain->chain_size <= 1) {
|
||||||
|
chain->chain_size = 0;
|
||||||
|
return NO_SWITCH;
|
||||||
|
}
|
||||||
|
chain->chain_size--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal_error:
|
||||||
|
chain->chain_size = 0;
|
||||||
|
return NO_SWITCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fpga_switch_conns_enum(struct swchain_conns* conns)
|
||||||
|
{
|
||||||
|
const char* end_of_chain_str;
|
||||||
|
|
||||||
|
if (conns->start_switch != SW_CHAIN_NEXT) {
|
||||||
|
conns->chain.model = conns->model;
|
||||||
|
conns->chain.y = conns->y;
|
||||||
|
conns->chain.x = conns->x;
|
||||||
|
conns->chain.start_switch = conns->start_switch;
|
||||||
|
conns->chain.from_to = SW_FROM;
|
||||||
|
|
||||||
|
conns->start_switch = SW_CHAIN_NEXT;
|
||||||
|
conns->num_dests = 0;
|
||||||
|
conns->dest_i = 0;
|
||||||
|
}
|
||||||
|
else if (!conns->chain.chain_size) { HERE(); goto internal_error; }
|
||||||
|
|
||||||
|
while (conns->dest_i >= conns->num_dests) {
|
||||||
|
fpga_switch_chain_enum(&conns->chain);
|
||||||
|
if (conns->chain.chain_size == 0)
|
||||||
|
return NO_CONN;
|
||||||
|
end_of_chain_str = fpga_switch_str(conns->model,
|
||||||
|
conns->y, conns->x,
|
||||||
|
conns->chain.chain[conns->chain.chain_size-1],
|
||||||
|
SW_TO);
|
||||||
|
if (!end_of_chain_str) { HERE(); goto internal_error; }
|
||||||
|
conns->dest_i = 0;
|
||||||
|
conns->num_dests = fpga_connpt_lookup(conns->model,
|
||||||
|
conns->y, conns->x, end_of_chain_str,
|
||||||
|
&conns->connpt_dest_start);
|
||||||
|
if (conns->num_dests)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
conns->dest_str = fpga_conn_dest(conns->model, conns->y, conns->x,
|
||||||
|
conns->connpt_dest_start + conns->dest_i,
|
||||||
|
&conns->dest_y, &conns->dest_x);
|
||||||
|
if (!conns->dest_str) { HERE(); goto internal_error; }
|
||||||
|
conns->dest_i++;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
internal_error:
|
||||||
|
conns->chain.chain_size = 0;
|
||||||
|
return NO_CONN;
|
||||||
|
}
|
||||||
|
|
67
control.h
67
control.h
|
@ -31,10 +31,13 @@ enum { A6_LUT, B6_LUT, C6_LUT, D6_LUT };
|
||||||
int fpga_set_lut(struct fpga_model* model, struct fpga_device* dev,
|
int fpga_set_lut(struct fpga_model* model, struct fpga_device* dev,
|
||||||
int which_lut, const char* lut_str, int lut_len);
|
int which_lut, const char* lut_str, int lut_len);
|
||||||
|
|
||||||
// returns a connpt dest index, or -1 (NO_CONN) if no connection was found
|
// returns the number of outgoing connections for the
|
||||||
int fpga_conn_dest(struct fpga_model* model, int y, int x,
|
// connection point given with 'name', and the connection
|
||||||
const char* name, int dest_idx);
|
// point's first dest offset in connpt_dests_o.
|
||||||
const char* fpga_conn_to(struct fpga_model* model, int y, int x,
|
int fpga_connpt_lookup(struct fpga_model* model, int y, int x,
|
||||||
|
const char* name, int* connpt_dests_o);
|
||||||
|
|
||||||
|
const char* fpga_conn_dest(struct fpga_model* model, int y, int x,
|
||||||
int connpt_dest_idx, int* dest_y, int* dest_x);
|
int connpt_dest_idx, int* dest_y, int* dest_x);
|
||||||
|
|
||||||
typedef int swidx_t;
|
typedef int swidx_t;
|
||||||
|
@ -48,11 +51,8 @@ swidx_t fpga_switch_first(struct fpga_model* model, int y, int x,
|
||||||
const char* name, int from_to);
|
const char* name, int from_to);
|
||||||
swidx_t fpga_switch_next(struct fpga_model* model, int y, int x,
|
swidx_t fpga_switch_next(struct fpga_model* model, int y, int x,
|
||||||
swidx_t last, int from_to);
|
swidx_t last, int from_to);
|
||||||
|
swidx_t fpga_switch_backtofirst(struct fpga_model* model, int y, int x,
|
||||||
#define SW_TREE_NEXT 0 // use for name
|
swidx_t last, int from_to);
|
||||||
// returns -1 (NO_SWITCH) when there are no more switches in the tree
|
|
||||||
swidx_t fpga_switch_tree(struct fpga_model* model, int y, int x,
|
|
||||||
const char* name, int from_to, swidx_t** parents, int* num_parents);
|
|
||||||
|
|
||||||
const char* fpga_switch_str(struct fpga_model* model, int y, int x,
|
const char* fpga_switch_str(struct fpga_model* model, int y, int x,
|
||||||
swidx_t swidx, int from_to);
|
swidx_t swidx, int from_to);
|
||||||
|
@ -64,3 +64,52 @@ void fpga_switch_enable(struct fpga_model* model, int y, int x,
|
||||||
swidx_t swidx);
|
swidx_t swidx);
|
||||||
void fpga_switch_disable(struct fpga_model* model, int y, int x,
|
void fpga_switch_disable(struct fpga_model* model, int y, int x,
|
||||||
swidx_t swidx);
|
swidx_t swidx);
|
||||||
|
|
||||||
|
#define SW_CHAIN_NEXT 0 // use for name
|
||||||
|
#define MAX_SW_CHAIN_SIZE 32
|
||||||
|
|
||||||
|
struct sw_chain
|
||||||
|
{
|
||||||
|
// start and recurring values:
|
||||||
|
struct fpga_model* model;
|
||||||
|
int y;
|
||||||
|
int x;
|
||||||
|
// start_switch will be set to SW_CHAIN_NEXT (0) after the first call
|
||||||
|
const char* start_switch;
|
||||||
|
int from_to;
|
||||||
|
|
||||||
|
// return values:
|
||||||
|
swidx_t chain[MAX_SW_CHAIN_SIZE];
|
||||||
|
int chain_size;
|
||||||
|
|
||||||
|
// internal:
|
||||||
|
int first_round;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns 0 if another switch is returned in chain, or
|
||||||
|
// NO_SWITCH (-1) if there is no other switch.
|
||||||
|
// chain_size set to 0 when there are no more switches in the tree
|
||||||
|
int fpga_switch_chain_enum(struct sw_chain* chain);
|
||||||
|
|
||||||
|
struct swchain_conns
|
||||||
|
{
|
||||||
|
// start and recurring values:
|
||||||
|
struct fpga_model* model;
|
||||||
|
int y;
|
||||||
|
int x;
|
||||||
|
// start_switch will be set to SW_CHAIN_NEXT (0) after first call
|
||||||
|
const char* start_switch;
|
||||||
|
|
||||||
|
// return values:
|
||||||
|
struct sw_chain chain;
|
||||||
|
int connpt_dest_start;
|
||||||
|
int num_dests;
|
||||||
|
int dest_i;
|
||||||
|
int dest_y;
|
||||||
|
int dest_x;
|
||||||
|
const char* dest_str;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns 0 if another connection is returned in conns, or
|
||||||
|
// NO_CONN (-1) if there is no other connection.
|
||||||
|
int fpga_switch_conns_enum(struct swchain_conns* conns);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user