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
|
EESchema Schematic File Version 4
|
||||||
LIBS:ttl-fpga-cache
|
LIBS:ttl-fpga-cache
|
||||||
EELAYER 29 0
|
EELAYER 30 0
|
||||||
EELAYER END
|
EELAYER END
|
||||||
$Descr A3 16535 11693
|
$Descr A3 16535 11693
|
||||||
encoding utf-8
|
encoding utf-8
|
||||||
Sheet 2 3
|
Sheet 2 3
|
||||||
Title "DISCRETE TTL FPGA"
|
Title "DISCRETE TTL FPGA"
|
||||||
Date "2019-05-31"
|
Date "2019-05-31"
|
||||||
Rev "02L"
|
Rev "03L"
|
||||||
Comp "Markus Koch <markus@notsyncing.net>"
|
Comp "Markus Koch <markus@notsyncing.net>"
|
||||||
Comment1 "Logic Block"
|
Comment1 "Logic Block"
|
||||||
Comment2 ""
|
Comment2 ""
|
||||||
|
@ -2125,19 +2125,6 @@ F 3 "" H 9100 6950 50 0001 C CNN
|
||||||
1 9100 6950
|
1 9100 6950
|
||||||
1 0 0 -1
|
1 0 0 -1
|
||||||
$EndComp
|
$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
|
Wire Wire Line
|
||||||
8750 5800 8350 5800
|
8750 5800 8350 5800
|
||||||
Wire Wire Line
|
Wire Wire Line
|
||||||
|
@ -2174,9 +2161,6 @@ Wire Wire Line
|
||||||
Wire Wire Line
|
Wire Wire Line
|
||||||
8250 5900 8250 6600
|
8250 5900 8250 6600
|
||||||
Connection ~ 8250 6600
|
Connection ~ 8250 6600
|
||||||
Wire Wire Line
|
|
||||||
8150 6000 8150 6500
|
|
||||||
Connection ~ 8150 6500
|
|
||||||
Wire Wire Line
|
Wire Wire Line
|
||||||
8050 6100 8050 6400
|
8050 6100 8050 6400
|
||||||
Connection ~ 8050 6400
|
Connection ~ 8050 6400
|
||||||
|
@ -2188,39 +2172,15 @@ Wire Wire Line
|
||||||
8750 6000 8150 6000
|
8750 6000 8150 6000
|
||||||
Wire Wire Line
|
Wire Wire Line
|
||||||
8050 6100 8750 6100
|
8050 6100 8750 6100
|
||||||
Wire Wire Line
|
|
||||||
8750 6400 8050 6400
|
|
||||||
Wire Wire Line
|
Wire Wire Line
|
||||||
8050 6400 8050 7950
|
8050 6400 8050 7950
|
||||||
Connection ~ 8050 7950
|
Connection ~ 8050 7950
|
||||||
Wire Wire Line
|
Wire Wire Line
|
||||||
8750 6500 8150 6500
|
8250 6600 8650 6600
|
||||||
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
|
|
||||||
Wire Wire Line
|
Wire Wire Line
|
||||||
8750 7950 8050 7950
|
8750 7950 8050 7950
|
||||||
Wire Wire Line
|
Wire Wire Line
|
||||||
8050 7950 8050 8250
|
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
|
Text Label 10600 5900 2 50 ~ 0
|
||||||
fabric0
|
fabric0
|
||||||
$Comp
|
$Comp
|
||||||
|
@ -2533,6 +2493,38 @@ Wire Notes Line
|
||||||
5300 5500 4850 5500
|
5300 5500 4850 5500
|
||||||
Text Notes 4900 5600 0 50 ~ 0
|
Text Notes 4900 5600 0 50 ~ 0
|
||||||
cfg[28..16]
|
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
|
Wire Bus Line
|
||||||
13100 7850 13700 7850
|
13100 7850 13700 7850
|
||||||
Wire Bus Line
|
Wire Bus Line
|
||||||
|
@ -2557,4 +2549,16 @@ Wire Bus Line
|
||||||
7750 1800 7750 4350
|
7750 1800 7750 4350
|
||||||
Wire Bus Line
|
Wire Bus Line
|
||||||
5900 1800 5900 4350
|
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
|
$EndSCHEMATC
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
EESchema Schematic File Version 4
|
EESchema Schematic File Version 4
|
||||||
LIBS:ttl-fpga-cache
|
LIBS:ttl-fpga-cache
|
||||||
EELAYER 29 0
|
EELAYER 30 0
|
||||||
EELAYER END
|
EELAYER END
|
||||||
$Descr A4 11693 8268
|
$Descr A4 11693 8268
|
||||||
encoding utf-8
|
encoding utf-8
|
||||||
Sheet 3 3
|
Sheet 3 3
|
||||||
Title "DISCRETE TTL FPGA"
|
Title "DISCRETE TTL FPGA"
|
||||||
Date "2019-05-31"
|
Date "2019-05-31"
|
||||||
Rev "02L"
|
Rev "03L"
|
||||||
Comp "Markus Koch <markus@notsyncing.net>"
|
Comp "Markus Koch <markus@notsyncing.net>"
|
||||||
Comment1 "Logic Block"
|
Comment1 "Logic Block"
|
||||||
Comment2 "single 4-input LUT / dual 3-input LUT"
|
Comment2 "single 4-input LUT / dual 3-input LUT"
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
EESchema Schematic File Version 4
|
EESchema Schematic File Version 4
|
||||||
LIBS:ttl-fpga-cache
|
LIBS:ttl-fpga-cache
|
||||||
EELAYER 29 0
|
EELAYER 30 0
|
||||||
EELAYER END
|
EELAYER END
|
||||||
$Descr A4 11693 8268
|
$Descr A4 11693 8268
|
||||||
encoding utf-8
|
encoding utf-8
|
||||||
Sheet 1 3
|
Sheet 1 3
|
||||||
Title "DISCRETE TTL FPGA"
|
Title "DISCRETE TTL FPGA"
|
||||||
Date "2019-05-31"
|
Date "2019-05-31"
|
||||||
Rev "02L"
|
Rev "03L"
|
||||||
Comp "Markus Koch <markus@notsyncing.net>"
|
Comp "Markus Koch <markus@notsyncing.net>"
|
||||||
Comment1 "PCB"
|
Comment1 "PCB"
|
||||||
Comment2 ""
|
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