From 0c4eaf6bd340751f6e66ba442bbfd142e4b083b9 Mon Sep 17 00:00:00 2001
From: donker <donker@astron.nl>
Date: Wed, 29 Sep 2021 14:42:01 +0200
Subject: [PATCH] L2SDP-489, change xst_offload points and add some.

---
 src/constants.h     |   1 +
 src/fpga.cpp        |   4 ++
 src/periph/fpga.cpp | 140 +++++++++++++++++++++++++++++++-------------
 src/periph/fpga.h   |   5 ++
 4 files changed, 110 insertions(+), 40 deletions(-)

diff --git a/src/constants.h b/src/constants.h
index 35b5e4f8..c520fb4e 100644
--- a/src/constants.h
+++ b/src/constants.h
@@ -49,6 +49,7 @@
 #define C_N_step 1
 #define C_N_crosslets_max 7
 #define C_N_scrap 512  // Number of 32 bit words in FPGA scrap memory.
+#define C_N_fft 1024  // The FFT size defines the number of samples per block.
 #define C_N_pol 2  // Number of antenna polarizations, X and Y.
 #define C_A_pn 6  // Number of dual polarization antennas per Processing Node (PN) FPGA.
 // #define C_N_beamlets 976  // Number of beamlets per antenna band  488, 976
diff --git a/src/fpga.cpp b/src/fpga.cpp
index 53ba9e97..4f5ece24 100644
--- a/src/fpga.cpp
+++ b/src/fpga.cpp
@@ -89,12 +89,16 @@ Fpga::Fpga(list<class Node*>& nodelist, const int32_t n_beamsets):
     pointMap->add_register("FPGA_xst_processing_enable_RW",                  "fpga/xst_processing_enable",                  nodes.size(), 1, "RW", REG_FORMAT_BOOLEAN);
     pointMap->add_register("FPGA_xst_offload_enable_R",                      "fpga/xst_offload_enable",                     nodes.size(), 1, "RO", REG_FORMAT_BOOLEAN);
     pointMap->add_register("FPGA_xst_offload_enable_RW",                     "fpga/xst_offload_enable",                     nodes.size(), 1, "RW", REG_FORMAT_BOOLEAN);
+    pointMap->add_register("FPGA_xst_offload_nof_crosslets_R",               "fpga/xst_offload_nof_crosslets",              nodes.size(), 1, "RO", REG_FORMAT_UINT32);
+    pointMap->add_register("FPGA_xst_offload_nof_crosslets_RW",              "fpga/xst_offload_nof_crosslets",              nodes.size(), 1, "RW", REG_FORMAT_UINT32);
     pointMap->add_register("FPGA_xst_offload_hdr_eth_destination_mac_R",     "fpga/xst_offload_hdr_eth_destination_mac",    nodes.size(), 1, "RO", REG_FORMAT_STRING);
     pointMap->add_register("FPGA_xst_offload_hdr_eth_destination_mac_RW",    "fpga/xst_offload_hdr_eth_destination_mac",    nodes.size(), 1, "RW", REG_FORMAT_STRING);
     pointMap->add_register("FPGA_xst_offload_hdr_ip_destination_address_R",  "fpga/xst_offload_hdr_ip_destination_address", nodes.size(), 1, "RO", REG_FORMAT_STRING);
     pointMap->add_register("FPGA_xst_offload_hdr_ip_destination_address_RW", "fpga/xst_offload_hdr_ip_destination_address", nodes.size(), 1, "RW", REG_FORMAT_STRING);
     pointMap->add_register("FPGA_xst_offload_hdr_udp_destination_port_R",    "fpga/xst_offload_hdr_udp_destination_port",   nodes.size(), 1, "RO", REG_FORMAT_UINT16);
     pointMap->add_register("FPGA_xst_offload_hdr_udp_destination_port_RW",   "fpga/xst_offload_hdr_udp_destination_port",   nodes.size(), 1, "RW", REG_FORMAT_UINT16);
