Commit 2198e311 authored by Bartosz Podrygajlo's avatar Bartosz Podrygajlo

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
parent c01adc5e
...@@ -321,6 +321,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, ...@@ -321,6 +321,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
LOG_D(PHY, "DLSCH received nok \n"); LOG_D(PHY, "DLSCH received nok \n");
kpiStructure.nb_nack++; kpiStructure.nb_nack++;
dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations + 1; 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; uint8_t dmrs_Type = dlsch_config->dmrsConfigType;
......
...@@ -35,7 +35,7 @@ set_target_properties(imscope PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY ...@@ -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) 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) 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}) 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) add_executable(imscope_iq_file_viewer imscope.cpp imscope_iq_file_viewer.cpp ../phy_scope_interface.c imscope_common.cpp)
......
...@@ -152,7 +152,7 @@ void copyDataUnsafeWithOffset(enum scopeDataType type, void *dataIn, size_t size ...@@ -152,7 +152,7 @@ void copyDataUnsafeWithOffset(enum scopeDataType type, void *dataIn, size_t size
void unlockScopeData(enum scopeDataType type); 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_record_thread(void *data_void_ptr);
void *imscope_thread(void *data_void_ptr); void *imscope_thread(void *data_void_ptr);
......
...@@ -22,6 +22,18 @@ ...@@ -22,6 +22,18 @@
#include "imscope_internal.h" #include "imscope_internal.h"
#include "openair1/PHY/TOOLS/phy_scope_interface.h" #include "openair1/PHY/TOOLS/phy_scope_interface.h"
#include <sys/stat.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 #define NUM_CACHED_DATA 4
// Set maximum number of kilobytes written per recording session to 1GB. This is a safeguard against // Set maximum number of kilobytes written per recording session to 1GB. This is a safeguard against
...@@ -29,8 +41,13 @@ ...@@ -29,8 +41,13 @@
#define MAX_KBYTES_WRITTEN_PER_SESSION (1000 * 1000) #define MAX_KBYTES_WRITTEN_PER_SESSION (1000 * 1000)
ImScopeDataWrapper scope_array[EXTRA_SCOPE_TYPES]; ImScopeDataWrapper scope_array[EXTRA_SCOPE_TYPES];
volatile int slot_to_dump = -1; typedef struct alignas(hardware_destructive_interference_size) ImScopeDumpInstruction {
volatile int frame_to_dump = -1; int slot;
int frame;
const char *cause;
} ImScopeDumpInstruction;
std::atomic<ImScopeDumpInstruction> dump_instruction;
extern "C" void imscope_record_autoinit(void *dataptr) extern "C" void imscope_record_autoinit(void *dataptr)
{ {
...@@ -44,6 +61,8 @@ 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}; scope_array[i].data.meta = {-1, -1};
} }
dump_instruction.store({-1, -1, nullptr});
scopeData_t *scope = (scopeData_t *)calloc(1, sizeof(scopeData_t)); scopeData_t *scope = (scopeData_t *)calloc(1, sizeof(scopeData_t));
scope->copyData = copyDataThreadSafe; scope->copyData = copyDataThreadSafe;
scope->tryLockScopeData = tryLockScopeData; scope->tryLockScopeData = tryLockScopeData;
...@@ -64,12 +83,11 @@ extern "C" void imscope_record_autoinit(void *dataptr) ...@@ -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)); threadCreate(&thread, imscope_record_thread, dataptr, (char *)"imscope_record", -1, sched_get_priority_min(SCHED_RR));
} }
void dumpScopeData(int slot, int frame) { void dumpScopeData(int slot, int frame, const char *cause_string)
if (slot_to_dump == -1) { {
LOG_E(PHY, "Will dump scope data\n"); ImScopeDumpInstruction to_dump = {slot, frame, cause_string};
frame_to_dump = frame; ImScopeDumpInstruction expected = {-1, -1, nullptr};
slot_to_dump = slot; dump_instruction.compare_exchange_weak(expected, to_dump);
}
} }
void *imscope_record_thread(void *data_void_ptr) void *imscope_record_thread(void *data_void_ptr)
...@@ -87,15 +105,26 @@ void *imscope_record_thread(void *data_void_ptr) ...@@ -87,15 +105,26 @@ void *imscope_record_thread(void *data_void_ptr)
} else { } else {
LOG_A(PHY, "ImScope recorder thread starts, recording data to cwd\n"); 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]; ImScopeData scope_cache[EXTRA_SCOPE_TYPES][NUM_CACHED_DATA];
memset(scope_cache, 0, sizeof(scope_cache)); memset(scope_cache, 0, sizeof(scope_cache));
uint scope_cache_index[EXTRA_SCOPE_TYPES] = {0}; uint scope_cache_index[EXTRA_SCOPE_TYPES] = {0};
float kbytes_written = 0.0f; float kbytes_written = 0.0f;
while (kbytes_written < MAX_KBYTES_WRITTEN_PER_SESSION) { while (kbytes_written < MAX_KBYTES_WRITTEN_PER_SESSION) {
if (slot_to_dump != -1) { ImScopeDumpInstruction dump = dump_instruction.load(std::memory_order::memory_order_relaxed);
std::string filename = std::string(path); if (dump.slot != -1) {
filename += has_dir ? "/" : "-"; std::string filename;
filename += std::to_string(frame_to_dump) + std::string("-") + std::to_string(slot_to_dump) + std::string(".imscope"); 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); std::ofstream outf(filename, std::ios_base::out | std::ios_base::binary);
if (!outf) { if (!outf) {
LOG_E(PHY, "Could not open file %s for writing\n", filename.c_str()); 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) ...@@ -104,7 +133,7 @@ void *imscope_record_thread(void *data_void_ptr)
for (auto i = 0U; i < EXTRA_SCOPE_TYPES; i++) { for (auto i = 0U; i < EXTRA_SCOPE_TYPES; i++) {
for (auto j = 0U; j < NUM_CACHED_DATA; j++) { for (auto j = 0U; j < NUM_CACHED_DATA; j++) {
ImScopeData &scope_data = scope_cache[i][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); scope_data.dump_to_file(outf);
} }
} }
...@@ -113,7 +142,7 @@ void *imscope_record_thread(void *data_void_ptr) ...@@ -113,7 +142,7 @@ void *imscope_record_thread(void *data_void_ptr)
kbytes_written += pos / 1000.0f; kbytes_written += pos / 1000.0f;
outf.close(); outf.close();
LOG_D(PHY, "ImScope done writing to %s\n", filename.c_str()); 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++) { for (auto i = 0U; i < EXTRA_SCOPE_TYPES; i++) {
ImScopeDataWrapper &scope_data = scope_array[i]; ImScopeDataWrapper &scope_data = scope_array[i];
......
...@@ -112,7 +112,7 @@ typedef struct scopeData_s { ...@@ -112,7 +112,7 @@ typedef struct scopeData_s {
bool (*tryLockScopeData)(enum scopeDataType type, int elementSz, int colSz, int lineSz, metadata *meta); 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 (*copyDataUnsafeWithOffset)(enum scopeDataType type, void *dataIn, size_t size, size_t offset, int copy_index);
void (*unlockScopeData)(enum scopeDataType type); void (*unlockScopeData)(enum scopeDataType type);
void (*dumpScopeData)(int slot, int frame); void (*dumpScopeData)(int slot, int frame, const char *cause_string);
} scopeData_t; } scopeData_t;
int load_softscope(char *exectype, void *initarg); int load_softscope(char *exectype, void *initarg);
...@@ -158,10 +158,10 @@ void copyData(void *, enum scopeDataType type, void *dataIn, int elementSz, int ...@@ -158,10 +158,10 @@ void copyData(void *, enum scopeDataType type, void *dataIn, int elementSz, int
scope_data->unlockScopeData(type); \ scope_data->unlockScopeData(type); \
} }
#define gNBdumpScopeData(gnb, slot, frame) \ #define gNBdumpScopeData(gnb, slot, frame, cause_string) \
scopeData_t *scope_data = (scopeData_t *)gnb->scopeData; \ scopeData_t *scope_data = (scopeData_t *)gnb->scopeData; \
if (scope_data && scope_data->dumpScopeData) { \ if (scope_data && scope_data->dumpScopeData) { \
scope_data->dumpScopeData(slot, frame); \ scope_data->dumpScopeData(slot, frame, cause_string); \
} }
#define UEScopeHasTryLock(ue) \ #define UEScopeHasTryLock(ue) \
...@@ -183,10 +183,10 @@ void copyData(void *, enum scopeDataType type, void *dataIn, int elementSz, int ...@@ -183,10 +183,10 @@ void copyData(void *, enum scopeDataType type, void *dataIn, int elementSz, int
scope_data->unlockScopeData(type); \ scope_data->unlockScopeData(type); \
} }
#define UEdumpScopeData(ue, slot, frame) \ #define UEdumpScopeData(ue, slot, frame, cause_string) \
scopeData_t *scope_data = (scopeData_t *)ue->scopeData; \ scopeData_t *scope_data = (scopeData_t *)ue->scopeData; \
if (scope_data && scope_data->dumpScopeData) { \ if (scope_data && scope_data->dumpScopeData) { \
scope_data->dumpScopeData(slot, frame); \ scope_data->dumpScopeData(slot, frame, cause_string); \
} \ } \
#ifdef __cplusplus #ifdef __cplusplus
......
...@@ -439,7 +439,7 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, boo ...@@ -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->ulsch_pdu.rb_size,
ulsch_harq->TBS); ulsch_harq->TBS);
nr_fill_indication(gNB, ulsch->frame, ulsch->slot, ULSCH_id, ulsch->harq_pid, 1, 0, crc, pdu); 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; ulsch->handled = 1;
LOG_D(PHY, "ULSCH %d in error\n",ULSCH_id); 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 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 ...@@ -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++]; 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); nr_fill_indication(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid, 1, 1, crc, pdu);
pusch_DTX++; pusch_DTX++;
gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame); gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame, "ULSCH_DTX");
continue; continue;
} }
} else { } else {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment