Finish basic bitstream generator

sw
Markus Koch 2019-06-21 20:31:34 +02:00
parent 5d86f8c7cf
commit 0834cf0c0d
6 changed files with 238 additions and 14 deletions

View File

@ -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));
}

View File

@ -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

View File

@ -3,6 +3,25 @@
#include <stdlib.h>
#include <string.h>
#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;
}

View File

@ -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();

View File

@ -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

View File

@ -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.");