ttl-fpga/sw/kousaten/src/fpga_cell.c

172 lines
4.0 KiB
C
Raw Normal View History

2019-06-16 21:27:42 +02:00
#include "fpga_cell.h"
#include "fpga_global.h"
2019-06-18 20:15:35 +02:00
#include "fpga_cell_lut34.h"
#include "fpga_cell_none.h"
#include "fpga_cell_wire.h"
2019-06-16 21:27:42 +02:00
2019-06-18 20:15:35 +02:00
static struct fpga_cell_type fpga_cell_list[] = {
{
.identifier = ' ',
.cell_new = fpga_cell_none_new,
.get_next_isp = fpga_cell_none_get_next_isp
},
{
.identifier = '[',
.cell_new = fpga_cell_wire_new,
.get_next_isp = fpga_cell_wire_get_next_isp
},
{
.identifier = ']',
.cell_new = fpga_cell_wire_new,
.get_next_isp = fpga_cell_wire_get_next_isp
},
{
.identifier = 'P',
.cell_new = fpga_cell_wire_new,
.get_next_isp = fpga_cell_wire_get_next_isp
},
{
.identifier = 'L',
.cell_new = fpga_cell_lut34_new,
.get_next_isp = fpga_cell_lut34_get_next_isp
},
{
.identifier = '\0',
.cell_new = NULL,
.get_next_isp = NULL
}
};
void fpga_cell_init(struct fpga_cell *cell,
struct fpga_cell_type *cell_type)
2019-06-16 21:27:42 +02:00
{
int i;
for (i = 0; i < FPGA_CELL_CONNECTION_COUNT; ++i) {
2019-06-18 20:15:35 +02:00
cell->cell_connections[i] = NULL;
2019-06-16 21:27:42 +02:00
}
2019-06-18 20:15:35 +02:00
cell->type = cell_type;
//fpga_cell->get_next_isp = fpga_cell_get_next_isp_dummy;
2019-06-16 21:27:42 +02:00
report(LL_DEBUG,
"Initialized cell of type %d at %p.",
2019-06-18 20:15:35 +02:00
cell_type, cell);
2019-06-16 21:27:42 +02:00
}
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;
}
2019-06-18 20:15:35 +02:00
/**
* @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 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;
}