+    pointMap->add_register("FPGA_xst_input_bsn_at_sync_R",                   "fpga/xst_input_sync_at_bsn",                  nodes.size(), 1, "RO", REG_FORMAT_INT64);
+    pointMap->add_register("FPGA_xst_output_sync_bsn_R",                     "fpga/xst_output_sync_bsn",                    nodes.size(), 1, "RO", REG_FORMAT_INT64);
 
     pointMap->add_register("FPGA_processing_enable_R",                       "fpga/processing_enable",                      nodes.size(), 1, "RO", REG_FORMAT_BOOLEAN);
     pointMap->add_register("FPGA_processing_enable_RW",                      "fpga/processing_enable",                      nodes.size(), 1, "RW", REG_FORMAT_BOOLEAN);
diff --git a/src/periph/fpga.cpp b/src/periph/fpga.cpp
index cfdc546d..c6037d4e 100644
--- a/src/periph/fpga.cpp
+++ b/src/periph/fpga.cpp
@@ -68,6 +68,8 @@ Periph_fpga::Periph_fpga(uint global_nr, string ipaddr, uint n_beamsets):
     my_current_fw_version("-.-"),
     my_bsn_input_sync_timeout(false),
     my_bsn_input_bsn(0),
+    my_xst_input_bsn_at_sync(0),
+    my_xst_output_sync_bsn(0),
     my_bsn_input_nof_packets(0),
     my_bsn_input_nof_valid(0),
     my_bsn_input_nof_err(0),
@@ -75,7 +77,6 @@ Periph_fpga::Periph_fpga(uint global_nr, string ipaddr, uint n_beamsets):
     my_jesd_csr_dev_syncn {0},
     my_jesd_rx_err0 {0},
     my_jesd_rx_err1 {0},
-    my_xst_processing_enable(false),
     my_pps_offset_cnt(0),
     my_signal_input_mean {0.0},
     my_signal_input_rms {0.0}
