The FPGA model of fpgatools and sw_bitpos

The FPGA model as defined in FpgaTools [1] with additional comments:

struct fpga_model
        /* return code */
        int rc; // if rc != 0, all function calls will immediately return

        const struct xc_die *die;
        /* array of the all the pins of the package */
        const struct xc6_pkg_info *pkg;

        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;

        // x_major is an array of column indices for each x coordinate,
        // starting with column 1 for the left side, and incrementing
        // through the configuration columns. This corresponds to the
        // 'majors' in the bitstream.
        int x_major[512];

        /* bit position of the routing swtich in the switch matrix */
        struct xc6_routing_bitpos* sw_bitpos;
        int num_bitpos;

        /* array of all the tiles of the FPGA: ROUTING, LOGIC, ... */
        struct fpga_tile* tiles;
        /* hashed string array, e.g., connection point names */
        struct hashed_strarray str;

        int nets_array_size;
        int highest_used_net; // 1-based net_idx_t
        struct fpga_net* nets;

        // tmp_str will be allocated to hold max(x_width, y_height)
        // pointers, useful for string seeding when running wires.
        const char** tmp_str;


The sw_bitpos array contains all the possible switiching combinations in the FPGA chip, but not all of them are available in each switch matrix. See fpga_tilen->switches for the switches that are actually available in the switch matrix of each tile. Never-the-less, the routing configuration in the bitstream gives the possibility to configure all the bitpos at every tile, even if many of them are not wired in the die.

Useful little functions:

  • YX_TILE(fpga_model, y, x) to get the pointer to a tile from its coordinates.
  • strarray_lookup(&model.str, str16_id) to get the string from the str16 hash key.

I wrote a little C program that generate C source code in order to create a statically initialized sw_bitpos array. Another C program includes this array, and analyses bitstreams for enabled switches.

A simple AND operation would produce the following configuration according to bit2fp from fpgatools:

#D bit_frames.c:1698 y68 x31 (r0 ma13 v64_13 mi10) from LOGICOUT15 to EL1B0 bidir 0 two_bits_o 64 two_bits_val 2 one_bit_o 71
#D bit_frames.c:1698 y68 x31 (r0 ma13 v64_13 mi16) from NL1E3 to LOGICIN_B39 bidir 0 two_bits_o 0 two_bits_val 1 one_bit_o 6
#D bit_frames.c:1698 y68 x31 (r0 ma13 v64_13 mi16) from NR1E0 to LOGICIN_B42 bidir 0 two_bits_o 96 two_bits_val 1 one_bit_o 104
#D bit_frames.c:1698 y69 x31 (r0 ma13 v64_14 mi8) from LOGICOUT7 to NL1B3 bidir 0 two_bits_o 110 two_bits_val 1 one_bit_o 104
#D bit_frames.c:1698 y69 x31 (r0 ma13 v64_14 mi10) from LOGICOUT0 to NR1B0 bidir 0 two_bits_o 110 two_bits_val 1 one_bit_o 108
#D bit_frames.c:1698 y70 x31 (r0 ma13 v64_15 mi14) from SW2E0 to LOGICIN_B15 bidir 0 two_bits_o 110 two_bits_val 0 one_bit_o 100
#D bit_frames.c:1698 y68 x33 (r0 ma14 v64_13 mi10) from EL1E0 to SL1B0 bidir 0 two_bits_o 112 two_bits_val 2 one_bit_o 120
#D bit_frames.c:1698 y69 x33 (r0 ma14 v64_14 mi4) from SL1E0 to SW2B0 bidir 0 two_bits_o 126 two_bits_val 1 one_bit_o 117
fpga_floorplan_format 1
dev y72 x31 IOB 0 istd LVCMOS25
dev y72 x31 IOB 0 bypass_mux I
dev y72 x31 IOB 0 imux I
dev y72 x31 IOB 1 istd LVCMOS25
dev y72 x31 IOB 1 bypass_mux I
dev y72 x31 IOB 1 imux I
dev y72 x31 IOB 2 ostd LVCMOS33
dev y72 x31 IOB 2 strength 12
dev y72 x31 IOB 2 slew SLOW
dev y72 x31 IOB 2 O_used
dev y72 x31 IOB 2 suspend 3STATE
dev y68 x32 LOGIC 0 B6_lut_str A3+A6
dev y68 x32 LOGIC 0 B_used
net 1 sw y68 x31 LOGICOUT15 -> EL1B0
net 2 sw y68 x31 NL1E3 -> LOGICIN_B39
net 3 sw y68 x31 NR1E0 -> LOGICIN_B42
net 4 sw y69 x31 LOGICOUT7 -> NL1B3
net 5 sw y69 x31 LOGICOUT0 -> NR1B0
net 6 sw y70 x31 SW2E0 -> LOGICIN_B15
net 11 sw y70 x32 D1_OLOGIC_SITE_S -> OQ_OLOGIC_SITE_S
net 12 sw y70 x32 OQ_OLOGIC_SITE_S -> BIOI_OUTER_O1
net 13 sw y68 x33 EL1E0 -> SL1B0
net 14 sw y69 x33 SL1E0 -> SW2B0
header_str_a simple_and.ncd;UserID=0xFFFFFFFF
header_str_b 6slx9tqg144
header_str_c 2014/04/24
header_str_d 16:34:49

The first 'comment' lines are debug information about the bit position from sw_bitpos. My statically initialized program can do the same:

In the tile y64 x31 (switch matrix):
bitpos 1228 is set (LOGICOUT15 -> EL1B0)
bitpos 1816 is set (NL1E3 -> LOGICIN_B39)
bitpos 2586 is set (NR1E0 -> LOGICIN_B42)

The sw_bitpos array is 3381 row long. Each row being defined as follows from fpgatools:

struct xc6_routing_bitpos
        // from and to are enum extra_wires values from model.h
        int from;
        int to;
        int bidir;

        // minors 0-19 are minor pairs, minor will be set
        // to the even beginning of the pair, two_bits_o and
        // one_bit_o are within 2*64 bits of the two minors.
        // Even bit offsets are from the first minor, odd bit
        // offsets from the second minor.
        // minor 20 is a regular single 64-bit minor.

        int minor; // 0,2,4,..18 for pairs, 20 for single-minor
        int two_bits_o; // 0-126 for pairs (even only), 0-62 for single-minor
        int two_bits_val; // 0-3
        int one_bit_o; // 1-6 positions up or down from two-bit pos

To save memory, the structure could be defined:

struct xc6_routing_bitpos
        uint16_t from;
        uint16_t to;
        uint8_t bidir;
        uint8_t minor;
        uint8_t two_bits_o;
        uint8_t two_bits_val;
        uint8_t one_bit_o;

The total structure is 9 bytes, therefore the whole array is 3381 * 9 = 30429Bytes (~30KB) of Flash. Allowing my little program to run on the microcontroller for reading and patching switch matrix in bitstreams on the fly!