348 lines
11 KiB
C
348 lines
11 KiB
C
//
|
|
// 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>
|
|
#define MACRO_STR(arg) #arg
|
|
|
|
#include "helper.h"
|
|
|
|
//
|
|
// columns
|
|
// 'L' = X+L logic block
|
|
// 'M' = X+M logic block
|
|
// 'B' = block ram
|
|
// 'D' = dsp (macc)
|
|
// 'R' = registers and center IO/logic column
|
|
//
|
|
// 'n' = noio - can follow L or M to designate a logic
|
|
// column without IO at top or bottom
|
|
// 'g' = gclk - can follow LlMmBD to designate exactly one
|
|
// place on the left and right side of the chip where
|
|
// the global clock is separated into left and right
|
|
// half (on each side of the chip, for a total of 4
|
|
// vertical clock separations).
|
|
//
|
|
// wiring on the left and right side is described with 16
|
|
// characters for each row, order is top-down
|
|
// 'W' = wired
|
|
// 'U' = unwired
|
|
//
|
|
|
|
#define XC6SLX9_ROWS 4
|
|
#define XC6SLX9_COLUMNS "M L Bg M L D M R M Ln M L Bg M L"
|
|
#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 cfg_rows;
|
|
char cfg_columns[512];
|
|
char cfg_left_wiring[1024], cfg_right_wiring[1024];
|
|
|
|
int x_width, y_height;
|
|
int center_x;
|
|
int center_y;
|
|
// Left and right gclk separators will be located on
|
|
// the device column (+1 or +2) of the logic or dsp/macc
|
|
// column as indicated in the chip's cfg_columns with a 'g'.
|
|
int left_gclk_sep_x, right_gclk_sep_x;
|
|
|
|
struct fpga_tile* tiles;
|
|
struct hashed_strarray str;
|
|
|
|
// tmp_str will be allocated to hold max(x_width, y_height)
|
|
// pointers, useful for string seeding when running wires.
|
|
const char** tmp_str;
|
|
};
|
|
|
|
enum fpga_tile_type
|
|
{
|
|
NA = 0,
|
|
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,
|
|
};
|
|
|
|
// Some macros to make the code more readable
|
|
#define LEFT_OUTER_COL 0
|
|
#define LEFT_INNER_COL 1
|
|
#define LEFT_IO_ROUTING 2
|
|
#define LEFT_IO_DEVS 3
|
|
#define LEFT_MCB_COL 4
|
|
|
|
#define TOP_IO_TILES 2
|
|
#define TOP_OUTER_ROW 0
|
|
#define TOP_INNER_ROW 1
|
|
#define HALF_ROW 8
|
|
#define HCLK_POS 8 // hclk pos in row
|
|
#define LAST_POS_IN_ROW 16 // including hclk at 8
|
|
#define ROW_SIZE (HALF_ROW+1+HALF_ROW)
|
|
|
|
// Some offsets that are being deducted from their origin
|
|
#define BOT_IO_TILES 2
|
|
#define BOT_OUTER_ROW 1
|
|
#define BOT_INNER_ROW 2
|
|
#define RIGHT_OUTER_O 1
|
|
#define RIGHT_INNER_O 2
|
|
#define RIGHT_MCB_O 3
|
|
#define RIGHT_IO_DEVS_O 4
|
|
#define RIGHT_IO_ROUTING_O 5
|
|
#define CENTER_CMTPLL_O 1
|
|
#define CENTER_LOGIC_O 2
|
|
#define CENTER_ROUTING_O 3
|
|
|
|
#define YX_TILE(model, y, x) (&(model)->tiles[(y)*model->x_width+(x)])
|
|
|
|
// tile flags
|
|
|
|
#define TF_FABRIC_ROUTING_COL 0x00000001 // only set in y==0, not for left and right IO routing or center
|
|
#define TF_FABRIC_LOGIC_COL 0x00000002 // only set in y==0
|
|
#define TF_FABRIC_BRAM_MACC_ROUTING_COL 0x00000004 // only set in y==0
|
|
#define TF_FABRIC_BRAM_COL 0x00000008 // only set in y==0
|
|
#define TF_FABRIC_MACC_COL 0x00000010 // only set in y==0
|
|
// TF_ROUTING_NO_IO is only set in y==0 - automatically for BRAM and MACC
|
|
// routing, and manually for logic routing with the noio flag in the column
|
|
// configuration string
|
|
#define TF_ROUTING_NO_IO 0x00000020
|
|
#define TF_BRAM_DEV 0x00000040
|
|
#define TF_MACC_DEV 0x00000080
|
|
#define TF_LOGIC_XL_DEV 0x00000100
|
|
#define TF_LOGIC_XM_DEV 0x00000200
|
|
#define TF_IOLOGIC_DELAY_DEV 0x00000400
|
|
#define TF_DCM_DEV 0x00000800
|
|
#define TF_PLL_DEV 0x00001000
|
|
// TF_WIRED is only set for x==0 on the left side or x==x_width-1
|
|
// on the right side.
|
|
#define TF_WIRED 0x00002000
|
|
|
|
#define Y_INNER_TOP 0x0001
|
|
#define Y_INNER_BOTTOM 0x0002
|
|
#define Y_CHIP_HORIZ_REGS 0x0004
|
|
#define Y_ROW_HORIZ_AXSYMM 0x0008
|
|
#define Y_BOTTOM_OF_ROW 0x0010
|
|
#define Y_LEFT_WIRED 0x0020
|
|
#define Y_RIGHT_WIRED 0x0040
|
|
|
|
// multiple checks are combined with OR logic
|
|
int is_aty(int check, struct fpga_model* model, int y);
|
|
|
|
#define X_OUTER_LEFT 0x00000001
|
|
#define X_INNER_LEFT 0x00000002
|
|
#define X_INNER_RIGHT 0x00000004
|
|
#define X_OUTER_RIGHT 0x00000008
|
|
#define X_ROUTING_COL 0x00000010 // includes routing col in left and right IO and center
|
|
#define X_ROUTING_TO_BRAM_COL 0x00000020
|
|
#define X_ROUTING_TO_MACC_COL 0x00000040
|
|
#define X_ROUTING_NO_IO 0x00000080
|
|
#define X_LOGIC_COL 0x00000100 // includes the center logic col
|
|
// todo: maybe X_FABRIC_ROUTING_COL could be logic+bram+macc?
|
|
#define X_FABRIC_ROUTING_COL 0x00000200 // logic+BRAM+MACC
|
|
#define X_FABRIC_LOGIC_ROUTING_COL 0x00000400 // logic only
|
|
#define X_FABRIC_LOGIC_COL 0x00000800
|
|
#define X_FABRIC_BRAM_ROUTING_COL 0x00001000 // BRAM only
|
|
#define X_FABRIC_MACC_ROUTING_COL 0x00002000 // MACC only
|
|
#define X_FABRIC_BRAM_MACC_ROUTING_COL 0x00004000 // second routing col for BRAM/MACC
|
|
#define X_FABRIC_BRAM_COL 0x00008000
|
|
#define X_FABRIC_MACC_COL 0x00010000
|
|
#define X_CENTER_ROUTING_COL 0x00020000
|
|
#define X_CENTER_LOGIC_COL 0x00040000
|
|
#define X_CENTER_CMTPLL_COL 0x00080000
|
|
#define X_CENTER_REGS_COL 0x00100000
|
|
#define X_LEFT_IO_ROUTING_COL 0x00200000
|
|
#define X_LEFT_IO_DEVS_COL 0x00400000
|
|
#define X_RIGHT_IO_ROUTING_COL 0x00800000
|
|
#define X_RIGHT_IO_DEVS_COL 0x01000000
|
|
#define X_LEFT_SIDE 0x02000000 // true for anything left of the center (not including center)
|
|
#define X_LEFT_MCB 0x04000000
|
|
#define X_RIGHT_MCB 0x08000000
|
|
|
|
#define IS_TOP_ROW(row, model) ((row) == (model)->cfg_rows-1)
|
|
#define IS_BOTTOM_ROW(row, model) ((row) == 0)
|
|
#define IS_CENTER_Y(row, model) ((row) == (model)->center_y)
|
|
#define BOT_TERM(model) ((model)->y_height-BOT_INNER_ROW)
|
|
#define TOP_TERM(model) (TOP_INNER_ROW)
|
|
|
|
// multiple checks are combined with OR logic
|
|
int is_atx(int check, struct fpga_model* model, int x);
|
|
|
|
// True for all tiles that are in the regular 0..15 row tiles of a routing col
|
|
#define YX_ROUTING_TILE 0x0001
|
|
|
|
int is_atyx(int check, struct fpga_model* model, int y, int x);
|
|
|
|
// if not in row, both return values (if given) will
|
|
// be set to -1. the row_pos is 0..7 for the upper half,
|
|
// 8 for the hclk, and 9..16 for the lower half.
|
|
void is_in_row(const struct fpga_model* model, int y,
|
|
int* row_num, int* row_pos);
|
|
|
|
// row_num() and row_pos() return -1 if y is outside of a row
|
|
int row_num(int y, struct fpga_model* model);
|
|
int row_pos(int y, struct fpga_model* model);
|
|
|
|
enum fpgadev_type
|
|
{
|
|
DEV_LOGIC_M,
|
|
DEV_LOGIC_L,
|
|
DEV_LOGIC_X,
|
|
DEV_TIEOFF,
|
|
DEV_MACC,
|
|
DEV_IOBM,
|
|
DEV_IOBS,
|
|
DEV_ILOGIC,
|
|
DEV_OLOGIC,
|
|
DEV_IODELAY,
|
|
DEV_BRAM16,
|
|
DEV_BRAM8,
|
|
DEV_BUFH,
|
|
DEV_BUFIO,
|
|
DEV_BUFIO_FB,
|
|
DEV_BUFPLL,
|
|
DEV_BUFPLL_MCB,
|
|
DEV_BUFGMUX,
|
|
DEV_BSCAN,
|
|
DEV_DCM,
|
|
DEV_PLL_ADV,
|
|
DEV_ICAP,
|
|
DEV_POST_CRC_INTERNAL,
|
|
DEV_STARTUP,
|
|
DEV_SLAVE_SPI,
|
|
DEV_SUSPEND_SYNC,
|
|
DEV_OCT_CALIBRATE,
|
|
DEV_SPI_ACCESS
|
|
};
|
|
|
|
struct fpgadev_logic_x
|
|
{
|
|
int a;
|
|
};
|
|
|
|
struct fpgadev_logic_l
|
|
{
|
|
int b;
|
|
};
|
|
|
|
struct fpgadev_logic_m
|
|
{
|
|
int c;
|
|
};
|
|
|
|
struct fpga_device
|
|
{
|
|
enum fpgadev_type type;
|
|
union {
|
|
struct fpgadev_logic_m log_m;
|
|
struct fpgadev_logic_l log_l;
|
|
struct fpgadev_logic_x log_x;
|
|
};
|
|
};
|
|
|
|
#define SWITCH_ON 0x80000000
|
|
#define SWITCH_BIDIRECTIONAL 0x40000000
|
|
#define SWITCH_MAX_CONNPT_O 0x7FFF // 15 bits
|
|
|
|
struct fpga_tile
|
|
{
|
|
enum fpga_tile_type type;
|
|
int flags;
|
|
|
|
// expect up to 64 devices per tile
|
|
int num_devices;
|
|
struct fpga_device devices[32];
|
|
|
|
// expect up to 5k connection point names per tile
|
|
// 2*16 bit per entry
|
|
// - index into conn_point_dests (not multiplied by 3) (16bit)
|
|
// - hashed string array index (16 bit)
|
|
int num_conn_point_names; // conn_point_names is 2*num_conn_point_names 16-bit words
|
|
uint16_t* conn_point_names; // num_conn_point_names*2 16-bit-words: 16(conn)-16(str)
|
|
|
|
// expect up to 28k connection point destinations to other tiles per tile
|
|
// 3*16 bit per destination:
|
|
// - x coordinate of other tile (16bit)
|
|
// - y coordinate of other tile (16bit)
|
|
// - hashed string array index for conn_point_names name in other tile (16bit)
|
|
int num_conn_point_dests; // conn_point_dests array is 3*num_conn_point_dests 16-bit words
|
|
uint16_t* conn_point_dests; // num_conn_point_dests*3 16-bit words: 16(x)-16(y)-16(conn_name)
|
|
|
|
// expect up to 4k switches per tile
|
|
// 32bit: 31 off: no connection on: connected
|
|
// 30 off: unidirectional on: bidirectional
|
|
// 29:15 from, index into conn_point_names
|
|
// 14:0 to, index into conn_point_names
|
|
int num_switches;
|
|
uint32_t* switches;
|
|
};
|
|
|
|
int fpga_build_model(struct fpga_model* model,
|
|
int fpga_rows, const char* columns,
|
|
const char* left_wiring, const char* right_wiring);
|
|
void fpga_free_model(struct fpga_model* model);
|
|
|
|
const char* fpga_tiletype_str(enum fpga_tile_type type);
|