Compare commits

..

2 Commits
sw ... master

26 changed files with 51 additions and 1252 deletions

Binary file not shown.

Binary file not shown.

View File

@ -1,13 +1,13 @@
EESchema Schematic File Version 4
LIBS:ttl-fpga-cache
EELAYER 29 0
EELAYER 30 0
EELAYER END
$Descr A3 16535 11693
encoding utf-8
Sheet 2 3
Title "DISCRETE TTL FPGA"
Date "2019-05-31"
Rev "02L"
Rev "03L"
Comp "Markus Koch <markus@notsyncing.net>"
Comment1 "Logic Block"
Comment2 ""
@ -2125,19 +2125,6 @@ F 3 "" H 9100 6950 50 0001 C CNN
1 9100 6950
1 0 0 -1
$EndComp
$Comp
L 74xx_IEEE:74253 U?
U 1 1 5D7AF006
P 9300 6050
AR Path="/5D7AF006" Ref="U?" Part="1"
AR Path="/5D77FDBE/5D7AF006" Ref="U7" Part="1"
F 0 "U7" H 9650 6600 50 0000 C CNN
F 1 "74253" H 9700 6750 50 0000 C CNN
F 2 "Package_SO:SOIC-16_3.9x9.9mm_P1.27mm" H 9300 6050 50 0001 C CNN
F 3 "" H 9300 6050 50 0001 C CNN
1 9300 6050
1 0 0 -1
$EndComp
Wire Wire Line
8750 5800 8350 5800
Wire Wire Line
@ -2174,9 +2161,6 @@ Wire Wire Line
Wire Wire Line
8250 5900 8250 6600
Connection ~ 8250 6600
Wire Wire Line
8150 6000 8150 6500
Connection ~ 8150 6500
Wire Wire Line
8050 6100 8050 6400
Connection ~ 8050 6400
@ -2188,39 +2172,15 @@ Wire Wire Line
8750 6000 8150 6000
Wire Wire Line
8050 6100 8750 6100
Wire Wire Line
8750 6400 8050 6400
Wire Wire Line
8050 6400 8050 7950
Connection ~ 8050 7950
Wire Wire Line
8750 6500 8150 6500
Wire Wire Line
8250 6600 8250 7750
Connection ~ 8250 7750
Wire Wire Line
8250 6600 8750 6600
Wire Wire Line
8750 7750 8250 7750
Wire Wire Line
8150 6500 8150 7850
Connection ~ 8150 7850
Wire Wire Line
8150 7850 8150 8350
Wire Wire Line
8150 7850 8750 7850
8250 6600 8650 6600
Wire Wire Line
8750 7950 8050 7950
Wire Wire Line
8050 7950 8050 8250
Wire Wire Line
8250 8450 8750 8450
Wire Wire Line
8250 7750 8250 8450
Wire Wire Line
8150 8350 8750 8350
Wire Wire Line
8050 8250 8750 8250
Text Label 10600 5900 2 50 ~ 0
fabric0
$Comp
@ -2533,6 +2493,38 @@ Wire Notes Line
5300 5500 4850 5500
Text Notes 4900 5600 0 50 ~ 0
cfg[28..16]
$Comp
L 74xx_IEEE:74253 U?
U 1 1 5D7AF006
P 9300 6050
AR Path="/5D7AF006" Ref="U?" Part="1"
AR Path="/5D77FDBE/5D7AF006" Ref="U7" Part="1"
F 0 "U7" H 9650 6600 50 0000 C CNN
F 1 "74253" H 9700 6750 50 0000 C CNN
F 2 "Package_SO:SOIC-16_3.9x9.9mm_P1.27mm" H 9300 6050 50 0001 C CNN
F 3 "" H 9300 6050 50 0001 C CNN
1 9300 6050
1 0 0 -1
$EndComp
Wire Wire Line
8750 6500 8650 6500
Wire Wire Line
8050 6400 8750 6400
Wire Wire Line
8650 6500 8650 6600
Connection ~ 8650 6600
Wire Wire Line
8650 6600 8750 6600
Wire Wire Line
8050 8250 8750 8250
Wire Wire Line
8150 8350 8750 8350
Wire Wire Line
8250 8450 8750 8450
Wire Wire Line
8250 6600 8250 7750
Wire Wire Line
8250 7750 8750 7750
Wire Bus Line
13100 7850 13700 7850
Wire Bus Line
@ -2557,4 +2549,16 @@ Wire Bus Line
7750 1800 7750 4350
Wire Bus Line
5900 1800 5900 4350
Connection ~ 8250 7750
Wire Wire Line
8250 7750 8250 8450
Wire Wire Line
8150 6000 8150 7850
Wire Wire Line
8150 7850 8150 8350
Connection ~ 8150 7850
Wire Wire Line
8150 7850 8750 7850
Text Notes 10050 7250 0 50 ~ 0
SEL00 = CC\nSEL01 = Ab\nSEL10 = BB \nSEL11 = bA
$EndSCHEMATC

