Start implementing Kousaten

sw
Markus Koch 2019-06-16 21:27:42 +02:00
parent 0072ed418b
commit e12120fade
12 changed files with 354 additions and 2 deletions

View File

@ -0,0 +1,4 @@
PLLLL]
[LLLL]
[LLLL]
[LLLL

View File

@ -0,0 +1,86 @@
#include "fpga_cell.h"
#include "fpga_global.h"
#include <stddef.h>
void fpga_cell_init(struct fpga_cell *fpga_cell,
enum fpga_cell_type fpga_cell_type)
{
int i;
for (i = 0; i < FPGA_CELL_CONNECTION_COUNT; ++i) {
fpga_cell->cell_connections[i] = NULL;
}
fpga_cell->type = fpga_cell_type;
report(LL_DEBUG,
"Initialized cell of type %d at %p.",
fpga_cell_type, fpga_cell);
}
enum fpga_cell_position fpga_cell_connection_opposing(enum fpga_cell_position position)
{
switch (position) {
case LEFT:
return RIGHT;
case RIGHT:
return LEFT;
case TOP:
return BOTTOM;
case BOTTOM:
return TOP;
default:
report(LL_ERROR,
"Internal error: Requested opposite of invalid position %d.",
position);
return LEFT;
}
}
/**
* @brief fpga_cell_connect Connect <fpga_cell> to the <position> of <target_cell>
* @param fpga_cell
* @param target_cell
* @param position
* @return 0 on success, -1 on failure
*/
int fpga_cell_connect(struct fpga_cell *fpga_cell,
struct fpga_cell *target_cell,
enum fpga_cell_position position)
{
if (target_cell->cell_connections[position] ||
fpga_cell->cell_connections[fpga_cell_connection_opposing(position)]) {
report(LL_WARNING,
"Tried to connect cell %p to pos %d of %p, even though a connection already exists for a least one of them.",
fpga_cell, target_cell, position);
errno = -ECONN;
return -1;
}
target_cell->cell_connections[position] = fpga_cell;
fpga_cell->cell_connections[fpga_cell_connection_opposing(position)] = target_cell;
report(LL_DEBUG,
"Connected cell %p to port %d of %p.",
fpga_cell, position, target_cell);
return 0;
}
/**
* @brief fpga_cell_get_far Get cell on the far <position> of <cell>
* @param cell
* @param position
* @return
*/
struct fpga_cell *fpga_cell_get_far(struct fpga_cell *cell,
enum fpga_cell_position position)
{
struct fpga_cell *next = cell;
while (next->cell_connections[position]) {
next = next->cell_connections[position];
}
return next;
}

View File

@ -0,0 +1,38 @@
#ifndef FPGA_CELL_H
#define FPGA_CELL_H
enum fpga_cell_position {
LEFT = 0,
TOP,
RIGHT,
BOTTOM,
FPGA_CELL_CONNECTION_COUNT
};
enum fpga_cell_type {
FPGA_CELL_NONE = 0,
FPGA_CELL_WIRE,
FPGA_CELL_LUT34
};
/* FPGA Logic cell base parameters */
struct fpga_cell
{
enum fpga_cell_type type;
struct fpga_cell *cell_connections[FPGA_CELL_CONNECTION_COUNT];
/* Cell-specific data will be appended depending on the cell type. */
};
void fpga_cell_init(struct fpga_cell *fpga_cell,
enum fpga_cell_type fpga_cell_type);
int fpga_cell_connect(struct fpga_cell *fpga_cell,
struct fpga_cell *target_cell,
enum fpga_cell_position position);
struct fpga_cell *fpga_cell_get_far(struct fpga_cell *cell,
enum fpga_cell_position position);
#define FPGA_TO_CELL(a) ((struct fpga_cell*) a)
#endif // FPGA_CELL_H

View File

@ -0,0 +1,15 @@
#include "fpga_cell_lut34.h"
#include <stdlib.h>
struct fpga_cell_lut34 *fpga_cell_lut_34_new()
{
struct fpga_cell_lut34 *fpga_cell_lut_34;
fpga_cell_lut_34 = malloc(sizeof(struct fpga_cell_lut34));
if (fpga_cell_lut_34) {
fpga_cell_init(FPGA_TO_CELL(fpga_cell_lut_34),
FPGA_CELL_LUT34);
}
return fpga_cell_lut_34;
}

View File

@ -0,0 +1,28 @@
#ifndef FPGA_CELL_LUT34_H
#define FPGA_CELL_LUT34_H
#include "fpga_cell.h"
enum lut_mode {LUT4, LUT3};
struct fpga_cell_lut34 {
struct fpga_cell base_cell;
int sync; /* Register output on rising edge of clk */
int led_lut_in_enable;
int led_lut_out_enable;
int 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 */
int LUT4; /* Look-up table for LUT-4 configuration */
int LUT3[2]; /* Look-up tables for LUT-3 configuration */
enum lut_mode lut_mode; /* Look-up table mode selection */
};
struct fpga_cell_lut34 *fpga_cell_lut_34_new();
#endif // FPGA_CELL_LUT34_H

View File

@ -0,0 +1,15 @@
#include "fpga_cell_none.h"
#include <stdlib.h>
struct fpga_cell_none *fpga_cell_none_new()
{
struct fpga_cell_none *fpga_cell_none;
fpga_cell_none = malloc(sizeof(struct fpga_cell_none));
if (fpga_cell_none) {
fpga_cell_init(FPGA_TO_CELL(fpga_cell_none),
FPGA_CELL_NONE);
}
return fpga_cell_none;
}

View File

@ -0,0 +1,12 @@
#ifndef FPGA_CELL_NONE_H
#define FPGA_CELL_NONE_H
#include "fpga_cell.h"
struct fpga_cell_none {
struct fpga_cell base_cell;
};
struct fpga_cell_none *fpga_cell_none_new();
#endif // FPGA_CELL_NONE_H

View File

@ -0,0 +1,75 @@
#include "fpga_fdef_loader.h"
#include <stdio.h>
struct fpga_cell *fpga_fdef_loader_load(char *filename)
{
FILE *fdef;
int c;
int line = 1;
int col = 1;
struct fpga_cell *cell_left = NULL;
struct fpga_cell *cell_top = NULL;
struct fpga_cell *cell = NULL;
report(LL_INFO, "Loading FDEF from %s...", filename);
fdef = fopen(filename, "r");
if (!fdef)
return NULL;
while ((c = fgetc(fdef)) != EOF) {
switch (c) {
case 'L':
cell = FPGA_TO_CELL(fpga_cell_lut_34_new());
if (!cell) {
report(LL_CRITICAL,
"Out of memory when creating cell.");
return NULL;
}
break;
case '\n':
col = 0;
line++;
break;
default:
report(LL_ERROR,
"%s:%d:%d: Invalid cell type %c. Replacing with empty cell.",
filename, line, col, c);
/* fall-through */
case ' ':
cell = FPGA_TO_CELL(fpga_cell_none_new());
if (!cell) {
report(LL_CRITICAL,
"Out of memory when creating cell.");
return NULL;
}
break;
}
if (c == '\n') {
cell_left = NULL;
cell_top = fpga_cell_get_far(cell, LEFT);
report(LL_DEBUG, "");
} else {
if (cell_left)
fpga_cell_connect(cell, cell_left, RIGHT);
if (cell_top)
fpga_cell_connect(cell, cell_top, BOTTOM);
cell_left = cell;
if (cell_top)
cell_top = cell_top->cell_connections[RIGHT];
}
col++;
}
fclose(fdef);
return fpga_cell_get_far(fpga_cell_get_far(cell, LEFT), TOP);
}

View File

@ -0,0 +1,11 @@
#ifndef FPGA_FDEF_LOADER_H
#define FPGA_FDEF_LOADER_H
#include "fpga_global.h"
#include "fpga_cell.h"
#include "fpga_cell_lut34.h"
#include "fpga_cell_none.h"
struct fpga_cell *fpga_fdef_loader_load(char *filename);
#endif // FPGA_FDEF_LOADER_H

View File

@ -0,0 +1,33 @@
#include "fpga_global.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
static int current_log_level = 100;
static const char *ll_string[] = {
"\x1B[34m[D] ",
"\x1B[32m[I] ",
"\x1B[33m[W] ",
"\x1B[31m[E] ",
"\x1B[31m\x1B[1m[X] ",
"[?] "
};
enum log_level report(enum log_level log_level, const char *format, ...)
{
va_list vargs;
if (log_level > LL_COUNT)
log_level = LL_COUNT;
if (log_level <= current_log_level) {
va_start(vargs, format);
fprintf(stderr, "%s", ll_string[log_level]);
vfprintf(stderr, format, vargs);
fprintf(stderr, "\x1B[0m\n");
va_end(vargs);
}
return log_level;
}

View File

@ -0,0 +1,17 @@
#ifndef FPGA_GLOBAL_H
#define FPGA_GLOBAL_H
#include <errno.h>
enum log_level {LL_DEBUG = 0,
LL_INFO,
LL_WARNING,
LL_ERROR,
LL_CRITICAL,
LL_COUNT};
enum log_level report(enum log_level log_level, const char *format, ...);
/* Error codes */
#define ECONN 1000 /* Tried to connect to already connected port */
#endif // FPGA_GLOBAL_H

View File

@ -1,7 +1,25 @@
#include <stdio.h>
#include "fpga_cell.h"
#include "fpga_fdef_loader.h"
#include "fpga_global.h"
int main()
int development_test_main(int argc, char *argv[])
{
printf("Hello World!\n");
struct fpga_cell *entry_cell;
entry_cell = fpga_fdef_loader_load("fdef/16x16.fdef");
if (!entry_cell) {
report(LL_CRITICAL, "Error loading FDEF.\n");
return 1;
}
report(LL_INFO, "FDEF loaded.");
return 0;
}
int main(int argc, char *argv[])
{
return development_test_main(argc, argv);
}