ttl-fpga/sw/kousaten/src/fpga_cell_lut34.c

301 lines
7.4 KiB
C

#include "fpga_cell_lut34.h"
#include "fpga_global.h"
#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] = {
24, 25, 26, 27, 28, 29, 30, 31,
16, 17, 18, 19, 20, 21, 22, 23
};
static int LUT3_BITMAP[2][8] = {
{24, 25, 26, 27, 28, 29, 30, 31},
{16, 17, 18, 19, 20, 21, 22, 23}
};
/* LUT Config Definitions */
static int BIT_LUT_SYNC_N = 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},
{LUT_NET_F0, LUT_NET_F1, LUT_NET_L1, LUT_NET_L2, LUT_NET_L3, LUT_NET_L0, LUT_NET_F2, LUT_NET_T1},
{LUT_NET_F3, LUT_NET_L0, LUT_NET_L3, LUT_NET_L2, LUT_NET_L1, LUT_NET_F1, LUT_NET_F0, LUT_NET_T2},
{LUT_NET_F0, LUT_NET_F1, LUT_NET_L1, LUT_NET_L2, LUT_NET_L3, LUT_NET_L0, LUT_NET_F3, LUT_NET_T3}
};
static int LUT_IN_BITMAP[4][3] = {
{12, 11, 19},
{ 8, 9, 10},
{15, 14, 13},
{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_A, 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[2][2] = {
{27, 23},
{25, 30}
};
static int LUT_OUT_EN_N_BITMAP[4] = {
22, 26, 31, 24
};
/* Routing Definitions */
static int ROUTE_BITMAP[8] = {
3, 6, 4, 0, /* Left */
5, 1, 2, 7, /* Top */
};
/* LED Definitions */
static int BIT_LED_LUT_IN = 28;
static int BIT_LED_LUT_OUT_N = 29; /* Low-active */
static inline int fpga_cell_lut34_is_driven(char drive_sel)
{
return (drive_sel != LUT_OUT_DC && drive_sel != LUT_OUT_Z);
}
static int fpga_cell_lut34_lut_get_mux(int lut, char port)
{
int i;
if (port == LUT_NET_DC)
return 0;
for (i = 0; i < 8; ++i) {
if (LUT_IN_MUX[lut][i] == port)
return i;
}
return -1;
}
static int fpga_cell_lut34_lut_get_out_mux(int lut_group, char *ports)
{
int i;
int lut;
if (lut_group < 0 || lut_group > 2) {
report(LL_ERROR,
"Invalid LUT group requested.");
return -1;
}
lut = lut_group * 2;
ports = ports + lut;
for (i = 0; i < 4; ++i) {
if (!fpga_cell_lut34_is_driven(ports[0]) ||
ports[0] == LUT_OUT_MUX[lut][i]) {
if (!fpga_cell_lut34_is_driven(ports[1]) ||
ports[1] == LUT_OUT_MUX[lut + 1][i])
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);
}
struct fpga_cell *fpga_cell_lut34_get_next_isp(struct fpga_cell *cell,
enum fpga_isp_channel *isp_channel)
{
switch (*isp_channel) {
case FPGA_ISP_CHANNEL_LFDN:
*isp_channel = FPGA_ISP_CHANNEL_NORMAL;
return cell->cell_connections[BOTTOM];
case FPGA_ISP_CHANNEL_NORMAL:
return cell->cell_connections[RIGHT];
case FPGA_ISP_CHANNEL_BACK:
return cell->cell_connections[LEFT];
default:
report(LL_ERROR,
"Unhandled ISP channel %d for LUT34.",
*isp_channel);
}
return NULL;
}
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;\
}} (void)0
#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;\
}} (void)0
char *fpga_cell_lut34_isp_generate_bitstream(struct fpga_cell *cell)
{
struct fpga_cell_lut34 *lut34 = (struct fpga_cell_lut34 *) cell;
char *buf = NULL;
char *sbuf = NULL;
int i;
int temp;
buf = calloc(cell->type->isp_length, sizeof(char));
sbuf = calloc(cell->type->isp_length, sizeof(char));
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 < 2; ++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_N, 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]);
if (temp < 0) {
report(LL_ERROR,
"Invalid input mux '%c' selected for mux %d on cell %p.",
lut34->lut_in_sel[i], i, cell);
errno = EINVAL;
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 < 2; ++i) {
temp = fpga_cell_lut34_lut_get_out_mux(i, lut34->drive_sel);
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;
}
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_lut34_is_driven(lut34->drive_sel[i]);
BS_SET_BIT(LUT_OUT_EN_N_BITMAP[i], !temp,
"Couldn't %s output for output %d.",
(!temp ? "enable" : "disabled"), 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], 8, 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_N, !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;
}
}
report(LL_DEBUG, "Bitstream result for %p:", cell);
for (i = 0; i < 48; ++i) {
report(LL_DEBUG,
" %d: %d%s",
i,
fpga_cell_bitstream_is_set(buf, i),
(fpga_cell_bitstream_is_set(sbuf, i) ? "" : " (Z)"));
}
free(sbuf);
return buf;
fail:
if (buf)
free(buf);
if (sbuf)
free(sbuf);
return NULL;
}