Start bitstream generator

This commit is contained in:
Markus Koch 2019-06-20 13:45:04 +02:00
parent a1d635889c
commit 5d86f8c7cf
7 changed files with 208 additions and 13 deletions

View File

@ -1,4 +1,52 @@
#include "fpga.h" #include "fpga.h"
#include "fpga_global.h" #include "fpga_global.h"
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <string.h>
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;
}

View File

@ -2,4 +2,7 @@
#define FPGA_H #define FPGA_H
#include "fpga_cell.h" #include "fpga_cell.h"
int fpga_generate_bitstream(struct fpga_chain *chain,
char *filename);
#endif // FPGA_H #endif // FPGA_H

View File

@ -10,37 +10,43 @@ static struct fpga_cell_type fpga_cell_list[] = {
.identifier = ' ', .identifier = ' ',
.cell_new = fpga_cell_none_new, .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 .isp_length = 0,
.isp_generate_bitstream = fpga_cell_isp_generate_bitstream_dummy
}, },
{ {
.identifier = '[', .identifier = '[',
.cell_new = fpga_cell_wire_new, .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 .isp_length = 0,
.isp_generate_bitstream = fpga_cell_isp_generate_bitstream_dummy
}, },
{ {
.identifier = ']', .identifier = ']',
.cell_new = fpga_cell_wire_new, .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 .isp_length = 0,
.isp_generate_bitstream = fpga_cell_isp_generate_bitstream_dummy
}, },
{ {
.identifier = 'P', .identifier = 'P',
.cell_new = fpga_cell_wire_new, .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 .isp_length = 0,
.isp_generate_bitstream = fpga_cell_isp_generate_bitstream_dummy
}, },
{ {
.identifier = 'L', .identifier = 'L',
.cell_new = fpga_cell_lut34_new, .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 .isp_length = 6,
.isp_generate_bitstream = fpga_cell_lut34_isp_generate_bitstream
}, },
{ {
.identifier = '\0', .identifier = '\0',
.cell_new = NULL, .cell_new = NULL,
.get_next_isp = 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; 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 <identifier> * @brief fpga_cell_new Create a new instance of type <identifier>
* @param identifier * @param identifier
@ -255,3 +275,24 @@ struct fpga_chain *fpga_isp_chain_new(struct fpga_cell *entry)
return chain; 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;
}

View File

@ -25,7 +25,8 @@ struct fpga_cell_type
struct fpga_cell *(*cell_new)(); struct fpga_cell *(*cell_new)();
struct fpga_cell *(*get_next_isp)(struct fpga_cell *cell, struct fpga_cell *(*get_next_isp)(struct fpga_cell *cell,
enum fpga_isp_channel *isp_channel); 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 */ /* 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); enum fpga_cell_position position);
struct fpga_cell *fpga_cell_get_next_isp_dummy(struct fpga_cell *fpga_cell, struct fpga_cell *fpga_cell_get_next_isp_dummy(struct fpga_cell *fpga_cell,
enum fpga_isp_channel *isp_channel); 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); struct fpga_cell *fpga_cell_new(char identifier);
#define FPGA_TO_CELL(a) ((struct fpga_cell*) a) #define FPGA_TO_CELL(a) ((struct fpga_cell*) a)
struct fpga_chain *fpga_isp_chain_new(struct fpga_cell *entry); 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 #endif // FPGA_CELL_H

View File

@ -1,6 +1,35 @@
#include "fpga_cell_lut34.h" #include "fpga_cell_lut34.h"
#include "fpga_global.h" #include "fpga_global.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
/* 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() 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; 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;
}

View File

@ -5,6 +5,22 @@
enum lut_mode {LUT4, LUT3}; 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_lut34 {
struct fpga_cell base_cell; struct fpga_cell base_cell;
@ -13,7 +29,7 @@ struct fpga_cell_lut34 {
int led_lut_in_enable; int led_lut_in_enable;
int led_lut_out_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 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_top_en[4]; /* Enable routing between top and main fabric */
int route_left_en[4]; /* Enable routing between left 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_new();
struct fpga_cell *fpga_cell_lut34_get_next_isp(struct fpga_cell *cell, struct fpga_cell *fpga_cell_lut34_get_next_isp(struct fpga_cell *cell,
enum fpga_isp_channel *isp_channel); enum fpga_isp_channel *isp_channel);
char *fpga_cell_lut34_isp_generate_bitstream(struct fpga_cell *cell);
#endif // FPGA_CELL_LUT34_H #endif // FPGA_CELL_LUT34_H

View File

@ -10,22 +10,35 @@
int development_test_main(int argc, char *argv[]) int development_test_main(int argc, char *argv[])
{ {
struct fpga_cell *entry_cell; struct fpga_cell *entry_cell;
struct fpga_chain *chain;
char *fdef_filename = "fdef/4x4.fdef";
char *bitstream_filename = "-";
set_log_level(LL_DEBUG); 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) { if (!entry_cell) {
report(LL_CRITICAL, "Error loading FDEF."); report(LL_CRITICAL, "Error loading FDEF.");
return E_FDEF; return E_FDEF;
} }
report(LL_INFO, "FDEF loaded."); 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."); report(LL_CRITICAL, "Critical error during bitstream generation.");
return E_BITSTREAM; 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; return 0;
} }