From 2198e311876daadcd60513296207e8f118f13436 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo <bartosz.podrygajlo@openairinterface.org> Date: Fri, 3 Jan 2025 15:57:59 +0100 Subject: [PATCH] More updates to imscope IQ recorder - Added event parameter for recording which is reflected in the filename - Added event in the UE for DLSCH NACK - Added program name to the filename for ease of identification - Reworked spinlock to use atomics --- .../PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c | 1 + openair1/PHY/TOOLS/imscope/CMakeLists.txt | 2 +- openair1/PHY/TOOLS/imscope/imscope_internal.h | 2 +- openair1/PHY/TOOLS/imscope/imscope_record.cpp | 57 ++++++++++++++----- openair1/PHY/TOOLS/phy_scope_interface.h | 10 ++-- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 4 +- 6 files changed, 53 insertions(+), 23 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 4fb88ec969..a3138f5d7f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -321,6 +321,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, LOG_D(PHY, "DLSCH received nok \n"); kpiStructure.nb_nack++; dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations + 1; + UEdumpScopeData(phy_vars_ue, proc->nr_slot_rx, proc->frame_rx, "DLSCH_NACK"); } uint8_t dmrs_Type = dlsch_config->dmrsConfigType; diff --git a/openair1/PHY/TOOLS/imscope/CMakeLists.txt b/openair1/PHY/TOOLS/imscope/CMakeLists.txt index 0b1ecf0835..060b288419 100644 --- a/openair1/PHY/TOOLS/imscope/CMakeLists.txt +++ b/openair1/PHY/TOOLS/imscope/CMakeLists.txt @@ -35,7 +35,7 @@ set_target_properties(imscope PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY configure_file(imgui.ini ${CMAKE_BINARY_DIR}/imscope-init.ini COPYONLY) add_library(imscope_record MODULE ../phy_scope_interface.c imscope_common.cpp imscope_record.cpp) -target_link_libraries(imscope_record PRIVATE UTIL) +target_link_libraries(imscope_record PRIVATE UTIL atomic) set_target_properties(imscope_record PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) add_executable(imscope_iq_file_viewer imscope.cpp imscope_iq_file_viewer.cpp ../phy_scope_interface.c imscope_common.cpp) diff --git a/openair1/PHY/TOOLS/imscope/imscope_internal.h b/openair1/PHY/TOOLS/imscope/imscope_internal.h index f0f738bf80..7b0b04758d 100644 --- a/openair1/PHY/TOOLS/imscope/imscope_internal.h +++ b/openair1/PHY/TOOLS/imscope/imscope_internal.h @@ -152,7 +152,7 @@ void copyDataUnsafeWithOffset(enum scopeDataType type, void *dataIn, size_t size void unlockScopeData(enum scopeDataType type); -void dumpScopeData(int slot, int frame); +void dumpScopeData(int slot, int frame, const char *cause_string); void *imscope_record_thread(void *data_void_ptr); void *imscope_thread(void *data_void_ptr); diff --git a/openair1/PHY/TOOLS/imscope/imscope_record.cpp b/openair1/PHY/TOOLS/imscope/imscope_record.cpp index c67b4b0efe..a59366d504 100644 --- a/openair1/PHY/TOOLS/imscope/imscope_record.cpp +++ b/openair1/PHY/TOOLS/imscope/imscope_record.cpp @@ -22,6 +22,18 @@ #include "imscope_internal.h" #include "openair1/PHY/TOOLS/phy_scope_interface.h" #include <sys/stat.h> +#include <errno.h> +#include <atomic> +#include <new> + +#ifdef __cpp_lib_hardware_interference_size + using std::hardware_constructive_interference_size; + using std::hardware_destructive_interference_size; +#else + // 64 bytes on x86-64 鈹� L1_CACHE_BYTES 鈹� L1_CACHE_SHIFT 鈹� __cacheline_aligned 鈹� ... + constexpr std::size_t hardware_constructive_interference_size = 64; + constexpr std::size_t hardware_destructive_interference_size = 64; +#endif #define NUM_CACHED_DATA 4 // Set maximum number of kilobytes written per recording session to 1GB. This is a safeguard against @@ -29,8 +41,13 @@ #define MAX_KBYTES_WRITTEN_PER_SESSION (1000 * 1000) ImScopeDataWrapper scope_array[EXTRA_SCOPE_TYPES]; -volatile int slot_to_dump = -1; -volatile int frame_to_dump = -1; +typedef struct alignas(hardware_destructive_interference_size) ImScopeDumpInstruction { + int slot; + int frame; + const char *cause; +} ImScopeDumpInstruction; + +std::atomic<ImScopeDumpInstruction> dump_instruction; extern "C" void imscope_record_autoinit(void *dataptr) { @@ -44,6 +61,8 @@ extern "C" void imscope_record_autoinit(void *dataptr) scope_array[i].data.meta = {-1, -1}; } + dump_instruction.store({-1, -1, nullptr}); + scopeData_t *scope = (scopeData_t *)calloc(1, sizeof(scopeData_t)); scope->copyData = copyDataThreadSafe; scope->tryLockScopeData = tryLockScopeData; @@ -64,12 +83,11 @@ extern "C" void imscope_record_autoinit(void *dataptr) threadCreate(&thread, imscope_record_thread, dataptr, (char *)"imscope_record", -1, sched_get_priority_min(SCHED_RR)); } -void dumpScopeData(int slot, int frame) { - if (slot_to_dump == -1) { - LOG_E(PHY, "Will dump scope data\n"); - frame_to_dump = frame; - slot_to_dump = slot; - } +void dumpScopeData(int slot, int frame, const char *cause_string) +{ + ImScopeDumpInstruction to_dump = {slot, frame, cause_string}; + ImScopeDumpInstruction expected = {-1, -1, nullptr}; + dump_instruction.compare_exchange_weak(expected, to_dump); } void *imscope_record_thread(void *data_void_ptr) @@ -87,15 +105,26 @@ void *imscope_record_thread(void *data_void_ptr) } else { LOG_A(PHY, "ImScope recorder thread starts, recording data to cwd\n"); } + + std::string program_name(program_invocation_name); + size_t last_slash = program_name.find_last_of("/"); + if (last_slash != std::string::npos) { + program_name = program_name.substr(last_slash + 1); + } + ImScopeData scope_cache[EXTRA_SCOPE_TYPES][NUM_CACHED_DATA]; memset(scope_cache, 0, sizeof(scope_cache)); uint scope_cache_index[EXTRA_SCOPE_TYPES] = {0}; float kbytes_written = 0.0f; while (kbytes_written < MAX_KBYTES_WRITTEN_PER_SESSION) { - if (slot_to_dump != -1) { - std::string filename = std::string(path); - filename += has_dir ? "/" : "-"; - filename += std::to_string(frame_to_dump) + std::string("-") + std::to_string(slot_to_dump) + std::string(".imscope"); + ImScopeDumpInstruction dump = dump_instruction.load(std::memory_order::memory_order_relaxed); + if (dump.slot != -1) { + std::string filename; + if (has_dir) { + filename += std::string(path) + "/"; + } + filename += program_name + std::string("-") + dump.cause + std::string("-"); + filename += std::to_string(dump.frame) + std::string("-") + std::to_string(dump.slot) + std::string(".imscope"); std::ofstream outf(filename, std::ios_base::out | std::ios_base::binary); if (!outf) { LOG_E(PHY, "Could not open file %s for writing\n", filename.c_str()); @@ -104,7 +133,7 @@ void *imscope_record_thread(void *data_void_ptr) for (auto i = 0U; i < EXTRA_SCOPE_TYPES; i++) { for (auto j = 0U; j < NUM_CACHED_DATA; j++) { ImScopeData &scope_data = scope_cache[i][j]; - if (scope_data.meta.frame == frame_to_dump && scope_data.meta.slot == slot_to_dump) { + if (scope_data.meta.frame == dump.frame && scope_data.meta.slot == dump.slot) { scope_data.dump_to_file(outf); } } @@ -113,7 +142,7 @@ void *imscope_record_thread(void *data_void_ptr) kbytes_written += pos / 1000.0f; outf.close(); LOG_D(PHY, "ImScope done writing to %s\n", filename.c_str()); - slot_to_dump = -1; + dump_instruction.store({-1, -1, nullptr}, std::memory_order::memory_order_relaxed); } for (auto i = 0U; i < EXTRA_SCOPE_TYPES; i++) { ImScopeDataWrapper &scope_data = scope_array[i]; diff --git a/openair1/PHY/TOOLS/phy_scope_interface.h b/openair1/PHY/TOOLS/phy_scope_interface.h index def4eba959..1bdb52181a 100644 --- a/openair1/PHY/TOOLS/phy_scope_interface.h +++ b/openair1/PHY/TOOLS/phy_scope_interface.h @@ -112,7 +112,7 @@ typedef struct scopeData_s { bool (*tryLockScopeData)(enum scopeDataType type, int elementSz, int colSz, int lineSz, metadata *meta); void (*copyDataUnsafeWithOffset)(enum scopeDataType type, void *dataIn, size_t size, size_t offset, int copy_index); void (*unlockScopeData)(enum scopeDataType type); - void (*dumpScopeData)(int slot, int frame); + void (*dumpScopeData)(int slot, int frame, const char *cause_string); } scopeData_t; int load_softscope(char *exectype, void *initarg); @@ -158,10 +158,10 @@ void copyData(void *, enum scopeDataType type, void *dataIn, int elementSz, int scope_data->unlockScopeData(type); \ } -#define gNBdumpScopeData(gnb, slot, frame) \ +#define gNBdumpScopeData(gnb, slot, frame, cause_string) \ scopeData_t *scope_data = (scopeData_t *)gnb->scopeData; \ if (scope_data && scope_data->dumpScopeData) { \ - scope_data->dumpScopeData(slot, frame); \ + scope_data->dumpScopeData(slot, frame, cause_string); \ } #define UEScopeHasTryLock(ue) \ @@ -183,10 +183,10 @@ void copyData(void *, enum scopeDataType type, void *dataIn, int elementSz, int scope_data->unlockScopeData(type); \ } -#define UEdumpScopeData(ue, slot, frame) \ +#define UEdumpScopeData(ue, slot, frame, cause_string) \ scopeData_t *scope_data = (scopeData_t *)ue->scopeData; \ if (scope_data && scope_data->dumpScopeData) { \ - scope_data->dumpScopeData(slot, frame); \ + scope_data->dumpScopeData(slot, frame, cause_string); \ } \ #ifdef __cplusplus diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 7d1bfca240..7020386c6e 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -439,7 +439,7 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, boo ulsch_harq->ulsch_pdu.rb_size, ulsch_harq->TBS); nr_fill_indication(gNB, ulsch->frame, ulsch->slot, ULSCH_id, ulsch->harq_pid, 1, 0, crc, pdu); - gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame); + gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame, "ULSCH_NACK"); ulsch->handled = 1; LOG_D(PHY, "ULSCH %d in error\n",ULSCH_id); ulsch->last_iteration_cnt = ulsch->max_ldpc_iterations + 1; // Setting to max_ldpc_iterations + 1 is sufficient given that this variable is only used for checking for failure @@ -870,7 +870,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N nfapi_nr_rx_data_pdu_t *pdu = &UL_INFO->rx_ind.pdu_list[UL_INFO->rx_ind.number_of_pdus++]; nr_fill_indication(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid, 1, 1, crc, pdu); pusch_DTX++; - gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame); + gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame, "ULSCH_DTX"); continue; } } else { -- 2.26.2