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 c79b23ab4cf4021ac721c5007a7620173c127b20..84c934a7ec8f039fc74bf031b1c20ab2f6292a52 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_pkg.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_pkg.vhd @@ -37,7 +37,7 @@ package sdp_bdo_pkg is 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 + 3; -- = 52 fields + constant c_sdp_bdo_destinations_info_nof_hdr_fields : natural := c_sdp_bdo_nof_destinations_max * 3 + 4; -- = 52 fields 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); @@ -45,21 +45,37 @@ package sdp_bdo_pkg is udp_destination_port_arr : t_slv_16_arr(c_sdp_bdo_nof_destinations_max - 1 downto 0); nof_destinations : natural; nof_destinations_act : natural; + nof_destinations_max : natural; nof_blocks_per_packet_act : natural; end record; constant t_sdp_bdo_destinations_info_rst : t_sdp_bdo_destinations_info := ( (others => (others => '0')), (others => (others => '0')), - (others => (others => '0')), 0, 0, 0 ); + (others => (others => '0')), + 1, + 1, + c_sdp_bdo_nof_destinations_max, + c_sdp_cep_nof_blocks_per_packet); - -- Determine actual nof_destinations and actual 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_nof_blocks_per_packet_look_up_table return t_natural_arr; - -- Determine nof_beamlets_per_block per destination + -- Use functions that return look up tables to precalculate the values as + -- constant arrays + + -- . 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 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; end package sdp_bdo_pkg; @@ -79,33 +95,62 @@ package body sdp_bdo_pkg is 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); begin - -- Determine nof_blocks_per_packet as function of number of destinations D. Use - -- look up table to precalculate the values as constants. - -- . Use same number of nof_blocks_per_packet for each destination. - -- . In total there are maximum c_sdp_bdo_reorder_nof_blocks_max = 16 blocks to - -- distribute over D destinations, so floor(16 / D) per destination yields: - -- D = 1:16 --> 16, 8, 5, 4, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1 - for D in 1 to c_sdp_bdo_nof_destinations_max loop - v_arr(D) := c_sdp_bdo_reorder_nof_blocks_max / D; - end loop; - -- . With 1 destination c_sdp_cep_nof_blocks_per_packet = 4 can fit in a jumbo frame. - -- . With D destinations D * c_sdp_cep_nof_blocks_per_packet can fit in a jumbo frame, - -- because the number of beamlets per destination reduces by D. + -- 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. + -- . 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. + -- 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 D: - -- D = 1:16 --> 4, 8, 5, 4, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1 - for D in 1 to c_sdp_bdo_nof_destinations_max loop - v_arr(D) := smallest(v_arr(D), D * c_sdp_cep_nof_blocks_per_packet); + -- per destination, 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); + 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); + 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 + 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); begin -- 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. + -- 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 ceil(488 / DN) yields the number of -- blocks for the first 1:DN-1 destinations: @@ -122,8 +167,7 @@ package body sdp_bdo_pkg is 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. + -- 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: @@ -146,6 +190,46 @@ package body sdp_bdo_pkg is return v_last_arr; end func_sdp_sdo_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); + begin + -- Determine nof_ch per packet for the first 1:DN-1 destinations, as + -- function of number of destinations DN. + -- The packet lengths follow from c_nof_blocks_arr * c_nof_beamlets_arr: + -- . c_nof_blocks_arr = 4, 8, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 + -- . 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 + 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; + + 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); + begin + -- Determine nof_ch per packet for the first 1:DN-1 destinations, as + -- function of number of destinations DN. + -- The packet lengths follow from c_nof_blocks_arr * c_nof_beamlets_arr: + -- . c_nof_blocks_arr = 4, 8, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 + -- . 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 + 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; + 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; @@ -155,8 +239,7 @@ package body sdp_bdo_pkg is 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. Use look up table to - -- precalculate the values as constants. + -- index DN, 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.