├── reloc.pdf ├── zedboard_example ├── .gitignore ├── zedboard_example.srcs │ ├── sources_1 │ │ ├── bd │ │ │ └── BD_PR_3 │ │ │ │ ├── hdl │ │ │ │ ├── BD_PR_3.hwdef │ │ │ │ └── BD_PR_3_wrapper.vhd │ │ │ │ ├── BD_PR_3_ooc.xdc │ │ │ │ ├── ui │ │ │ │ └── bd_442d2033.ui │ │ │ │ └── BD_PR_3.bxml │ │ └── imports │ │ │ └── sources_1 │ │ │ ├── new │ │ │ ├── pr_axis_loopback.vhd │ │ │ ├── axis_lut_buffer.vhd │ │ │ ├── axis_buffer.vhd │ │ │ ├── pr_axis.vhd │ │ │ └── pr_axis_buffer.vhd │ │ │ └── imports │ │ │ └── new │ │ │ └── wrapper.vhd │ └── wrapper │ │ └── imports │ │ └── wrapper │ │ ├── new │ │ ├── pr_2.xdc │ │ ├── pr_0.xdc │ │ └── pr_1.xdc │ │ └── imports │ │ └── new │ │ └── isol.xdc ├── zedboard_example.hw │ └── zedboard_example.lpr └── zedboard_example.xpr ├── relocater ├── Makefile ├── relocater.h ├── bitstreams.h └── relocater.c ├── LICENSE ├── README.md ├── pr_script.tcl └── procs.tcl /reloc.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bgottschall/reloc/HEAD/reloc.pdf -------------------------------------------------------------------------------- /zedboard_example/.gitignore: -------------------------------------------------------------------------------- 1 | hd_visual 2 | *.cache 3 | *.runs 4 | *.sim 5 | *.ip_user_files 6 | .Xil 7 | *.log 8 | *.jou 9 | *.str 10 | *.zip 11 | *.debug 12 | -------------------------------------------------------------------------------- /zedboard_example/zedboard_example.srcs/sources_1/bd/BD_PR_3/hdl/BD_PR_3.hwdef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bgottschall/reloc/HEAD/zedboard_example/zedboard_example.srcs/sources_1/bd/BD_PR_3/hdl/BD_PR_3.hwdef -------------------------------------------------------------------------------- /zedboard_example/zedboard_example.hw/zedboard_example.lpr: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /relocater/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | 3 | help: 4 | @echo "Compile relocater" 5 | @echo "" 6 | @echo "Targets:" 7 | @echo " all - build everything" 8 | @echo " clean - clean workspace" 9 | @echo "" 10 | @echo "Options:" 11 | @echo " CROSS_COMPILE - cross compiler prefix" 12 | 13 | all: 14 | $(CROSS_COMPILE)gcc relocater.c -o relocater 15 | 16 | clean: 17 | @rm -Rf relocater 18 | -------------------------------------------------------------------------------- /zedboard_example/zedboard_example.srcs/wrapper/imports/wrapper/new/pr_2.xdc: -------------------------------------------------------------------------------- 1 | create_pblock pr_2 2 | add_cells_to_pblock [get_pblocks pr_2] [get_cells -quiet [list pr_2]] 3 | resize_pblock [get_pblocks pr_2] -add {SLICE_X90Y0:SLICE_X113Y49} 4 | resize_pblock [get_pblocks pr_2] -add {DSP48_X3Y0:DSP48_X4Y19} 5 | resize_pblock [get_pblocks pr_2] -add {PMVBRAM_X4Y0:PMVBRAM_X5Y0} 6 | resize_pblock [get_pblocks pr_2] -add {RAMB18_X4Y0:RAMB18_X5Y19} 7 | resize_pblock [get_pblocks pr_2] -add {RAMB36_X4Y0:RAMB36_X5Y9} 8 | set_property SNAPPING_MODE ON [get_pblocks pr_2] 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /zedboard_example/zedboard_example.srcs/wrapper/imports/wrapper/new/pr_0.xdc: -------------------------------------------------------------------------------- 1 | create_pblock pr_0 2 | add_cells_to_pblock [get_pblocks pr_0] [get_cells -quiet [list pr_0]] 3 | resize_pblock [get_pblocks pr_0] -add {SLICE_X90Y100:SLICE_X113Y149} 4 | resize_pblock [get_pblocks pr_0] -add {DSP48_X3Y40:DSP48_X4Y59} 5 | resize_pblock [get_pblocks pr_0] -add {PMVBRAM_X4Y2:PMVBRAM_X5Y2} 6 | resize_pblock [get_pblocks pr_0] -add {RAMB18_X4Y40:RAMB18_X5Y59} 7 | resize_pblock [get_pblocks pr_0] -add {RAMB36_X4Y20:RAMB36_X5Y29} 8 | set_property SNAPPING_MODE ON [get_pblocks pr_0] 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /zedboard_example/zedboard_example.srcs/wrapper/imports/wrapper/new/pr_1.xdc: -------------------------------------------------------------------------------- 1 | create_pblock pr_1 2 | add_cells_to_pblock [get_pblocks pr_1] [get_cells -quiet [list pr_1]] 3 | resize_pblock [get_pblocks pr_1] -add {SLICE_X90Y50:SLICE_X113Y99} 4 | resize_pblock [get_pblocks pr_1] -add {DSP48_X3Y20:DSP48_X4Y39} 5 | resize_pblock [get_pblocks pr_1] -add {PMVBRAM_X4Y1:PMVBRAM_X5Y1} 6 | resize_pblock [get_pblocks pr_1] -add {RAMB18_X4Y20:RAMB18_X5Y39} 7 | resize_pblock [get_pblocks pr_1] -add {RAMB36_X4Y10:RAMB36_X5Y19} 8 | set_property SNAPPING_MODE ON [get_pblocks pr_1] 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /zedboard_example/zedboard_example.srcs/sources_1/bd/BD_PR_3/BD_PR_3_ooc.xdc: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | 3 | # This XDC is used only for OOC mode of synthesis, implementation 4 | # This constraints file contains default clock frequencies to be used during 5 | # out-of-context flows such as OOC Synthesis and Hierarchical Designs. 6 | # This constraints file is not used in normal top-down synthesis (default flow 7 | # of Vivado) 8 | ################################################################################ 9 | create_clock -name Processing_System_processing_system7_0_FCLK_CLK0 -period 10 [get_pins Processing_System/processing_system7_0/FCLK_CLK0] 10 | 11 | ################################################################################ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Björn Gottschall 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Reloc - An Open-Sourced Vivado Workflow for Generating Relocatable, Out-Of-Context End-User Configuration Tiles 2 | 3 | * Implement one bitstream and configure it in different FPGA locations 4 | * Combining Isolation Design Flow and Partial Reconfiguration 5 | * Preserving compatibility of bitstreams over different implementations 6 | * Independent development of static design and partial reconfigurations 7 | * Much less implementation time 8 | 9 | # procs.tcl 10 | This file contains a collection of tcl functions which are useful and necessary for the relocation process. Source this file for the relocation process in pr_script.tcl or simply to extend the Vivado features. 11 | 12 | # pr_script.tcl 13 | This file contains a complete example workflow for a relocation process. On the first few lines are different parameters to control the workflow and interface placement. The workflow is only compatible with the design guidelines described in 'reloc.pdf'. 14 | 15 | # reloc.pdf 16 | This is the complete guide with all explanations and examples. 17 | 18 | # zedboard_example 19 | Example Project for the ZedBoard. 20 | 21 | * Open with Vivado 22 | * Open and generate shipped block design 23 | * source procs.tcl 24 | * source pr_script.tcl 25 | 26 | Implemented design has now 3 relocatable partions. 27 | 28 | # relocater 29 | Working proof of concept. Creating FAR Profiles from existing Bitstreams and patching them in new ones! 30 | 31 | * Get Header and FAR Informations from bitstreams 32 | * Writing the FAR Addresses into profile files 33 | * Patching bitstreams with FAR Address Profiles 34 | 35 | WARNING: make always a copy of the bitstreams you are working on. If the patching is successful the relocater overwrites the bitstream. 36 | -------------------------------------------------------------------------------- /zedboard_example/zedboard_example.srcs/sources_1/imports/sources_1/new/pr_axis_loopback.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.numeric_std.all; 3 | use ieee.std_logic_1164.all; 4 | use ieee.std_logic_arith.all; 5 | use ieee.std_logic_unsigned.all; 6 | 7 | entity pr_axis_loopback is 8 | generic ( 9 | DATAWIDTH : integer := 64 10 | ); 11 | port ( 12 | s_axis_data_tdata : in std_logic_vector(DATAWIDTH-1 downto 0); 13 | s_axis_data_tkeep : in std_logic_vector(DATAWIDTH/8 - 1 downto 0); 14 | s_axis_data_tready : out std_logic; 15 | s_axis_data_tlast : in std_logic; 16 | s_axis_data_tvalid : in std_logic; 17 | 18 | m_axis_data_tdata : out std_logic_vector(DATAWIDTH-1 downto 0); 19 | m_axis_data_tkeep : out std_logic_vector(DATAWIDTH/8 - 1 downto 0); 20 | m_axis_data_tready : in std_logic; 21 | m_axis_data_tlast : out std_logic; 22 | m_axis_data_tvalid : out std_logic; 23 | 24 | -- Global Clock Signal 25 | clk : in std_logic 26 | ); 27 | end pr_axis_loopback; 28 | 29 | architecture rtl of pr_axis_loopback is 30 | 31 | component axis_buffer is 32 | generic ( 33 | DATAWIDTH : integer := DATAWIDTH; 34 | BUFFER_SIZE : integer := 1 35 | ); 36 | port ( 37 | s_axis_data_tdata : in std_logic_vector(DATAWIDTH - 1 downto 0); 38 | s_axis_data_tkeep : in std_logic_vector(DATAWIDTH/8 - 1 downto 0); 39 | s_axis_data_tready : out std_logic; 40 | s_axis_data_tlast : in std_logic; 41 | s_axis_data_tvalid : in std_logic; 42 | 43 | m_axis_data_tdata : out std_logic_vector(DATAWIDTH - 1 downto 0); 44 | m_axis_data_tkeep : out std_logic_vector(DATAWIDTH/8 - 1 downto 0); 45 | m_axis_data_tready : in std_logic; 46 | m_axis_data_tlast : out std_logic; 47 | m_axis_data_tvalid : out std_logic; 48 | 49 | -- Global Clock Signal 50 | clk : in std_logic 51 | ); 52 | end component; 53 | begin 54 | 55 | loopback: component axis_buffer 56 | port map ( 57 | s_axis_data_tdata => s_axis_data_tdata, 58 | s_axis_data_tkeep => s_axis_data_tkeep, 59 | s_axis_data_tready => s_axis_data_tready, 60 | s_axis_data_tlast => s_axis_data_tlast, 61 | s_axis_data_tvalid => s_axis_data_tvalid, 62 | 63 | m_axis_data_tdata => m_axis_data_tdata, 64 | m_axis_data_tkeep => m_axis_data_tkeep, 65 | m_axis_data_tready => m_axis_data_tready, 66 | m_axis_data_tlast => m_axis_data_tlast, 67 | m_axis_data_tvalid => m_axis_data_tvalid, 68 | 69 | clk => clk 70 | ); 71 | end architecture; -------------------------------------------------------------------------------- /zedboard_example/zedboard_example.srcs/sources_1/imports/sources_1/new/axis_lut_buffer.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.numeric_std.all; 3 | use ieee.std_logic_1164.all; 4 | use ieee.std_logic_arith.all; 5 | use ieee.std_logic_unsigned.all; 6 | 7 | entity axis_lut_buffer is 8 | generic ( 9 | DATAWIDTH : integer := 64 10 | ); 11 | port ( 12 | s_axis_data_tdata : in std_logic_vector(DATAWIDTH-1 downto 0); 13 | s_axis_data_tkeep : in std_logic_vector(DATAWIDTH/8 - 1 downto 0); 14 | s_axis_data_tready : out std_logic; 15 | s_axis_data_tlast : in std_logic; 16 | s_axis_data_tvalid : in std_logic; 17 | 18 | m_axis_data_tdata : out std_logic_vector(DATAWIDTH-1 downto 0); 19 | m_axis_data_tkeep : out std_logic_vector(DATAWIDTH/8 - 1 downto 0); 20 | m_axis_data_tready : in std_logic; 21 | m_axis_data_tlast : out std_logic; 22 | m_axis_data_tvalid : out std_logic; 23 | 24 | -- Global Clock Signal 25 | clk : in std_logic 26 | ); 27 | end axis_lut_buffer; 28 | 29 | architecture rtl of axis_lut_buffer is 30 | component LUT1 31 | generic ( 32 | INIT: bit_vector(1 downto 0) := "10" 33 | ); 34 | port ( 35 | O : out std_logic; 36 | I0 : in std_logic 37 | ); 38 | end component; 39 | begin 40 | 41 | LUTBUF_TDATA: 42 | for I in 0 to DATAWIDTH-1 generate 43 | LUTX: 44 | LUT1 45 | generic map ( INIT => "10" ) 46 | port map ( 47 | O => m_axis_data_tdata(I), 48 | I0 => s_axis_data_tdata(I) 49 | ); 50 | end generate LUTBUF_TDATA; 51 | 52 | LUTBUF_TKEEP: 53 | for I in 0 to (DATAWIDTH/8)-1 generate 54 | LUTX: 55 | LUT1 56 | generic map ( INIT => "10" ) 57 | port map ( 58 | O => m_axis_data_tkeep(I), 59 | I0 => s_axis_data_tkeep(I) 60 | ); 61 | end generate LUTBUF_TKEEP; 62 | 63 | LUTBUF_TVALID: 64 | LUT1 65 | generic map ( INIT => "10" ) 66 | port map ( 67 | O => m_axis_data_tvalid, 68 | I0 => s_axis_data_tvalid 69 | ); 70 | 71 | LUTBUF_TLAST: 72 | LUT1 73 | generic map ( INIT => "10" ) 74 | port map ( 75 | O => m_axis_data_tlast, 76 | I0 => s_axis_data_tlast 77 | ); 78 | 79 | LUTBUF_TREADY: 80 | LUT1 81 | generic map ( INIT => "10" ) 82 | port map ( 83 | O => s_axis_data_tready, 84 | I0 => m_axis_data_tready 85 | ); 86 | 87 | end rtl; -------------------------------------------------------------------------------- /zedboard_example/zedboard_example.srcs/sources_1/imports/sources_1/new/axis_buffer.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.numeric_std.all; 3 | use ieee.std_logic_1164.all; 4 | use ieee.std_logic_arith.all; 5 | use ieee.std_logic_unsigned.all; 6 | 7 | entity axis_buffer is 8 | generic ( 9 | DATAWIDTH : integer := 64; 10 | BUFFER_SIZE : positive := 1 11 | ); 12 | port ( 13 | s_axis_data_tdata : in std_logic_vector(DATAWIDTH-1 downto 0); 14 | s_axis_data_tkeep : in std_logic_vector(DATAWIDTH/8 - 1 downto 0); 15 | s_axis_data_tready : out std_logic; 16 | s_axis_data_tlast : in std_logic; 17 | s_axis_data_tvalid : in std_logic; 18 | 19 | m_axis_data_tdata : out std_logic_vector(DATAWIDTH-1 downto 0); 20 | m_axis_data_tkeep : out std_logic_vector(DATAWIDTH/8 - 1 downto 0); 21 | m_axis_data_tready : in std_logic; 22 | m_axis_data_tlast : out std_logic; 23 | m_axis_data_tvalid : out std_logic; 24 | 25 | -- Global Clock Signal 26 | clk : in std_logic 27 | ); 28 | end axis_buffer; 29 | 30 | architecture rtl of axis_buffer is 31 | signal reg_tdata : STD_LOGIC_VECTOR (((BUFFER_SIZE + 1) * DATAWIDTH) - 1 downto 0) := ( others => '0' ); 32 | signal reg_tkeep : STD_LOGIC_VECTOR (((BUFFER_SIZE + 1) * DATAWIDTH/8) - 1 downto 0) := ( others => '1' ); 33 | signal reg_tlast : STD_LOGIC_VECTOR (BUFFER_SIZE downto 0) := ( others => '0' ); 34 | signal reg_tvalid : STD_LOGIC_VECTOR (BUFFER_SIZE downto 0) := ( others => '0' ); 35 | signal tready : STD_LOGIC := '0'; 36 | begin 37 | process(clk) 38 | begin 39 | if rising_edge(clk) then 40 | 41 | if (tready = '1') then 42 | reg_tdata(((BUFFER_SIZE + 1) * DATAWIDTH) - 1 downto BUFFER_SIZE * DATAWIDTH) <= s_axis_data_tdata; 43 | reg_tkeep(((BUFFER_SIZE + 1) * DATAWIDTH/8) - 1 downto BUFFER_SIZE * DATAWIDTH/8) <= s_axis_data_tkeep; 44 | reg_tlast(BUFFER_SIZE) <= s_axis_data_tlast; 45 | reg_tvalid(BUFFER_SIZE) <= s_axis_data_tvalid; 46 | end if; 47 | 48 | if (m_axis_data_tready = '1') then 49 | tready <= '1'; 50 | reg_tdata((BUFFER_SIZE * DATAWIDTH) - 1 downto 0) <= reg_tdata(((BUFFER_SIZE + 1) * DATAWIDTH) - 1 downto DATAWIDTH); 51 | reg_tkeep((BUFFER_SIZE * DATAWIDTH/8) - 1 downto 0) <= reg_tkeep(((BUFFER_SIZE + 1) * DATAWIDTH/8) - 1 downto DATAWIDTH/8); 52 | reg_tlast(BUFFER_SIZE - 1 downto 0) <= reg_tlast(BUFFER_SIZE downto 1); 53 | reg_tvalid(BUFFER_SIZE - 1 downto 0) <= reg_tvalid(BUFFER_SIZE downto 1); 54 | else 55 | tready <= '0'; 56 | end if; 57 | 58 | end if; 59 | end process; 60 | 61 | m_axis_data_tdata <= reg_tdata(DATAWIDTH - 1 downto 0); 62 | m_axis_data_tkeep <= reg_tkeep(DATAWIDTH/8 - 1 downto 0); 63 | m_axis_data_tlast <= reg_tlast(0); 64 | m_axis_data_tvalid <= reg_tvalid(0); 65 | s_axis_data_tready <= tready; 66 | end architecture; -------------------------------------------------------------------------------- /relocater/relocater.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Björn Gottschall 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | //This is a Proof of Concept, not clean code! 22 | 23 | #include 24 | #include 25 | 26 | /********************** 27 | * Boyer-Moore search * 28 | **********************/ 29 | void *kmemmem(const void *_str, int n, const void *_pat, int m); 30 | 31 | typedef unsigned char ubyte_t; 32 | 33 | // reference: http://www-igm.univ-mlv.fr/~lecroq/string/node14.html 34 | static int *ksBM_prep(const ubyte_t *pat, int m) 35 | { 36 | int i, *suff, *prep, *bmGs, *bmBc; 37 | prep = calloc(m + 256, sizeof(int)); 38 | bmGs = prep; bmBc = prep + m; 39 | { // preBmBc() 40 | for (i = 0; i < 256; ++i) bmBc[i] = m; 41 | for (i = 0; i < m - 1; ++i) bmBc[pat[i]] = m - i - 1; 42 | } 43 | suff = calloc(m, sizeof(int)); 44 | { // suffixes() 45 | int f = 0, g; 46 | suff[m - 1] = m; 47 | g = m - 1; 48 | for (i = m - 2; i >= 0; --i) { 49 | if (i > g && suff[i + m - 1 - f] < i - g) 50 | suff[i] = suff[i + m - 1 - f]; 51 | else { 52 | if (i < g) g = i; 53 | f = i; 54 | while (g >= 0 && pat[g] == pat[g + m - 1 - f]) --g; 55 | suff[i] = f - g; 56 | } 57 | } 58 | } 59 | { // preBmGs() 60 | int j = 0; 61 | for (i = 0; i < m; ++i) bmGs[i] = m; 62 | for (i = m - 1; i >= 0; --i) 63 | if (suff[i] == i + 1) 64 | for (; j < m - 1 - i; ++j) 65 | if (bmGs[j] == m) 66 | bmGs[j] = m - 1 - i; 67 | for (i = 0; i <= m - 2; ++i) 68 | bmGs[m - 1 - suff[i]] = m - 1 - i; 69 | } 70 | free(suff); 71 | return prep; 72 | } 73 | 74 | void *kmemmem(const void *_str, int n, const void *_pat, int m) 75 | { 76 | int i, j, *prep = 0, *bmGs, *bmBc; 77 | const ubyte_t *str, *pat; 78 | str = (const ubyte_t*)_str; pat = (const ubyte_t*)_pat; 79 | prep = ksBM_prep(pat, m); 80 | bmGs = prep; bmBc = prep + m; 81 | j = 0; 82 | while (j <= n - m) { 83 | for (i = m - 1; i >= 0 && pat[i] == str[i+j]; --i); 84 | if (i >= 0) { 85 | int max = bmBc[str[i+j]] - m + 1 + i; 86 | if (max < bmGs[i]) max = bmGs[i]; 87 | j += max; 88 | } else return (void*)(str + j); 89 | } 90 | free(prep); 91 | return NULL; 92 | } 93 | -------------------------------------------------------------------------------- /zedboard_example/zedboard_example.srcs/wrapper/imports/wrapper/imports/new/isol.xdc: -------------------------------------------------------------------------------- 1 | create_pblock static 2 | add_cells_to_pblock [get_pblocks static] [get_cells -quiet [list block_design]] 3 | resize_pblock [get_pblocks static] -add {SLICE_X0Y0:SLICE_X81Y149} 4 | resize_pblock [get_pblocks static] -add {BSCAN_X0Y0:BSCAN_X0Y3} 5 | resize_pblock [get_pblocks static] -add {BUFGCTRL_X0Y0:BUFGCTRL_X0Y31} 6 | resize_pblock [get_pblocks static] -add {BUFHCE_X0Y0:BUFHCE_X1Y35} 7 | resize_pblock [get_pblocks static] -add {BUFMRCE_X0Y0:BUFMRCE_X0Y1} 8 | resize_pblock [get_pblocks static] -add {CAPTURE_X0Y0:CAPTURE_X0Y0} 9 | resize_pblock [get_pblocks static] -add {CFG_IO_ACCESS_X0Y0:CFG_IO_ACCESS_X0Y0} 10 | resize_pblock [get_pblocks static] -add {DCIRESET_X0Y0:DCIRESET_X0Y0} 11 | resize_pblock [get_pblocks static] -add {DNA_PORT_X0Y0:DNA_PORT_X0Y0} 12 | resize_pblock [get_pblocks static] -add {DSP48_X0Y0:DSP48_X2Y59} 13 | resize_pblock [get_pblocks static] -add {EFUSE_USR_X0Y0:EFUSE_USR_X0Y0} 14 | resize_pblock [get_pblocks static] -add {FRAME_ECC_X0Y0:FRAME_ECC_X0Y0} 15 | resize_pblock [get_pblocks static] -add {ICAP_X0Y0:ICAP_X0Y1} 16 | resize_pblock [get_pblocks static] -add {IN_FIFO_X0Y0:IN_FIFO_X0Y3} 17 | resize_pblock [get_pblocks static] -add {IOPAD_X1Y1:IOPAD_X1Y134} 18 | resize_pblock [get_pblocks static] -add {IPAD_X0Y0:IPAD_X0Y1} 19 | resize_pblock [get_pblocks static] -add {MMCME2_ADV_X0Y0:MMCME2_ADV_X0Y0} 20 | resize_pblock [get_pblocks static] -add {OUT_FIFO_X0Y0:OUT_FIFO_X0Y3} 21 | resize_pblock [get_pblocks static] -add {PHASER_IN_PHY_X0Y0:PHASER_IN_PHY_X0Y3} 22 | resize_pblock [get_pblocks static] -add {PHASER_OUT_PHY_X0Y0:PHASER_OUT_PHY_X0Y3} 23 | resize_pblock [get_pblocks static] -add {PHASER_REF_X0Y0:PHASER_REF_X0Y0} 24 | resize_pblock [get_pblocks static] -add {PHY_CONTROL_X0Y0:PHY_CONTROL_X0Y0} 25 | resize_pblock [get_pblocks static] -add {PLLE2_ADV_X0Y0:PLLE2_ADV_X0Y0} 26 | resize_pblock [get_pblocks static] -add {PMV_X0Y0:PMV_X0Y2} 27 | resize_pblock [get_pblocks static] -add {PMVBRAM_X0Y0:PMVBRAM_X3Y2} 28 | resize_pblock [get_pblocks static] -add {PMVIOB_X0Y0:PMVIOB_X1Y1} 29 | resize_pblock [get_pblocks static] -add {PS7_X0Y0:PS7_X0Y0} 30 | resize_pblock [get_pblocks static] -add {RAMB18_X0Y0:RAMB18_X3Y59} 31 | resize_pblock [get_pblocks static] -add {RAMB36_X0Y0:RAMB36_X3Y29} 32 | resize_pblock [get_pblocks static] -add {STARTUP_X0Y0:STARTUP_X0Y0} 33 | resize_pblock [get_pblocks static] -add {USR_ACCESS_X0Y0:USR_ACCESS_X0Y0} 34 | resize_pblock [get_pblocks static] -add {XADC_X0Y0:XADC_X0Y0} 35 | 36 | create_pblock pr_0_buffer 37 | add_cells_to_pblock [get_pblocks pr_0_buffer] [get_cells -quiet [list pr_0_buffer]] 38 | resize_pblock [get_pblocks pr_0_buffer] -add {SLICE_X84Y100:SLICE_X87Y149} 39 | 40 | create_pblock pr_1_buffer 41 | add_cells_to_pblock [get_pblocks pr_1_buffer] [get_cells -quiet [list pr_1_buffer]] 42 | resize_pblock [get_pblocks pr_1_buffer] -add {SLICE_X84Y50:SLICE_X87Y99} 43 | 44 | create_pblock pr_2_buffer 45 | add_cells_to_pblock [get_pblocks pr_2_buffer] [get_cells -quiet [list pr_2_buffer]] 46 | resize_pblock [get_pblocks pr_2_buffer] -add {SLICE_X84Y0:SLICE_X87Y49} 47 | 48 | set_property HD.ISOLATED true [get_cells pr_0] 49 | set_property HD.ISOLATED true [get_cells pr_1] 50 | set_property HD.ISOLATED true [get_cells pr_2] 51 | set_property HD.ISOLATED true [get_cells pr_0_buffer] 52 | set_property HD.ISOLATED true [get_cells pr_1_buffer] 53 | set_property HD.ISOLATED true [get_cells pr_2_buffer] 54 | 55 | set_property HD.ISOLATED true [get_cells block_design] 56 | set_property HD.ISOLATED_EXEMPT true [get_cells -hierarchical -filter {PRIMITIVE_TYPE =~ CLK.gclk.*}] 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /relocater/bitstreams.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Björn Gottschall 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | //This is a Proof of Concept, not clean code! 22 | 23 | #include 24 | #include 25 | 26 | #define TYPE_1 0b001 27 | #define TYPE_2 0b010 28 | 29 | #define OPCODE_NOP 0b00 30 | #define OPCODE_READ 0b01 31 | #define OPCODE_WRITE 0b10 32 | #define OPCODE_RESERVED 0b11 33 | 34 | #define REGISTER_CRC 0b00000 35 | #define REGISTER_FAR 0b00001 36 | #define REGISTER_FDRI 0b00010 37 | #define REGISTER_FDRO 0b00011 38 | #define REGISTER_CMD 0b00100 39 | #define REGISTER_CTL0 0b00101 40 | #define REGISTER_MASK 0b00110 41 | #define REGISTER_STAT 0b00111 42 | #define REGISTER_LOUT 0b01000 43 | #define REGISTER_COR0 0b01001 44 | #define REGISTER_MFWR 0b01010 45 | #define REGISTER_CBC 0b01011 46 | #define REGISTER_IDCODE 0b01100 47 | #define REGISTER_AXSS 0b01101 48 | #define REGISTER_COR1 0b01110 49 | #define REGISTER_WBSTAR 0b10000 50 | #define REGISTER_TIMER 0b10001 51 | #define REGISTER_BOOTSTS 0b10110 52 | #define REGISTER_CTL1 0b11000 53 | #define REGISTER_BSPI 0b11111 54 | #define REGISTER_BSPI_READ 0b10010 55 | #define REGISTER_FALL_EDGE 0b10011 56 | 57 | 58 | #define REGISTER_INVALID -1 59 | 60 | #define PACKAGE_SIZE 4 61 | 62 | struct BITSTREAM_PACKAGE { 63 | unsigned int type; //E0 64 | unsigned int opcode; //2 65 | // 66 | unsigned int register_address; // 5 67 | unsigned int word_count; // 11 - 27 68 | }; 69 | 70 | 71 | // WWWW WWWW AAAR RWWW RRRR RRAA TTTO ORRR 72 | // 00000RRRRRRRRR00000RR00000000000 73 | // 00100000000000000000000000000000 74 | // 00001000000000000000000000000000 75 | // 00000010000000000000000000000000 76 | // 00000010000000000000000000000000 77 | struct BITSTREAM_PACKAGE create_package(void *data) { 78 | struct BITSTREAM_PACKAGE package; 79 | char *values = (char *) data; 80 | uint32_t value = be32toh(*((uint32_t *)data)); 81 | package.type = (value & 0xE0000000) >> 29; 82 | package.opcode = (value & 0x18000000) >> 27; 83 | if (package.type == TYPE_1) { 84 | package.register_address = (value & 0x0003E000) >> 13; 85 | package.word_count = (value & 0x000007FF); 86 | } else { 87 | package.register_address = REGISTER_INVALID; 88 | package.word_count = (value & 0x7FFFFFF); 89 | } 90 | return package; 91 | } 92 | 93 | void dump_package(struct BITSTREAM_PACKAGE package) { 94 | printf("Package Type:\t\t\t%d\n", package.type); 95 | printf("Package OpCode:\t\t\t0x%x\n", package.opcode); 96 | printf("Package Register Address:\t0x%x\n", package.register_address); 97 | printf("Package Word Count:\t\t0x%x\n", package.word_count); 98 | } 99 | -------------------------------------------------------------------------------- /zedboard_example/zedboard_example.srcs/sources_1/bd/BD_PR_3/ui/bd_442d2033.ui: -------------------------------------------------------------------------------- 1 | { 2 | guistr: "# # String gsaved with Nlview 6.6.5b 2016-09-06 bk=1.3687 VDI=39 GEI=35 GUI=JA:1.6 3 | # -string -flagsOSRD 4 | preplace port DDR -pg 1 -lvl 1:60 -defaultsOSRD -top 5 | preplace port s_axis_data_0 -pg 1 -y 200 -defaultsOSRD 6 | preplace port m_axis_data_0 -pg 1 -y 230 -defaultsOSRD 7 | preplace port s_axis_data_1 -pg 1 -y 480 -defaultsOSRD 8 | preplace port m_axis_data_1 -pg 1 -y 490 -defaultsOSRD 9 | preplace port AXIS_CLK -pg 1 -lvl 2:-140 -defaultsOSRD -top 10 | preplace port s_axis_data_2 -pg 1 -y 680 -defaultsOSRD 11 | preplace port m_axis_data_2 -pg 1 -y 690 -defaultsOSRD 12 | preplace port FIXED_IO -pg 1 -lvl 1:80 -defaultsOSRD -top 13 | preplace inst Processing_System|axi_mem_intercon -pg 1 -lvl 3 -y 920 -defaultsOSRD 14 | preplace inst axi_dma_0 -pg 1 -lvl 2 -y 250 -defaultsOSRD 15 | preplace inst Processing_System|rst_ps7_0_100M -pg 1 -lvl 2 -y 430 -defaultsOSRD 16 | preplace inst axi_dma_1 -pg 1 -lvl 2 -y 510 -defaultsOSRD 17 | preplace inst Processing_System|IRQ_Concat -pg 1 -lvl 1 -y 710 -defaultsOSRD 18 | preplace inst axi_dma_2 -pg 1 -lvl 2 -y 750 -defaultsOSRD 19 | preplace inst Processing_System|ps7_0_axi_periph -pg 1 -lvl 3 -y 470 -defaultsOSRD 20 | preplace inst Processing_System -pg 1 -lvl 1 -y 410 -defaultsOSRD 21 | preplace inst Processing_System|processing_system7_0 -pg 1 -lvl 2 -y 700 -defaultsOSRD 22 | preplace netloc Processing_System|Conn2 1 0 3 NJ 350 420J 340 1000 23 | preplace netloc s_axis_data_2_1 1 0 2 -70J 1220 1530J 24 | preplace netloc processing_system7_0_DDR 1 1 1 1470 25 | preplace netloc ps7_0_axi_periph_M02_AXI 1 1 1 1490 26 | preplace netloc Processing_System|Conn3 1 0 3 NJ 520 NJ 520 980 27 | preplace netloc axi_dma_1_M_AXI_S2MM 1 0 3 10 100 NJ 100 1990 28 | preplace netloc axi_dma_2_s2mm_introut 1 0 3 30 1240 NJ 1240 1930 29 | preplace netloc Processing_System|Conn4 1 0 3 NJ 540 NJ 540 970 30 | preplace netloc Processing_System|processing_system7_0_DDR 1 2 2 930J 300 NJ 31 | preplace netloc Processing_System|Conn5 1 0 3 NJ 560 NJ 560 950 32 | preplace netloc Processing_System|ps7_0_axi_periph_M02_AXI 1 3 1 N 33 | preplace netloc Processing_System|ps7_0_axi_periph_M00_AXI 1 3 1 N 34 | preplace netloc Processing_System|processing_system7_0_FIXED_IO 1 2 2 NJ 640 1310J 35 | preplace netloc Processing_System|axi_dma_0_s2mm_introut 1 0 1 N 36 | preplace netloc Processing_System|rst_ps7_0_100M_interconnect_aresetn 1 2 1 910 37 | preplace netloc axi_dma_1_M_AXI_MM2S 1 0 3 0 60 NJ 60 2020 38 | preplace netloc axi_dma_1_M_AXIS_MM2S 1 2 1 NJ 39 | preplace netloc rst_ps7_0_100M_peripheral_aresetn 1 1 1 1520 40 | preplace netloc Processing_System|Conn6 1 0 3 NJ 580 420J 570 920 41 | preplace netloc Processing_System|axi_mem_intercon_M00_AXI 1 1 3 430 280 NJ 280 1300 42 | preplace netloc Processing_System|axi_dma_1_mm2s_introut 1 0 1 N 43 | preplace netloc axi_dma_1_s2mm_introut 1 0 3 -30 120 NJ 120 1970 44 | preplace netloc Processing_System|processing_system7_0_M_AXI_GP0 1 2 1 960 45 | preplace netloc Processing_System|IRQ_Concat_dout 1 1 1 420 46 | preplace netloc axi_dma_2_M_AXI_S2MM 1 0 3 30 140 NJ 140 1950 47 | preplace netloc Processing_System|axi_dma_1_s2mm_introut 1 0 1 N 48 | preplace netloc ps7_0_axi_periph_M01_AXI 1 1 1 1530 49 | preplace netloc axi_dma_0_s2mm_introut 1 0 3 -50 90 NJ 90 1930 50 | preplace netloc Processing_System|axi_dma_2_s2mm_introut 1 0 1 N 51 | preplace netloc Processing_System|processing_system7_0_FCLK_RESET0_N 1 1 2 450 550 900 52 | preplace netloc axi_dma_0_M_AXI_MM2S 1 0 3 -20 40 NJ 40 2010 53 | preplace netloc processing_system7_0_FIXED_IO 1 1 1 1480 54 | preplace netloc axi_dma_2_mm2s_introut 1 0 3 20 1230 NJ 1230 1940 55 | preplace netloc axi_dma_0_mm2s_introut 1 0 3 -60 80 NJ 80 1940 56 | preplace netloc Processing_System|ps7_0_axi_periph_M01_AXI 1 3 1 N 57 | preplace netloc Processing_System|rst_ps7_0_100M_peripheral_aresetn 1 2 2 940 1190 NJ 58 | preplace netloc axi_dma_0_M_AXI_S2MM 1 0 3 -10 50 NJ 50 2000 59 | preplace netloc Processing_System|axi_dma_2_mm2s_introut 1 0 1 N 60 | preplace netloc Processing_System|processing_system7_0_FCLK_CLK0 1 1 3 440 830 990 650 NJ 61 | preplace netloc axi_dma_2_M_AXI_MM2S 1 0 3 20 130 NJ 130 1960 62 | preplace netloc s_axis_data_1_1 1 0 2 -70J 240 1490J 63 | preplace netloc processing_system7_0_FCLK_CLK0 1 1 1 1510 64 | preplace netloc s_axis_data_0_1 1 0 2 -70J 220 NJ 65 | preplace netloc axi_dma_2_M_AXIS_MM2S 1 2 1 2010J 66 | preplace netloc axi_dma_0_M_AXIS_MM2S 1 2 1 NJ 67 | preplace netloc ps7_0_axi_periph_M00_AXI 1 1 1 1500 68 | preplace netloc Processing_System|Conn1 1 0 3 NJ 330 NJ 330 1010 69 | preplace netloc Processing_System|axi_dma_0_mm2s_introut 1 0 1 N 70 | preplace netloc axi_dma_1_mm2s_introut 1 0 3 -40 110 NJ 110 1980 71 | levelinfo -pg 1 -90 300 1760 2040 -top -140 -bot 1320 72 | levelinfo -hier Processing_System * 330 680 1160 * 73 | ", 74 | } 75 | { 76 | da_axi4_cnt: "10", 77 | da_ps7_cnt: "1", 78 | } -------------------------------------------------------------------------------- /zedboard_example/zedboard_example.srcs/sources_1/imports/sources_1/new/pr_axis.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.numeric_std.all; 3 | use ieee.std_logic_1164.all; 4 | use ieee.std_logic_arith.all; 5 | use ieee.std_logic_unsigned.all; 6 | 7 | entity pr_axis is 8 | generic ( 9 | DATAWIDTH : integer := 64 10 | ); 11 | port ( 12 | s_axis_data_tdata : in std_logic_vector(DATAWIDTH-1 downto 0); 13 | s_axis_data_tkeep : in std_logic_vector(DATAWIDTH/8 - 1 downto 0); 14 | s_axis_data_tready : out std_logic; 15 | s_axis_data_tlast : in std_logic; 16 | s_axis_data_tvalid : in std_logic; 17 | 18 | m_axis_data_tdata : out std_logic_vector(DATAWIDTH-1 downto 0); 19 | m_axis_data_tkeep : out std_logic_vector(DATAWIDTH/8 - 1 downto 0); 20 | m_axis_data_tready : in std_logic; 21 | m_axis_data_tlast : out std_logic; 22 | m_axis_data_tvalid : out std_logic; 23 | 24 | -- Global Clock Signal 25 | clk : in std_logic 26 | ); 27 | end pr_axis; 28 | 29 | architecture rtl of pr_axis is 30 | 31 | component axis_lut_buffer is 32 | generic ( 33 | DATAWIDTH : integer := DATAWIDTH 34 | ); 35 | port ( 36 | s_axis_data_tdata : in std_logic_vector(DATAWIDTH - 1 downto 0); 37 | s_axis_data_tkeep : in std_logic_vector(DATAWIDTH/8 - 1 downto 0); 38 | s_axis_data_tready : out std_logic; 39 | s_axis_data_tlast : in std_logic; 40 | s_axis_data_tvalid : in std_logic; 41 | 42 | m_axis_data_tdata : out std_logic_vector(DATAWIDTH - 1 downto 0); 43 | m_axis_data_tkeep : out std_logic_vector(DATAWIDTH/8 - 1 downto 0); 44 | m_axis_data_tready : in std_logic; 45 | m_axis_data_tlast : out std_logic; 46 | m_axis_data_tvalid : out std_logic; 47 | 48 | -- Global Clock Signal 49 | clk : in std_logic 50 | ); 51 | end component; 52 | 53 | component pr_axis_loopback is 54 | generic ( 55 | DATAWIDTH : integer := DATAWIDTH 56 | ); 57 | port ( 58 | s_axis_data_tdata : in std_logic_vector(DATAWIDTH-1 downto 0); 59 | s_axis_data_tkeep : in std_logic_vector(DATAWIDTH/8 - 1 downto 0); 60 | s_axis_data_tready : out std_logic; 61 | s_axis_data_tlast : in std_logic; 62 | s_axis_data_tvalid : in std_logic; 63 | 64 | m_axis_data_tdata : out std_logic_vector(DATAWIDTH-1 downto 0); 65 | m_axis_data_tkeep : out std_logic_vector(DATAWIDTH/8 - 1 downto 0); 66 | m_axis_data_tready : in std_logic; 67 | m_axis_data_tlast : out std_logic; 68 | m_axis_data_tvalid : out std_logic; 69 | 70 | -- Global Clock Signal 71 | clk : in std_logic 72 | ); 73 | end component; 74 | 75 | signal pr_m_axis_data_tdata : STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 76 | signal pr_m_axis_data_tkeep : STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 77 | signal pr_m_axis_data_tlast : STD_LOGIC; 78 | signal pr_m_axis_data_tready : STD_LOGIC; 79 | signal pr_m_axis_data_tvalid : STD_LOGIC; 80 | signal pr_s_axis_data_tdata : STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 81 | signal pr_s_axis_data_tkeep : STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 82 | signal pr_s_axis_data_tlast : STD_LOGIC; 83 | signal pr_s_axis_data_tready : STD_LOGIC; 84 | signal pr_s_axis_data_tvalid : STD_LOGIC; 85 | 86 | begin 87 | 88 | input_lut_buffer: component axis_lut_buffer 89 | port map ( 90 | s_axis_data_tdata => s_axis_data_tdata, 91 | s_axis_data_tkeep => s_axis_data_tkeep, 92 | s_axis_data_tready => s_axis_data_tready, 93 | s_axis_data_tlast => s_axis_data_tlast, 94 | s_axis_data_tvalid => s_axis_data_tvalid, 95 | 96 | m_axis_data_tdata => pr_s_axis_data_tdata, 97 | m_axis_data_tkeep => pr_s_axis_data_tkeep, 98 | m_axis_data_tready => pr_s_axis_data_tready, 99 | m_axis_data_tlast => pr_s_axis_data_tlast, 100 | m_axis_data_tvalid => pr_s_axis_data_tvalid, 101 | 102 | clk => clk 103 | ); 104 | 105 | output_lut_buffer: component axis_lut_buffer 106 | port map ( 107 | s_axis_data_tdata => pr_m_axis_data_tdata, 108 | s_axis_data_tkeep => pr_m_axis_data_tkeep, 109 | s_axis_data_tready => pr_m_axis_data_tready, 110 | s_axis_data_tlast => pr_m_axis_data_tlast, 111 | s_axis_data_tvalid => pr_m_axis_data_tvalid, 112 | 113 | m_axis_data_tdata => m_axis_data_tdata, 114 | m_axis_data_tkeep => m_axis_data_tkeep, 115 | m_axis_data_tready => m_axis_data_tready, 116 | m_axis_data_tlast => m_axis_data_tlast, 117 | m_axis_data_tvalid => m_axis_data_tvalid, 118 | 119 | clk => clk 120 | ); 121 | 122 | pr: component pr_axis_loopback 123 | port map ( 124 | s_axis_data_tdata => pr_s_axis_data_tdata, 125 | s_axis_data_tkeep => pr_s_axis_data_tkeep, 126 | s_axis_data_tready => pr_s_axis_data_tready, 127 | s_axis_data_tlast => pr_s_axis_data_tlast, 128 | s_axis_data_tvalid => pr_s_axis_data_tvalid, 129 | 130 | m_axis_data_tdata => pr_m_axis_data_tdata, 131 | m_axis_data_tkeep => pr_m_axis_data_tkeep, 132 | m_axis_data_tready => pr_m_axis_data_tready, 133 | m_axis_data_tlast => pr_m_axis_data_tlast, 134 | m_axis_data_tvalid => pr_m_axis_data_tvalid, 135 | 136 | clk => clk 137 | ); 138 | 139 | end architecture; -------------------------------------------------------------------------------- /zedboard_example/zedboard_example.srcs/sources_1/imports/sources_1/new/pr_axis_buffer.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | 4 | entity pr_axis_buffer is 5 | generic ( 6 | DATAWIDTH : integer := 64 7 | ); 8 | port ( 9 | static_m_axis_data_tdata : in std_logic_vector(DATAWIDTH-1 downto 0); 10 | static_m_axis_data_tkeep : in std_logic_vector(DATAWIDTH/8 - 1 downto 0); 11 | static_m_axis_data_tready : out std_logic; 12 | static_m_axis_data_tlast : in std_logic; 13 | static_m_axis_data_tvalid : in std_logic; 14 | pr_m_axis_data_tdata : in std_logic_vector(DATAWIDTH-1 downto 0); 15 | pr_m_axis_data_tkeep : in std_logic_vector(DATAWIDTH/8 - 1 downto 0); 16 | pr_m_axis_data_tready : out std_logic; 17 | pr_m_axis_data_tlast : in std_logic; 18 | pr_m_axis_data_tvalid : in std_logic; 19 | 20 | 21 | static_s_axis_data_tdata : out std_logic_vector(DATAWIDTH-1 downto 0); 22 | static_s_axis_data_tkeep : out std_logic_vector(DATAWIDTH/8 - 1 downto 0); 23 | static_s_axis_data_tready : in std_logic; 24 | static_s_axis_data_tlast : out std_logic; 25 | static_s_axis_data_tvalid : out std_logic; 26 | pr_s_axis_data_tdata : out std_logic_vector(DATAWIDTH-1 downto 0); 27 | pr_s_axis_data_tkeep : out std_logic_vector(DATAWIDTH/8 - 1 downto 0); 28 | pr_s_axis_data_tready : in std_logic; 29 | pr_s_axis_data_tlast : out std_logic; 30 | pr_s_axis_data_tvalid : out std_logic; 31 | 32 | -- Global Clock Signal 33 | clk : in std_logic 34 | ); 35 | 36 | end pr_axis_buffer; 37 | 38 | architecture rtl of pr_axis_buffer is 39 | component axis_buffer is 40 | generic ( 41 | DATAWIDTH : integer := DATAWIDTH; 42 | BUFFER_SIZE : positive := 1 43 | ); 44 | port ( 45 | s_axis_data_tdata : in std_logic_vector(DATAWIDTH-1 downto 0); 46 | s_axis_data_tkeep : in std_logic_vector(DATAWIDTH/8 - 1 downto 0); 47 | s_axis_data_tready : out std_logic; 48 | s_axis_data_tlast : in std_logic; 49 | s_axis_data_tvalid : in std_logic; 50 | 51 | m_axis_data_tdata : out std_logic_vector(DATAWIDTH-1 downto 0); 52 | m_axis_data_tkeep : out std_logic_vector(DATAWIDTH/8 - 1 downto 0); 53 | m_axis_data_tready : in std_logic; 54 | m_axis_data_tlast : out std_logic; 55 | m_axis_data_tvalid : out std_logic; 56 | 57 | -- Global Clock Signal 58 | clk : in std_logic 59 | ); 60 | end component; 61 | component axis_lut_buffer is 62 | generic ( 63 | DATAWIDTH : integer := DATAWIDTH 64 | ); 65 | port ( 66 | s_axis_data_tdata : in std_logic_vector(DATAWIDTH-1 downto 0); 67 | s_axis_data_tkeep : in std_logic_vector(DATAWIDTH/8 - 1 downto 0); 68 | s_axis_data_tready : out std_logic; 69 | s_axis_data_tlast : in std_logic; 70 | s_axis_data_tvalid : in std_logic; 71 | 72 | m_axis_data_tdata : out std_logic_vector(DATAWIDTH-1 downto 0); 73 | m_axis_data_tkeep : out std_logic_vector(DATAWIDTH/8 - 1 downto 0); 74 | m_axis_data_tready : in std_logic; 75 | m_axis_data_tlast : out std_logic; 76 | m_axis_data_tvalid : out std_logic; 77 | 78 | -- Global Clock Signal 79 | clk : in std_logic 80 | ); 81 | end component; 82 | 83 | signal m_axis_data_tdata : STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 84 | signal m_axis_data_tkeep : STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 85 | signal m_axis_data_tlast : STD_LOGIC; 86 | signal m_axis_data_tready : STD_LOGIC; 87 | signal m_axis_data_tvalid : STD_LOGIC; 88 | signal s_axis_data_tdata : STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 89 | signal s_axis_data_tkeep : STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 90 | signal s_axis_data_tlast : STD_LOGIC; 91 | signal s_axis_data_tready : STD_LOGIC; 92 | signal s_axis_data_tvalid : STD_LOGIC; 93 | begin 94 | input_buffer: component axis_buffer 95 | generic map ( 96 | DATAWIDTH => DATAWIDTH, 97 | BUFFER_SIZE => 1 98 | ) 99 | port map( 100 | s_axis_data_tdata => static_m_axis_data_tdata, 101 | s_axis_data_tkeep => static_m_axis_data_tkeep, 102 | s_axis_data_tready => static_m_axis_data_tready, 103 | s_axis_data_tlast => static_m_axis_data_tlast, 104 | s_axis_data_tvalid => static_m_axis_data_tvalid, 105 | 106 | m_axis_data_tdata => m_axis_data_tdata, 107 | m_axis_data_tkeep => m_axis_data_tkeep, 108 | m_axis_data_tready => m_axis_data_tready, 109 | m_axis_data_tlast => m_axis_data_tlast, 110 | m_axis_data_tvalid => m_axis_data_tvalid, 111 | 112 | clk => clk 113 | ); 114 | 115 | input_lut_buffer: component axis_lut_buffer 116 | generic map ( 117 | DATAWIDTH => DATAWIDTH 118 | ) 119 | port map( 120 | s_axis_data_tdata => m_axis_data_tdata, 121 | s_axis_data_tkeep => m_axis_data_tkeep, 122 | s_axis_data_tready => m_axis_data_tready, 123 | s_axis_data_tlast => m_axis_data_tlast, 124 | s_axis_data_tvalid => m_axis_data_tvalid, 125 | 126 | m_axis_data_tdata => pr_s_axis_data_tdata, 127 | m_axis_data_tkeep => pr_s_axis_data_tkeep, 128 | m_axis_data_tready => pr_s_axis_data_tready, 129 | m_axis_data_tlast => pr_s_axis_data_tlast, 130 | m_axis_data_tvalid => pr_s_axis_data_tvalid, 131 | 132 | clk => clk 133 | ); 134 | 135 | output_buffer: component axis_buffer 136 | generic map ( 137 | DATAWIDTH => DATAWIDTH, 138 | BUFFER_SIZE => 1 139 | ) 140 | port map( 141 | s_axis_data_tdata => s_axis_data_tdata, 142 | s_axis_data_tkeep => s_axis_data_tkeep, 143 | s_axis_data_tready => s_axis_data_tready, 144 | s_axis_data_tlast => s_axis_data_tlast, 145 | s_axis_data_tvalid => s_axis_data_tvalid, 146 | 147 | m_axis_data_tdata => static_s_axis_data_tdata, 148 | m_axis_data_tkeep => static_s_axis_data_tkeep, 149 | m_axis_data_tready => static_s_axis_data_tready, 150 | m_axis_data_tlast => static_s_axis_data_tlast, 151 | m_axis_data_tvalid => static_s_axis_data_tvalid, 152 | 153 | clk => clk 154 | ); 155 | 156 | output_lut_buffer: component axis_lut_buffer 157 | generic map ( 158 | DATAWIDTH => DATAWIDTH 159 | ) 160 | port map( 161 | s_axis_data_tdata => pr_m_axis_data_tdata, 162 | s_axis_data_tkeep => pr_m_axis_data_tkeep, 163 | s_axis_data_tready => pr_m_axis_data_tready, 164 | s_axis_data_tlast => pr_m_axis_data_tlast, 165 | s_axis_data_tvalid => pr_m_axis_data_tvalid, 166 | 167 | m_axis_data_tdata => s_axis_data_tdata, 168 | m_axis_data_tkeep => s_axis_data_tkeep, 169 | m_axis_data_tready => s_axis_data_tready, 170 | m_axis_data_tlast => s_axis_data_tlast, 171 | m_axis_data_tvalid => s_axis_data_tvalid, 172 | 173 | clk => clk 174 | ); 175 | end architecture rtl; -------------------------------------------------------------------------------- /zedboard_example/zedboard_example.srcs/sources_1/bd/BD_PR_3/hdl/BD_PR_3_wrapper.vhd: -------------------------------------------------------------------------------- 1 | --Copyright 1986-2016 Xilinx, Inc. All Rights Reserved. 2 | ---------------------------------------------------------------------------------- 3 | --Tool Version: Vivado v.2016.4 (lin64) Build 1733598 Wed Dec 14 22:35:42 MST 2016 4 | --Date : Sat Aug 5 18:37:52 2017 5 | --Host : knuff running 64-bit Debian GNU/Linux 9.0 (stretch) 6 | --Command : generate_target BD_PR_3_wrapper.bd 7 | --Design : BD_PR_3_wrapper 8 | --Purpose : IP block netlist 9 | ---------------------------------------------------------------------------------- 10 | library IEEE; 11 | use IEEE.STD_LOGIC_1164.ALL; 12 | library UNISIM; 13 | use UNISIM.VCOMPONENTS.ALL; 14 | entity BD_PR_3_wrapper is 15 | port ( 16 | AXIS_CLK : out STD_LOGIC; 17 | DDR_addr : inout STD_LOGIC_VECTOR ( 14 downto 0 ); 18 | DDR_ba : inout STD_LOGIC_VECTOR ( 2 downto 0 ); 19 | DDR_cas_n : inout STD_LOGIC; 20 | DDR_ck_n : inout STD_LOGIC; 21 | DDR_ck_p : inout STD_LOGIC; 22 | DDR_cke : inout STD_LOGIC; 23 | DDR_cs_n : inout STD_LOGIC; 24 | DDR_dm : inout STD_LOGIC_VECTOR ( 3 downto 0 ); 25 | DDR_dq : inout STD_LOGIC_VECTOR ( 31 downto 0 ); 26 | DDR_dqs_n : inout STD_LOGIC_VECTOR ( 3 downto 0 ); 27 | DDR_dqs_p : inout STD_LOGIC_VECTOR ( 3 downto 0 ); 28 | DDR_odt : inout STD_LOGIC; 29 | DDR_ras_n : inout STD_LOGIC; 30 | DDR_reset_n : inout STD_LOGIC; 31 | DDR_we_n : inout STD_LOGIC; 32 | FIXED_IO_ddr_vrn : inout STD_LOGIC; 33 | FIXED_IO_ddr_vrp : inout STD_LOGIC; 34 | FIXED_IO_mio : inout STD_LOGIC_VECTOR ( 53 downto 0 ); 35 | FIXED_IO_ps_clk : inout STD_LOGIC; 36 | FIXED_IO_ps_porb : inout STD_LOGIC; 37 | FIXED_IO_ps_srstb : inout STD_LOGIC; 38 | m_axis_data_0_tdata : out STD_LOGIC_VECTOR ( 31 downto 0 ); 39 | m_axis_data_0_tkeep : out STD_LOGIC_VECTOR ( 3 downto 0 ); 40 | m_axis_data_0_tlast : out STD_LOGIC; 41 | m_axis_data_0_tready : in STD_LOGIC; 42 | m_axis_data_0_tvalid : out STD_LOGIC; 43 | m_axis_data_1_tdata : out STD_LOGIC_VECTOR ( 31 downto 0 ); 44 | m_axis_data_1_tkeep : out STD_LOGIC_VECTOR ( 3 downto 0 ); 45 | m_axis_data_1_tlast : out STD_LOGIC; 46 | m_axis_data_1_tready : in STD_LOGIC; 47 | m_axis_data_1_tvalid : out STD_LOGIC; 48 | m_axis_data_2_tdata : out STD_LOGIC_VECTOR ( 31 downto 0 ); 49 | m_axis_data_2_tkeep : out STD_LOGIC_VECTOR ( 3 downto 0 ); 50 | m_axis_data_2_tlast : out STD_LOGIC; 51 | m_axis_data_2_tready : in STD_LOGIC; 52 | m_axis_data_2_tvalid : out STD_LOGIC; 53 | s_axis_data_0_tdata : in STD_LOGIC_VECTOR ( 31 downto 0 ); 54 | s_axis_data_0_tkeep : in STD_LOGIC_VECTOR ( 3 downto 0 ); 55 | s_axis_data_0_tlast : in STD_LOGIC; 56 | s_axis_data_0_tready : out STD_LOGIC; 57 | s_axis_data_0_tvalid : in STD_LOGIC; 58 | s_axis_data_1_tdata : in STD_LOGIC_VECTOR ( 31 downto 0 ); 59 | s_axis_data_1_tkeep : in STD_LOGIC_VECTOR ( 3 downto 0 ); 60 | s_axis_data_1_tlast : in STD_LOGIC; 61 | s_axis_data_1_tready : out STD_LOGIC; 62 | s_axis_data_1_tvalid : in STD_LOGIC; 63 | s_axis_data_2_tdata : in STD_LOGIC_VECTOR ( 31 downto 0 ); 64 | s_axis_data_2_tkeep : in STD_LOGIC_VECTOR ( 3 downto 0 ); 65 | s_axis_data_2_tlast : in STD_LOGIC; 66 | s_axis_data_2_tready : out STD_LOGIC; 67 | s_axis_data_2_tvalid : in STD_LOGIC 68 | ); 69 | end BD_PR_3_wrapper; 70 | 71 | architecture STRUCTURE of BD_PR_3_wrapper is 72 | component BD_PR_3 is 73 | port ( 74 | m_axis_data_0_tdata : out STD_LOGIC_VECTOR ( 31 downto 0 ); 75 | m_axis_data_0_tkeep : out STD_LOGIC_VECTOR ( 3 downto 0 ); 76 | m_axis_data_0_tlast : out STD_LOGIC; 77 | m_axis_data_0_tready : in STD_LOGIC; 78 | m_axis_data_0_tvalid : out STD_LOGIC; 79 | m_axis_data_1_tdata : out STD_LOGIC_VECTOR ( 31 downto 0 ); 80 | m_axis_data_1_tkeep : out STD_LOGIC_VECTOR ( 3 downto 0 ); 81 | m_axis_data_1_tlast : out STD_LOGIC; 82 | m_axis_data_1_tready : in STD_LOGIC; 83 | m_axis_data_1_tvalid : out STD_LOGIC; 84 | m_axis_data_2_tdata : out STD_LOGIC_VECTOR ( 31 downto 0 ); 85 | m_axis_data_2_tkeep : out STD_LOGIC_VECTOR ( 3 downto 0 ); 86 | m_axis_data_2_tlast : out STD_LOGIC; 87 | m_axis_data_2_tready : in STD_LOGIC; 88 | m_axis_data_2_tvalid : out STD_LOGIC; 89 | s_axis_data_0_tdata : in STD_LOGIC_VECTOR ( 31 downto 0 ); 90 | s_axis_data_0_tkeep : in STD_LOGIC_VECTOR ( 3 downto 0 ); 91 | s_axis_data_0_tlast : in STD_LOGIC; 92 | s_axis_data_0_tready : out STD_LOGIC; 93 | s_axis_data_0_tvalid : in STD_LOGIC; 94 | s_axis_data_1_tdata : in STD_LOGIC_VECTOR ( 31 downto 0 ); 95 | s_axis_data_1_tkeep : in STD_LOGIC_VECTOR ( 3 downto 0 ); 96 | s_axis_data_1_tlast : in STD_LOGIC; 97 | s_axis_data_1_tready : out STD_LOGIC; 98 | s_axis_data_1_tvalid : in STD_LOGIC; 99 | s_axis_data_2_tdata : in STD_LOGIC_VECTOR ( 31 downto 0 ); 100 | s_axis_data_2_tkeep : in STD_LOGIC_VECTOR ( 3 downto 0 ); 101 | s_axis_data_2_tlast : in STD_LOGIC; 102 | s_axis_data_2_tready : out STD_LOGIC; 103 | s_axis_data_2_tvalid : in STD_LOGIC; 104 | AXIS_CLK : out STD_LOGIC; 105 | DDR_cas_n : inout STD_LOGIC; 106 | DDR_cke : inout STD_LOGIC; 107 | DDR_ck_n : inout STD_LOGIC; 108 | DDR_ck_p : inout STD_LOGIC; 109 | DDR_cs_n : inout STD_LOGIC; 110 | DDR_reset_n : inout STD_LOGIC; 111 | DDR_odt : inout STD_LOGIC; 112 | DDR_ras_n : inout STD_LOGIC; 113 | DDR_we_n : inout STD_LOGIC; 114 | DDR_ba : inout STD_LOGIC_VECTOR ( 2 downto 0 ); 115 | DDR_addr : inout STD_LOGIC_VECTOR ( 14 downto 0 ); 116 | DDR_dm : inout STD_LOGIC_VECTOR ( 3 downto 0 ); 117 | DDR_dq : inout STD_LOGIC_VECTOR ( 31 downto 0 ); 118 | DDR_dqs_n : inout STD_LOGIC_VECTOR ( 3 downto 0 ); 119 | DDR_dqs_p : inout STD_LOGIC_VECTOR ( 3 downto 0 ); 120 | FIXED_IO_mio : inout STD_LOGIC_VECTOR ( 53 downto 0 ); 121 | FIXED_IO_ddr_vrn : inout STD_LOGIC; 122 | FIXED_IO_ddr_vrp : inout STD_LOGIC; 123 | FIXED_IO_ps_srstb : inout STD_LOGIC; 124 | FIXED_IO_ps_clk : inout STD_LOGIC; 125 | FIXED_IO_ps_porb : inout STD_LOGIC 126 | ); 127 | end component BD_PR_3; 128 | begin 129 | BD_PR_3_i: component BD_PR_3 130 | port map ( 131 | AXIS_CLK => AXIS_CLK, 132 | DDR_addr(14 downto 0) => DDR_addr(14 downto 0), 133 | DDR_ba(2 downto 0) => DDR_ba(2 downto 0), 134 | DDR_cas_n => DDR_cas_n, 135 | DDR_ck_n => DDR_ck_n, 136 | DDR_ck_p => DDR_ck_p, 137 | DDR_cke => DDR_cke, 138 | DDR_cs_n => DDR_cs_n, 139 | DDR_dm(3 downto 0) => DDR_dm(3 downto 0), 140 | DDR_dq(31 downto 0) => DDR_dq(31 downto 0), 141 | DDR_dqs_n(3 downto 0) => DDR_dqs_n(3 downto 0), 142 | DDR_dqs_p(3 downto 0) => DDR_dqs_p(3 downto 0), 143 | DDR_odt => DDR_odt, 144 | DDR_ras_n => DDR_ras_n, 145 | DDR_reset_n => DDR_reset_n, 146 | DDR_we_n => DDR_we_n, 147 | FIXED_IO_ddr_vrn => FIXED_IO_ddr_vrn, 148 | FIXED_IO_ddr_vrp => FIXED_IO_ddr_vrp, 149 | FIXED_IO_mio(53 downto 0) => FIXED_IO_mio(53 downto 0), 150 | FIXED_IO_ps_clk => FIXED_IO_ps_clk, 151 | FIXED_IO_ps_porb => FIXED_IO_ps_porb, 152 | FIXED_IO_ps_srstb => FIXED_IO_ps_srstb, 153 | m_axis_data_0_tdata(31 downto 0) => m_axis_data_0_tdata(31 downto 0), 154 | m_axis_data_0_tkeep(3 downto 0) => m_axis_data_0_tkeep(3 downto 0), 155 | m_axis_data_0_tlast => m_axis_data_0_tlast, 156 | m_axis_data_0_tready => m_axis_data_0_tready, 157 | m_axis_data_0_tvalid => m_axis_data_0_tvalid, 158 | m_axis_data_1_tdata(31 downto 0) => m_axis_data_1_tdata(31 downto 0), 159 | m_axis_data_1_tkeep(3 downto 0) => m_axis_data_1_tkeep(3 downto 0), 160 | m_axis_data_1_tlast => m_axis_data_1_tlast, 161 | m_axis_data_1_tready => m_axis_data_1_tready, 162 | m_axis_data_1_tvalid => m_axis_data_1_tvalid, 163 | m_axis_data_2_tdata(31 downto 0) => m_axis_data_2_tdata(31 downto 0), 164 | m_axis_data_2_tkeep(3 downto 0) => m_axis_data_2_tkeep(3 downto 0), 165 | m_axis_data_2_tlast => m_axis_data_2_tlast, 166 | m_axis_data_2_tready => m_axis_data_2_tready, 167 | m_axis_data_2_tvalid => m_axis_data_2_tvalid, 168 | s_axis_data_0_tdata(31 downto 0) => s_axis_data_0_tdata(31 downto 0), 169 | s_axis_data_0_tkeep(3 downto 0) => s_axis_data_0_tkeep(3 downto 0), 170 | s_axis_data_0_tlast => s_axis_data_0_tlast, 171 | s_axis_data_0_tready => s_axis_data_0_tready, 172 | s_axis_data_0_tvalid => s_axis_data_0_tvalid, 173 | s_axis_data_1_tdata(31 downto 0) => s_axis_data_1_tdata(31 downto 0), 174 | s_axis_data_1_tkeep(3 downto 0) => s_axis_data_1_tkeep(3 downto 0), 175 | s_axis_data_1_tlast => s_axis_data_1_tlast, 176 | s_axis_data_1_tready => s_axis_data_1_tready, 177 | s_axis_data_1_tvalid => s_axis_data_1_tvalid, 178 | s_axis_data_2_tdata(31 downto 0) => s_axis_data_2_tdata(31 downto 0), 179 | s_axis_data_2_tkeep(3 downto 0) => s_axis_data_2_tkeep(3 downto 0), 180 | s_axis_data_2_tlast => s_axis_data_2_tlast, 181 | s_axis_data_2_tready => s_axis_data_2_tready, 182 | s_axis_data_2_tvalid => s_axis_data_2_tvalid 183 | ); 184 | end STRUCTURE; 185 | -------------------------------------------------------------------------------- /zedboard_example/zedboard_example.srcs/sources_1/bd/BD_PR_3/BD_PR_3.bxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Composite Fileset 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /pr_script.tcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Björn Gottschall 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | # SOFTWARE. 20 | 21 | 22 | #Do this manually once 23 | #source procs.tcl 24 | 25 | if { [info exists STEP] eq 0 } { 26 | set STEP 0 27 | } 28 | 29 | set pr_base pr_0 30 | set pr_cells { pr_1 pr_2 } 31 | #left, right 32 | set interface_location left 33 | #top, bottom, center, nosplit_top, nosplit_bottom 34 | set interface_strategy nosplit_top 35 | #How many slices at top and bottom will not be used for interface placement 36 | set interface_strategy_trim 4 37 | #every n'th bel gets skipped, 0 or 1 disabled 38 | set interface_strategy_skip 3 39 | 40 | set target_constraints "reloc" 41 | set synth "synth_1" 42 | set impl "impl_1" 43 | #Autorun will source pr_script.tcl automatically after every step, vivado will be more stable 44 | set autorun 1 45 | 46 | 47 | 48 | set script [file normalize [info script]] 49 | set dir [file dirname [file normalize [info script]]] 50 | 51 | 52 | set script [file normalize [info script]] 53 | if { [info exists called_from_autorun] eq 0 } { 54 | set called_from_autorun 0 55 | } 56 | 57 | if { $called_from_autorun eq 0 && $autorun eq 1 } { 58 | puts "Start Autorun" 59 | set STEP 0 60 | } 61 | 62 | if { $STEP eq 0 } { 63 | 64 | if {[synthesize $synth] eq 0} { 65 | return "ERROR: Synthesize" 66 | } 67 | 68 | open_run $synth 69 | 70 | if { [verify_relocateable_pblocks [get_pblocks [get_cells [concat $pr_base $pr_cells]]]] ne 1 } { 71 | return "ERROR: Cells $pr_base and $pr_cells are not in relocateable pblocks" 72 | } 73 | 74 | save_constraints_force $target_constraints isol.xdc 75 | 76 | 77 | set pr_base [get_cells $pr_base] 78 | set boundary_nets [get_boundary_nets $pr_base] 79 | set intf_start [get_nets_start_cells $boundary_nets] 80 | set intf_end [get_nets_end_cells $boundary_nets] 81 | 82 | set pr_input_cells [lsort [get_cells $intf_end -filter [list NAME=~$pr_base/*]]] 83 | set pr_output_cells [lsort [get_cells $intf_start -filter [list NAME =~$pr_base/*]]] 84 | set buffer_output_cells [get_cells $intf_end -filter [list NAME!~$pr_base/*]] 85 | set buffer_input_cells [get_cells $intf_start -filter [list NAME!~$pr_base/*]] 86 | 87 | if { [match_lists $pr_input_cells buffer_input_cells] eq 0 } { 88 | return "ERROR: Interface Cells of $pr_base and connecting cell don't match!" 89 | } 90 | if { [match_lists $pr_output_cells buffer_output_cells] eq 0 } { 91 | return "ERROR: Interface Cells of $pr_base and connecting cell don't match!" 92 | } 93 | 94 | 95 | set buf_cell [get_cells [lsort -unique [get_cells_root [concat $buffer_output_cells $buffer_input_cells]]]] 96 | if { [llength $buf_cell] ne 1 } { 97 | return "ERROR: Only one cell should be connected to PR $pr_base: $buf_cell" 98 | } 99 | 100 | set buf_pblock [get_pblocks [get_property PBLOCK $buf_cell]] 101 | set pr_pblock [get_pblocks [get_property PBLOCK $pr_base]] 102 | 103 | if { [string length $pr_pblock] eq 0 } { 104 | return "ERROR: No pblock found for PR cell $pr_base" 105 | } 106 | 107 | if { [string length $buf_pblock] eq 0 } { 108 | return "ERROR: No pblock found for connecting cell $buf_cell" 109 | } 110 | 111 | set pr_slices [get_list_from_range [get_range_from_pblock $pr_pblock SLICE]] 112 | set buf_slices [get_list_from_range [get_range_from_pblock $buf_pblock SLICE]] 113 | 114 | switch $interface_location { 115 | left { 116 | puts "Try to place Interface on the left of $pr_base" 117 | set pr_pos [lindex [get_cols $pr_slices] 0] 118 | set buf_pos [lindex [get_cols $buf_slices] end] 119 | if { $buf_pos > $pr_pos } { 120 | return "ERROR: PR interface at X${pr_pos} not facing connecting cell interface at X${$buf_pos}" 121 | } 122 | set pr_slices [filter_tiles $pr_slices SLICE ${pr_pos}] 123 | set buf_slices [filter_tiles $buf_slices SLICE ${buf_pos}] 124 | } 125 | right { 126 | puts "Try to place Interface on the right of $pr_base" 127 | set pr_pos [lindex [get_cols $pr_slices] end] 128 | set buf_pos [lindex [get_cols $buf_slices] 0] 129 | if { $pr_pos > $buf_pos } { 130 | return "ERROR: PR interface at X${pr_pos} not facing connecting cell interface at X${$buf_pos}" 131 | } 132 | set pr_slices [filter_tiles $pr_slices SLICE ${pr_pos}] 133 | set buf_slices [filter_tiles $buf_slices SLICE ${buf_pos}] 134 | } 135 | default { 136 | return "ERROR: unknown interface location (left, right): $interface_location" 137 | } 138 | } 139 | 140 | #Interface strategy trim will leave slices at top and bottom free from interface cells 141 | set pr_slices [lrange $pr_slices $interface_strategy_trim [expr [llength $pr_slices] - $interface_strategy_trim]] 142 | set buf_slices [lrange $buf_slices $interface_strategy_trim [expr [llength $buf_slices] - $interface_strategy_trim]] 143 | 144 | #Always sorted from bottom to top 145 | #interface_strategy: 146 | # top starts placement at top 147 | # bottom starts placement at bottom 148 | # center starts placement at center 149 | 150 | 151 | 152 | set slice_count [llength $pr_slices] 153 | set pr_input_slices [get_sites [lrange $pr_slices 0 [expr $slice_count / 2] ]] 154 | set pr_output_slices [get_sites [lrange $pr_slices [expr ($slice_count / 2) + 1] $slice_count]] 155 | 156 | set slice_count [llength $buf_slices] 157 | set buf_input_slices [get_sites [lrange $buf_slices 0 [expr $slice_count / 2]]] 158 | set buf_output_slices [get_sites [lrange $buf_slices [expr ($slice_count / 2) + 1] $slice_count]] 159 | 160 | switch $interface_strategy { 161 | bottom { 162 | set pr_input_slices [lsort $pr_input_slices] 163 | set pr_output_slices [lsort $pr_output_slices] 164 | set buf_input_slices [lsort $buf_input_slices] 165 | set buf_output_slices [lsort $buf_output_slices] 166 | } 167 | top { 168 | #Nothing to do 169 | } 170 | center { 171 | set pr_output_slices [lsort $pr_output_slices] 172 | set buf_output_slices [lsort $buf_output_slices] 173 | } 174 | nosplit_top - 175 | nosplit_bottom { 176 | set pr_input_slices [concat $pr_output_slices $pr_input_slices] 177 | set buf_input_slices [concat $buf_output_slices $buf_input_slices] 178 | set pr_input_cells [concat $pr_output_cells $pr_input_cells] 179 | set buffer_input_cells [concat $buffer_output_cells $buffer_input_cells] 180 | if { $interface_strategy eq "nosplit_bottom" } { 181 | set pr_input_slices [lsort $pr_input_slices] 182 | set buf_input_slices [lsort $buf_input_slices] 183 | } 184 | 185 | } 186 | default { 187 | return "ERROR: unknown interface strategy (top, bottom, center): $interface_strategy" 188 | } 189 | } 190 | 191 | set pr_input_bels [get_bels_lut6 $pr_input_slices] 192 | set pr_output_bels [get_bels_lut6 $pr_output_slices] 193 | 194 | set buf_input_bels [get_bels_lut6 $buf_input_slices] 195 | set buf_output_bels [get_bels_lut6 $buf_output_slices] 196 | 197 | if { $interface_strategy_skip > 1 } { 198 | set to_process [list pr_input_bels pr_output_bels buf_input_bels buf_output_bels] 199 | foreach list_name $to_process { 200 | set skip_list [set $list_name] 201 | set $list_name {} 202 | for {set i 0} {$i < [llength $skip_list]} {incr i} { 203 | if { [expr ($i + 1) % $interface_strategy_skip] != 0 } { 204 | lappend $list_name [lindex $skip_list $i] 205 | } 206 | } 207 | } 208 | } 209 | 210 | 211 | 212 | if { [llength $buffer_input_cells] > [llength $buf_input_bels] } { 213 | return "ERROR: Connecting cell $buf_cell, more input cells than available bels" 214 | } 215 | 216 | if { [llength $pr_input_cells] > [llength $pr_input_bels] } { 217 | return "ERROR: PR cell $pr_base, more input cells than available bels" 218 | } 219 | 220 | relocate_cleanup $pr_base 221 | 222 | #Custom function which can place multiple cells on bels 223 | #opt_design will remove all luts, set them to DONT_TOUCH 224 | 225 | place_cells $buffer_input_cells $buf_input_bels 226 | place_cells $pr_input_cells $pr_input_bels 227 | set_property DONT_TOUCH 1 $pr_input_cells 228 | set_property DONT_TOUCH 1 $buffer_input_cells 229 | 230 | #In case nosplit isn't used we have to do the same for the other half of cells 231 | if { $interface_strategy ne "nosplit_bottom" && $interface_strategy ne "nosplit_top" } { 232 | 233 | if { [llength $buffer_output_cells] > [llength $buf_output_bels] } { 234 | return "ERROR: Connecting cell $buf_cell, more output cells than available bels" 235 | } 236 | 237 | if { [llength $pr_output_cells] > [llength $pr_output_bels] } { 238 | return "ERROR: PR Cell $pr_base, more output pr cells than available bels" 239 | } 240 | 241 | place_cells $pr_output_cells $pr_output_bels 242 | place_cells $buffer_output_cells $buf_output_bels 243 | set_property DONT_TOUCH 1 $pr_output_cells 244 | set_property DONT_TOUCH 1 $buffer_output_cells 245 | } 246 | 247 | 248 | save_constraints_force $target_constraints ${pr_base}_reloc.xdc 249 | 250 | fix_plocs [get_pins_no_clk ${pr_base}/*] 251 | 252 | save_constraints_force $target_constraints ${pr_base}_plocs.xdc 253 | 254 | set_isolated $pr_base 255 | set_isolated $pr_cells 256 | 257 | save_constraints_force $target_constraints isol.xdc 258 | 259 | close_design 260 | 261 | if { $autorun eq 1 } { 262 | incr STEP 263 | set called_from_autorun 1 264 | source -notrace $script 265 | set called_from_autorun 0 266 | return "" 267 | } 268 | } 269 | 270 | if { $STEP eq 1 } { 271 | if { [implement $impl] eq 0} { 272 | return "ERROR: Implementation" 273 | } 274 | 275 | open_run $impl 276 | 277 | set pr_base [get_cells $pr_base] 278 | 279 | set boundary_nets [get_nets_no_clk [get_boundary_nets ${pr_base}]] 280 | 281 | fix_lut_pins $boundary_nets 282 | fix_routes $boundary_nets 283 | 284 | save_constraints_force $target_constraints ${pr_base}_reloc.xdc 285 | 286 | if { $autorun eq 1 } { 287 | incr STEP 288 | set called_from_autorun 1 289 | source -notrace $script 290 | set called_from_autorun 0 291 | return "" 292 | } 293 | } 294 | 295 | if { $STEP eq 2 } { 296 | 297 | if { [synthesize $synth] eq 0} { 298 | return "ERROR: Synthesize" 299 | } 300 | open_run $synth 301 | 302 | set pr_base [get_cells $pr_base] 303 | 304 | foreach cell $pr_cells { 305 | #Does copy boundary nets and their cells to other things: 306 | relocate_cells $pr_base $cell 307 | save_constraints_force $target_constraints ${cell}_reloc.xdc 308 | fix_plocs [get_pins_no_clk ${cell}/*] 309 | save_constraints_force $target_constraints ${cell}_plocs.xdc 310 | } 311 | 312 | #With isolated cells this will mostly fail, the router/placer has problems with placing routes/pins INSIDE the pr (I wonder why) 313 | set_reconfigurable $pr_base 314 | set_reconfigurable $pr_cells 315 | save_constraints_force $target_constraints isol.xdc 316 | 317 | if { [implement $impl] eq 0} { 318 | return "ERROR: Implementation" 319 | } 320 | 321 | open_run $impl 322 | 323 | if { $autorun eq 1 } { 324 | incr STEP 325 | set called_from_autorun 1 326 | source -notrace $script 327 | set called_from_autorun 0 328 | return "" 329 | } 330 | } 331 | 332 | if { $STEP > 2 } { 333 | puts "This is the End!" 334 | } 335 | -------------------------------------------------------------------------------- /relocater/relocater.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Björn Gottschall 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | //This is a Proof of Concept, not clean code! 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "relocater.h" 35 | #include "bitstreams.h" 36 | 37 | 38 | const char SYNC_WORD[] = { '\xAA', '\x99', '\x55', '\x66' }; 39 | const char HEADER_DELIMIT[] = { '\x61', '\x00' }; 40 | const char HEADER_DELIMITER_INCREMENT[] = { '\x01', '\x00' }; 41 | 42 | const char BUS_WIDTH_AUTO_DETECTION_PATTERN[] = { '\xFF', '\xFF', '\xFF', '\xFF', 43 | '\x00', '\x00', '\x00', '\xBB' }; 44 | #define BUS_WIDTH_AUTO_DETECTION_LENGTH 20 * sizeof(char) 45 | #define HEADER_NODE_INDEX_START '\x61' 46 | 47 | 48 | enum command { help, header, patch, create }; 49 | enum command todo = help; 50 | 51 | struct binary_data { 52 | void *data; 53 | size_t length; 54 | }; 55 | 56 | struct header_node { 57 | char index; 58 | struct binary_data value; 59 | struct header_node *next; 60 | }; 61 | 62 | struct header_dump { 63 | struct binary_data bus_width_auto_detection; 64 | struct header_node *nodes; 65 | }; 66 | 67 | 68 | 69 | bool is_string(char *data, size_t length) { 70 | if (length == 0) { 71 | return false; 72 | } 73 | if (data[length-1] != '\x00' ) { 74 | return false; 75 | } 76 | for (int i = 0; i < length-1; i++) { 77 | if (!isprint(data[i])) { 78 | return false; 79 | } 80 | } 81 | return true; 82 | } 83 | 84 | 85 | void fprintf_hd(FILE *stream, void *mem, int size) { 86 | unsigned char *p = (unsigned char *)mem; 87 | for (int i=0;i= far_profile_count) { 133 | fprintf(stderr, "Not enough FAR Addresses in FAR Profile!\n"); 134 | return 1; 135 | } 136 | fprintf(stdout,"Patching FAR Address #%i: ", (far_index+1)); 137 | fprintf_hd(stdout, payload, PACKAGE_SIZE); 138 | fprintf(stdout, " -> "); 139 | fprintf_hd(stdout, (void *) &far_profiles[far_index], PACKAGE_SIZE); 140 | fprintf(stdout, "\n"); 141 | memcpy(payload, (void *) &far_profiles[far_index], PACKAGE_SIZE); 142 | far_index++; 143 | } 144 | if ( todo == header ) { 145 | fprintf(stdout,"FAR Address #%i: ", (far_index+1)); 146 | fprintf_hd(stdout, payload, PACKAGE_SIZE); 147 | fprintf(stdout, "\n"); 148 | far_index++; 149 | } 150 | return 0; 151 | }; 152 | 153 | typedef struct 154 | { 155 | unsigned int type; 156 | unsigned int opcode; 157 | unsigned int register_address; 158 | int (*parse_package) (void *package, void *payload); 159 | } parsetab; 160 | 161 | static const parsetab parsing[] = 162 | { 163 | { TYPE_1, OPCODE_READ, REGISTER_FAR, parse_package_far }, 164 | { TYPE_1, OPCODE_WRITE, REGISTER_FAR, parse_package_far }, 165 | }; 166 | 167 | 168 | void free_header_dump(struct header_dump *dump) { 169 | struct header_node *node,*old_node; 170 | if (dump != NULL) { 171 | node = dump->nodes; 172 | while (node != NULL) { 173 | old_node = node; 174 | node = node->next; 175 | free(old_node); 176 | } 177 | free(dump); 178 | } 179 | 180 | } 181 | 182 | 183 | 184 | struct header_dump *create_header_dump(char *data, size_t length) { 185 | char *sync_pos = kmemmem(data, length, SYNC_WORD, sizeof(SYNC_WORD)); 186 | char *bus_pos = kmemmem(data, length, BUS_WIDTH_AUTO_DETECTION_PATTERN, sizeof(BUS_WIDTH_AUTO_DETECTION_PATTERN)); 187 | char header_index = HEADER_NODE_INDEX_START; 188 | char header_field[2] = { HEADER_NODE_INDEX_START, '\x00' }; 189 | const size_t header_field_size = sizeof(header_field) + sizeof(char); 190 | bool traverse = false; 191 | if (sync_pos == NULL || bus_pos == NULL) { 192 | return NULL; 193 | } 194 | 195 | struct header_dump *dump = malloc(sizeof(struct header_dump)); 196 | dump->nodes = NULL; 197 | dump->bus_width_auto_detection.data = bus_pos; 198 | dump->bus_width_auto_detection.length = BUS_WIDTH_AUTO_DETECTION_LENGTH; 199 | 200 | size_t max_length = (size_t) bus_pos - (size_t) data; 201 | char *pos1 = kmemmem(data, max_length, header_field, sizeof(header_field)); 202 | char *pos2 = NULL; 203 | if (pos1 != NULL) { 204 | traverse = true; 205 | pos1 += header_field_size; 206 | } 207 | 208 | struct header_node *old_node = NULL; 209 | while (traverse) { 210 | struct header_node *new_node = malloc(sizeof(struct header_node)); 211 | new_node->index = header_index; 212 | new_node->next = NULL; 213 | 214 | header_index++; 215 | header_field[0] = header_index; 216 | pos2 = kmemmem(data, max_length, header_field, sizeof(header_field)); 217 | if (pos2 == NULL) { 218 | pos2 = bus_pos; 219 | traverse = false; 220 | } 221 | 222 | new_node->value.data = pos1; 223 | new_node->value.length = (size_t) pos2 - (size_t) pos1; 224 | if (dump->nodes == NULL) { 225 | dump->nodes = new_node; 226 | } else { 227 | old_node->next = new_node; 228 | } 229 | old_node = new_node; 230 | pos1 = (char *) ((size_t) pos2 + header_field_size); 231 | } 232 | return dump; 233 | } 234 | 235 | void output_header_dump(struct header_dump *dump) { 236 | struct header_node *node; 237 | if (dump == NULL) { 238 | fprintf(stderr, "Invalid Header Dump!"); 239 | return; 240 | } 241 | node = dump->nodes; 242 | while (node != NULL) { 243 | fprintf(stdout, "Header %c: ", node->index); 244 | if (is_string(node->value.data, node->value.length)) { 245 | fprintf(stdout, "%s\n", (char *)node->value.data); 246 | } else { 247 | fprintf(stdout, "\n"); 248 | fprintf_hd(stdout, node->value.data, node->value.length); 249 | fprintf(stdout,"\n\n"); 250 | } 251 | 252 | node = node->next; 253 | } 254 | fprintf(stdout, "Bus Width Auto Detection Pattern:\n"); 255 | fprintf_hd(stdout, dump->bus_width_auto_detection.data, dump->bus_width_auto_detection.length); 256 | fprintf(stdout,"\n\n"); 257 | } 258 | 259 | 260 | 261 | void hfree(void * pointer) { 262 | if (pointer != NULL) { 263 | free(pointer); 264 | } 265 | } 266 | 267 | void usage(void) { 268 | printf("Usage: relocater [-d] [-c|-p profile] bitstream\n"); 269 | printf("\t-d\t\tDump Bitstream Header\n"); 270 | printf("\t-c profile\tcreate frame address profile from bitstream\n"); 271 | printf("\t-p profile\tpatch frame address profile to bitstream\n"); 272 | printf("\t-h\t\tshow this help page\n"); 273 | } 274 | 275 | int main(int argc, char **argv) { 276 | struct binary_data file_buffer; 277 | struct binary_data bitstream; 278 | struct binary_data far_file; 279 | far_file.data = NULL; 280 | file_buffer.data=NULL; 281 | FILE *fp; 282 | struct header_dump *dump; 283 | char *frame_profile_filename = NULL; 284 | char *bitstream_filename = NULL; 285 | int c; 286 | 287 | 288 | if (argc < 2) { 289 | goto usage; 290 | } 291 | 292 | while ((c = getopt(argc, argv, "hdc:p:")) != -1) { 293 | switch (c) { 294 | case 'd': 295 | todo = header; 296 | break; 297 | case 'p': 298 | todo = patch; 299 | frame_profile_filename = strdup(optarg); 300 | break; 301 | case 'c': 302 | todo = create; 303 | frame_profile_filename = strdup(optarg); 304 | break; 305 | case '?': 306 | todo = help; 307 | goto usage; 308 | break; 309 | case 'h': 310 | todo = help; 311 | goto usage; 312 | break; 313 | break; 314 | 315 | default: 316 | printf("?? getopt returned character code 0%o ??\n", c); 317 | } 318 | } 319 | 320 | if (todo == help) { 321 | goto usage; 322 | } 323 | 324 | if (optind >= argc) { 325 | fprintf(stderr,"No Bitstream provided!\n"); 326 | goto usage; 327 | } 328 | 329 | bitstream_filename = strdup(argv[optind]); 330 | 331 | if( access( bitstream_filename, W_OK ) == -1 ) { 332 | fprintf(stderr, "Bitstream %s not found!\n",bitstream_filename); 333 | goto error_early; 334 | } 335 | 336 | struct stat info; 337 | 338 | if (todo == patch) { 339 | if( access( frame_profile_filename, R_OK ) == -1 ) { 340 | fprintf(stderr, "Frame address profile %s not found!\n",bitstream_filename); 341 | goto error_early; 342 | } 343 | stat(frame_profile_filename, &info); 344 | far_file.length = info.st_size; 345 | fp = fopen(frame_profile_filename, "r+b"); 346 | if (fp == NULL) { 347 | fprintf(stderr, "Cannot open far profile %s!\n", frame_profile_filename); 348 | goto error_early; 349 | } 350 | far_file.length = info.st_size; 351 | if (far_file.length % 4 != 0) { 352 | fprintf(stderr, "Incorrect FAR Profile!\n"); 353 | goto error; 354 | } 355 | far_file.data = (char *) malloc (far_file.length * sizeof(char)); 356 | if (far_file.data == NULL) { 357 | fprintf(stderr, "Could not allocate memory!\n"); 358 | goto error; 359 | } 360 | if ( fread(far_file.data, far_file.length, 1, fp) != 1 ) { 361 | fprintf(stderr, "Could not read whole bitstream!\n"); 362 | goto error; 363 | } 364 | fclose(fp); 365 | far_profile_count = far_file.length / sizeof(struct far_profile); 366 | far_profiles = (struct far_profile *)far_file.data; 367 | fprintf(stdout, "%u FAR Addresses found for patching!\n", far_profile_count); 368 | } 369 | 370 | 371 | stat(bitstream_filename, &info); 372 | 373 | fp = fopen(bitstream_filename, "r+b"); 374 | if (fp == NULL) { 375 | fprintf(stderr, "Cannot open bitstream %s!\n", bitstream_filename); 376 | goto error_early; 377 | } 378 | file_buffer.length = info.st_size; 379 | file_buffer.data = (char *) malloc (file_buffer.length * sizeof(char)); 380 | if (file_buffer.data == NULL) { 381 | fprintf(stderr, "Could not allocate memory!\n"); 382 | goto error; 383 | } 384 | if ( fread(file_buffer.data, file_buffer.length, 1, fp) != 1 ) { 385 | fprintf(stderr, "Could not read whole bitstream!\n"); 386 | goto error; 387 | } 388 | fclose(fp); 389 | 390 | 391 | dump = create_header_dump(file_buffer.data, file_buffer.length); 392 | 393 | if (dump == NULL) { 394 | fprintf(stderr, "Invalid Bitstream Header!\n"); 395 | goto error; 396 | } 397 | 398 | if (todo == header) { 399 | output_header_dump(dump); 400 | } 401 | 402 | bitstream.data = kmemmem(file_buffer.data, file_buffer.length, SYNC_WORD, sizeof(SYNC_WORD)); 403 | if (bitstream.data == NULL) { 404 | fprintf(stderr, "Invalid Bitstream Header!\n"); 405 | goto error; 406 | } 407 | bitstream.data += sizeof(SYNC_WORD); 408 | bitstream.length = file_buffer.length - ((size_t) bitstream.data - (size_t) file_buffer.data); 409 | 410 | 411 | unsigned int processed_length = 0; 412 | unsigned int package_length = 0; 413 | const unsigned int parsing_size = sizeof(parsing) / sizeof(parsing[0]); 414 | struct BITSTREAM_PACKAGE package; 415 | while (processed_length < bitstream.length) { 416 | if (processed_length + PACKAGE_SIZE > bitstream.length) { 417 | fprintf(stderr, "Unexpected bitstream ending!"); 418 | goto error; 419 | } 420 | package = create_package(bitstream.data); 421 | 422 | for (int i = 0; i < parsing_size; i++) { 423 | if (parsing[i].type == package.type && 424 | parsing[i].opcode == package.opcode && 425 | parsing[i].register_address == package.register_address) { 426 | if (parsing[i].parse_package((void *) bitstream.data, (void *) ((size_t) bitstream.data + PACKAGE_SIZE))) { 427 | fprintf(stderr,"Error occured while parsing bitstream package!\n"); 428 | goto error; 429 | } 430 | break; 431 | } 432 | } 433 | package_length = (1 + package.word_count) * PACKAGE_SIZE; 434 | processed_length += package_length; 435 | bitstream.data = (void *) ((size_t) bitstream.data + package_length); 436 | } 437 | 438 | if ( todo == create ) { 439 | fp = fopen(frame_profile_filename, "w+b"); 440 | if (fp == NULL) { 441 | fprintf(stderr, "Cannot open FAR profile file %s!\n", frame_profile_filename); 442 | goto error; 443 | } 444 | if ( fwrite((void *)far_profiles, far_profile_count * sizeof(struct far_profile), 1, fp) != 1 ) { 445 | fprintf(stderr, "Could not write FAR profile!\n"); 446 | goto error; 447 | } 448 | fclose(fp); 449 | fprintf(stdout, "FAR Profile saved to %s\n", frame_profile_filename); 450 | } 451 | 452 | if ( todo == patch ) { 453 | if (far_index != far_profile_count) { 454 | fprintf(stderr,"Not all FAR Addresses from profile were patched. Will not save bitstream!\n"); 455 | goto error; 456 | } 457 | fp = fopen(bitstream_filename, "w+b"); 458 | if (fp == NULL) { 459 | fprintf(stderr, "Cannot open bitstream file %s!\n", bitstream_filename); 460 | goto error; 461 | } 462 | if ( fwrite(file_buffer.data, file_buffer.length, 1, fp) != 1 ) { 463 | fprintf(stderr, "Could not write bitstream file!\n"); 464 | goto error; 465 | } 466 | fclose(fp); 467 | fprintf(stdout, "Bitstream saved to %s\n", bitstream_filename); 468 | } 469 | 470 | 471 | done: 472 | free_header_dump(dump); 473 | hfree(file_buffer.data); 474 | hfree(far_file.data); 475 | hfree(frame_profile_filename); 476 | hfree(bitstream_filename); 477 | hfree(far_profiles); 478 | exit(EXIT_SUCCESS); 479 | 480 | error: 481 | hfree(far_profiles); 482 | free_header_dump(dump); 483 | hfree(file_buffer.data); 484 | hfree(far_file.data); 485 | error_early: 486 | hfree(frame_profile_filename); 487 | hfree(bitstream_filename); 488 | exit(EXIT_FAILURE); 489 | 490 | usage: 491 | usage(); 492 | hfree(frame_profile_filename); 493 | hfree(bitstream_filename); 494 | exit(EXIT_SUCCESS); 495 | } 496 | -------------------------------------------------------------------------------- /zedboard_example/zedboard_example.srcs/sources_1/imports/sources_1/imports/new/wrapper.vhd: -------------------------------------------------------------------------------- 1 | library IEEE; 2 | use IEEE.STD_LOGIC_1164.ALL; 3 | 4 | entity wrapper is 5 | generic ( 6 | DATAWIDTH : integer := 32 7 | ); 8 | port ( 9 | DDR_addr : inout STD_LOGIC_VECTOR ( 14 downto 0 ); 10 | DDR_ba : inout STD_LOGIC_VECTOR ( 2 downto 0 ); 11 | DDR_cas_n : inout STD_LOGIC; 12 | DDR_ck_n : inout STD_LOGIC; 13 | DDR_ck_p : inout STD_LOGIC; 14 | DDR_cke : inout STD_LOGIC; 15 | DDR_cs_n : inout STD_LOGIC; 16 | DDR_dm : inout STD_LOGIC_VECTOR ( 3 downto 0 ); 17 | DDR_dq : inout STD_LOGIC_VECTOR ( 31 downto 0 ); 18 | DDR_dqs_n : inout STD_LOGIC_VECTOR ( 3 downto 0 ); 19 | DDR_dqs_p : inout STD_LOGIC_VECTOR ( 3 downto 0 ); 20 | DDR_odt : inout STD_LOGIC; 21 | DDR_ras_n : inout STD_LOGIC; 22 | DDR_reset_n : inout STD_LOGIC; 23 | DDR_we_n : inout STD_LOGIC; 24 | FIXED_IO_ddr_vrn : inout STD_LOGIC; 25 | FIXED_IO_ddr_vrp : inout STD_LOGIC; 26 | FIXED_IO_mio : inout STD_LOGIC_VECTOR ( 53 downto 0 ); 27 | FIXED_IO_ps_clk : inout STD_LOGIC; 28 | FIXED_IO_ps_porb : inout STD_LOGIC; 29 | FIXED_IO_ps_srstb : inout STD_LOGIC 30 | ); 31 | end wrapper; 32 | 33 | architecture rtl of wrapper is 34 | component BD_PR_3 is 35 | port ( 36 | DDR_addr : inout STD_LOGIC_VECTOR ( 14 downto 0 ); 37 | DDR_ba : inout STD_LOGIC_VECTOR ( 2 downto 0 ); 38 | DDR_cas_n : inout STD_LOGIC; 39 | DDR_ck_n : inout STD_LOGIC; 40 | DDR_ck_p : inout STD_LOGIC; 41 | DDR_cke : inout STD_LOGIC; 42 | DDR_cs_n : inout STD_LOGIC; 43 | DDR_dm : inout STD_LOGIC_VECTOR ( 3 downto 0 ); 44 | DDR_dq : inout STD_LOGIC_VECTOR ( 31 downto 0 ); 45 | DDR_dqs_n : inout STD_LOGIC_VECTOR ( 3 downto 0 ); 46 | DDR_dqs_p : inout STD_LOGIC_VECTOR ( 3 downto 0 ); 47 | DDR_odt : inout STD_LOGIC; 48 | DDR_ras_n : inout STD_LOGIC; 49 | DDR_reset_n : inout STD_LOGIC; 50 | DDR_we_n : inout STD_LOGIC; 51 | FIXED_IO_ddr_vrn : inout STD_LOGIC; 52 | FIXED_IO_ddr_vrp : inout STD_LOGIC; 53 | FIXED_IO_mio : inout STD_LOGIC_VECTOR ( 53 downto 0 ); 54 | FIXED_IO_ps_clk : inout STD_LOGIC; 55 | FIXED_IO_ps_porb : inout STD_LOGIC; 56 | FIXED_IO_ps_srstb : inout STD_LOGIC; 57 | 58 | m_axis_data_0_tdata : inout STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 59 | m_axis_data_0_tkeep : inout STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 60 | m_axis_data_0_tlast : inout STD_LOGIC; 61 | m_axis_data_0_tready : inout STD_LOGIC; 62 | m_axis_data_0_tvalid : inout STD_LOGIC; 63 | s_axis_data_0_tdata : inout STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 64 | s_axis_data_0_tkeep : inout STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 65 | s_axis_data_0_tlast : inout STD_LOGIC; 66 | s_axis_data_0_tready : inout STD_LOGIC; 67 | s_axis_data_0_tvalid : inout STD_LOGIC; 68 | 69 | m_axis_data_1_tdata : inout STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 70 | m_axis_data_1_tkeep : inout STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 71 | m_axis_data_1_tlast : inout STD_LOGIC; 72 | m_axis_data_1_tready : inout STD_LOGIC; 73 | m_axis_data_1_tvalid : inout STD_LOGIC; 74 | s_axis_data_1_tdata : inout STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 75 | s_axis_data_1_tkeep : inout STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 76 | s_axis_data_1_tlast : inout STD_LOGIC; 77 | s_axis_data_1_tready : inout STD_LOGIC; 78 | s_axis_data_1_tvalid : inout STD_LOGIC; 79 | 80 | m_axis_data_2_tdata : inout STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 81 | m_axis_data_2_tkeep : inout STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 82 | m_axis_data_2_tlast : inout STD_LOGIC; 83 | m_axis_data_2_tready : inout STD_LOGIC; 84 | m_axis_data_2_tvalid : inout STD_LOGIC; 85 | s_axis_data_2_tdata : inout STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 86 | s_axis_data_2_tkeep : inout STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 87 | s_axis_data_2_tlast : inout STD_LOGIC; 88 | s_axis_data_2_tready : inout STD_LOGIC; 89 | s_axis_data_2_tvalid : inout STD_LOGIC; 90 | 91 | AXIS_CLK : buffer STD_LOGIC 92 | ); 93 | end component; 94 | 95 | component pr_axis_buffer is 96 | generic ( 97 | DATAWIDTH : integer := DATAWIDTH 98 | ); 99 | port ( 100 | static_m_axis_data_tdata : in std_logic_vector(DATAWIDTH-1 downto 0); 101 | static_m_axis_data_tkeep : in std_logic_vector(DATAWIDTH/8 - 1 downto 0); 102 | static_m_axis_data_tready : out std_logic; 103 | static_m_axis_data_tlast : in std_logic; 104 | static_m_axis_data_tvalid : in std_logic; 105 | pr_m_axis_data_tdata : in std_logic_vector(DATAWIDTH-1 downto 0); 106 | pr_m_axis_data_tkeep : in std_logic_vector(DATAWIDTH/8 - 1 downto 0); 107 | pr_m_axis_data_tready : out std_logic; 108 | pr_m_axis_data_tlast : in std_logic; 109 | pr_m_axis_data_tvalid : in std_logic; 110 | 111 | 112 | static_s_axis_data_tdata : out std_logic_vector(DATAWIDTH-1 downto 0); 113 | static_s_axis_data_tkeep : out std_logic_vector(DATAWIDTH/8 - 1 downto 0); 114 | static_s_axis_data_tready : in std_logic; 115 | static_s_axis_data_tlast : out std_logic; 116 | static_s_axis_data_tvalid : out std_logic; 117 | pr_s_axis_data_tdata : out std_logic_vector(DATAWIDTH-1 downto 0); 118 | pr_s_axis_data_tkeep : out std_logic_vector(DATAWIDTH/8 - 1 downto 0); 119 | pr_s_axis_data_tready : in std_logic; 120 | pr_s_axis_data_tlast : out std_logic; 121 | pr_s_axis_data_tvalid : out std_logic; 122 | 123 | -- Global Clock Signal 124 | clk : in std_logic 125 | ); 126 | end component; 127 | 128 | 129 | component pr_axis is 130 | generic ( 131 | DATAWIDTH : integer := DATAWIDTH 132 | ); 133 | port ( 134 | s_axis_data_tdata : in std_logic_vector(DATAWIDTH-1 downto 0); 135 | s_axis_data_tkeep : in std_logic_vector(DATAWIDTH/8 - 1 downto 0); 136 | s_axis_data_tready : out std_logic; 137 | s_axis_data_tlast : in std_logic; 138 | s_axis_data_tvalid : in std_logic; 139 | 140 | m_axis_data_tdata : out std_logic_vector(DATAWIDTH-1 downto 0); 141 | m_axis_data_tkeep : out std_logic_vector(DATAWIDTH/8 - 1 downto 0); 142 | m_axis_data_tready : in std_logic; 143 | m_axis_data_tlast : out std_logic; 144 | m_axis_data_tvalid : out std_logic; 145 | 146 | -- Global Clock Signal 147 | clk : in std_logic 148 | ); 149 | end component; 150 | 151 | 152 | signal static_m_axis_data_0_tdata : STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 153 | signal static_m_axis_data_0_tkeep : STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 154 | signal static_m_axis_data_0_tlast : STD_LOGIC; 155 | signal static_m_axis_data_0_tready : STD_LOGIC; 156 | signal static_m_axis_data_0_tvalid : STD_LOGIC; 157 | signal static_s_axis_data_0_tdata : STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 158 | signal static_s_axis_data_0_tkeep : STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 159 | signal static_s_axis_data_0_tlast : STD_LOGIC; 160 | signal static_s_axis_data_0_tready : STD_LOGIC; 161 | signal static_s_axis_data_0_tvalid : STD_LOGIC; 162 | 163 | signal pr_m_axis_data_0_tdata : STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 164 | signal pr_m_axis_data_0_tkeep : STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 165 | signal pr_m_axis_data_0_tlast : STD_LOGIC; 166 | signal pr_m_axis_data_0_tready : STD_LOGIC; 167 | signal pr_m_axis_data_0_tvalid : STD_LOGIC; 168 | signal pr_s_axis_data_0_tdata : STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 169 | signal pr_s_axis_data_0_tkeep : STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 170 | signal pr_s_axis_data_0_tlast : STD_LOGIC; 171 | signal pr_s_axis_data_0_tready : STD_LOGIC; 172 | signal pr_s_axis_data_0_tvalid : STD_LOGIC; 173 | 174 | signal static_m_axis_data_1_tdata : STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 175 | signal static_m_axis_data_1_tkeep : STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 176 | signal static_m_axis_data_1_tlast : STD_LOGIC; 177 | signal static_m_axis_data_1_tready : STD_LOGIC; 178 | signal static_m_axis_data_1_tvalid : STD_LOGIC; 179 | signal static_s_axis_data_1_tdata : STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 180 | signal static_s_axis_data_1_tkeep : STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 181 | signal static_s_axis_data_1_tlast : STD_LOGIC; 182 | signal static_s_axis_data_1_tready : STD_LOGIC; 183 | signal static_s_axis_data_1_tvalid : STD_LOGIC; 184 | 185 | signal pr_m_axis_data_1_tdata : STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 186 | signal pr_m_axis_data_1_tkeep : STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 187 | signal pr_m_axis_data_1_tlast : STD_LOGIC; 188 | signal pr_m_axis_data_1_tready : STD_LOGIC; 189 | signal pr_m_axis_data_1_tvalid : STD_LOGIC; 190 | signal pr_s_axis_data_1_tdata : STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 191 | signal pr_s_axis_data_1_tkeep : STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 192 | signal pr_s_axis_data_1_tlast : STD_LOGIC; 193 | signal pr_s_axis_data_1_tready : STD_LOGIC; 194 | signal pr_s_axis_data_1_tvalid : STD_LOGIC; 195 | 196 | signal static_m_axis_data_2_tdata : STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 197 | signal static_m_axis_data_2_tkeep : STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 198 | signal static_m_axis_data_2_tlast : STD_LOGIC; 199 | signal static_m_axis_data_2_tready : STD_LOGIC; 200 | signal static_m_axis_data_2_tvalid : STD_LOGIC; 201 | signal static_s_axis_data_2_tdata : STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 202 | signal static_s_axis_data_2_tkeep : STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 203 | signal static_s_axis_data_2_tlast : STD_LOGIC; 204 | signal static_s_axis_data_2_tready : STD_LOGIC; 205 | signal static_s_axis_data_2_tvalid : STD_LOGIC; 206 | 207 | signal pr_m_axis_data_2_tdata : STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 208 | signal pr_m_axis_data_2_tkeep : STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 209 | signal pr_m_axis_data_2_tlast : STD_LOGIC; 210 | signal pr_m_axis_data_2_tready : STD_LOGIC; 211 | signal pr_m_axis_data_2_tvalid : STD_LOGIC; 212 | signal pr_s_axis_data_2_tdata : STD_LOGIC_VECTOR ( DATAWIDTH - 1 downto 0 ); 213 | signal pr_s_axis_data_2_tkeep : STD_LOGIC_VECTOR ( DATAWIDTH/8 - 1 downto 0 ); 214 | signal pr_s_axis_data_2_tlast : STD_LOGIC; 215 | signal pr_s_axis_data_2_tready : STD_LOGIC; 216 | signal pr_s_axis_data_2_tvalid : STD_LOGIC; 217 | 218 | signal clk : STD_LOGIC; 219 | begin 220 | 221 | 222 | block_design: component BD_PR_3 223 | port map( 224 | DDR_addr(14 downto 0) => DDR_addr(14 downto 0), 225 | DDR_ba(2 downto 0) => DDR_ba(2 downto 0), 226 | DDR_cas_n => DDR_cas_n, 227 | DDR_ck_n => DDR_ck_n, 228 | DDR_ck_p => DDR_ck_p, 229 | DDR_cke => DDR_cke, 230 | DDR_cs_n => DDR_cs_n, 231 | DDR_dm(3 downto 0) => DDR_dm(3 downto 0), 232 | DDR_dq(31 downto 0) => DDR_dq(31 downto 0), 233 | DDR_dqs_n(3 downto 0) => DDR_dqs_n(3 downto 0), 234 | DDR_dqs_p(3 downto 0) => DDR_dqs_p(3 downto 0), 235 | DDR_odt => DDR_odt, 236 | DDR_ras_n => DDR_ras_n, 237 | DDR_reset_n => DDR_reset_n, 238 | DDR_we_n => DDR_we_n, 239 | FIXED_IO_ddr_vrn => FIXED_IO_ddr_vrn, 240 | FIXED_IO_ddr_vrp => FIXED_IO_ddr_vrp, 241 | FIXED_IO_mio(53 downto 0) => FIXED_IO_mio(53 downto 0), 242 | FIXED_IO_ps_clk => FIXED_IO_ps_clk, 243 | FIXED_IO_ps_porb => FIXED_IO_ps_porb, 244 | FIXED_IO_ps_srstb => FIXED_IO_ps_srstb, 245 | 246 | m_axis_data_0_tdata => static_m_axis_data_0_tdata, 247 | m_axis_data_0_tkeep => static_m_axis_data_0_tkeep, 248 | m_axis_data_0_tlast => static_m_axis_data_0_tlast, 249 | m_axis_data_0_tready => static_m_axis_data_0_tready, 250 | m_axis_data_0_tvalid => static_m_axis_data_0_tvalid, 251 | s_axis_data_0_tdata => static_s_axis_data_0_tdata, 252 | 253 | s_axis_data_0_tkeep => static_s_axis_data_0_tkeep, 254 | s_axis_data_0_tlast => static_s_axis_data_0_tlast, 255 | s_axis_data_0_tready => static_s_axis_data_0_tready, 256 | s_axis_data_0_tvalid => static_s_axis_data_0_tvalid, 257 | 258 | m_axis_data_1_tdata => static_m_axis_data_1_tdata, 259 | m_axis_data_1_tkeep => static_m_axis_data_1_tkeep, 260 | m_axis_data_1_tlast => static_m_axis_data_1_tlast, 261 | m_axis_data_1_tready => static_m_axis_data_1_tready, 262 | m_axis_data_1_tvalid => static_m_axis_data_1_tvalid, 263 | s_axis_data_1_tdata => static_s_axis_data_1_tdata, 264 | 265 | s_axis_data_1_tkeep => static_s_axis_data_1_tkeep, 266 | s_axis_data_1_tlast => static_s_axis_data_1_tlast, 267 | s_axis_data_1_tready => static_s_axis_data_1_tready, 268 | s_axis_data_1_tvalid => static_s_axis_data_1_tvalid, 269 | 270 | m_axis_data_2_tdata => static_m_axis_data_2_tdata, 271 | m_axis_data_2_tkeep => static_m_axis_data_2_tkeep, 272 | m_axis_data_2_tlast => static_m_axis_data_2_tlast, 273 | m_axis_data_2_tready => static_m_axis_data_2_tready, 274 | m_axis_data_2_tvalid => static_m_axis_data_2_tvalid, 275 | s_axis_data_2_tdata => static_s_axis_data_2_tdata, 276 | 277 | s_axis_data_2_tkeep => static_s_axis_data_2_tkeep, 278 | s_axis_data_2_tlast => static_s_axis_data_2_tlast, 279 | s_axis_data_2_tready => static_s_axis_data_2_tready, 280 | s_axis_data_2_tvalid => static_s_axis_data_2_tvalid, 281 | 282 | AXIS_CLK => clk 283 | ); 284 | 285 | 286 | pr_0_buffer: component pr_axis_buffer 287 | port map ( 288 | static_m_axis_data_tdata => static_m_axis_data_0_tdata, 289 | static_m_axis_data_tkeep => static_m_axis_data_0_tkeep, 290 | static_m_axis_data_tready => static_m_axis_data_0_tready, 291 | static_m_axis_data_tlast => static_m_axis_data_0_tlast, 292 | static_m_axis_data_tvalid => static_m_axis_data_0_tvalid, 293 | 294 | pr_m_axis_data_tdata => pr_m_axis_data_0_tdata, 295 | pr_m_axis_data_tkeep => pr_m_axis_data_0_tkeep, 296 | pr_m_axis_data_tready => pr_m_axis_data_0_tready, 297 | pr_m_axis_data_tlast => pr_m_axis_data_0_tlast, 298 | pr_m_axis_data_tvalid => pr_m_axis_data_0_tvalid, 299 | 300 | 301 | static_s_axis_data_tdata => static_s_axis_data_0_tdata, 302 | static_s_axis_data_tkeep => static_s_axis_data_0_tkeep, 303 | static_s_axis_data_tready => static_s_axis_data_0_tready, 304 | static_s_axis_data_tlast => static_s_axis_data_0_tlast, 305 | static_s_axis_data_tvalid => static_s_axis_data_0_tvalid, 306 | pr_s_axis_data_tdata => pr_s_axis_data_0_tdata, 307 | pr_s_axis_data_tkeep => pr_s_axis_data_0_tkeep, 308 | pr_s_axis_data_tready => pr_s_axis_data_0_tready, 309 | pr_s_axis_data_tlast => pr_s_axis_data_0_tlast, 310 | pr_s_axis_data_tvalid => pr_s_axis_data_0_tvalid, 311 | 312 | clk => clk 313 | ); 314 | 315 | pr_1_buffer: component pr_axis_buffer 316 | port map ( 317 | static_m_axis_data_tdata => static_m_axis_data_1_tdata, 318 | static_m_axis_data_tkeep => static_m_axis_data_1_tkeep, 319 | static_m_axis_data_tready => static_m_axis_data_1_tready, 320 | static_m_axis_data_tlast => static_m_axis_data_1_tlast, 321 | static_m_axis_data_tvalid => static_m_axis_data_1_tvalid, 322 | 323 | pr_m_axis_data_tdata => pr_m_axis_data_1_tdata, 324 | pr_m_axis_data_tkeep => pr_m_axis_data_1_tkeep, 325 | pr_m_axis_data_tready => pr_m_axis_data_1_tready, 326 | pr_m_axis_data_tlast => pr_m_axis_data_1_tlast, 327 | pr_m_axis_data_tvalid => pr_m_axis_data_1_tvalid, 328 | 329 | 330 | static_s_axis_data_tdata => static_s_axis_data_1_tdata, 331 | static_s_axis_data_tkeep => static_s_axis_data_1_tkeep, 332 | static_s_axis_data_tready => static_s_axis_data_1_tready, 333 | static_s_axis_data_tlast => static_s_axis_data_1_tlast, 334 | static_s_axis_data_tvalid => static_s_axis_data_1_tvalid, 335 | pr_s_axis_data_tdata => pr_s_axis_data_1_tdata, 336 | pr_s_axis_data_tkeep => pr_s_axis_data_1_tkeep, 337 | pr_s_axis_data_tready => pr_s_axis_data_1_tready, 338 | pr_s_axis_data_tlast => pr_s_axis_data_1_tlast, 339 | pr_s_axis_data_tvalid => pr_s_axis_data_1_tvalid, 340 | 341 | clk => clk 342 | ); 343 | 344 | 345 | pr_2_buffer: component pr_axis_buffer 346 | port map ( 347 | static_m_axis_data_tdata => static_m_axis_data_2_tdata, 348 | static_m_axis_data_tkeep => static_m_axis_data_2_tkeep, 349 | static_m_axis_data_tready => static_m_axis_data_2_tready, 350 | static_m_axis_data_tlast => static_m_axis_data_2_tlast, 351 | static_m_axis_data_tvalid => static_m_axis_data_2_tvalid, 352 | 353 | pr_m_axis_data_tdata => pr_m_axis_data_2_tdata, 354 | pr_m_axis_data_tkeep => pr_m_axis_data_2_tkeep, 355 | pr_m_axis_data_tready => pr_m_axis_data_2_tready, 356 | pr_m_axis_data_tlast => pr_m_axis_data_2_tlast, 357 | pr_m_axis_data_tvalid => pr_m_axis_data_2_tvalid, 358 | 359 | 360 | static_s_axis_data_tdata => static_s_axis_data_2_tdata, 361 | static_s_axis_data_tkeep => static_s_axis_data_2_tkeep, 362 | static_s_axis_data_tready => static_s_axis_data_2_tready, 363 | static_s_axis_data_tlast => static_s_axis_data_2_tlast, 364 | static_s_axis_data_tvalid => static_s_axis_data_2_tvalid, 365 | pr_s_axis_data_tdata => pr_s_axis_data_2_tdata, 366 | pr_s_axis_data_tkeep => pr_s_axis_data_2_tkeep, 367 | pr_s_axis_data_tready => pr_s_axis_data_2_tready, 368 | pr_s_axis_data_tlast => pr_s_axis_data_2_tlast, 369 | pr_s_axis_data_tvalid => pr_s_axis_data_2_tvalid, 370 | 371 | clk => clk 372 | ); 373 | 374 | 375 | pr_0 : component pr_axis 376 | port map ( 377 | s_axis_data_tdata => pr_s_axis_data_0_tdata, 378 | s_axis_data_tkeep => pr_s_axis_data_0_tkeep, 379 | s_axis_data_tready => pr_s_axis_data_0_tready, 380 | s_axis_data_tlast => pr_s_axis_data_0_tlast, 381 | s_axis_data_tvalid => pr_s_axis_data_0_tvalid, 382 | 383 | m_axis_data_tdata => pr_m_axis_data_0_tdata, 384 | m_axis_data_tkeep => pr_m_axis_data_0_tkeep, 385 | m_axis_data_tready => pr_m_axis_data_0_tready, 386 | m_axis_data_tlast => pr_m_axis_data_0_tlast, 387 | m_axis_data_tvalid => pr_m_axis_data_0_tvalid, 388 | 389 | clk => clk 390 | ); 391 | 392 | pr_1 : component pr_axis 393 | port map ( 394 | s_axis_data_tdata => pr_s_axis_data_1_tdata, 395 | s_axis_data_tkeep => pr_s_axis_data_1_tkeep, 396 | s_axis_data_tready => pr_s_axis_data_1_tready, 397 | s_axis_data_tlast => pr_s_axis_data_1_tlast, 398 | s_axis_data_tvalid => pr_s_axis_data_1_tvalid, 399 | 400 | m_axis_data_tdata => pr_m_axis_data_1_tdata, 401 | m_axis_data_tkeep => pr_m_axis_data_1_tkeep, 402 | m_axis_data_tready => pr_m_axis_data_1_tready, 403 | m_axis_data_tlast => pr_m_axis_data_1_tlast, 404 | m_axis_data_tvalid => pr_m_axis_data_1_tvalid, 405 | 406 | clk => clk 407 | ); 408 | 409 | pr_2 : component pr_axis 410 | port map ( 411 | s_axis_data_tdata => pr_s_axis_data_2_tdata, 412 | s_axis_data_tkeep => pr_s_axis_data_2_tkeep, 413 | s_axis_data_tready => pr_s_axis_data_2_tready, 414 | s_axis_data_tlast => pr_s_axis_data_2_tlast, 415 | s_axis_data_tvalid => pr_s_axis_data_2_tvalid, 416 | 417 | m_axis_data_tdata => pr_m_axis_data_2_tdata, 418 | m_axis_data_tkeep => pr_m_axis_data_2_tkeep, 419 | m_axis_data_tready => pr_m_axis_data_2_tready, 420 | m_axis_data_tlast => pr_m_axis_data_2_tlast, 421 | m_axis_data_tvalid => pr_m_axis_data_2_tvalid, 422 | 423 | clk => clk 424 | ); 425 | 426 | end architecture rtl; -------------------------------------------------------------------------------- /zedboard_example/zedboard_example.xpr: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 156 | 157 | 158 | 159 | 160 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 205 | 206 | 207 | 208 | 211 | 212 | 213 | 214 | 217 | 218 | 219 | 220 | 223 | 224 | 225 | 226 | 229 | 230 | 231 | 232 | 235 | 236 | 237 | 238 | 241 | 242 | 243 | 244 | 247 | 248 | 249 | 250 | 253 | 254 | 255 | 256 | 257 | 260 | 261 | 263 | 264 | 266 | 267 | 269 | 270 | 272 | 273 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | -------------------------------------------------------------------------------- /procs.tcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Björn Gottschall 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | # SOFTWARE. 20 | 21 | 22 | # Checks if a design is opened, like elaborated, synthesized or implemented 23 | # design. Outputs Error if not and can be used in if statements. 24 | # 25 | # @return 1 if design is open, 0 else 26 | proc design_open {} { 27 | if { [llength [current_design -quiet]] eq 0 } { 28 | puts stderr "ERROR: \[Common 17-53\] User Exception: No open design. Please open an elaborated, synthesized or implemented design before executing this command." 29 | return 0 30 | } 31 | return 1 32 | } 33 | 34 | # Gets the primitive starting cells of a net or a list of nets 35 | # 36 | # @param of_nets list of nets 37 | # @return list of start cells 38 | proc get_nets_start_cells { of_nets } { 39 | if { ! [design_open] } { 40 | return "" 41 | } 42 | set of_nets [get_nets $of_nets] 43 | set cells [list] 44 | #need to iterate over possible list, we only take one elemnt for each call 45 | foreach net $of_nets { 46 | lappend cells [get_cells -of_objects [lindex [get_nets -segments $net] 0] -filter {IS_PRIMITIVE}] 47 | } 48 | return [get_cells $cells] 49 | } 50 | 51 | # Gets the primitive ending cells of a net or a list of nets 52 | # 53 | # @param of_nets list of nets 54 | # @return list of end cells 55 | proc get_nets_end_cells { of_nets } { 56 | if { ! [design_open] } { 57 | return "" 58 | } 59 | set of_nets [get_nets $of_nets] 60 | set cells [list] 61 | #need to iterate over possible list, we only take one elemnt for each call 62 | foreach net $of_nets { 63 | lappend cells [get_cells -of_objects [lindex [get_nets -segments $net] end] -filter {IS_PRIMITIVE}] 64 | } 65 | return [get_cells $cells] 66 | } 67 | 68 | # Get all Interconnect Tiles of Sites or Tiles like SLICE_X0Y0 or 69 | # 70 | # @param of_nets list of nets 71 | # @return list of end cells 72 | proc get_interconnects { from } { 73 | if { ! [design_open] } { 74 | return "" 75 | } 76 | set target [get_sites -quiet $from] 77 | if { [string length $target] eq 0 } { 78 | #Could be a tile, check it 79 | set target [get_tiles -quiet $from] 80 | if { [string length $target] eq 0 } { 81 | #unknown what ever, empty response 82 | puts stderr "WARNING: Not a valid object for retrieving interconnects" 83 | return "" 84 | } 85 | } { 86 | #List of Sites were given, parse all tiles from: 87 | set target [get_tiles -of_objects $target] 88 | } 89 | return [filter_tiles [get_tiles -of_objects $target] "INT_\[RL\]"] 90 | } 91 | 92 | # Unfixes and unroutes given nets, routes them and fixes them again 93 | # Useful in relocation process for nets which fails on routing 94 | # 95 | # @param of_nets list of nets 96 | # @return nothing 97 | proc refix_routes {of_nets} { 98 | if { ! [design_open] } { 99 | return "" 100 | } 101 | set of_nets [get_nets $of_nets] 102 | fix_lut_pins $of_nets 0 103 | fix_routes $of_nets 0 104 | route_design -unroute -nets $of_nets 105 | route_design -nets $of_nets 106 | fix_lut_pins $of_nets 1 107 | fix_routes $of_nets 1 108 | } 109 | 110 | # (Un)fixes the routes of the given nets. Does basically the same as the GUI 111 | # but for any number of nets. Aliases will be transformed to real nets. 112 | # 113 | # @param of_nets list of nets 114 | # @param state 1 for fix (default), 0 for unfix 115 | # @return nothing 116 | proc fix_routes {of_nets {state 1}} { 117 | if { ! [design_open] } { 118 | return "" 119 | } 120 | set index 0 121 | set of_nets [get_nets $of_nets] 122 | if { $state eq 1 } { 123 | puts "Fix #[llength $of_nets] routes..." 124 | } { 125 | puts "Unfix #[llength $of_nets] routes..." 126 | set state 0 127 | } 128 | 129 | foreach net $of_nets { 130 | set parent [get_property PARENT $net] 131 | if { $parent ne $net } { 132 | puts "Net #$index: Parent $parent found!" 133 | set net [get_nets $parent] 134 | } 135 | set start [get_nets_start_cells $net] 136 | set end [get_nets_end_cells $net] 137 | puts "Net #$index: $net starts at $start and goes to $end" 138 | 139 | startgroup 140 | set_property is_route_fixed $state $net 141 | set_property is_bel_fixed $state [get_cells $start] 142 | set_property is_loc_fixed $state [get_cells $start] 143 | set_property is_bel_fixed $state [get_cells $end] 144 | set_property is_loc_fixed $state [get_cells $end] 145 | endgroup 146 | incr index 147 | } 148 | } 149 | 150 | # (Un)sets the LOCK_PINS constraint of a placed and routed LUT Cell. This 151 | # constraint is a fixed definition which Input Pins and Output Pin of the LUT 152 | # Cell is used from the routes. Fixing a Route without this constraint is not 153 | # possible! Basically an improved version from Xilinx which does ignore non 154 | # LUT Cells. 155 | # 156 | # @param of_nets list of nets 157 | # @param state 1 for fix (default), 0 for unfix 158 | # @return nothing 159 | proc fix_lut_pins {of_nets {state 1}} { 160 | if { ! [design_open] } { 161 | return "" 162 | } 163 | set of_nets [get_nets $of_nets] 164 | foreach net $of_nets { 165 | puts "Processing net $net" 166 | set loadpins [get_pins -leaf -of [get_nets $net] -filter direction=~in] 167 | 168 | foreach loadpin $loadpins { 169 | 170 | set pin [lindex [split $loadpin /] end] 171 | set belpin [lindex [split [get_bel_pins -of [get_pins $loadpin]] /] end] 172 | set index [expr [string last "/" $loadpin] - 1] 173 | set lut [string range $loadpin 0 $index] 174 | set beltype [get_bel_pins -of [get_pins $loadpin]] 175 | 176 | set type [get_property PRIMITIVE_GROUP [get_cells $lut]] 177 | if { $type eq "LUT" } { 178 | # Create hash table of LUT names and pin assignments, appending when needed 179 | if {[regexp (LUT) $beltype]} { 180 | if { [info exists lut_array($lut)] } { 181 | set lut_array($lut) "$lut_array($lut) $pin:$belpin" 182 | } else { 183 | set lut_array($lut) "$pin:$belpin" 184 | } 185 | } 186 | } else { 187 | puts "Primitive Cell is $type and not LUT! Skipping..." 188 | } 189 | } 190 | 191 | } 192 | 193 | foreach lut_name [array names lut_array] { 194 | if { $state eq 1 } { 195 | puts "Creating LOCK_PINS constraint $lut_array($lut_name) for LUT $lut_name." 196 | set_property LOCK_PINS "$lut_array($lut_name)" [get_cells $lut_name] 197 | } else { 198 | puts "Reset LOCK_PINS constraint for LUT $lut_name." 199 | reset_property LOCK_PINS [get_cells $lut_name] 200 | } 201 | 202 | 203 | } 204 | } 205 | 206 | # Sets the HD.PARTPIN_LOCS constraint for the given pins to the nearest. 207 | # interconnect. A Pin has a direction (IN or OUT) and a related net. Depending 208 | # on the direction the interconnect tile from the start or end cells is used. 209 | # 210 | # @param of_pins list of pins 211 | # @param state 1 for fix (default), 0 for unfix 212 | # @return nothing 213 | proc fix_plocs { of_pins {state 1}} { 214 | if { ! [design_open] } { 215 | return "" 216 | } 217 | set of_pins [get_pins $of_pins] 218 | foreach pin $of_pins { 219 | if { $state eq 0 } { 220 | reset_property -quiet HD.PARTPIN_LOCS $pin 221 | puts "$pin resetted" 222 | } { 223 | set dir [get_property DIRECTION $pin] 224 | set net [get_nets -of_objects $pin] 225 | set parent [get_property PARENT $net] 226 | set parentNet [get_nets $parent] 227 | #Get only one target Cell 228 | if { $dir eq "OUT" } { 229 | set targetCell [lindex [get_nets_start_cells $parentNet] 0] 230 | } { 231 | set targetCell [lindex [get_nets_end_cells $parentNet] 0] 232 | } 233 | 234 | set loc [get_property LOC $targetCell] 235 | if { [string length $loc] eq 0 } { 236 | puts "Pin $pin is not correctly fixed! Pin ignored!" 237 | } { 238 | set intc [get_interconnects $loc] 239 | if { [string length $intc] eq 0 } { 240 | puts "No Interconnect found for LOC $loc! Pin ignored!" 241 | } { 242 | reset_property -quiet HD.PARTPIN_LOCS $pin 243 | set_property HD.PARTPIN_LOCS $intc $pin 244 | puts "$pin will be placed on $intc" 245 | } 246 | } 247 | } 248 | } 249 | } 250 | 251 | # Helper Procedure for saving constraints in a more comfortable way. Can save 252 | # constraints to a new constraints set (existing one gets overwritten) and can 253 | # also change target file while saving. The saved constraint set will be the 254 | # target set. 255 | # 256 | # @param name optionally a new name of the constraint (current set is default) 257 | # @param target_file name of the target file to save the constraints 258 | # @return nothing 259 | proc save_constraints_force {{name ""} {target_file ""}} { 260 | if { ! [design_open] } { 261 | return "" 262 | } 263 | set path [get_property DIRECTORY [current_project]]/[current_project].srcs 264 | set old_target_file [file tail [get_property TARGET_CONSTRS_FILE [current_fileset -constrset]]] 265 | if { [string length $name] eq 0 } { 266 | #NO OBJECT HERE! Deleting fileset will turn $name empty if it is an object 267 | set name [lindex [current_fileset -constrset] 0] 268 | } 269 | if { [string length $target_file] eq 0} { 270 | 271 | set target_file $old_target_file 272 | } 273 | 274 | if { [string length $target_file] ne 0 && [file extension $target_file] ne ".xdc" } { 275 | set target_file [file tail [file rootname $target_file]].xdc 276 | } 277 | 278 | 279 | if { [current_fileset -constrset] eq $name } { 280 | #Switch to another name, save_constraints doesn't support changing target file 281 | save_constraints_as SAVE_CONSTRAINTS_FORCE_TEMP -target_constrs_file $target_file 282 | set_property constrset SAVE_CONSTRAINTS_FORCE_TEMP [current_run -synthesis] 283 | set_property constrset SAVE_CONSTRAINTS_FORCE_TEMP [current_run -implementation] 284 | 285 | delete_fileset -quiet $name 286 | file delete -force $path/$name 287 | 288 | save_constraints_as $name -target_constrs_file $target_file 289 | set_property constrset $name [current_run -synthesis] 290 | set_property constrset $name [current_run -implementation] 291 | 292 | delete_fileset -quiet SAVE_CONSTRAINTS_FORCE_TEMP 293 | file delete -force $path/SAVE_CONSTRAINTS_FORCE_TEMP 294 | } else { 295 | if { [file exists $path/$name] eq 1 || [string length [get_filesets -quiet -filter {FILESET_TYPE==Constrs} $name]] ne 0 } { 296 | delete_fileset -quiet $name 297 | file delete -force $path/$name 298 | } 299 | save_constraints_as $name -target_constrs_file $target_file 300 | set_property constrset $name [current_run -synthesis] 301 | set_property constrset $name [current_run -implementation] 302 | } 303 | } 304 | 305 | 306 | # Gets the resource ranges from a pblock. Can filter a specific resource type 307 | # out of the ranges list (SLICES, RAM ...) 308 | # 309 | # @param pblock pblock to get the ranges from 310 | # @param type optional filter for a range type 311 | # @return nothing 312 | proc get_range_from_pblock {pblock {type ""}} { 313 | if { ! [design_open] } { 314 | return "" 315 | } 316 | set pblock [ get_pblocks $pblock ] 317 | if { [llength $pblock] ne 1 } { 318 | puts stderr "ERROR: no pblock or multiple pblocks found" 319 | return "" 320 | } 321 | set ranges [get_property DERIVED_RANGES [get_pblock $pblock]] 322 | if { [string length $type] ne 0 } { 323 | set gridtypes [list] 324 | foreach gridtype $ranges { 325 | if { [regexp ^${type}_X[0-9]+Y[0-9]+ $gridtype] eq 1 } { 326 | lappend gridtypes $gridtype 327 | } 328 | } 329 | return $gridtypes 330 | } else { 331 | return $ranges 332 | } 333 | } 334 | 335 | # Filters a list of tiles or sites. Useful for filtering specific tiles, rows 336 | # or columns. 337 | # 338 | # @param tiles list to process 339 | # @param regex_tile regex filter for tile (default any) 340 | # @param regex_col regex filter for column (default any) 341 | # @param regex_row regex filter for row (default any) 342 | # @return filtered list 343 | proc filter_tiles {tiles {regex_tile "[A-Z0-9_]+"} {regex_col "[0-9]+"} {regex_row "[0-9]+"}} { 344 | set result [list] 345 | foreach tile $tiles { 346 | if { [regexp ^${regex_tile}_X${regex_col}Y${regex_row}\$ $tile] eq 1 } { 347 | lappend result $tile 348 | } 349 | } 350 | return $result 351 | } 352 | 353 | # Extracts the types from a tile list. 354 | # E.g. SLICE_X1Y1 INT_L_X0Y0 -> SLICE INT_L 355 | # 356 | # @param tiles list to process 357 | # @return list of types 358 | proc get_types { tiles } { 359 | set types [list] 360 | foreach tile $tiles { 361 | set matched [regexp {^([A-Z0-9_]+)_X([0-9]+)Y([0-9]+)} $tile -> tile x y] 362 | if { $matched ne 0 } { 363 | if { [lsearch $types $tile] eq -1 } { 364 | lappend types $tile 365 | } 366 | } 367 | } 368 | return $types 369 | } 370 | 371 | # Extracts the rows from a tile list. 372 | # E.g. SLICE_X1Y1 SLICEX0Y0 -> 0 1 373 | # 374 | # @param tiles list to process 375 | # @return list of rows in ascending order 376 | proc get_rows {tiles} { 377 | set result [list] 378 | foreach tile $tiles { 379 | set matched [regexp {^[A-Z0-9_]+_X([0-9]+)Y([0-9]+)$} $tile -> x y] 380 | if {$matched eq 0} { 381 | puts stderr "$tile: invalid tile" 382 | } else { 383 | if { [lsearch $result $y] eq -1 } { 384 | lappend result $y 385 | } 386 | } 387 | } 388 | return [lsort -integer $result] 389 | } 390 | 391 | # Extracts the columns from a tile list. 392 | # E.g. SLICE_X1Y0 SLICEX0Y0 -> 0 1 393 | # 394 | # @param tiles list to process 395 | # @return list of cols in ascending order 396 | proc get_cols {tiles} { 397 | set result [list] 398 | foreach tile $tiles { 399 | set matched [regexp {^[A-Z0-9_]+_X([0-9]+)Y([0-9]+)$} $tile -> x y] 400 | if {$matched eq 0} { 401 | puts stderr "$tile: invalid tile" 402 | } else { 403 | if { [lsearch $result $x] eq -1 } { 404 | lappend result $x 405 | } 406 | } 407 | } 408 | return [lsort -integer $result] 409 | } 410 | 411 | # Transforms a range statement to a list. Respects the changing bahviour of 412 | # interconnect tiles (R and L). 413 | # E.g. SLICE_X0Y0:SLICE_X2Y0 -> SLICE_X0Y0 SLICE_X1Y0 SLICEX2Y0 414 | # 415 | # @param ranges range list to process 416 | # @return list of tiles (no objects) 417 | proc get_list_from_range {ranges} { 418 | set result [list] 419 | foreach range $ranges { 420 | set matched [regexp {^([A-Z0-9_]+)_X([0-9]+)Y([0-9]+):([A-Z0-9_]+)_X([0-9]+)Y([0-9]+)} $range -> tile1 x1 y1 tile2 x2 y2] 421 | if {$matched eq 0} { 422 | puts stderr "$range: invalid tile range" 423 | } 424 | 425 | if { $tile1 eq "INT_L" || $tile1 eq "INT_R" } { 426 | set tile1 "INT" 427 | } 428 | 429 | if { $tile2 eq "INT_L" || $tile2 eq "INT_R" } { 430 | set tile2 "INT" 431 | } 432 | 433 | if { $tile1 ne $tile2 } { 434 | puts stderr "$range: invalid tile range" 435 | set matched 0 436 | } 437 | 438 | if { $matched ne 0 } { 439 | set tile $tile1 440 | set startx [expr min($x1,$x2)] 441 | set endx [expr max($x1,$x2)] 442 | set starty [expr min($y1,$y2)] 443 | set endy [expr max($y1,$y2)] 444 | for {set i $startx} {$i <= $endx} {incr i} { 445 | if { $tile1 eq "INT" } { 446 | set tile [if {[expr {$i%2}]} {list "INT_R"} {list "INT_L"}] 447 | } 448 | 449 | for {set z $starty} {$z <= $endy} {incr z} { 450 | lappend result "${tile}_X${i}Y${z}" 451 | } 452 | } 453 | } 454 | } 455 | return $result 456 | } 457 | 458 | # Evenly distributes the given pins on the given interconnects with respect of 459 | # the list orders. 460 | # 461 | # @param ranges range list to process 462 | # @return list of tiles (no objects) 463 | proc distribute_pins { pins intc } { 464 | if { ! [design_open] } { 465 | return "" 466 | } 467 | set pins [get_pins $pins] 468 | set intc [get_tiles $intc] 469 | set pinsPerIntc [expr ceil(double([llength $pins])/double([llength $intc]))] 470 | 471 | set pinIndex 0 472 | for {set i 0} {$i < [llength $intc]} {incr i} { 473 | for {set z 0} {$z < $pinsPerIntc && $pinIndex < [llength $pins]} {incr z; incr pinIndex} { 474 | put "Pin [lindex $pins $pinIndex] will be on [lindex $intc $i]" 475 | reset_property HD.PARTPIN_LOCS [lindex $pins $pinIndex] 476 | set_property HD.PARTPIN_LOCS [lindex $intc $i] [lindex $pins $pinIndex] 477 | } 478 | } 479 | } 480 | 481 | # Returns all nets which failed on routing. Does a simple text processing of 482 | # report_route_status and parsing the nets to objects. 483 | # 484 | # @return list of nets with routing errors 485 | proc get_failed_nets {} { 486 | if { ! [design_open] } { 487 | return "" 488 | } 489 | set nets [list] 490 | set status [report_route_status -return_string -show_all] 491 | set matched [regexp {^.*Nets with Routing Errors:(.*)$} $status -> nets_status] 492 | if { $matched eq 0 } { 493 | return $nets 494 | } 495 | while { $matched eq 1 } { 496 | set matched [regexp {\n ([^\n]+)\n(.*)$} $nets_status -> net nets_status] 497 | if { $matched eq 1 } { 498 | lappend nets $net 499 | } 500 | 501 | } 502 | return [get_nets $nets] 503 | } 504 | 505 | # Helper function for sort_properties. Constraints need a fixed order in the 506 | # files which are not always correctly saved by Vivado. 507 | # 508 | # @param x item to compare 509 | # @param y item to compare 510 | # @return 0 if no sorting is neede, -1 if y < x, 1 if y > x 511 | proc sort_properties_compare { x y } { 512 | set order [list BEL LOC LOCK_PINS FIXED_ROUTE] 513 | foreach item $order { 514 | set pos1 [string first "set_property $item" $x] 515 | set pos2 [string first "set_property $item" $y] 516 | if { $pos1 > $pos2 } { 517 | return -1 518 | } elseif { $pos1 < $pos2 } { 519 | return 1 520 | } 521 | } 522 | return 0 523 | } 524 | 525 | # Sorts a constraint file to assure correct order of constraints. Vivado 526 | # does sometimes strange stuff. 527 | # BEL < LOC < LOCK_PINS < FIXED_ROUTE 528 | # 529 | # @param file file to sort 530 | # @return nothing 531 | proc sort_properties { file } { 532 | set file [get_files -of_objects [current_fileset -constrset] $file] 533 | if { [file exists $file] eq 0 } { 534 | puts stderr "ERROR: $file doesn't exist!" 535 | return "" 536 | } 537 | 538 | set f [open $file "r"] 539 | set sortdata [split [read $f] "\n"] 540 | close $f 541 | 542 | set sorted [lsort -command sort_properties_compare $sortdata] 543 | 544 | set f [open $file "w"] 545 | puts $f [join $sorted "\n"] 546 | close $f 547 | } 548 | 549 | # Starts and waits for the given run 550 | # 551 | # @param run run to start 552 | # @return 0 on error and 1 on success 553 | proc start_run { run } { 554 | launch_runs $run 555 | wait_on_run $run 556 | if { [get_property PROGRESS $run] != "100%" } { 557 | puts stderr "ERROR: $run failed" 558 | return 0 559 | } 560 | return 1 561 | } 562 | 563 | # Start the synthesize run 564 | # 565 | # @param run name of the synth run 566 | # @param force force the run even if not necessary 567 | # @return 0 on error and 1 on success 568 | proc synthesize {{run "synth_1"} {force ""}} { 569 | set run [get_runs $run] 570 | set refresh [get_property NEEDS_REFRESH $run] 571 | set progress [get_property PROGRESS $run] 572 | if { $force ne "force" && $refresh eq 0 && $progress eq "100%" } { 573 | puts stderr "WARNING: Synthesized Design is up to date! Will not synthesize again!" 574 | return 1 575 | } 576 | reset_run $run 577 | return [start_run $run] 578 | } 579 | 580 | # Start the implementation run. does always start on synthesize 581 | # 582 | # @param run name of the impl run 583 | # @param force force the run even if not necessary 584 | # @return 0 on error and 1 on success 585 | proc implement {{run "impl_1"} {force ""}} { 586 | set run [get_runs $run] 587 | set refresh [get_property NEEDS_REFRESH $run] 588 | set progress [get_property PROGRESS $run] 589 | if { $force ne "force" && $refresh eq 0 && $progress eq "100%" } { 590 | puts stderr "WARNING: Implemented Design is up to date! Will not synthesize again!" 591 | return 1 592 | } 593 | set parent [get_runs [get_property PARENT $run]] 594 | reset_run $run 595 | reset_run $parent 596 | return [start_run $run] 597 | } 598 | 599 | # Opens the synthesized design 600 | # 601 | # @param run optional name of the synthesize run 602 | # @return nothing 603 | proc open_synth { {run "synth_1"} } { 604 | set run [get_runs $run] 605 | open_run $run 606 | } 607 | 608 | # Opens the implemented design 609 | # 610 | # @param run optional name of the implementation run 611 | # @return nothing 612 | proc open_impl { {run "impl_1"} } { 613 | set run [get_runs $run] 614 | open_run $run 615 | } 616 | 617 | # Get all LUT6 resources of the given BELs 618 | # 619 | # @param of_objects list of BELs to retrieve the LUTs 620 | # @return list of LUTs 621 | proc get_bels_lut6 { of_objects } { 622 | set luts [list] 623 | set luts [concat $luts [get_bels -of_objects $of_objects -filter {TYPE=~LUT*6}]] 624 | return $luts 625 | } 626 | 627 | # Get all REG resources of the given BELs 628 | # 629 | # @param of_objects list of BELs to retrieve the REGs 630 | # @return list of REGs 631 | proc get_bels_ff { of_objects } { 632 | set of_objects [get_sites $of_objects] 633 | set ffs [list] 634 | set ffs [concat $ffs [get_bels -of_objects $of_objects -filter {TYPE==FF_INIT}]] 635 | set ffs [lsort [concat $ffs [get_bels -of_objects $of_objects -filter {TYPE==REG_INIT}]]] 636 | return $ffs 637 | } 638 | 639 | # Placed the given cells on the given BELs with respect to the list orders. 640 | # 641 | # @param cells list of cells 642 | # @param bels list of bells 643 | # @return nothing 644 | proc place_cells {cells bels} { 645 | if {[llength $bels] < [llength $cells]} { 646 | puts stderr "Cannot place [llength $cells] cells on [llength $bels] BELs!" 647 | return "" 648 | } 649 | set index 0 650 | foreach cell $cells { 651 | puts "Place $cell to [lindex $bels $index]" 652 | place_cell $cell [lindex $bels $index] 653 | incr index 654 | } 655 | } 656 | 657 | # Gets the top cell in hirachie foreach given cell. 658 | # 659 | # @param cells list of cells 660 | # @return root cells 661 | proc get_cells_root { cells } { 662 | set cells [get_cells $cells] 663 | set result [list] 664 | foreach cell $cells { 665 | set parent $cell 666 | set prev_parent [get_property PARENT $parent] 667 | set timeout 0 668 | while { [string length $prev_parent] ne 0 && $timeout ne 100} { 669 | set parent $prev_parent 670 | set prev_parent [get_property PARENT $parent] 671 | incr timeout 672 | } 673 | if { $timeout ne 100 } { 674 | lappend result $parent 675 | } else { 676 | puts stderr "TIMEOUT: get_cells_root $cell" 677 | } 678 | } 679 | return $result 680 | } 681 | 682 | # Get the root from a path. 683 | # E.g. pr_0/pr_0_input/reg[0] -> pr_0 684 | # 685 | # @param values list of paths 686 | # @return root element of the paths 687 | proc get_roots { values } { 688 | set result [list] 689 | foreach value $values { 690 | set matched [regexp {^([a-zA-Z0-9\[\]_\.]+)/?.*$} $value -> name] 691 | if { $matched ne 0 } { 692 | lappend result $name 693 | } 694 | } 695 | if { [llength $result] eq 1 } { 696 | set result [lindex $result 0] 697 | } 698 | return $result 699 | } 700 | 701 | # Get name from a path. 702 | # E.g. pr_0/pr_0_input/reg[0] -> reg[0] 703 | # 704 | # @param values list of paths 705 | # @return name from the paths 706 | proc get_names { values } { 707 | set result [list] 708 | foreach value $values { 709 | set matched [regexp {^.*/([a-zA-Z0-9\[\]_\.]+)$} $value -> name] 710 | if { $matched ne 0 } { 711 | lappend result $name 712 | } 713 | } 714 | if { [llength $result] eq 1 } { 715 | set result [lindex $result 0] 716 | } 717 | return $result 718 | } 719 | 720 | # Get all boundary nets from a cell. That means all nets of a cell from which 721 | # the start or end cell is not inside the cell itself. 722 | # 723 | # @param of_cells list of cells 724 | # @return boundary nets 725 | proc get_boundary_nets { of_cells } { 726 | set of_cells [get_cells $of_cells] 727 | set result [list] 728 | foreach cell $of_cells { 729 | set nets [get_nets $cell/*] 730 | foreach net $nets { 731 | set boundary false 732 | set starts [get_cells_root [get_nets_start_cells $net]] 733 | set ends [get_cells_root [get_nets_end_cells $net]] 734 | foreach start $starts { 735 | if { [lsearch $ends $start] eq -1 } { 736 | set boundary true 737 | break 738 | } 739 | } 740 | if { $boundary eq true } { 741 | lappend result $net 742 | } 743 | } 744 | } 745 | return $result 746 | } 747 | 748 | # Outputs a list to the console. Child elements get indented. 749 | # 750 | # @param output_list list to output on the console 751 | # @param level indent level used for childs 752 | # @return nothing 753 | proc puts_list { output_list {level 1} } { 754 | if { [string length $output_list] eq 0 } { 755 | return 756 | } 757 | for {set i 1} { $i < $level } {incr i} { 758 | puts -nonewline "\t" 759 | } 760 | puts "{" 761 | foreach ele $output_list { 762 | if { [llength $ele] > 1 } { 763 | puts_list $ele [expr $level + 1] 764 | } else { 765 | for {set i 0} { $i < $level } {incr i} { 766 | puts -nonewline "\t" 767 | } 768 | puts $ele 769 | } 770 | } 771 | for {set i 1} { $i < $level } {incr i} { 772 | puts -nonewline "\t" 773 | } 774 | puts "}" 775 | } 776 | 777 | # get_nets wrapper for filtering clock nets 778 | # 779 | # @param nets nets to process 780 | # @return nets without clock nets 781 | proc get_nets_no_clk { nets } { 782 | get_nets -filter {TYPE!~*CLOCK*} $nets 783 | } 784 | 785 | # get_pins wrapper for filtering clock pins. Sadly only detecting clock pins 786 | # only from the name of the pins. 787 | # 788 | # @param pins pins to process 789 | # @return pins without clock pins 790 | proc get_pins_no_clk { nets } { 791 | get_pins -filter {NAME!~*CLOCK* && NAME!~*clk*} $nets 792 | } 793 | 794 | # Compares two lists 795 | # 796 | # @param a list 797 | # @param b list 798 | # @return 0 if not equal, 1 if equal 799 | proc lequal {a b} { 800 | if { [llength $a] ne [llength $b] } { 801 | return 0 802 | } 803 | foreach i $a { 804 | if {[lsearch -exact $b $i] == -1} { 805 | return 0 806 | } 807 | } 808 | return 1 809 | } 810 | 811 | # Checkes the existance of elements in a list 812 | # 813 | # @param a list to search in 814 | # @param b list of elements to search in a 815 | # @return 0 if b is not in a, 1 if b is in a 816 | proc lcontains {a b} { 817 | foreach i $b { 818 | if {[lsearch -exact $a $i] eq -1 } { 819 | return 0 820 | } 821 | } 822 | return 1 823 | } 824 | 825 | # Relocates the given tiles with a column and row offset 826 | # E.g. SLICE_X5Y0 5 10 -> SLICE_X10Y10 827 | # 828 | # @param tiles list of tiles 829 | # @param offset_x column offset 830 | # @param offset_y row offset 831 | # @return list of relocated tiles 832 | proc get_tiles_relocated { tiles { offset_x 0 } { offset_y 0 }} { 833 | set result [list] 834 | foreach tile $tiles { 835 | set matched [regexp {^([A-Z0-9_]+)_X([0-9]+)Y([0-9]+)$} $tile -> tile x y] 836 | if { $matched ne 0 } { 837 | lappend result "${tile}_X[expr $x + ${offset_x}]Y[expr $y + ${offset_y}]" 838 | } 839 | } 840 | return $result 841 | } 842 | 843 | # Normalizes a list of tile to column 0 and row 0 844 | # E.g. SLICE_X5Y6 SLICE_X7Y7 -> SLICE_X0Y0 SLICE_X2Y1 845 | # 846 | # @param tiles list of tiles 847 | # @return list of normalized tiles 848 | proc get_tiles_normalized { tiles } { 849 | return [get_tiles_relocated $tiles -[get_tiles_offset_x $tiles] -[get_tiles_offset_y $tiles]] 850 | } 851 | 852 | # Returns the column offset of the tile list, which is the smallest column 853 | # number 854 | # E.g. SLICE_X5Y6 SLICE_X7Y7 -> 5 855 | # 856 | # @param tiles list of tiles 857 | # @return column offset 858 | proc get_tiles_offset_x { tiles } { 859 | return [lindex [get_cols $tiles] 0] 860 | } 861 | 862 | # Returns the row offset of the tile list, which is the smallest row 863 | # number 864 | # E.g. SLICE_X5Y6 SLICE_X7Y7 -> 6 865 | # 866 | # @param tiles list of tiles 867 | # @return row offset 868 | proc get_tiles_offset_y { tiles } { 869 | return [lindex [get_rows $tiles] 0] 870 | } 871 | 872 | # Compares given pblocks if they are relocatable. Does not compare the 873 | # arrangement of resources over different resource types. Checkes wrong 874 | # hirachie and nested Cell count and the amount and arrangement of resources of 875 | # the same type 876 | # 877 | # @param pblocks list of pblocks 878 | # @return 1 on success, 0 on error 879 | proc verify_relocateable_pblocks { pblocks } { 880 | set verify_pblocks [get_pblocks $pblocks] 881 | if { [lequal $verify_pblocks $pblocks] eq 0 } { 882 | puts stderr "Verify Error: Invalid pblocks!" 883 | return 0 884 | } 885 | if {[llength $verify_pblocks] eq 1 } { 886 | puts stderr "Verify Error: need more than one pblock!" 887 | return 0 888 | } 889 | 890 | set reloc 1 891 | set base_pblock "" 892 | set base_types [list] 893 | set base_sites [list] 894 | 895 | foreach pblock $verify_pblocks { 896 | if { [get_property CELL_COUNT $pblock] ne 1 } { 897 | puts stderr "Verify Error: Pblock $pblock needs exactly one cell!" 898 | set reloc 0 899 | } 900 | if { [get_property PARENT $pblock] ne "ROOT" } { 901 | puts stderr "Verify Error: Pblock $pblock is nested!" 902 | set reloc 0 903 | } 904 | 905 | set comp_types [list] 906 | set comp_sites [list] 907 | 908 | puts "Verify pblock $pblock:" 909 | set comp_types [lsort [get_types [get_range_from_pblock $pblock]]] 910 | foreach type $comp_types { 911 | set sites [lsort [get_tiles_normalized [get_list_from_range [get_range_from_pblock $pblock $type]]]] 912 | puts "\t - [llength $sites] $type sites" 913 | lappend comp_sites $sites 914 | } 915 | 916 | if { [llength $base_types] eq 0 } { 917 | set base_types $comp_types 918 | set base_sites $comp_sites 919 | set base_pblock $pblock 920 | } else { 921 | if { [lequal $base_sites $comp_sites] eq 0 } { 922 | puts stderr "Verify Error: pblock $pblock doesn't match with $base_pblock!" 923 | set reloc 0 924 | } 925 | } 926 | } 927 | if { $reloc eq 1 } { 928 | return 1 929 | } else { 930 | puts stderr "Verify Error: pblocks are not suitable for relocation!" 931 | return 0 932 | } 933 | } 934 | 935 | # Sets cells as isolated for the Isolated Design Flow 936 | # 937 | # @param cells list of cells 938 | # @return nothing 939 | proc set_isolated { cells } { 940 | set cells [get_cells $cells] 941 | foreach cell $cells { 942 | set_property HD.RECONFIGURABLE false $cell 943 | #set_property DONT_TOUCH false $cell 944 | set_property HD.ISOLATED true $cell 945 | } 946 | } 947 | 948 | # Sets cells as reconfigurable 949 | # 950 | # @param cells list of cells 951 | # @return nothing 952 | proc set_reconfigurable { cells } { 953 | set cells [get_cells $cells] 954 | foreach cell $cells { 955 | set_property HD.ISOLATED false $cell 956 | #set_property DONT_TOUCH true $cell 957 | set_property HD.RECONFIGURABLE true $cell 958 | } 959 | } 960 | 961 | # Escapes all special TCL characters in a value 962 | # 963 | # @param value 964 | # @return escaped valued 965 | proc escape { value } { 966 | return [string map [list \[ {\[} \] {\]} \* {\*} \? {\?} \\ {\\}] $value] 967 | } 968 | 969 | # Escapes all special regex characters in a value 970 | # 971 | # @param value 972 | # @return escaped valued 973 | proc escape_regex { value } { 974 | return [string map [list \[ {\[} \] {\]} \* {\*} \? {\?} \\ {\\} - {\-} ( {\(} ) {\)} + {\+} . {\.} , {\,} / {\/}] $value] 975 | } 976 | 977 | # Sorts the second lsit to match the first one. Also Strips off path elements 978 | # for comparison. Useful to match cells or nets from different parent cells. 979 | # E.g [X/T[0] X/T[1]] [Y/T[1] Y/T[0]] -> [X/T[0] X/T[1]] [Y/T[0] Y/T[1]] 980 | # 981 | # @param list1 list to compare against 982 | # @param pList2 name of list to sort and compare to list one 983 | # @param strip_filter regex filter to strip of path elements for comparison (default first path element) 984 | # @return 0 on error, 1 on success 985 | proc match_lists { list1 pList2 { strip_filter "[a-zA-Z0-9_\\.\\[\\]]+/?" } } { 986 | upvar 1 $pList2 list2 987 | set assoc_list [list] 988 | set result 1 989 | for {set i 0} { $i < [llength $list1] } { incr i } { 990 | set entry [lindex $list1 $i] 991 | set matching_entry "" 992 | set matched [regex ^${strip_filter}(.*)$ $entry -> value] 993 | if { $matched ne 0 } { 994 | set value [escape_regex $value] 995 | set index [lsearch -regex $list2 ^.*${value}$] 996 | if { $index ne -1 } { 997 | set matching_entry [lindex $list2 $index] 998 | } else { 999 | puts stderr "Associate Error: no matching element found for $value" 1000 | set result 0 1001 | } 1002 | } else { 1003 | puts stderr "Associate Error: strip filter $strip_filter not correct for entry $entry" 1004 | set result 0 1005 | } 1006 | lappend assoc_list $matching_entry 1007 | } 1008 | if { $result eq 1 } { 1009 | set list2 $assoc_list 1010 | } 1011 | return $result 1012 | } 1013 | 1014 | # Helper Function for copy_object_properties to relocate the HD.PARTPIN_LOCS 1015 | # property from one cell to another cell. Does calculate the new 1016 | # interconnect tile location relative to the pblocks of the cells. Works 1017 | # directly on the vars of the caller function. 1018 | # 1019 | # @param pFrom name cell to copy from 1020 | # @param pTo name cell to copy to 1021 | # @param pProperty name of the property 1022 | # @param pValue name of the value to apply 1023 | # @return nothing 1024 | proc relocate_partpin_property { pFrom pTo pProperty pValue } { 1025 | upvar 1 $pFrom from 1026 | upvar 1 $pTo to 1027 | upvar 1 $pProperty property 1028 | upvar 1 $pValue value 1029 | 1030 | if { $property eq "HD.PARTPIN_LOCS" } { 1031 | set prop [filter_tiles $value "INT_\[LR\]"] 1032 | if { [string length $prop] ne 0 } { 1033 | set from_cell [get_property PARENT_CELL $from] 1034 | set to_cell [get_property PARENT_CELL $to] 1035 | set pblock_from [get_pblocks [get_property PBLOCK [get_cells_root $from_cell]]] 1036 | set pblock_to [get_pblocks [get_property PBLOCK [get_cells_root $to_cell]]] 1037 | 1038 | if { [string length $pblock_from] ne 0 && [string length $pblock_to] ne 0 } { 1039 | set slice_range_from [get_list_from_range [get_range_from_pblock $pblock_from SLICE]] 1040 | set slice_range_to [get_list_from_range [get_range_from_pblock $pblock_to SLICE]] 1041 | 1042 | set from_int [get_interconnects "SLICE_X[get_tiles_offset_x $slice_range_from]Y[get_tiles_offset_y $slice_range_from]"] 1043 | set to_int [get_interconnects "SLICE_X[get_tiles_offset_x $slice_range_to]Y[get_tiles_offset_y $slice_range_to]"] 1044 | 1045 | set offset_x [expr [get_tiles_offset_x $to_int] - [get_tiles_offset_x $from_int]] 1046 | set offset_y [expr [get_tiles_offset_y $to_int] - [get_tiles_offset_y $from_int]] 1047 | set prop [get_tiles_relocated $prop $offset_x $offset_y] 1048 | set value [lindex [get_list_from_range "${prop}:${prop}"] 0] 1049 | puts "Parsing PARTPIN_LOC: Apply offset X${offset_x}Y${offset_y}" 1050 | } else { 1051 | puts "WARNING: NOT PARSING PARTPIN_LOC, there is no pblock on $from or $to" 1052 | } 1053 | } else { 1054 | puts "WARNING: NOT PARSING PARTPIN_LOC, there is a PARTPIN_LOC Property but no Interconnect Tile on Object $from" 1055 | } 1056 | } 1057 | } 1058 | 1059 | # Helper Function for copy_object_properties to relocate the LOC property from 1060 | # one cell to another cell. Does calculate the new LOC location relative to the 1061 | # pblocks of the cells. Works directly on the vars of the caller function. 1062 | # 1063 | # @param pFrom name cell to copy from 1064 | # @param pTo name cell to copy to 1065 | # @param pProperty name of the property 1066 | # @param pValue name of the value to apply 1067 | # @return nothing 1068 | proc relocate_loc_property { pFrom pTo pProperty pValue } { 1069 | upvar 1 $pFrom from 1070 | upvar 1 $pTo to 1071 | upvar 1 $pProperty property 1072 | upvar 1 $pValue value 1073 | 1074 | if { $property eq "LOC" } { 1075 | set prop [filter_tiles $value SLICE] 1076 | if { [string length $prop] ne 0 } { 1077 | 1078 | set pblock_from [get_pblocks [get_property PBLOCK [get_cells_root $from]]] 1079 | set pblock_to [get_pblocks [get_property PBLOCK [get_cells_root $to]]] 1080 | 1081 | if { [string length $pblock_from] ne 0 && [string length $pblock_to] ne 0 } { 1082 | set slice_range_from [get_list_from_range [get_range_from_pblock $pblock_from SLICE]] 1083 | set slice_range_to [get_list_from_range [get_range_from_pblock $pblock_to SLICE]] 1084 | set offset_x [expr [get_tiles_offset_x $slice_range_to] - [get_tiles_offset_x $slice_range_from]] 1085 | set offset_y [expr [get_tiles_offset_y $slice_range_to] - [get_tiles_offset_y $slice_range_from]] 1086 | set value [get_tiles_relocated $prop $offset_x $offset_y] 1087 | puts "Parsing LOC: Apply offset X${offset_x}Y${offset_y}" 1088 | } else { 1089 | puts "WARNING: NOT PARSING LOC, there is no pblock on $from or $to" 1090 | } 1091 | } else { 1092 | puts "WARNING: NOT PARSING LOC, there is a LOC Property but no SLICE Tile on Object $from" 1093 | } 1094 | } 1095 | } 1096 | 1097 | # Copies multiple properties from objects to other objects. Optional can parse 1098 | # the property with a helper function if a modification is needed before 1099 | # applying the new property (see relocate_loc_property or 1100 | # relocate_parpin_property) 1101 | # 1102 | # @param properties list of properties to copy 1103 | # @param from list of objects to copy from 1104 | # @param to list of ibjects to copy to 1105 | # @param parse_prop name of a parsing property function 1106 | # @return nothing 1107 | proc copy_object_properties { properties from to { parse_prop "" }} { 1108 | set parse 0 1109 | if { [string length $parse_prop] ne 0 } { 1110 | if { [string length [info commands $parse_prop]] ne 0 } { 1111 | set parse 1 1112 | } else { 1113 | puts stderr "WARNING: proc $parse_prop not found!" 1114 | } 1115 | } 1116 | 1117 | 1118 | foreach property $properties { 1119 | foreach obj $to { 1120 | reset_properties $property $obj 1121 | } 1122 | set value [get_property $property $from] 1123 | if { [string length $value] ne 0 } { 1124 | foreach obj $to { 1125 | if { $parse eq 1 } { 1126 | [$parse_prop from obj property value] 1127 | } 1128 | puts "Copy property $property $value from $from to $obj" 1129 | set_property $property $value $obj 1130 | } 1131 | } 1132 | } 1133 | } 1134 | 1135 | # Resets multiple properties on any given objects. Does ignore errors if 1136 | # propety could not be ressetted. Does have special threatment for some 1137 | # properties 1138 | # 1139 | # @param properties list of properties to reset 1140 | # @param objs list of objects 1141 | # @return nothing 1142 | proc reset_properties { properties objs } { 1143 | set empty_properties {LOC BEL LOCK_PINS} 1144 | set false_properties {IS_LOC_FIXED IS_BEL_FIXED DONT_TOUCH} 1145 | set unsupported_properties {DONT_TOUCH} 1146 | foreach obj $objs { 1147 | foreach prop $properties { 1148 | if { [lsearch $false_properties $prop] ne -1 } { 1149 | catch [list set $prop 0 $obj] err 1150 | } elseif { [lsearch $empty_properties $prop] ne -1 } { 1151 | catch [list set $prop "" $obj] err 1152 | catch [list reset_property $prop $obj] err 1153 | } else { 1154 | catch [list reset_property $prop $obj] err 1155 | } 1156 | } 1157 | } 1158 | } 1159 | 1160 | # Gets all pins from a cell hierarchical 1161 | # 1162 | # @param cells list of cells to retrieve the pins 1163 | # @return all hierarchical pins from the given cells 1164 | proc get_pins_hierarchical { cells } { 1165 | set result [list] 1166 | foreach cell $cells { 1167 | lappend result [get_pins -quiet $cell] 1168 | set result [concat $result [get_pins -hierarchical -filter NAME=~$cell/*]] 1169 | } 1170 | return $result 1171 | 1172 | } 1173 | 1174 | # Gets all nets from a cell hierarchical 1175 | # 1176 | # @param cells list of cells to retrieve the nets 1177 | # @return all hierarchical nets from the given cells 1178 | proc get_nets_hierarchical { cells } { 1179 | set result [list] 1180 | foreach cell $cells { 1181 | lappend result [get_nets -quiet $cell] 1182 | set result [concat $result [get_nets -hierarchical -filter NAME=~$cell/*]] 1183 | } 1184 | return $result 1185 | } 1186 | 1187 | # Gets all cells from a cell hierarchical. The cell itself is also returned. 1188 | # 1189 | # @param cells list of cells to retrieve all cells 1190 | # @return all hierarchical cells from the given cells 1191 | proc get_cells_hierarchical { cells } { 1192 | set result [list] 1193 | foreach cell $cells { 1194 | lappend result [get_cells $cell] 1195 | set result [concat $result [get_cells -hierarchical -filter NAME=~$cell/*]] 1196 | } 1197 | return $result 1198 | } 1199 | 1200 | # Cleans up a Cell for relocation. Resets properties which are important for 1201 | # relocation. 1202 | # RESETS ALL PROPERTIES INSIDE A CELL, NOT ONLY INTERFACE PROPERTIES! 1203 | # 1204 | # @param cells list of cells 1205 | # @return nothing 1206 | proc relocate_cleanup { cells } { 1207 | set cells [get_cells $cells] 1208 | foreach cell $cells { 1209 | set clean_cells [get_cells_hierarchical $cell] 1210 | reset_properties {IS_LOC_FIXED IS_BEL_FIXED LOC BEL LOCK_PINS} $clean_cells 1211 | 1212 | set clean_pins [get_pins_hierarchical $cell] 1213 | reset_properties {HD.PARTPIN_LOCS} $clean_pins 1214 | 1215 | set clean_nets [get_nets_hierarchical $cell] 1216 | reset_properties {FIXED_ROUTE} $clean_nets 1217 | 1218 | set boundary_nets [get_boundary_nets $cell] 1219 | reset_properties {IS_LOC_FIXED IS_BEL_FIXED LOC BEL LOCK_PINS} [get_nets_end_cells $boundary_nets] 1220 | reset_properties {IS_LOC_FIXED IS_BEL_FIXED LOC BEL LOCK_PINS} [get_nets_start_cells $boundary_nets] 1221 | } 1222 | } 1223 | 1224 | # Relocates the interface of a base_cell to a given list of cells. It retrieves 1225 | # the interface of the first cell and compares ot to the others. If they match 1226 | # it will copy all properties from the base_cell to the others with special 1227 | # threatment to the LOC property. 1228 | # Relocation of HD.PARTPIN_LOCS is not enabled, fix_plocs does the same! 1229 | # 1230 | # @param base_cell base_cell to relocate from 1231 | # @param cells list of cells to relocate to 1232 | # @return nothing 1233 | proc relocate_cells { base_cell cells } { 1234 | set base_cell [get_cells $base_cell] 1235 | set cells [get_cells $cells] 1236 | if { [string length $base_cell] eq 0 } { 1237 | return "ERROR: Need a base cell to relocate from" 1238 | } 1239 | if { [string length $cells] eq 0 } { 1240 | return "ERROR: Need at least one target cell to relocate to" 1241 | } 1242 | 1243 | set base_pins [get_pins_no_clk $base_cell/*] 1244 | set base_nets [get_nets_no_clk [get_boundary_nets $base_cell]] 1245 | #Associate List will strip off the root cell and compares the rest, lut_buffers in pr_buffer and pr are symmetric, split them up 1246 | set base_intfs [get_nets_start_cells $base_nets] 1247 | set base_intfs [concat $base_intfs [get_nets_end_cells $base_nets]] 1248 | set base_intfs_1 [get_cells $base_intfs -filter NAME=~$base_cell/*] 1249 | set base_intfs_2 [get_cells $base_intfs -filter NAME!~$base_cell/*] 1250 | #base_intfs will be sorted: first cells from the $cell and then the rest 1251 | set base_intfs [concat $base_intfs_1 $base_intfs_2] 1252 | 1253 | foreach cell $cells { 1254 | set cpy 1 1255 | set nets [get_nets_no_clk [get_boundary_nets $cell]] 1256 | set pins [get_pins_no_clk $cell/*] 1257 | 1258 | if { [match_lists $base_nets nets] eq 0 } { 1259 | puts stderr "Boundary nets from $cell not matching with $base_cell" 1260 | set cpy 0 1261 | } else { 1262 | set intfs [get_nets_start_cells $nets] 1263 | set intfs [concat $intfs [get_nets_end_cells $nets]] 1264 | set intfs_1 [get_cells $intfs -filter NAME=~$cell/*] 1265 | set intfs_2 [get_cells $intfs -filter NAME!~$cell/*] 1266 | if { [match_lists $base_intfs_1 intfs_1] eq 0 } { 1267 | puts stderr "Interface Cells from $cell not matching with $base_cell" 1268 | set cpy 0 1269 | } 1270 | if { [match_lists $base_intfs_2 intfs_2] eq 0 } { 1271 | puts stderr "Interface Cells to $cell not matching with $base_cell" 1272 | set cpy 0 1273 | } 1274 | set intfs [concat $intfs_1 $intfs_2] 1275 | } 1276 | if { [match_lists $base_pins pins] eq 0 } { 1277 | puts stderr "Pin Nets from $cell not matching with $base_cell" 1278 | set cpy 0 1279 | } 1280 | 1281 | if { $cpy eq 1 } { 1282 | puts "Cleanup cell $cell" 1283 | relocate_cleanup $cell 1284 | 1285 | for {set i 0} { $i < [llength $base_intfs]} {incr i} { 1286 | set base_intf [get_cells [lindex $base_intfs $i]] 1287 | set intf [get_cells [lindex $intfs $i]] 1288 | puts "#$i: $base_intf -> $intf" 1289 | copy_object_properties [list "LOCK_PINS" "LOC" "BEL" "IS_LOC_FIXED" "IS_BEL_FIXED" "DONT_TOUCH"] $base_intf $intf relocate_loc_property 1290 | } 1291 | for {set i 0} { $i < [llength $base_nets]} {incr i} { 1292 | set base_net [get_nets [lindex $base_nets $i]] 1293 | set net [get_nets [lindex $nets $i]] 1294 | puts "#$i: $base_net -> $net" 1295 | copy_object_properties [list "FIXED_ROUTE"] $base_net $net 1296 | } 1297 | 1298 | # After relocation, fix_plocs will do the job but this would works: 1299 | # for {set i 0} { $i < [llength $base_pins]} {incr i} { 1300 | # set base_pin [get_pins [lindex $base_pins $i]] 1301 | # set pin [get_pins [lindex $pins $i]] 1302 | # puts "#$i: $base_pin -> $pin" 1303 | # copy_object_properties [list "HD.PARTPIN_LOCS"] $base_pin $pin relocate_partpin_property 1304 | # } 1305 | 1306 | } 1307 | } 1308 | } 1309 | --------------------------------------------------------------------------------