Start implementing Kousaten
This commit is contained in:
parent
0072ed418b
commit
e12120fade
4
sw/kousaten/fdef/16x16.fdef
Normal file
4
sw/kousaten/fdef/16x16.fdef
Normal file
@ -0,0 +1,4 @@
|
||||
PLLLL]
|
||||
[LLLL]
|
||||
[LLLL]
|
||||
[LLLL
|
86
sw/kousaten/src/fpga_cell.c
Normal file
86
sw/kousaten/src/fpga_cell.c
Normal 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;
|
||||
}
|
38
sw/kousaten/src/fpga_cell.h
Normal file
38
sw/kousaten/src/fpga_cell.h
Normal 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
|
15
sw/kousaten/src/fpga_cell_lut34.c
Normal file
15
sw/kousaten/src/fpga_cell_lut34.c
Normal 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;
|
||||
}
|
28
sw/kousaten/src/fpga_cell_lut34.h
Normal file
28
sw/kousaten/src/fpga_cell_lut34.h
Normal 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
|
15
sw/kousaten/src/fpga_cell_none.c
Normal file
15
sw/kousaten/src/fpga_cell_none.c
Normal 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;
|
||||
}
|
12
sw/kousaten/src/fpga_cell_none.h
Normal file
12
sw/kousaten/src/fpga_cell_none.h
Normal 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
|
75
sw/kousaten/src/fpga_fdef_loader.c
Normal file
75
sw/kousaten/src/fpga_fdef_loader.c
Normal 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);
|
||||
}
|
11
sw/kousaten/src/fpga_fdef_loader.h
Normal file
11
sw/kousaten/src/fpga_fdef_loader.h
Normal 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
|
33
sw/kousaten/src/fpga_global.c
Normal file
33
sw/kousaten/src/fpga_global.c
Normal 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;
|
||||
}
|
17
sw/kousaten/src/fpga_global.h
Normal file
17
sw/kousaten/src/fpga_global.h
Normal 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
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user