diff --git a/Makefile b/Makefile index 70b5a9a..a9eb26e 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ # For details see the UNLICENSE file at the root of the source tree. # +CC = clang-3.6 CFLAGS += -I$(CURDIR)/libs diff --git a/README b/README index 5248ab4..8c12274 100644 --- a/README +++ b/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 - fpgatools is a toolchain to program field-programmable gate arrays - (FPGAs). The only supported chip at this time is the xc6slx9, a - 45nm-generation fpga with 5720 6-input LUTs, block ram and - multiply-accumulate devices. + fpgatools converts the configuration of an FPGA between + JSON and bitstream representation. - *) maximize chip performance - *) fast development cycles - *) independent toolchain that only depends on free software - *) reconfigure on-chip - *) include get-started tools such as jtag, debugging, parts data - and hardware designs - *) design flow that includes asic manufacturing - *) lightweight C implementation without GUI + The only supported chips at this time is the xc6slx9, a 45nm-generation + FPGA with 5720 6-input LUTs, block ram and multiply-accumulate + resources. + + Also not included are place and route tools or other higher-level + logic optimization, synthesis, Verilog, HLS, etc. + Future work on integrating with graywolf or yosys might be an option. + 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 - *) license: public domain + *) free software, released into the public domain (see + UNLICENSE for details) FAQ todo Libraries -- libfpga-cores reusable cores -- libfpga-stdlib standard design elements on top of libfpga-control - 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-bit reads and writes .bit bitstream files @@ -58,34 +53,27 @@ Profiling ~# perf annotate ~# 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 -- plain C, no C++ -- simple Makefiles -- text-based file formats -- automatic test suite -- public domain software +TODO (as of 2015-03) -TODO (as of February, 2013) - -short-term (1 month): +short-term (3 months): * support block memory - -> develop structure of dev_bram16/8 -> write block_mem autotest -* example: counter (including clock, jtag) +* support macc +* support pll_adv +* support dcm +* support ilogic2/ologic2 -mid-term (6 months): -* example: j1 soc -* hls: llvm backend -* maybe fp2bit should natively write ieee1532 and separate tools convert - from ieee1532 to .bit and other formats -* macc +mid-term (12 months): +* example: counter (including clock, jtag) * more cases in logic block configuration * autotest: fix bugs in lut_encoding, logic_cfg, routing_sw, io_sw tests * 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: - switchbox description into bit parser/generator (bit_frames.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 * move all part-specific static data into xc_info() -long-term (>6 months): +long-term (>12 months): * auto-crc calculation in .bit file * MCB switches and connections -* support lm32 or openrisc core, either via libfpga or iverilog backend -* ipv6 or vnc in hardware? -* iverilog fpga backend +* maybe fp2bit should natively write ieee1532 and separate tools convert + from ieee1532 to .bit and other formats * 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 diff --git a/autotest.c b/autotest.c index 152ef23..27a70d1 100644 --- a/autotest.c +++ b/autotest.c @@ -49,7 +49,7 @@ static int dump_file(const char* path) || !strncmp(line, "+++ ", 4) || !strncmp(line, "@@ ", 3)) continue; - printf(line); + printf("%s", line); } fclose(f); } diff --git a/libs/Makefile b/libs/Makefile index 159125a..8596b4e 100644 --- a/libs/Makefile +++ b/libs/Makefile @@ -6,6 +6,8 @@ # For details see the UNLICENSE file at the root of the source tree. # +CC = clang-3.6 + LIBS_VERSION_MAJOR = 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 \ model_ports.o model_conns.o model_switches.o model_helper.o LIBFPGA_FLOORPLAN_OBJS = floorplan.o -LIBFPGA_CONTROL_OBJS = control.o -LIBFPGA_CORES_OBJS = parts.o helper.o +LIBFPGA_CONTROL_OBJS = control.o 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) 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 -libfpga-cores.a: $(LIBFPGA_CORES_OBJS) - libfpga-bit.a: $(LIBFPGA_BIT_OBJS) libfpga-model.a: $(LIBFPGA_MODEL_OBJS) @@ -45,8 +44,6 @@ libfpga-control.a: $(LIBFPGA_CONTROL_OBJS) $(AR) $@ $^ $(RANLIB) $@ -libfpga-cores.so: $(LIBFPGA_CORES_OBJS) - libfpga-bit.so: $(LIBFPGA_BIT_OBJS) libfpga-model.so: $(LIBFPGA_MODEL_OBJS) diff --git a/libs/bit.h b/libs/bit.h index c6bcc0c..39eb6dc 100644 --- a/libs/bit.h +++ b/libs/bit.h @@ -7,15 +7,14 @@ // xc6 configuration registers, documentation in ug380, page90 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, GENERAL1, GENERAL2, GENERAL3, GENERAL4, GENERAL5, MODE_REG, PU_GWE, PU_GTS, MFWR, CCLK_FREQ, SEU_OPT, EXP_SIGN, RDBK_SIGN, BOOTSTS, EYE_MASK, CBC_REG }; -#define REG_NOOP -1 // pseudo register for noops - #define COR1_DEF 0x3D00 #define COR1_CRC_BYPASS 0x0010 #define COR2_DEF 0x09EE diff --git a/libs/bit_regs.c b/libs/bit_regs.c index 6a27fa4..e7ff3e4 100644 --- a/libs/bit_regs.c +++ b/libs/bit_regs.c @@ -680,6 +680,8 @@ static int dump_maj_logic(const uint8_t* bits, int row, int major) return 0; } +#if 0 + typedef struct ramb16_cfg { uint8_t byte[64]; @@ -851,6 +853,7 @@ static void print_ramb16_cfg(ramb16_cfg_t* cfg) } printf("}\n"); } +#endif static void printf_minor_diff(int row, int major, int minor, 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) { - ramb16_cfg_t ramb16_cfg[4]; - int minor, i, j, offset_in_frame; +// ramb16_cfg_t ramb16_cfg[4]; +// int j, offset_in_frame; + int minor, i; for (minor = 0; minor < get_major_minors(XC6SLX9, major); minor++) printf_clock(&bits[minor*FRAME_SIZE], row, major, minor); diff --git a/libs/control.c b/libs/control.c index 0dc6879..00bb0aa 100644 --- a/libs/control.c +++ b/libs/control.c @@ -171,7 +171,7 @@ static const char* dev_str[] = FPGA_DEV_STR; 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; } 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]; } +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, 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) { struct fpga_net* net; + dev_idx_t dev_idx; fnet_useidx(model, net_i); 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].x = x; 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); - RC_ASSERT(model, net->el[net->len].dev_idx != NO_DEV); + dev_idx = fpga_dev_idx(model, y, x, type, type_idx); + RC_ASSERT(model, dev_idx != NO_DEV); + net->el[net->len].dev_idx = dev_idx; net->len++; 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); if (!pin_str) { HERE(); return; } - snprintf(buf, sizeof(buf), "net %i %s y%i x%i %s %i pin %s\n", - net_i, in_pin ? "in" : "out", el->y, el->x, + snprintf(buf, sizeof(buf), " { \"type\" : \"%s\", \"y\" : %i, \"x\" : %i, " + "\"dev\" : \"%s\", \"dev_idx\" : %i, \"pin\" : \"%s\" }", + in_pin ? "in" : "out", el->y, el->x, fdev_type2str(tile->devs[dev_idx].type), fdev_typeidx(model, el->y, el->x, dev_idx), 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) { struct fpga_net* net; - int i; + int i, first_line; net = fnet_get(model, net_i); if (!net) { HERE(); return; } + fprintf(f, "[\n"); + first_line = 1; 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) { fprintf_inout_pin(f, model, net_i, &net->el[i]); continue; } // switch - fprintf(f, "net %i sw y%i x%i %s\n", - net_i, net->el[i].y, net->el[i].x, - fpga_switch_print(model, net->el[i].y, + fprintf(f, " { \"type\" : \"sw\", \"y\" : %i, \"x\" : %i%s }", + net->el[i].y, net->el[i].x, + fpga_switch_print_json(model, net->el[i].y, net->el[i].x, net->el[i].idx)); } + fprintf(f, "\n ]"); } // diff --git a/libs/control.h b/libs/control.h index 6036f8b..ba88dd8 100644 --- a/libs/control.h +++ b/libs/control.h @@ -190,6 +190,8 @@ const char* fpga_switch_str(struct fpga_model* model, int y, int x, swidx_t swidx, int from_to); str16_t fpga_switch_str_i(struct fpga_model* model, int y, int x, 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, swidx_t swidx); int fpga_switch_is_bidir(struct fpga_model* model, int y, int x, diff --git a/libs/floorplan.c b/libs/floorplan.c index f326e20..33cc2c7 100644 --- a/libs/floorplan.c +++ b/libs/floorplan.c @@ -11,14 +11,14 @@ #include "control.h" #include "floorplan.h" -void printf_version(FILE* f) -{ - fprintf(f, "fpga_floorplan_format 1\n"); -} - #define PRINT_FLAG(fp, flag) if ((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) { struct fpga_tile* tile; @@ -67,110 +67,143 @@ int printf_IOB(FILE *f, struct fpga_model *model, { struct fpga_tile *tile; char pref[256]; - int dev_i; + int dev_i, first_line; dev_i = fpga_dev_idx(model, y, x, DEV_IOB, type_idx); RC_ASSERT(model, dev_i != NO_DEV); tile = YX_TILE(model, y, x); if (config_only && !(tile->devs[dev_i].instantiated)) 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) - fprintf(f, "%s type %s\n", pref, + if (!config_only) { + fprintf(f, "%s%s\"type\" : \"%s\" }", first_line ? "" : ",\n", pref, tile->devs[dev_i].subtype == IOBM ? "M" : "S"); - if (tile->devs[dev_i].u.iob.istandard[0]) - fprintf(f, "%s istd %s\n", pref, + first_line = 0; + } + 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); - if (tile->devs[dev_i].u.iob.ostandard[0]) - fprintf(f, "%s ostd %s\n", pref, + first_line = 0; + } + 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); + first_line = 0; + } switch (tile->devs[dev_i].u.iob.bypass_mux) { 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; 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; 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; case 0: break; default: RC_FAIL(model, EINVAL); } switch (tile->devs[dev_i].u.iob.I_mux) { 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; case IMUX_I: - fprintf(f, "%s imux I\n", pref); + fprintf(f, "%s%s\"imux\" : \"I\" }", first_line ? "" : ",\n", pref); + first_line = 0; break; case 0: break; default: RC_FAIL(model, EINVAL); } - if (tile->devs[dev_i].u.iob.drive_strength) - fprintf(f, "%s strength %i\n", pref, + if (tile->devs[dev_i].u.iob.drive_strength) { + fprintf(f, "%s%s\"strength\" : %i }", first_line ? "" : ",\n", pref, tile->devs[dev_i].u.iob.drive_strength); + first_line = 0; + } switch (tile->devs[dev_i].u.iob.slew) { case SLEW_SLOW: - fprintf(f, "%s slew SLOW\n", pref); + fprintf(f, "%s%s\"slew\" : \"SLOW\" }", first_line ? "" : ",\n", pref); + first_line = 0; break; case SLEW_FAST: - fprintf(f, "%s slew FAST\n", pref); + fprintf(f, "%s%s\"slew\" : \"FAST\" }", first_line ? "" : ",\n", pref); + first_line = 0; break; case SLEW_QUIETIO: - fprintf(f, "%s slew QUIETIO\n", pref); + fprintf(f, "%s%s\"slew\" : \"QUIETIO\" }", first_line ? "" : ",\n", pref); + first_line = 0; break; case 0: break; default: RC_FAIL(model, EINVAL); } - if (tile->devs[dev_i].u.iob.O_used) - fprintf(f, "%s O_used\n", pref); + if (tile->devs[dev_i].u.iob.O_used) { + fprintf(f, "%s%s\"O_used\" : true }", first_line ? "" : ",\n", pref); + first_line = 0; + } switch (tile->devs[dev_i].u.iob.suspend) { 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; case SUSP_3STATE: - fprintf(f, "%s suspend 3STATE\n", pref); + fprintf(f, "%s%s\"suspend\" : \"3STATE\" }", first_line ? "" : ",\n", pref); + first_line = 0; break; 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; 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; 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; 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; case 0: break; default: RC_FAIL(model, EINVAL); } switch (tile->devs[dev_i].u.iob.in_term) { 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; 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; 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; 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; case 0: break; default: RC_FAIL(model, EINVAL); } switch (tile->devs[dev_i].u.iob.out_term) { 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; 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; 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; 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; 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; char pref[256]; 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); RC_ASSERT(model, dev_i != NO_DEV); tile = YX_TILE(model, y, x); if (config_only && !(tile->devs[dev_i].instantiated)) 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) { switch (tile->devs[dev_i].subtype) { case LOGIC_X: - fprintf(f, "%s type X\n", pref); + fprintf(f, "%s%s\"type\" : \"X\" }", first_line ? "" : ",\n", pref); + first_line = 0; break; case LOGIC_L: - fprintf(f, "%s type L\n", pref); + fprintf(f, "%s%s\"type\" : \"L\" }", first_line ? "" : ",\n", pref); + first_line = 0; break; case LOGIC_M: - fprintf(f, "%s type M\n", pref); + fprintf(f, "%s%s\"type\" : \"M\" }", first_line ? "" : ",\n", pref); + first_line = 0; break; 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) { RC_ASSERT(model, !ULL_HIGH32(cfg->a2d[j].lut6_val)); if (print_hex_vals) - fprintf(f, "%s %c6_lut_val 0x%016lX\n", - pref, 'A'+j, cfg->a2d[j].lut6_val); + fprintf(f, "%s%s\"%c6_lut_val\" : \"0x%016lX\" }", + first_line ? "" : ",\n", pref, 'A'+j, cfg->a2d[j].lut6_val); else { str = bool_bits2str(cfg->a2d[j].lut6_val, 32); RC_ASSERT(model, str); - fprintf(f, "%s %c6_lut_str (A6+~A6)*(%s)\n", - pref, 'A'+j, str); + fprintf(f, "%s%s\"%c6_lut_str\" : \"(A6+~A6)*(%s)\" }", + first_line ? "" : ",\n", pref, 'A'+j, str); } + first_line = 0; } if (print_hex_vals) - fprintf(f, "%s %c5_lut_val 0x%08X\n", - pref, 'A'+j, ULL_LOW32(cfg->a2d[j].lut5_val)); + fprintf(f, "%s%s\"%c5_lut_val\" : \"0x%08X\" }", + first_line ? "" : ",\n", pref, 'A'+j, ULL_LOW32(cfg->a2d[j].lut5_val)); else { str = bool_bits2str(cfg->a2d[j].lut5_val, 32); RC_ASSERT(model, str); - fprintf(f, "%s %c5_lut_str %s\n", - pref, 'A'+j, str); + fprintf(f, "%s%s\"%c5_lut_str\" : \"%s\" }", + first_line ? "" : ",\n", pref, 'A'+j, str); } + first_line = 0; } else { if (cfg->a2d[j].flags & LUT6VAL_SET) { if (print_hex_vals) - fprintf(f, "%s %c6_lut_val 0x%016lX\n", - pref, 'A'+j, cfg->a2d[j].lut6_val); + fprintf(f, "%s%s\"%c6_lut_val\" : \"0x%016lX\" }", + first_line ? "" : ",\n", pref, 'A'+j, cfg->a2d[j].lut6_val); else { str = bool_bits2str(cfg->a2d[j].lut6_val, 64); RC_ASSERT(model, str); - fprintf(f, "%s %c6_lut_str %s\n", - pref, 'A'+j, str); + fprintf(f, "%s%s\"%c6_lut_str\" : \"%s\" }", + first_line ? "" : ",\n", pref, 'A'+j, str); } + first_line = 0; } } - if (cfg->a2d[j].flags & OUT_USED) - fprintf(f, "%s %c_used\n", pref, 'A'+j); + if (cfg->a2d[j].flags & OUT_USED) { + fprintf(f, "%s%s\"%c_used\" : true }", first_line ? "" : ",\n", pref, 'A'+j); + first_line = 0; + } switch (cfg->a2d[j].ff) { 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; 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; 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; 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; case 0: break; default: RC_FAIL(model, EINVAL); } switch (cfg->a2d[j].ff_mux) { 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; 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; 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; 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; 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; 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; 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; 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; case 0: break; default: RC_FAIL(model, EINVAL); } switch (cfg->a2d[j].ff_srinit) { 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; 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; case 0: break; default: RC_FAIL(model, EINVAL); } switch (cfg->a2d[j].out_mux) { 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; 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; 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; 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; 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; 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; 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; 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; case 0: break; default: RC_FAIL(model, EINVAL); } switch (cfg->a2d[j].ff5_srinit) { 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; 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; case 0: break; default: RC_FAIL(model, EINVAL); } switch (cfg->a2d[j].cy0) { 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; 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; case 0: break; default: RC_FAIL(model, EINVAL); } // distributed memory related: switch (cfg->a2d[j].ram_mode) { 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; 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; 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; 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; 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; 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; case 0: break; default: RC_FAIL(model, EINVAL); } switch (cfg->a2d[j].di_mux) { 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; 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; 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; 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; case 0: break; default: RC_FAIL(model, EINVAL); } } switch (cfg->clk_inv) { 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; case CLKINV_CLK: - fprintf(f, "%s clk CLK\n", pref); + fprintf(f, "%s%s\"clk\" : \"CLK\" }", first_line ? "" : ",\n", pref); + first_line = 0; break; case 0: break; default: RC_FAIL(model, EINVAL); } switch (cfg->sync_attr) { case SYNCATTR_SYNC: - fprintf(f, "%s sync SYNC\n", pref); + fprintf(f, "%s%s\"sync\" : \"SYNC\" }", first_line ? "" : ",\n", pref); + first_line = 0; break; case SYNCATTR_ASYNC: - fprintf(f, "%s sync ASYNC\n", pref); + fprintf(f, "%s%s\"sync\" : \"ASYNC\" }", first_line ? "" : ",\n", pref); + first_line = 0; break; case 0: break; default: RC_FAIL(model, EINVAL); } - if (cfg->ce_used) - fprintf(f, "%s ce_used\n", pref); - if (cfg->sr_used) - fprintf(f, "%s sr_used\n", pref); + if (cfg->ce_used) { + fprintf(f, "%s%s\"ce_used\" : true }", first_line ? "" : ",\n", pref); + first_line = 0; + } + if (cfg->sr_used) { + fprintf(f, "%s%s\"sr_used\" : true }", first_line ? "" : ",\n", pref); + first_line = 0; + } switch (cfg->we_mux) { case WEMUX_WE: - fprintf(f, "%s wemux WE\n", pref); + fprintf(f, "%s%s\"wemux\" : \"WE\" }", first_line ? "" : ",\n", pref); + first_line = 0; break; case WEMUX_CE: - fprintf(f, "%s wemux CE\n", pref); + fprintf(f, "%s%s\"wemux\" : \"CE\" }", first_line ? "" : ",\n", pref); + first_line = 0; break; case 0: break; default: RC_FAIL(model, EINVAL); } - if (cfg->cout_used) - fprintf(f, "%s cout_used\n", pref); + if (cfg->cout_used) { + fprintf(f, "%s%s\"cout_used\" : true }", first_line ? "" : ",\n", pref); + first_line = 0; + } switch (cfg->precyinit) { case PRECYINIT_0: - fprintf(f, "%s precyinit 0\n", pref); + fprintf(f, "%s%s\"precyinit\" : \"0\" }", first_line ? "" : ",\n", pref); + first_line = 0; break; case PRECYINIT_1: - fprintf(f, "%s precyinit 1\n", pref); + fprintf(f, "%s%s\"precyinit\" : \"1\" }", first_line ? "" : ",\n", pref); + first_line = 0; break; case PRECYINIT_AX: - fprintf(f, "%s precyinit AX\n", pref); + fprintf(f, "%s%s\"precyinit\" : \"AX\" }", first_line ? "" : ",\n", pref); + first_line = 0; break; case 0: break; default: RC_FAIL(model, EINVAL); } - if (cfg->wa7_used) - fprintf(f, "%s wa7_used\n", pref); - if (cfg->wa8_used) - fprintf(f, "%s wa8_used\n", pref); + if (cfg->wa7_used) { + fprintf(f, "%s%s\"wa7_used\" : true }", first_line ? "" : ",\n", pref); + first_line = 0; + } + if (cfg->wa8_used) { + fprintf(f, "%s%s\"wa8_used\" : true }", first_line ? "" : ",\n", pref); + first_line = 0; + } RC_RETURN(model); } @@ -1016,16 +1113,21 @@ inst: 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; RC_CHECK(model); + fprintf(f, " \"devices\" : [\n"); + first_dev = 1; for (x = 0; x < model->x_width; x++) { for (y = 0; y < model->y_height; y++) { tile = YX_TILE(model, y, x); for (i = 0; i < tile->num_devs; i++) { if (config_only && !(tile->devs[i].instantiated)) continue; + if (!first_dev) + fprintf(f, ",\n"); + first_dev = 0; switch (tile->devs[i].type) { case DEV_IOB: printf_IOB(f, model, y, x, @@ -1053,13 +1155,15 @@ int printf_devices(FILE* f, struct fpga_model* model, int config_only) config_only); break; 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)); break; } } } } + if (!first_dev) fprintf(f, "\n"); + fprintf(f, " ]"); 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) { net_idx_t net_i; - int rc; + int rc, first_line; RC_CHECK(model); + fprintf(f, " \"nets\" : [\n"); + first_line = 1; 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); + } if (rc) FAIL(rc); + if (!first_line) fprintf(f, "\n"); + fprintf(f, " ]"); return 0; fail: 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) { - if (!(flags & FP_NO_HEADER)) - printf_version(f); + fprintf(f, "{\n"); + printf_version(f); if (model->rc) fprintf(f, "rc %i\n", model->rc); else { + fprintf(f, ",\n"); printf_devices(f, model, /*config_only*/ 1); + + fprintf(f, ",\n"); printf_nets(f, model); } + fprintf(f, "\n}\n"); RC_RETURN(model); } diff --git a/libs/floorplan.h b/libs/floorplan.h index 8ac053b..fa65ce2 100644 --- a/libs/floorplan.h +++ b/libs/floorplan.h @@ -5,25 +5,6 @@ // 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); #define FP_DEFAULT 0x0000 #define FP_NO_HEADER 0x0001 diff --git a/libs/model.h b/libs/model.h index b351ef9..7e6ae90 100644 --- a/libs/model.h +++ b/libs/model.h @@ -320,7 +320,7 @@ const char* logicin_s(int wire, int routing_io); enum fpgadev_type { DEV_NONE = 0, 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_BUFGMUX, DEV_BSCAN, DEV_DCM, DEV_PLL, DEV_ICAP, DEV_POST_CRC_INTERNAL, DEV_STARTUP, DEV_SLAVE_SPI, @@ -329,7 +329,7 @@ enum fpgadev_type #define FPGA_DEV_STR \ { 0, \ "LOGIC", "TIEOFF", "MACC", "IOB", \ - "ILOGIC", "OLOGIC", "IODELAY", "BRAM16", "BRAM8", \ + "ILOGIC", "OLOGIC", "IODELAY", "BRAM", \ "BUFH", "BUFIO", "BUFIO_FB", "BUFPLL", "BUFPLL_MCB", \ "BUFGMUX", "BSCAN", "DCM", "PLL", "ICAP", \ "POST_CRC_INTERNAL", "STARTUP", "SLAVE_SPI", \ @@ -350,7 +350,9 @@ typedef int dev_type_idx_t; #define NO_DEV -1 #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 @@ -664,15 +666,45 @@ enum { }; // requirements for valid bram -// 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 -{ -}; +// - rstram and rst_priority must be set for A and B. -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; // subtypes: + // --- todo: wouldn't it be better to have the subtype inside the fpgadev structures? // IOB: IOBM, IOBS // LOGIC: LOGIC_M, LOGIC_L, LOGIC_X + // BRAM: BRAM16, BRAM8 int subtype; int instantiated; @@ -761,8 +795,7 @@ struct fpga_device struct fpgadev_bufgmux bufgmux; struct fpgadev_bufio bufio; struct fpgadev_bscan bscan; - struct fpgadev_bram16 bram16; - struct fpgadev_bram8 bram8; + struct fpgadev_bram bram; } u; }; @@ -1200,54 +1233,3 @@ struct w_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 diff --git a/libs/model_conns.c b/libs/model_conns.c index 75959d8..2bc5d66 100644 --- a/libs/model_conns.c +++ b/libs/model_conns.c @@ -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++) { if (is_atx(X_FABRIC_BRAM_ROUTING_COL, model, x)) { 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++) { struct w_net n = { .last_inc = 1, .num_pts = 3, .pt = diff --git a/libs/model_devices.c b/libs/model_devices.c index bf5cbf7..e0cb007 100644 --- a/libs/model_devices.c +++ b/libs/model_devices.c @@ -146,11 +146,9 @@ int init_devices(struct fpga_model* model) for (y = TOP_IO_TILES; y < model->y_height-BOT_IO_TILES; y++) { if (!(YX_TILE(model, y, x)->flags & TF_BRAM_DEV)) continue; - if ((rc = add_dev(model, y, x, DEV_BRAM16, 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; - if ((rc = add_dev(model, y, x, DEV_BRAM8, 0))) + if ((rc = add_dev(model, y, x, DEV_BRAM, 0))) goto fail; } } diff --git a/libs/model_switches.c b/libs/model_switches.c index 4ee14ef..dd89448 100644 --- a/libs/model_switches.c +++ b/libs/model_switches.c @@ -1722,7 +1722,7 @@ static int init_bram(struct fpga_model *model) if (!is_atx(X_FABRIC_BRAM_COL, model, x)) continue; 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; { const char* pairs[] = { "BRAM_CLK%c_INT1", "RAMB16BWER_CLK%c", diff --git a/libs/parts.c b/libs/parts.c index 9b0b809..491d6b9 100644 --- a/libs/parts.c +++ b/libs/parts.c @@ -285,6 +285,7 @@ const struct xc_die *xc_die_info(int idcode) case XC6SLX9: return &xc6slx9_info; } HERE(); + fprintf(stderr, "#E unknown id_code %i\n", idcode); return 0; } diff --git a/merge_seq.c b/merge_seq.c index 700bbd3..39d6755 100644 --- a/merge_seq.c +++ b/merge_seq.c @@ -32,7 +32,7 @@ static int print_line(const struct line_buf* line) if (!line->buf[0]) return 0; if (!line->sequence_size || line->left_digit_start_o < 0) { - printf(line->buf); + printf("%s", line->buf); return 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->sequence_size, &line->buf[line->right_digit_end_o]); - printf(buf); + printf("%s", buf); return 0; } diff --git a/mini-jtag/Makefile b/mini-jtag/Makefile index a465fbb..dc6efb9 100644 --- a/mini-jtag/Makefile +++ b/mini-jtag/Makefile @@ -5,6 +5,7 @@ # For details see the UNLICENSE file at the root of the source tree. # +CC = clang-3.6 LDLIBS += `pkg-config libftdi --libs` OBJS := mini-jtag.o load-bits.o jtag.o diff --git a/sort_seq.c b/sort_seq.c index c9d8bca..1dcad2b 100644 --- a/sort_seq.c +++ b/sort_seq.c @@ -409,7 +409,7 @@ int main(int argc, char** argv) // print first 800 lines for (i = 0; i < 800; i++) { if (i >= s_numlines) break; - printf(s_lines[i]); + printf("%s", s_lines[i]); } // move up last 200 lines to beginning of buffer if (s_numlines > i) {