View File

@ -1,13 +1,13 @@
EESchema Schematic File Version 4
LIBS:ttl-fpga-cache
EELAYER 29 0
EELAYER 30 0
EELAYER END
$Descr A4 11693 8268
encoding utf-8
Sheet 3 3
Title "DISCRETE TTL FPGA"
Date "2019-05-31"
Rev "02L"
Rev "03L"
Comp "Markus Koch <markus@notsyncing.net>"
Comment1 "Logic Block"
Comment2 "single 4-input LUT / dual 3-input LUT"

View File

@ -1,13 +1,13 @@
EESchema Schematic File Version 4
LIBS:ttl-fpga-cache
EELAYER 29 0
EELAYER 30 0
EELAYER END
$Descr A4 11693 8268
encoding utf-8
Sheet 1 3
Title "DISCRETE TTL FPGA"
Date "2019-05-31"
Rev "02L"
Rev "03L"
Comp "Markus Koch <markus@notsyncing.net>"
Comment1 "PCB"
Comment2 ""

View File

@ -1,5 +0,0 @@
*.user
*~
Makefile
*.autosave
build-*

View File

@ -1,8 +0,0 @@
cmake_minimum_required(VERSION 2.8)
project(kousaten)
#set(CMAKE_BUILD_TYPE Release)
set(CMAKE_C_FLAGS "-Wall")
aux_source_directory(./src SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})

View File

@ -1,2 +0,0 @@
# TTL-FPGA Compiler *Kousaten*
Tool to generate bitstreams for the TTL-FPGA after manual synthesis and PNR.

View File

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

View File

@ -1 +0,0 @@
PL

View File

@ -1,9 +0,0 @@
#!/bin/bash
if [ $# -lt 2 ]; then
echo "Usage: $0 </dev/ttyX> <progfile>"
exit 1
fi
stty -F "$1" raw
cat "$2" > "$1"

View File

@ -1,56 +0,0 @@
#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 ascii)
{
int i;
char *buf = NULL;
FILE *bitstream = stdout;
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) {
if (ascii)
fprintf(bitstream, "%02X ", buf[j] & 0xFF);
else
fputc(buf[j] & 0xFF, bitstream);
}
if (ascii)
fprintf(bitstream, "\n");
free(buf);
}
return 0;
fail:
if (bitstream && (strcmp(filename, "-")))
fclose(bitstream);
return 1;
}

View File

@ -1,8 +0,0 @@
#ifndef FPGA_H
#define FPGA_H
#include "fpga_cell.h"
int fpga_generate_bitstream(struct fpga_chain *chain,
char *filename, int ascii);
#endif // FPGA_H

View File

