- a few things moved from custom text to json

- switched to llvm, fixed a few warnings
This commit is contained in:
Wolfgang Spraul 2015-03-15 16:42:35 -04:00
parent 7d872ef24f
commit ad0d2924df
18 changed files with 377 additions and 279 deletions

View File

@ -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
View File

@ -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

View File

@ -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);
} }

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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 ]");
} }
// //

View File

@ -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,

View File

@ -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);
} }

View File

@ -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

View File

@ -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

View File

@ -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 =

View File

@ -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;
} }
} }

View File

@ -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",

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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

View File

@ -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) {