moved model into separate file so multiple utils can use it
This commit is contained in:
parent
9d0a00856b
commit
d1e8d5f557
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -1,5 +1,6 @@
|
||||||
bit2txt
|
bit2txt
|
||||||
bit2txt.o
|
bit2txt.o
|
||||||
draw_fpga
|
draw_svg_tiles
|
||||||
draw_fpga.o
|
draw_svg_tiles.o
|
||||||
helper.o
|
helper.o
|
||||||
|
model.o
|
||||||
|
|
22
Makefile
22
Makefile
|
@ -6,24 +6,26 @@
|
||||||
# For details see the UNLICENSE file at the root of the source tree.
|
# For details see the UNLICENSE file at the root of the source tree.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
.PHONY: all clean
|
||||||
CFLAGS = -Wall -g
|
CFLAGS = -Wall -g
|
||||||
#TARGETS = bit2txt draw_fpga
|
|
||||||
#OBJS = $(TARGETS:=.o)
|
|
||||||
LDLIBS = -lxml2
|
LDLIBS = -lxml2
|
||||||
|
|
||||||
all: bit2txt draw_fpga xc6slx9.svg
|
all: bit2txt draw_svg_tiles xc6slx9.svg
|
||||||
|
|
||||||
xc6slx9.svg: draw_fpga
|
xc6slx9.svg: draw_svg_tiles
|
||||||
./draw_fpga --svg | xmllint --pretty 1 - > $@
|
./draw_svg_tiles | xmllint --pretty 1 - > $@
|
||||||
|
|
||||||
bit2txt: bit2txt.o helper.o
|
bit2txt: bit2txt.o helper.o
|
||||||
|
|
||||||
bit2txt.o:bit2txt.c helper.h
|
bit2txt.o: bit2txt.c helper.h
|
||||||
|
|
||||||
helper.o:helper.c helper.h
|
helper.o: helper.c helper.h
|
||||||
|
|
||||||
draw_fpga: draw_fpga.o
|
model.o: model.c model.h
|
||||||
|
|
||||||
|
draw_svg_tiles: draw_svg_tiles.o model.o
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f bit2txt bit2txt.o helper.o draw_fpga
|
rm -f bit2txt bit2txt.o \
|
||||||
.PHONY: all clean
|
draw_svg_tiles draw_svg_tiles.o \
|
||||||
|
helper.o model.o
|
||||||
|
|
103
draw_svg_tiles.c
Normal file
103
draw_svg_tiles.c
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
//
|
||||||
|
// Author: Wolfgang Spraul
|
||||||
|
//
|
||||||
|
// This is free and unencumbered software released into the public domain.
|
||||||
|
// For details see the UNLICENSE file at the root of the source tree.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include <libxml/parser.h>
|
||||||
|
#include <libxml/xpath.h>
|
||||||
|
#include <libxml/xpathInternals.h>
|
||||||
|
|
||||||
|
#include "model.h"
|
||||||
|
|
||||||
|
void print_svg_tiles(struct fpga_model* model);
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
static const xmlChar* empty_svg = (const xmlChar*)
|
||||||
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
|
"<svg version=\"2.0\"\n"
|
||||||
|
" xmlns=\"http://www.w3.org/2000/svg\"\n"
|
||||||
|
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
|
||||||
|
" xmlns:fpga=\"http://qi-hw.com/fpga\"\n"
|
||||||
|
" id=\"root\">\n"
|
||||||
|
"<style type=\"text/css\"><![CDATA[text{font-size:6pt;text-anchor:end;}]]></style>\n"
|
||||||
|
"</svg>\n";
|
||||||
|
|
||||||
|
xmlDocPtr doc = 0;
|
||||||
|
xmlXPathContextPtr xpathCtx = 0;
|
||||||
|
xmlXPathObjectPtr xpathObj = 0;
|
||||||
|
xmlNodePtr new_node;
|
||||||
|
struct fpga_model* model = 0;
|
||||||
|
char str[128];
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
// can't get indent formatting to work - use 'xmllint --pretty 1 -'
|
||||||
|
// on the output for now
|
||||||
|
|
||||||
|
xmlInitParser();
|
||||||
|
model = fpga_build_model(XC6SLX9_ROWS, XC6SLX9_COLUMNS,
|
||||||
|
XC6SLX9_LEFT_WIRING, XC6SLX9_RIGHT_WIRING);
|
||||||
|
if (!model) goto fail;
|
||||||
|
|
||||||
|
doc = xmlParseDoc(empty_svg);
|
||||||
|
if (!doc) {
|
||||||
|
fprintf(stderr, "Internal error %i.\n", __LINE__);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
xpathCtx = xmlXPathNewContext(doc);
|
||||||
|
if (!xpathCtx) {
|
||||||
|
fprintf(stderr, "Cannot create XPath context.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
xmlXPathRegisterNs(xpathCtx, BAD_CAST "svg", BAD_CAST "http://www.w3.org/2000/svg");
|
||||||
|
xpathObj = xmlXPathEvalExpression(BAD_CAST "//svg:*[@id='root']", xpathCtx);
|
||||||
|
if (!xpathObj) {
|
||||||
|
fprintf(stderr, "Cannot evaluate root expression.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (!xpathObj->nodesetval) {
|
||||||
|
fprintf(stderr, "Cannot find root node.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (xpathObj->nodesetval->nodeNr != 1) {
|
||||||
|
fprintf(stderr, "Found %i root nodes.\n", xpathObj->nodesetval->nodeNr);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < model->tile_y_range; i++) {
|
||||||
|
for (j = 0; j < model->tile_x_range; j++) {
|
||||||
|
strcpy(str, fpga_tiletype_str(model->tiles[i*model->tile_x_range+j].type));
|
||||||
|
new_node = xmlNewChild(xpathObj->nodesetval->nodeTab[0], 0 /* xmlNsPtr */, BAD_CAST "text", BAD_CAST str);
|
||||||
|
xmlSetProp(new_node, BAD_CAST "x", xmlXPathCastNumberToString(130 + j*130));
|
||||||
|
xmlSetProp(new_node, BAD_CAST "y", xmlXPathCastNumberToString(40 + i*14));
|
||||||
|
xmlSetProp(new_node, BAD_CAST "fpga:tile_y", BAD_CAST xmlXPathCastNumberToString(i));
|
||||||
|
xmlSetProp(new_node, BAD_CAST "fpga:tile_x", BAD_CAST xmlXPathCastNumberToString(j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlSetProp(xpathObj->nodesetval->nodeTab[0], BAD_CAST "width", BAD_CAST xmlXPathCastNumberToString(model->tile_x_range * 130 + 65));
|
||||||
|
xmlSetProp(xpathObj->nodesetval->nodeTab[0], BAD_CAST "height", BAD_CAST xmlXPathCastNumberToString(model->tile_y_range * 14 + 60));
|
||||||
|
|
||||||
|
xmlDocFormatDump(stdout, doc, 1 /* format */);
|
||||||
|
xmlXPathFreeObject(xpathObj);
|
||||||
|
xmlXPathFreeContext(xpathCtx);
|
||||||
|
xmlFreeDoc(doc);
|
||||||
|
xmlCleanupParser();
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (xpathObj) xmlXPathFreeObject(xpathObj);
|
||||||
|
if (xpathCtx) xmlXPathFreeContext(xpathCtx);
|
||||||
|
if (doc) xmlFreeDoc(doc);
|
||||||
|
xmlCleanupParser();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
|
@ -5,180 +5,9 @@
|
||||||
// For details see the UNLICENSE file at the root of the source tree.
|
// For details see the UNLICENSE file at the root of the source tree.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <stdio.h>
|
#include "model.h"
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#include <libxml/tree.h>
|
static const char* fpga_ttstr[] = // tile type strings
|
||||||
#include <libxml/parser.h>
|
|
||||||
#include <libxml/xpath.h>
|
|
||||||
#include <libxml/xpathInternals.h>
|
|
||||||
|
|
||||||
struct fpga_model
|
|
||||||
{
|
|
||||||
int tile_x_range, tile_y_range;
|
|
||||||
struct fpga_tile* tiles;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum fpga_tile_type
|
|
||||||
{
|
|
||||||
NA,
|
|
||||||
ROUTING,
|
|
||||||
ROUTING_BRK,
|
|
||||||
ROUTING_VIA,
|
|
||||||
HCLK_ROUTING_XM,
|
|
||||||
HCLK_ROUTING_XL,
|
|
||||||
HCLK_LOGIC_XM,
|
|
||||||
HCLK_LOGIC_XL,
|
|
||||||
LOGIC_XM,
|
|
||||||
LOGIC_XL,
|
|
||||||
REGH_ROUTING_XM,
|
|
||||||
REGH_ROUTING_XL,
|
|
||||||
REGH_LOGIC_XM,
|
|
||||||
REGH_LOGIC_XL,
|
|
||||||
BRAM_ROUTING,
|
|
||||||
BRAM_ROUTING_BRK,
|
|
||||||
BRAM,
|
|
||||||
BRAM_ROUTING_TERM_T,
|
|
||||||
BRAM_ROUTING_TERM_B,
|
|
||||||
BRAM_ROUTING_VIA_TERM_T,
|
|
||||||
BRAM_ROUTING_VIA_TERM_B,
|
|
||||||
BRAM_TERM_LT,
|
|
||||||
BRAM_TERM_RT,
|
|
||||||
BRAM_TERM_LB,
|
|
||||||
BRAM_TERM_RB,
|
|
||||||
HCLK_BRAM_ROUTING,
|
|
||||||
HCLK_BRAM_ROUTING_VIA,
|
|
||||||
HCLK_BRAM,
|
|
||||||
REGH_BRAM_ROUTING,
|
|
||||||
REGH_BRAM_ROUTING_VIA,
|
|
||||||
REGH_BRAM_L,
|
|
||||||
REGH_BRAM_R,
|
|
||||||
MACC,
|
|
||||||
HCLK_MACC_ROUTING,
|
|
||||||
HCLK_MACC_ROUTING_VIA,
|
|
||||||
HCLK_MACC,
|
|
||||||
REGH_MACC_ROUTING,
|
|
||||||
REGH_MACC_ROUTING_VIA,
|
|
||||||
REGH_MACC_L,
|
|
||||||
PLL_T,
|
|
||||||
DCM_T,
|
|
||||||
PLL_B,
|
|
||||||
DCM_B,
|
|
||||||
REG_T,
|
|
||||||
REG_TERM_T,
|
|
||||||
REG_TERM_B,
|
|
||||||
REG_B,
|
|
||||||
REGV_TERM_T,
|
|
||||||
REGV_TERM_B,
|
|
||||||
HCLK_REGV,
|
|
||||||
REGV,
|
|
||||||
REGV_BRK,
|
|
||||||
REGV_T,
|
|
||||||
REGV_B,
|
|
||||||
REGV_MIDBUF_T,
|
|
||||||
REGV_HCLKBUF_T,
|
|
||||||
REGV_HCLKBUF_B,
|
|
||||||
REGV_MIDBUF_B,
|
|
||||||
REGC_ROUTING,
|
|
||||||
REGC_LOGIC,
|
|
||||||
REGC_CMT,
|
|
||||||
CENTER, // unique center tile in the middle of the chip
|
|
||||||
IO_T,
|
|
||||||
IO_B,
|
|
||||||
IO_TERM_T,
|
|
||||||
IO_TERM_B,
|
|
||||||
IO_ROUTING,
|
|
||||||
IO_LOGIC_TERM_T,
|
|
||||||
IO_LOGIC_TERM_B,
|
|
||||||
IO_OUTER_T,
|
|
||||||
IO_INNER_T,
|
|
||||||
IO_OUTER_B,
|
|
||||||
IO_INNER_B,
|
|
||||||
IO_BUFPLL_TERM_T,
|
|
||||||
IO_LOGIC_REG_TERM_T,
|
|
||||||
IO_BUFPLL_TERM_B,
|
|
||||||
IO_LOGIC_REG_TERM_B,
|
|
||||||
LOGIC_ROUTING_TERM_B,
|
|
||||||
LOGIC_NOIO_TERM_B,
|
|
||||||
MACC_ROUTING_TERM_T,
|
|
||||||
MACC_ROUTING_TERM_B,
|
|
||||||
MACC_VIA_TERM_T,
|
|
||||||
MACC_TERM_TL,
|
|
||||||
MACC_TERM_TR,
|
|
||||||
MACC_TERM_BL,
|
|
||||||
MACC_TERM_BR,
|
|
||||||
ROUTING_VIA_REGC,
|
|
||||||
ROUTING_VIA_IO,
|
|
||||||
ROUTING_VIA_IO_DCM,
|
|
||||||
ROUTING_VIA_CARRY,
|
|
||||||
CORNER_TERM_L,
|
|
||||||
CORNER_TERM_R,
|
|
||||||
IO_TERM_L_UPPER_TOP,
|
|
||||||
IO_TERM_L_UPPER_BOT,
|
|
||||||
IO_TERM_L_LOWER_TOP,
|
|
||||||
IO_TERM_L_LOWER_BOT,
|
|
||||||
IO_TERM_R_UPPER_TOP,
|
|
||||||
IO_TERM_R_UPPER_BOT,
|
|
||||||
IO_TERM_R_LOWER_TOP,
|
|
||||||
IO_TERM_R_LOWER_BOT,
|
|
||||||
IO_TERM_L,
|
|
||||||
IO_TERM_R,
|
|
||||||
HCLK_TERM_L,
|
|
||||||
HCLK_TERM_R,
|
|
||||||
REGH_IO_TERM_L,
|
|
||||||
REGH_IO_TERM_R,
|
|
||||||
REG_L,
|
|
||||||
REG_R,
|
|
||||||
IO_PCI_L,
|
|
||||||
IO_PCI_R,
|
|
||||||
IO_RDY_L,
|
|
||||||
IO_RDY_R,
|
|
||||||
IO_L,
|
|
||||||
IO_R,
|
|
||||||
IO_PCI_CONN_L,
|
|
||||||
IO_PCI_CONN_R,
|
|
||||||
CORNER_TERM_T,
|
|
||||||
CORNER_TERM_B,
|
|
||||||
ROUTING_IO_L,
|
|
||||||
HCLK_ROUTING_IO_L,
|
|
||||||
HCLK_ROUTING_IO_R,
|
|
||||||
REGH_ROUTING_IO_L,
|
|
||||||
REGH_ROUTING_IO_R,
|
|
||||||
ROUTING_IO_L_BRK,
|
|
||||||
ROUTING_GCLK,
|
|
||||||
REGH_IO_L,
|
|
||||||
REGH_IO_R,
|
|
||||||
REGH_MCB,
|
|
||||||
HCLK_MCB,
|
|
||||||
ROUTING_IO_VIA_L,
|
|
||||||
ROUTING_IO_VIA_R,
|
|
||||||
ROUTING_IO_PCI_CE_L,
|
|
||||||
ROUTING_IO_PCI_CE_R,
|
|
||||||
CORNER_TL,
|
|
||||||
CORNER_BL,
|
|
||||||
CORNER_TR_UPPER,
|
|
||||||
CORNER_TR_LOWER,
|
|
||||||
CORNER_BR_UPPER,
|
|
||||||
CORNER_BR_LOWER,
|
|
||||||
HCLK_IO_TOP_UP_L,
|
|
||||||
HCLK_IO_TOP_UP_R,
|
|
||||||
HCLK_IO_TOP_SPLIT_L,
|
|
||||||
HCLK_IO_TOP_SPLIT_R,
|
|
||||||
HCLK_IO_TOP_DN_L,
|
|
||||||
HCLK_IO_TOP_DN_R,
|
|
||||||
HCLK_IO_BOT_UP_L,
|
|
||||||
HCLK_IO_BOT_UP_R,
|
|
||||||
HCLK_IO_BOT_SPLIT_L,
|
|
||||||
HCLK_IO_BOT_SPLIT_R,
|
|
||||||
HCLK_IO_BOT_DN_L,
|
|
||||||
HCLK_IO_BOT_DN_R,
|
|
||||||
};
|
|
||||||
|
|
||||||
const char* fpga_ttstr[] = // tile type strings
|
|
||||||
{
|
{
|
||||||
[NA] = "NA",
|
[NA] = "NA",
|
||||||
[ROUTING] = "ROUTING",
|
[ROUTING] = "ROUTING",
|
||||||
|
@ -333,103 +162,7 @@ const char* fpga_ttstr[] = // tile type strings
|
||||||
[HCLK_IO_BOT_DN_R] = "HCLK_IO_BOT_DN_R",
|
[HCLK_IO_BOT_DN_R] = "HCLK_IO_BOT_DN_R",
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fpga_tile
|
struct fpga_model* fpga_build_model(int fpga_rows, const char* columns,
|
||||||
{
|
|
||||||
enum fpga_tile_type type;
|
|
||||||
|
|
||||||
// expect up to 64 devices per tile
|
|
||||||
int num_devices;
|
|
||||||
struct fpga_device* devices;
|
|
||||||
|
|
||||||
// expect up to 28k connections to other tiles per tile
|
|
||||||
// 3*16 bit per connection:
|
|
||||||
// - x coordinate of other tile (16bit)
|
|
||||||
// - y coordinate of other tile (16bit)
|
|
||||||
// - endpoint index in other tile (16bit)
|
|
||||||
int num_conns; // conns array is 3*num_conns 16-bit words
|
|
||||||
uint16_t* conns; // num_conns*3 16-bit words: 16(x)-16(y)-16(endpoint)
|
|
||||||
|
|
||||||
// expect up to 5k endpoints per tile
|
|
||||||
// 16-bit index into conns (not yet multiplied by 3)
|
|
||||||
int num_endpoints;
|
|
||||||
uint16_t* endpoints;
|
|
||||||
// endpoints0 are conceptual endpoints without outgoing wires.
|
|
||||||
// Imagine their indices added to the end of num_endpoints, so
|
|
||||||
// the first endpoint0 is at index num_endpoints, the second one
|
|
||||||
// at num_endpoints+1, and so on.
|
|
||||||
int num_endpoints0;
|
|
||||||
|
|
||||||
// expect up to 4k connection pairs per tile
|
|
||||||
// 32bit: 31 off: not in use on: used
|
|
||||||
// 30 off: unidirectional on: bidirectional
|
|
||||||
// 29:15 from, index into endpoints
|
|
||||||
// 14:0 to, index into endpoints
|
|
||||||
int num_connect_pairs;
|
|
||||||
uint32_t* connect_pairs;
|
|
||||||
};
|
|
||||||
|
|
||||||
// columns
|
|
||||||
// 'L' = X+L logic block
|
|
||||||
// 'l' = X+L logic block without IO at top and bottom
|
|
||||||
// 'M' = X+M logic block
|
|
||||||
// 'm' = X+M logic block without IO at top and bottom
|
|
||||||
// 'B' = block ram
|
|
||||||
// 'D' = dsp (macc)
|
|
||||||
// 'R' = registers and center IO/logic column
|
|
||||||
//
|
|
||||||
// wiring on the left and right side is described with 16
|
|
||||||
// characters for each row - 'W' = wired, 'U' = unwired
|
|
||||||
// order is top-down
|
|
||||||
|
|
||||||
#define XC6SLX9_ROWS 4
|
|
||||||
#define XC6SLX9_COLUMNS "MLBMLDMRMlMLBML"
|
|
||||||
#define XC6SLX9_LEFT_WIRING \
|
|
||||||
/* row 3 */ "UWUWUWUW" "WWWWUUUU" \
|
|
||||||
/* row 2 */ "UUUUUUUU" "WWWWWWUU" \
|
|
||||||
/* row 1 */ "WWWUUWUU" "WUUWUUWU" \
|
|
||||||
/* row 0 */ "UWUUWUUW" "UUWWWWUU"
|
|
||||||
#define XC6SLX9_RIGHT_WIRING \
|
|
||||||
/* row 3 */ "UUWWUWUW" "WWWWUUUU" \
|
|
||||||
/* row 2 */ "UUUUUUUU" "WWWWWWUU" \
|
|
||||||
/* row 1 */ "WWWUUWUU" "WUUWUUWU" \
|
|
||||||
/* row 0 */ "UWUUWUUW" "UUWWWWUU"
|
|
||||||
|
|
||||||
struct fpga_model* build_model(int fpga_rows, const char* columns,
|
|
||||||
const char* left_wiring, const char* right_wiring);
|
|
||||||
void print_svg_tiles(struct fpga_model* model);
|
|
||||||
void write_folders(struct fpga_model* model, const char* root_folder);
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
|
||||||
{
|
|
||||||
struct fpga_model* model = 0;
|
|
||||||
|
|
||||||
if (argc < 2) {
|
|
||||||
printf("\n"
|
|
||||||
"draw_fpga - model and view of an FPGA\n"
|
|
||||||
"Public domain work by Wolfgang Spraul\n"
|
|
||||||
"\n"
|
|
||||||
"draw_fpga [options]\n"
|
|
||||||
" --svg writes a simple svg tile grid to stdout\n"
|
|
||||||
" --folder <path> writes a folder structure of tiles and devices\n"
|
|
||||||
"\n");
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
model = build_model(XC6SLX9_ROWS, XC6SLX9_COLUMNS,
|
|
||||||
XC6SLX9_LEFT_WIRING, XC6SLX9_RIGHT_WIRING);
|
|
||||||
if (!model) goto fail;
|
|
||||||
|
|
||||||
if (!strcmp(argv[1], "--svg"))
|
|
||||||
print_svg_tiles(model);
|
|
||||||
if (!strcmp(argv[1], "--folder"))
|
|
||||||
write_folders(model, argv[2]);
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
fail:
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct fpga_model* build_model(int fpga_rows, const char* columns,
|
|
||||||
const char* left_wiring, const char* right_wiring)
|
const char* left_wiring, const char* right_wiring)
|
||||||
{
|
{
|
||||||
int tile_rows, tile_columns, i, j, k, l, row_top_y, center_row, left_side;
|
int tile_rows, tile_columns, i, j, k, l, row_top_y, center_row, left_side;
|
||||||
|
@ -897,91 +630,9 @@ struct fpga_model* build_model(int fpga_rows, const char* columns,
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_svg_tiles(struct fpga_model* model)
|
const char* fpga_tiletype_str(enum fpga_tile_type type)
|
||||||
{
|
{
|
||||||
static const xmlChar* empty_svg = (const xmlChar*)
|
if (type >= sizeof(fpga_ttstr)/sizeof(fpga_ttstr[0])
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
|| !fpga_ttstr[type]) return "UNK";
|
||||||
"<svg version=\"2.0\"\n"
|
return fpga_ttstr[type];
|
||||||
" xmlns=\"http://www.w3.org/2000/svg\"\n"
|
|
||||||
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
|
|
||||||
" xmlns:fpga=\"http://qi-hw.com/fpga\"\n"
|
|
||||||
" id=\"root\">\n"
|
|
||||||
"<style type=\"text/css\"><![CDATA[text{font-size:6pt;text-anchor:end;}]]></style>\n"
|
|
||||||
"</svg>\n";
|
|
||||||
|
|
||||||
xmlDocPtr doc = 0;
|
|
||||||
xmlXPathContextPtr xpathCtx = 0;
|
|
||||||
xmlXPathObjectPtr xpathObj = 0;
|
|
||||||
xmlNodePtr new_node;
|
|
||||||
char str[128];
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
// can't get indent formatting to work - use 'xmllint --pretty 1 -'
|
|
||||||
// on the output for now
|
|
||||||
|
|
||||||
xmlInitParser();
|
|
||||||
doc = xmlParseDoc(empty_svg);
|
|
||||||
if (!doc) {
|
|
||||||
fprintf(stderr, "Internal error %i.\n", __LINE__);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
xpathCtx = xmlXPathNewContext(doc);
|
|
||||||
if (!xpathCtx) {
|
|
||||||
fprintf(stderr, "Cannot create XPath context.\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
xmlXPathRegisterNs(xpathCtx, BAD_CAST "svg", BAD_CAST "http://www.w3.org/2000/svg");
|
|
||||||
xpathObj = xmlXPathEvalExpression(BAD_CAST "//svg:*[@id='root']", xpathCtx);
|
|
||||||
if (!xpathObj) {
|
|
||||||
fprintf(stderr, "Cannot evaluate root expression.\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (!xpathObj->nodesetval) {
|
|
||||||
fprintf(stderr, "Cannot find root node.\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (xpathObj->nodesetval->nodeNr != 1) {
|
|
||||||
fprintf(stderr, "Found %i root nodes.\n", xpathObj->nodesetval->nodeNr);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < model->tile_y_range; i++) {
|
|
||||||
for (j = 0; j < model->tile_x_range; j++) {
|
|
||||||
strcpy(str, fpga_ttstr[model->tiles[i*model->tile_x_range+j].type]);
|
|
||||||
new_node = xmlNewChild(xpathObj->nodesetval->nodeTab[0], 0 /* xmlNsPtr */, BAD_CAST "text", BAD_CAST str);
|
|
||||||
xmlSetProp(new_node, BAD_CAST "x", xmlXPathCastNumberToString(130 + j*130));
|
|
||||||
xmlSetProp(new_node, BAD_CAST "y", xmlXPathCastNumberToString(40 + i*14));
|
|
||||||
xmlSetProp(new_node, BAD_CAST "fpga:tile_y", BAD_CAST xmlXPathCastNumberToString(i));
|
|
||||||
xmlSetProp(new_node, BAD_CAST "fpga:tile_x", BAD_CAST xmlXPathCastNumberToString(j));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xmlSetProp(xpathObj->nodesetval->nodeTab[0], BAD_CAST "width", BAD_CAST xmlXPathCastNumberToString(model->tile_x_range * 130 + 65));
|
|
||||||
xmlSetProp(xpathObj->nodesetval->nodeTab[0], BAD_CAST "height", BAD_CAST xmlXPathCastNumberToString(model->tile_y_range * 14 + 60));
|
|
||||||
|
|
||||||
xmlDocFormatDump(stdout, doc, 1 /* format */);
|
|
||||||
xmlXPathFreeObject(xpathObj);
|
|
||||||
xmlXPathFreeContext(xpathCtx);
|
|
||||||
xmlFreeDoc(doc);
|
|
||||||
xmlCleanupParser();
|
|
||||||
return;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
if (xpathObj) xmlXPathFreeObject(xpathObj);
|
|
||||||
if (xpathCtx) xmlXPathFreeContext(xpathCtx);
|
|
||||||
if (doc) xmlFreeDoc(doc);
|
|
||||||
xmlCleanupParser();
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_folders(struct fpga_model* model, const char* root_folder)
|
|
||||||
{
|
|
||||||
char path[1024];
|
|
||||||
|
|
||||||
sprintf(path, "%s/devices", root_folder);
|
|
||||||
if (mkdir(path, S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH)) {
|
|
||||||
fprintf(stderr, "Cannot create folder %s\n", path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// root/devices/IOB
|
|
||||||
// root/tile_type/1file_per_tile
|
|
||||||
}
|
}
|
141
model.h
Normal file
141
model.h
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
//
|
||||||
|
// Author: Wolfgang Spraul
|
||||||
|
//
|
||||||
|
// This is free and unencumbered software released into the public domain.
|
||||||
|
// For details see the UNLICENSE file at the root of the source tree.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
// columns
|
||||||
|
// 'L' = X+L logic block
|
||||||
|
// 'l' = X+L logic block without IO at top and bottom
|
||||||
|
// 'M' = X+M logic block
|
||||||
|
// 'm' = X+M logic block without IO at top and bottom
|
||||||
|
// 'B' = block ram
|
||||||
|
// 'D' = dsp (macc)
|
||||||
|
// 'R' = registers and center IO/logic column
|
||||||
|
//
|
||||||
|
// wiring on the left and right side is described with 16
|
||||||
|
// characters for each row - 'W' = wired, 'U' = unwired
|
||||||
|
// order is top-down
|
||||||
|
|
||||||
|
#define XC6SLX9_ROWS 4
|
||||||
|
#define XC6SLX9_COLUMNS "MLBMLDMRMlMLBML"
|
||||||
|
#define XC6SLX9_LEFT_WIRING \
|
||||||
|
/* row 3 */ "UWUWUWUW" "WWWWUUUU" \
|
||||||
|
/* row 2 */ "UUUUUUUU" "WWWWWWUU" \
|
||||||
|
/* row 1 */ "WWWUUWUU" "WUUWUUWU" \
|
||||||
|
/* row 0 */ "UWUUWUUW" "UUWWWWUU"
|
||||||
|
#define XC6SLX9_RIGHT_WIRING \
|
||||||
|
/* row 3 */ "UUWWUWUW" "WWWWUUUU" \
|
||||||
|
/* row 2 */ "UUUUUUUU" "WWWWWWUU" \
|
||||||
|
/* row 1 */ "WWWUUWUU" "WUUWUUWU" \
|
||||||
|
/* row 0 */ "UWUUWUUW" "UUWWWWUU"
|
||||||
|
|
||||||
|
struct fpga_model
|
||||||
|
{
|
||||||
|
int tile_x_range, tile_y_range;
|
||||||
|
struct fpga_tile* tiles;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum fpga_tile_type
|
||||||
|
{
|
||||||
|
NA,
|
||||||
|
ROUTING, ROUTING_BRK, ROUTING_VIA,
|
||||||
|
HCLK_ROUTING_XM, HCLK_ROUTING_XL, HCLK_LOGIC_XM, HCLK_LOGIC_XL,
|
||||||
|
LOGIC_XM, LOGIC_XL,
|
||||||
|
REGH_ROUTING_XM, REGH_ROUTING_XL, REGH_LOGIC_XM, REGH_LOGIC_XL,
|
||||||
|
BRAM_ROUTING, BRAM_ROUTING_BRK,
|
||||||
|
BRAM,
|
||||||
|
BRAM_ROUTING_TERM_T, BRAM_ROUTING_TERM_B, BRAM_ROUTING_VIA_TERM_T, BRAM_ROUTING_VIA_TERM_B,
|
||||||
|
BRAM_TERM_LT, BRAM_TERM_RT, BRAM_TERM_LB, BRAM_TERM_RB,
|
||||||
|
HCLK_BRAM_ROUTING, HCLK_BRAM_ROUTING_VIA, HCLK_BRAM,
|
||||||
|
REGH_BRAM_ROUTING, REGH_BRAM_ROUTING_VIA, REGH_BRAM_L, REGH_BRAM_R,
|
||||||
|
MACC,
|
||||||
|
HCLK_MACC_ROUTING, HCLK_MACC_ROUTING_VIA, HCLK_MACC,
|
||||||
|
REGH_MACC_ROUTING, REGH_MACC_ROUTING_VIA, REGH_MACC_L,
|
||||||
|
PLL_T, DCM_T, PLL_B, DCM_B, REG_T,
|
||||||
|
REG_TERM_T, REG_TERM_B, REG_B,
|
||||||
|
REGV_TERM_T, REGV_TERM_B,
|
||||||
|
HCLK_REGV,
|
||||||
|
REGV, REGV_BRK, REGV_T, REGV_B, REGV_MIDBUF_T, REGV_HCLKBUF_T, REGV_HCLKBUF_B, REGV_MIDBUF_B,
|
||||||
|
REGC_ROUTING, REGC_LOGIC, REGC_CMT,
|
||||||
|
CENTER, // unique center tile in the middle of the chip
|
||||||
|
IO_T, IO_B, IO_TERM_T, IO_TERM_B, IO_ROUTING, IO_LOGIC_TERM_T, IO_LOGIC_TERM_B,
|
||||||
|
IO_OUTER_T, IO_INNER_T, IO_OUTER_B, IO_INNER_B,
|
||||||
|
IO_BUFPLL_TERM_T, IO_LOGIC_REG_TERM_T, IO_BUFPLL_TERM_B, IO_LOGIC_REG_TERM_B,
|
||||||
|
LOGIC_ROUTING_TERM_B, LOGIC_NOIO_TERM_B,
|
||||||
|
MACC_ROUTING_TERM_T, MACC_ROUTING_TERM_B, MACC_VIA_TERM_T,
|
||||||
|
MACC_TERM_TL, MACC_TERM_TR, MACC_TERM_BL, MACC_TERM_BR,
|
||||||
|
ROUTING_VIA_REGC, ROUTING_VIA_IO, ROUTING_VIA_IO_DCM, ROUTING_VIA_CARRY,
|
||||||
|
CORNER_TERM_L, CORNER_TERM_R,
|
||||||
|
IO_TERM_L_UPPER_TOP, IO_TERM_L_UPPER_BOT, IO_TERM_L_LOWER_TOP, IO_TERM_L_LOWER_BOT,
|
||||||
|
IO_TERM_R_UPPER_TOP, IO_TERM_R_UPPER_BOT, IO_TERM_R_LOWER_TOP, IO_TERM_R_LOWER_BOT,
|
||||||
|
IO_TERM_L, IO_TERM_R,
|
||||||
|
HCLK_TERM_L, HCLK_TERM_R,
|
||||||
|
REGH_IO_TERM_L, REGH_IO_TERM_R,
|
||||||
|
REG_L, REG_R,
|
||||||
|
IO_PCI_L, IO_PCI_R, IO_RDY_L, IO_RDY_R,
|
||||||
|
IO_L, IO_R,
|
||||||
|
IO_PCI_CONN_L, IO_PCI_CONN_R,
|
||||||
|
CORNER_TERM_T, CORNER_TERM_B,
|
||||||
|
ROUTING_IO_L,
|
||||||
|
HCLK_ROUTING_IO_L, HCLK_ROUTING_IO_R, REGH_ROUTING_IO_L, REGH_ROUTING_IO_R,
|
||||||
|
ROUTING_IO_L_BRK, ROUTING_GCLK,
|
||||||
|
REGH_IO_L, REGH_IO_R, REGH_MCB, HCLK_MCB,
|
||||||
|
ROUTING_IO_VIA_L, ROUTING_IO_VIA_R, ROUTING_IO_PCI_CE_L, ROUTING_IO_PCI_CE_R,
|
||||||
|
CORNER_TL, CORNER_BL,
|
||||||
|
CORNER_TR_UPPER, CORNER_TR_LOWER, CORNER_BR_UPPER, CORNER_BR_LOWER,
|
||||||
|
HCLK_IO_TOP_UP_L, HCLK_IO_TOP_UP_R,
|
||||||
|
HCLK_IO_TOP_SPLIT_L, HCLK_IO_TOP_SPLIT_R,
|
||||||
|
HCLK_IO_TOP_DN_L, HCLK_IO_TOP_DN_R,
|
||||||
|
HCLK_IO_BOT_UP_L, HCLK_IO_BOT_UP_R,
|
||||||
|
HCLK_IO_BOT_SPLIT_L, HCLK_IO_BOT_SPLIT_R,
|
||||||
|
HCLK_IO_BOT_DN_L, HCLK_IO_BOT_DN_R,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fpga_tile
|
||||||
|
{
|
||||||
|
enum fpga_tile_type type;
|
||||||
|
|
||||||
|
// expect up to 64 devices per tile
|
||||||
|
int num_devices;
|
||||||
|
struct fpga_device* devices;
|
||||||
|
|
||||||
|
// expect up to 28k connections to other tiles per tile
|
||||||
|
// 3*16 bit per connection:
|
||||||
|
// - x coordinate of other tile (16bit)
|
||||||
|
// - y coordinate of other tile (16bit)
|
||||||
|
// - endpoint index in other tile (16bit)
|
||||||
|
int num_conns; // conns array is 3*num_conns 16-bit words
|
||||||
|
uint16_t* conns; // num_conns*3 16-bit words: 16(x)-16(y)-16(endpoint)
|
||||||
|
|
||||||
|
// expect up to 5k endpoints per tile
|
||||||
|
// 16-bit index into conns (not yet multiplied by 3)
|
||||||
|
int num_endpoints;
|
||||||
|
uint16_t* endpoints;
|
||||||
|
// endpoints0 are conceptual endpoints without outgoing wires.
|
||||||
|
// Imagine their indices added to the end of num_endpoints, so
|
||||||
|
// the first endpoint0 is at index num_endpoints, the second one
|
||||||
|
// at num_endpoints+1, and so on.
|
||||||
|
int num_endpoints0;
|
||||||
|
|
||||||
|
// expect up to 4k connection pairs per tile
|
||||||
|
// 32bit: 31 off: not in use on: used
|
||||||
|
// 30 off: unidirectional on: bidirectional
|
||||||
|
// 29:15 from, index into endpoints
|
||||||
|
// 14:0 to, index into endpoints
|
||||||
|
int num_connect_pairs;
|
||||||
|
uint32_t* connect_pairs;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fpga_model* fpga_build_model(int fpga_rows, const char* columns,
|
||||||
|
const char* left_wiring, const char* right_wiring);
|
||||||
|
|
||||||
|
const char* fpga_tiletype_str(enum fpga_tile_type type);
|
Loading…
Reference in New Issue
Block a user