@ -1,329 +0,0 @@
#include "fpga_cell.h"
#include "fpga_global.h"
#include "fpga_cell_lut34.h"
#include "fpga_cell_none.h"
#include "fpga_cell_wire.h"
#include <stdlib.h>
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_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_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_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_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 = 6,
.isp_generate_bitstream = fpga_cell_lut34_isp_generate_bitstream
},
{
.identifier = '\0',
.cell_new = NULL,
.get_next_isp = NULL,
.isp_length = 0,
.isp_generate_bitstream = fpga_cell_isp_generate_bitstream_dummy
}
};
void fpga_cell_init(struct fpga_cell *cell,
struct fpga_cell_type *cell_type)
{
int i;
for (i = 0; i < FPGA_CELL_CONNECTION_COUNT; ++i) {
cell->cell_connections[i] = NULL;
}
cell->type = cell_type;
//fpga_cell->get_next_isp = fpga_cell_get_next_isp_dummy;
report(LL_DEBUG,
"Initialized cell of type %d at %p.",
cell_type, 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;
}
/**
* @brief fpga_cell_get_next_isp Get the next cell in the ISP chain
* @param fpga_cell the current cell in the ISP chain
* @param isp_channel the current channel. This will be updated when calling this function!
* @return the next ISP cell
*/
struct fpga_cell *fpga_cell_get_next_isp_dummy(struct fpga_cell *cell,
enum fpga_isp_channel *isp_channel)
{
report(LL_CRITICAL,
"Internal error. Cell type %c does not implement get_next_isp!",
cell->type->identifier);
*isp_channel = FPGA_ISP_CHANNEL_ERROR;
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
* @return
*/
struct fpga_cell *fpga_cell_new(char identifier)
{
struct fpga_cell_type *cell_type = fpga_cell_list;
struct fpga_cell *cell = NULL;
while (cell_type->identifier) {
if (identifier == cell_type->identifier) {
cell = cell_type->cell_new();
if (!cell) {
report(LL_CRITICAL,
"Out of memory when creating cell.");
return NULL;
}
cell->type = cell_type;
report(LL_DEBUG,
"Created cell %p of type %c.",
cell, identifier);
return cell;
}
cell_type++;
}
report(LL_ERROR,
"Invalid cell type %c found in FDEF.",
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...");
if (entry->type->identifier != 'P') {
report(LL_CRITICAL,
"Entry cell must be of type P, was '%c'",
entry->type->identifier);
errno = EINVAL;
return NULL;
}
chain = calloc(sizeof (struct fpga_chain), 1);
if (!chain) {
report (LL_CRITICAL,
"Out of memory during ISP chain generation.");
errno = ENOMEM;
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,
&current_channel);
if (current_channel == FPGA_ISP_CHANNEL_ERROR) {
/* TODO: Clean up memory */
errno = ETYPE;
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 generation finished.");
return chain;
}
int fpga_cell_bitstream_set_bit(char *buffer, char *sbuffer,
int bit, int value) {
int byteno;
int bitno;
bit = 47 - bit;
bitno = 7 - (bit % 8);
byteno = bit / 8;
value = !!value; /* Make sure it's a proper boolean value */
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;
}
int fpga_cell_bitstream_set_bits(char *buffer, char *sbuffer,
int value, int nbits, int *mapping)
{
int i;
int ret = 0;
for (i = 0; i < nbits; ++i) {
ret = ret || fpga_cell_bitstream_set_bit(buffer, sbuffer,
mapping[i], value & (1 << i));
}
return ret;
}
int fpga_cell_bitstream_is_set(char *buffer, int bit)
{
int byteno;
int bitno;
bit = 47 - bit;
bitno = 7 - (bit % 8);
byteno = bit / 8;
return !!(buffer[byteno] & (1 << bitno));
}

View File

@ -1,67 +0,0 @@
#ifndef FPGA_CELL_H
#define FPGA_CELL_H
#include <stddef.h>
enum fpga_cell_position {
LEFT = 0,
TOP,
RIGHT,
BOTTOM,
FPGA_CELL_CONNECTION_COUNT
};
enum fpga_isp_channel {
FPGA_ISP_CHANNEL_NORMAL = 0,
FPGA_ISP_CHANNEL_BACK,
FPGA_ISP_CHANNEL_LFDN,
FPGA_ISP_CHANNEL_DNUP,
FPGA_ISP_CHANNEL_ERROR
};
struct fpga_cell_type
{
char identifier;
struct fpga_cell *(*cell_new)();
struct fpga_cell *(*get_next_isp)(struct fpga_cell *cell,
enum fpga_isp_channel *isp_channel);
unsigned long isp_length;
char *(*isp_generate_bitstream)(struct fpga_cell *cell);
};
/* FPGA Logic cell base parameters */
struct fpga_cell
{
struct fpga_cell_type *type;
struct fpga_cell *cell_connections[FPGA_CELL_CONNECTION_COUNT];
/* 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,
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);
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);
int fpga_cell_bitstream_set_bits(char *buffer, char *sbuffer,
int value, int nbits, int *mapping);
int fpga_cell_bitstream_is_set(char *buffer, int bit);
#endif // FPGA_CELL_H

View File

@ -1,300 +0,0 @@
#include "fpga_cell_lut34.h"
#include "fpga_global.h"
#include <stdlib.h>
#include <string.h>
#define LUTD_POSITION 16 /* First bit of LUTD cfg bits */
#define LUTD_BIT_COUNT 16 /* To be applied for any cfg no > 15 */
static int need_fix = 1;
/* LUT Definitions (correct offset, no fix must be applied) */
static int LUT4_BITMAP[16] = {
24, 25, 26, 27, 28, 29, 30, 31,
16, 17, 18, 19, 20, 21, 22, 23
};
static int LUT3_BITMAP[2][8] = {
{24, 25, 26, 27, 28, 29, 30, 31},
{16, 17, 18, 19, 20, 21, 22, 23}
};
/* LUT Config Definitions */
static int BIT_LUT_SYNC_N = 20;
static int BIT_LUT_SPLIT_N = 21;
/* 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}
};
/* LUT OUT MUX Definitions */
static int LUT_OUT_MUX[4][4] = {
{LUT_OUT_C, LUT_OUT_A, LUT_OUT_B, LUT_OUT_B_ASYNC},
{LUT_OUT_C, LUT_OUT_B_ASYNC, LUT_OUT_A, LUT_OUT_A},
{LUT_OUT_C, LUT_OUT_A, LUT_OUT_B, LUT_OUT_B_ASYNC},
{LUT_OUT_C, LUT_OUT_B_ASYNC, LUT_OUT_B, LUT_OUT_A}
};
static int LUT_OUT_BITMAP[2][2] = {
{27, 23},
{25, 30}
};
static int LUT_OUT_EN_N_BITMAP[4] = {
22, 26, 31, 24
};
/* Routing Definitions */
static int ROUTE_BITMAP[8] = {
3, 6, 4, 0, /* Left */
5, 1, 2, 7, /* Top */
};
/* LED Definitions */
static int BIT_LED_LUT_IN = 28;
static int BIT_LED_LUT_OUT_N = 29; /* Low-active */
static inline int fpga_cell_lut34_is_driven(char drive_sel)
{
return (drive_sel != LUT_OUT_DC && drive_sel != LUT_OUT_Z);
}
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;
}
static int fpga_cell_lut34_lut_get_out_mux(int lut_group, char *ports)
{
int i;
int lut;
if (lut_group < 0 || lut_group > 2) {
report(LL_ERROR,
"Invalid LUT group requested.");
return -1;
}
lut = lut_group * 2;
ports = ports + lut;
for (i = 0; i < 4; ++i) {
if (!fpga_cell_lut34_is_driven(ports[0]) ||
ports[0] == LUT_OUT_MUX[lut][i]) {
if (!fpga_cell_lut34_is_driven(ports[1]) ||
ports[1] == LUT_OUT_MUX[lut + 1][i])
return i;
}
}
return -1;
}
struct fpga_cell *fpga_cell_lut34_new()
{
struct fpga_cell_lut34 *fpga_cell_lut_34;
fpga_cell_lut_34 = malloc(sizeof(struct fpga_cell_lut34));
fpga_cell_lut_34->LUT3[0] = -1;
fpga_cell_lut_34->LUT3[1] = -1;
fpga_cell_lut_34->LUT4 = -1;
return FPGA_TO_CELL(fpga_cell_lut_34);
}
struct fpga_cell *fpga_cell_lut34_get_next_isp(struct fpga_cell *cell,
enum fpga_isp_channel *isp_channel)
{
switch (*isp_channel) {
case FPGA_ISP_CHANNEL_LFDN:
*isp_channel = FPGA_ISP_CHANNEL_NORMAL;
return cell->cell_connections[BOTTOM];
case FPGA_ISP_CHANNEL_NORMAL:
return cell->cell_connections[RIGHT];
case FPGA_ISP_CHANNEL_BACK:
return cell->cell_connections[LEFT];
default:
report(LL_ERROR,
"Unhandled ISP channel %d for LUT34.",
*isp_channel);
}
return NULL;
}
static void fix_bitfields(int *bitmap, int count)
{
int i;
for (i = 0; i < count; ++i) {
if (bitmap[i] >= LUTD_POSITION) {
bitmap[i] += LUTD_BIT_COUNT;
}
}
}
#define BS_SET_BIT(bitno, value, errmsg, ...)\
{if (fpga_cell_bitstream_set_bit(buf, sbuf, bitno, value)) {\
report(LL_ERROR, errmsg, ##__VA_ARGS__);\
errno = ERECONF;\
goto fail;\
}} (void)0
#define BS_SET_BITS(value, nbits, mapping, errmsg, ...) \
{if (fpga_cell_bitstream_set_bits(buf, sbuf, value, nbits, mapping)) {\
report(LL_ERROR, errmsg, ##__VA_ARGS__);\
errno = ERECONF;\
goto fail;\
}} (void)0
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 || !sbuf) {
report(LL_CRITICAL,
"Out of memory during bitstream generation.");
errno = ENOMEM;
goto fail;
}
/* Reposition cfg bits after LUTD cfg, cheap workaround to use the same
cfg names as the schematic does. */
if (need_fix) {
need_fix = 0;
for (i = 0; i < 4; ++i) {
fix_bitfields(LUT_IN_BITMAP[i], 3);
}
for (i = 0; i < 2; ++i) {
fix_bitfields(LUT_OUT_BITMAP[i], 2);
}
fix_bitfields(LUT_OUT_EN_N_BITMAP, 4);
fix_bitfields(ROUTE_BITMAP, 8);
fix_bitfields(&BIT_LED_LUT_IN, 1);
fix_bitfields(&BIT_LED_LUT_OUT_N, 1);
fix_bitfields(&BIT_LUT_SYNC_N, 1);
fix_bitfields(&BIT_LUT_SPLIT_N, 1);
}
/* LEDs */
BS_SET_BIT(BIT_LED_LUT_IN, 1,
"Couldn't set LUT in LED to %d.", 1);
BS_SET_BIT(BIT_LED_LUT_OUT_N, 0,
"Couldn't set LUT out LED to %d.", 0);
/* LUT input sel */
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;
}
BS_SET_BITS(temp, 3, LUT_IN_BITMAP[i], "Couldn't set LUT input sel for input %d.", i);
}
/* LUT output sel + enable */
for (i = 0; i < 2; ++i) {
temp = fpga_cell_lut34_lut_get_out_mux(i, lut34->drive_sel);
if (temp < 0) {
report(LL_ERROR,
"Invalid output mux sel '%c' selected for net %d on cell %p.",
lut34->drive_sel[i], i, cell);
errno = EINVAL;
goto fail;
}
BS_SET_BITS(temp, 2, LUT_OUT_BITMAP[i],
"Couldn't set LUT output sel %d for output %d.", temp, i);
}
for (i = 0; i < 4; ++i) {
temp = fpga_cell_lut34_is_driven(lut34->drive_sel[i]);
BS_SET_BIT(LUT_OUT_EN_N_BITMAP[i], !temp,
"Couldn't %s output for output %d.",
(!temp ? "enable" : "disabled"), i);
}
/* Routing */
for (i = 0; i < 8; ++i) {
BS_SET_BITS(lut34->route_en, 8, ROUTE_BITMAP,
"Couldn't set routing bitmap to 0x%X for cell %p.",
lut34->route_en, cell);
}
/* LUTD */
if (lut34->LUT4 > -1) {
BS_SET_BITS(lut34->LUT4, 16, LUT4_BITMAP,
"Error setting LUT4 data.");
BS_SET_BIT(BIT_LUT_SPLIT_N, 1, "Couldn't set LUT4 mode.");
}
for (i = 0; i < 2; ++i) {
if (lut34->LUT3[i] > -1) {
BS_SET_BITS(lut34->LUT3[i], 8, LUT3_BITMAP[i],
"Error setting LUT3[%d] data. Did you configure a LUT4 before?",
i);
BS_SET_BIT(BIT_LUT_SPLIT_N, 0, "Couldn't set LUT3-2 mode. Did you configure a LUT4 before?");
}
}
BS_SET_BIT(BIT_LUT_SYNC_N, !lut34->sync, "Couldn't %s synchronous mode.",
(lut34->sync ? "enabling" : "disabling"));
/* Basic check whether each bit has been configured */
for (i = 0; i < cell->type->isp_length; ++i) {
if ((sbuf[i] & 0xFF) != 255) {
report(LL_WARNING,
"Incomplete configuration for cell %p (byte %d: 0x%X).",
cell, i, sbuf[i] & 0xFF);
break;
}
}
report(LL_DEBUG, "Bitstream result for %p:", cell);
for (i = 0; i < 48; ++i) {
report(LL_DEBUG,
" %d: %d%s",
i,
fpga_cell_bitstream_is_set(buf, i),
(fpga_cell_bitstream_is_set(sbuf, i) ? "" : " (Z)"));
}
free(sbuf);
return buf;
fail:
if (buf)
free(buf);
if (sbuf)
free(sbuf);
return NULL;
}

View File

@ -1,61 +0,0 @@
#ifndef FPGA_CELL_LUT34_H
#define FPGA_CELL_LUT34_H
#include "fpga_cell.h"
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'
};
enum LUT_OUT_NAMES {
LUT_OUT_DC = '\0', /* Don't care, treated like Z */
LUT_OUT_Z = 'Z',
LUT_OUT_C = 'C',
LUT_OUT_A = 'A',
LUT_OUT_B = 'B',
LUT_OUT_B_ASYNC = 'b'
};
enum ROUTE_NAMES {
ROUTE_L0 = 0,
ROUTE_L1,
ROUTE_L2,
ROUTE_L3,
ROUTE_T0,
ROUTE_T1,
ROUTE_T2,
ROUTE_T3
};
struct fpga_cell_lut34 {
struct fpga_cell base_cell;
int led_lut_in_enable;
int led_lut_out_enable;
char lut_in_sel[4]; /* Input select */
char drive_sel[4]; /* Which signal to drive onto each fabric line */
int sync; /* Register output on rising edge of clk */
int route_en; /* Bitfield, Enable routing between {left, top} and main fabric */
int LUT4; /* Look-up table for LUT-4 configuration */
int LUT3[2]; /* Look-up tables for LUT-3 configuration */
};
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

View File

@ -1,20 +0,0 @@
#include "fpga_cell_none.h"
#include <stdlib.h>
#include "fpga_global.h"
struct fpga_cell *fpga_cell_none_new()
{
struct fpga_cell_none *fpga_cell_none;
fpga_cell_none = malloc(sizeof(struct fpga_cell_none));
return FPGA_TO_CELL(fpga_cell_none);
}
struct fpga_cell *fpga_cell_none_get_next_isp(struct fpga_cell *fpga_cell,
enum fpga_isp_channel *isp_channel)
{
report(LL_WARNING,
"ISP signal ran into empty cell. Terminating chain.");
return NULL;
}

View File

@ -1,14 +0,0 @@
#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 *fpga_cell_none_new();
struct fpga_cell *fpga_cell_none_get_next_isp(struct fpga_cell *fpga_cell,
enum fpga_isp_channel *isp_channel);
#endif // FPGA_CELL_NONE_H

View File

@ -1,48 +0,0 @@
#include "fpga_cell_wire.h"
#include <stdlib.h>
#include "fpga_global.h"
struct fpga_cell *fpga_cell_wire_new()
{
struct fpga_cell_wire *fpga_cell_wire;
fpga_cell_wire = malloc(sizeof(struct fpga_cell_wire));
return FPGA_TO_CELL(fpga_cell_wire);
}
struct fpga_cell *fpga_cell_wire_get_next_isp(struct fpga_cell *cell,
enum fpga_isp_channel *isp_channel)
{
switch (*isp_channel) {
case FPGA_ISP_CHANNEL_NORMAL:
switch (cell->type->identifier) {
case 'P':
return cell->cell_connections[RIGHT];
case ']':
*isp_channel = FPGA_ISP_CHANNEL_BACK;
return cell->cell_connections[LEFT];
default:
goto fail;
}
case FPGA_ISP_CHANNEL_BACK:
switch (cell->type->identifier) {
case 'P':
case '[':
*isp_channel = FPGA_ISP_CHANNEL_LFDN;
return cell->cell_connections[RIGHT];
}
default:
goto fail;
}
fail:
report(LL_ERROR,
"Entered wiring cell %c on invalid ISP channel %d.",
cell->type->identifier, *isp_channel);
*isp_channel = FPGA_ISP_CHANNEL_ERROR;
return NULL;
return NULL;
}

View File

@ -1,14 +0,0 @@
#ifndef FPGA_CELL_WIRE_H
#define FPGA_CELL_WIRE_H
#include "fpga_cell.h"
struct fpga_cell_wire {
struct fpga_cell base_cell;
};
struct fpga_cell *fpga_cell_wire_new();
struct fpga_cell *fpga_cell_wire_get_next_isp(struct fpga_cell *cell,
enum fpga_isp_channel *isp_channel);
#endif // FPGA_CELL_WIRE_H

View File

@ -1,60 +0,0 @@
#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 '\n':
col = 0;
line++;
break;
default:
cell = fpga_cell_new((char) c);
if (!cell) {
/* TODO: clean up existing cells */
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

@ -1,11 +0,0 @@
#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

@ -1,38 +0,0 @@
#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[31m\x1B[1m[X] ",
"\x1B[31m[E] ",
"\x1B[33m[W] ",
"\x1B[32m[I] ",
"\x1B[34m[D] ",
"[?] "
};
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;
}
void set_log_level(enum log_level log_level)
{
current_log_level = log_level;
}

