diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_multiple_destinations.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_multiple_destinations.vhd index 33e2fc12e0ec47c425ba4980fb1c91ce752ca95c..1e2b7c0e3d1ffcade10c18e8c6f67c82986b6cf0 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_multiple_destinations.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_multiple_destinations.vhd @@ -22,15 +22,29 @@ -- Purpose: -- Construct beamformer data output (BDO) payloads for multiple destinations. -- Description: --- * Get N_destinations from sdp_bdo_destinations_reg. --- * Merge, reorder and unmerge beamlet data for N_destinations > 1 from: --- (int8) [t] [N_blocks_per_packet][S_sub_bf / N_destinations] [N_pol_bf][N_complex] +-- * The nof_destinations_max determines how to MM control the beamlet packet +-- destination(s) MAC/IP/UDP port: +-- . nof_destinations_max = 1 then use sdp_bdo_one_destination.vhd and +-- MM program the one destination MAC/IP/UDP port from dp_offload_tx_v3. +-- . nof_destinations_max > 1 then use sdp_bdo_multiple_destinations.vhd and +-- MM program the one or more destination MAC/IP/UDP port via +-- sdp_bdo_destinations_reg. +-- * Get nof_destinations from sdp_bdo_destinations_reg. The nof_destinations +-- is MM programmable between 1 and nof_destinations_max. +-- * The nof_blocks_per_packet is not MM programmable, but based on +-- nof_destinations to ensure that the packet fits in a jumbo frame or +-- equal to c_sdp_bdo_reorder_nof_blocks_max to make maximum use of the +-- available reorder buffer size. +-- * Merge, reorder and unmerge beamlet data for nof_destinations > 1 from: +-- (int8) [t] [nof_blocks_per_packet][S_sub_bf / nof_destinations] [N_pol_bf][N_complex] -- to: --- (int8) [t] [S_sub_bf / N_destinations][N_blocks_per_packet] [N_pol_bf][N_complex] +-- (int8) [t] [S_sub_bf / nof_destinations][nof_blocks_per_packet] [N_pol_bf][N_complex] -- -- . where (int8) [N_pol_bf][N_complex] = c_sdp_W_dual_pol_beamlet = 32b -- dual polarization beamlet word --- . where N_destinations packets together transport the S_sub_bf beamlets. +-- . where nof_destinations packets together transport the S_sub_bf beamlets. +-- * Only support transposed beamlet data output, because each destination +-- must receive all blocks (= time samples) per beamlet. -- References: -- [1] https://support.astron.nl/confluence/display/L2M/L4+SDPFW+Decision%3A+Multiple+beamlet+output+destinations -- @@ -48,8 +62,8 @@ library IEEE, common_lib, dp_lib, reorder_lib; entity sdp_bdo_multiple_destinations is generic ( - g_beamset_id : natural := 0; - g_use_transpose : boolean := false + g_nof_destinations_max : natural := 1; + g_beamset_id : natural := 0 ); port ( mm_clk : in std_logic; @@ -71,25 +85,17 @@ end sdp_bdo_multiple_destinations; architecture str of sdp_bdo_multiple_destinations is constant c_beamlet_index : natural := g_beamset_id * c_sdp_S_sub_bf; - -- Reorder c_nof_ch = c_nof_ch_sel = c_nof_ch_in - constant c_reorder_nof_blocks_max : natural := c_sdp_bdo_reorder_nof_blocks_max; -- = 16 - constant c_reorder_nof_blocks_w : natural := ceil_log2(c_reorder_nof_blocks_max + 1); - constant c_reorder_nof_ch_max : natural := c_reorder_nof_blocks_max * - c_sdp_nof_beamlets_per_block * - c_sdp_nof_words_per_beamlet; -- = 7808 - - -- Look up table constants as function of N_destinations - constant c_m : natural := c_sdp_bdo_nof_destinations_max; -- 16 - constant c_nof_blocks_per_packet_arr : t_natural_arr(1 to c_m) := func_sdp_bdo_nof_blocks_per_packet_look_up_table; - constant c_reorder_nof_blocks_arr : t_natural_arr(1 to c_m) := func_sdp_bdo_reorder_nof_blocks_look_up_table; - constant c_reorder_nof_ch_arr : t_natural_arr(1 to c_m) := func_sdp_bdo_reorder_nof_ch_look_up_table; - constant c_nof_beamlets_per_block_first_destination_arr : t_natural_arr(1 to c_m) := func_sdp_sdo_nof_beamlets_per_block_first_destination_look_up_table; - constant c_nof_beamlets_per_block_last_destination_arr : t_natural_arr(1 to c_m) := func_sdp_sdo_nof_beamlets_per_block_last_destination_look_up_table; - constant c_nof_ch_per_packet_first_destination_arr : t_natural_arr(1 to c_m) := func_sdp_sdo_nof_ch_per_packet_first_destination_look_up_table; - constant c_nof_ch_per_packet_last_destination_arr : t_natural_arr(1 to c_m) := func_sdp_sdo_nof_ch_per_packet_last_destination_look_up_table; + -- Look up table constants as function of nof_destinations in range(g_nof_destinations_max) + constant c_m : natural := g_nof_destinations_max; + constant c_reorder_nof_blocks_arr : t_natural_arr(1 to c_m) := func_sdp_bdo_reorder_nof_blocks_look_up_table(g_nof_destinations_max); + constant c_reorder_nof_ch_arr : t_natural_arr(1 to c_m) := func_sdp_bdo_reorder_nof_ch_look_up_table(g_nof_destinations_max); + constant c_nof_beamlets_per_block_first_destination_arr : t_natural_arr(1 to c_m) := func_sdp_bdo_nof_beamlets_per_block_first_destination_look_up_table(g_nof_destinations_max); + constant c_nof_beamlets_per_block_last_destination_arr : t_natural_arr(1 to c_m) := func_sdp_bdo_nof_beamlets_per_block_last_destination_look_up_table(g_nof_destinations_max); + constant c_nof_ch_per_packet_first_destination_arr : t_natural_arr(1 to c_m) := func_sdp_bdo_nof_ch_per_packet_first_destination_look_up_table(g_nof_destinations_max); + constant c_nof_ch_per_packet_last_destination_arr : t_natural_arr(1 to c_m) := func_sdp_bdo_nof_ch_per_packet_last_destination_look_up_table(g_nof_destinations_max); constant c_beamlet_index_per_destination_mat : t_natural_matrix(1 to c_m, 0 to c_m - 1) := - func_sdp_sdo_beamlet_index_per_destination_look_up_matrix; + func_sdp_bdo_beamlet_index_per_destination_look_up_matrix(g_nof_destinations_max); constant c_nof_ch_per_packet_max : natural := largest(c_nof_ch_per_packet_first_destination_arr); constant c_nof_ch_per_packet_w : natural := ceil_log2(c_nof_ch_per_packet_max + 1); @@ -97,10 +103,9 @@ architecture str of sdp_bdo_multiple_destinations is signal i_destinations_info : t_sdp_bdo_destinations_info; -- Dynamic merge, reorder, unmerge packet sizes - -- . default use values for N_destinations = 1 - signal nof_blocks_per_packet : natural := c_nof_blocks_per_packet_arr(1); + -- . default use values for nof_destinations = 1 signal reorder_nof_blocks : natural := c_reorder_nof_blocks_arr(1); - signal reorder_nof_blocks_slv : std_logic_vector(c_reorder_nof_blocks_w - 1 downto 0); + signal reorder_nof_blocks_slv : std_logic_vector(c_sdp_bdo_reorder_nof_blocks_w - 1 downto 0); signal reorder_nof_ch : natural := c_reorder_nof_ch_arr(1); signal nof_beamlets_per_block_first_destination : natural := c_nof_beamlets_per_block_first_destination_arr(1); signal nof_beamlets_per_block_last_destination : natural := c_nof_beamlets_per_block_last_destination_arr(1); @@ -110,14 +115,12 @@ architecture str of sdp_bdo_multiple_destinations is signal nof_ch_per_packet : natural; signal nof_ch_per_packet_slv : std_logic_vector(c_nof_ch_per_packet_w - 1 downto 0); - -- . default use values for N_destinations = 1 and destination index = 0 + -- . default use values for nof_destinations = 1 and destination index = 0 signal beamlet_index_per_destination_bset_0 : natural := c_beamlet_index_per_destination_mat(1, 0); signal beamlet_index_per_destination : natural := c_beamlet_index + c_beamlet_index_per_destination_mat(1, 0); signal select_copi : t_mem_copi := c_mem_copi_rst; signal select_cipo : t_mem_cipo := c_mem_cipo_rst; - signal r_identity : t_reorder_identity; - signal d_identity : t_reorder_identity; signal r_transpose : t_reorder_transpose; signal d_transpose : t_reorder_transpose; @@ -137,6 +140,9 @@ begin ----------------------------------------------------------------------------- -- Use dynamic sizes for beamlet data output to multiple destination. u_sdp_bdo_destinations_reg : entity work.sdp_bdo_destinations_reg + generic map ( + g_nof_destinations_max => g_nof_destinations_max + ) port map ( -- Clocks and reset mm_clk => mm_clk, @@ -162,7 +168,6 @@ begin begin if rising_edge(dp_clk) then v_DN := i_destinations_info.nof_destinations_act; - nof_blocks_per_packet <= i_destinations_info.nof_blocks_per_packet_act; reorder_nof_blocks <= c_reorder_nof_blocks_arr(v_DN); reorder_nof_ch <= c_reorder_nof_ch_arr(v_DN); nof_beamlets_per_block_first_destination <= c_nof_beamlets_per_block_first_destination_arr(v_DN); @@ -181,12 +186,12 @@ begin ----------------------------------------------------------------------------- -- Use slv in port map to avoid vcom-1436: Actual expression (function call -- "TO_UVEC") of formal "nof_pkt" is not globally static. - reorder_nof_blocks_slv <= to_uvec(reorder_nof_blocks, c_reorder_nof_blocks_w); + reorder_nof_blocks_slv <= to_uvec(reorder_nof_blocks, c_sdp_bdo_reorder_nof_blocks_w); u_dp_packet_merge : entity dp_lib.dp_packet_merge generic map( g_use_ready => false, -- no flow control - g_nof_pkt => c_reorder_nof_blocks_max, + g_nof_pkt => c_sdp_bdo_reorder_nof_blocks_max, g_bsn_increment => 1 ) port map( @@ -206,13 +211,15 @@ begin ----------------------------------------------------------------------------- -- reorder_col_select -- . See tb_reorder_col_select_all.vhd for how to control col_select_copi / - -- cipo with p_reorder_identity or p_reorder_transpose. + -- cipo with p_reorder_transpose. + -- . Reorder nof_ch_sel = c_nof_ch_in = reorder_nof_ch, because the reorder + -- outputs all input. ----------------------------------------------------------------------------- u_reorder_col_select : entity reorder_lib.reorder_col_select generic map ( g_dsp_data_w => c_sdp_W_dual_pol_beamlet / c_nof_complex, -- = 32b / 2 - g_nof_ch_in => c_reorder_nof_ch_max, - g_nof_ch_sel => c_reorder_nof_ch_max, + g_nof_ch_in => c_sdp_bdo_reorder_nof_ch_max, + g_nof_ch_sel => c_sdp_bdo_reorder_nof_ch_max, g_use_complex => false ) port map ( @@ -245,37 +252,19 @@ begin p_dp_clk : process(dp_clk) begin if rising_edge(dp_clk) then - r_identity <= d_identity; r_transpose <= d_transpose; end if; end process; - -- Pass on beamlet data in original order or in transposed order - select_copi <= r_transpose.select_copi when g_use_transpose else r_identity.select_copi; - - p_reorder_identity : process(dp_rst, select_cipo, reorder_nof_ch, r_identity) - variable v : t_reorder_identity; - begin - if select_cipo.waitrequest = '0' then - -- Read from reorder_col_select page - v := func_reorder_identity(reorder_nof_ch, r_identity); - else - -- No read, new reorder_col_select page not available yet - v := c_reorder_identity_rst; - end if; - -- Synchronous reset - if dp_rst = '1' then - v := c_reorder_identity_rst; - end if; - d_identity <= v; - end process; + -- Pass on beamlet data in transposed order + select_copi <= r_transpose.select_copi; - p_reorder_transpose : process(dp_rst, select_cipo, nof_blocks_per_packet, nof_beamlets_per_block, r_transpose) + p_reorder_transpose : process(dp_rst, select_cipo, reorder_nof_blocks, nof_beamlets_per_block, r_transpose) variable v : t_reorder_transpose; begin if select_cipo.waitrequest = '0' then -- Read from reorder_col_select page - v := func_reorder_transpose(nof_blocks_per_packet, nof_beamlets_per_block, r_transpose); + v := func_reorder_transpose(reorder_nof_blocks, nof_beamlets_per_block, r_transpose); else -- No read, new reorder_col_select page not available yet v := c_reorder_transpose_rst; @@ -288,14 +277,14 @@ begin end process; ----------------------------------------------------------------------------- - -- dp_packet_unmerge for N_destinations + -- dp_packet_unmerge for nof_destinations ----------------------------------------------------------------------------- nof_ch_per_packet_slv <= to_uvec(nof_ch_per_packet, c_nof_ch_per_packet_w); u_dp_packet_unmerge : entity dp_lib.dp_packet_unmerge generic map ( g_use_ready => false, -- no flow control - g_nof_pkt => c_reorder_nof_blocks_max, + g_nof_pkt => g_nof_destinations_max, g_pkt_len => c_nof_ch_per_packet_max, g_bsn_increment => 1 ) diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_pkg.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_pkg.vhd index 098d853c91e7c3dac21ceae9d02aaecf8c7e9680..96dafef61e3282ebfe52d8fec163430eef388f16 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_pkg.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_pkg.vhd @@ -34,121 +34,134 @@ use work.sdp_pkg.all; package sdp_bdo_pkg is -- Beamlet data output (BDO) for multiple destinations - constant c_sdp_bdo_nof_destinations_max : natural := 16; - constant c_sdp_bdo_reorder_nof_blocks_max : natural := largest(16, c_sdp_cep_nof_blocks_per_packet); - constant c_sdp_bdo_destinations_info_nof_hdr_fields : natural := c_sdp_bdo_nof_destinations_max * 3 + 4; -- = 52 fields + -- Define the maximum number of destination to size the address span of the + -- MM register in sdp_bdo_destinations_reg. The actual nof_destinations_max + -- <= c_sdp_bdo_mm_nof_destinations_max is defined as revision constant, so + -- that it can differ per design revision. + constant c_sdp_bdo_mm_nof_destinations_max : natural := 32; + + -- Define the maximum number of blocks (= time samples per beamlet) here as + -- a package constant, because it can be the same for all design revisions. + -- The actual reorder_nof_blocks_max depends slightly on + -- nof_destinations_max, because the number of blocks has to fit in a jumbo + -- frame. Therefore func_sdp_bdo_reorder_nof_blocks_look_up_table() + -- determines the actual reorder_nof_blocks. + -- The nof_blocks_per_packet = reorder_nof_blocks. The beamlet packets will + -- have the same nof_blocks_per_packet for each destination, because the + -- blocks represent beamlet time samples that have to be kept together per + -- destination. The beamlets are distributed to the different destinations + -- based on their beamlet index as defined by + -- func_sdp_bdo_nof_beamlets_per_block_first_destination_look_up_table(). + -- The minimum value is c_sdp_cep_nof_blocks_per_packet = 4 to fill a jumbo + -- frame when nof_destinations = 1. + -- The maximum value is a balance between having sufficiently large packets + -- nof_destinations > 1 and how many block RAM resources are available for + -- the reordering. Therefore c_sdp_bdo_reorder_nof_blocks_max = 16 is a + -- suitable compromise value. + constant c_sdp_bdo_reorder_nof_blocks_max : natural := 16; + constant c_sdp_bdo_reorder_nof_blocks_w : natural := ceil_log2(c_sdp_bdo_reorder_nof_blocks_max + 1); + constant c_sdp_bdo_reorder_nof_ch_max : natural := c_sdp_bdo_reorder_nof_blocks_max * + c_sdp_nof_beamlets_per_block * + c_sdp_nof_words_per_beamlet; -- = 7808 + + -- 32 * 3 + 4 = 100 fields + constant c_sdp_bdo_destinations_info_nof_hdr_fields : natural := c_sdp_bdo_mm_nof_destinations_max * 3 + 4; type t_sdp_bdo_destinations_info is record - eth_destination_mac_arr : t_slv_48_arr(c_sdp_bdo_nof_destinations_max - 1 downto 0); - ip_destination_address_arr : t_slv_32_arr(c_sdp_bdo_nof_destinations_max - 1 downto 0); - udp_destination_port_arr : t_slv_16_arr(c_sdp_bdo_nof_destinations_max - 1 downto 0); + eth_destination_mac_arr : t_slv_48_arr(c_sdp_bdo_mm_nof_destinations_max - 1 downto 0); + ip_destination_address_arr : t_slv_32_arr(c_sdp_bdo_mm_nof_destinations_max - 1 downto 0); + udp_destination_port_arr : t_slv_16_arr(c_sdp_bdo_mm_nof_destinations_max - 1 downto 0); nof_destinations : natural; nof_destinations_act : natural; nof_destinations_max : natural; - nof_blocks_per_packet_act : natural; + nof_blocks_per_packet : natural; end record; - constant t_sdp_bdo_destinations_info_rst : t_sdp_bdo_destinations_info := + constant c_sdp_bdo_destinations_info_rst : t_sdp_bdo_destinations_info := ( (others => (others => '0')), (others => (others => '0')), (others => (others => '0')), 1, 1, - c_sdp_bdo_nof_destinations_max, + 1, c_sdp_cep_nof_blocks_per_packet); -- Parse user input to determine actual nof_destinations - function func_sdp_bdo_parse_nof_destinations(nof_destinations : natural) return natural; + function func_sdp_bdo_parse_nof_destinations(nof_destinations, c_nof_destinations_max : natural) return natural; -- Use functions that return look up tables to precalculate the values as -- constant arrays -- . One ch (channel) = one 32b word = one dual polarization beamlet (Xre, Xim, Yre, Yim) - -- . Look up table arrays for: t_natural_arr(1 to c_sdp_bdo_nof_destinations_max) - function func_sdp_bdo_nof_blocks_per_packet_look_up_table return t_natural_arr; - function func_sdp_bdo_reorder_nof_blocks_look_up_table return t_natural_arr; - function func_sdp_bdo_reorder_nof_ch_look_up_table return t_natural_arr; - function func_sdp_sdo_nof_beamlets_per_block_first_destination_look_up_table return t_natural_arr; - function func_sdp_sdo_nof_beamlets_per_block_last_destination_look_up_table return t_natural_arr; - function func_sdp_sdo_nof_ch_per_packet_first_destination_look_up_table return t_natural_arr; - function func_sdp_sdo_nof_ch_per_packet_last_destination_look_up_table return t_natural_arr; + -- . Look up table arrays for: t_natural_arr(1 to c_nof_destinations_max) + function func_sdp_bdo_reorder_nof_blocks_look_up_table(c_nof_destinations_max : natural) return t_natural_arr; + function func_sdp_bdo_reorder_nof_ch_look_up_table(c_nof_destinations_max : natural) return t_natural_arr; + function func_sdp_bdo_nof_beamlets_per_block_first_destination_look_up_table(c_nof_destinations_max : natural) return t_natural_arr; + function func_sdp_bdo_nof_beamlets_per_block_last_destination_look_up_table(c_nof_destinations_max : natural) return t_natural_arr; + function func_sdp_bdo_nof_ch_per_packet_first_destination_look_up_table(c_nof_destinations_max : natural) return t_natural_arr; + function func_sdp_bdo_nof_ch_per_packet_last_destination_look_up_table(c_nof_destinations_max : natural) return t_natural_arr; -- Look up table matrix for: - -- t_natural_matrix(1 to c_sdp_bdo_nof_destinations_max, -- N_destinations - -- 0 to c_sdp_bdo_nof_destinations_max - 1) -- destination index - function func_sdp_sdo_beamlet_index_per_destination_look_up_matrix return t_natural_matrix; + -- t_natural_matrix(1 to c_nof_destinations_max, -- N_destinations + -- 0 to c_nof_destinations_max - 1) -- destination index + function func_sdp_bdo_beamlet_index_per_destination_look_up_matrix(c_nof_destinations_max : natural) return t_natural_matrix; end package sdp_bdo_pkg; package body sdp_bdo_pkg is - function func_sdp_bdo_parse_nof_destinations(nof_destinations : natural) return natural is + function func_sdp_bdo_parse_nof_destinations(nof_destinations, c_nof_destinations_max : natural) return natural is begin -- Parse input nof_destinations value if nof_destinations = 0 then return 1; - elsif nof_destinations > c_sdp_bdo_nof_destinations_max then - return c_sdp_bdo_nof_destinations_max; + elsif nof_destinations > c_nof_destinations_max then + return c_nof_destinations_max; else return nof_destinations; end if; end func_sdp_bdo_parse_nof_destinations; - function func_sdp_bdo_nof_blocks_per_packet_look_up_table return t_natural_arr is - variable v_arr : t_natural_arr(1 to c_sdp_bdo_nof_destinations_max); + function func_sdp_bdo_reorder_nof_blocks_look_up_table(c_nof_destinations_max : natural) return t_natural_arr is + variable v_arr : t_natural_arr(1 to c_nof_destinations_max); begin - -- Determine nof_blocks_per_packet as function of number of destinations - -- DN. - -- . With 1 destination c_sdp_cep_nof_blocks_per_packet = 4 can fit in a - -- jumbo frame. + -- Determine reorder_nof_blocks = nof_blocks_per_packet as function of + -- c_sdp_bdo_reorder_nof_blocks_max and the number of destinations DN. + -- . With DN = 1 destination c_sdp_cep_nof_blocks_per_packet = 4 can fit + -- in a jumbo frame. -- . With DN destinations DN * c_sdp_cep_nof_blocks_per_packet can fit in - -- a jumbo frame, because the number of beamlets per destination reduces - -- by DN. + -- a jumbo frame, because the number of beamlet indices per destination + -- reduces by DN. -- DN = 1:16 --> 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64 - -- . In total there are maximum c_sdp_bdo_reorder_nof_blocks_max = 16 - -- blocks to distribute over DN destinations. - -- . Taking smallest yields the actual maximum number of blocks per packet - -- per destination, as function of number of destinations DN: + -- . In total there can be maximum c_sdp_bdo_reorder_nof_blocks_max = 16 + -- blocks per packet, due to the size of the reorder buffer. Taking + -- smallest yields the actual number of blocks per packet, as function + -- of number of destinations DN: -- DN = 1:16 --> 4, 8, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 - for DN in 1 to c_sdp_bdo_nof_destinations_max loop - v_arr(DN) := smallest(c_sdp_bdo_reorder_nof_blocks_max, DN * c_sdp_cep_nof_blocks_per_packet); - end loop; - return v_arr; - end func_sdp_bdo_nof_blocks_per_packet_look_up_table; - - function func_sdp_bdo_reorder_nof_blocks_look_up_table return t_natural_arr is - constant c_arr : t_natural_arr(1 to c_sdp_bdo_nof_destinations_max) := - func_sdp_bdo_nof_blocks_per_packet_look_up_table; - variable v_arr : t_natural_arr(1 to c_sdp_bdo_nof_destinations_max); - begin - -- Determine reorder_nof_blocks as function of number of destinations DN. - -- . The number of blocks per destination is given by c_arr, so the number - -- of blocks that need to be merged for the reorder is DN * c_arr(DN): - -- DN = 1:16 --> 4, 16, 15, 16, 15, 12, 14, 16, 9, 10, 11, 12, 13, 14, 15, 16 - for DN in 1 to c_sdp_bdo_nof_destinations_max loop - v_arr(DN) := DN * c_arr(DN); + for DN in 1 to c_nof_destinations_max loop + v_arr(DN) := smallest(DN * c_sdp_cep_nof_blocks_per_packet, c_sdp_bdo_reorder_nof_blocks_max); end loop; return v_arr; end func_sdp_bdo_reorder_nof_blocks_look_up_table; - function func_sdp_bdo_reorder_nof_ch_look_up_table return t_natural_arr is - constant c_arr : t_natural_arr(1 to c_sdp_bdo_nof_destinations_max) := - func_sdp_bdo_reorder_nof_blocks_look_up_table; - variable v_arr : t_natural_arr(1 to c_sdp_bdo_nof_destinations_max); + function func_sdp_bdo_reorder_nof_ch_look_up_table(c_nof_destinations_max : natural) return t_natural_arr is + constant c_arr : t_natural_arr(1 to c_nof_destinations_max) := + func_sdp_bdo_reorder_nof_blocks_look_up_table(c_nof_destinations_max); + variable v_arr : t_natural_arr(1 to c_nof_destinations_max); begin -- Determine reorder nof_ch as function of number of destinations DN. - -- . The number of blocks to reorder is given by c_arr, so the number - -- of ch (channels = words) that need to be reordered is c_sdp_S_sub_bf - -- * c_arr(DN): - -- DN = 1:16 --> 1952, 7808, 7320, 7808, 7320, 5856, 6832, 7808 - -- 4392, 4880, 5368, 5856, 6344, 6832, 7320, 7808 - for DN in 1 to c_sdp_bdo_nof_destinations_max loop + -- . The number of blocks to reorder is given by c_arr, so the number of + -- ch (channels = words = dual pol, complex beamlets) that need to be + -- reordered is c_sdp_S_sub_bf * c_arr(DN): + -- DN = 1:16 --> 1952, 3904, 5856, 7808, 7808, 7808, 7808, 7808 + -- 7808, 7808, 7808, 7808, 7808, 7808, 7808, 7808 + for DN in 1 to c_nof_destinations_max loop v_arr(DN) := c_sdp_S_sub_bf * c_arr(DN); end loop; return v_arr; end func_sdp_bdo_reorder_nof_ch_look_up_table; - function func_sdp_sdo_nof_beamlets_per_block_first_destination_look_up_table return t_natural_arr is - variable v_first_arr : t_natural_arr(1 to c_sdp_bdo_nof_destinations_max); + function func_sdp_bdo_nof_beamlets_per_block_first_destination_look_up_table(c_nof_destinations_max : natural) return t_natural_arr is + variable v_first_arr : t_natural_arr(1 to c_nof_destinations_max); begin -- Determine nof_beamlets_per_block for the first 1:DN-1 destinations, as -- function of number of destinations DN. @@ -156,19 +169,19 @@ package body sdp_bdo_pkg is -- distribute over DN destinations, so ceil(488 / DN) yields the number of -- blocks for the first 1:DN-1 destinations: -- DN = 1:16 --> v_first_arr = 488, 244, 163, 122, 98, 82, 70, 61, 55, 49, 45, 41, 38, 35, 33, 31 - for DN in 1 to c_sdp_bdo_nof_destinations_max loop + for DN in 1 to c_nof_destinations_max loop v_first_arr(DN) := ceil_div(c_sdp_S_sub_bf, DN); end loop; return v_first_arr; - end func_sdp_sdo_nof_beamlets_per_block_first_destination_look_up_table; + end func_sdp_bdo_nof_beamlets_per_block_first_destination_look_up_table; - function func_sdp_sdo_nof_beamlets_per_block_last_destination_look_up_table return t_natural_arr is - variable v_first_arr : t_natural_arr(1 to c_sdp_bdo_nof_destinations_max) := - func_sdp_sdo_nof_beamlets_per_block_first_destination_look_up_table; - variable v_last_arr : t_natural_arr(1 to c_sdp_bdo_nof_destinations_max); + function func_sdp_bdo_nof_beamlets_per_block_last_destination_look_up_table(c_nof_destinations_max : natural) return t_natural_arr is + variable v_first_arr : t_natural_arr(1 to c_nof_destinations_max) := + func_sdp_bdo_nof_beamlets_per_block_first_destination_look_up_table(c_nof_destinations_max); + variable v_last_arr : t_natural_arr(1 to c_nof_destinations_max); begin - -- Determine nof_beamlets_per_block for the last destination with index DN, - -- as function of number of destinations DN. + -- Determine remaining nof_beamlets_per_block for the last destination + -- with index DN, as function of number of destinations DN. -- . In total there are c_sdp_S_sub_bf = 488 dual polarization beamlets to -- distribute over DN destinations, so 488 - (DN-1) * ceil(488 / DN) -- beamlets remain for the last destination: @@ -176,27 +189,26 @@ package body sdp_bdo_pkg is -- DN = 1:16 --> v_last_arr = 488, 244, 162, 122, 96, 78, 68, 61, 48, 47, 38, 37, 32, 33, 26, 23 -- -- Remark: - -- . The v_last_arr may be < v_first_arr - 1, so the last destination may - -- contain much less beamlets than the others. In combination with - -- dp_packet_unmerge it is not feasible to distribute the beamlets evenly - -- over all destinations, using v_hi beamlets for some first destinations - -- and v_lo = v_hi - 1 for the remaining destinations. This is because - -- dp_packet_unmerge can only unmerge the same packet length for N - 1 - -- blocks and then unmerge the remaining data in the last block until the - -- eop. - -- - for DN in 1 to c_sdp_bdo_nof_destinations_max loop + -- . The v_last_arr(DN) may be < v_first_arr(DN) - 1, so the last + -- destination may contain much less beamlets than the others. In + -- combination with dp_packet_unmerge it is not feasible to distribute + -- the beamlets evenly over all destinations, using v_hi beamlets for + -- some first destinations and v_lo = v_hi - 1 for the remaining + -- destinations. This is because dp_packet_unmerge can only unmerge the + -- same packet length for N - 1 blocks and then unmerge the remaining + -- data in the last block until the eop. + for DN in 1 to c_nof_destinations_max loop v_last_arr(DN) := c_sdp_S_sub_bf - (DN - 1) * v_first_arr(DN); end loop; return v_last_arr; - end func_sdp_sdo_nof_beamlets_per_block_last_destination_look_up_table; + end func_sdp_bdo_nof_beamlets_per_block_last_destination_look_up_table; - function func_sdp_sdo_nof_ch_per_packet_first_destination_look_up_table return t_natural_arr is - constant c_nof_blocks_arr : t_natural_arr(1 to c_sdp_bdo_nof_destinations_max) := - func_sdp_bdo_nof_blocks_per_packet_look_up_table; - constant c_nof_beamlets_arr : t_natural_arr(1 to c_sdp_bdo_nof_destinations_max) := - func_sdp_sdo_nof_beamlets_per_block_first_destination_look_up_table; - variable v_len_arr : t_natural_arr(1 to c_sdp_bdo_nof_destinations_max); + function func_sdp_bdo_nof_ch_per_packet_first_destination_look_up_table(c_nof_destinations_max : natural) return t_natural_arr is + constant c_nof_blocks_arr : t_natural_arr(1 to c_nof_destinations_max) := + func_sdp_bdo_reorder_nof_blocks_look_up_table(c_nof_destinations_max); + constant c_nof_beamlets_arr : t_natural_arr(1 to c_nof_destinations_max) := + func_sdp_bdo_nof_beamlets_per_block_first_destination_look_up_table(c_nof_destinations_max); + variable v_len_arr : t_natural_arr(1 to c_nof_destinations_max); begin -- Determine nof_ch per packet for the first 1:DN-1 destinations, as -- function of number of destinations DN. @@ -205,18 +217,18 @@ package body sdp_bdo_pkg is -- . c_nof_beamlets_arr = 488, 244, 163, 122, 98, 82, 70, 61, 55, 49, 45, 41, 38, 35, 33, 31 -- . v_len_arr = 1952,1952,1956,1952,1568,1312,1120, 976, 880, 784, 720, 656, 608, 560, 528, 496 -- . nof octets = 7808,7808,7824,7808,6272,5248,4480,3904,3520,3136,2880,2624,2432,2240,2112,1984 - for DN in 1 to c_sdp_bdo_nof_destinations_max loop + for DN in 1 to c_nof_destinations_max loop v_len_arr(DN) := c_nof_blocks_arr(DN) * c_nof_beamlets_arr(DN); end loop; return v_len_arr; - end func_sdp_sdo_nof_ch_per_packet_first_destination_look_up_table; + end func_sdp_bdo_nof_ch_per_packet_first_destination_look_up_table; - function func_sdp_sdo_nof_ch_per_packet_last_destination_look_up_table return t_natural_arr is - constant c_nof_blocks_arr : t_natural_arr(1 to c_sdp_bdo_nof_destinations_max) := - func_sdp_bdo_nof_blocks_per_packet_look_up_table; - constant c_nof_beamlets_arr : t_natural_arr(1 to c_sdp_bdo_nof_destinations_max) := - func_sdp_sdo_nof_beamlets_per_block_last_destination_look_up_table; - variable v_len_arr : t_natural_arr(1 to c_sdp_bdo_nof_destinations_max); + function func_sdp_bdo_nof_ch_per_packet_last_destination_look_up_table(c_nof_destinations_max : natural) return t_natural_arr is + constant c_nof_blocks_arr : t_natural_arr(1 to c_nof_destinations_max) := + func_sdp_bdo_reorder_nof_blocks_look_up_table(c_nof_destinations_max); + constant c_nof_beamlets_arr : t_natural_arr(1 to c_nof_destinations_max) := + func_sdp_bdo_nof_beamlets_per_block_last_destination_look_up_table(c_nof_destinations_max); + variable v_len_arr : t_natural_arr(1 to c_nof_destinations_max); begin -- Determine nof_ch per packet for the first 1:DN-1 destinations, as -- function of number of destinations DN. @@ -225,22 +237,22 @@ package body sdp_bdo_pkg is -- . c_nof_beamlets_arr = 488, 244, 162, 122, 96, 78, 68, 61, 48, 47, 38, 37, 32, 33, 26, 23 -- . v_len_arr = 1952,1952,1944,1952,1536,1248,1088, 976, 768, 752, 608, 592, 512, 528, 416, 368 -- . nof octets = 7808,7808,7776,7808,6144,4992,4352,3904,3072,3008,2432,2368,2048,2112,1664,1472 - for DN in 1 to c_sdp_bdo_nof_destinations_max loop + for DN in 1 to c_nof_destinations_max loop v_len_arr(DN) := c_nof_blocks_arr(DN) * c_nof_beamlets_arr(DN); end loop; return v_len_arr; - end func_sdp_sdo_nof_ch_per_packet_last_destination_look_up_table; + end func_sdp_bdo_nof_ch_per_packet_last_destination_look_up_table; - function func_sdp_sdo_beamlet_index_per_destination_look_up_matrix return t_natural_matrix is - constant c_len_arr : t_natural_arr(1 to c_sdp_bdo_nof_destinations_max) := - func_sdp_sdo_nof_beamlets_per_block_first_destination_look_up_table; - variable v_index_mat : t_natural_matrix(1 to c_sdp_bdo_nof_destinations_max, - 0 to c_sdp_bdo_nof_destinations_max - 1); + function func_sdp_bdo_beamlet_index_per_destination_look_up_matrix(c_nof_destinations_max : natural) return t_natural_matrix is + constant c_len_arr : t_natural_arr(1 to c_nof_destinations_max) := + func_sdp_bdo_nof_beamlets_per_block_first_destination_look_up_table(c_nof_destinations_max); + variable v_index_mat : t_natural_matrix(1 to c_nof_destinations_max, + 0 to c_nof_destinations_max - 1); variable v_beamlet_index : natural; variable v_step : natural; begin -- Determine beamlet index of first beamlet in packet per destination with - -- index DN, as function of number of destinations DN. + -- index DI, as function of number of destinations DN. -- . Beamlet index for first destination starts at 0 -- . Beamlet index for the other destinations increments with number of -- beamlets per previous destination given by c_len_arr. @@ -280,10 +292,10 @@ package body sdp_bdo_pkg is -- v_beamlet_index += v_step -- print(lineStr) -- - for DN in 1 to c_sdp_bdo_nof_destinations_max loop + for DN in 1 to c_nof_destinations_max loop v_beamlet_index := 0; v_step := c_len_arr(DN); - for DI in 0 to c_sdp_bdo_nof_destinations_max - 1 loop + for DI in 0 to c_nof_destinations_max - 1 loop if v_beamlet_index < c_sdp_S_sub_bf then v_index_mat(DN, DI) := v_beamlet_index; end if; @@ -291,5 +303,5 @@ package body sdp_bdo_pkg is end loop; end loop; return v_index_mat; - end func_sdp_sdo_beamlet_index_per_destination_look_up_matrix; + end func_sdp_bdo_beamlet_index_per_destination_look_up_matrix; end sdp_bdo_pkg;