diff --git a/sw/kousaten/src/fpga.c b/sw/kousaten/src/fpga.c index 2336497..4b05b05 100644 --- a/sw/kousaten/src/fpga.c +++ b/sw/kousaten/src/fpga.c @@ -1,23 +1,4 @@ #include "fpga.h" #include "fpga_global.h" +#include -int fpga_generate_bitstream(struct fpga_cell *cell) -{ - struct fpga_cell *current_cell = cell; - enum fpga_isp_channel current_channel = FPGA_ISP_CHANNEL_NORMAL; - - while (current_cell) { - report(LL_DEBUG, - "Adding %p (%c) to ISP chain.", - current_cell, current_cell->type->identifier); - current_cell = current_cell->type->get_next_isp(current_cell, - ¤t_channel); - if (current_channel == FPGA_ISP_CHANNEL_ERROR) - return 1; - } - - report(LL_INFO, - "Bitstream generation finished."); - - return 0; -} diff --git a/sw/kousaten/src/fpga.h b/sw/kousaten/src/fpga.h index 266be57..2812a9a 100644 --- a/sw/kousaten/src/fpga.h +++ b/sw/kousaten/src/fpga.h @@ -2,6 +2,4 @@ #define FPGA_H #include "fpga_cell.h" -int fpga_generate_bitstream(struct fpga_cell *cell); - #endif // FPGA_H diff --git a/sw/kousaten/src/fpga_cell.c b/sw/kousaten/src/fpga_cell.c index 5b24c71..ded54cf 100644 --- a/sw/kousaten/src/fpga_cell.c +++ b/sw/kousaten/src/fpga_cell.c @@ -3,37 +3,44 @@ #include "fpga_cell_lut34.h" #include "fpga_cell_none.h" #include "fpga_cell_wire.h" +#include static struct fpga_cell_type fpga_cell_list[] = { { .identifier = ' ', .cell_new = fpga_cell_none_new, - .get_next_isp = fpga_cell_none_get_next_isp + .get_next_isp = fpga_cell_none_get_next_isp, + .isp_length = 0 }, { .identifier = '[', .cell_new = fpga_cell_wire_new, - .get_next_isp = fpga_cell_wire_get_next_isp + .get_next_isp = fpga_cell_wire_get_next_isp, + .isp_length = 0 }, { .identifier = ']', .cell_new = fpga_cell_wire_new, - .get_next_isp = fpga_cell_wire_get_next_isp + .get_next_isp = fpga_cell_wire_get_next_isp, + .isp_length = 0 }, { .identifier = 'P', .cell_new = fpga_cell_wire_new, - .get_next_isp = fpga_cell_wire_get_next_isp + .get_next_isp = fpga_cell_wire_get_next_isp, + .isp_length = 0 }, { .identifier = 'L', .cell_new = fpga_cell_lut34_new, - .get_next_isp = fpga_cell_lut34_get_next_isp + .get_next_isp = fpga_cell_lut34_get_next_isp, + .isp_length = 1 // TODO:TBD }, { .identifier = '\0', .cell_new = NULL, - .get_next_isp = NULL + .get_next_isp = NULL, + .isp_length = 0 } }; @@ -169,3 +176,72 @@ struct fpga_cell *fpga_cell_new(char identifier) identifier); return NULL; } + +/** + * @brief fpga_isp_chain_new + * @param entry + * @return + */ +struct fpga_chain *fpga_isp_chain_new(struct fpga_cell *entry) +{ + struct fpga_cell *current_cell = entry; + enum fpga_isp_channel current_channel = FPGA_ISP_CHANNEL_NORMAL; + struct fpga_chain *chain; + + report(LL_INFO, + "Generating ISP chain..."); + + chain = calloc(sizeof (struct fpga_chain), 1); + if (!chain) { + report (LL_CRITICAL, + "Out of memory during ISP chain generation."); + return NULL; + } + + while (current_cell) { + if (current_channel == FPGA_ISP_CHANNEL_NORMAL && + current_cell->type->isp_length > 0) { + report(LL_DEBUG, + "Adding %p (%c) to ISP chain.", + current_cell, current_cell->type->identifier); + + if (!chain->head) { + chain->head = malloc(sizeof(chain->head)); + *(chain->head) = current_cell; + chain->length = 1; + } else { + chain->length++; + chain->head = realloc(chain->head, + sizeof(chain->head) * chain->length); + *(chain->head + chain->length - 1) = current_cell; + } + + } else { + report(LL_DEBUG, + "Using %p (%c) for ISP routing.", + current_cell, current_cell->type->identifier); + } + + current_cell = current_cell->type->get_next_isp(current_cell, + ¤t_channel); + if (current_channel == FPGA_ISP_CHANNEL_ERROR) { + /* TODO: Clean up memory */ + return NULL; + } + } + + report(LL_INFO, + "Added %d cells to ISP chain.", + chain->length); + + for (int i = 0; i < chain->length; ++i) { + report(LL_DEBUG, + " %4d = %p", + i, chain->head[i]); + } + + report(LL_INFO, + "ISP chain generated finished."); + + return chain; +} diff --git a/sw/kousaten/src/fpga_cell.h b/sw/kousaten/src/fpga_cell.h index 1c1cfb7..2ea4b0a 100644 --- a/sw/kousaten/src/fpga_cell.h +++ b/sw/kousaten/src/fpga_cell.h @@ -25,6 +25,7 @@ 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; }; /* FPGA Logic cell base parameters */ @@ -37,6 +38,11 @@ struct fpga_cell /* Cell-specific data will be appended depending on the cell type. */ }; +struct fpga_chain { + struct fpga_cell **head; + int length; +}; + void fpga_cell_init(struct fpga_cell *cell, struct fpga_cell_type *cell_type); int fpga_cell_connect(struct fpga_cell *fpga_cell, @@ -49,4 +55,6 @@ struct fpga_cell *fpga_cell_get_next_isp_dummy(struct fpga_cell *fpga_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); + #endif // FPGA_CELL_H diff --git a/sw/kousaten/src/fpga_cell_wire.c b/sw/kousaten/src/fpga_cell_wire.c index d4fefb4..4d7198b 100644 --- a/sw/kousaten/src/fpga_cell_wire.c +++ b/sw/kousaten/src/fpga_cell_wire.c @@ -33,23 +33,10 @@ struct fpga_cell *fpga_cell_wire_get_next_isp(struct fpga_cell *cell, *isp_channel = FPGA_ISP_CHANNEL_LFDN; return cell->cell_connections[RIGHT]; } + default: + goto fail; } - // switch (cell->type->identifier) { - // case ' ': - // report(LL_WARNING, - // "ISP signal ran into empty cell. Terminating chain."); - // return NULL; - // case ']': - // switch (*isp_channel) { - // case FPGA_ISP_CHANNEL_NORMAL: - // *isp_channel = FPGA_ISP_CHANNEL_BACK; - // return cell->cell_connections[LEFT]; - // default: - // goto fail; - // } - // } - fail: report(LL_ERROR, "Entered wiring cell %c on invalid ISP channel %d.", diff --git a/sw/kousaten/src/main.c b/sw/kousaten/src/main.c index 73ee8fe..46a8cb8 100644 --- a/sw/kousaten/src/main.c +++ b/sw/kousaten/src/main.c @@ -25,7 +25,7 @@ int development_test_main(int argc, char *argv[]) report(LL_INFO, "FDEF loaded."); - if (fpga_generate_bitstream(entry_cell)) { + if (!fpga_isp_chain_new(entry_cell)) { report(LL_CRITICAL, "Critical error during bitstream generation."); return E_BITSTREAM; }