Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
Markus Koch | a19096942d | |
Markus Koch | 4424d762f7 |
Binary file not shown.
Binary file not shown.
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 ""
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
*.user
|
||||
*~
|
||||
Makefile
|
||||
*.autosave
|
||||
build-*
|
|
@ -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})
|
|
@ -1,2 +0,0 @@
|
|||
# TTL-FPGA Compiler *Kousaten*
|
||||
Tool to generate bitstreams for the TTL-FPGA after manual synthesis and PNR.
|
|
@ -1,4 +0,0 @@
|
|||
PLLLL]
|
||||
[LLLL]
|
||||
[LLLL]
|
||||
[LLLL
|
|
@ -1 +0,0 @@
|
|||
PL
|
|
@ -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"
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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,
|
||||
¤t_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));
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue