more json, some bram work

This commit is contained in:
Wolfgang Spraul 2015-04-01 17:13:32 -04:00
parent ad0d2924df
commit ea54683e8f
15 changed files with 612 additions and 566 deletions

2
.gitignore vendored
View File

@ -20,7 +20,7 @@
# binaries # binaries
# #
draw_svg_tiles draw_svg_tiles
new_fp fpinfo
hstrrep hstrrep
sort_seq sort_seq
merge_seq merge_seq

View File

@ -13,7 +13,7 @@ CFLAGS += -I$(CURDIR)/libs
LDFLAGS += -Wl,-rpath,$(CURDIR)/libs LDFLAGS += -Wl,-rpath,$(CURDIR)/libs
OBJS = autotest.o bit2fp.o printf_swbits.o draw_svg_tiles.o fp2bit.o \ OBJS = autotest.o bit2fp.o printf_swbits.o draw_svg_tiles.o fp2bit.o \
hstrrep.o merge_seq.o new_fp.o pair2net.o sort_seq.o hello_world.o \ hstrrep.o merge_seq.o fpinfo.o pair2net.o sort_seq.o hello_world.o \
blinking_led.o jtag_counter.o j1_blinking.o blinking_led.o jtag_counter.o j1_blinking.o
DYNAMIC_LIBS = libs/libfpga-model.so libs/libfpga-bit.so \ DYNAMIC_LIBS = libs/libfpga-model.so libs/libfpga-bit.so \
@ -24,7 +24,7 @@ DYNAMIC_LIBS = libs/libfpga-model.so libs/libfpga-bit.so \
.SECONDARY: .SECONDARY:
.SECONDEXPANSION: .SECONDEXPANSION:
all: new_fp fp2bit bit2fp printf_swbits draw_svg_tiles autotest hstrrep \ all: fpinfo fp2bit bit2fp printf_swbits draw_svg_tiles autotest hstrrep \
sort_seq merge_seq pair2net hello_world blinking_led jtag_counter \ sort_seq merge_seq pair2net hello_world blinking_led jtag_counter \
j1_blinking.o j1_blinking.o
@ -173,8 +173,8 @@ compare_%_sw.fco: compare_%.fp
compare_%_swbits.fco: printf_swbits compare_%_swbits.fco: printf_swbits
@./printf_swbits | sort > $@ @./printf_swbits | sort > $@
compare_%.fp: new_fp compare_%.fp: fpinfo
@./new_fp >$@ @./fpinfo >$@
# todo: .cnets not integrated yet # todo: .cnets not integrated yet
%.cnets: %.fp pair2net %.cnets: %.fp pair2net
@ -206,7 +206,7 @@ bit2fp: bit2fp.o $(DYNAMIC_LIBS)
printf_swbits: printf_swbits.o $(DYNAMIC_LIBS) printf_swbits: printf_swbits.o $(DYNAMIC_LIBS)
new_fp: new_fp.o $(DYNAMIC_LIBS) fpinfo: fpinfo.o $(DYNAMIC_LIBS)
draw_svg_tiles: CFLAGS += `pkg-config libxml-2.0 --cflags` draw_svg_tiles: CFLAGS += `pkg-config libxml-2.0 --cflags`
draw_svg_tiles: LDLIBS += `pkg-config libxml-2.0 --libs` draw_svg_tiles: LDLIBS += `pkg-config libxml-2.0 --libs`
@ -220,8 +220,8 @@ merge_seq: merge_seq.o $(DYNAMIC_LIBS)
hstrrep: hstrrep.o $(DYNAMIC_LIBS) hstrrep: hstrrep.o $(DYNAMIC_LIBS)
xc6slx9.fp: new_fp xc6slx9.fp: fpinfo
./new_fp > $@ ./fpinfo > $@
xc6slx9.svg: draw_svg_tiles xc6slx9.svg: draw_svg_tiles
./draw_svg_tiles | xmllint --pretty 1 - > $@ ./draw_svg_tiles | xmllint --pretty 1 - > $@
@ -229,7 +229,7 @@ xc6slx9.svg: draw_svg_tiles
clean: clean:
@make -C libs clean @make -C libs clean
rm -f $(OBJS) *.d rm -f $(OBJS) *.d
rm -f draw_svg_tiles new_fp hstrrep sort_seq merge_seq autotest rm -f draw_svg_tiles fpinfo hstrrep sort_seq merge_seq autotest
rm -f fp2bit bit2fp printf_swbits pair2net hello_world blinking_led rm -f fp2bit bit2fp printf_swbits pair2net hello_world blinking_led
rm -f jtag_counter j1_blinking rm -f jtag_counter j1_blinking
rm -f xc6slx9.fp xc6slx9.svg rm -f xc6slx9.fp xc6slx9.svg

11
README
View File

@ -2,7 +2,7 @@ Introduction
fpgatools converts the configuration of an FPGA between fpgatools converts the configuration of an FPGA between
JSON and bitstream representation. JSON and bitstream representation.
The only supported chips at this time is the xc6slx9, a 45nm-generation The only supported chip at this time is the xc6slx9, a 45nm-generation
FPGA with 5720 6-input LUTs, block ram and multiply-accumulate FPGA with 5720 6-input LUTs, block ram and multiply-accumulate
resources. resources.
@ -33,7 +33,8 @@ Design Utilities
- hello_world outputs an AND gate floorplan to stdout - hello_world outputs an AND gate floorplan to stdout
- blinking_led outputs blinking led design to stdout - blinking_led outputs blinking led design to stdout
- new_fp creates empty .fp floorplan file - fpinfo outputs information about tiles, devices, ports,
connections and switches in a floorplan
- fp2bit converts .fp floorplan into .bit bitstream - fp2bit converts .fp floorplan into .bit bitstream
- bit2fp converts .bit bitstream into .fp floorplan - bit2fp converts .bit bitstream into .fp floorplan
- draw_svg_tiles draws a simple .svg showing tile types - draw_svg_tiles draws a simple .svg showing tile types
@ -53,12 +54,6 @@ Profiling
~# perf annotate ~# perf annotate
~# perf report ~# perf report
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
TODO (as of 2015-03) TODO (as of 2015-03)
short-term (3 months): short-term (3 months):

View File

@ -103,9 +103,9 @@ static int diff_printf(struct test_state* tstate)
dest_f = fopen(path, "w"); dest_f = fopen(path, "w");
if (!dest_f) FAIL(errno); if (!dest_f) FAIL(errno);
rc = printf_devices(dest_f, tstate->model, /*config_only*/ 1); rc = printf_devices(dest_f, tstate->model, /*config_only*/ 1, /*no_json*/ 1);
if (rc) FAIL(rc); if (rc) FAIL(rc);
rc = printf_nets(dest_f, tstate->model); rc = printf_nets(dest_f, tstate->model, /*no_json*/ 1);
if (rc) FAIL(rc); if (rc) FAIL(rc);
fclose(dest_f); fclose(dest_f);
@ -382,7 +382,7 @@ static int test_switches(struct test_state* tstate, int y, int x,
if (switch_str[2] == '4') { if (switch_str[2] == '4') {
// base for len-4 wire // base for len-4 wire
if (tstate->dry_run) if (tstate->dry_run)
fnet_printf(stdout, tstate->model, net); fnet_printf(stdout, tstate->model, net, /*no_json*/ 1);
rc = diff_printf(tstate); rc = diff_printf(tstate);
if (rc) FAIL(rc); if (rc) FAIL(rc);
@ -420,7 +420,7 @@ static int test_switches(struct test_state* tstate, int y, int x,
// base for len-4 target // base for len-4 target
if (tstate->dry_run) if (tstate->dry_run)
fnet_printf(stdout, tstate->model, net); fnet_printf(stdout, tstate->model, net, /*no_json*/ 1);
rc = diff_printf(tstate); rc = diff_printf(tstate);
if (rc) FAIL(rc); if (rc) FAIL(rc);
@ -430,7 +430,7 @@ static int test_switches(struct test_state* tstate, int y, int x,
if (rc) FAIL(rc); if (rc) FAIL(rc);
if (tstate->dry_run) if (tstate->dry_run)
fnet_printf(stdout, tstate->model, net); fnet_printf(stdout, tstate->model, net, /*no_json*/ 1);
rc = diff_printf(tstate); rc = diff_printf(tstate);
if (rc) FAIL(rc); if (rc) FAIL(rc);
@ -605,7 +605,7 @@ static int test_routing_sw_from_logic(struct test_state *tstate,
swto.dest_x, conns.chain.set.sw, conns.chain.set.len); swto.dest_x, conns.chain.set.sw, conns.chain.set.len);
if (rc) FAIL(rc); if (rc) FAIL(rc);
if (tstate->dry_run) if (tstate->dry_run)
fnet_printf(stdout, tstate->model, net); fnet_printf(stdout, tstate->model, net, /*no_json*/ 1);
rc = test_switches(tstate, conns.dest_y, conns.dest_x, rc = test_switches(tstate, conns.dest_y, conns.dest_x,
conns.dest_str_i, net, done_list, done_list_len); conns.dest_str_i, net, done_list, done_list_len);

View File

@ -15,7 +15,7 @@ static void help_exit(int argc, char **argv)
"\n" "\n"
"%s - bitstream to floorplan\n" "%s - bitstream to floorplan\n"
"Usage: %s [--help] [--verbose] [--bit-header] [--bit-regs] [--bit-crc]\n" "Usage: %s [--help] [--verbose] [--bit-header] [--bit-regs] [--bit-crc]\n"
" %*s [--no-model] [--no-fp-header] <bitstream_file>\n" " %*s [--no-model] [--no-json] <bitstream_file>\n"
"\n", argv[0], argv[0], (int) strlen(argv[0]), ""); "\n", argv[0], argv[0], (int) strlen(argv[0]), "");
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
@ -23,7 +23,7 @@ static void help_exit(int argc, char **argv)
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
struct fpga_model model; struct fpga_model model;
int bit_header, bit_regs, bit_crc, fp_header, pull_model, file_arg; int bit_header, bit_regs, bit_crc, json, pull_model, file_arg;
int verbose, flags, rc = -1; int verbose, flags, rc = -1;
struct fpga_config config; struct fpga_config config;
@ -34,7 +34,7 @@ int main(int argc, char** argv)
bit_regs = 0; bit_regs = 0;
bit_crc = 0; bit_crc = 0;
pull_model = 1; pull_model = 1;
fp_header = 1; json = 1;
file_arg = 1; file_arg = 1;
while (file_arg < argc && !strncmp(argv[file_arg], "--", 2)) { while (file_arg < argc && !strncmp(argv[file_arg], "--", 2)) {
if (!strcmp(argv[file_arg], "--help")) if (!strcmp(argv[file_arg], "--help"))
@ -50,8 +50,8 @@ int main(int argc, char** argv)
bit_crc = 1; bit_crc = 1;
else if (!strcmp(argv[file_arg], "--no-model")) else if (!strcmp(argv[file_arg], "--no-model"))
pull_model = 0; pull_model = 0;
else if (!strcmp(argv[file_arg], "--no-fp-header")) else if (!strcmp(argv[file_arg], "--no-json"))
fp_header = 0; json = 0;
else break; else break;
file_arg++; file_arg++;
} }
@ -83,7 +83,7 @@ int main(int argc, char** argv)
// dump model // dump model
flags = FP_DEFAULT; flags = FP_DEFAULT;
if (!fp_header) flags |= FP_NO_HEADER; if (!json) flags |= FP_NO_JSON;
if ((rc = write_floorplan(stdout, &model, flags))) FAIL(rc); if ((rc = write_floorplan(stdout, &model, flags))) FAIL(rc);
// dump what doesn't fit into the model // dump what doesn't fit into the model

View File

@ -20,25 +20,32 @@ int main(int argc, char** argv)
if (argc > 1 && !strcmp(argv[1], "--no-conns")) if (argc > 1 && !strcmp(argv[1], "--no-conns"))
no_conns = 1; no_conns = 1;
printf("{\n");
printf_version(stdout); printf_version(stdout);
printf(",\n");
rc = printf_tiles(stdout, &model); rc = printf_tiles(stdout, &model);
if (rc) goto fail; if (rc) goto fail;
rc = printf_devices(stdout, &model, /*config_only*/ 0); printf(",\n");
rc = printf_devices(stdout, &model, /*config_only*/ 0, /*no_json*/ 0);
if (rc) goto fail; if (rc) goto fail;
printf(",\n");
rc = printf_ports(stdout, &model); rc = printf_ports(stdout, &model);
if (rc) goto fail; if (rc) goto fail;
if (!no_conns) { if (!no_conns) {
printf(",\n");
rc = printf_conns(stdout, &model); rc = printf_conns(stdout, &model);
if (rc) goto fail; if (rc) goto fail;
} }
printf(",\n");
rc = printf_switches(stdout, &model); rc = printf_switches(stdout, &model);
if (rc) goto fail; if (rc) goto fail;
printf("\n}\n");
return EXIT_SUCCESS; return EXIT_SUCCESS;
fail: fail:
return rc; return rc;

View File

@ -2315,6 +2315,10 @@ static void destruct_extract_state(struct extract_state *es)
es->yx_pos = 0; es->yx_pos = 0;
} }
//
// bscan
//
static int extract_bscan(struct extract_state *es) static int extract_bscan(struct extract_state *es)
{ {
int enum_i, bscan_y, bscan_x, bscan_type_idx; int enum_i, bscan_y, bscan_x, bscan_type_idx;
@ -2389,6 +2393,245 @@ static int write_bscan(struct fpga_bits *bits, struct fpga_model *model)
RC_RETURN(model); RC_RETURN(model);
} }
//
// bram
//
// Each RAMB16 stores configuration in 3 minors (22-24) and 16 vertical
// 16-bit words, for a total of 3*16*16 = 768 configuration bits per RAMB16.
// This does not include parity and initial data values which are stored
// in the data section.
// Minor 22 is for INIT and SRVAL A+B bits only (36*4=144 bits).
enum bram_cfg_names { BRAM_ENABLED_TOP, BRAM_ENABLED_BOTTOM,
BRAM_ENA_HIGH, BRAM_ENB_HIGH,
BRAM_REGCEA_HIGH, BRAM_REGCEB_HIGH,
BRAM_RSTA_LOW, BRAM_RSTB_HIGH,
BRAM_WEA0_HIGH, BRAM_WEA1_HIGH, BRAM_WEA2_HIGH,
BRAM_WEA3_HIGH,
BRAM_WEB0_HIGH, BRAM_WEB1_HIGH, BRAM_WEB2_HIGH,
BRAM_WEB3_HIGH,
BRAM_RSTTYPE_ASYNC,
BRAM_DOA_REG, BRAM_DOB_REG,
BRAM_READ_FIRST_A, BRAM_NO_CHANGE_A,
BRAM_READ_FIRST_B, BRAM_NO_CHANGE_B,
BRAM_EN_RSTRAM_A, BRAM_EN_RSTRAM_B,
BRAM_RST_PRIORITY_A_CE, BRAM_RST_PRIORITY_B_CE,
BRAM_DATA_WIDTH_A_0, BRAM_DATA_WIDTH_A_2, BRAM_DATA_WIDTH_A_4,
BRAM_DATA_WIDTH_A_9, BRAM_DATA_WIDTH_A_18,
BRAM_DATA_WIDTH_A_36,
BRAM_DATA_WIDTH_B_0, BRAM_DATA_WIDTH_B_2, BRAM_DATA_WIDTH_B_4,
BRAM_DATA_WIDTH_B_9, BRAM_DATA_WIDTH_B_18,
BRAM_DATA_WIDTH_B_36,
BRAM_RAM_MODE_TDP, BRAM_RAM_MODE_SDP };
static const cfg_bits_t bram_bits[] =
{
// minor v16 bits name
{ 23, 0, 0x0040, BRAM_ENABLED_TOP },
{ 24, 0, 0x0600, BRAM_ENABLED_TOP },
{ 24, 1, 0xC000, BRAM_ENABLED_TOP },
{ 24, 5, 0x000C, BRAM_ENABLED_TOP },
{ 24, 10, 0x3000, BRAM_ENABLED_BOTTOM },
{ 24, 14, 0x0003, BRAM_ENABLED_BOTTOM },
{ 23, 15, 0x0200, BRAM_ENABLED_BOTTOM },
{ 24, 15, 0x0060, BRAM_ENABLED_BOTTOM },
{ 24, 5, 0x0080, BRAM_ENA_HIGH },
{ 24, 6, 0x0200, BRAM_ENA_HIGH },
{ 24, 6, 0x0500, BRAM_ENB_HIGH },
{ 23, 0, 0x0400, BRAM_REGCEA_HIGH },
{ 23, 15, 0x0020, BRAM_REGCEA_HIGH },
{ 23, 0, 0x0010, BRAM_REGCEB_HIGH },
{ 23, 15, 0x0800, BRAM_REGCEB_HIGH },
{ 23, 0, 0x1000, BRAM_RSTA_LOW },
{ 23, 15, 0x0008, BRAM_RSTA_LOW },
{ 23, 0, 0x0004, BRAM_RSTB_HIGH },
{ 23, 15, 0x2000, BRAM_RSTB_HIGH },
{ 23, 15, 0x0040, BRAM_WEA0_HIGH },
{ 23, 15, 0x0010, BRAM_WEA1_HIGH },
{ 23, 0, 0x0200, BRAM_WEA2_HIGH },
{ 23, 0, 0x0800, BRAM_WEA3_HIGH },
{ 23, 15, 0x1000, BRAM_WEB0_HIGH },
{ 23, 15, 0x4000, BRAM_WEB1_HIGH },
{ 23, 0, 0x0008, BRAM_WEB2_HIGH },
{ 23, 0, 0x0002, BRAM_WEB3_HIGH },
{ 24, 0, 0x0080, BRAM_RSTTYPE_ASYNC },
{ 24, 1, 0x0100, BRAM_RSTTYPE_ASYNC },
{ 24, 14, 0x0080, BRAM_RSTTYPE_ASYNC },
{ 24, 15, 0x0100, BRAM_RSTTYPE_ASYNC },
{ 24, 1, 0x0400, BRAM_DOA_REG },
{ 24, 14, 0x0020, BRAM_DOA_REG },
{ 24, 1, 0x0200, BRAM_DOB_REG },
{ 24, 14, 0x0040, BRAM_DOB_REG },
{ 24, 0, 0x1000, BRAM_READ_FIRST_A },
{ 24, 15, 0x0008, BRAM_READ_FIRST_A },
{ 24, 0, 0x4000, BRAM_NO_CHANGE_A },
{ 24, 15, 0x0002, BRAM_NO_CHANGE_A },
{ 24, 0, 0x0800, BRAM_READ_FIRST_B },
{ 24, 15, 0x0010, BRAM_READ_FIRST_B },
{ 24, 0, 0x2000, BRAM_NO_CHANGE_B },
{ 24, 15, 0x0004, BRAM_NO_CHANGE_B },
{ 24, 1, 0x0002, BRAM_EN_RSTRAM_A },
{ 24, 14, 0x4000, BRAM_EN_RSTRAM_A },
{ 24, 5, 0x4000, BRAM_EN_RSTRAM_B },
{ 24, 10, 0x0002, BRAM_EN_RSTRAM_B },
{ 24, 0, 0x0040, BRAM_RST_PRIORITY_A_CE },
{ 24, 15, 0x0200, BRAM_RST_PRIORITY_A_CE },
{ 24, 0, 0x0020, BRAM_RST_PRIORITY_B_CE },
{ 24, 15, 0x0400, BRAM_RST_PRIORITY_B_CE },
{ 24, 0, 0x0015, BRAM_DATA_WIDTH_A_0 },
{ 24, 15, 0xA800, BRAM_DATA_WIDTH_A_0 },
{ 24, 0, 0x0001, BRAM_DATA_WIDTH_A_2 },
{ 24, 15, 0x8000, BRAM_DATA_WIDTH_A_2 },
{ 24, 0, 0x0004, BRAM_DATA_WIDTH_A_4 },
{ 24, 15, 0x2000, BRAM_DATA_WIDTH_A_4 },
{ 24, 0, 0x0005, BRAM_DATA_WIDTH_A_9 },
{ 24, 15, 0xA000, BRAM_DATA_WIDTH_A_9 },
{ 24, 0, 0x0010, BRAM_DATA_WIDTH_A_18 },
{ 24, 15, 0x0800, BRAM_DATA_WIDTH_A_18 },
{ 24, 0, 0x0011, BRAM_DATA_WIDTH_A_36 },
{ 24, 15, 0x8800, BRAM_DATA_WIDTH_A_36 },
{ 24, 0, 0x800A, BRAM_DATA_WIDTH_B_0 },
{ 24, 15, 0x5001, BRAM_DATA_WIDTH_B_0 },
{ 24, 0, 0x0002, BRAM_DATA_WIDTH_B_2 },
{ 24, 15, 0x4000, BRAM_DATA_WIDTH_B_2 },
{ 24, 0, 0x8000, BRAM_DATA_WIDTH_B_4 },
{ 24, 15, 0x0001, BRAM_DATA_WIDTH_B_4 },
{ 24, 0, 0x8002, BRAM_DATA_WIDTH_B_9 },
{ 24, 15, 0x4001, BRAM_DATA_WIDTH_B_9 },
{ 24, 0, 0x0008, BRAM_DATA_WIDTH_B_18 },
{ 24, 15, 0x1000, BRAM_DATA_WIDTH_B_18 },
{ 24, 0, 0x000A, BRAM_DATA_WIDTH_B_36 },
{ 24, 15, 0x5000, BRAM_DATA_WIDTH_B_36 },
{ 23, 0, 0x0080, BRAM_RAM_MODE_TDP },
{ 23, 15, 0x0200, BRAM_RAM_MODE_TDP },
{ 23, 1, 0x0100, BRAM_RAM_MODE_SDP },
{ 23, 15, 0x0080, BRAM_RAM_MODE_SDP },
{ -1 }
};
// Use struct to avoid warnings/casts compared to pointer to array of int.
struct eight_words
{
int w[8];
};
static void extract_init_srval_18(struct eight_words* eight_words, int *init_a,
int *init_b, int *srval_a, int *srval_b);
static void extract_init_srval_36(struct eight_words* eight_top_words,
struct eight_words* eight_bot_words, int64_t *init_a,
int64_t *init_b, int64_t *srval_a, int64_t *srval_b);
#define INIT_A 0x40000000
#define SRVAL_A 0x20000000
#define INIT_B 0x10000000
#define SRVAL_B 0x08000000
#define INIT_SRVAL_BITMASK 0x0000001F // max 17 (16-bit word plus 2 parity bits)
static void extract_init_srval_18(struct eight_words* eight_words, int *init_a,
int *init_b, int *srval_a, int *srval_b)
{
static const int bits[] = {
/* 0*/ SRVAL_B|14, INIT_A|14, 0, SRVAL_A|14, INIT_B|13, 0, SRVAL_B|13, INIT_A|13,
INIT_B|15, 0, SRVAL_B|15, INIT_A|15, 0, SRVAL_A|15, INIT_B|14, 0,
/*16*/ INIT_B|17, 0, SRVAL_B|17, INIT_A|17, 0, SRVAL_A|17, INIT_B|11, 0,
SRVAL_A|13, 0, INIT_B|12, 0, SRVAL_B|12, 0, INIT_A|12, SRVAL_A|12,
/*32*/ INIT_A|10, SRVAL_A|10, INIT_B|9, 0, 0, SRVAL_B|9, INIT_A|9, SRVAL_A|9,
SRVAL_B|11, INIT_A|11, 0, SRVAL_A|11, 0, INIT_B|10, 0, SRVAL_B|10,
/*48*/ 0, 0, 0, 0, 0, 0, 0, 0,
INIT_B|8, 0, SRVAL_B|8, INIT_A|8, 0, SRVAL_A|8, 0, 0,
/*64*/ 0, INIT_B|7, SRVAL_B|7, INIT_A|7, 0, SRVAL_A|7, 0, INIT_B|6,
0, 0, 0, 0, 0, 0, 0, 0,
/*80*/ 0, SRVAL_A|5, INIT_B|4, 0, 0, SRVAL_B|4, INIT_A|4, SRVAL_A|4,
SRVAL_B|6, INIT_A|6, 0, SRVAL_A|6, INIT_B|5, 0, SRVAL_B|5, INIT_A|5,
/*96*/ SRVAL_B|3, INIT_A|3, 0, SRVAL_A|3, 0, INIT_B|2, 0, SRVAL_B|2,
INIT_B|16, 0, SRVAL_B|16, INIT_A|16, 0, SRVAL_A|16, 0, INIT_B|3,
/*112*/ INIT_B|0, 0, SRVAL_B|0, INIT_A|0, 0, 0, SRVAL_A|0, 0,
INIT_A|2, SRVAL_A|2, 0, INIT_B|1, 0, SRVAL_B|1, INIT_A|1, SRVAL_A|1 };
int i, j, bit_set;
*init_a = 0; *srval_a = 0;
*init_b = 0; *srval_b = 0;
for (i = 0; i < 8; i++) {
for (j = 0; j < 16; j++) {
if (!(eight_words->w[i] & (1<<j))) continue;
if ((bits[i*16+j] & INIT_SRVAL_BITMASK) > 17)
HERE();
bit_set = 1<<(bits[i*16+j]&INIT_SRVAL_BITMASK);
if (bits[i*16+j] & INIT_A) {
*init_a |= bit_set;
} else if (bits[i*16+j] & SRVAL_A) {
*srval_a |= bit_set;
} else if (bits[i*16+j] & INIT_B) {
*init_b |= bit_set;
} else if (bits[i*16+j] & SRVAL_B) {
*srval_b |= bit_set;
} else {
HERE();
}
}
}
}
static void extract_init_srval_36(struct eight_words* eight_top_words,
struct eight_words* eight_bot_words, int64_t *init_a,
int64_t *init_b, int64_t *srval_a, int64_t *srval_b)
{
int init_a_top, init_a_bot, srval_a_top, srval_a_bot,
init_b_top, init_b_bot, srval_b_top, srval_b_bot;
extract_init_srval_18(eight_top_words, &init_a_top, &init_b_top, &srval_a_top, &srval_b_top);
extract_init_srval_18(eight_bot_words, &init_a_bot, &init_b_bot, &srval_a_bot, &srval_b_bot);
*init_a = ((int64_t) init_a_top & 0xFFFF) | (((int64_t) init_a_bot & 0xFFFF) << 16)
| (((int64_t) init_a_top & 0x3000) << 32) | (( (int64_t) init_a_bot & 0x3000) << 34);
*init_b = ((int64_t) init_b_top & 0xFFFF) | (((int64_t) init_b_bot & 0xFFFF) << 16)
| (((int64_t) init_b_top & 0x3000) << 32) | (( (int64_t) init_b_bot & 0x3000) << 34);
*srval_a = ((int64_t) srval_a_top & 0xFFFF) | (((int64_t) srval_a_bot & 0xFFFF) << 16)
| (((int64_t) srval_a_top & 0x3000) << 32) | (( (int64_t) srval_a_bot & 0x3000) << 34);
*srval_b = ((int64_t) srval_b_top & 0xFFFF) | (((int64_t) srval_b_bot & 0xFFFF) << 16)
| (((int64_t) srval_b_top & 0x3000) << 32) | (( (int64_t) srval_b_bot & 0x3000) << 34);
}
static int extract_bram(struct extract_state *es)
{
RC_CHECK(es->model);
/*
typedef struct _bram_init // only first half of array used for bram8
{
int data[64][16];
int parity[8][16];
} bram_init_t;
void bram_extract_init(bram_init_t *init, const uint8_t *bits);
for (row = 3; row >= 0; row--) {
for (i = XC6_BRAM16_DEVS_PER_ROW-1; i >= 0; i--) {
printf_ramb_data(&cfg->bits.d[BRAM_DATA_START
+ (row*XC6_BRAM16_DEVS_PER_ROW+i)
*XC6_BRAM_DATA_FRAMES_PER_DEV*FRAME_SIZE],
row, i);
}
}
*/
// todo
RC_RETURN(es->model);
}
static int write_bram(struct fpga_bits *bits, struct fpga_model *model)
{
RC_CHECK(model);
// todo
RC_RETURN(model);
}
int extract_model(struct fpga_model* model, struct fpga_bits* bits) int extract_model(struct fpga_model* model, struct fpga_bits* bits)
{ {
struct extract_state es; struct extract_state es;
@ -2415,6 +2658,8 @@ int extract_model(struct fpga_model* model, struct fpga_bits* bits)
if (rc) { RC_SET(model, rc); goto out; } if (rc) { RC_SET(model, rc); goto out; }
rc = extract_bscan(&es); rc = extract_bscan(&es);
if (rc) { RC_SET(model, rc); goto out; } if (rc) { RC_SET(model, rc); goto out; }
rc = extract_bram(&es);
if (rc) { RC_SET(model, rc); goto out; }
// turn switches into nets // turn switches into nets
if (model->nets) if (model->nets)
@ -3188,6 +3433,7 @@ int write_model(struct fpga_bits *bits, struct fpga_model *model)
write_type2(bits, model); write_type2(bits, model);
write_logic(bits, model); write_logic(bits, model);
write_bscan(bits, model); write_bscan(bits, model);
write_bram(bits, model);
RC_RETURN(model); RC_RETURN(model);
} }

View File

@ -680,200 +680,12 @@ static int dump_maj_logic(const uint8_t* bits, int row, int major)
return 0; return 0;
} }
#if 0
typedef struct ramb16_cfg
{
uint8_t byte[64];
} __attribute((packed)) ramb16_cfg_t;
static const cfg_atom_t ramb16_instance =
{
{-1}, {12,13, 274,275,276,277,316,317,318,319,
420,421,422,423,-1}, "default_bits"
};
static cfg_atom_t ramb16_atoms[] =
{
// data_width_a
{{264,265,260,261,256,257,-1},{ -1},"data_width_a 1"},
{{264,265,260,261, -1},{ 256,257,-1},"data_width_a 2"},
{{264,265, 256,257,-1},{ 260,261, -1},"data_width_a 4"},
{{264,265, -1},{ 260,261,256,257,-1},"data_width_a 9"},
{{ 260,261,256,257,-1},{264,265, -1},"data_width_a 18"},
{{ 260,261, -1},{264,265, 256,257,-1},"data_width_a 36"},
{{ -1},{264,265,260,261,256,257,-1},"data_width_a 0"},
// data_width_b
{{262,263,286,287,258,259,-1},{ -1},"data_width_b 1"},
{{262,263,286,287, -1},{ 258,259,-1},"data_width_b 2"},
{{262,263, 258,259,-1},{ 286,287, -1},"data_width_b 4"},
{{262,263, -1},{ 286,287,258,259,-1},"data_width_b 9"},
{{ 286,287,258,259,-1},{262,263, -1},"data_width_b 18"},
{{ 286,287, -1},{262,263, 258,259,-1},"data_width_b 36"},
{{ -1},{262,263,286,287,258,259,-1},"data_width_b 0"},
// required
{ { -1}, {266, 267, -1}, "RST_PRIORITY_B:CE" },
{ {266, 267, -1}, { -1}, "RST_PRIORITY_B:SR" },
{ { -1}, {268, 269, -1}, "RST_PRIORITY_A:CE" },
{ {268, 269, -1}, { -1}, "RST_PRIORITY_A:SR" },
{ { -1}, {290, 291, -1}, "EN_RSTRAM_A:TRUE" },
{ {290, 291, -1}, { -1}, "EN_RSTRAM_A:FALSE" },
{ { -1}, {444, 445, -1}, "EN_RSTRAM_B:TRUE" },
{ {444, 445, -1}, { -1}, "EN_RSTRAM_B:FALSE" },
// optional
{ { -1}, { 26, 27, -1}, "CLKAINV:CLKA" },
{ { 26, 27, -1}, { -1}, "CLKAINV:CLKA_B" }, // def
{ { -1}, { 30, 31, -1}, "CLKBINV:CLKB" },
{ { 30, 31, -1}, { -1}, "CLKBINV:CLKB_B" }, // def
{ { -1}, {270, 271, -1}, "RSTTYPE:ASYNC" },
{ {270, 271, -1}, { -1}, "RSTTYPE:SYNC" }, // def
{ { -1}, {278, 279, -1}, "WRITE_MODE_B:READ_FIRST" },
{ { -1}, {280, 281, -1}, "WRITE_MODE_A:READ_FIRST" },
{ { -1}, {282, 283, -1}, "WRITE_MODE_B:NO_CHANGE" },
{ { -1}, {284, 285, -1}, "WRITE_MODE_A:NO_CHANGE" },
{ {278, 279, 282, 283, -1}, {-1}, "WRITE_MODE_B:WRITE_FIRST" }, //def
{ {280, 281, 284, 285, -1}, {-1}, "WRITE_MODE_A:WRITE_FIRST" }, //def
{ { -1}, {306, 307, -1}, "DOB_REG:1" },
{ {306, 306, -1}, { -1}, "DOB_REG:0" }, // def
{ { -1}, {308, 309, -1}, "DOA_REG:1" },
{ {308, 309, -1}, { -1}, "DOA_REG:0" }, // def
{ {431, 467, -1}, {430, 466, -1}, "ENAINV:ENA" }, // def
{ {430, 431, 466, 467, -1}, {-1}, "ENAINV:ENA_B" },
{ {465, 469, -1}, {464, 468, -1}, "ENBINV:ENB" }, // def
{ {464, 465, 468, 469, -1}, {-1}, "ENBINV:ENB_B" },
{ { -1}, { 20, 21, -1}, "REGCEAINV:REGCEA" }, // def
{ { 20, 21, -1}, { -1}, "REGCEAINV:REGCEA_B" },
{ { -1}, { 8, 9, -1}, "REGCEBINV:REGCEB" },
{ { 8, 9, -1}, { -1}, "REGCEBINV:REGCEB_B" }, // def
{ { 24, 25, -1}, { -1}, "RSTAINV:RSTA" }, // def
{ { -1}, { 24, 25, -1}, "RSTAINV:RSTA_B" },
{ { -1}, { 4, 5, -1}, "RSTBINV:RSTB" }, // def
{ { 4, 5, -1}, { -1}, "RSTBINV:RSTB_B" },
{ { -1}, { 19, -1}, "WEA0INV:WEA0" }, // def
{ { 19, -1}, { -1}, "WEA0INV:WEA0_B" },
{ { -1}, { 23, -1}, "WEA2INV:WEA1" }, // def
{ { 23, -1}, { -1}, "WEA2INV:WEA1_B" },
{ { -1}, { 18, -1}, "WEA2INV:WEA2" }, // def
{ { 18, -1}, { -1}, "WEA2INV:WEA2_B" },
{ { -1}, { 22, -1}, "WEA2INV:WEA3" }, // def
{ { 22, -1}, { -1}, "WEA2INV:WEA3_B" },
{ { -1}, { 7, -1}, "WEB0INV:WEB0" }, // def
{ { 7, -1}, { -1}, "WEB0INV:WEB0_B" },
{ { -1}, { 3, -1}, "WEB1INV:WEB1" }, // def
{ { 3, -1}, { -1}, "WEB1INV:WEB1_B" },
{ { -1}, { 6, -1}, "WEB2INV:WEB2" }, // def
{ { 6, -1}, { -1}, "WEB2INV:WEB2_B" },
{ { -1}, { 2, -1}, "WEB3INV:WEB3" }, // def
{ { 2, -1}, { -1}, "WEB3INV:WEB3_B" },
};
static void print_ramb16_cfg(ramb16_cfg_t* cfg)
{
char bits[512];
uint8_t u8;
int i, first_extra;
for (i = 0; i < 32; i++) {
u8 = cfg->byte[i*2];
cfg->byte[i*2] = cfg->byte[i*2+1];
cfg->byte[i*2+1] = u8;
}
for (i = 0; i < 64; i++) {
u8 = 0;
if (cfg->byte[i] & 0x01) u8 |= 0x80;
if (cfg->byte[i] & 0x02) u8 |= 0x40;
if (cfg->byte[i] & 0x04) u8 |= 0x20;
if (cfg->byte[i] & 0x08) u8 |= 0x10;
if (cfg->byte[i] & 0x10) u8 |= 0x08;
if (cfg->byte[i] & 0x20) u8 |= 0x04;
if (cfg->byte[i] & 0x40) u8 |= 0x02;
if (cfg->byte[i] & 0x80) u8 |= 0x01;
cfg->byte[i] = u8;
}
//
// Bits 0..255 come from minor 23, Bits 256..511 from minor 24.
// Each set of 256 bits is divided into two halfs of 128 bits
// that are swept forward and backward to form 2-bit pairs,
// pairs 0..127 are formed out of bits 0..127 and 255..128,
// p128..p255 are formed out of b256..b383 and b511..b384.
// Since so much bit twiddling is already happening, we are sorting
// the bits so that pairs are next to each other.
// The notation for a pair is "p8=01".
// minor 23
for (i = 0; i < 128; i++) {
bits[i*2] = (cfg->byte[i/8] & (1<<(i%8))) != 0;
bits[i*2+1] = (cfg->byte[(255-i)/8]
& (1<<(7-(i%8)))) != 0;
}
// minor 24
for (i = 0; i < 128; i++) {
bits[256+i*2] = (cfg->byte[32+i/8] & (1<<(i%8))) != 0;
bits[256+i*2+1] = (cfg->byte[32+(255-i)/8]
& (1<<(7-(i%8)))) != 0;
}
printf("{\n");
// hexdump(1 /* indent */, &cfg->byte[0], 64 /* len */);
for (i = 0; i < sizeof(ramb16_atoms)/sizeof(ramb16_atoms[0]); i++) {
if (atom_found(bits, &ramb16_atoms[i])
&& ramb16_atoms[i].must_1[0] != -1) {
printf(" %s\n", ramb16_atoms[i].str);
ramb16_atoms[i].flag = 1;
} else
ramb16_atoms[i].flag = 0;
}
for (i = 0; i < sizeof(ramb16_atoms)/sizeof(ramb16_atoms[0]); i++) {
if (ramb16_atoms[i].flag)
atom_remove(bits, &ramb16_atoms[i]);
}
// instantiation bits
if (ramb16_instance.must_1[0] != -1) {
if (atom_found(bits, &ramb16_instance)) {
for (i = 0; ramb16_instance.must_1[i] != -1; i++)
printf(" b%i\n", ramb16_instance.must_1[i]);
atom_remove(bits, &ramb16_instance);
} else
printf(" #W Not all instantiation bits set.\n");
}
// extra bits
first_extra = 1;
for (i = 0; i < 512; i++) {
if (bits[i]) {
if (first_extra) {
printf(" #W Extra bits set.\n");
first_extra = 0;
}
printf(" b%i\n", i);
}
}
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)
{ {
int word_i, w_old, w_new; int word_i, w_old, w_new;
char v16_str[32]; char v16_str[32];
// print words as pins (fpga bit ordering)
for (word_i = 0; word_i < FRAME_SIZE/XC6_WORD_BYTES; word_i++) {
if (word_i == XC6_HCLK_POS/XC6_WORD_BYTES)
sprintf(v16_str, "v16_clk");
else
sprintf(v16_str, "v16_%i",
word_i<XC6_HCLK_POS/XC6_WORD_BYTES ? word_i : word_i - 1);
w_old = frame_get_pinword(&old_minor_bits[word_i*XC6_WORD_BYTES]);
w_new = frame_get_pinword(&new_minor_bits[word_i*XC6_WORD_BYTES]);
if (w_old == w_new) continue;
printf("#I <r%i ma%i %s mi%i pin %s", row, major, v16_str, minor, fmt_word(w_old));
printf("#I >r%i ma%i %s mi%i pin %s", row, major, v16_str, minor, fmt_word(w_new));
}
// print words as bits (cpu bit ordering) // print words as bits (cpu bit ordering)
for (word_i = 0; word_i < FRAME_SIZE/XC6_WORD_BYTES; word_i++) { for (word_i = 0; word_i < FRAME_SIZE/XC6_WORD_BYTES; word_i++) {
if (word_i == XC6_HCLK_POS/XC6_WORD_BYTES) if (word_i == XC6_HCLK_POS/XC6_WORD_BYTES)
@ -881,11 +693,11 @@ static void printf_minor_diff(int row, int major, int minor,
else else
sprintf(v16_str, "v16_%i", sprintf(v16_str, "v16_%i",
word_i<XC6_HCLK_POS/XC6_WORD_BYTES ? word_i : word_i - 1); word_i<XC6_HCLK_POS/XC6_WORD_BYTES ? word_i : word_i - 1);
w_old = frame_get_pinword(&old_minor_bits[word_i*XC6_WORD_BYTES]); w_old = frame_get_cpuword(&old_minor_bits[word_i*XC6_WORD_BYTES]);
w_new = frame_get_pinword(&new_minor_bits[word_i*XC6_WORD_BYTES]); w_new = frame_get_cpuword(&new_minor_bits[word_i*XC6_WORD_BYTES]);
if (w_old == w_new) continue; if (w_old == w_new) continue;
printf("#I <r%i ma%i %s mi%i cpu %s", row, major, v16_str, minor, fmt_word(pinword_to_cpu(w_old))); printf("#I <r%i ma%i %s mi%i %s", row, major, v16_str, minor, fmt_word(w_old));
printf("#I >r%i ma%i %s mi%i cpu %s", row, major, v16_str, minor, fmt_word(pinword_to_cpu(w_new))); printf("#I >r%i ma%i %s mi%i %s", row, major, v16_str, minor, fmt_word(w_new));
} }
} }
@ -895,20 +707,6 @@ static void printf_minors(int row, int major, int minor, int num_minors,
int word_i, minor_i, w; int word_i, minor_i, w;
char v16_str[32]; char v16_str[32];
// print words as pins (fpga bit ordering)
for (word_i = 0; word_i < FRAME_SIZE/XC6_WORD_BYTES; word_i++) {
if (word_i == XC6_HCLK_POS/XC6_WORD_BYTES)
sprintf(v16_str, "v16_clk");
else
sprintf(v16_str, "v16_%i",
word_i<XC6_HCLK_POS/XC6_WORD_BYTES ? word_i : word_i - 1);
for (minor_i = minor; minor_i < minor + num_minors; minor_i++) {
w = frame_get_pinword(&major_bits[minor_i*FRAME_SIZE
+ word_i*XC6_WORD_BYTES]);
if (!w) continue;
printf("r%i ma%i %s mi%i pin %s", row, major, v16_str, minor_i, fmt_word(w));
}
}
// print words as bits (cpu bit ordering) // print words as bits (cpu bit ordering)
for (word_i = 0; word_i < FRAME_SIZE/XC6_WORD_BYTES; word_i++) { for (word_i = 0; word_i < FRAME_SIZE/XC6_WORD_BYTES; word_i++) {
if (word_i == XC6_HCLK_POS/XC6_WORD_BYTES) if (word_i == XC6_HCLK_POS/XC6_WORD_BYTES)
@ -917,18 +715,16 @@ static void printf_minors(int row, int major, int minor, int num_minors,
sprintf(v16_str, "v16_%i", sprintf(v16_str, "v16_%i",
word_i<XC6_HCLK_POS/XC6_WORD_BYTES ? word_i : word_i - 1); word_i<XC6_HCLK_POS/XC6_WORD_BYTES ? word_i : word_i - 1);
for (minor_i = minor; minor_i < minor + num_minors; minor_i++) { for (minor_i = minor; minor_i < minor + num_minors; minor_i++) {
w = frame_get_pinword(&major_bits[minor_i*FRAME_SIZE w = frame_get_cpuword(&major_bits[minor_i*FRAME_SIZE
+ word_i*XC6_WORD_BYTES]); + word_i*XC6_WORD_BYTES]);
if (!w) continue; if (!w) continue;
printf("r%i ma%i %s mi%i cpu %s", row, major, v16_str, minor_i, fmt_word(pinword_to_cpu(w))); printf("r%i ma%i %s mi%i %s", row, major, v16_str, minor_i, fmt_word(w));
} }
} }
} }
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];
// int j, offset_in_frame;
int minor, i; int minor, i;
for (minor = 0; minor < get_major_minors(XC6SLX9, major); minor++) for (minor = 0; minor < get_major_minors(XC6SLX9, major); minor++)
@ -942,35 +738,6 @@ static int dump_maj_bram(const uint8_t *bits, int row, int major)
printf_v64_mi20(&bits[20*FRAME_SIZE], row, major); printf_v64_mi20(&bits[20*FRAME_SIZE], row, major);
printf_minors(row, major, /*minor*/ 21, /*num_minors*/ 4, bits); printf_minors(row, major, /*minor*/ 21, /*num_minors*/ 4, bits);
#if 0
printf_frames(&bits[21*FRAME_SIZE], /*max_frames*/ 1,
row, major, 21, /*print_empty*/ 0, /*no_clock*/ 1);
printf_frames(&bits[22*FRAME_SIZE], /*max_frames*/ 1,
row, major, 22, /*print_empty*/ 0, /*no_clock*/ 1);
// minors 23&24
for (i = 0; i < 4; i++) {
offset_in_frame = i*32;
if (offset_in_frame >= 64)
offset_in_frame += 2;
for (j = 0; j < 32; j++) {
ramb16_cfg[i].byte[j] = bits[23*130+offset_in_frame+j];
ramb16_cfg[i].byte[j+32] = bits[24*130+offset_in_frame+j];
}
}
for (i = 0; i < 4; i++) {
for (j = 0; j < 64; j++) {
if (ramb16_cfg[i].byte[j])
break;
}
if (j >= 64)
continue;
printf("r%i ma%i ramb16 i%i\n",
row, major, i);
print_ramb16_cfg(&ramb16_cfg[i]);
}
#endif
return 0; return 0;
} }

View File

@ -2319,19 +2319,20 @@ static void fprintf_inout_pin(FILE* f, struct fpga_model* model,
fprintf(f, "%s", buf); fprintf(f, "%s", buf);
} }
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, int no_json)
{ {
struct fpga_net* net; struct fpga_net* net;
int i, first_line; 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"); if (!no_json) fprintf(f, "[\n");
first_line = 1; first_line = 1;
for (i = 0; i < net->len; i++) { for (i = 0; i < net->len; i++) {
if (!first_line) if (!first_line)
fprintf(f, ",\n"); fprintf(f, ",\n");
first_line = 0; first_line = 0;
if (no_json) fprintf(f, "net_i %i:", net_i);
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;
@ -2342,7 +2343,8 @@ void fnet_printf(FILE* f, struct fpga_model* model, net_idx_t net_i)
fpga_switch_print_json(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 ]"); fprintf(f, "\n");
if (!no_json) fprintf(f, " ]");
} }
// //

View File

@ -410,7 +410,7 @@ int fnet_add_sw(struct fpga_model* model, net_idx_t net_i,
int fnet_remove_sw(struct fpga_model* model, net_idx_t net_i, int fnet_remove_sw(struct fpga_model* model, net_idx_t net_i,
int y, int x, const swidx_t* switches, int num_sw); int y, int x, const swidx_t* switches, int num_sw);
int fnet_remove_all_sw(struct fpga_model* model, net_idx_t net_i); int fnet_remove_all_sw(struct fpga_model* model, net_idx_t net_i);
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, int no_json);
int fnet_route(struct fpga_model* model, net_idx_t net_i); int fnet_route(struct fpga_model* model, net_idx_t net_i);
// is_vcc == 1 for a vcc net, is_vcc == 0 for a gnd net // is_vcc == 1 for a vcc net, is_vcc == 0 for a gnd net

View File

@ -11,8 +11,8 @@
#include "control.h" #include "control.h"
#include "floorplan.h" #include "floorplan.h"
#define PRINT_FLAG(fp, flag) if ((tf) & (flag)) \ #define PRINT_FLAG(fp, flag, firstp) if ((tf) & (flag)) \
{ fprintf (fp, " %s", #flag); tf &= ~(flag); } { fprintf (fp, "%s\"%s\"", firstp ? "" : ", ", #flag); tf &= ~(flag); firstp = 0; }
void printf_version(FILE* f) void printf_version(FILE* f)
{ {
@ -22,43 +22,53 @@ void printf_version(FILE* f)
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;
int x, y; int x, y, first_line;
RC_CHECK(model); RC_CHECK(model);
fprintf(f, " \"tiles\" : [\n");
for (x = 0; x < model->x_width; x++) { for (x = 0; x < model->x_width; x++) {
fprintf(f, "\n"); if (x) fprintf(f, ",\n\n");
first_line = 1;
for (y = 0; y < model->y_height; y++) { for (y = 0; y < model->y_height; y++) {
tile = &model->tiles[y*model->x_width + x]; tile = &model->tiles[y*model->x_width + x];
if (tile->type != NA) if (tile->type != NA) {
fprintf(f, "tile y%i x%i name %s\n", y, x, fprintf(f, "%s { \"y\" : %i, \"x\" : %i, \"name\" : \"%s\" }",
first_line ? "" : ",\n", y, x,
fpga_tiletype_str(tile->type)); fpga_tiletype_str(tile->type));
first_line = 0;
}
if (tile->flags) { if (tile->flags) {
int tf = tile->flags; int tf = tile->flags, first_flag = 1;
fprintf(f, "tile y%i x%i flags", y, x);
fprintf(f, "%s { \"y\" : %i, \"x\" : %i, \"flags\" : [ ",
first_line ? "" : ",\n", y, x);
first_line = 0;
PRINT_FLAG(f, TF_FABRIC_ROUTING_COL); PRINT_FLAG(f, TF_FABRIC_ROUTING_COL, first_flag);
PRINT_FLAG(f, TF_FABRIC_LOGIC_XM_COL); PRINT_FLAG(f, TF_FABRIC_LOGIC_XM_COL, first_flag);
PRINT_FLAG(f, TF_FABRIC_LOGIC_XL_COL); PRINT_FLAG(f, TF_FABRIC_LOGIC_XL_COL, first_flag);
PRINT_FLAG(f, TF_FABRIC_BRAM_VIA_COL); PRINT_FLAG(f, TF_FABRIC_BRAM_VIA_COL, first_flag);
PRINT_FLAG(f, TF_FABRIC_MACC_VIA_COL); PRINT_FLAG(f, TF_FABRIC_MACC_VIA_COL, first_flag);
PRINT_FLAG(f, TF_FABRIC_BRAM_COL); PRINT_FLAG(f, TF_FABRIC_BRAM_COL, first_flag);
PRINT_FLAG(f, TF_FABRIC_MACC_COL); PRINT_FLAG(f, TF_FABRIC_MACC_COL, first_flag);
PRINT_FLAG(f, TF_ROUTING_NO_IO); PRINT_FLAG(f, TF_ROUTING_NO_IO, first_flag);
PRINT_FLAG(f, TF_BRAM_DEV); PRINT_FLAG(f, TF_BRAM_DEV, first_flag);
PRINT_FLAG(f, TF_MACC_DEV); PRINT_FLAG(f, TF_MACC_DEV, first_flag);
PRINT_FLAG(f, TF_LOGIC_XL_DEV); PRINT_FLAG(f, TF_LOGIC_XL_DEV, first_flag);
PRINT_FLAG(f, TF_LOGIC_XM_DEV); PRINT_FLAG(f, TF_LOGIC_XM_DEV, first_flag);
PRINT_FLAG(f, TF_IOLOGIC_DELAY_DEV); PRINT_FLAG(f, TF_IOLOGIC_DELAY_DEV, first_flag);
PRINT_FLAG(f, TF_DCM_DEV); PRINT_FLAG(f, TF_DCM_DEV, first_flag);
PRINT_FLAG(f, TF_PLL_DEV); PRINT_FLAG(f, TF_PLL_DEV, first_flag);
PRINT_FLAG(f, TF_WIRED); PRINT_FLAG(f, TF_WIRED, first_flag);
PRINT_FLAG(f, TF_CENTER_MIDBUF, first_flag);
if (tf) fprintf(f, " 0x%x", tf); if (tf) fprintf(f, "%s\"0x%x\"", first_flag ? "" : ", ", tf);
fprintf(f, "\n"); fprintf(f, " ] }");
} }
} }
} }
fprintf(f, "\n ]");
return 0; return 0;
} }
@ -907,42 +917,51 @@ int printf_BUFGMUX(FILE *f, struct fpga_model *model,
struct fpga_tile *tile; struct fpga_tile *tile;
struct fpgadev_bufgmux *cfg; struct fpgadev_bufgmux *cfg;
char pref[256]; char pref[256];
int dev_i; int dev_i, first_line;
dev_i = fpga_dev_idx(model, y, x, DEV_BUFGMUX, type_idx); dev_i = fpga_dev_idx(model, y, x, DEV_BUFGMUX, 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 BUFGMUX %i", y, x, type_idx); snprintf(pref, sizeof(pref), " { \"y\" : %i, \"x\" : %i, \"dev\" : \"BUFGMUX\", \"dev_idx\" : %i", y, x, type_idx);
first_line = 1;
if (!config_only) if (!config_only) {
fprintf(f, "%s\n", pref); fprintf(f, "%s }", pref);
first_line = 0;
}
cfg = &tile->devs[dev_i].u.bufgmux; cfg = &tile->devs[dev_i].u.bufgmux;
switch (cfg->clk) { switch (cfg->clk) {
case BUFG_CLK_ASYNC: case BUFG_CLK_ASYNC:
fprintf(f, "%s clk ASYNC\n", pref); fprintf(f, "%s%s, \"clk\" : \"ASYNC\" }", first_line ? "" : ",\n", pref);
first_line = 0;
break; break;
case BUFG_CLK_SYNC: case BUFG_CLK_SYNC:
fprintf(f, "%s clk SYNC\n", pref); fprintf(f, "%s%s, \"clk\" : \"SYNC\" }", 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->disable_attr) { switch (cfg->disable_attr) {
case BUFG_DISATTR_LOW: case BUFG_DISATTR_LOW:
fprintf(f, "%s disable_attr LOW\n", pref); fprintf(f, "%s%s, \"disable_attr\" : \"LOW\" }", first_line ? "" : ",\n", pref);
first_line = 0;
break; break;
case BUFG_DISATTR_HIGH: case BUFG_DISATTR_HIGH:
fprintf(f, "%s disable_attr HIGH\n", pref); fprintf(f, "%s%s, \"disable_attr\" : \"HIGH\" }", 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->s_inv) { switch (cfg->s_inv) {
case BUFG_SINV_N: case BUFG_SINV_N:
fprintf(f, "%s s_inv NO\n", pref); fprintf(f, "%s%s, \"s_inv\" : false }", first_line ? "" : ",\n", pref);
first_line = 0;
break; break;
case BUFG_SINV_Y: case BUFG_SINV_Y:
fprintf(f, "%s s_inv YES\n", pref); fprintf(f, "%s%s, \"s_inv\" : true }", 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);
} }
@ -990,35 +1009,44 @@ int printf_BUFIO(FILE *f, struct fpga_model *model,
struct fpga_tile *tile; struct fpga_tile *tile;
struct fpgadev_bufio *cfg; struct fpgadev_bufio *cfg;
char pref[256]; char pref[256];
int dev_i; int dev_i, first_line;
dev_i = fpga_dev_idx(model, y, x, DEV_BUFIO, type_idx); dev_i = fpga_dev_idx(model, y, x, DEV_BUFIO, 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 BUFIO %i", y, x, type_idx); snprintf(pref, sizeof(pref), " { \"y\" : %i, \"x\" : %i, \"dev\" : \"BUFIO\", \"dev_idx\" : %i", y, x, type_idx);
first_line = 1;
if (!config_only) if (!config_only) {
fprintf(f, "%s\n", pref); fprintf(f, "%s }", pref);
first_line = 0;
}
cfg = &tile->devs[dev_i].u.bufio; cfg = &tile->devs[dev_i].u.bufio;
if (cfg->divide) if (cfg->divide) {
fprintf(f, "%s divide %i\n", pref, cfg->divide); fprintf(f, "%s%s, \"divide\" : %i\n", first_line ? "" : ",\n", pref, cfg->divide);
first_line = 0;
}
switch (cfg->divide_bypass) { switch (cfg->divide_bypass) {
case BUFIO_DIVIDEBP_N: case BUFIO_DIVIDEBP_N:
fprintf(f, "%s divide_bypass NO\n", pref); fprintf(f, "%s%s, \"divide_bypass\" : false }", first_line ? "" : ",\n", pref);
first_line = 0;
break; break;
case BUFIO_DIVIDEBP_Y: case BUFIO_DIVIDEBP_Y:
fprintf(f, "%s divide_bypass YES\n", pref); fprintf(f, "%s%s, \"divide_bypass\" : true }", 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->i_inv) { switch (cfg->i_inv) {
case BUFIO_IINV_N: case BUFIO_IINV_N:
fprintf(f, "%s i_inv NO\n", pref); fprintf(f, "%s%s, \"i_inv\" : false }", first_line ? "" : ",\n", pref);
first_line = 0;
break; break;
case BUFIO_IINV_Y: case BUFIO_IINV_Y:
fprintf(f, "%s i_inv YES\n", pref); fprintf(f, "%s%s, \"i_inv\" : true }", 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);
} }
@ -1062,26 +1090,33 @@ int printf_BSCAN(FILE *f, struct fpga_model *model,
struct fpga_tile *tile; struct fpga_tile *tile;
struct fpgadev_bscan *cfg; struct fpgadev_bscan *cfg;
char pref[256]; char pref[256];
int dev_i; int dev_i, first_line;
dev_i = fpga_dev_idx(model, y, x, DEV_BSCAN, type_idx); dev_i = fpga_dev_idx(model, y, x, DEV_BSCAN, 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 BSCAN %i", y, x, type_idx); snprintf(pref, sizeof(pref), " { \"y\" : %i, \"x\" : %i, \"dev\" : \"BSCAN\", \"dev_idx\" : %i", y, x, type_idx);
first_line = 1;
if (!config_only) if (!config_only) {
fprintf(f, "%s\n", pref); fprintf(f, "%s }", pref);
first_line = 0;
}
cfg = &tile->devs[dev_i].u.bscan; cfg = &tile->devs[dev_i].u.bscan;
if (cfg->jtag_chain) if (cfg->jtag_chain) {
fprintf(f, "%s jtag_chain %i\n", pref, cfg->jtag_chain); fprintf(f, "%s%s, \"jtag_chain\" : %i }", first_line ? "" : ",\n", pref, cfg->jtag_chain);
first_line = 0;
}
switch (cfg->jtag_test) { switch (cfg->jtag_test) {
case BSCAN_JTAG_TEST_N: case BSCAN_JTAG_TEST_N:
fprintf(f, "%s jtag_test NO\n", pref); fprintf(f, "%s%s, \"jtag_test\" : false }", first_line ? "" : ",\n", pref);
first_line = 0;
break; break;
case BSCAN_JTAG_TEST_Y: case BSCAN_JTAG_TEST_Y:
fprintf(f, "%s jtag_test YES\n", pref); fprintf(f, "%s%s, \"jtag_test\" : true }", 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);
} }
@ -1111,13 +1146,13 @@ inst:
return 2; return 2;
} }
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 no_json)
{ {
int x, y, i, first_dev; int x, y, i, first_dev;
struct fpga_tile* tile; struct fpga_tile* tile;
RC_CHECK(model); RC_CHECK(model);
fprintf(f, " \"devices\" : [\n"); if (!no_json) fprintf(f, " \"devices\" : [\n");
first_dev = 1; 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++) {
@ -1163,7 +1198,7 @@ int printf_devices(FILE* f, struct fpga_model* model, int config_only)
} }
} }
if (!first_dev) fprintf(f, "\n"); if (!first_dev) fprintf(f, "\n");
fprintf(f, " ]"); if (!no_json) fprintf(f, " ]");
RC_RETURN(model); RC_RETURN(model);
} }
@ -1172,14 +1207,16 @@ int printf_ports(FILE* f, struct fpga_model* model)
struct fpga_tile* tile; struct fpga_tile* tile;
const char* conn_point_name_src; const char* conn_point_name_src;
int x, y, i, conn_point_dests_o, num_dests_for_this_conn_point; int x, y, i, conn_point_dests_o, num_dests_for_this_conn_point;
int first_port_printed; int first_in_tile, first_tile;
RC_CHECK(model); RC_CHECK(model);
fprintf(f, " \"ports\" : [\n");
first_tile = 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 = &model->tiles[y*model->x_width + x]; tile = &model->tiles[y*model->x_width + x];
first_port_printed = 0; first_in_tile = 1;
for (i = 0; i < tile->num_conn_point_names; i++) { for (i = 0; i < tile->num_conn_point_names; i++) {
conn_point_dests_o = tile->conn_point_names[i*2]; conn_point_dests_o = tile->conn_point_names[i*2];
if (i < tile->num_conn_point_names-1) if (i < tile->num_conn_point_names-1)
@ -1195,16 +1232,17 @@ int printf_ports(FILE* f, struct fpga_model* model)
tile->conn_point_names[i*2+1], x, y, i); tile->conn_point_names[i*2+1], x, y, i);
continue; continue;
} }
if (!first_port_printed) { if (first_in_tile && !first_tile)
first_port_printed = 1; fprintf(f, ",\n\n");
fprintf(f, "\n"); fprintf(f, "%s { \"y\" : %i, \"x\" : %i, \"name\" : \"%s\" }",
} first_in_tile ? "" : ",\n", y, x, conn_point_name_src);
fprintf(f, "port y%i x%i %s\n", first_in_tile = 0;
y, x, conn_point_name_src); first_tile = 0;
} }
} }
} }
return 0; fprintf(f, "\n ]");
RC_RETURN(model);
} }
int printf_conns(FILE* f, struct fpga_model* model) int printf_conns(FILE* f, struct fpga_model* model)
@ -1214,14 +1252,16 @@ int printf_conns(FILE* f, struct fpga_model* model)
const char* conn_point_name_src, *other_tile_connpt_str; const char* conn_point_name_src, *other_tile_connpt_str;
uint16_t other_tile_connpt_str_i; uint16_t other_tile_connpt_str_i;
int x, y, i, j, k, conn_point_dests_o, num_dests_for_this_conn_point; int x, y, i, j, k, conn_point_dests_o, num_dests_for_this_conn_point;
int other_tile_x, other_tile_y, first_conn_printed; int other_tile_x, other_tile_y, first_tile, first_in_tile;
RC_CHECK(model); RC_CHECK(model);
fprintf(f, " \"connections\" : [\n");
first_tile = 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 = &model->tiles[y*model->x_width + x]; tile = &model->tiles[y*model->x_width + x];
first_conn_printed = 0; first_in_tile = 1;
for (i = 0; i < tile->num_conn_point_names; i++) { for (i = 0; i < tile->num_conn_point_names; i++) {
conn_point_dests_o = tile->conn_point_names[i*2]; conn_point_dests_o = tile->conn_point_names[i*2];
if (i < tile->num_conn_point_names-1) if (i < tile->num_conn_point_names-1)
@ -1248,66 +1288,73 @@ int printf_conns(FILE* f, struct fpga_model* model)
continue; continue;
} }
if (!first_conn_printed) { if (first_in_tile && !first_tile)
first_conn_printed = 1; fprintf(f, ",\n\n");
fprintf(f, "\n"); sprintf(tmp_line, "\"y1\" : %i, \"x1\" : %i, \"name1\" : \"%s\", ",
}
sprintf(tmp_line, "conn y%i x%i %s ",
y, x, conn_point_name_src); y, x, conn_point_name_src);
k = strlen(tmp_line); k = strlen(tmp_line);
while (k < 45) while (k < 60)
tmp_line[k++] = ' '; tmp_line[k++] = ' ';
sprintf(&tmp_line[k], "y%i x%i %s\n", sprintf(&tmp_line[k], "\"y2\" : %i, \"x2\" : %i, \"name2\" : \"%s\"",
other_tile_y, other_tile_x, other_tile_connpt_str); other_tile_y, other_tile_x, other_tile_connpt_str);
fprintf(f, "%s", tmp_line); fprintf(f, "%s { %s }",
first_in_tile ? "" : ",\n", tmp_line);
first_in_tile = 0;
first_tile = 0;
} }
} }
} }
} }
return 0; fprintf(f, "\n ]");
RC_RETURN(model);
} }
int printf_switches(FILE* f, struct fpga_model* model) int printf_switches(FILE *f, struct fpga_model *model)
{ {
struct fpga_tile* tile; struct fpga_tile *tile;
int x, y, i, first_switch_printed; int x, y, i, first_in_tile, first_tile;
RC_CHECK(model); RC_CHECK(model);
fprintf(f, " \"switches\" : [\n");
first_tile = 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);
first_switch_printed = 0; first_in_tile = 1;
for (i = 0; i < tile->num_switches; i++) { for (i = 0; i < tile->num_switches; i++) {
if (!first_switch_printed) { if (first_in_tile && !first_tile)
first_switch_printed = 1; fprintf(f, ",\n\n");
fprintf(f, "\n"); fprintf(f, "%s { \"y\" : %i, \"x\" : %i%s }",
} first_in_tile ? "" : ",\n", y, x,
fprintf(f, "sw y%i x%i %s\n", fpga_switch_print_json(model, y, x, i));
y, x, fpga_switch_print(model, y, x, i)); first_in_tile = 0;
first_tile = 0;
} }
} }
} }
return 0; fprintf(f, "\n ]");
RC_RETURN(model);
} }
int printf_nets(FILE* f, struct fpga_model* model) int printf_nets(FILE* f, struct fpga_model* model, int no_json)
{ {
net_idx_t net_i; net_idx_t net_i;
int rc, first_line; int rc, first_line;
RC_CHECK(model); RC_CHECK(model);
fprintf(f, " \"nets\" : [\n"); if (!no_json) fprintf(f, " \"nets\" : [\n");
first_line = 1; 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) if (!no_json) fprintf(f, first_line ? " " : ",");
fprintf(f, ",");
first_line = 0; first_line = 0;
fnet_printf(f, model, net_i); fnet_printf(f, model, net_i, no_json);
} }
if (rc) FAIL(rc); if (rc) FAIL(rc);
if (!first_line) fprintf(f, "\n"); if (!no_json) {
fprintf(f, " ]"); if (!first_line) fprintf(f, "\n");
fprintf(f, " ]");
}
return 0; return 0;
fail: fail:
return rc; return rc;
@ -1555,19 +1602,24 @@ 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)
{ {
fprintf(f, "{\n"); if (!(flags & FP_NO_JSON)) {
printf_version(f); fprintf(f, "{\n");
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"); if (!(flags & FP_NO_JSON))
printf_devices(f, model, /*config_only*/ 1); fprintf(f, ",\n");
printf_devices(f, model, /*config_only*/ 1, flags & FP_NO_JSON);
fprintf(f, ",\n"); if (!(flags & FP_NO_JSON))
printf_nets(f, model); fprintf(f, ",\n");
printf_nets(f, model, flags & FP_NO_JSON);
} }
fprintf(f, "\n}\n"); if (!(flags & FP_NO_JSON))
fprintf(f, "\n}\n");
RC_RETURN(model); RC_RETURN(model);
} }

View File

@ -7,16 +7,16 @@
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_JSON 0x0001
int write_floorplan(FILE *f, struct fpga_model *model, int flags); int write_floorplan(FILE *f, struct fpga_model *model, int flags);
void printf_version(FILE *f); void printf_version(FILE *f);
int printf_tiles(FILE *f, struct fpga_model *model); int printf_tiles(FILE *f, struct fpga_model *model);
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 no_json);
int printf_ports(FILE *f, struct fpga_model *model); int printf_ports(FILE *f, struct fpga_model *model);
int printf_conns(FILE *f, struct fpga_model *model); int printf_conns(FILE *f, struct fpga_model *model);
int printf_switches(FILE *f, struct fpga_model *model); 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, int no_json);
int printf_IOB(FILE* f, struct fpga_model* model, int printf_IOB(FILE* f, struct fpga_model* model,
int y, int x, int type_idx, int config_only); int y, int x, int type_idx, int config_only);

View File

@ -79,32 +79,41 @@ void dump_data(int indent, const uint8_t *data, int len, int base)
} }
// returns a 16-bit word (0:15) plus 2 bits parity in bits 16 & 17 // returns a 16-bit word (0:15) plus 2 bits parity in bits 16 & 17
static int get_ramb_word_with_parity(const void *d, int word_idx) static int get_ramb_word_with_parity(const void *d, int word_idx, int clear_bits)
{ {
int w, i, bit_pos; int w, i, bit_pos, bit_mask;
w = 0; w = 0;
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
bit_pos = word_idx * 18 + 2 + 15-i; bit_pos = word_idx * 18 + 2 + 15-i;
if (((uint8_t *)d)[bit_pos/8] & (1<<((7-(bit_pos%8))))) bit_mask = 1<<((7-(bit_pos%8)));
if (((uint8_t *)d)[bit_pos/8] & bit_mask)
w |= 1<<i; w |= 1<<i;
if (clear_bits)
((uint8_t *)d)[bit_pos/8] &= ~bit_mask;
} }
// parity bit 0 (pos +1) // parity bit 0 (pos +1)
if (((uint8_t *)d)[(word_idx*18+1)/8] & (1<<(7-((word_idx*18+1)%8)))) bit_mask = 1<<(7-((word_idx*18+1)%8));
if (((uint8_t *)d)[(word_idx*18+1)/8] & bit_mask)
w |= 1<<16; w |= 1<<16;
if (clear_bits)
((uint8_t *)d)[(word_idx*18+1)/8] &= ~bit_mask;
// parity bit 1 (pos +0) // parity bit 1 (pos +0)
if (((uint8_t *)d)[(word_idx*18+0)/8] & (1<<(7-((word_idx*18+0)%8)))) bit_mask = 1<<(7-((word_idx*18+0)%8));
if (((uint8_t *)d)[(word_idx*18+0)/8] & bit_mask)
w |= 1<<17; w |= 1<<17;
if (clear_bits)
((uint8_t *)d)[(word_idx*18+0)/8] &= ~bit_mask;
return w; return w;
} }
// src points to 16+2 (=18) bit words, dest must hold enough space // src points to 16+2 (=18) bit words, dest must hold enough space
// for num_words words. // for num_words words.
static void ramb_data_to_words(int *dest, const void *src, int num_words) static void ramb_data_to_words(int *dest, const void *src, int num_words, int clear_bits)
{ {
int i; int i;
for (i = 0; i < num_words; i++) for (i = 0; i < num_words; i++)
dest[i] = get_ramb_word_with_parity(src, i); dest[i] = get_ramb_word_with_parity(src, i, clear_bits);
} }
uint16_t __swab16(uint16_t x) uint16_t __swab16(uint16_t x)
@ -121,29 +130,6 @@ uint32_t __swab32(uint32_t x)
((x & 0xff000000UL) >> 24)); \ ((x & 0xff000000UL) >> 24)); \
} }
int atom_found(char *bits, const cfg_atom_t *atom)
{
int i;
for (i = 0; atom->must_0[i] != -1; i++)
if (bits[atom->must_0[i]])
break;
if (atom->must_0[i] != -1)
return 0;
for (i = 0; atom->must_1[i] != -1; i++)
if (!bits[atom->must_1[i]])
break;
return atom->must_1[i] == -1;
}
void atom_remove(char *bits, const cfg_atom_t *atom)
{
int i;
for (i = 0; atom->must_1[i] != -1; i++) {
if (bits[atom->must_1[i]])
bits[atom->must_1[i]] = 0;
}
}
static int bool_nextlen(const char *expr, int len) static int bool_nextlen(const char *expr, int len)
{ {
int i, depth; int i, depth;
@ -471,53 +457,14 @@ void printf_type2(uint8_t *d, int len, int inpos, int num_entries)
} }
} }
static int ramb_words_to_bram16(int (*init_data)[64][16], int (*init_parity)[8][16], int (*ramb_words)[1024]) static void ramb_words_split_data_parity(const int (*ramb_words)[1024],
int (*init_data)[64][16], int (*init_parity)[8][16])
{ {
int init_i, i, j, bits_set; int init_i, i, j;
bits_set = 0; // merge parity bits into parity words
// prepare parity words for string printf
for (init_i = 0; init_i < 8; init_i++) { for (init_i = 0; init_i < 8; init_i++) {
for (i = 0; i < 16; i++) { // 16 uint16_t words in one ramb16 parity string for (i = 0; i < 16; i++) {
(*init_parity)[init_i][i] = 0;
// 2 parity bits from each word, so 2*4=8 words have
// to be processed for 16 parity bits
for (j = 0; j < 4; j++) {
if ((*ramb_words)[64*init_i + 4*i + j] & (1<<16))
(*init_parity)[init_i][i] |= 1<<(j*4+0);
if ((*ramb_words)[64*init_i + 4*i + j] & (1<<17))
(*init_parity)[init_i][i] |= 1<<(j*4+1);
if ((*ramb_words)[512 + 64*init_i + 4*i + j] & (1<<16))
(*init_parity)[init_i][i] |= 1<<(j*4+2);
if ((*ramb_words)[512 + 64*init_i + 4*i + j] & (1<<17))
(*init_parity)[init_i][i] |= 1<<(j*4+3);
}
if ((*init_parity)[init_i][i])
bits_set = 1;
}
}
// prepare data words for string printf
for (init_i = 0; init_i < 64; init_i++) {
for (i = 0; i < 8; i++) {
(*init_data)[init_i][i*2] = (*ramb_words)[init_i*8 + i] & 0xFFFF;
(*init_data)[init_i][i*2+1] = (*ramb_words)[512 + init_i*8 + i] & 0xFFFF;
if ((*init_data)[init_i][i*2]
|| (*init_data)[init_i][i*2+1])
bits_set = 1;
}
}
return bits_set;
}
static int ramb_words_to_bram8(int (*init_data)[64][16], int (*init_parity)[8][16], int (*ramb_words)[1024])
{
int init_i, i, j, devs_used;
devs_used = 0; // bit1 = dev0, bit2 = dev1
// prepare parity words (0:3 are for the first bram8 device, 4:7 for the second one)
for (init_i = 0; init_i < 8; init_i++) {
for (i = 0; i < 16; i++) { // 16 uint16_t words in one ramb16 parity string
(*init_parity)[init_i][i] = 0; (*init_parity)[init_i][i] = 0;
// 2 parity bits from each word, so 2*4=8 words have // 2 parity bits from each word, so 2*4=8 words have
// to be processed for 16 parity bits // to be processed for 16 parity bits
@ -527,26 +474,21 @@ static int ramb_words_to_bram8(int (*init_data)[64][16], int (*init_parity)[8][1
if ((*ramb_words)[128*init_i + 8*i + j] & (1<<17)) if ((*ramb_words)[128*init_i + 8*i + j] & (1<<17))
(*init_parity)[init_i][i] |= 1<<(j*2+1); (*init_parity)[init_i][i] |= 1<<(j*2+1);
} }
if ((*init_parity)[init_i][i])
devs_used |= (init_i < 4) ? 0x01 : 0x02;
} }
} }
// prepare data words (0:31 are for the first bram8 device, 32:63 for the second one) // mask out parity bits
for (init_i = 0; init_i < 64; init_i++) { for (init_i = 0; init_i < 64; init_i++) {
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
(*init_data)[init_i][i] = (*ramb_words)[init_i*16 + i] & 0xFFFF; (*init_data)[init_i][i] = (*ramb_words)[init_i*16 + i] & 0xFFFF;
if ((*init_data)[init_i][i])
devs_used |= (init_i < 32) ? 0x01 : 0x02;
} }
} }
return devs_used;
} }
void printf_ramb_data(const uint8_t *bits, int row, int bram_idx) void printf_ramb_data(const uint8_t *bits, int row, int bram_idx)
{ {
int nonzero_head, nonzero_tail, ramb_words[1024]; int nonzero_head, nonzero_tail, ramb_words[1024];
int init_data[64][16], init_parity[8][16]; int init_data[64][16], init_parity[8][16];
int i, j, devs_used; int i, j, header_printed;
// check head and tail // check head and tail
nonzero_head = 0; nonzero_head = 0;
@ -579,102 +521,123 @@ void printf_ramb_data(const uint8_t *bits, int row, int bram_idx)
} }
} }
ramb_data_to_words(ramb_words, &bits[18], sizeof(ramb_words)/sizeof(*ramb_words)); ramb_data_to_words(ramb_words, &bits[XC6_BRAM_DATA_PREFIX_LEN],
sizeof(ramb_words)/sizeof(*ramb_words), /*clear_bits*/ 0);
ramb_words_split_data_parity(&ramb_words, &init_data, &init_parity);
// ramb16 // ramb16
devs_used = ramb_words_to_bram16(&init_data, &init_parity, &ramb_words); header_printed = 0;
if (devs_used) { for (i = 0; i < 8; i++) {
printf("br%i maj_i %i dev_i %i/16\n", row, for (j = 0; j < 16; j++) {
bram_idx/XC6_BRAM16_DEVS_PER_MAJOR, if (!init_parity[i][j]) continue;
bram_idx%XC6_BRAM16_DEVS_PER_MAJOR); if (!header_printed) {
printf("{\n"); header_printed = 1;
for (i = 0; i < 8; i++) { printf("br%i maj_i %i dev_i %i/16\n{\n", row,
for (j = 0; j < 16; j++) { bram_idx/XC6_BRAM16_DEVS_PER_MAJOR,
if (init_parity[i][j]) { bram_idx%XC6_BRAM16_DEVS_PER_MAJOR);
printf(" parity 0x%02X \"", i);
for (j = 0; j < 16; j++)
printf("%04X", init_parity[i][15-j]);
printf("\"\n");
break;
}
} }
printf(" parity 0x%02X \"", i);
for (j = 0; j < 16; j++)
printf("%04X", init_parity[i][15-j]);
printf("\"\n");
} }
for (i = 0; i < 64; i++) {
for (j = 0; j < 16; j++) {
if (init_data[i][j]) {
printf(" init 0x%02X \"", i);
for (j = 0; j < 16; j++)
printf("%04X", init_data[i][15-j]);
printf("\"\n");
break;
}
}
}
printf("}\n");
} }
for (i = 0; i < 64; i++) {
for (j = 0; j < 16; j++) {
if (!init_data[i][j]) continue;
if (!header_printed) {
header_printed = 1;
printf("br%i maj_i %i dev_i %i/16\n{\n", row,
bram_idx/XC6_BRAM16_DEVS_PER_MAJOR,
bram_idx%XC6_BRAM16_DEVS_PER_MAJOR);
}
printf(" init 0x%02X \"", i);
for (j = 0; j < 16; j++)
printf("%04X", init_data[i][15-j]);
printf("\"\n");
}
}
if (header_printed)
printf("}\n");
devs_used = ramb_words_to_bram8(&init_data, &init_parity, &ramb_words);
// ramb8,0 // ramb8,0
if (devs_used & 0x01) { header_printed = 0;
printf("br%i maj_i %i dev_i %i,0/8\n", row, for (i = 0; i < 4; i++) {
bram_idx/XC6_BRAM16_DEVS_PER_MAJOR, for (j = 0; j < 16; j++) {
bram_idx%XC6_BRAM16_DEVS_PER_MAJOR); if (!init_parity[i][j]) continue;
printf("{\n"); if (!header_printed) {
for (i = 0; i < 4; i++) { header_printed = 1;
for (j = 0; j < 16; j++) { printf("br%i maj_i %i dev_i %i,0/8\n{\n", row,
if (init_parity[i][j]) { bram_idx/XC6_BRAM16_DEVS_PER_MAJOR,
printf(" parity 0x%02X \"", i); bram_idx%XC6_BRAM16_DEVS_PER_MAJOR);
for (j = 0; j < 16; j++)
printf("%04X", init_parity[i][15-j]);
printf("\"\n");
break;
}
} }
printf(" parity 0x%02X \"", i);
for (j = 0; j < 16; j++)
printf("%04X", init_parity[i][15-j]);
printf("\"\n");
} }
for (i = 0; i < 32; i++) {
for (j = 0; j < 16; j++) {
if (init_data[i][j]) {
printf(" init 0x%02X \"", i);
for (j = 0; j < 16; j++)
printf("%04X", init_data[i][15-j]);
printf("\"\n");
break;
}
}
}
printf("}\n");
} }
for (i = 0; i < 32; i++) {
for (j = 0; j < 16; j++) {
if (!init_data[i][j]) continue;
if (!header_printed) {
header_printed = 1;
printf("br%i maj_i %i dev_i %i,0/8\n{\n", row,
bram_idx/XC6_BRAM16_DEVS_PER_MAJOR,
bram_idx%XC6_BRAM16_DEVS_PER_MAJOR);
}
printf(" init 0x%02X \"", i);
for (j = 0; j < 16; j++)
printf("%04X", init_data[i][15-j]);
printf("\"\n");
}
}
if (header_printed)
printf("}\n");
// ramb8,1 // ramb8,1
if (devs_used & 0x02) { header_printed = 0;
printf("br%i maj_i %i dev_i %i,1/8\n", row, for (i = 4; i < 8; i++) {
bram_idx/XC6_BRAM16_DEVS_PER_MAJOR, for (j = 0; j < 16; j++) {
bram_idx%XC6_BRAM16_DEVS_PER_MAJOR); if (!init_parity[i][j]) continue;
printf("{\n"); if (!header_printed) {
for (i = 4; i < 8; i++) { header_printed = 1;
for (j = 0; j < 16; j++) { printf("br%i maj_i %i dev_i %i,1/8\n{\n", row,
if (init_parity[i][j]) { bram_idx/XC6_BRAM16_DEVS_PER_MAJOR,
printf(" parity 0x%02X \"", i-4); bram_idx%XC6_BRAM16_DEVS_PER_MAJOR);
for (j = 0; j < 16; j++)
printf("%04X", init_parity[i][15-j]);
printf("\"\n");
break;
}
} }
printf(" parity 0x%02X \"", i-4);
for (j = 0; j < 16; j++)
printf("%04X", init_parity[i][15-j]);
printf("\"\n");
} }
for (i = 32; i < 64; i++) {
for (j = 0; j < 16; j++) {
if (init_data[i][j]) {
printf(" init 0x%02X \"", i-32);
for (j = 0; j < 16; j++)
printf("%04X", init_data[i][15-j]);
printf("\"\n");
break;
}
}
}
printf("}\n");
} }
for (i = 32; i < 64; i++) {
for (j = 0; j < 16; j++) {
if (!init_data[i][j]) continue;
if (!header_printed) {
header_printed = 1;
printf("br%i maj_i %i dev_i %i,1/8\n{\n", row,
bram_idx/XC6_BRAM16_DEVS_PER_MAJOR,
bram_idx%XC6_BRAM16_DEVS_PER_MAJOR);
}
printf(" init 0x%02X \"", i-32);
for (j = 0; j < 16; j++)
printf("%04X", init_data[i][15-j]);
printf("\"\n");
}
}
if (header_printed)
printf("}\n");
}
void bram_extract_init(bram_init_t *init, const uint8_t *bits)
{
int ramb_words[1024];
ramb_data_to_words(ramb_words, &bits[XC6_BRAM_DATA_PREFIX_LEN],
sizeof(ramb_words)/sizeof(*ramb_words), /*clear_bits*/ 1);
ramb_words_split_data_parity(&ramb_words, &init->data, &init->parity);
} }
int is_empty(const uint8_t *d, int l) int is_empty(const uint8_t *d, int l)
@ -718,6 +681,16 @@ void frame_set_bit(uint8_t *frame_d, int bit)
frame_d[(bit/16)*2 + !((bit/8)%2)] |= v; frame_d[(bit/16)*2 + !((bit/8)%2)] |= v;
} }
int frame_get_cpuword(const void *bits)
{
return mirror_2bytes(frame_get_pinword(bits));
}
void frame_set_cpuword(void *bits, int v)
{
frame_set_pinword(bits, mirror_2bytes(v));
}
// see ug380, table 2-5, bit ordering // see ug380, table 2-5, bit ordering
int frame_get_pinword(const void *bits) int frame_get_pinword(const void *bits)
{ {
@ -727,7 +700,7 @@ int frame_get_pinword(const void *bits)
return byte0 << 8 | byte1; return byte0 << 8 | byte1;
} }
void frame_set_pinword(void* bits, int v) void frame_set_pinword(void *bits, int v)
{ {
((uint8_t*)bits)[0] = v >> 8; ((uint8_t*)bits)[0] = v >> 8;
((uint8_t*)bits)[1] = v & 0xFF; ((uint8_t*)bits)[1] = v & 0xFF;
@ -742,9 +715,9 @@ uint8_t mirror_bits(uint8_t v)
return mv; return mv;
} }
int pinword_to_cpu(int pinword) int mirror_2bytes(int v)
{ {
return mirror_bits(((pinword & 0xFF00) >> 8)) << 8 | mirror_bits(pinword & 0xFF); return mirror_bits(((v & 0xFF00) >> 8)) << 8 | mirror_bits(v & 0xFF);
} }
// see ug380, table 2-5, bit ordering // see ug380, table 2-5, bit ordering
@ -1025,7 +998,7 @@ const char *fmt_word(int word)
static char buf[NUM_BUFS][BUF_SIZE]; static char buf[NUM_BUFS][BUF_SIZE];
static int last_buf = 0; static int last_buf = 0;
char bit_str[XC6_WORD_BITS]; char bit_str[XC6_WORD_BITS];
int i, num_bits_printed; int i;
last_buf = (last_buf+1)%NUM_BUFS; last_buf = (last_buf+1)%NUM_BUFS;
@ -1033,16 +1006,11 @@ const char *fmt_word(int word)
bit_str[i] = (word & (1ULL << (XC6_WORD_BITS-i-1))) ? '1' : '0'; bit_str[i] = (word & (1ULL << (XC6_WORD_BITS-i-1))) ? '1' : '0';
snprintf(buf[last_buf], sizeof(*buf), "0b%.*s 0x%.*X", XC6_WORD_BITS, bit_str, XC6_WORD_BITS/4, word); snprintf(buf[last_buf], sizeof(*buf), "0b%.*s 0x%.*X", XC6_WORD_BITS, bit_str, XC6_WORD_BITS/4, word);
num_bits_printed = 0;
for (i = 0; i < XC6_WORD_BITS; i++) { for (i = 0; i < XC6_WORD_BITS; i++) {
if (word & (1 << i)) { if (word & (1 << i))
if (num_bits_printed >= 4) {
sprintf(&buf[last_buf][strlen(buf[last_buf])], " ...");
break;
}
sprintf(&buf[last_buf][strlen(buf[last_buf])], " %i", i); sprintf(&buf[last_buf][strlen(buf[last_buf])], " %i", i);
num_bits_printed++; else
} sprintf(&buf[last_buf][strlen(buf[last_buf])], i < 10 ? " " : " ");
} }
strcat(buf[last_buf], "\n"); strcat(buf[last_buf], "\n");
return buf[last_buf]; return buf[last_buf];

View File

@ -57,16 +57,13 @@ uint32_t __swab32(uint32_t x);
#define ATOM_MAX_BITS 32+1 // -1 signals end of array #define ATOM_MAX_BITS 32+1 // -1 signals end of array
typedef struct _cfg_atom typedef struct _cfg_bits
{ {
int must_0[ATOM_MAX_BITS]; int minor; // -1 is illegal and can be used to signal end-of-array
int must_1[ATOM_MAX_BITS]; int rel_v16; // vertical 16 from top, relative to start of device
const char* str; int bits; // 1 or more bits set
int flag; // used to remember a state such as 'found' int name; // enum value
} cfg_atom_t; } cfg_bits_t;
int atom_found(char* bits, const cfg_atom_t* atom);
void atom_remove(char* bits, const cfg_atom_t* atom);
uint64_t map_bits(uint64_t u64, int num_bits, int* src_pos); uint64_t map_bits(uint64_t u64, int num_bits, int* src_pos);
@ -80,6 +77,13 @@ int bool_req_pins(uint64_t u64, int num_bits);
void printf_type2(uint8_t* d, int len, int inpos, int num_entries); void printf_type2(uint8_t* d, int len, int inpos, int num_entries);
void printf_ramb_data(const uint8_t *bits, int row, int bram_idx); void printf_ramb_data(const uint8_t *bits, int row, int bram_idx);
typedef struct _bram_init // only first half of array used for bram8
{
int data[64][16];
int parity[8][16];
} bram_init_t;
void bram_extract_init(bram_init_t *init, const uint8_t *bits);
int is_empty(const uint8_t* d, int l); int is_empty(const uint8_t* d, int l);
int count_set_bits(const uint8_t* d, int l); int count_set_bits(const uint8_t* d, int l);
@ -87,11 +91,17 @@ int frame_get_bit(const uint8_t* frame_d, int bit);
void frame_clear_bit(uint8_t* frame_d, int bit); void frame_clear_bit(uint8_t* frame_d, int bit);
void frame_set_bit(uint8_t* frame_d, int bit); void frame_set_bit(uint8_t* frame_d, int bit);
// cpuword returns the word in such a way that a bit
// index (cpuword & (1<<i)) corresponds to the same bit
// position as presented to the FPGA.
int frame_get_cpuword(const void *bits);
void frame_set_cpuword(void* bits, int v);
int frame_get_pinword(const void *bits); int frame_get_pinword(const void *bits);
void frame_set_pinword(void* bits, int v); void frame_set_pinword(void* bits, int v);
uint8_t mirror_bits(uint8_t v); uint8_t mirror_bits(uint8_t v);
int pinword_to_cpu(int pinword); int mirror_2bytes(int pinword);
uint16_t frame_get_u16(const uint8_t* frame_d); uint16_t frame_get_u16(const uint8_t* frame_d);
uint64_t frame_get_u64(const uint8_t* frame_d); uint64_t frame_get_u64(const uint8_t* frame_d);

View File

@ -668,7 +668,7 @@ 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.
enum { BRAM16 = 1, BRAM8 }; // subtype enum { BRAM16 = 1, BRAM8 }; // subtype, bram8 not currently supported
enum { BRAM_TDP = 1, BRAM_SDP, BRAM_SP }; enum { BRAM_TDP = 1, BRAM_SDP, BRAM_SP };
enum { BRAM_RST_SYNC = 1, BRAM_RST_ASYNC }; 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_WIDTH_0 = 1, BRAM_WIDTH_1, BRAM_WIDTH_2, BRAM_WIDTH_4, BRAM_WIDTH_9, BRAM_WIDTH_18, BRAM_WIDTH_36 };
@ -676,11 +676,11 @@ enum { BRAM_WRITE_FIRST = 1, BRAM_READ_FIRST, BRAM_NO_CHANGE };
enum { BRAM_OUTREG_ON = 1, BRAM_OUTREG_OFF }; enum { BRAM_OUTREG_ON = 1, BRAM_OUTREG_OFF };
enum { BRAM_RST_PRIORITY_SR = 1, BRAM_RST_PRIORITY_CE }; enum { BRAM_RST_PRIORITY_SR = 1, BRAM_RST_PRIORITY_CE };
// fpgadev_bram configures either a bram16 or a bram8 device. // fpgadev_bram configures a bram16 device (bram8 is not currently supported)
// see ug383 // see ug383
struct fpgadev_bram struct fpgadev_bram
{ {
int *data; // points to 1024 (BRAM16) or 512 (BRAM8) words (each 16+2=18 bits) struct bram_init *init;
int ram_mode; // BRAM8 only: BRAM_TDP, BRAM_SDP, BRAM_SP (?) int ram_mode; // BRAM8 only: BRAM_TDP, BRAM_SDP, BRAM_SP (?)
int rst_type; // BRAM_RST_SYNC, BRAM_RST_ASYNC int rst_type; // BRAM_RST_SYNC, BRAM_RST_ASYNC
@ -1232,4 +1232,3 @@ struct w_net
#define ADD_PREF 1 #define ADD_PREF 1
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);