From 75f505c4d8fbda23e68871dc17dd1faacd61aaaa Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Thu, 28 Sep 2023 17:22:42 +0200
Subject: [PATCH] Connect streaming data output info per destination index.

---
 .../vhdl/sdp_bdo_multiple_destinations.vhd    | 121 +++++++++++-------
 1 file changed, 75 insertions(+), 46 deletions(-)

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 1e2b7c0e3d..dc6683df3b 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
@@ -23,11 +23,11 @@
 --   Construct beamformer data output (BDO) payloads for multiple destinations.
 -- Description:
 -- * The nof_destinations_max determines how to MM control the beamlet packet
---   destination(s) MAC/IP/UDP port:
+--   destination(s) MAC/IP/UDP:
 --   . 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.
+--     MM program the one destination MAC/IP/UDP 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
+--     MM program the one or more destination MAC/IP/UDP 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.
@@ -72,52 +72,61 @@ entity sdp_bdo_multiple_destinations is
     dp_clk   : in  std_logic;
     dp_rst   : in  std_logic;
 
+    -- MM register
     reg_destinations_copi : in  t_mem_copi;
     reg_destinations_cipo : out t_mem_cipo;
 
     destinations_info     : out t_sdp_bdo_destinations_info;
 
+    -- Streaming data
     snk_in   : in  t_dp_sosi;
-    src_out  : out t_dp_sosi
+    src_out  : out t_dp_sosi;
+
+    -- Streaming data output info per destination index
+    destination_index                      : out natural;
+    nof_blocks_per_packet                  : out natural;
+    nof_beamlets_per_block_per_destination : out natural;
+    beamlet_index_per_destination          : out natural
   );
 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;
+  constant c_beamset_beamlet_index  : natural := g_beamset_id * c_sdp_S_sub_bf;
 
   -- 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_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_destinations_arr : t_natural_arr(1 to c_m) := func_sdp_bdo_nof_beamlets_per_block_first_destinations_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_destinations_arr      : t_natural_arr(1 to c_m) := func_sdp_bdo_nof_ch_per_packet_first_destinations_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_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_max  : natural := largest(c_nof_ch_per_packet_first_destinations_arr);
   constant c_nof_ch_per_packet_w    : natural := ceil_log2(c_nof_ch_per_packet_max + 1);
 
+  -- Reorder all c_sdp_nof_beamlets_per_block = c_sdp_S_sub_bf = 488 beamlets
+  -- in buffer, such that they appear with first all blocks (= time samples)
+  -- for beamlet index 0 and last all blocks for beamlet index 477.
+  constant c_reorder_nof_beamlets_per_block       : natural := c_sdp_nof_beamlets_per_block;
+
   signal i_destinations_info     : t_sdp_bdo_destinations_info;
 
+  signal s_DN  : natural range 1 to g_nof_destinations_max;      -- number of destinations
+  signal s_DI  : natural range 0 to g_nof_destinations_max - 1;  -- destination index
+
   -- Dynamic merge, reorder, unmerge packet sizes
-  -- . 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_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);
-  signal nof_beamlets_per_block                   : natural;
-  signal nof_ch_per_packet_first_destination      : natural := c_nof_ch_per_packet_first_destination_arr(1);
-  signal nof_ch_per_packet_last_destination       : natural := c_nof_ch_per_packet_last_destination_arr(1);
-  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 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 reorder_nof_blocks                        : natural;
+  signal reorder_nof_blocks_slv                    : std_logic_vector(c_sdp_bdo_reorder_nof_blocks_w - 1 downto 0);
+  signal reorder_nof_ch                            : natural;
+  signal nof_beamlets_per_block_first_destinations : natural;
+  signal nof_beamlets_per_block_last_destination   : natural;
+  signal nof_ch_per_packet_first_destinations      : natural;
+  signal nof_ch_per_packet_first_destinations_slv  : std_logic_vector(c_nof_ch_per_packet_w - 1 downto 0);
+  signal nof_ch_per_packet_last_destination        : natural;
 
   signal select_copi            : t_mem_copi := c_mem_copi_rst;
   signal select_cipo            : t_mem_cipo := c_mem_cipo_rst;
@@ -132,7 +141,6 @@ architecture str of sdp_bdo_multiple_destinations is
   signal unmerge_src_out        : t_dp_sosi;
   signal unmerge_word           : t_sdp_dual_pol_beamlet_in_word;
 begin
-  src_out <= unmerge_src_out;
   destinations_info <= i_destinations_info;
 
   -----------------------------------------------------------------------------
@@ -159,28 +167,45 @@ begin
     );
 
   -----------------------------------------------------------------------------
-  -- Multiple destinations info look up values
+  -- Look up table values and and output info dependent on DN and DI
   -----------------------------------------------------------------------------
