#include "fpga_cell_lut34.h" #include "fpga_global.h" #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] = { 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; }