@@ -210,6 +211,9 @@ bool Periph_fpga::read(TermOutput& termout, const string addr,
         else if (addr == "fpga/xst_offload_enable") {
             retval = read_mm_port(termout, "REG_STAT_ENABLE_XST", "enable", format);
         }
+        else if (addr == "fpga/xst_offload_nof_crosslets") {
+            retval = read_mm_port(termout, "REG_NOF_CROSSLETS", "nof_crosslets", format);
+        }
         else if (addr == "fpga/xst_offload_hdr_eth_destination_mac") {
             retval = read_xst_offload_hdr_eth_destination_mac(termout, format);
         }
@@ -228,6 +232,12 @@ bool Periph_fpga::read(TermOutput& termout, const string addr,
         else if (addr == "fpga/xst_subband_select") {
             retval = read_xst_subband_select(termout, format);
         }
+        else if (addr == "fpga/xst_input_sync_at_bsn") {
+            retval = read_xst_input_sync_at_bsn(termout, format, R_MEM);
+        }
+        else if (addr == "fpga/xst_output_sync_bsn") {
+            retval = read_xst_output_sync_bsn(termout, format, R_MEM);
+        }
         else if (addr == "fpga/processing_enable") {
             retval = read_mm_port(termout, "REG_BSN_SOURCE_V2", "dp_on", format);
         }
@@ -414,6 +424,9 @@ bool Periph_fpga::write(TermOutput& termout, const string addr, const string typ
         else if (addr == "fpga/xst_offload_enable") {
             retval = write_xst_offload_enable(data);
         }
+        else if (addr == "fpga/xst_offload_nof_crosslets") {
+            retval = write_xst_offload_nof_crosslets(data);
+        }
         else if (addr == "fpga/xst_offload_hdr_eth_destination_mac") {
             retval = write_xst_offload_hdr_eth_destination_mac(data);
         }
@@ -483,6 +496,8 @@ bool Periph_fpga::monitor(TermOutput& termout)
         read_time_since_last_pps(termout, REG_FORMAT_INT64, R_UCP);
         read_bsn_monitor_input_sync_timeout(termout, REG_FORMAT_INT64, R_UCP);
         read_bsn_monitor_input_bsn(termout, REG_FORMAT_INT64, R_UCP);
+        read_xst_input_sync_at_bsn(termout, REG_FORMAT_INT64, R_UCP);
+        read_xst_output_sync_bsn(termout, REG_FORMAT_INT64, R_UCP);
         read_bsn_monitor_input_nof_packets(termout, REG_FORMAT_INT32, R_UCP);
         read_bsn_monitor_input_nof_valid(termout, REG_FORMAT_INT32, R_UCP);
         read_bsn_monitor_input_nof_err(termout, REG_FORMAT_INT32, R_UCP);
@@ -1292,6 +1307,11 @@ bool Periph_fpga::write_xst_offload_enable(const char *data)
     return Write("mm/0/REG_STAT_ENABLE_XST/0/enable", _data);
 }
 
+bool Periph_fpga::write_xst_offload_nof_crosslets(const char *data)
+{
+    uint32_t *_ptr = (uint32_t *)data;
+    return Write("mm/0/REG_NOF_CROSSLETS/0/nof_crosslets", _ptr);
+}
 
 bool Periph_fpga::read_xst_offload_hdr_eth_destination_mac(TermOutput& termout, int format)
 {
@@ -1398,13 +1418,12 @@ bool Periph_fpga::read_xst_processing_enable(TermOutput& termout, int format)
 {
     bool retval = true;
 
-    // uint32_t data[20];
-    // memset((void *)data, 0, sizeof(data));
-    // retval = Read("mm/0/REG_BSN_SCHEDULER_XSUB/0/enable", data);
-    // bool processing_enable = (bool)data[0];
+    uint32_t data[1];
+    memset((void *)data, 0, sizeof(data));
+    retval = Read("mm/0/REG_BSN_SYNC_SCHEDULER_XSUB/0/mon_output_enable", data);
 
     bool *_ptr = (bool *)termout.val;
-    *_ptr = my_xst_processing_enable;
+    *_ptr = (bool)data[0];;
     termout.nof_vals = 1;
     termout.datatype = format;
     return retval;
@@ -1415,38 +1434,41 @@ bool Periph_fpga::write_xst_processing_enable(const char *data)
     bool retval = true;
     uint32_t *reg = new uint32_t[2];
     bool processing_enable = (bool)data[0];
-    uint64_t scheduled_bsn;
+    uint64_t start_bsn;
     if (processing_enable == true) {
         // get bsn and add latency
-        retval &= Read("mm/0/REG_BSN_SCHEDULER_XSUB/0/scheduled_bsn", reg);
+        retval &= Read("mm/0/REG_BSN_SYNC_SCHEDULER_XSUB/0/mon_input_bsn_at_sync", reg);
         if (retval == true) {
-            scheduled_bsn = (((uint64_t)reg[1] << 32) + reg[0]);
-            cout << "bsn=" << to_string(scheduled_bsn) << endl;
-            scheduled_bsn += C_BSN_LATENCY;
-            cout << "new bsn=" << to_string(scheduled_bsn) << endl;
-            reg[0] = (uint32_t)(scheduled_bsn & 0xffffffff);
-            reg[1] = (uint32_t)((scheduled_bsn >> 32) & 0xffffffff);
+            start_bsn = (((uint64_t)reg[1] << 32) + reg[0]);
+            cout << "bsn=" << to_string(start_bsn) << endl;
+            start_bsn = start_bsn + 2 * C_F_adc / C_N_fft;
+            cout << "new bsn=" << to_string(start_bsn) << endl;
+            reg[0] = (uint32_t)(start_bsn & 0xffffffff);
+            reg[1] = (uint32_t)((start_bsn >> 32) & 0xffffffff);
             // write sheduled bsn
-            retval &= Write("mm/0/REG_BSN_SCHEDULER_XSUB/0/scheduled_bsn", reg);
-            if (retval == true) {
-                my_xst_processing_enable = processing_enable;
-            }
+            retval &= Write("mm/0/REG_BSN_SYNC_SCHEDULER_XSUB/0/start_bsn", reg);
+            reg[0] = 1;
+            // write ctrl_enable = 1
+            retval &= Write("mm/0/REG_BSN_SYNC_SCHEDULER_XSUB/0/ctrl_enable", reg);
         }
     }
+    else {
+        reg[0] = 0;
+        // write ctrl_enable = 0
+        retval &= Write("mm/0/REG_BSN_SYNC_SCHEDULER_XSUB/0/ctrl_enable", reg);
+    }
     return retval;
 }
 
 bool Periph_fpga::read_xst_integration_interval(TermOutput& termout, int format)
 {
-    // TODO, fill in if supported in FW
     bool retval = true;
 
-    // uint32_t data[20];
-    // memset((void *)data, 0, sizeof(data));
-    // retval = Read("mm/0/REG_STAT_HDR_DAT_XST/0/??", data);
-    // double interval = ??;
+    uint32_t data[20];
+    memset((void *)data, 0, sizeof(data));
+    retval = Read("mm/0/REG_BSN_SYNC_SCHEDULER_XSUB/0/ctrl_interval_size", data);
+    double interval = (double)data[0] / C_F_adc;
 
-    double interval = 1.0;
     double *_ptr = (double *)termout.val;
     *_ptr = interval;
     termout.nof_vals = 1;
@@ -1456,10 +1478,10 @@ bool Periph_fpga::read_xst_integration_interval(TermOutput& termout, int format)
 
 bool Periph_fpga::write_xst_integration_interval(const char *data)
 {
-    // uint32_t *_ptr = (uint32_t *)data;
-    // TODO, fill in if supported in FW
-    // return Write("mm/0/REG_STAT_HDR_DAT_XST/0/??", data);
-    return true;
+    double *_ptr = (double *)data;
+    uint32_t *reg = new uint32_t[1];
+    reg[0] = (uint32_t)round(_ptr[0] * C_F_adc);
+    return Write("mm/0/REG_BSN_SYNC_SCHEDULER_XSUB/0/ctrl_interval_size", reg);
 }
 
 bool Periph_fpga::read_xst_subband_select(TermOutput& termout, int format)
@@ -1481,6 +1503,44 @@ bool Periph_fpga::read_xst_subband_select(TermOutput& termout, int format)
     return retval;
 }
 
+bool Periph_fpga::read_xst_input_sync_at_bsn(TermOutput& termout, int format, int mode) {
+    bool retval = true;
+    int64_t bsn = my_xst_input_bsn_at_sync;
+    if (mode == R_UCP) {
+        uint32_t data[20];
+        memset((void *)data, 0, sizeof(data));
+        string regname;
+        regname = "mm/0/REG_BSN_SYNC_SCHEDULER_XSUB/0/mon_input_bsn_at_sync";
+        retval = Read(regname, data);
+        bsn = (((int64_t)data[1] << 32) + data[0]);
+    }
+    int64_t *_ptr = (int64_t *)termout.val;
+    *_ptr = bsn;
+    termout.nof_vals = 1;
+    termout.datatype = format;
+    my_xst_input_bsn_at_sync = bsn;
+    return retval;
+}
+
+bool Periph_fpga::read_xst_output_sync_bsn(TermOutput& termout, int format, int mode) {
+    bool retval = true;
+    int64_t bsn = my_xst_output_sync_bsn;
+    if (mode == R_UCP) {
+        uint32_t data[20];
+        memset((void *)data, 0, sizeof(data));
+        string regname;
+        regname = "mm/0/REG_BSN_SYNC_SCHEDULER_XSUB/0/mon_output_sync_bsn";
+        retval = Read(regname, data);
+        bsn = (((int64_t)data[1] << 32) + data[0]);
+    }
+    int64_t *_ptr = (int64_t *)termout.val;
+    *_ptr = bsn;
+    termout.nof_vals = 1;
+    termout.datatype = format;
+    my_xst_output_sync_bsn = bsn;
+    return retval;
+}
+
 bool Periph_fpga::write_xst_subband_select(const char *data)
 {
     uint32_t *_ptr = (uint32_t *)data;
@@ -1579,10 +1639,10 @@ When FPGA_wg_enable_RW is set True, then enable the WG via mode = c_mode_calc =
 WG starts or restarts when it gets a trigger from the BSN scheduler. The trigger has to occur at the
 same BSN for all WG that are enabled, to ensure that they start synchronously. Any WG that are not
 enabled will ignore the trigger. The exact BSN at which the WG start is don't care. The trigger is
-scheduled via scheduled_bsn in REG_BSN_SCHEDULER. The current BSN can be read from the REG_BSN_SCHEDULER
-on one of the FPGAs. Assume the communication to write the scheduled_bsn in all FPGAs will take
+scheduled via start_bsn in REG_BSN_SCHEDULER. The current BSN can be read from the REG_BSN_SCHEDULER
+on one of the FPGAs. Assume the communication to write the start_bsn in all FPGAs will take
 less than 1 ms, then a margin of 10 - 100 ms is sufficient. The BSN period corresponds to 5.12 μs, so
-a c_bsn_latency = 20000 (≈ 100 ms) is sufficient for scheduled_bsn = current_bsn + c_bsn_latency.
+a c_bsn_latency = 20000 (≈ 100 ms) is sufficient for start_bsn = current_bsn + c_bsn_latency.
 The MP reports False when mode = c_mode_off = 0, else True.
 Note:
   The nof_samples field and mode field share an address in REG_DIAG_WG. The nof_samples = 2**W_wg_buf = 1024.
@@ -1592,7 +1652,7 @@ bool Periph_fpga::write_wg_enable(const char *data) {
     bool *_ptr = (bool *)data;
     bool retval = true;
     uint32_t *reg = new uint32_t[4];
-    uint64_t scheduled_bsn;
+    uint64_t start_bsn;
     bool wg_enable;
 
     string regname1;
@@ -1621,20 +1681,20 @@ bool Periph_fpga::write_wg_enable(const char *data) {
     // get bsn and add latency
     wg_enable = _ptr[0];
     if (wg_enable == true) {
-        regname1 = "mm/0/REG_BSN_SCHEDULER/0/scheduled_bsn";
+        regname1 = "mm/0/REG_BSN_SCHEDULER/0/start_bsn";
         retval = Read(regname1, reg);
-        scheduled_bsn = (((uint64_t)reg[1] << 32) + reg[0]);
-        cout << "bsn=" << to_string(scheduled_bsn) << endl;
-        scheduled_bsn += C_BSN_LATENCY;
-        cout << "new bsn=" << to_string(scheduled_bsn) << endl;
-        reg[0] = (uint32_t)(scheduled_bsn & 0xffffffff);
-        reg[1] = (uint32_t)((scheduled_bsn >> 32) & 0xffffffff);
+        start_bsn = (((uint64_t)reg[1] << 32) + reg[0]);
+        cout << "bsn=" << to_string(start_bsn) << endl;
+        start_bsn += C_BSN_LATENCY;
+        cout << "new bsn=" << to_string(start_bsn) << endl;
+        reg[0] = (uint32_t)(start_bsn & 0xffffffff);
+        reg[1] = (uint32_t)((start_bsn >> 32) & 0xffffffff);
     }
     // write sheduled bsn
     for (uint i=0; i< C_S_pn; i++) {
         wg_enable = _ptr[i];
         if (wg_enable == true) {
-            regname1 = "mm/0/REG_BSN_SCHEDULER/" + to_string(i) + "/scheduled_bsn";
+            regname1 = "mm/0/REG_BSN_SCHEDULER/" + to_string(i) + "/start_bsn";
             retval = Write(regname1, reg);
         }
     }
diff --git a/src/periph/fpga.h b/src/periph/fpga.h
index a5370082..6fd29266 100644
--- a/src/periph/fpga.h
+++ b/src/periph/fpga.h
@@ -61,6 +61,8 @@ private:
 
   bool    my_bsn_input_sync_timeout;
   int64_t my_bsn_input_bsn;
+  int64_t my_xst_input_bsn_at_sync;
+  int64_t my_xst_output_sync_bsn;
   int32_t my_bsn_input_nof_packets;
   int32_t my_bsn_input_nof_valid;
   int32_t my_bsn_input_nof_err;
@@ -128,11 +130,14 @@ private:
 
   bool read_xst_subband_select(TermOutput& termout, int format);
   bool write_xst_subband_select(const char *data);
+  bool read_xst_input_sync_at_bsn(TermOutput& termout, int format, int mode);
+  bool read_xst_output_sync_bsn(TermOutput& termout, int format, int mode);  
   bool read_xst_integration_interval(TermOutput& termout, int format);
   bool write_xst_integration_interval(const char *data);
   bool read_xst_processing_enable(TermOutput& termout, int format);
   bool write_xst_processing_enable(const char *data);
   bool write_xst_offload_enable(const char *data);
+  bool write_xst_offload_nof_crosslets(const char *data);
   bool read_xst_offload_hdr_eth_destination_mac(TermOutput& termout, int format);
   bool write_xst_offload_hdr_eth_destination_mac(const char *data);
   bool read_xst_offload_hdr_ip_destination_address(TermOutput& termout, int format);
-- 
GitLab