-  -- Pipeline values from look up tables to ease timing closure
-  p_pipeline : process(dp_clk)
+  -- Register values to ease timing closure
+  p_reg : process(dp_clk)
     variable v_DN : natural;  -- number of destinations
     variable v_DI : natural;  -- destination index
   begin
     if rising_edge(dp_clk) then
       v_DN := i_destinations_info.nof_destinations_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);
-      nof_beamlets_per_block_last_destination  <= c_nof_beamlets_per_block_last_destination_arr(v_DN);
-      v_DI := 0;
-      beamlet_index_per_destination_bset_0     <= c_beamlet_index_per_destination_mat(v_DN, v_DI);
-      beamlet_index_per_destination            <= c_beamlet_index + beamlet_index_per_destination_bset_0;
+      v_DI := to_uint(unmerge_src_out.channel);
+
+      -- Constant values that depend on DN = nof_destinations_act set via MM
+      s_DN <= v_DN;
+      reorder_nof_blocks                        <= c_reorder_nof_blocks_arr(s_DN);
+      reorder_nof_ch                            <= c_reorder_nof_ch_arr(s_DN);
+      nof_beamlets_per_block_first_destinations <= c_nof_beamlets_per_block_first_destinations_arr(s_DN);
+      nof_beamlets_per_block_last_destination   <= c_nof_beamlets_per_block_last_destination_arr(s_DN);
+      nof_ch_per_packet_first_destinations      <= c_nof_ch_per_packet_first_destinations_arr(s_DN);
+      nof_ch_per_packet_last_destination        <= c_nof_ch_per_packet_last_destination_arr(s_DN);
+      -- . output info
+      nof_blocks_per_packet <= reorder_nof_blocks;
+
+      -- Variable values that depend on DN set via MM and on current DI of
+      -- dp_packet_unmerge output destination channel
+      s_DI <= v_DI;
+      -- . output info
+      destination_index <= v_DI;
+      beamlet_index_per_destination <= c_beamset_beamlet_index + c_beamlet_index_per_destination_mat(s_DN, v_DI);
+      if v_DI < s_DN - 1 then
+        nof_beamlets_per_block_per_destination <= nof_beamlets_per_block_first_destinations;
+      else
+        nof_beamlets_per_block_per_destination <= nof_beamlets_per_block_last_destination;
+      end if;
+
+      -- Register src_out to time align output info with src_out.sop
+      src_out <= unmerge_src_out;
     end if;
   end process;
 
-  nof_beamlets_per_block <= nof_beamlets_per_block_first_destination;
-  nof_ch_per_packet <= nof_ch_per_packet_first_destination;
-
   -----------------------------------------------------------------------------
   -- dp_packet_merge
   -----------------------------------------------------------------------------
@@ -259,12 +284,12 @@ begin
   -- Pass on beamlet data in transposed order
   select_copi <= r_transpose.select_copi;
 
-  p_reorder_transpose : process(dp_rst, select_cipo, reorder_nof_blocks, nof_beamlets_per_block, r_transpose)
+  p_reorder_transpose : process(dp_rst, select_cipo, reorder_nof_blocks, r_transpose)
     variable v : t_reorder_transpose;
   begin
     if select_cipo.waitrequest = '0' then
       -- Read from reorder_col_select page
-      v := func_reorder_transpose(reorder_nof_blocks, nof_beamlets_per_block, r_transpose);
+      v := func_reorder_transpose(reorder_nof_blocks, c_reorder_nof_beamlets_per_block, r_transpose);
     else
       -- No read, new reorder_col_select page not available yet
       v := c_reorder_transpose_rst;
@@ -279,7 +304,11 @@ begin
   -----------------------------------------------------------------------------
   -- dp_packet_unmerge for nof_destinations
   -----------------------------------------------------------------------------
-  nof_ch_per_packet_slv <= to_uvec(nof_ch_per_packet, c_nof_ch_per_packet_w);
+  nof_ch_per_packet_first_destinations_slv <= to_uvec(nof_ch_per_packet_first_destinations, c_nof_ch_per_packet_w);
+
+  -- The nof_ch_per_packet_last_destination is used only for view in Wave
+  -- window, because dp_packet_unmerge automatically will output that number
+  -- of remaining number of ch for the last block.
 
   u_dp_packet_unmerge : entity dp_lib.dp_packet_unmerge
     generic map (
@@ -292,7 +321,7 @@ begin
       rst     => dp_rst,
       clk     => dp_clk,
 
-      pkt_len     => nof_ch_per_packet_slv,
+      pkt_len     => nof_ch_per_packet_first_destinations_slv,
       pkt_len_out => open,  -- Valid at src_out.sop
 
       snk_in      => reorder_src_out,
-- 
GitLab