Finish basic bitstream generator
This commit is contained in:
parent
5d86f8c7cf
commit
0834cf0c0d
@ -296,3 +296,28 @@ int fpga_cell_bitstream_set_bit(char *buffer, char *sbuffer,
|
|||||||
|
|
||||||
return 0;
|
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));
|
||||||
|
}
|
||||||
|
@ -60,5 +60,8 @@ struct fpga_cell *fpga_cell_new(char identifier);
|
|||||||
struct fpga_chain *fpga_isp_chain_new(struct fpga_cell *entry);
|
struct fpga_chain *fpga_isp_chain_new(struct fpga_cell *entry);
|
||||||
int fpga_cell_bitstream_set_bit(char *buffer, char *sbuffer,
|
int fpga_cell_bitstream_set_bit(char *buffer, char *sbuffer,
|
||||||
int bit, int value);
|
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
|
#endif // FPGA_CELL_H
|
||||||
|
@ -3,6 +3,25 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.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 */
|
/* LUT IN MUX Definitions */
|
||||||
static char LUT_IN_MUX[4][8] = {
|
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},
|
{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}
|
{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) {
|
static int fpga_cell_lut34_lut_get_mux(int lut, char port) {
|
||||||
int i;
|
int i;
|
||||||
@ -31,12 +76,29 @@ static int fpga_cell_lut34_lut_get_mux(int lut, char port) {
|
|||||||
return -1;
|
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 *fpga_cell_lut34_new()
|
||||||
{
|
{
|
||||||
struct fpga_cell_lut34 *fpga_cell_lut_34;
|
struct fpga_cell_lut34 *fpga_cell_lut_34;
|
||||||
|
|
||||||
fpga_cell_lut_34 = malloc(sizeof(struct fpga_cell_lut34));
|
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);
|
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)
|
char *fpga_cell_lut34_isp_generate_bitstream(struct fpga_cell *cell)
|
||||||
{
|
{
|
||||||
struct fpga_cell_lut34 *lut34 = (struct fpga_cell_lut34 *) 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));
|
buf = calloc(cell->type->isp_length, sizeof(char));
|
||||||
sbuf = calloc(cell->type->isp_length, sizeof(char));
|
sbuf = calloc(cell->type->isp_length, sizeof(char));
|
||||||
|
|
||||||
if (!buf) {
|
if (!buf || !sbuf) {
|
||||||
report(LL_CRITICAL,
|
report(LL_CRITICAL,
|
||||||
"Out of memory during bitstream generation.");
|
"Out of memory during bitstream generation.");
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
goto fail;
|
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) {
|
for (i = 0; i < 4; ++i) {
|
||||||
temp = fpga_cell_lut34_lut_get_mux(i, lut34->lut_in_sel[i]);
|
temp = fpga_cell_lut34_lut_get_mux(i, lut34->lut_in_sel[i]);
|
||||||
|
|
||||||
@ -89,11 +201,77 @@ char *fpga_cell_lut34_isp_generate_bitstream(struct fpga_cell *cell)
|
|||||||
goto fail;
|
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;
|
return buf;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
if (buf)
|
if (buf)
|
||||||
free(buf);
|
free(buf);
|
||||||
if (sbuf)
|
if (sbuf)
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
|
|
||||||
#include "fpga_cell.h"
|
#include "fpga_cell.h"
|
||||||
|
|
||||||
enum lut_mode {LUT4, LUT3};
|
|
||||||
|
|
||||||
enum LUT_NET_NAMES {
|
enum LUT_NET_NAMES {
|
||||||
LUT_NET_DC = '\0', /* Dont' care */
|
LUT_NET_DC = '\0', /* Dont' care */
|
||||||
LUT_NET_T0 = '0',
|
LUT_NET_T0 = '0',
|
||||||
@ -21,22 +19,39 @@ enum LUT_NET_NAMES {
|
|||||||
LUT_NET_F3 = 'Z'
|
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_lut34 {
|
||||||
struct fpga_cell base_cell;
|
struct fpga_cell base_cell;
|
||||||
|
|
||||||
int sync; /* Register output on rising edge of clk */
|
|
||||||
|
|
||||||
int led_lut_in_enable;
|
int led_lut_in_enable;
|
||||||
int led_lut_out_enable;
|
int led_lut_out_enable;
|
||||||
|
|
||||||
char lut_in_sel[4]; /* Input select */
|
char lut_in_sel[4]; /* Input select */
|
||||||
int drive_sel[4]; /* Which signal to drive onto each fabric line */
|
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 sync; /* Register output on rising edge of clk */
|
||||||
int route_left_en[4]; /* Enable routing between left and main fabric */
|
int route_en; /* Bitfield, Enable routing between {left, top} and main fabric */
|
||||||
|
|
||||||
int LUT4; /* Look-up table for LUT-4 configuration */
|
int LUT4; /* Look-up table for LUT-4 configuration */
|
||||||
int LUT3[2]; /* Look-up tables for LUT-3 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();
|
struct fpga_cell *fpga_cell_lut34_new();
|
||||||
|
@ -15,5 +15,6 @@ void set_log_level(enum log_level log_level);
|
|||||||
/* Error codes */
|
/* Error codes */
|
||||||
#define ECONN 1000 /* Tried to connect to already connected port */
|
#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 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
|
#endif // FPGA_GLOBAL_H
|
||||||
|
@ -33,6 +33,8 @@ int development_test_main(int argc, char *argv[])
|
|||||||
|
|
||||||
/* TODO: Configure application specific logic */
|
/* 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]))->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)) {
|
if (fpga_generate_bitstream(chain, bitstream_filename)) {
|
||||||
report(LL_ERROR, "Bitstream generation failed.");
|
report(LL_ERROR, "Bitstream generation failed.");
|
||||||
|
Loading…
Reference in New Issue
Block a user