This directory contains all reverse-engineered device and architecture parameter files. Bitfiltrator automatically adds new device and architecture files here when calling create_device_summary.py and create_arch_summary.py.
The parts_all.json and parts_webpack.json files are generated by generate_fpga_part_files.py. The former contains all US/US+ FPGA part numbers known by your Vivado installation, while the latter lists only WebPack-enabled part numbers.
Each FPGA part number is categorized by its architecture and device name. The architecture names are obtained from Vivado, not marketing materials, as devices’ categorization differs between both sources. The following Tcl command is used to extract the full architecture name.
get_property ARCHITECTURE_FULL_NAME ${part}
Bitfiltrator generates a device summary file for every device it analyzes. A short extract of the summary for the xcku025
device is shown below. We expand on the definition of fields that are not self-explanatory.
{
"device": "xcku025",
"license": "Webpack",
"num_brams": 360,
"num_dsps": 1152,
"num_luts": 145440,
"num_regs": 290880,
"num_slices": 18180,
"num_slrs": 1,
"part": "xcku025-ffva1156-1-c",
"slrs": {
"SLR0": {
// The order in which SLRs are configured in the bitstream. Configuration frames for multi-SLR devices are not
// forcefully found in the bitstream in the "expected" SLR0-SLR1-SLR2-...-SLRx order.
"config_order_idx": 0,
"idcode": "0x03824093",
// Min X-value of VISIBLE clock regions (X<x>Y<y>) in Vivado.
"min_clock_region_col_idx": 0,
// Max X-value of VISIBLE clock regions (X<x>Y<y>) in Vivado.
"max_clock_region_col_idx": 3,
// Min Y-value of VISIBLE clock regions (X<x>Y<y>) in Vivado.
"min_clock_region_row_idx": 0,
// Max Y-value of VISIBLE clock regions (X<x>Y<y>) in Vivado.
"max_clock_region_row_idx": 2,
// Min Y-value of clock regions (X<x>Y<y>) in the BITSTREAM.
"min_far_row_idx": 0,
// Max Y-value of clock regions (X<x>Y<y>) in the BITSTREAM. This value may be larger than the number of "visible"
// clock region rows in Vivado! There are therefore some "hidden" rows that are only visible in the bitstream itself.
// Devices that have hidden rows are probably restricted versions of larger devices.
"max_far_row_idx": 4,
"rowMajors": {
"0": {
// Map from X-value in RAMB18_X<x>Y* to major column number (block type BRAM_CONTENT).
"bram_content_colMajors": {"0": 0,"1": 1,"2": 2, ...},
// Map from X-value in RAMB18_X<x>Y* to major column number (block type BRAM_CONTENT).
"bram_content_parity_colMajors": {"0": 0,"1": 1,"2": 2, ...},
// Map from X-value in RAMB18_X<x>Y* to major column number (block type CLB_IO_CLK). Notice that the output
// registers of the BRAMs are stored in CLB_IO_CLK frames, whereas the BRAM content and parity bits are stored
// in BRAM_CONTENT frames.
"bram_reg_colMajors": {"0": 7,"1": 19,"2": 43, ...},
// Map from X-value in SLICE_X<x>Y* to major column number (block type CLB_IO_CLK). A dictionary is used as
// some X-values do not exist (for example, when a column of LAGUNA cells are used to bridge connections between
// two SLRs as the LAGUNA cells take up the space that would have been uesd by CLBs).
"clb_colMajors": {"0": 3,"1": 4,"2": 6, ...},
// Determines what type of CLB tile is located at the X-value in SLICE_X<x>Y*.
"clb_tileTypes": {"0": "CLEL_R","1": "CLE_M","2": "CLEL_R", ...},
// Map from X-value in DSP48E2_X<x>Y* to major column number (block type CLB_IO_CLK).
"dsp_colMajors": {"0": 12,"1": 24,"2": 36, ...},
// Max Y-value in DSP48E2_X*Y<y> in this major row. This field is needed as DSP resources do not always span
// the full height of a clock region (devices with HBM memory replace the bottom 6 DSPs in a column with an
// AXI interface for the HBM memory). This max Y-value is therefore needed in order to determine which major
// row the given DSP48E2_X*Y<y> is located in.
"max_dsp_y_ofst": 23,
"min_dsp_y_ofst": 0,
// Number of minors in BRAM_CONTENT major columns 0, 1, 2, ...
"num_minors_per_bram_content_colMajor": [128,128,128,128,128,128,128,128, ...],
// Number of minors in CLB_IO_CLK major columns 0, 1, 2, ...
"num_minors_per_std_colMajor": [10,16,58,12,12,58,12,4,58,12,12,58,4,12, ...]
},
"1": {
...
}
}
}
},
// This key contains pairs of BEL properties in Vivado (TILE_TYPE, SITE_TYPE).
// For example, the values here tell us that sites of type SLICEM can be found in tiles of type CLE_M and CLEM_M_R.
// In theory every tile that has a different name as its TILE_TYPE property could have a different encoding in the
// bitstream. Bitfiltrator therefore extracts architecture parameters for SLICEL/SLICEM resources for every TILE_TYPE
// that contains them.
"tileType_siteType_pairs": [
...
["BRAM","RAMB181"],
["BRAM","RAMBFIFO18"],
["BRAM","RAMBFIFO36"],
...
["CLE_M","SLICEM"],
["CLE_M_R","SLICEM"],
["CLEL_L","SLICEL"],
["CLEL_R","SLICEL"],
["DSP","DSP48E2"],
...
]
}
Bitfiltrator generates an architecture summary file for every architecture it analyzes. An architecture summary can be extracted from any device that has the given architecture. A short extract of the summary for the ULTRASCALE_PLUS
architecture is shown below. We expand on the definition of fields that are not self-explanatory.
{
// TILE_TYPE property in Vivado.
"BRAM": {
// Contains minors and frame offsets for BRAM content bits (block type BRAM_CONTENT).
// This data is extracted for 18K BRAMs, so there are 16386 entries in the lists below.
"BramMemLoc": {
"Y_ofst": {
"0": {
// INIT[0], INIT[1], INIT[2], ..., INIT[16385]
"frame_ofst": [0,12,24,36,60,72,84,96,6,18, ...],
"minor": [0,0,0,0,0,0,0,0,0,0, ...]
},
"1": {
// INIT[0], INIT[1], INIT[2], ..., INIT[16385]
"frame_ofst": [132,144,156,168,192,204,216,228,138,150, ...],
"minor": [0,0,0,0,0,0,0,0,0,0, ...]
},
...
}
},
// Contains minors and frame offsets for BRAM parity bits (block type BRAM_CONTENT).
// This data is extracted for 18K BRAMs, so there are 2048 entries in the list below (16K content + 2K parity = 18K BRAM).
"BramMemParityLoc": {
"Y_ofst": {
"0": {
// INIT[0], INIT[1], INIT[2], ..., INIT[2047]
"frame_ofst": [48,54,51,57,50,56,53,59,48,54, ...],
"minor": [0,0,0,0,0,0,0,0,1,1, ...]
},
"1": {
// INIT[0], INIT[1], INIT[2], ..., INIT[2047]
"frame_ofst": [180,186,183,189,182,188,185,191,180,186, ...],
"minor": [0,0,0,0,0,0,0,0,1,1, ...]
},
...
}
}
},
// TILE_TYPE property in Vivado.
"CLEL_L": {
// Contains minors and frame offsets for LUT content bits (block type CLB_IO_CLK).
// This data is extracted for 6-LUTs, so there are 64 entries in the lists below.
"LutLoc": {
"Y_ofst": {
"0": {
"frame_ofst": {
// INIT[0], INIT[1], INIT[2], ..., INIT[63]
"A6LUT": [15,15,15,15,14,14,14,14,13,13, ...],
"B6LUT": [15,15,15,15,14,14,14,14,13,13, ...],
"C6LUT": [15,15,15,15,14,14,14,14,13,13, ...],
"D6LUT": [31,31,31,31,30,30,30,30,29,29, ...],
"E6LUT": [31,31,31,31,30,30,30,30,29,29, ...],
"F6LUT": [47,47,47,47,46,46,46,46,45,45, ...],
"G6LUT": [47,47,47,47,46,46,46,46,45,45, ...],
"H6LUT": [47,47,47,47,46,46,46,46,45,45, ...]
},
"minor": {
// INIT[0], INIT[1], INIT[2], ..., INIT[63]
"A6LUT": [11,10,9,8,11,10,9,8,11,10, ...],
"B6LUT": [7,6,5,4,7,6,5,4,7,6, ...],
"C6LUT": [3,2,1,0,3,2,1,0,3,2, ...],
"D6LUT": [3,2,1,0,3,2,1,0,3,2, ...],
"E6LUT": [7,6,5,4,7,6,5,4,7,6, ...],
"F6LUT": [3,2,1,0,3,2,1,0,3,2, ...],
"G6LUT": [7,6,5,4,7,6,5,4,7,6, ...],
"H6LUT": [11,10,9,8,11,10,9,8,11,10, ...]
}
},
"1": {
"frame_ofst": {
// INIT[0], INIT[1], INIT[2], ..., INIT[63]
"A6LUT": [63,63,63,63,62,62,62,62,61,61, ...],
"B6LUT": [63,63,63,63,62,62,62,62,61,61, ...],
"C6LUT": [63,63,63,63,62,62,62,62,61,61, ...],
"D6LUT": [79,79,79,79,78,78,78,78,77,77, ...],
"E6LUT": [79,79,79,79,78,78,78,78,77,77, ...],
"F6LUT": [95,95,95,95,94,94,94,94,93,93, ...],
"G6LUT": [95,95,95,95,94,94,94,94,93,93, ...],
"H6LUT": [95,95,95,95,94,94,94,94,93,93, ...]
},
"minor": {
// INIT[0], INIT[1], INIT[2], ..., INIT[63]
"A6LUT": [11,10,9,8,11,10,9,8,11,10, ...],
"B6LUT": [7,6,5,4,7,6,5,4,7,6, ...],
"C6LUT": [3,2,1,0,3,2,1,0,3,2, ...],
"D6LUT": [3,2,1,0,3,2,1,0,3,2, ...],
"E6LUT": [7,6,5,4,7,6,5,4,7,6, ...],
"F6LUT": [3,2,1,0,3,2,1,0,3,2, ...],
"G6LUT": [7,6,5,4,7,6,5,4,7,6, ...],
"H6LUT": [11,10,9,8,11,10,9,8,11,10, ...]
}
},
...
},
},
// Contains minors and frame offsets for Flip-Flop content bits (block type CLB_IO_CLK).
// There are 8 Flip-Flops per CLB, named [A-H]FF2? and each has a single INIT bit since they are 1-bit Flip-Flops.
"RegLoc": {
"Y_ofst": {
"0": {
"frame_ofst": {
// INIT
"AFF": 2,
"AFF2": 14,
"BFF": 4,
"BFF2": 16,
"CFF": 8,
"CFF2": 20,
"DFF": 10,
"DFF2": 22,
"EFF": 26,
"EFF2": 38,
"FFF": 28,
"FFF2": 40,
"GFF": 32,
"GFF2": 44,
"HFF": 34,
"HFF2": 46
},
"minor": {
// INIT
"AFF": 12,
"AFF2": 12,
"BFF": 12,
"BFF2": 12,
"CFF": 12,
"CFF2": 12,
"DFF": 12,
"DFF2": 12,
"EFF": 12,
"EFF2": 12,
"FFF": 12,
"FFF2": 12,
"GFF": 12,
"GFF2": 12,
"HFF": 12,
"HFF2": 12
}
},
"1": {
"frame_ofst": {
// INIT
"AFF": 50,
"AFF2": 62,
"BFF": 52,
"BFF2": 64,
"CFF": 56,
"CFF2": 68,
"DFF": 58,
"DFF2": 70,
"EFF": 74,
"EFF2": 86,
"FFF": 76,
"FFF2": 88,
"GFF": 80,
"GFF2": 92,
"HFF": 82,
"HFF2": 94
},
"minor": {
// INIT
"AFF": 12,
"AFF2": 12,
"BFF": 12,
"BFF2": 12,
"CFF": 12,
"CFF2": 12,
"DFF": 12,
"DFF2": 12,
"EFF": 12,
"EFF2": 12,
"FFF": 12,
"FFF2": 12,
"GFF": 12,
"GFF2": 12,
"HFF": 12,
"HFF2": 12
}
},
...
}
}
},
"CLEL_R": {
"LutLoc": {
"Y_ofst": {
"0": {
"frame_ofst": {
...
},
"minor_ofst": {
...
}
}
}
}
},
...
}