├── 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 |
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 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
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 |
--------------------------------------------------------------------------------