View File

@ -1,20 +0,0 @@
#ifndef FPGA_GLOBAL_H
#define FPGA_GLOBAL_H
#include <errno.h>
enum log_level {LL_CRITICAL = 0,
LL_ERROR,
LL_WARNING,
LL_INFO,
LL_DEBUG,
LL_COUNT};
enum log_level report(enum log_level log_level, const char *format, ...);
void set_log_level(enum log_level log_level);
/* Error codes */
#define ECONN 1000 /* Tried to connect to already connected port */
#define ETYPE 1001 /* Tried an operation on a cell that does not support it */
#define ERECONF 1100 /* Tried to set a configuration bit to multiple values */
#endif // FPGA_GLOBAL_H

View File

@ -1,130 +0,0 @@
#include <stdio.h>
#include "fpga_cell.h"
#include "fpga_fdef_loader.h"
#include "fpga_global.h"
#include "fpga.h"
#include "unistd.h"
#include "string.h"
#include "fpga_cell_lut34.h" /* For testing purposes only */
#define E_FDEF 1
#define E_BITSTREAM 2
static void test_design_cell_ripple(struct fpga_cell_lut34 *cell, int first, int last)
{
cell->lut_in_sel[0] = LUT_NET_F0; // Own state
cell->lut_in_sel[1] = LUT_NET_F2; // Feedback &-net -- just for fun
cell->lut_in_sel[2] = (first ? LUT_NET_T2 : LUT_NET_L1); // &-state of previous stages
cell->lut_in_sel[3] = LUT_NET_L0; // Previous state -- just for fun
cell->sync = 1;
cell->drive_sel[0] = 'A';
cell->drive_sel[1] = 'b';
cell->drive_sel[2] = (last ? 'b' : 'Z');
cell->drive_sel[3] = 'Z';
cell->route_en = (1 << ROUTE_L2);
cell->LUT3[0] = 0b01011010;
cell->LUT3[1] = 0b10100000;
}
// WARNING: Requires a >=4x4 FPGA FDEF!
static void test_design_counter(struct fpga_cell *entry_cell)
{
struct fpga_cell_lut34 *cell;
int i, j;
for (i = 0; i < 4; ++i) {
cell = ((struct fpga_cell_lut34 *)(entry_cell->cell_connections[RIGHT]));
for (j = 4 - i; j < 4; ++j) {
cell = (struct fpga_cell_lut34 *)cell->base_cell.cell_connections[BOTTOM];
}
test_design_cell_ripple(cell, 1, 0);
cell = (struct fpga_cell_lut34 *)cell->base_cell.cell_connections[RIGHT];
test_design_cell_ripple(cell, 0, 0);
cell = (struct fpga_cell_lut34 *)cell->base_cell.cell_connections[RIGHT];
test_design_cell_ripple(cell, 0, 0);
cell = (struct fpga_cell_lut34 *)cell->base_cell.cell_connections[RIGHT];
test_design_cell_ripple(cell, 0, 1);
}
}
int development_test_main(int argc, char *argv[])
{
struct fpga_cell *entry_cell;
struct fpga_chain *chain;
int opt;
char *fdef_filename = "fdef/4x4.fdef";
char *kst_filename = "-";
char *bitstream_filename = "-";
int bitstream_ascii = 0;
set_log_level(LL_DEBUG);
while((opt = getopt(argc, argv, "f:i:o:h")) != -1)
{
switch(opt)
{
case 'f':
fdef_filename = optarg;
break;
case 'i':
kst_filename = optarg;
report(LL_WARNING, "Input not yet implemented.");
break;
case 'o':
bitstream_filename = optarg;
break;
case 'h':
bitstream_ascii = 1;
break;
case ':':
case '?':
printf("Usage: %s [-f fdef] [-i input.kst] [-o output.bin] [-h]\n"
"Generate bitstreams for the TTL-FPGA.\n\n"
"When INPUT or OUTPUT is -, read/write standard input.\n\n"
" -f\tFDEF FPGA description file, default fdef/4x4.fdef\n"
" -i\tKousaten input file, default stdin\n"
" -o\tOutput file, default stdout\n"
" -h\tGenerate output as ASCII HEX\n",
argv[0]);
return 0;
default:
break;
}
}
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.");
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.");
test_design_counter(entry_cell);
if (fpga_generate_bitstream(chain, bitstream_filename, bitstream_ascii)) {
report(LL_ERROR, "Bitstream generation failed.");
return E_BITSTREAM;
}
report(LL_INFO, "Generated bitstream.");
return 0;
}
int main(int argc, char *argv[])
{
return development_test_main(argc, argv);
}