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 8a855419e5a7d760841b55b188169abf6bbdbb71..c79b23ab4cf4021ac721c5007a7620173c127b20 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_pkg.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_pkg.vhd @@ -53,31 +53,17 @@ package sdp_bdo_pkg is (others => (others => '0')), (others => (others => '0')), 0, 0, 0 ); - -- Select header destination MAC, IP, UDP field from data path, to support - -- BDO multiple destinations register - function func_sdp_bdo_cep_hdr_field_sel_dest(sl : std_logic) return std_logic_vector; - -- Determine actual nof_destinations and actual nof_blocks_per_packet function func_sdp_bdo_parse_nof_destinations(nof_destinations : natural) return natural; function func_sdp_bdo_nof_blocks_per_packet_look_up_table return t_natural_arr; -- Determine nof_beamlets_per_block per destination - function func_sdp_nof_beamlets_per_block_look_up_table return t_natural_arr; - function func_sdp_nof_beamlets_per_block_look_up_matrix return t_natural_matrix; + 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_beamlet_index_per_destination_look_up_matrix return t_natural_matrix; end package sdp_bdo_pkg; package body sdp_bdo_pkg is - function func_sdp_bdo_cep_hdr_field_sel_dest(sl : std_logic) return std_logic_vector is - variable v_sel : std_logic_vector(c_sdp_cep_nof_hdr_fields - 1 downto 0) := c_sdp_cep_hdr_field_sel; - begin - -- Select header destination MAC, IP, UDP field from data path instead of - -- from MM in dp_offload_tx_v3 - v_sel(38) := sl; -- eth_dst_mac - v_sel(24) := sl; -- ip_dst_addr - v_sel(22) := sl; -- udp_dst_port - return v_sel; - end func_sdp_bdo_cep_hdr_field_sel_dest; - function func_sdp_bdo_parse_nof_destinations(nof_destinations : natural) return natural is begin -- Parse input nof_destinations value @@ -114,70 +100,112 @@ package body sdp_bdo_pkg is return v_arr; end func_sdp_bdo_nof_blocks_per_packet_look_up_table; - function func_sdp_nof_beamlets_per_block_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_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); begin - -- Determine nof_beamlets_per_block as function of number of destinations D. Use - -- look up table to precalculate the values as constants. + -- Determine nof_beamlets_per_block for the first 1:DN-1 destinations, as + -- function of number of destinations DN. Use look up table to precalculate + -- the values as constants. -- . In total there are c_sdp_S_sub_bf = 488 dual polarization beamlets to - -- distribute over D destinations, so ceil(488 / D) per destination yields: - -- D = 1:16 --> 488, 244, 163, 122, 98, 82, 70, 61, 55, 49, 45, 41, 38, 35, 33, 31 - for D in 1 to c_sdp_bdo_nof_destinations_max loop - v_arr(D) := ceil_div(c_sdp_S_sub_bf, D); + -- 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 + v_first_arr(DN) := ceil_div(c_sdp_S_sub_bf, DN); end loop; - return v_arr; - end func_sdp_nof_beamlets_per_block_look_up_table; + return v_first_arr; + end func_sdp_sdo_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); + begin + -- Determine nof_beamlets_per_block for the last destination with index DN, + -- as function of number of destinations DN. Use look up table to + -- precalculate the values as constants. + -- . 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: + -- DN = 1:16 --> v_first_arr = 488, 244, 163, 122, 98, 82, 70, 61, 55, 49, 45, 41, 38, 35, 33, 31 + -- 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 + 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; - function func_sdp_nof_beamlets_per_block_look_up_matrix return t_natural_matrix is - constant c_arr : t_natural_arr(1 to c_sdp_bdo_nof_destinations_max) := - func_sdp_nof_beamlets_per_block_look_up_table; - variable v_mat : t_natural_matrix(1 to c_sdp_bdo_nof_destinations_max, - 1 to c_sdp_bdo_nof_destinations_max); - variable v_hi : natural; - variable v_lo : natural; + 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); + variable v_beamlet_index : natural; + variable v_step : natural; begin - -- Determine nof_beamlets_per_block as function of number of destinations DN and - -- destination index DI. Use look up table to precalculate the values as constants. + -- Determine beamlet index of first beamlet in packet per destination with + -- index DN, as function of number of destinations DN. Use look up table to + -- precalculate the values as constants. + -- . 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. -- - -- * vertical : nof_destinations DN - -- * horizontal : destination index DI + -- * rows: nof_destinations DN + -- * columns: destination index DI -- - -- DI: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 + -- DI: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 -- DN: - -- 1 488, 0, .................................................................0 - -- 2 244, 244, 0 . - -- 3 163, 163, 162, 0 . - -- 4 122, 122, 122, 122, 0 . - -- 5 98, 98, 98, 97, 97, 0 . - -- 6 82, 82, 81, 81, 81, 81, 0 . - -- 7 70, 70, 70, 70, 70, 69, 69, 0 . - -- 8 61, 61, 61, 61, 61, 61, 61, 61, 0 . - -- 9 55, 55, 57, 57, 57, 57, 57, 57, 57, 0 . - -- 10 49, 49, 49, 49, 49, 49, 49, 49, 48, 48, 0 . - -- 11 45, 45, 45, 45, 44, 44, 44, 44, 44, 44, 44, 0 . - -- 12 41, 41, 41, 41, 41, 41, 41, 41, 40, 40, 40, 40, 0 . - -- 13 38, 38, 38, 38, 38, 38, 38, 37, 37, 37, 37, 37, 37, 0 . - -- 14 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 34, 34, 0 . - -- 15 33, 33, 33, 33, 33, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 0 - -- 16 31, 31, 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 30, 30, 30 + -- 1 0, 0.....................................................................0 + -- 2 0, 244, 0 . + -- 3 0, 163, 326, 0 . + -- 4 0, 122, 244, 366, 0 . + -- 5 0, 98, 196, 294, 392, 0 . + -- 6 0, 82, 164, 246, 328, 410, 0 . + -- 7 0, 70, 140, 210, 280, 350, 420, 0 . + -- 8 0, 61, 122, 183, 244, 305, 366, 427, 0 . + -- 9 0, 55, 110, 165, 220, 275, 330, 385, 440, 0 . + -- 10 0, 49, 98, 147, 196, 245, 294, 343, 392, 441, 0 . + -- 11 0, 45, 90, 135, 180, 225, 270, 315, 360, 405, 450, 0 . + -- 12 0, 41, 82, 123, 164, 205, 246, 287, 328, 369, 410, 451, 0 . + -- 13 0, 38, 76, 114, 152, 190, 228, 266, 304, 342, 380, 418, 456, 0 . + -- 14 0, 35, 70, 105, 140, 175, 210, 245, 280, 315, 350, 385, 420, 455, 0 . + -- 15 0, 33, 66, 99, 132, 165, 198, 231, 264, 297, 330, 363, 396, 429, 462, 0 + -- 16 0, 31, 62, 93, 124, 155, 186, 217, 248, 279, 310, 341, 372, 403, 434, 465 + -- + -- Equivalent Python code to produce matrix: + -- + -- c_len_arr = [488, 244, 163, 122, 98, 82, 70, 61, 55, 49, 45, 41, 38, 35, 33, 31] + -- for DN in range(16): + -- lineStr = '%2d ' % (DN + 1) + -- v_beamlet_index = 0 + -- v_step = c_len_arr[DN] + -- for DI in range(16): + -- if v_beamlet_index < 488: + -- lineStr += '%4d,' % v_beamlet_index + -- v_beamlet_index += v_step + -- print(lineStr) + -- for DN in 1 to c_sdp_bdo_nof_destinations_max loop - v_hi := c_arr(DN); - v_lo := v_hi - 1; - for DI in 1 to c_sdp_bdo_nof_destinations_max loop - -- Default initialize to zero for unused elements - v_mat(DN, DI) := 0; - -- Determine number of destinations in DN with v_hi value and with - -- v_lo value, to distribute in total c_sdp_S_sub_bf beamlets to DN - -- destinations. - if DI * v_hi + (DN - DI) * v_lo <= c_sdp_S_sub_bf then - -- Use v_hi for first destinations DI - v_mat(DN, DI) := v_hi; - else - -- Use v_lo for remaining destinations, if there are any remaining - v_mat(DN, DI) := v_lo; + v_beamlet_index := 0; + v_step := c_len_arr(DN); + for DI in 0 to c_sdp_bdo_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; + v_beamlet_index := v_beamlet_index + v_step; end loop; end loop; - return v_mat; - end func_sdp_nof_beamlets_per_block_look_up_matrix; + return v_index_mat; + end func_sdp_sdo_beamlet_index_per_destination_look_up_matrix; end sdp_bdo_pkg; diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd index 101842bae736d26bef4f1eac777280004e182a07..78cb5f8062d474f82d96b6f2b64dcf9407f3be91 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd @@ -685,6 +685,9 @@ package sdp_pkg is function func_sdp_map_stat_header(hdr_fields_raw : std_logic_vector) return t_sdp_stat_header; function func_sdp_map_cep_header(hdr_fields_raw : std_logic_vector) return t_sdp_cep_header; + -- Select header destination MAC, IP, UDP fields from DP (sl = 0) or from MM (sl = '1') in dp_offload_tx_v3 + function func_sdp_cep_hdr_field_sel_dst(sl : std_logic) return std_logic_vector; + function func_sdp_map_stat_data_id(g_statistics_type : string; data_id_slv : std_logic_vector) return t_sdp_stat_data_id; function func_sdp_map_stat_data_id(g_statistics_type : string; data_id_rec : t_sdp_stat_data_id) return std_logic_vector; @@ -948,6 +951,16 @@ package body sdp_pkg is return v; end func_sdp_map_cep_header; + function func_sdp_cep_hdr_field_sel_dst(sl : std_logic) return std_logic_vector is + variable v_sel : std_logic_vector(c_sdp_cep_nof_hdr_fields - 1 downto 0) := c_sdp_cep_hdr_field_sel; + begin + -- Select header destination MAC, IP, UDP field from DP or from MM in dp_offload_tx_v3 + v_sel(38) := sl; -- eth_dst_mac + v_sel(24) := sl; -- ip_dst_addr + v_sel(22) := sl; -- udp_dst_port + return v_sel; + end func_sdp_cep_hdr_field_sel_dst; + function func_sdp_map_stat_data_id(g_statistics_type : string; data_id_slv : std_logic_vector) return t_sdp_stat_data_id is variable v_rec : t_sdp_stat_data_id; begin