- a few things moved from custom text to json
- switched to llvm, fixed a few warnings
This commit is contained in:
parent
7d872ef24f
commit
ad0d2924df
1
Makefile
1
Makefile
|
@ -6,6 +6,7 @@
|
||||||
# For details see the UNLICENSE file at the root of the source tree.
|
# For details see the UNLICENSE file at the root of the source tree.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
CC = clang-3.6
|
||||||
|
|
||||||
CFLAGS += -I$(CURDIR)/libs
|
CFLAGS += -I$(CURDIR)/libs
|
||||||
|
|
||||||
|
|
83
README
83
README
|
@ -1,36 +1,31 @@
|
||||||
**** NOTE - JUNE 2013 ****
|
|
||||||
I would L O V E to do continue with fpgatools but each day is
|
|
||||||
short so I have to postpone fpgatools development probably
|
|
||||||
until 2014. Maybe I can switch directly to Artix then :-)
|
|
||||||
If you want to contact me please email wspraul@q-ag.de
|
|
||||||
****
|
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
fpgatools is a toolchain to program field-programmable gate arrays
|
fpgatools converts the configuration of an FPGA between
|
||||||
(FPGAs). The only supported chip at this time is the xc6slx9, a
|
JSON and bitstream representation.
|
||||||
45nm-generation fpga with 5720 6-input LUTs, block ram and
|
|
||||||
multiply-accumulate devices.
|
|
||||||
|
|
||||||
*) maximize chip performance
|
The only supported chips at this time is the xc6slx9, a 45nm-generation
|
||||||
*) fast development cycles
|
FPGA with 5720 6-input LUTs, block ram and multiply-accumulate
|
||||||
*) independent toolchain that only depends on free software
|
resources.
|
||||||
*) reconfigure on-chip
|
|
||||||
*) include get-started tools such as jtag, debugging, parts data
|
Also not included are place and route tools or other higher-level
|
||||||
and hardware designs
|
logic optimization, synthesis, Verilog, HLS, etc.
|
||||||
*) design flow that includes asic manufacturing
|
Future work on integrating with graywolf or yosys might be an option.
|
||||||
*) lightweight C implementation without GUI
|
If you have ideas in that direction, please email the author at
|
||||||
|
wspraul@q-ag.de
|
||||||
|
|
||||||
|
*) educational resource
|
||||||
|
*) have fun and experiment with every feature of the chip
|
||||||
|
*) command-line tools, text-based file formats
|
||||||
*) supported platform: Linux
|
*) supported platform: Linux
|
||||||
*) license: public domain
|
*) free software, released into the public domain (see
|
||||||
|
UNLICENSE for details)
|
||||||
|
|
||||||
FAQ
|
FAQ
|
||||||
todo
|
todo
|
||||||
|
|
||||||
Libraries
|
Libraries
|
||||||
|
|
||||||
- libfpga-cores reusable cores
|
|
||||||
- libfpga-stdlib standard design elements on top of libfpga-control
|
|
||||||
- libfpga-control programmatic access to libfpga-model
|
- libfpga-control programmatic access to libfpga-model
|
||||||
- libfpga-model memory-only representation of an FPGA
|
- libfpga-model in-memory representation of the FPGA
|
||||||
- libfpga-floorplan reads and writes .fp floorplan files
|
- libfpga-floorplan reads and writes .fp floorplan files
|
||||||
- libfpga-bit reads and writes .bit bitstream files
|
- libfpga-bit reads and writes .bit bitstream files
|
||||||
|
|
||||||
|
@ -58,34 +53,27 @@ Profiling
|
||||||
~# perf annotate
|
~# perf annotate
|
||||||
~# perf report
|
~# perf report
|
||||||
|
|
||||||
Design Principles
|
How to Help
|
||||||
|
- use fpgatools, email author for free support
|
||||||
|
- fund electron microscope photos
|
||||||
|
- want bigger or newer chips? email the author
|
||||||
|
- timing analysis, temperature analysis, visualizations
|
||||||
|
|
||||||
- small independent command line utilities, no GUI
|
TODO (as of 2015-03)
|
||||||
- plain C, no C++
|
|
||||||
- simple Makefiles
|
|
||||||
- text-based file formats
|
|
||||||
- automatic test suite
|
|
||||||
- public domain software
|
|
||||||
|
|
||||||
TODO (as of February, 2013)
|
short-term (3 months):
|
||||||
|
|
||||||
short-term (1 month):
|
|
||||||
* support block memory
|
* support block memory
|
||||||
-> develop structure of dev_bram16/8
|
|
||||||
-> write block_mem autotest
|
-> write block_mem autotest
|
||||||
* example: counter (including clock, jtag)
|
* support macc
|
||||||
|
* support pll_adv
|
||||||
|
* support dcm
|
||||||
|
* support ilogic2/ologic2
|
||||||
|
|
||||||
mid-term (6 months):
|
mid-term (12 months):
|
||||||
* example: j1 soc
|
* example: counter (including clock, jtag)
|
||||||
* hls: llvm backend
|
|
||||||
* maybe fp2bit should natively write ieee1532 and separate tools convert
|
|
||||||
from ieee1532 to .bit and other formats
|
|
||||||
* macc
|
|
||||||
* more cases in logic block configuration
|
* more cases in logic block configuration
|
||||||
* autotest: fix bugs in lut_encoding, logic_cfg, routing_sw, io_sw tests
|
* autotest: fix bugs in lut_encoding, logic_cfg, routing_sw, io_sw tests
|
||||||
* autotest: protect stderr of diff executable in autotest log
|
* autotest: protect stderr of diff executable in autotest log
|
||||||
* support chips other than xc6slx9, maybe xc7a20
|
|
||||||
* write standard design elements for libfpga-stdlib library
|
|
||||||
* several places might benefit from a bison parser:
|
* several places might benefit from a bison parser:
|
||||||
- switchbox description into bit parser/generator (bit_frames.c)
|
- switchbox description into bit parser/generator (bit_frames.c)
|
||||||
- inter-tile wire connections (model_conns.c)
|
- inter-tile wire connections (model_conns.c)
|
||||||
|
@ -97,13 +85,14 @@ cleanup (whenever convenient):
|
||||||
* describe more wire names/meanings with integers instead of strings
|
* describe more wire names/meanings with integers instead of strings
|
||||||
* move all part-specific static data into xc_info()
|
* move all part-specific static data into xc_info()
|
||||||
|
|
||||||
long-term (>6 months):
|
long-term (>12 months):
|
||||||
* auto-crc calculation in .bit file
|
* auto-crc calculation in .bit file
|
||||||
* MCB switches and connections
|
* MCB switches and connections
|
||||||
* support lm32 or openrisc core, either via libfpga or iverilog backend
|
* maybe fp2bit should natively write ieee1532 and separate tools convert
|
||||||
* ipv6 or vnc in hardware?
|
from ieee1532 to .bit and other formats
|
||||||
* iverilog fpga backend
|
|
||||||
* design fpga core that uses high-speed icap/reconfig to process data
|
* design fpga core that uses high-speed icap/reconfig to process data
|
||||||
|
* example: j1 soc
|
||||||
|
* support chips other than xc6slx9, maybe xc7a35 or xc7a100
|
||||||
|
|
||||||
ChangeLog
|
ChangeLog
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ static int dump_file(const char* path)
|
||||||
|| !strncmp(line, "+++ ", 4)
|
|| !strncmp(line, "+++ ", 4)
|
||||||
|| !strncmp(line, "@@ ", 3))
|
|| !strncmp(line, "@@ ", 3))
|
||||||
continue;
|
continue;
|
||||||
printf(line);
|
printf("%s", line);
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
# For details see the UNLICENSE file at the root of the source tree.
|
# For details see the UNLICENSE file at the root of the source tree.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
CC = clang-3.6
|
||||||
|
|
||||||
LIBS_VERSION_MAJOR = 0
|
LIBS_VERSION_MAJOR = 0
|
||||||
LIBS_VERSION = $(LIBS_VERSION_MAJOR).0.0
|
LIBS_VERSION = $(LIBS_VERSION_MAJOR).0.0
|
||||||
|
|
||||||
|
@ -13,10 +15,9 @@ LIBFPGA_BIT_OBJS = bit_frames.o bit_regs.o
|
||||||
LIBFPGA_MODEL_OBJS = model_main.o model_tiles.o model_devices.o \
|
LIBFPGA_MODEL_OBJS = model_main.o model_tiles.o model_devices.o \
|
||||||
model_ports.o model_conns.o model_switches.o model_helper.o
|
model_ports.o model_conns.o model_switches.o model_helper.o
|
||||||
LIBFPGA_FLOORPLAN_OBJS = floorplan.o
|
LIBFPGA_FLOORPLAN_OBJS = floorplan.o
|
||||||
LIBFPGA_CONTROL_OBJS = control.o
|
LIBFPGA_CONTROL_OBJS = control.o parts.o helper.o
|
||||||
LIBFPGA_CORES_OBJS = parts.o helper.o
|
|
||||||
|
|
||||||
OBJS := $(LIBFPGA_CORES_OBJS) $(LIBFPGA_BIT_OBJS) $(LIBFPGA_MODEL_OBJS) \
|
OBJS := $(LIBFPGA_BIT_OBJS) $(LIBFPGA_MODEL_OBJS) \
|
||||||
$(LIBFPGA_FLOORPLAN_OBJS) $(LIBFPGA_CONTROL_OBJS)
|
$(LIBFPGA_FLOORPLAN_OBJS) $(LIBFPGA_CONTROL_OBJS)
|
||||||
|
|
||||||
DYNAMIC_LIBS = libfpga-model.so libfpga-bit.so libfpga-floorplan.so \
|
DYNAMIC_LIBS = libfpga-model.so libfpga-bit.so libfpga-floorplan.so \
|
||||||
|
@ -31,8 +32,6 @@ all: $(DYNAMIC_LIBS) $(DYNAMIC_LIBS:.so=.a)
|
||||||
|
|
||||||
include ../Makefile.common
|
include ../Makefile.common
|
||||||
|
|
||||||
libfpga-cores.a: $(LIBFPGA_CORES_OBJS)
|
|
||||||
|
|
||||||
libfpga-bit.a: $(LIBFPGA_BIT_OBJS)
|
libfpga-bit.a: $(LIBFPGA_BIT_OBJS)
|
||||||
|
|
||||||
libfpga-model.a: $(LIBFPGA_MODEL_OBJS)
|
libfpga-model.a: $(LIBFPGA_MODEL_OBJS)
|
||||||
|
@ -45,8 +44,6 @@ libfpga-control.a: $(LIBFPGA_CONTROL_OBJS)
|
||||||
$(AR) $@ $^
|
$(AR) $@ $^
|
||||||
$(RANLIB) $@
|
$(RANLIB) $@
|
||||||
|
|
||||||
libfpga-cores.so: $(LIBFPGA_CORES_OBJS)
|
|
||||||
|
|
||||||
libfpga-bit.so: $(LIBFPGA_BIT_OBJS)
|
libfpga-bit.so: $(LIBFPGA_BIT_OBJS)
|
||||||
|
|
||||||
libfpga-model.so: $(LIBFPGA_MODEL_OBJS)
|
libfpga-model.so: $(LIBFPGA_MODEL_OBJS)
|
||||||
|
|
|
@ -7,15 +7,14 @@
|
||||||
|
|
||||||
// xc6 configuration registers, documentation in ug380, page90
|
// xc6 configuration registers, documentation in ug380, page90
|
||||||
enum fpga_config_reg {
|
enum fpga_config_reg {
|
||||||
CRC = 0, FAR_MAJ, FAR_MIN, FDRI, FDRO, CMD, CTL, MASK, STAT, LOUT, COR1,
|
REG_NOOP = -1, // pseudo register for noops
|
||||||
|
CRC, FAR_MAJ, FAR_MIN, FDRI, FDRO, CMD, CTL, MASK, STAT, LOUT, COR1,
|
||||||
COR2, PWRDN_REG, FLR, IDCODE, CWDT, HC_OPT_REG, CSBO = 18,
|
COR2, PWRDN_REG, FLR, IDCODE, CWDT, HC_OPT_REG, CSBO = 18,
|
||||||
GENERAL1, GENERAL2, GENERAL3, GENERAL4, GENERAL5, MODE_REG, PU_GWE,
|
GENERAL1, GENERAL2, GENERAL3, GENERAL4, GENERAL5, MODE_REG, PU_GWE,
|
||||||
PU_GTS, MFWR, CCLK_FREQ, SEU_OPT, EXP_SIGN, RDBK_SIGN, BOOTSTS,
|
PU_GTS, MFWR, CCLK_FREQ, SEU_OPT, EXP_SIGN, RDBK_SIGN, BOOTSTS,
|
||||||
EYE_MASK, CBC_REG
|
EYE_MASK, CBC_REG
|
||||||
};
|
};
|
||||||
|
|
||||||
#define REG_NOOP -1 // pseudo register for noops
|
|
||||||
|
|
||||||
#define COR1_DEF 0x3D00
|
#define COR1_DEF 0x3D00
|
||||||
#define COR1_CRC_BYPASS 0x0010
|
#define COR1_CRC_BYPASS 0x0010
|
||||||
#define COR2_DEF 0x09EE
|
#define COR2_DEF 0x09EE
|
||||||
|
|
|
@ -680,6 +680,8 @@ static int dump_maj_logic(const uint8_t* bits, int row, int major)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
typedef struct ramb16_cfg
|
typedef struct ramb16_cfg
|
||||||
{
|
{
|
||||||
uint8_t byte[64];
|
uint8_t byte[64];
|
||||||
|
@ -851,6 +853,7 @@ static void print_ramb16_cfg(ramb16_cfg_t* cfg)
|
||||||
}
|
}
|
||||||
printf("}\n");
|
printf("}\n");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void printf_minor_diff(int row, int major, int minor,
|
static void printf_minor_diff(int row, int major, int minor,
|
||||||
const uint8_t *old_minor_bits, const uint8_t *new_minor_bits)
|
const uint8_t *old_minor_bits, const uint8_t *new_minor_bits)
|
||||||
|
@ -924,8 +927,9 @@ static void printf_minors(int row, int major, int minor, int num_minors,
|
||||||
|
|
||||||
static int dump_maj_bram(const uint8_t *bits, int row, int major)
|
static int dump_maj_bram(const uint8_t *bits, int row, int major)
|
||||||
{
|
{
|
||||||
ramb16_cfg_t ramb16_cfg[4];
|
// ramb16_cfg_t ramb16_cfg[4];
|
||||||
int minor, i, j, offset_in_frame;
|
// int j, offset_in_frame;
|
||||||
|
int minor, i;
|
||||||
|
|
||||||
for (minor = 0; minor < get_major_minors(XC6SLX9, major); minor++)
|
for (minor = 0; minor < get_major_minors(XC6SLX9, major); minor++)
|
||||||
printf_clock(&bits[minor*FRAME_SIZE], row, major, minor);
|
printf_clock(&bits[minor*FRAME_SIZE], row, major, minor);
|
||||||
|
|
|
@ -171,7 +171,7 @@ static const char* dev_str[] = FPGA_DEV_STR;
|
||||||
|
|
||||||
const char* fdev_type2str(enum fpgadev_type type)
|
const char* fdev_type2str(enum fpgadev_type type)
|
||||||
{
|
{
|
||||||
if (type < 0 || type >= sizeof(dev_str)/sizeof(*dev_str))
|
if (type >= sizeof(dev_str)/sizeof(*dev_str))
|
||||||
{ HERE(); return 0; }
|
{ HERE(); return 0; }
|
||||||
return dev_str[type];
|
return dev_str[type];
|
||||||
}
|
}
|
||||||
|
@ -1310,6 +1310,24 @@ const char* fpga_switch_print(struct fpga_model* model, int y, int x,
|
||||||
return buf[last_buf];
|
return buf[last_buf];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* fpga_switch_print_json(struct fpga_model* model, int y, int x,
|
||||||
|
swidx_t swidx)
|
||||||
|
{
|
||||||
|
enum { NUM_BUFS = 16, BUF_SIZE = 128 };
|
||||||
|
static char buf[NUM_BUFS][BUF_SIZE];
|
||||||
|
static int last_buf = 0;
|
||||||
|
uint32_t sw;
|
||||||
|
|
||||||
|
sw = YX_TILE(model, y, x)->switches[swidx];
|
||||||
|
last_buf = (last_buf+1)%NUM_BUFS;
|
||||||
|
|
||||||
|
snprintf(buf[last_buf], sizeof(*buf), ", \"from\" : \"%s\", \"to\" : \"%s\"%s",
|
||||||
|
connpt_str(model, y, x, SW_FROM_I(sw)),
|
||||||
|
connpt_str(model, y, x, SW_TO_I(sw)),
|
||||||
|
sw & SWITCH_BIDIRECTIONAL ? ", \"bidir\" : true" : "");
|
||||||
|
return buf[last_buf];
|
||||||
|
}
|
||||||
|
|
||||||
int fpga_switch_is_bidir(struct fpga_model* model, int y, int x,
|
int fpga_switch_is_bidir(struct fpga_model* model, int y, int x,
|
||||||
swidx_t swidx)
|
swidx_t swidx)
|
||||||
{
|
{
|
||||||
|
@ -2148,6 +2166,7 @@ int fnet_add_port(struct fpga_model* model, net_idx_t net_i,
|
||||||
pinw_idx_t pinw_idx)
|
pinw_idx_t pinw_idx)
|
||||||
{
|
{
|
||||||
struct fpga_net* net;
|
struct fpga_net* net;
|
||||||
|
dev_idx_t dev_idx;
|
||||||
|
|
||||||
fnet_useidx(model, net_i);
|
fnet_useidx(model, net_i);
|
||||||
RC_CHECK(model);
|
RC_CHECK(model);
|
||||||
|
@ -2158,8 +2177,9 @@ int fnet_add_port(struct fpga_model* model, net_idx_t net_i,
|
||||||
net->el[net->len].y = y;
|
net->el[net->len].y = y;
|
||||||
net->el[net->len].x = x;
|
net->el[net->len].x = x;
|
||||||
net->el[net->len].idx = pinw_idx | NET_IDX_IS_PINW;
|
net->el[net->len].idx = pinw_idx | NET_IDX_IS_PINW;
|
||||||
net->el[net->len].dev_idx = fpga_dev_idx(model, y, x, type, type_idx);
|
dev_idx = fpga_dev_idx(model, y, x, type, type_idx);
|
||||||
RC_ASSERT(model, net->el[net->len].dev_idx != NO_DEV);
|
RC_ASSERT(model, dev_idx != NO_DEV);
|
||||||
|
net->el[net->len].dev_idx = dev_idx;
|
||||||
|
|
||||||
net->len++;
|
net->len++;
|
||||||
RC_RETURN(model);
|
RC_RETURN(model);
|
||||||
|
@ -2290,8 +2310,9 @@ static void fprintf_inout_pin(FILE* f, struct fpga_model* model,
|
||||||
pin_str = fdev_pinw_idx2str(tile->devs[dev_idx].type, pinw_i);
|
pin_str = fdev_pinw_idx2str(tile->devs[dev_idx].type, pinw_i);
|
||||||
if (!pin_str) { HERE(); return; }
|
if (!pin_str) { HERE(); return; }
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "net %i %s y%i x%i %s %i pin %s\n",
|
snprintf(buf, sizeof(buf), " { \"type\" : \"%s\", \"y\" : %i, \"x\" : %i, "
|
||||||
net_i, in_pin ? "in" : "out", el->y, el->x,
|
"\"dev\" : \"%s\", \"dev_idx\" : %i, \"pin\" : \"%s\" }",
|
||||||
|
in_pin ? "in" : "out", el->y, el->x,
|
||||||
fdev_type2str(tile->devs[dev_idx].type),
|
fdev_type2str(tile->devs[dev_idx].type),
|
||||||
fdev_typeidx(model, el->y, el->x, dev_idx),
|
fdev_typeidx(model, el->y, el->x, dev_idx),
|
||||||
pin_str);
|
pin_str);
|
||||||
|
@ -2301,21 +2322,27 @@ static void fprintf_inout_pin(FILE* f, struct fpga_model* model,
|
||||||
void fnet_printf(FILE* f, struct fpga_model* model, net_idx_t net_i)
|
void fnet_printf(FILE* f, struct fpga_model* model, net_idx_t net_i)
|
||||||
{
|
{
|
||||||
struct fpga_net* net;
|
struct fpga_net* net;
|
||||||
int i;
|
int i, first_line;
|
||||||
|
|
||||||
net = fnet_get(model, net_i);
|
net = fnet_get(model, net_i);
|
||||||
if (!net) { HERE(); return; }
|
if (!net) { HERE(); return; }
|
||||||
|
fprintf(f, "[\n");
|
||||||
|
first_line = 1;
|
||||||
for (i = 0; i < net->len; i++) {
|
for (i = 0; i < net->len; i++) {
|
||||||
|
if (!first_line)
|
||||||
|
fprintf(f, ",\n");
|
||||||
|
first_line = 0;
|
||||||
if (net->el[i].idx & NET_IDX_IS_PINW) {
|
if (net->el[i].idx & NET_IDX_IS_PINW) {
|
||||||
fprintf_inout_pin(f, model, net_i, &net->el[i]);
|
fprintf_inout_pin(f, model, net_i, &net->el[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// switch
|
// switch
|
||||||
fprintf(f, "net %i sw y%i x%i %s\n",
|
fprintf(f, " { \"type\" : \"sw\", \"y\" : %i, \"x\" : %i%s }",
|
||||||
net_i, net->el[i].y, net->el[i].x,
|
net->el[i].y, net->el[i].x,
|
||||||
fpga_switch_print(model, net->el[i].y,
|
fpga_switch_print_json(model, net->el[i].y,
|
||||||
net->el[i].x, net->el[i].idx));
|
net->el[i].x, net->el[i].idx));
|
||||||
}
|
}
|
||||||
|
fprintf(f, "\n ]");
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -190,6 +190,8 @@ const char* fpga_switch_str(struct fpga_model* model, int y, int x,
|
||||||
swidx_t swidx, int from_to);
|
swidx_t swidx, int from_to);
|
||||||
str16_t fpga_switch_str_i(struct fpga_model* model, int y, int x,
|
str16_t fpga_switch_str_i(struct fpga_model* model, int y, int x,
|
||||||
swidx_t swidx, int from_to);
|
swidx_t swidx, int from_to);
|
||||||
|
const char* fpga_switch_print_json(struct fpga_model* model, int y, int x,
|
||||||
|
swidx_t swidx);
|
||||||
const char* fpga_switch_print(struct fpga_model* model, int y, int x,
|
const char* fpga_switch_print(struct fpga_model* model, int y, int x,
|
||||||
swidx_t swidx);
|
swidx_t swidx);
|
||||||
int fpga_switch_is_bidir(struct fpga_model* model, int y, int x,
|
int fpga_switch_is_bidir(struct fpga_model* model, int y, int x,
|
||||||
|
|
354
libs/floorplan.c
354
libs/floorplan.c
|
@ -11,14 +11,14 @@
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "floorplan.h"
|
#include "floorplan.h"
|
||||||
|
|
||||||
void printf_version(FILE* f)
|
|
||||||
{
|
|
||||||
fprintf(f, "fpga_floorplan_format 1\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PRINT_FLAG(fp, flag) if ((tf) & (flag)) \
|
#define PRINT_FLAG(fp, flag) if ((tf) & (flag)) \
|
||||||
{ fprintf (fp, " %s", #flag); tf &= ~(flag); }
|
{ fprintf (fp, " %s", #flag); tf &= ~(flag); }
|
||||||
|
|
||||||
|
void printf_version(FILE* f)
|
||||||
|
{
|
||||||
|
fprintf(f, " \"fpga_floorplan_version\" : 1");
|
||||||
|
}
|
||||||
|
|
||||||
int printf_tiles(FILE* f, struct fpga_model* model)
|
int printf_tiles(FILE* f, struct fpga_model* model)
|
||||||
{
|
{
|
||||||
struct fpga_tile* tile;
|
struct fpga_tile* tile;
|
||||||
|
@ -67,110 +67,143 @@ int printf_IOB(FILE *f, struct fpga_model *model,
|
||||||
{
|
{
|
||||||
struct fpga_tile *tile;
|
struct fpga_tile *tile;
|
||||||
char pref[256];
|
char pref[256];
|
||||||
int dev_i;
|
int dev_i, first_line;
|
||||||
|
|
||||||
dev_i = fpga_dev_idx(model, y, x, DEV_IOB, type_idx);
|
dev_i = fpga_dev_idx(model, y, x, DEV_IOB, type_idx);
|
||||||
RC_ASSERT(model, dev_i != NO_DEV);
|
RC_ASSERT(model, dev_i != NO_DEV);
|
||||||
tile = YX_TILE(model, y, x);
|
tile = YX_TILE(model, y, x);
|
||||||
if (config_only && !(tile->devs[dev_i].instantiated))
|
if (config_only && !(tile->devs[dev_i].instantiated))
|
||||||
RC_RETURN(model);
|
RC_RETURN(model);
|
||||||
snprintf(pref, sizeof(pref), "dev y%i x%i IOB %i", y, x, type_idx);
|
snprintf(pref, sizeof(pref), " { \"y\" : %i, \"x\" : %i, \"dev\" : \"IOB\", \"dev_idx\" : %i, ", y, x, type_idx);
|
||||||
|
first_line = 1;
|
||||||
|
|
||||||
if (!config_only)
|
if (!config_only) {
|
||||||
fprintf(f, "%s type %s\n", pref,
|
fprintf(f, "%s%s\"type\" : \"%s\" }", first_line ? "" : ",\n", pref,
|
||||||
tile->devs[dev_i].subtype == IOBM ? "M" : "S");
|
tile->devs[dev_i].subtype == IOBM ? "M" : "S");
|
||||||
if (tile->devs[dev_i].u.iob.istandard[0])
|
first_line = 0;
|
||||||
fprintf(f, "%s istd %s\n", pref,
|
}
|
||||||
|
if (tile->devs[dev_i].u.iob.istandard[0]) {
|
||||||
|
fprintf(f, "%s%s\"istd\" : \"%s\" }", first_line ? "" : ",\n", pref,
|
||||||
tile->devs[dev_i].u.iob.istandard);
|
tile->devs[dev_i].u.iob.istandard);
|
||||||
if (tile->devs[dev_i].u.iob.ostandard[0])
|
first_line = 0;
|
||||||
fprintf(f, "%s ostd %s\n", pref,
|
}
|
||||||
|
if (tile->devs[dev_i].u.iob.ostandard[0]) {
|
||||||
|
fprintf(f, "%s%s\"ostd\" : \"%s\" }", first_line ? "" : ",\n", pref,
|
||||||
tile->devs[dev_i].u.iob.ostandard);
|
tile->devs[dev_i].u.iob.ostandard);
|
||||||
|
first_line = 0;
|
||||||
|
}
|
||||||
switch (tile->devs[dev_i].u.iob.bypass_mux) {
|
switch (tile->devs[dev_i].u.iob.bypass_mux) {
|
||||||
case BYPASS_MUX_I:
|
case BYPASS_MUX_I:
|
||||||
fprintf(f, "%s bypass_mux I\n", pref);
|
fprintf(f, "%s%s\"bypass_mux\" : \"I\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case BYPASS_MUX_O:
|
case BYPASS_MUX_O:
|
||||||
fprintf(f, "%s bypass_mux O\n", pref);
|
fprintf(f, "%s%s\"bypass_mux\" : \"O\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case BYPASS_MUX_T:
|
case BYPASS_MUX_T:
|
||||||
fprintf(f, "%s bypass_mux T\n", pref);
|
fprintf(f, "%s%s\"bypass_mux\" : \"T\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case 0: break; default: RC_FAIL(model, EINVAL);
|
case 0: break; default: RC_FAIL(model, EINVAL);
|
||||||
}
|
}
|
||||||
switch (tile->devs[dev_i].u.iob.I_mux) {
|
switch (tile->devs[dev_i].u.iob.I_mux) {
|
||||||
case IMUX_I_B:
|
case IMUX_I_B:
|
||||||
fprintf(f, "%s imux I_B\n", pref);
|
fprintf(f, "%s%s\"imux\" : \"I_B\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case IMUX_I:
|
case IMUX_I:
|
||||||
fprintf(f, "%s imux I\n", pref);
|
fprintf(f, "%s%s\"imux\" : \"I\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case 0: break; default: RC_FAIL(model, EINVAL);
|
case 0: break; default: RC_FAIL(model, EINVAL);
|
||||||
}
|
}
|
||||||
if (tile->devs[dev_i].u.iob.drive_strength)
|
if (tile->devs[dev_i].u.iob.drive_strength) {
|
||||||
fprintf(f, "%s strength %i\n", pref,
|
fprintf(f, "%s%s\"strength\" : %i }", first_line ? "" : ",\n", pref,
|
||||||
tile->devs[dev_i].u.iob.drive_strength);
|
tile->devs[dev_i].u.iob.drive_strength);
|
||||||
|
first_line = 0;
|
||||||
|
}
|
||||||
switch (tile->devs[dev_i].u.iob.slew) {
|
switch (tile->devs[dev_i].u.iob.slew) {
|
||||||
case SLEW_SLOW:
|
case SLEW_SLOW:
|
||||||
fprintf(f, "%s slew SLOW\n", pref);
|
fprintf(f, "%s%s\"slew\" : \"SLOW\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case SLEW_FAST:
|
case SLEW_FAST:
|
||||||
fprintf(f, "%s slew FAST\n", pref);
|
fprintf(f, "%s%s\"slew\" : \"FAST\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case SLEW_QUIETIO:
|
case SLEW_QUIETIO:
|
||||||
fprintf(f, "%s slew QUIETIO\n", pref);
|
fprintf(f, "%s%s\"slew\" : \"QUIETIO\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case 0: break; default: RC_FAIL(model, EINVAL);
|
case 0: break; default: RC_FAIL(model, EINVAL);
|
||||||
}
|
}
|
||||||
if (tile->devs[dev_i].u.iob.O_used)
|
if (tile->devs[dev_i].u.iob.O_used) {
|
||||||
fprintf(f, "%s O_used\n", pref);
|
fprintf(f, "%s%s\"O_used\" : true }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
|
}
|
||||||
switch (tile->devs[dev_i].u.iob.suspend) {
|
switch (tile->devs[dev_i].u.iob.suspend) {
|
||||||
case SUSP_LAST_VAL:
|
case SUSP_LAST_VAL:
|
||||||
fprintf(f, "%s suspend DRIVE_LAST_VALUE\n", pref);
|
fprintf(f, "%s%s\"suspend\" : \"DRIVE_LAST_VALUE\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case SUSP_3STATE:
|
case SUSP_3STATE:
|
||||||
fprintf(f, "%s suspend 3STATE\n", pref);
|
fprintf(f, "%s%s\"suspend\" : \"3STATE\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case SUSP_3STATE_PULLUP:
|
case SUSP_3STATE_PULLUP:
|
||||||
fprintf(f, "%s suspend 3STATE_PULLUP\n", pref);
|
fprintf(f, "%s%s\"suspend\" : \"3STATE_PULLUP\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case SUSP_3STATE_PULLDOWN:
|
case SUSP_3STATE_PULLDOWN:
|
||||||
fprintf(f, "%s suspend 3STATE_PULLDOWN\n", pref);
|
fprintf(f, "%s%s\"suspend\" : \"3STATE_PULLDOWN\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case SUSP_3STATE_KEEPER:
|
case SUSP_3STATE_KEEPER:
|
||||||
fprintf(f, "%s suspend 3STATE_KEEPER\n", pref);
|
fprintf(f, "%s%s\"suspend\" : \"3STATE_KEEPER\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case SUSP_3STATE_OCT_ON:
|
case SUSP_3STATE_OCT_ON:
|
||||||
fprintf(f, "%s suspend 3STATE_OCT_ON\n", pref);
|
fprintf(f, "%s%s\"suspend\" : \"3STATE_OCT_ON\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case 0: break; default: RC_FAIL(model, EINVAL);
|
case 0: break; default: RC_FAIL(model, EINVAL);
|
||||||
}
|
}
|
||||||
switch (tile->devs[dev_i].u.iob.in_term) {
|
switch (tile->devs[dev_i].u.iob.in_term) {
|
||||||
case ITERM_NONE:
|
case ITERM_NONE:
|
||||||
fprintf(f, "%s in_term NONE\n", pref);
|
fprintf(f, "%s%s\"in_term\" : \"NONE\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case ITERM_UNTUNED_25:
|
case ITERM_UNTUNED_25:
|
||||||
fprintf(f, "%s in_term UNTUNED_SPLIT_25\n", pref);
|
fprintf(f, "%s%s\"in_term\" : \"UNTUNED_SPLIT_25\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case ITERM_UNTUNED_50:
|
case ITERM_UNTUNED_50:
|
||||||
fprintf(f, "%s in_term UNTUNED_SPLIT_50\n", pref);
|
fprintf(f, "%s%s\"in_term\" : \"UNTUNED_SPLIT_50\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case ITERM_UNTUNED_75:
|
case ITERM_UNTUNED_75:
|
||||||
fprintf(f, "%s in_term UNTUNED_SPLIT_75\n", pref);
|
fprintf(f, "%s%s\"in_term\" : \"UNTUNED_SPLIT_75\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case 0: break; default: RC_FAIL(model, EINVAL);
|
case 0: break; default: RC_FAIL(model, EINVAL);
|
||||||
}
|
}
|
||||||
switch (tile->devs[dev_i].u.iob.out_term) {
|
switch (tile->devs[dev_i].u.iob.out_term) {
|
||||||
case OTERM_NONE:
|
case OTERM_NONE:
|
||||||
fprintf(f, "%s out_term NONE\n", pref);
|
fprintf(f, "%s%s\"out_term\" : \"NONE\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case OTERM_UNTUNED_25:
|
case OTERM_UNTUNED_25:
|
||||||
fprintf(f, "%s out_term UNTUNED_25\n", pref);
|
fprintf(f, "%s%s\"out_term\" : \"UNTUNED_25\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case OTERM_UNTUNED_50:
|
case OTERM_UNTUNED_50:
|
||||||
fprintf(f, "%s out_term UNTUNED_50\n", pref);
|
fprintf(f, "%s%s\"out_term\" : \"UNTUNED_50\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case OTERM_UNTUNED_75:
|
case OTERM_UNTUNED_75:
|
||||||
fprintf(f, "%s out_term UNTUNED_75\n", pref);
|
fprintf(f, "%s%s\"out_term\" : \"UNTUNED_75\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case 0: break; default: RC_FAIL(model, EINVAL);
|
case 0: break; default: RC_FAIL(model, EINVAL);
|
||||||
}
|
}
|
||||||
|
@ -287,25 +320,29 @@ int printf_LOGIC(FILE* f, struct fpga_model* model,
|
||||||
struct fpgadev_logic *cfg;
|
struct fpgadev_logic *cfg;
|
||||||
char pref[256];
|
char pref[256];
|
||||||
const char *str;
|
const char *str;
|
||||||
int dev_i, j;
|
int dev_i, j, first_line;
|
||||||
|
|
||||||
dev_i = fpga_dev_idx(model, y, x, DEV_LOGIC, type_idx);
|
dev_i = fpga_dev_idx(model, y, x, DEV_LOGIC, type_idx);
|
||||||
RC_ASSERT(model, dev_i != NO_DEV);
|
RC_ASSERT(model, dev_i != NO_DEV);
|
||||||
tile = YX_TILE(model, y, x);
|
tile = YX_TILE(model, y, x);
|
||||||
if (config_only && !(tile->devs[dev_i].instantiated))
|
if (config_only && !(tile->devs[dev_i].instantiated))
|
||||||
RC_RETURN(model);
|
RC_RETURN(model);
|
||||||
snprintf(pref, sizeof(pref), "dev y%i x%i LOGIC %i", y, x, type_idx);
|
snprintf(pref, sizeof(pref), " { \"y\" : %i, \"x\" : %i, \"dev\" : \"LOGIC\", \"dev_idx\" : %i, ", y, x, type_idx);
|
||||||
|
first_line = 1;
|
||||||
|
|
||||||
if (!config_only) {
|
if (!config_only) {
|
||||||
switch (tile->devs[dev_i].subtype) {
|
switch (tile->devs[dev_i].subtype) {
|
||||||
case LOGIC_X:
|
case LOGIC_X:
|
||||||
fprintf(f, "%s type X\n", pref);
|
fprintf(f, "%s%s\"type\" : \"X\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case LOGIC_L:
|
case LOGIC_L:
|
||||||
fprintf(f, "%s type L\n", pref);
|
fprintf(f, "%s%s\"type\" : \"L\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case LOGIC_M:
|
case LOGIC_M:
|
||||||
fprintf(f, "%s type M\n", pref);
|
fprintf(f, "%s%s\"type\" : \"M\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
default: RC_FAIL(model, EINVAL);
|
default: RC_FAIL(model, EINVAL);
|
||||||
}
|
}
|
||||||
|
@ -319,222 +356,282 @@ int printf_LOGIC(FILE* f, struct fpga_model* model,
|
||||||
if (cfg->a2d[j].flags & LUT6VAL_SET) {
|
if (cfg->a2d[j].flags & LUT6VAL_SET) {
|
||||||
RC_ASSERT(model, !ULL_HIGH32(cfg->a2d[j].lut6_val));
|
RC_ASSERT(model, !ULL_HIGH32(cfg->a2d[j].lut6_val));
|
||||||
if (print_hex_vals)
|
if (print_hex_vals)
|
||||||
fprintf(f, "%s %c6_lut_val 0x%016lX\n",
|
fprintf(f, "%s%s\"%c6_lut_val\" : \"0x%016lX\" }",
|
||||||
pref, 'A'+j, cfg->a2d[j].lut6_val);
|
first_line ? "" : ",\n", pref, 'A'+j, cfg->a2d[j].lut6_val);
|
||||||
else {
|
else {
|
||||||
str = bool_bits2str(cfg->a2d[j].lut6_val, 32);
|
str = bool_bits2str(cfg->a2d[j].lut6_val, 32);
|
||||||
RC_ASSERT(model, str);
|
RC_ASSERT(model, str);
|
||||||
fprintf(f, "%s %c6_lut_str (A6+~A6)*(%s)\n",
|
fprintf(f, "%s%s\"%c6_lut_str\" : \"(A6+~A6)*(%s)\" }",
|
||||||
pref, 'A'+j, str);
|
first_line ? "" : ",\n", pref, 'A'+j, str);
|
||||||
}
|
}
|
||||||
|
first_line = 0;
|
||||||
}
|
}
|
||||||
if (print_hex_vals)
|
if (print_hex_vals)
|
||||||
fprintf(f, "%s %c5_lut_val 0x%08X\n",
|
fprintf(f, "%s%s\"%c5_lut_val\" : \"0x%08X\" }",
|
||||||
pref, 'A'+j, ULL_LOW32(cfg->a2d[j].lut5_val));
|
first_line ? "" : ",\n", pref, 'A'+j, ULL_LOW32(cfg->a2d[j].lut5_val));
|
||||||
else {
|
else {
|
||||||
str = bool_bits2str(cfg->a2d[j].lut5_val, 32);
|
str = bool_bits2str(cfg->a2d[j].lut5_val, 32);
|
||||||
RC_ASSERT(model, str);
|
RC_ASSERT(model, str);
|
||||||
fprintf(f, "%s %c5_lut_str %s\n",
|
fprintf(f, "%s%s\"%c5_lut_str\" : \"%s\" }",
|
||||||
pref, 'A'+j, str);
|
first_line ? "" : ",\n", pref, 'A'+j, str);
|
||||||
}
|
}
|
||||||
|
first_line = 0;
|
||||||
} else {
|
} else {
|
||||||
if (cfg->a2d[j].flags & LUT6VAL_SET) {
|
if (cfg->a2d[j].flags & LUT6VAL_SET) {
|
||||||
if (print_hex_vals)
|
if (print_hex_vals)
|
||||||
fprintf(f, "%s %c6_lut_val 0x%016lX\n",
|
fprintf(f, "%s%s\"%c6_lut_val\" : \"0x%016lX\" }",
|
||||||
pref, 'A'+j, cfg->a2d[j].lut6_val);
|
first_line ? "" : ",\n", pref, 'A'+j, cfg->a2d[j].lut6_val);
|
||||||
else {
|
else {
|
||||||
str = bool_bits2str(cfg->a2d[j].lut6_val, 64);
|
str = bool_bits2str(cfg->a2d[j].lut6_val, 64);
|
||||||
RC_ASSERT(model, str);
|
RC_ASSERT(model, str);
|
||||||
fprintf(f, "%s %c6_lut_str %s\n",
|
fprintf(f, "%s%s\"%c6_lut_str\" : \"%s\" }",
|
||||||
pref, 'A'+j, str);
|
first_line ? "" : ",\n", pref, 'A'+j, str);
|
||||||
}
|
}
|
||||||
|
first_line = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cfg->a2d[j].flags & OUT_USED)
|
if (cfg->a2d[j].flags & OUT_USED) {
|
||||||
fprintf(f, "%s %c_used\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_used\" : true }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
|
}
|
||||||
switch (cfg->a2d[j].ff) {
|
switch (cfg->a2d[j].ff) {
|
||||||
case FF_OR2L:
|
case FF_OR2L:
|
||||||
fprintf(f, "%s %c_ff OR2L\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_ff\" : \"OR2L\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case FF_AND2L:
|
case FF_AND2L:
|
||||||
fprintf(f, "%s %c_ff AND2L\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_ff\" : \"AND2L\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case FF_LATCH:
|
case FF_LATCH:
|
||||||
fprintf(f, "%s %c_ff LATCH\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_ff\" : \"LATCH\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case FF_FF:
|
case FF_FF:
|
||||||
fprintf(f, "%s %c_ff FF\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_ff\" : \"FF\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case 0: break; default: RC_FAIL(model, EINVAL);
|
case 0: break; default: RC_FAIL(model, EINVAL);
|
||||||
}
|
}
|
||||||
switch (cfg->a2d[j].ff_mux) {
|
switch (cfg->a2d[j].ff_mux) {
|
||||||
case MUX_O6:
|
case MUX_O6:
|
||||||
fprintf(f, "%s %c_ffmux O6\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_ffmux\" : \"O6\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case MUX_O5:
|
case MUX_O5:
|
||||||
fprintf(f, "%s %c_ffmux O5\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_ffmux\" : \"O5\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case MUX_X:
|
case MUX_X:
|
||||||
fprintf(f, "%s %c_ffmux X\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_ffmux\" : \"X\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case MUX_CY:
|
case MUX_CY:
|
||||||
fprintf(f, "%s %c_ffmux CY\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_ffmux\" : \"CY\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case MUX_XOR:
|
case MUX_XOR:
|
||||||
fprintf(f, "%s %c_ffmux XOR\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_ffmux\" : \"XOR\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case MUX_F7:
|
case MUX_F7:
|
||||||
fprintf(f, "%s %c_ffmux F7\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_ffmux\" : \"F7\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case MUX_F8:
|
case MUX_F8:
|
||||||
fprintf(f, "%s %c_ffmux F8\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_ffmux\" : \"F8\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case MUX_MC31:
|
case MUX_MC31:
|
||||||
fprintf(f, "%s %c_ffmux MC31\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_ffmux\" : \"MC31\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case 0: break; default: RC_FAIL(model, EINVAL);
|
case 0: break; default: RC_FAIL(model, EINVAL);
|
||||||
}
|
}
|
||||||
switch (cfg->a2d[j].ff_srinit) {
|
switch (cfg->a2d[j].ff_srinit) {
|
||||||
case FF_SRINIT0:
|
case FF_SRINIT0:
|
||||||
fprintf(f, "%s %c_ffsrinit 0\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_ffsrinit\" : false }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case FF_SRINIT1:
|
case FF_SRINIT1:
|
||||||
fprintf(f, "%s %c_ffsrinit 1\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_ffsrinit\" : true }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case 0: break; default: RC_FAIL(model, EINVAL);
|
case 0: break; default: RC_FAIL(model, EINVAL);
|
||||||
}
|
}
|
||||||
switch (cfg->a2d[j].out_mux) {
|
switch (cfg->a2d[j].out_mux) {
|
||||||
case MUX_O6:
|
case MUX_O6:
|
||||||
fprintf(f, "%s %c_outmux O6\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_outmux\" : \"O6\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case MUX_O5:
|
case MUX_O5:
|
||||||
fprintf(f, "%s %c_outmux O5\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_outmux\" : \"O5\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case MUX_5Q:
|
case MUX_5Q:
|
||||||
fprintf(f, "%s %c_outmux 5Q\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_outmux\" : \"5Q\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case MUX_CY:
|
case MUX_CY:
|
||||||
fprintf(f, "%s %c_outmux CY\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_outmux\" : \"CY\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case MUX_XOR:
|
case MUX_XOR:
|
||||||
fprintf(f, "%s %c_outmux XOR\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_outmux\" : \"XOR\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case MUX_F7:
|
case MUX_F7:
|
||||||
fprintf(f, "%s %c_outmux F7\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_outmux\" : \"F7\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case MUX_F8:
|
case MUX_F8:
|
||||||
fprintf(f, "%s %c_outmux F8\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_outmux\" : \"F8\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case MUX_MC31:
|
case MUX_MC31:
|
||||||
fprintf(f, "%s %c_outmux MC31\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_outmux\" : \"MC31\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case 0: break; default: RC_FAIL(model, EINVAL);
|
case 0: break; default: RC_FAIL(model, EINVAL);
|
||||||
}
|
}
|
||||||
switch (cfg->a2d[j].ff5_srinit) {
|
switch (cfg->a2d[j].ff5_srinit) {
|
||||||
case FF_SRINIT0:
|
case FF_SRINIT0:
|
||||||
fprintf(f, "%s %c5_ffsrinit 0\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c5_ffsrinit\" : false }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case FF_SRINIT1:
|
case FF_SRINIT1:
|
||||||
fprintf(f, "%s %c5_ffsrinit 1\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c5_ffsrinit\" : true }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case 0: break; default: RC_FAIL(model, EINVAL);
|
case 0: break; default: RC_FAIL(model, EINVAL);
|
||||||
}
|
}
|
||||||
switch (cfg->a2d[j].cy0) {
|
switch (cfg->a2d[j].cy0) {
|
||||||
case CY0_X:
|
case CY0_X:
|
||||||
fprintf(f, "%s %c_cy0 X\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_cy0\" : \"X\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case CY0_O5:
|
case CY0_O5:
|
||||||
fprintf(f, "%s %c_cy0 O5\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_cy0\" : \"O5\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case 0: break; default: RC_FAIL(model, EINVAL);
|
case 0: break; default: RC_FAIL(model, EINVAL);
|
||||||
}
|
}
|
||||||
// distributed memory related:
|
// distributed memory related:
|
||||||
switch (cfg->a2d[j].ram_mode) {
|
switch (cfg->a2d[j].ram_mode) {
|
||||||
case DPRAM64:
|
case DPRAM64:
|
||||||
fprintf(f, "%s %c_ram_mode DPRAM64\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_ram_mode\" : \"DPRAM64\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case DPRAM32:
|
case DPRAM32:
|
||||||
fprintf(f, "%s %c_ram_mode DPRAM32\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_ram_mode\" : \"DPRAM32\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case SPRAM64:
|
case SPRAM64:
|
||||||
fprintf(f, "%s %c_ram_mode SPRAM64\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_ram_mode\" : \"SPRAM64\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case SPRAM32:
|
case SPRAM32:
|
||||||
fprintf(f, "%s %c_ram_mode SPRAM32\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_ram_mode\" : \"SPRAM32\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case SRL32:
|
case SRL32:
|
||||||
fprintf(f, "%s %c_ram_mode SRL32\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_ram_mode\" : \"SRL32\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case SRL16:
|
case SRL16:
|
||||||
fprintf(f, "%s %c_ram_mode SRL16\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_ram_mode\" : \"SRL16\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case 0: break; default: RC_FAIL(model, EINVAL);
|
case 0: break; default: RC_FAIL(model, EINVAL);
|
||||||
}
|
}
|
||||||
switch (cfg->a2d[j].di_mux) {
|
switch (cfg->a2d[j].di_mux) {
|
||||||
case DIMUX_MC31:
|
case DIMUX_MC31:
|
||||||
fprintf(f, "%s %c_di_mux MC31\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_di_mux\" : \"MC31\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case DIMUX_X:
|
case DIMUX_X:
|
||||||
fprintf(f, "%s %c_di_mux X\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_di_mux\" : \"X\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case DIMUX_DX:
|
case DIMUX_DX:
|
||||||
fprintf(f, "%s %c_di_mux DX\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_di_mux\" : \"DX\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case DIMUX_BDI1:
|
case DIMUX_BDI1:
|
||||||
fprintf(f, "%s %c_di_mux BDI1\n", pref, 'A'+j);
|
fprintf(f, "%s%s\"%c_di_mux\" : \"BDI1\" }", first_line ? "" : ",\n", pref, 'A'+j);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case 0: break; default: RC_FAIL(model, EINVAL);
|
case 0: break; default: RC_FAIL(model, EINVAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (cfg->clk_inv) {
|
switch (cfg->clk_inv) {
|
||||||
case CLKINV_B:
|
case CLKINV_B:
|
||||||
fprintf(f, "%s clk CLK_B\n", pref);
|
fprintf(f, "%s%s\"clk\" : \"CLK_B\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case CLKINV_CLK:
|
case CLKINV_CLK:
|
||||||
fprintf(f, "%s clk CLK\n", pref);
|
fprintf(f, "%s%s\"clk\" : \"CLK\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case 0: break; default: RC_FAIL(model, EINVAL);
|
case 0: break; default: RC_FAIL(model, EINVAL);
|
||||||
}
|
}
|
||||||
switch (cfg->sync_attr) {
|
switch (cfg->sync_attr) {
|
||||||
case SYNCATTR_SYNC:
|
case SYNCATTR_SYNC:
|
||||||
fprintf(f, "%s sync SYNC\n", pref);
|
fprintf(f, "%s%s\"sync\" : \"SYNC\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case SYNCATTR_ASYNC:
|
case SYNCATTR_ASYNC:
|
||||||
fprintf(f, "%s sync ASYNC\n", pref);
|
fprintf(f, "%s%s\"sync\" : \"ASYNC\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case 0: break; default: RC_FAIL(model, EINVAL);
|
case 0: break; default: RC_FAIL(model, EINVAL);
|
||||||
}
|
}
|
||||||
if (cfg->ce_used)
|
if (cfg->ce_used) {
|
||||||
fprintf(f, "%s ce_used\n", pref);
|
fprintf(f, "%s%s\"ce_used\" : true }", first_line ? "" : ",\n", pref);
|
||||||
if (cfg->sr_used)
|
first_line = 0;
|
||||||
fprintf(f, "%s sr_used\n", pref);
|
}
|
||||||
|
if (cfg->sr_used) {
|
||||||
|
fprintf(f, "%s%s\"sr_used\" : true }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
|
}
|
||||||
switch (cfg->we_mux) {
|
switch (cfg->we_mux) {
|
||||||
case WEMUX_WE:
|
case WEMUX_WE:
|
||||||
fprintf(f, "%s wemux WE\n", pref);
|
fprintf(f, "%s%s\"wemux\" : \"WE\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case WEMUX_CE:
|
case WEMUX_CE:
|
||||||
fprintf(f, "%s wemux CE\n", pref);
|
fprintf(f, "%s%s\"wemux\" : \"CE\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case 0: break; default: RC_FAIL(model, EINVAL);
|
case 0: break; default: RC_FAIL(model, EINVAL);
|
||||||
}
|
}
|
||||||
if (cfg->cout_used)
|
if (cfg->cout_used) {
|
||||||
fprintf(f, "%s cout_used\n", pref);
|
fprintf(f, "%s%s\"cout_used\" : true }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
|
}
|
||||||
switch (cfg->precyinit) {
|
switch (cfg->precyinit) {
|
||||||
case PRECYINIT_0:
|
case PRECYINIT_0:
|
||||||
fprintf(f, "%s precyinit 0\n", pref);
|
fprintf(f, "%s%s\"precyinit\" : \"0\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case PRECYINIT_1:
|
case PRECYINIT_1:
|
||||||
fprintf(f, "%s precyinit 1\n", pref);
|
fprintf(f, "%s%s\"precyinit\" : \"1\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case PRECYINIT_AX:
|
case PRECYINIT_AX:
|
||||||
fprintf(f, "%s precyinit AX\n", pref);
|
fprintf(f, "%s%s\"precyinit\" : \"AX\" }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
break;
|
break;
|
||||||
case 0: break; default: RC_FAIL(model, EINVAL);
|
case 0: break; default: RC_FAIL(model, EINVAL);
|
||||||
}
|
}
|
||||||
if (cfg->wa7_used)
|
if (cfg->wa7_used) {
|
||||||
fprintf(f, "%s wa7_used\n", pref);
|
fprintf(f, "%s%s\"wa7_used\" : true }", first_line ? "" : ",\n", pref);
|
||||||
if (cfg->wa8_used)
|
first_line = 0;
|
||||||
fprintf(f, "%s wa8_used\n", pref);
|
}
|
||||||
|
if (cfg->wa8_used) {
|
||||||
|
fprintf(f, "%s%s\"wa8_used\" : true }", first_line ? "" : ",\n", pref);
|
||||||
|
first_line = 0;
|
||||||
|
}
|
||||||
RC_RETURN(model);
|
RC_RETURN(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1016,16 +1113,21 @@ inst:
|
||||||
|
|
||||||
int printf_devices(FILE* f, struct fpga_model* model, int config_only)
|
int printf_devices(FILE* f, struct fpga_model* model, int config_only)
|
||||||
{
|
{
|
||||||
int x, y, i;
|
int x, y, i, first_dev;
|
||||||
struct fpga_tile* tile;
|
struct fpga_tile* tile;
|
||||||
|
|
||||||
RC_CHECK(model);
|
RC_CHECK(model);
|
||||||
|
fprintf(f, " \"devices\" : [\n");
|
||||||
|
first_dev = 1;
|
||||||
for (x = 0; x < model->x_width; x++) {
|
for (x = 0; x < model->x_width; x++) {
|
||||||
for (y = 0; y < model->y_height; y++) {
|
for (y = 0; y < model->y_height; y++) {
|
||||||
tile = YX_TILE(model, y, x);
|
tile = YX_TILE(model, y, x);
|
||||||
for (i = 0; i < tile->num_devs; i++) {
|
for (i = 0; i < tile->num_devs; i++) {
|
||||||
if (config_only && !(tile->devs[i].instantiated))
|
if (config_only && !(tile->devs[i].instantiated))
|
||||||
continue;
|
continue;
|
||||||
|
if (!first_dev)
|
||||||
|
fprintf(f, ",\n");
|
||||||
|
first_dev = 0;
|
||||||
switch (tile->devs[i].type) {
|
switch (tile->devs[i].type) {
|
||||||
case DEV_IOB:
|
case DEV_IOB:
|
||||||
printf_IOB(f, model, y, x,
|
printf_IOB(f, model, y, x,
|
||||||
|
@ -1053,13 +1155,15 @@ int printf_devices(FILE* f, struct fpga_model* model, int config_only)
|
||||||
config_only);
|
config_only);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(f, "dev y%i x%i %s\n", y, x,
|
fprintf(f, " { \"y\" : %i, \"x\" : %i, \"dev\" : \"%s\" }", y, x,
|
||||||
fdev_type2str(tile->devs[i].type));
|
fdev_type2str(tile->devs[i].type));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!first_dev) fprintf(f, "\n");
|
||||||
|
fprintf(f, " ]");
|
||||||
RC_RETURN(model);
|
RC_RETURN(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1189,13 +1293,21 @@ int printf_switches(FILE* f, struct fpga_model* model)
|
||||||
int printf_nets(FILE* f, struct fpga_model* model)
|
int printf_nets(FILE* f, struct fpga_model* model)
|
||||||
{
|
{
|
||||||
net_idx_t net_i;
|
net_idx_t net_i;
|
||||||
int rc;
|
int rc, first_line;
|
||||||
|
|
||||||
RC_CHECK(model);
|
RC_CHECK(model);
|
||||||
|
fprintf(f, " \"nets\" : [\n");
|
||||||
|
first_line = 1;
|
||||||
net_i = NO_NET;
|
net_i = NO_NET;
|
||||||
while (!(rc = fnet_enum(model, net_i, &net_i)) && net_i != NO_NET)
|
while (!(rc = fnet_enum(model, net_i, &net_i)) && net_i != NO_NET) {
|
||||||
|
if (!first_line)
|
||||||
|
fprintf(f, ",");
|
||||||
|
first_line = 0;
|
||||||
fnet_printf(f, model, net_i);
|
fnet_printf(f, model, net_i);
|
||||||
|
}
|
||||||
if (rc) FAIL(rc);
|
if (rc) FAIL(rc);
|
||||||
|
if (!first_line) fprintf(f, "\n");
|
||||||
|
fprintf(f, " ]");
|
||||||
return 0;
|
return 0;
|
||||||
fail:
|
fail:
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -1443,15 +1555,19 @@ int read_floorplan(struct fpga_model* model, FILE* f)
|
||||||
|
|
||||||
int write_floorplan(FILE* f, struct fpga_model* model, int flags)
|
int write_floorplan(FILE* f, struct fpga_model* model, int flags)
|
||||||
{
|
{
|
||||||
if (!(flags & FP_NO_HEADER))
|
fprintf(f, "{\n");
|
||||||
printf_version(f);
|
printf_version(f);
|
||||||
|
|
||||||
if (model->rc)
|
if (model->rc)
|
||||||
fprintf(f, "rc %i\n", model->rc);
|
fprintf(f, "rc %i\n", model->rc);
|
||||||
else {
|
else {
|
||||||
|
fprintf(f, ",\n");
|
||||||
printf_devices(f, model, /*config_only*/ 1);
|
printf_devices(f, model, /*config_only*/ 1);
|
||||||
|
|
||||||
|
fprintf(f, ",\n");
|
||||||
printf_nets(f, model);
|
printf_nets(f, model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fprintf(f, "\n}\n");
|
||||||
RC_RETURN(model);
|
RC_RETURN(model);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,25 +5,6 @@
|
||||||
// For details see the UNLICENSE file at the root of the source tree.
|
// For details see the UNLICENSE file at the root of the source tree.
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
|
||||||
// Design principles of a floorplan file
|
|
||||||
//
|
|
||||||
// What needs to be in the file:
|
|
||||||
// - all devices, configuration for each device
|
|
||||||
// probably multiple lines that are adding config strings
|
|
||||||
// - wires maybe separately, and/or as named connection points
|
|
||||||
// in tiles?
|
|
||||||
// - connection pairs that can be enabled/disabled
|
|
||||||
// - global flags and configuration registers
|
|
||||||
// - the static data should be optional (unused conn pairs,
|
|
||||||
// unused devices, wires)
|
|
||||||
//
|
|
||||||
// - each line should be in the global namespace, line order
|
|
||||||
// should not matter
|
|
||||||
// - file should be easily parsable with bison
|
|
||||||
// - lines should typically not exceed 80 characters
|
|
||||||
//
|
|
||||||
|
|
||||||
int read_floorplan(struct fpga_model *model, FILE *f);
|
int read_floorplan(struct fpga_model *model, FILE *f);
|
||||||
#define FP_DEFAULT 0x0000
|
#define FP_DEFAULT 0x0000
|
||||||
#define FP_NO_HEADER 0x0001
|
#define FP_NO_HEADER 0x0001
|
||||||
|
|
108
libs/model.h
108
libs/model.h
|
@ -320,7 +320,7 @@ const char* logicin_s(int wire, int routing_io);
|
||||||
enum fpgadev_type
|
enum fpgadev_type
|
||||||
{ DEV_NONE = 0,
|
{ DEV_NONE = 0,
|
||||||
DEV_LOGIC, DEV_TIEOFF, DEV_MACC, DEV_IOB,
|
DEV_LOGIC, DEV_TIEOFF, DEV_MACC, DEV_IOB,
|
||||||
DEV_ILOGIC, DEV_OLOGIC, DEV_IODELAY, DEV_BRAM16, DEV_BRAM8,
|
DEV_ILOGIC, DEV_OLOGIC, DEV_IODELAY, DEV_BRAM,
|
||||||
DEV_BUFH, DEV_BUFIO, DEV_BUFIO_FB, DEV_BUFPLL, DEV_BUFPLL_MCB,
|
DEV_BUFH, DEV_BUFIO, DEV_BUFIO_FB, DEV_BUFPLL, DEV_BUFPLL_MCB,
|
||||||
DEV_BUFGMUX, DEV_BSCAN, DEV_DCM, DEV_PLL, DEV_ICAP,
|
DEV_BUFGMUX, DEV_BSCAN, DEV_DCM, DEV_PLL, DEV_ICAP,
|
||||||
DEV_POST_CRC_INTERNAL, DEV_STARTUP, DEV_SLAVE_SPI,
|
DEV_POST_CRC_INTERNAL, DEV_STARTUP, DEV_SLAVE_SPI,
|
||||||
|
@ -329,7 +329,7 @@ enum fpgadev_type
|
||||||
#define FPGA_DEV_STR \
|
#define FPGA_DEV_STR \
|
||||||
{ 0, \
|
{ 0, \
|
||||||
"LOGIC", "TIEOFF", "MACC", "IOB", \
|
"LOGIC", "TIEOFF", "MACC", "IOB", \
|
||||||
"ILOGIC", "OLOGIC", "IODELAY", "BRAM16", "BRAM8", \
|
"ILOGIC", "OLOGIC", "IODELAY", "BRAM", \
|
||||||
"BUFH", "BUFIO", "BUFIO_FB", "BUFPLL", "BUFPLL_MCB", \
|
"BUFH", "BUFIO", "BUFIO_FB", "BUFPLL", "BUFPLL_MCB", \
|
||||||
"BUFGMUX", "BSCAN", "DCM", "PLL", "ICAP", \
|
"BUFGMUX", "BSCAN", "DCM", "PLL", "ICAP", \
|
||||||
"POST_CRC_INTERNAL", "STARTUP", "SLAVE_SPI", \
|
"POST_CRC_INTERNAL", "STARTUP", "SLAVE_SPI", \
|
||||||
|
@ -350,7 +350,9 @@ typedef int dev_type_idx_t;
|
||||||
|
|
||||||
#define NO_DEV -1
|
#define NO_DEV -1
|
||||||
#define FPGA_DEV(model, y, x, dev_idx) \
|
#define FPGA_DEV(model, y, x, dev_idx) \
|
||||||
(((dev_idx) == NO_DEV) ? 0 : (&YX_TILE(model, y, x)->devs[dev_idx]))
|
(((int) (dev_idx) == NO_DEV) ? 0 : (&YX_TILE(model, y, x)->devs[dev_idx]))
|
||||||
|
|
||||||
|
enum { DEVCFG_FALSE = 1, DEVCFG_TRUE };
|
||||||
|
|
||||||
//
|
//
|
||||||
// DEV_LOGIC
|
// DEV_LOGIC
|
||||||
|
@ -664,15 +666,45 @@ enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
// requirements for valid bram
|
// requirements for valid bram
|
||||||
// rstram and rst_priority must be set for A and B.
|
// - rstram and rst_priority must be set for A and B.
|
||||||
// todo: haven't decided whether dev_bram should be one structure
|
|
||||||
// for 8+16 or two separate structures
|
|
||||||
struct fpgadev_bram16
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
struct fpgadev_bram8
|
enum { BRAM16 = 1, BRAM8 }; // subtype
|
||||||
|
enum { BRAM_TDP = 1, BRAM_SDP, BRAM_SP };
|
||||||
|
enum { BRAM_RST_SYNC = 1, BRAM_RST_ASYNC };
|
||||||
|
enum { BRAM_WIDTH_0 = 1, BRAM_WIDTH_1, BRAM_WIDTH_2, BRAM_WIDTH_4, BRAM_WIDTH_9, BRAM_WIDTH_18, BRAM_WIDTH_36 };
|
||||||
|
enum { BRAM_WRITE_FIRST = 1, BRAM_READ_FIRST, BRAM_NO_CHANGE };
|
||||||
|
enum { BRAM_OUTREG_ON = 1, BRAM_OUTREG_OFF };
|
||||||
|
enum { BRAM_RST_PRIORITY_SR = 1, BRAM_RST_PRIORITY_CE };
|
||||||
|
|
||||||
|
// fpgadev_bram configures either a bram16 or a bram8 device.
|
||||||
|
// see ug383
|
||||||
|
struct fpgadev_bram
|
||||||
{
|
{
|
||||||
|
int *data; // points to 1024 (BRAM16) or 512 (BRAM8) words (each 16+2=18 bits)
|
||||||
|
int ram_mode; // BRAM8 only: BRAM_TDP, BRAM_SDP, BRAM_SP (?)
|
||||||
|
int rst_type; // BRAM_RST_SYNC, BRAM_RST_ASYNC
|
||||||
|
|
||||||
|
// Output latch/register init value after configuration:
|
||||||
|
int out_init_a, out_init_b;
|
||||||
|
|
||||||
|
// Output latch/register value after reset:
|
||||||
|
int srval_a, srval_b;
|
||||||
|
|
||||||
|
int data_width_a, data_width_b; // BRAM_WIDTH_0..36
|
||||||
|
int write_mode_a, write_mode_b; // BRAM_WRITE_FIRST, BRAM_READ_FIRST, BRAM_NO_CHANGE
|
||||||
|
int doa_reg, dob_reg; // BRAM_OUTREG_ON, BRAM_OUTREG_OFF
|
||||||
|
int rst_priority_a, rst_priority_b; // BRAM_RST_PRIORITY_SR, BRAM_RST_PRIORITY_CE
|
||||||
|
int en_rstram_a, en_rstram_b; // DEVCFG_FALSE, DEVCFG_TRUE
|
||||||
|
|
||||||
|
// inverter bits (DEVCFG_FALSE, DEVCFG_TRUE)
|
||||||
|
// Default polarity is active high (rising edge for clka/clkb).
|
||||||
|
// With invert = true this will change to active low (falling
|
||||||
|
// edge for clka/clkb).
|
||||||
|
int clka_inv, clkb_inv;
|
||||||
|
int ena_inv, enb_inv;
|
||||||
|
int reg_cea_inv, reg_ceb_inv;
|
||||||
|
int rsta_inv, rstb_inv;
|
||||||
|
int wea_inv[4], web_inv[4]; // only 2 used for BRAM8 (wea-wel, web-weu)
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -739,8 +771,10 @@ struct fpga_device
|
||||||
{
|
{
|
||||||
enum fpgadev_type type;
|
enum fpgadev_type type;
|
||||||
// subtypes:
|
// subtypes:
|
||||||
|
// --- todo: wouldn't it be better to have the subtype inside the fpgadev structures?
|
||||||
// IOB: IOBM, IOBS
|
// IOB: IOBM, IOBS
|
||||||
// LOGIC: LOGIC_M, LOGIC_L, LOGIC_X
|
// LOGIC: LOGIC_M, LOGIC_L, LOGIC_X
|
||||||
|
// BRAM: BRAM16, BRAM8
|
||||||
int subtype;
|
int subtype;
|
||||||
int instantiated;
|
int instantiated;
|
||||||
|
|
||||||
|
@ -761,8 +795,7 @@ struct fpga_device
|
||||||
struct fpgadev_bufgmux bufgmux;
|
struct fpgadev_bufgmux bufgmux;
|
||||||
struct fpgadev_bufio bufio;
|
struct fpgadev_bufio bufio;
|
||||||
struct fpgadev_bscan bscan;
|
struct fpgadev_bscan bscan;
|
||||||
struct fpgadev_bram16 bram16;
|
struct fpgadev_bram bram;
|
||||||
struct fpgadev_bram8 bram8;
|
|
||||||
} u;
|
} u;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1200,54 +1233,3 @@ struct w_net
|
||||||
|
|
||||||
int add_conn_net(struct fpga_model* model, int add_pref, const struct w_net *net);
|
int add_conn_net(struct fpga_model* model, int add_pref, const struct w_net *net);
|
||||||
|
|
||||||
#if 0
|
|
||||||
bram16:
|
|
||||||
int *data; // points to 1024 words (each 16+2=18 bits)
|
|
||||||
int clka_inv; // DEVCFG_INV_Y, DEVCFG_INV_N
|
|
||||||
int clkb_inv;
|
|
||||||
int data_width_a; // 0,1,2,4,9,18,36
|
|
||||||
int data_width_b; // 0,1,2,4,9,18,36
|
|
||||||
int doa_reg; // BRAM_OUTREG_ON, BRAM_OUTREG_OFF
|
|
||||||
int dob_reg;
|
|
||||||
int ena_inv;
|
|
||||||
int enb_inv; // BRAM_ENB_INV_Y, BRAM_ENB_INV_N
|
|
||||||
int reg_cea_inv;
|
|
||||||
int reg_ceb_inv;
|
|
||||||
int rsta_inv;
|
|
||||||
int rstb_inv;
|
|
||||||
int wea_inv[4];
|
|
||||||
int web_inv[4];
|
|
||||||
int rst_type; // BRAM_RST_SYNC, BRAM_RST_ASYNC
|
|
||||||
int write_mode_a; // BRAM_WRITE_FIRST, BRAM_READ_FIRST, BRAM_NO_CHANGE
|
|
||||||
int write_mode_b;
|
|
||||||
int ram_mode; // BRAM_TDP, BRAM_SDP, BRAM_SP
|
|
||||||
int rst_priority_a; // BRAM_RST_PRIORITY_SR, BRAM_RST_PRIORITY_CE
|
|
||||||
int rst_priority_b; // BRAM_RST_PRIORITY_SR, BRAM_RST_PRIORITY_CE
|
|
||||||
int en_rstram_a; // DEVCFG_FALSE, DEVCFG_TRUE
|
|
||||||
int en_rstram_b; // DEVCFG_FALSE, DEVCFG_TRUE
|
|
||||||
|
|
||||||
bram8:
|
|
||||||
int *data; // points to 512 words (each 16+2=18 bits)
|
|
||||||
int clk_awr_inv; // DEVCFG_INV_Y, DEVCFG_INV_N
|
|
||||||
int clk_brd_inv;
|
|
||||||
int data_width_a; // 0,1,2,4,9,18,36
|
|
||||||
int data_width_b; // 0,1,2,4,9,18,36
|
|
||||||
int doa_reg; // BRAM_OUTREG_ON, BRAM_OUTREG_OFF
|
|
||||||
int dob_reg;
|
|
||||||
int en_awr_inv;
|
|
||||||
int en_brd_inv; // BRAM_ENB_INV_Y, BRAM_ENB_INV_N
|
|
||||||
int reg_cea_inv;
|
|
||||||
int reg_ceb_reg_ce_inv;
|
|
||||||
int rsta_inv;
|
|
||||||
int rstb_rst_inv;
|
|
||||||
int wea_wel_inv[2];
|
|
||||||
int web_weu_inv[2];
|
|
||||||
int rst_type; // BRAM_RST_SYNC, BRAM_RST_ASYNC
|
|
||||||
int write_mode_a; // BRAM_WRITE_FIRST, BRAM_READ_FIRST, BRAM_NO_CHANGE
|
|
||||||
int write_mode_b;
|
|
||||||
int ram_mode; // BRAM_TDP, BRAM_SDP, BRAM_SP
|
|
||||||
int rst_priority_a; // BRAM_RST_PRIORITY_SR, BRAM_RST_PRIORITY_CE
|
|
||||||
int rst_priority_b; // BRAM_RST_PRIORITY_SR, BRAM_RST_PRIORITY_CE
|
|
||||||
int en_rstram_a; // DEVCFG_FALSE, DEVCFG_TRUE
|
|
||||||
int en_rstram_b; // DEVCFG_FALSE, DEVCFG_TRUE
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -3197,7 +3197,7 @@ static int connect_clk_sr(struct fpga_model* model, const char* clk_sr)
|
||||||
for (x = LEFT_SIDE_WIDTH; x < model->x_width - RIGHT_SIDE_WIDTH; x++) {
|
for (x = LEFT_SIDE_WIDTH; x < model->x_width - RIGHT_SIDE_WIDTH; x++) {
|
||||||
if (is_atx(X_FABRIC_BRAM_ROUTING_COL, model, x)) {
|
if (is_atx(X_FABRIC_BRAM_ROUTING_COL, model, x)) {
|
||||||
for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) {
|
for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) {
|
||||||
if (has_device(model, y, x+2, DEV_BRAM16)) {
|
if (has_device(model, y, x+2, DEV_BRAM)) {
|
||||||
for (i = 0; i <= 3; i++) {
|
for (i = 0; i <= 3; i++) {
|
||||||
struct w_net n = {
|
struct w_net n = {
|
||||||
.last_inc = 1, .num_pts = 3, .pt =
|
.last_inc = 1, .num_pts = 3, .pt =
|
||||||
|
|
|
@ -146,11 +146,9 @@ int init_devices(struct fpga_model* model)
|
||||||
for (y = TOP_IO_TILES; y < model->y_height-BOT_IO_TILES; y++) {
|
for (y = TOP_IO_TILES; y < model->y_height-BOT_IO_TILES; y++) {
|
||||||
if (!(YX_TILE(model, y, x)->flags & TF_BRAM_DEV))
|
if (!(YX_TILE(model, y, x)->flags & TF_BRAM_DEV))
|
||||||
continue;
|
continue;
|
||||||
if ((rc = add_dev(model, y, x, DEV_BRAM16, 0)))
|
if ((rc = add_dev(model, y, x, DEV_BRAM, 0)))
|
||||||
goto fail;
|
goto fail;
|
||||||
if ((rc = add_dev(model, y, x, DEV_BRAM8, 0)))
|
if ((rc = add_dev(model, y, x, DEV_BRAM, 0)))
|
||||||
goto fail;
|
|
||||||
if ((rc = add_dev(model, y, x, DEV_BRAM8, 0)))
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1722,7 +1722,7 @@ static int init_bram(struct fpga_model *model)
|
||||||
if (!is_atx(X_FABRIC_BRAM_COL, model, x))
|
if (!is_atx(X_FABRIC_BRAM_COL, model, x))
|
||||||
continue;
|
continue;
|
||||||
for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) {
|
for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) {
|
||||||
if (!has_device(model, y, x, DEV_BRAM16))
|
if (!has_device(model, y, x, DEV_BRAM))
|
||||||
continue;
|
continue;
|
||||||
{ const char* pairs[] = {
|
{ const char* pairs[] = {
|
||||||
"BRAM_CLK%c_INT1", "RAMB16BWER_CLK%c",
|
"BRAM_CLK%c_INT1", "RAMB16BWER_CLK%c",
|
||||||
|
|
|
@ -285,6 +285,7 @@ const struct xc_die *xc_die_info(int idcode)
|
||||||
case XC6SLX9: return &xc6slx9_info;
|
case XC6SLX9: return &xc6slx9_info;
|
||||||
}
|
}
|
||||||
HERE();
|
HERE();
|
||||||
|
fprintf(stderr, "#E unknown id_code %i\n", idcode);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ static int print_line(const struct line_buf* line)
|
||||||
|
|
||||||
if (!line->buf[0]) return 0;
|
if (!line->buf[0]) return 0;
|
||||||
if (!line->sequence_size || line->left_digit_start_o < 0) {
|
if (!line->sequence_size || line->left_digit_start_o < 0) {
|
||||||
printf(line->buf);
|
printf("%s", line->buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (line->right_digit_start_o < 0)
|
if (line->right_digit_start_o < 0)
|
||||||
|
@ -53,7 +53,7 @@ static int print_line(const struct line_buf* line)
|
||||||
line->right_digit_base,
|
line->right_digit_base,
|
||||||
line->right_digit_base+line->sequence_size,
|
line->right_digit_base+line->sequence_size,
|
||||||
&line->buf[line->right_digit_end_o]);
|
&line->buf[line->right_digit_end_o]);
|
||||||
printf(buf);
|
printf("%s", buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
# For details see the UNLICENSE file at the root of the source tree.
|
# For details see the UNLICENSE file at the root of the source tree.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
CC = clang-3.6
|
||||||
LDLIBS += `pkg-config libftdi --libs`
|
LDLIBS += `pkg-config libftdi --libs`
|
||||||
OBJS := mini-jtag.o load-bits.o jtag.o
|
OBJS := mini-jtag.o load-bits.o jtag.o
|
||||||
|
|
||||||
|
|
|
@ -409,7 +409,7 @@ int main(int argc, char** argv)
|
||||||
// print first 800 lines
|
// print first 800 lines
|
||||||
for (i = 0; i < 800; i++) {
|
for (i = 0; i < 800; i++) {
|
||||||
if (i >= s_numlines) break;
|
if (i >= s_numlines) break;
|
||||||
printf(s_lines[i]);
|
printf("%s", s_lines[i]);
|
||||||
}
|
}
|
||||||
// move up last 200 lines to beginning of buffer
|
// move up last 200 lines to beginning of buffer
|
||||||
if (s_numlines > i) {
|
if (s_numlines > i) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user