Commit bcb6f006 authored by Cedric Roux's avatar Cedric Roux

T tracer: add gnb tracer

Minimalist gnb tracer to trace (for the moment) rxdataF when some
decoding for PUCCH or PUSCH has been done.

Important: T_BUFFER_MAX and T_CACHE_SIZE have been changed. T_BUFFER_MAX
is twice as big as before. T_CACHE_SIZE has been devided by two. Globally,
the memory usage of the T tracer is the same, but since we divided by two
the number of buffers in the cache, we may hit some realtime problems if
all the buffers are busy at some point. The simple solution would be to
use 8192*2 for T_CACHE_SIZE as it was, but then we double the memory usage
of the T tracer. This, or another solution, to be defined.
parent 01141602
...@@ -4,6 +4,7 @@ T_IDs.h ...@@ -4,6 +4,7 @@ T_IDs.h
T_messages.txt.h T_messages.txt.h
genids genids
tracer/enb tracer/enb
tracer/gnb
tracer/extract_config tracer/extract_config
tracer/record tracer/record
tracer/replay tracer/replay
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
/* let's have 100 RBs functional for the basic simulator */ /* let's have 100 RBs functional for the basic simulator */
# define T_BUFFER_MAX (1024*64*2) # define T_BUFFER_MAX (1024*64*2)
#else #else
# define T_BUFFER_MAX (1024*64) # define T_BUFFER_MAX (1024*128)
#endif #endif
/* size of the local cache for messages (must be pow(2,something)) */ /* size of the local cache for messages (must be pow(2,something)) */
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
/* we don't need much space for the basic simulator */ /* we don't need much space for the basic simulator */
# define T_CACHE_SIZE 1024 # define T_CACHE_SIZE 1024
#else #else
# define T_CACHE_SIZE (8192 * 2) # define T_CACHE_SIZE (8192)
#endif #endif
/* maximum number of bytes a message can contain */ /* maximum number of bytes a message can contain */
......
...@@ -89,6 +89,10 @@ ID = GNB_PHY_MIB ...@@ -89,6 +89,10 @@ ID = GNB_PHY_MIB
DESC = NR MIB data DESC = NR MIB data
GROUP = ALL:PHY:GNB:WIRESHARK GROUP = ALL:PHY:GNB:WIRESHARK
FORMAT = int,gNB_ID : int,frame : int,slot : buffer,data FORMAT = int,gNB_ID : int,frame : int,slot : buffer,data
ID = GNB_PHY_PUCCH_PUSCH_IQ
DESC = gNodeB input data in the frequency domain for a slot where some PUCCH or PUSCH detection was done
GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB
FORMAT = int,frame : int,slot : buffer,rxdataF
#MAC logs #MAC logs
ID = ENB_MAC_UE_DL_SDU ID = ENB_MAC_UE_DL_SDU
......
...@@ -7,7 +7,8 @@ LIBS=-lm ...@@ -7,7 +7,8 @@ LIBS=-lm
XLIBS=-lX11 -lpng -lXft XLIBS=-lX11 -lpng -lXft
all: record replay extract_config textlog enb ue vcd macpdu2wireshark \ all: record replay extract_config textlog enb ue vcd macpdu2wireshark \
extract_input_subframe extract_output_subframe to_vcd extract multi extract_input_subframe extract_output_subframe to_vcd extract multi \
gnb
record: utils.o record.o database.o config.o record: utils.o record.o database.o config.o
$(CC) $(CFLAGS) -o record $^ $(LIBS) $(CC) $(CFLAGS) -o record $^ $(LIBS)
...@@ -60,6 +61,11 @@ macpdu2wireshark: macpdu2wireshark.o database.o utils.o handler.o event.o \ ...@@ -60,6 +61,11 @@ macpdu2wireshark: macpdu2wireshark.o database.o utils.o handler.o event.o \
multi: multi.o utils.o database.o config.o multi: multi.o utils.o database.o config.o
$(CC) $(CFLAGS) -o multi $^ $(LIBS) $(CC) $(CFLAGS) -o multi $^ $(LIBS)
gnb: utils.o gnb.o database.o event.o handler.o config.o \
view/view.a gui/gui.a logger/logger.a \
filter/filter.a
$(CC) $(CFLAGS) -o gnb $^ $(LIBS) $(XLIBS)
multi.o: ../T_IDs.h multi.o: ../T_IDs.h
../T_IDs.h: ../T_IDs.h:
...@@ -85,7 +91,7 @@ filter/filter.a: ...@@ -85,7 +91,7 @@ filter/filter.a:
clean: clean:
rm -f *.o core tracer_remote textlog enb ue vcd record replay rm -f *.o core tracer_remote textlog enb ue vcd record replay
rm -f extract_config macpdu2wireshark extract_input_subframe rm -f extract_config macpdu2wireshark extract_input_subframe
rm -f extract_output_subframe to_vcd extract multi rm -f extract_output_subframe to_vcd extract multi gnb
cd gui && $(MAKE) clean cd gui && $(MAKE) clean
cd view && $(MAKE) clean cd view && $(MAKE) clean
cd logger && $(MAKE) clean cd logger && $(MAKE) clean
......
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include "database.h"
#include "handler.h"
#include "config.h"
#include "logger/logger.h"
#include "view/view.h"
#include "gui/gui.h"
typedef struct {
widget *pucch_pusch_iq_plot;
logger *pucch_pusch_iq_logger;
} gnb_gui;
typedef struct {
int socket;
int *is_on;
int nevents;
pthread_mutex_t lock;
gnb_gui *e;
void *database;
} gnb_data;
void is_on_changed(void *_d)
{
gnb_data *d = _d;
char t;
if (pthread_mutex_lock(&d->lock)) abort();
if (d->socket == -1) goto no_connection;
t = 1;
if (socket_send(d->socket, &t, 1) == -1 ||
socket_send(d->socket, &d->nevents, sizeof(int)) == -1 ||
socket_send(d->socket, d->is_on, d->nevents * sizeof(int)) == -1)
goto connection_dies;
no_connection:
if (pthread_mutex_unlock(&d->lock)) abort();
return;
connection_dies:
close(d->socket);
d->socket = -1;
if (pthread_mutex_unlock(&d->lock)) abort();
}
void usage(void)
{
printf(
"options:\n"
" -d <database file> this option is mandatory\n"
" -ip <host> connect to given IP address (default %s)\n"
" -p <port> connect to given port (default %d)\n",
DEFAULT_REMOTE_IP,
DEFAULT_REMOTE_PORT
);
exit(1);
}
static void *gui_thread(void *_g)
{
gui *g = _g;
gui_loop(g);
return NULL;
}
static void gnb_main_gui(gnb_gui *e, gui *g, event_handler *h, void *database,
gnb_data *ed)
{
widget *main_window;
widget *top_container;
widget *line;
widget *w;
logger *l;
view *v;
main_window = new_toplevel_window(g, 500, 300, "gNB tracer");
top_container = new_container(g, VERTICAL);
widget_add_child(g, main_window, top_container, -1);
line = new_container(g, HORIZONTAL);
widget_add_child(g, top_container, line, -1);
/* PUCCH/PUSCH IQ data */
w = new_xy_plot(g, 55, 55, "", 50);
e->pucch_pusch_iq_plot = w;
widget_add_child(g, line, w, -1);
xy_plot_set_range(g, w, -1000, 1000, -1000, 1000);
xy_plot_set_title(g, w, "rxdataF");
l = new_iqlog_full(h, database, "GNB_PHY_PUCCH_PUSCH_IQ", "rxdataF");
v = new_view_xy(300*12*14,10,g,w,new_color(g,"#000"),XY_FORCED_MODE);
logger_add_view(l, v);
e->pucch_pusch_iq_logger = l;
}
int main(int n, char **v)
{
char *database_filename = NULL;
void *database;
char *ip = DEFAULT_REMOTE_IP;
int port = DEFAULT_REMOTE_PORT;
int *is_on;
int number_of_events;
int i;
event_handler *h;
gnb_data gnb_data;
gui *g;
gnb_gui eg;
for (i = 1; i < n; i++) {
if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
if (!strcmp(v[i], "-d"))
{ if (i > n-2) usage(); database_filename = v[++i]; continue; }
usage();
}
if (database_filename == NULL) {
printf("ERROR: provide a database file (-d)\n");
exit(1);
}
database = parse_database(database_filename);
load_config_file(database_filename);
number_of_events = number_of_ids(database);
is_on = calloc(number_of_events, sizeof(int));
if (is_on == NULL) abort();
h = new_handler(database);
on_off(database, "GNB_PHY_PUCCH_PUSCH_IQ", is_on, 1);
gnb_data.database = database;
gnb_data.socket = -1;
gnb_data.is_on = is_on;
gnb_data.nevents = number_of_events;
if (pthread_mutex_init(&gnb_data.lock, NULL)) abort();
g = gui_init();
new_thread(gui_thread, g);
gnb_main_gui(&eg, g, h, database, &gnb_data);
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
restart:
clear_remote_config();
if (gnb_data.socket != -1) close(gnb_data.socket);
gnb_data.socket = connect_to(ip, port);
/* send the first message - activate selected traces */
is_on_changed(&gnb_data);
/* read messages */
while (1) {
event e;
e = get_event(gnb_data.socket, &ebuf, database);
if (e.type == -1) goto restart;
if (pthread_mutex_lock(&gnb_data.lock)) abort();
handle_event(h, e);
if (pthread_mutex_unlock(&gnb_data.lock)) abort();
}
return 0;
}
...@@ -74,6 +74,44 @@ static void _event(void *p, event e) ...@@ -74,6 +74,44 @@ static void _event(void *p, event e)
l->common.v[i]->append(l->common.v[i], l->i, l->q, count); l->common.v[i]->append(l->common.v[i], l->i, l->q, count);
} }
static void _event_full(void *p, event e)
{
struct iqlog *l = p;
int i;
void *buffer;
int bsize;
int nsamples;
float *idst, *qdst;
if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0)
return;
buffer = e.e[l->buffer_arg].b;
bsize = e.e[l->buffer_arg].bsize;
nsamples = bsize / 4;
if (nsamples > l->max_length) {
l->i = realloc(l->i, nsamples * sizeof(float));
if (l->i == NULL) abort();
l->q = realloc(l->q, nsamples * sizeof(float));
if (l->q == NULL) abort();
l->max_length = nsamples;
}
idst = l->i;
qdst = l->q;
for (i = 0; i < nsamples; i++) {
*idst = ((int16_t *)buffer)[i * 2];
*qdst = ((int16_t *)buffer)[i * 2 + 1];
idst++;
qdst++;
}
for (i = 0; i < l->common.vsize; i++)
l->common.v[i]->append(l->common.v[i], l->i, l->q, nsamples);
}
logger *new_iqlog(event_handler *h, void *database, logger *new_iqlog(event_handler *h, void *database,
char *event_name, char *nb_rb, char *N_RB_UL, char *symbols_per_tti, char *event_name, char *nb_rb, char *N_RB_UL, char *symbols_per_tti,
char *buffer_varname) char *buffer_varname)
...@@ -149,3 +187,43 @@ logger *new_iqlog(event_handler *h, void *database, ...@@ -149,3 +187,43 @@ logger *new_iqlog(event_handler *h, void *database,
return ret; return ret;
} }
logger *new_iqlog_full(event_handler *h, void *database, char *event_name,
char *buffer_varname)
{
struct iqlog *ret;
int event_id;
database_event_format f;
int i;
ret = calloc(1, sizeof(struct iqlog)); if (ret == NULL) abort();
ret->common.event_name = strdup(event_name);
if (ret->common.event_name == NULL) abort();
ret->database = database;
event_id = event_id_from_name(database, event_name);
ret->common.handler_id = register_handler_function(h, event_id, _event_full,
ret);
f = get_format(database, event_id);
/* look for args */
ret->buffer_arg = -1;
for (i = 0; i < f.count; i++) {
if (!strcmp(f.name[i], buffer_varname)) ret->buffer_arg = i;
}
if (ret->buffer_arg == -1) {
printf("%s:%d: buffer argument '%s' not found in event '%s'\n",
__FILE__, __LINE__, buffer_varname, event_name);
abort();
}
if (strcmp(f.type[ret->buffer_arg], "buffer") != 0) {
printf("%s:%d: argument '%s' has wrong type (should be 'buffer')\n",
__FILE__, __LINE__, buffer_varname);
abort();
}
return ret;
}
...@@ -23,6 +23,8 @@ logger *new_ticklog(void *event_handler, void *database, ...@@ -23,6 +23,8 @@ logger *new_ticklog(void *event_handler, void *database,
logger *new_iqlog(void *event_handler, void *database, logger *new_iqlog(void *event_handler, void *database,
char *event_name, char *nb_rb, char *N_RB_UL, char *symbols_per_tti, char *event_name, char *nb_rb, char *N_RB_UL, char *symbols_per_tti,
char *buffer_varname); char *buffer_varname);
logger *new_iqlog_full(void *event_handler, void *database, char *event_name,
char *buffer_varname);
logger *new_iqdotlog(void *event_handler, void *database, logger *new_iqdotlog(void *event_handler, void *database,
char *event_name, char *I, char *Q); char *event_name, char *I, char *Q);
......
...@@ -542,6 +542,9 @@ void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) ...@@ -542,6 +542,9 @@ void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
} }
void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
/* those variables to log T_GNB_PHY_PUCCH_PUSCH_IQ only when we try to decode */
int pucch_decode_done = 0;
int pusch_decode_done = 0;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,1);
LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx); LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx);
...@@ -558,6 +561,8 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) ...@@ -558,6 +561,8 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
(pucch->frame == frame_rx) && (pucch->frame == frame_rx) &&
(pucch->slot == slot_rx) ) { (pucch->slot == slot_rx) ) {
pucch_decode_done = 1;
nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu; nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu;
uint16_t num_ucis; uint16_t num_ucis;
switch (pucch_pdu->format_type) { switch (pucch_pdu->format_type) {
...@@ -646,6 +651,8 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) ...@@ -646,6 +651,8 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
} }
#endif #endif
pusch_decode_done = 1;
uint8_t symbol_start = ulsch_harq->ulsch_pdu.start_symbol_index; uint8_t symbol_start = ulsch_harq->ulsch_pdu.start_symbol_index;
uint8_t symbol_end = symbol_start + ulsch_harq->ulsch_pdu.nr_of_symbols; uint8_t symbol_end = symbol_start + ulsch_harq->ulsch_pdu.nr_of_symbols;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH,1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH,1);
...@@ -673,5 +680,9 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) ...@@ -673,5 +680,9 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
// figure out a better way to choose slot_rx, 19 is ok for a particular TDD configuration with 30kHz SCS // figure out a better way to choose slot_rx, 19 is ok for a particular TDD configuration with 30kHz SCS
if ((frame_rx&127) == 0 && slot_rx==19) dump_pusch_stats(gNB); if ((frame_rx&127) == 0 && slot_rx==19) dump_pusch_stats(gNB);
if (pucch_decode_done || pusch_decode_done) {
T(T_GNB_PHY_PUCCH_PUSCH_IQ, T_INT(frame_rx), T_INT(slot_rx), T_BUFFER(&gNB->common_vars.rxdataF[0][0], gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size * 4));
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,0);
} }
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