Start bitstream generator
This commit is contained in:
parent
a1d635889c
commit
5d86f8c7cf
@ -1,4 +1,52 @@
|
||||
#include "fpga.h"
|
||||
#include "fpga_global.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;
|
||||
}
|
||||
|
@ -2,4 +2,7 @@
|
||||
#define FPGA_H
|
||||
#include "fpga_cell.h"
|
||||
|
||||
int fpga_generate_bitstream(struct fpga_chain *chain,
|
||||
char *filename);
|
||||
|
||||
#endif // FPGA_H
|
||||
|
@ -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 <identifier>
|
||||
* @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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -1,6 +1,35 @@
|
||||
#include "fpga_cell_lut34.h"
|
||||
#include "fpga_global.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()
|
||||
{
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user