From e12120fade8b4b07b63f2bab3a9873a5b4e8013b Mon Sep 17 00:00:00 2001 From: Markus Koch Date: Sun, 16 Jun 2019 21:27:42 +0200 Subject: [PATCH] Start implementing Kousaten --- sw/kousaten/fdef/16x16.fdef | 4 ++ sw/kousaten/src/fpga_cell.c | 86 ++++++++++++++++++++++++++++++ sw/kousaten/src/fpga_cell.h | 38 +++++++++++++ sw/kousaten/src/fpga_cell_lut34.c | 15 ++++++ sw/kousaten/src/fpga_cell_lut34.h | 28 ++++++++++ sw/kousaten/src/fpga_cell_none.c | 15 ++++++ sw/kousaten/src/fpga_cell_none.h | 12 +++++ sw/kousaten/src/fpga_fdef_loader.c | 75 ++++++++++++++++++++++++++ sw/kousaten/src/fpga_fdef_loader.h | 11 ++++ sw/kousaten/src/fpga_global.c | 33 ++++++++++++ sw/kousaten/src/fpga_global.h | 17 ++++++ sw/kousaten/src/main.c | 22 +++++++- 12 files changed, 354 insertions(+), 2 deletions(-) create mode 100644 sw/kousaten/fdef/16x16.fdef create mode 100644 sw/kousaten/src/fpga_cell.c create mode 100644 sw/kousaten/src/fpga_cell.h create mode 100644 sw/kousaten/src/fpga_cell_lut34.c create mode 100644 sw/kousaten/src/fpga_cell_lut34.h create mode 100644 sw/kousaten/src/fpga_cell_none.c create mode 100644 sw/kousaten/src/fpga_cell_none.h create mode 100644 sw/kousaten/src/fpga_fdef_loader.c create mode 100644 sw/kousaten/src/fpga_fdef_loader.h create mode 100644 sw/kousaten/src/fpga_global.c create mode 100644 sw/kousaten/src/fpga_global.h diff --git a/sw/kousaten/fdef/16x16.fdef b/sw/kousaten/fdef/16x16.fdef new file mode 100644 index 0000000..e1f8cb2 --- /dev/null +++ b/sw/kousaten/fdef/16x16.fdef @@ -0,0 +1,4 @@ +PLLLL] +[LLLL] +[LLLL] +[LLLL diff --git a/sw/kousaten/src/fpga_cell.c b/sw/kousaten/src/fpga_cell.c new file mode 100644 index 0000000..e578c90 --- /dev/null +++ b/sw/kousaten/src/fpga_cell.c @@ -0,0 +1,86 @@ +#include "fpga_cell.h" +#include "fpga_global.h" +#include + +void fpga_cell_init(struct fpga_cell *fpga_cell, + enum fpga_cell_type fpga_cell_type) +{ + int i; + + for (i = 0; i < FPGA_CELL_CONNECTION_COUNT; ++i) { + fpga_cell->cell_connections[i] = NULL; + } + + fpga_cell->type = fpga_cell_type; + + report(LL_DEBUG, + "Initialized cell of type %d at %p.", + fpga_cell_type, fpga_cell); +} + +enum fpga_cell_position fpga_cell_connection_opposing(enum fpga_cell_position position) +{ + switch (position) { + case LEFT: + return RIGHT; + case RIGHT: + return LEFT; + case TOP: + return BOTTOM; + case BOTTOM: + return TOP; + default: + report(LL_ERROR, + "Internal error: Requested opposite of invalid position %d.", + position); + return LEFT; + } +} + +/** + * @brief fpga_cell_connect Connect to the of + * @param fpga_cell + * @param target_cell + * @param position + * @return 0 on success, -1 on failure + */ +int fpga_cell_connect(struct fpga_cell *fpga_cell, + struct fpga_cell *target_cell, + enum fpga_cell_position position) +{ + if (target_cell->cell_connections[position] || + fpga_cell->cell_connections[fpga_cell_connection_opposing(position)]) { + report(LL_WARNING, + "Tried to connect cell %p to pos %d of %p, even though a connection already exists for a least one of them.", + fpga_cell, target_cell, position); + errno = -ECONN; + return -1; + } + + target_cell->cell_connections[position] = fpga_cell; + fpga_cell->cell_connections[fpga_cell_connection_opposing(position)] = target_cell; + + report(LL_DEBUG, + "Connected cell %p to port %d of %p.", + fpga_cell, position, target_cell); + + return 0; +} + +/** + * @brief fpga_cell_get_far Get cell on the far of + * @param cell + * @param position + * @return + */ +struct fpga_cell *fpga_cell_get_far(struct fpga_cell *cell, + enum fpga_cell_position position) +{ + struct fpga_cell *next = cell; + + while (next->cell_connections[position]) { + next = next->cell_connections[position]; + } + + return next; +} diff --git a/sw/kousaten/src/fpga_cell.h b/sw/kousaten/src/fpga_cell.h new file mode 100644 index 0000000..aa6413b --- /dev/null +++ b/sw/kousaten/src/fpga_cell.h @@ -0,0 +1,38 @@ +#ifndef FPGA_CELL_H +#define FPGA_CELL_H + +enum fpga_cell_position { + LEFT = 0, + TOP, + RIGHT, + BOTTOM, + FPGA_CELL_CONNECTION_COUNT +}; + +enum fpga_cell_type { + FPGA_CELL_NONE = 0, + FPGA_CELL_WIRE, + FPGA_CELL_LUT34 +}; + +/* FPGA Logic cell base parameters */ +struct fpga_cell +{ + enum fpga_cell_type type; + + struct fpga_cell *cell_connections[FPGA_CELL_CONNECTION_COUNT]; + + /* Cell-specific data will be appended depending on the cell type. */ +}; + +void fpga_cell_init(struct fpga_cell *fpga_cell, + enum fpga_cell_type fpga_cell_type); +int fpga_cell_connect(struct fpga_cell *fpga_cell, + struct fpga_cell *target_cell, + enum fpga_cell_position position); +struct fpga_cell *fpga_cell_get_far(struct fpga_cell *cell, + enum fpga_cell_position position); + +#define FPGA_TO_CELL(a) ((struct fpga_cell*) a) + +#endif // FPGA_CELL_H diff --git a/sw/kousaten/src/fpga_cell_lut34.c b/sw/kousaten/src/fpga_cell_lut34.c new file mode 100644 index 0000000..e7e46ac --- /dev/null +++ b/sw/kousaten/src/fpga_cell_lut34.c @@ -0,0 +1,15 @@ +#include "fpga_cell_lut34.h" +#include + +struct fpga_cell_lut34 *fpga_cell_lut_34_new() +{ + struct fpga_cell_lut34 *fpga_cell_lut_34; + + fpga_cell_lut_34 = malloc(sizeof(struct fpga_cell_lut34)); + if (fpga_cell_lut_34) { + fpga_cell_init(FPGA_TO_CELL(fpga_cell_lut_34), + FPGA_CELL_LUT34); + } + + return fpga_cell_lut_34; +} diff --git a/sw/kousaten/src/fpga_cell_lut34.h b/sw/kousaten/src/fpga_cell_lut34.h new file mode 100644 index 0000000..6fcf188 --- /dev/null +++ b/sw/kousaten/src/fpga_cell_lut34.h @@ -0,0 +1,28 @@ +#ifndef FPGA_CELL_LUT34_H +#define FPGA_CELL_LUT34_H + +#include "fpga_cell.h" + +enum lut_mode {LUT4, LUT3}; + +struct fpga_cell_lut34 { + struct fpga_cell base_cell; + + int sync; /* Register output on rising edge of clk */ + + int led_lut_in_enable; + int led_lut_out_enable; + + int lut_in_sel[4]; /* Input select */ + int drive_sel[4]; /* Which signal to drive onto each fabric line */ + int route_top_en[4]; /* Enable routing between top and main fabric */ + int route_left_en[4]; /* Enable routing between left and main fabric */ + + int LUT4; /* Look-up table for LUT-4 configuration */ + int LUT3[2]; /* Look-up tables for LUT-3 configuration */ + enum lut_mode lut_mode; /* Look-up table mode selection */ +}; + +struct fpga_cell_lut34 *fpga_cell_lut_34_new(); + +#endif // FPGA_CELL_LUT34_H diff --git a/sw/kousaten/src/fpga_cell_none.c b/sw/kousaten/src/fpga_cell_none.c new file mode 100644 index 0000000..0904b22 --- /dev/null +++ b/sw/kousaten/src/fpga_cell_none.c @@ -0,0 +1,15 @@ +#include "fpga_cell_none.h" +#include + +struct fpga_cell_none *fpga_cell_none_new() +{ + struct fpga_cell_none *fpga_cell_none; + + fpga_cell_none = malloc(sizeof(struct fpga_cell_none)); + if (fpga_cell_none) { + fpga_cell_init(FPGA_TO_CELL(fpga_cell_none), + FPGA_CELL_NONE); + } + + return fpga_cell_none; +} diff --git a/sw/kousaten/src/fpga_cell_none.h b/sw/kousaten/src/fpga_cell_none.h new file mode 100644 index 0000000..7d8c0e1 --- /dev/null +++ b/sw/kousaten/src/fpga_cell_none.h @@ -0,0 +1,12 @@ +#ifndef FPGA_CELL_NONE_H +#define FPGA_CELL_NONE_H + +#include "fpga_cell.h" + +struct fpga_cell_none { + struct fpga_cell base_cell; +}; + +struct fpga_cell_none *fpga_cell_none_new(); + +#endif // FPGA_CELL_NONE_H diff --git a/sw/kousaten/src/fpga_fdef_loader.c b/sw/kousaten/src/fpga_fdef_loader.c new file mode 100644 index 0000000..634db93 --- /dev/null +++ b/sw/kousaten/src/fpga_fdef_loader.c @@ -0,0 +1,75 @@ +#include "fpga_fdef_loader.h" +#include + +struct fpga_cell *fpga_fdef_loader_load(char *filename) +{ + FILE *fdef; + int c; + int line = 1; + int col = 1; + + struct fpga_cell *cell_left = NULL; + struct fpga_cell *cell_top = NULL; + struct fpga_cell *cell = NULL; + + report(LL_INFO, "Loading FDEF from %s...", filename); + + fdef = fopen(filename, "r"); + + if (!fdef) + return NULL; + + while ((c = fgetc(fdef)) != EOF) { + switch (c) { + case 'L': + cell = FPGA_TO_CELL(fpga_cell_lut_34_new()); + if (!cell) { + report(LL_CRITICAL, + "Out of memory when creating cell."); + return NULL; + } + break; + + case '\n': + col = 0; + line++; + break; + + default: + report(LL_ERROR, + "%s:%d:%d: Invalid cell type %c. Replacing with empty cell.", + filename, line, col, c); + /* fall-through */ + case ' ': + cell = FPGA_TO_CELL(fpga_cell_none_new()); + if (!cell) { + report(LL_CRITICAL, + "Out of memory when creating cell."); + return NULL; + } + break; + } + + if (c == '\n') { + cell_left = NULL; + cell_top = fpga_cell_get_far(cell, LEFT); + report(LL_DEBUG, ""); + + } else { + if (cell_left) + fpga_cell_connect(cell, cell_left, RIGHT); + if (cell_top) + fpga_cell_connect(cell, cell_top, BOTTOM); + + cell_left = cell; + if (cell_top) + cell_top = cell_top->cell_connections[RIGHT]; + } + + col++; + } + + fclose(fdef); + + return fpga_cell_get_far(fpga_cell_get_far(cell, LEFT), TOP); +} diff --git a/sw/kousaten/src/fpga_fdef_loader.h b/sw/kousaten/src/fpga_fdef_loader.h new file mode 100644 index 0000000..55007c0 --- /dev/null +++ b/sw/kousaten/src/fpga_fdef_loader.h @@ -0,0 +1,11 @@ +#ifndef FPGA_FDEF_LOADER_H +#define FPGA_FDEF_LOADER_H + +#include "fpga_global.h" +#include "fpga_cell.h" +#include "fpga_cell_lut34.h" +#include "fpga_cell_none.h" + +struct fpga_cell *fpga_fdef_loader_load(char *filename); + +#endif // FPGA_FDEF_LOADER_H diff --git a/sw/kousaten/src/fpga_global.c b/sw/kousaten/src/fpga_global.c new file mode 100644 index 0000000..c572d52 --- /dev/null +++ b/sw/kousaten/src/fpga_global.c @@ -0,0 +1,33 @@ +#include "fpga_global.h" +#include +#include +#include + +static int current_log_level = 100; + +static const char *ll_string[] = { + "\x1B[34m[D] ", + "\x1B[32m[I] ", + "\x1B[33m[W] ", + "\x1B[31m[E] ", + "\x1B[31m\x1B[1m[X] ", + "[?] " +}; + +enum log_level report(enum log_level log_level, const char *format, ...) +{ + va_list vargs; + + if (log_level > LL_COUNT) + log_level = LL_COUNT; + + if (log_level <= current_log_level) { + va_start(vargs, format); + fprintf(stderr, "%s", ll_string[log_level]); + vfprintf(stderr, format, vargs); + fprintf(stderr, "\x1B[0m\n"); + va_end(vargs); + } + + return log_level; +} diff --git a/sw/kousaten/src/fpga_global.h b/sw/kousaten/src/fpga_global.h new file mode 100644 index 0000000..5d0c78f --- /dev/null +++ b/sw/kousaten/src/fpga_global.h @@ -0,0 +1,17 @@ +#ifndef FPGA_GLOBAL_H +#define FPGA_GLOBAL_H + +#include + +enum log_level {LL_DEBUG = 0, + LL_INFO, + LL_WARNING, + LL_ERROR, + LL_CRITICAL, + LL_COUNT}; +enum log_level report(enum log_level log_level, const char *format, ...); + +/* Error codes */ +#define ECONN 1000 /* Tried to connect to already connected port */ + +#endif // FPGA_GLOBAL_H diff --git a/sw/kousaten/src/main.c b/sw/kousaten/src/main.c index 754935c..2c2288f 100644 --- a/sw/kousaten/src/main.c +++ b/sw/kousaten/src/main.c @@ -1,7 +1,25 @@ #include +#include "fpga_cell.h" +#include "fpga_fdef_loader.h" +#include "fpga_global.h" -int main() +int development_test_main(int argc, char *argv[]) { - printf("Hello World!\n"); + struct fpga_cell *entry_cell; + + entry_cell = fpga_fdef_loader_load("fdef/16x16.fdef"); + + if (!entry_cell) { + report(LL_CRITICAL, "Error loading FDEF.\n"); + return 1; + } + + report(LL_INFO, "FDEF loaded."); + return 0; } + +int main(int argc, char *argv[]) +{ + return development_test_main(argc, argv); +}