diff --git a/sw/kousaten/src/fpga.c b/sw/kousaten/src/fpga.c index 4b05b05..2c546e0 100644 --- a/sw/kousaten/src/fpga.c +++ b/sw/kousaten/src/fpga.c @@ -1,4 +1,52 @@ #include "fpga.h" #include "fpga_global.h" #include +#include +#include +int fpga_generate_bitstream(struct fpga_chain *chain, + char *filename) +{ + int i; + char *buf = NULL; + FILE *bitstream = stderr; + + if (strcmp(filename, "-")) { + bitstream = fopen(filename, "wb"); + } + if (!bitstream) { + report(LL_ERROR, + "Could not open output file '%s'.", + filename); + errno = EIO; + goto fail; + } + + report(LL_INFO, "Generating bitstream..."); + + for (i = chain->length - 1; i >= 0; --i) { + report(LL_DEBUG, + "Generating bitstream for cell %p (%c)...", + chain->head[i], chain->head[i]->type->identifier); + buf = chain->head[i]->type->isp_generate_bitstream(chain->head[i]); + if (!buf) { + report(LL_ERROR, + "Error during bitstream generation for cell %p.", + chain->head[i]); + errno = ETYPE; + goto fail; + } + for (int j = 0; j < chain->head[i]->type->isp_length; ++j) { + fprintf(bitstream, "%02X ", buf[j] & 0xFF); + } + fprintf(bitstream, "\n"); + free(buf); + } + + return 0; + +fail: + if (bitstream && (strcmp(filename, "-"))) + fclose(bitstream); + return 1; +} diff --git a/sw/kousaten/src/fpga.h b/sw/kousaten/src/fpga.h index 2812a9a..e347dd9 100644 --- a/sw/kousaten/src/fpga.h +++ b/sw/kousaten/src/fpga.h @@ -2,4 +2,7 @@ #define FPGA_H #include "fpga_cell.h" +int fpga_generate_bitstream(struct fpga_chain *chain, + char *filename); + #endif // FPGA_H diff --git a/sw/kousaten/src/fpga_cell.c b/sw/kousaten/src/fpga_cell.c index 871d9d7..72e5589 100644 --- a/sw/kousaten/src/fpga_cell.c +++ b/sw/kousaten/src/fpga_cell.c @@ -10,37 +10,43 @@ static struct fpga_cell_type fpga_cell_list[] = { .identifier = ' ', .cell_new = fpga_cell_none_new, .get_next_isp = fpga_cell_none_get_next_isp, - .isp_length = 0 + .isp_length = 0, + .isp_generate_bitstream = fpga_cell_isp_generate_bitstream_dummy }, { .identifier = '[', .cell_new = fpga_cell_wire_new, .get_next_isp = fpga_cell_wire_get_next_isp, - .isp_length = 0 + .isp_length = 0, + .isp_generate_bitstream = fpga_cell_isp_generate_bitstream_dummy }, { .identifier = ']', .cell_new = fpga_cell_wire_new, .get_next_isp = fpga_cell_wire_get_next_isp, - .isp_length = 0 + .isp_length = 0, + .isp_generate_bitstream = fpga_cell_isp_generate_bitstream_dummy }, { .identifier = 'P', .cell_new = fpga_cell_wire_new, .get_next_isp = fpga_cell_wire_get_next_isp, - .isp_length = 0 + .isp_length = 0, + .isp_generate_bitstream = fpga_cell_isp_generate_bitstream_dummy }, { .identifier = 'L', .cell_new = fpga_cell_lut34_new, .get_next_isp = fpga_cell_lut34_get_next_isp, - .isp_length = 1 // TODO:TBD + .isp_length = 6, + .isp_generate_bitstream = fpga_cell_lut34_isp_generate_bitstream }, { .identifier = '\0', .cell_new = NULL, .get_next_isp = NULL, - .isp_length = 0 + .isp_length = 0, + .isp_generate_bitstream = fpga_cell_isp_generate_bitstream_dummy } }; @@ -144,6 +150,20 @@ struct fpga_cell *fpga_cell_get_next_isp_dummy(struct fpga_cell *cell, return NULL; } +/** + * @brief isp_generate_bitstream_dummy + * @param cell + * @param buf + * @return + */ +char *fpga_cell_isp_generate_bitstream_dummy(struct fpga_cell *cell) +{ + report(LL_CRITICAL, + "Internal error. Cell type %c does not implement isp_generate_bitstream!", + cell->type->identifier); + return NULL; +} + /** * @brief fpga_cell_new Create a new instance of type * @param identifier @@ -255,3 +275,24 @@ struct fpga_chain *fpga_isp_chain_new(struct fpga_cell *entry) return chain; } + +int fpga_cell_bitstream_set_bit(char *buffer, char *sbuffer, + int bit, int value) { + int byteno; + int bitno; + + bitno = bit % 8; + byteno = bit / 8; + + if ((sbuffer[byteno] & (1 << bitno))) { /* Already set */ + return value == !((buffer[byteno] & (1 << bitno))); + } else { + sbuffer[byteno] |= (1 << bitno); + if (value) + buffer[byteno] |= (1 << bitno); + else + buffer[byteno] &= ~(1 << bitno); + } + + return 0; +} diff --git a/sw/kousaten/src/fpga_cell.h b/sw/kousaten/src/fpga_cell.h index 2ea4b0a..97acdc6 100644 --- a/sw/kousaten/src/fpga_cell.h +++ b/sw/kousaten/src/fpga_cell.h @@ -25,7 +25,8 @@ struct fpga_cell_type struct fpga_cell *(*cell_new)(); struct fpga_cell *(*get_next_isp)(struct fpga_cell *cell, enum fpga_isp_channel *isp_channel); - int isp_length; + unsigned long isp_length; + char *(*isp_generate_bitstream)(struct fpga_cell *cell); }; /* FPGA Logic cell base parameters */ @@ -52,9 +53,12 @@ struct fpga_cell *fpga_cell_get_far(struct fpga_cell *cell, enum fpga_cell_position position); struct fpga_cell *fpga_cell_get_next_isp_dummy(struct fpga_cell *fpga_cell, enum fpga_isp_channel *isp_channel); +char *fpga_cell_isp_generate_bitstream_dummy(struct fpga_cell *cell); struct fpga_cell *fpga_cell_new(char identifier); #define FPGA_TO_CELL(a) ((struct fpga_cell*) a) 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); #endif // FPGA_CELL_H diff --git a/sw/kousaten/src/fpga_cell_lut34.c b/sw/kousaten/src/fpga_cell_lut34.c index 89f16c6..9caf48c 100644 --- a/sw/kousaten/src/fpga_cell_lut34.c +++ b/sw/kousaten/src/fpga_cell_lut34.c @@ -1,6 +1,35 @@ #include "fpga_cell_lut34.h" #include "fpga_global.h" #include +#include + +/* 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} +}; + + +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; +} struct fpga_cell *fpga_cell_lut34_new() { @@ -30,3 +59,44 @@ struct fpga_cell *fpga_cell_lut34_get_next_isp(struct fpga_cell *cell, return NULL; } + +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) { + report(LL_CRITICAL, + "Out of memory during bitstream generation."); + errno = ENOMEM; + goto fail; + } + + 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; + } + + } + + return buf; + + fail: + if (buf) + free(buf); + if (sbuf) + free(sbuf); + return NULL; +} diff --git a/sw/kousaten/src/fpga_cell_lut34.h b/sw/kousaten/src/fpga_cell_lut34.h index ef7671f..e4baa0d 100644 --- a/sw/kousaten/src/fpga_cell_lut34.h +++ b/sw/kousaten/src/fpga_cell_lut34.h @@ -5,6 +5,22 @@ enum lut_mode {LUT4, LUT3}; +enum LUT_NET_NAMES { + LUT_NET_DC = '\0', /* Dont' care */ + LUT_NET_T0 = '0', + LUT_NET_T1 = '1', + LUT_NET_T2 = '2', + LUT_NET_T3 = '3', + LUT_NET_L0 = 'A', + LUT_NET_L1 = 'B', + LUT_NET_L2 = 'C', + LUT_NET_L3 = 'D', + LUT_NET_F0 = 'W', + LUT_NET_F1 = 'X', + LUT_NET_F2 = 'Y', + LUT_NET_F3 = 'Z' +}; + struct fpga_cell_lut34 { struct fpga_cell base_cell; @@ -13,7 +29,7 @@ struct fpga_cell_lut34 { int led_lut_in_enable; int led_lut_out_enable; - int 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 route_top_en[4]; /* Enable routing between top and main fabric */ int route_left_en[4]; /* Enable routing between left and main fabric */ @@ -26,5 +42,5 @@ struct fpga_cell_lut34 { struct fpga_cell *fpga_cell_lut34_new(); struct fpga_cell *fpga_cell_lut34_get_next_isp(struct fpga_cell *cell, enum fpga_isp_channel *isp_channel); - +char *fpga_cell_lut34_isp_generate_bitstream(struct fpga_cell *cell); #endif // FPGA_CELL_LUT34_H diff --git a/sw/kousaten/src/main.c b/sw/kousaten/src/main.c index 18e692d..ede8e1a 100644 --- a/sw/kousaten/src/main.c +++ b/sw/kousaten/src/main.c @@ -10,22 +10,35 @@ int development_test_main(int argc, char *argv[]) { struct fpga_cell *entry_cell; + struct fpga_chain *chain; + + char *fdef_filename = "fdef/4x4.fdef"; + char *bitstream_filename = "-"; set_log_level(LL_DEBUG); - entry_cell = fpga_fdef_loader_load("fdef/4x4.fdef"); - + entry_cell = fpga_fdef_loader_load(fdef_filename); if (!entry_cell) { report(LL_CRITICAL, "Error loading FDEF."); return E_FDEF; } - report(LL_INFO, "FDEF loaded."); - if (!fpga_isp_chain_new(entry_cell)) { + chain = fpga_isp_chain_new(entry_cell); + if (!chain) { report(LL_CRITICAL, "Critical error during bitstream generation."); return E_BITSTREAM; } + report(LL_INFO, "Chain loaded."); + + /* TODO: Configure application specific logic */ + ((struct fpga_cell_lut34 *)(entry_cell->cell_connections[RIGHT]))->lut_in_sel[0] = 'A'; + + if (fpga_generate_bitstream(chain, bitstream_filename)) { + report(LL_ERROR, "Bitstream generation failed."); + return E_BITSTREAM; + } + report(LL_INFO, "Generated bitstream."); return 0; }