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;
|
||||
}
|
||||
|
||||
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);
|
||||
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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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.");
|
||||
|
Loading…
Reference in New Issue
Block a user