From 0834cf0c0de949112cd35f72a81354df1f5a70ae Mon Sep 17 00:00:00 2001 From: Markus Koch Date: Fri, 21 Jun 2019 20:31:34 +0200 Subject: [PATCH] Finish basic bitstream generator --- sw/kousaten/src/fpga_cell.c | 25 ++++ sw/kousaten/src/fpga_cell.h | 3 + sw/kousaten/src/fpga_cell_lut34.c | 192 ++++++++++++++++++++++++++++-- sw/kousaten/src/fpga_cell_lut34.h | 29 +++-- sw/kousaten/src/fpga_global.h | 1 + sw/kousaten/src/main.c | 2 + 6 files changed, 238 insertions(+), 14 deletions(-) diff --git a/sw/kousaten/src/fpga_cell.c b/sw/kousaten/src/fpga_cell.c index 72e5589..7a9dba8 100644 --- a/sw/kousaten/src/fpga_cell.c +++ b/sw/kousaten/src/fpga_cell.c @@ -296,3 +296,28 @@ int fpga_cell_bitstream_set_bit(char *buffer, char *sbuffer, return 0; } + +int fpga_cell_bitstream_set_bits(char *buffer, char *sbuffer, + int value, int nbits, int *mapping) +{ + int i; + int ret = 0; + + for (i = 0; i < nbits; ++i) { + ret = ret || fpga_cell_bitstream_set_bit(buffer, sbuffer, + mapping[i], value & (1 << i)); + } + + return ret; +} + +int fpga_cell_bitstream_is_set(char *buffer, int bit) +{ + int byteno; + int bitno; + + bitno = bit % 8; + byteno = bit / 8; + + return !!(buffer[byteno] & (1 << bitno)); +} diff --git a/sw/kousaten/src/fpga_cell.h b/sw/kousaten/src/fpga_cell.h index 97acdc6..bc57895 100644 --- a/sw/kousaten/src/fpga_cell.h +++ b/sw/kousaten/src/fpga_cell.h @@ -60,5 +60,8 @@ struct fpga_cell *fpga_cell_new(char identifier); struct fpga_chain *fpga_isp_chain_new(struct fpga_cell *entry); int fpga_cell_bitstream_set_bit(char *buffer, char *sbuffer, int bit, int value); +int fpga_cell_bitstream_set_bits(char *buffer, char *sbuffer, + int value, int nbits, int *mapping); +int fpga_cell_bitstream_is_set(char *buffer, int bit); #endif // FPGA_CELL_H diff --git a/sw/kousaten/src/fpga_cell_lut34.c b/sw/kousaten/src/fpga_cell_lut34.c index 9caf48c..5851b45 100644 --- a/sw/kousaten/src/fpga_cell_lut34.c +++ b/sw/kousaten/src/fpga_cell_lut34.c @@ -3,6 +3,25 @@ #include #include +#define LUTD_POSITION 16 /* First bit of LUTD cfg bits */ +#define LUTD_BIT_COUNT 16 /* To be applied for any cfg no > 15 */ + +static int need_fix = 1; + +/* LUT Definitions (correct offset, no fix must be applied) */ +static int LUT4_BITMAP[16] = { + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31 +}; +static int LUT3_BITMAP[2][8] = { + {16, 17, 18, 19, 20, 21, 22, 23}, + {24, 25, 26, 27, 28, 29, 30, 31} +}; + +/* LUT Config Definitions */ +static int BIT_LUT_SYNC = 20; +static int BIT_LUT_SPLIT_N = 21; + /* LUT IN MUX Definitions */ static char LUT_IN_MUX[4][8] = { {LUT_NET_F2, LUT_NET_L0, LUT_NET_L3, LUT_NET_L2, LUT_NET_L1, LUT_NET_F1, LUT_NET_F0, LUT_NET_T0}, @@ -17,6 +36,32 @@ static int LUT_IN_BITMAP[4][3] = { {16, 17, 18} }; +/* LUT OUT MUX Definitions */ +static int LUT_OUT_MUX[4][4] = { + {LUT_OUT_C, LUT_OUT_A, LUT_OUT_B, LUT_OUT_B_ASYNC}, + {LUT_OUT_C, LUT_OUT_B_ASYNC, LUT_OUT_B, LUT_OUT_A}, + {LUT_OUT_C, LUT_OUT_A, LUT_OUT_B, LUT_OUT_B_ASYNC}, + {LUT_OUT_C, LUT_OUT_B_ASYNC, LUT_OUT_B, LUT_OUT_A} +}; +static int LUT_OUT_BITMAP[4][2] = { + {27, 23}, + {27, 23}, /* Shared with 0 */ + {25, 30}, + {25, 30}, /* Shared with 2 */ +}; +static int LUT_OUT_EN_N_BITMAP[4] = { + 22, 26, 31, 24 +}; + +/* Routing Definitions */ +static int ROUTE_BITMAP[8] = { + 5, 1, 2, 0, + 3, 6, 4, 7 +}; + +/* LED Definitions */ +static int BIT_LED_LUT_IN = 28; +static int BIT_LED_LUT_OUT_N = 29; /* Low-active */ static int fpga_cell_lut34_lut_get_mux(int lut, char port) { int i; @@ -31,12 +76,29 @@ static int fpga_cell_lut34_lut_get_mux(int lut, char port) { return -1; } +static int fpga_cell_lut34_lut_get_out_mux(int lut, char port) { + int i; + + if (port == LUT_OUT_DC || port == LUT_OUT_Z) + return 255; + + for (i = 0; i < 4; ++i) { + if (LUT_OUT_MUX[lut][i] == port) + return i; + } + return -1; +} + struct fpga_cell *fpga_cell_lut34_new() { struct fpga_cell_lut34 *fpga_cell_lut_34; fpga_cell_lut_34 = malloc(sizeof(struct fpga_cell_lut34)); + fpga_cell_lut_34->LUT3[0] = -1; + fpga_cell_lut_34->LUT3[1] = -1; + fpga_cell_lut_34->LUT4 = -1; + return FPGA_TO_CELL(fpga_cell_lut_34); } @@ -60,6 +122,30 @@ struct fpga_cell *fpga_cell_lut34_get_next_isp(struct fpga_cell *cell, } +static void fix_bitfields(int *bitmap, int count) +{ + int i; + + for (i = 0; i < count; ++i) { + if (bitmap[i] >= LUTD_POSITION) { + bitmap[i] += LUTD_BIT_COUNT; + } + } +} + +#define BS_SET_BIT(bitno, value, errmsg, ...)\ +{if (fpga_cell_bitstream_set_bit(buf, sbuf, bitno, value)) {\ + report(LL_ERROR, errmsg, ##__VA_ARGS__);\ + errno = ERECONF;\ + goto fail;\ + }} +#define BS_SET_BITS(value, nbits, mapping, errmsg, ...) \ +{if (fpga_cell_bitstream_set_bits(buf, sbuf, value, nbits, mapping)) {\ + report(LL_ERROR, errmsg, ##__VA_ARGS__);\ + errno = ERECONF;\ + goto fail;\ + }} + char *fpga_cell_lut34_isp_generate_bitstream(struct fpga_cell *cell) { struct fpga_cell_lut34 *lut34 = (struct fpga_cell_lut34 *) cell; @@ -71,13 +157,39 @@ char *fpga_cell_lut34_isp_generate_bitstream(struct fpga_cell *cell) buf = calloc(cell->type->isp_length, sizeof(char)); sbuf = calloc(cell->type->isp_length, sizeof(char)); - if (!buf) { + if (!buf || !sbuf) { report(LL_CRITICAL, "Out of memory during bitstream generation."); errno = ENOMEM; goto fail; } + /* Reposition cfg bits after LUTD cfg, cheap workaround to use the same + cfg names as the schematic does. */ + if (need_fix) { + need_fix = 0; + for (i = 0; i < 4; ++i) { + fix_bitfields(LUT_IN_BITMAP[i], 3); + } + for (i = 0; i < 4; ++i) { + fix_bitfields(LUT_OUT_BITMAP[i], 2); + } + fix_bitfields(LUT_OUT_EN_N_BITMAP, 4); + fix_bitfields(ROUTE_BITMAP, 8); + fix_bitfields(&BIT_LED_LUT_IN, 1); + fix_bitfields(&BIT_LED_LUT_OUT_N, 1); + fix_bitfields(&BIT_LUT_SYNC, 1); + fix_bitfields(&BIT_LUT_SPLIT_N, 1); + } + + + /* LEDs */ + BS_SET_BIT(BIT_LED_LUT_IN, 1, + "Couldn't set LUT in LED to %d.", 1); + BS_SET_BIT(BIT_LED_LUT_OUT_N, 0, + "Couldn't set LUT out LED to %d.", 0); + + /* LUT input sel */ for (i = 0; i < 4; ++i) { temp = fpga_cell_lut34_lut_get_mux(i, lut34->lut_in_sel[i]); @@ -89,14 +201,80 @@ char *fpga_cell_lut34_isp_generate_bitstream(struct fpga_cell *cell) goto fail; } + BS_SET_BITS(temp, 3, LUT_IN_BITMAP[i], "Couldn't set LUT input sel for input %d.", i); } + /* LUT output sel + enable */ + for (i = 0; i < 4; ++i) { + temp = fpga_cell_lut34_lut_get_out_mux(i, lut34->drive_sel[i]); + + if (temp < 0) { + report(LL_ERROR, + "Invalid output mux sel '%c' selected for net %d on cell %p.", + lut34->drive_sel[i], i, cell); + errno = EINVAL; + goto fail; + } + + if (temp != 255) { + BS_SET_BITS(temp, 2, LUT_OUT_BITMAP[i], + "Couldn't set LUT output sel %d for output %d.", temp, i); + } + + } + for (i = 0; i < 4; ++i) { + temp = fpga_cell_bitstream_is_set(sbuf, LUT_OUT_BITMAP[i][0]); /* At some point, we set a specific output on this MUX */ + BS_SET_BIT(LUT_OUT_EN_N_BITMAP[i], 1, + "Couldn't %s output for output %d.", + (temp ? "enable" : "disabled"), i); + if (!temp) { + BS_SET_BITS(0, 2 , LUT_OUT_BITMAP[i], + "Couldn't set LUT output sel 0 for output %d (undriven by user logic).", i); + } + } + + /* Routing */ + for (i = 0; i < 8; ++i) { + BS_SET_BITS(lut34->route_en, 8, ROUTE_BITMAP, + "Couldn't set routing bitmap to 0x%X for cell %p.", + lut34->route_en, cell); + } + + /* LUTD */ + if (lut34->LUT4 > -1) { + BS_SET_BITS(lut34->LUT4, 16, LUT4_BITMAP, + "Error setting LUT4 data."); + BS_SET_BIT(BIT_LUT_SPLIT_N, 1, "Couldn't set LUT4 mode."); + } + for (i = 0; i < 2; ++i) { + if (lut34->LUT3[i] > -1) { + BS_SET_BITS(lut34->LUT3[i], 16, LUT3_BITMAP[i], + "Error setting LUT3[%d] data. Did you configure a LUT4 before?", + i); + BS_SET_BIT(BIT_LUT_SPLIT_N, 0, "Couldn't set LUT3-2 mode. Did you configure a LUT4 before?"); + } + } + BS_SET_BIT(BIT_LUT_SYNC, lut34->sync, "Couldn't %s synchronous mode.", + (lut34->sync ? "enabling" : "disabling")); + + /* Basic check whether each bit has been configured */ + for (i = 0; i < cell->type->isp_length; ++i) { + if ((sbuf[i] & 0xFF) != 255) { + report(LL_WARNING, + "Incomplete configuration for cell %p (byte %d: 0x%X).", + cell, i, sbuf[i] & 0xFF); + break; + } + } + + free(sbuf); + return buf; - fail: - if (buf) - free(buf); - if (sbuf) - free(sbuf); - return NULL; +fail: + if (buf) + free(buf); + if (sbuf) + free(sbuf); + return NULL; } diff --git a/sw/kousaten/src/fpga_cell_lut34.h b/sw/kousaten/src/fpga_cell_lut34.h index e4baa0d..ede13c6 100644 --- a/sw/kousaten/src/fpga_cell_lut34.h +++ b/sw/kousaten/src/fpga_cell_lut34.h @@ -3,8 +3,6 @@ #include "fpga_cell.h" -enum lut_mode {LUT4, LUT3}; - enum LUT_NET_NAMES { LUT_NET_DC = '\0', /* Dont' care */ LUT_NET_T0 = '0', @@ -21,22 +19,39 @@ enum LUT_NET_NAMES { LUT_NET_F3 = 'Z' }; +enum LUT_OUT_NAMES { + LUT_OUT_DC = '\0', /* Don't care, treated like Z */ + LUT_OUT_Z = 'Z', + LUT_OUT_C = 'C', + LUT_OUT_A = 'A', + LUT_OUT_B = 'B', + LUT_OUT_B_ASYNC = 'b' +}; + +enum ROUTE_NAMES { + ROUTE_L0 = 0, + ROUTE_L1, + ROUTE_L2, + ROUTE_L3, + ROUTE_T0, + ROUTE_T1, + ROUTE_T2, + ROUTE_T3 +}; + 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; char 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 sync; /* Register output on rising edge of clk */ + int route_en; /* Bitfield, Enable routing between {left, top} 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 *fpga_cell_lut34_new(); diff --git a/sw/kousaten/src/fpga_global.h b/sw/kousaten/src/fpga_global.h index 66e8b59..1e5e5ab 100644 --- a/sw/kousaten/src/fpga_global.h +++ b/sw/kousaten/src/fpga_global.h @@ -15,5 +15,6 @@ void set_log_level(enum log_level log_level); /* Error codes */ #define ECONN 1000 /* Tried to connect to already connected port */ #define ETYPE 1001 /* Tried an operation on a cell that does not support it */ +#define ERECONF 1100 /* Tried to set a configuration bit to multiple values */ #endif // FPGA_GLOBAL_H diff --git a/sw/kousaten/src/main.c b/sw/kousaten/src/main.c index ede8e1a..022b8e4 100644 --- a/sw/kousaten/src/main.c +++ b/sw/kousaten/src/main.c @@ -33,6 +33,8 @@ int development_test_main(int argc, char *argv[]) /* TODO: Configure application specific logic */ ((struct fpga_cell_lut34 *)(entry_cell->cell_connections[RIGHT]))->lut_in_sel[0] = 'A'; + ((struct fpga_cell_lut34 *)(entry_cell->cell_connections[RIGHT]))->drive_sel[0] = 'C'; + ((struct fpga_cell_lut34 *)(entry_cell->cell_connections[RIGHT]))->LUT4 = 0; if (fpga_generate_bitstream(chain, bitstream_filename)) { report(LL_ERROR, "Bitstream generation failed.");