Merge remote-tracking branch 'origin/t-gnb-mac' into integration_2025_w35 (!3538)
add a new graphical T tracer to see gNB MAC scheduling decisions May be useful for debugging
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
genids
|
||||
tracer/enb
|
||||
tracer/gnb
|
||||
tracer/gnb_mac
|
||||
tracer/extract_config
|
||||
tracer/record
|
||||
tracer/replay
|
||||
|
||||
@@ -92,9 +92,13 @@ ID = UE_PHY_INITIATE_RA_PROCEDURE
|
||||
GROUP = ALL:PHY:UE:WIRESHARK
|
||||
FORMAT = int,frame : int,subframe_or_slot : int,preamble : int,power
|
||||
ID = GNB_PHY_DL_TICK
|
||||
DESC = gNodeB downlink tick - one tick per ms at start of downlink processing
|
||||
DESC = gNodeB downlink tick - one tick per slot at start of downlink processing
|
||||
GROUP = ALL:PHY:GRAPHIC:GNB
|
||||
FORMAT = int,gNB_ID : int,frame : int,subframe
|
||||
FORMAT = int,gNB_ID : int,frame : int,slot
|
||||
ID = GNB_PHY_UL_TICK
|
||||
DESC = gNodeB uplink tick - one tick per slot at start of uplink processing
|
||||
GROUP = ALL:PHY:GRAPHIC:GNB
|
||||
FORMAT = int,gNB_ID : int,frame : int,slot
|
||||
ID = ENB_PHY_MIB
|
||||
DESC = MIB data
|
||||
GROUP = ALL:PHY:ENB:WIRESHARK
|
||||
@@ -221,6 +225,22 @@ ID = NRUE_MAC_DL_RAR_PDU_WITH_DATA
|
||||
DESC = NR MAC downlink PDU for RAR
|
||||
GROUP = ALL:MAC:UE:WIRESHARK
|
||||
FORMAT = int,rnti : int,frame : int,slot : buffer,data
|
||||
ID = GNB_MAC_DL
|
||||
DESC = NR MAC downlink scheduler decision for an UE
|
||||
GROUP = ALL:MAC:GNB
|
||||
FORMAT = int,rnti : int,frame : int,slot : int,mcs : int,tbs
|
||||
ID = GNB_MAC_LCID_DL
|
||||
DESC = NR MAC downlink scheduler decision for an UE for a specific LCID
|
||||
GROUP = ALL:MAC:GNB
|
||||
FORMAT = int,rnti : int,frame : int,slot : int,lcid : int,data_size : int,tx_list_occupancy
|
||||
ID = GNB_MAC_UL
|
||||
DESC = NR MAC uplink scheduler decision for an UE
|
||||
GROUP = ALL:MAC:GNB
|
||||
FORMAT = int,rnti : int,frame : int,slot : int,mcs : int,tbs
|
||||
ID = GNB_MAC_LCID_UL
|
||||
DESC = NR MAC uplink traffic received for an UE for a specific LCID
|
||||
GROUP = ALL:MAC:GNB
|
||||
FORMAT = int,rnti : int,frame : int,slot : int,lcid : int,data_size
|
||||
|
||||
#RLC logs
|
||||
ID = ENB_RLC_DL
|
||||
|
||||
@@ -62,9 +62,13 @@ if(T_TRACER_GUI)
|
||||
tracer_logger tracer_view tracer_events)
|
||||
target_link_libraries(gnb PRIVATE png)
|
||||
|
||||
add_executable(ue ue.c)
|
||||
target_link_libraries(ue PRIVATE tracer_utils tracer_filter tracer_gui
|
||||
add_executable(gnb_mac gnb_mac.c)
|
||||
target_link_libraries(gnb_mac PRIVATE tracer_utils tracer_filter tracer_gui
|
||||
tracer_logger tracer_view tracer_events)
|
||||
|
||||
add_executable(ue ue.c)
|
||||
target_link_libraries(ue PRIVATE tracer_utils tracer_view tracer_gui
|
||||
tracer_logger tracer_filter tracer_events)
|
||||
target_link_libraries(ue PRIVATE png)
|
||||
|
||||
add_executable(vcd vcd.c)
|
||||
@@ -77,5 +81,5 @@ if(T_TRACER_GUI)
|
||||
|
||||
add_subdirectory(gui)
|
||||
|
||||
add_dependencies(T_tools enb gnb ue vcd to_vcd)
|
||||
add_dependencies(T_tools enb gnb gnb_mac ue vcd to_vcd)
|
||||
endif()
|
||||
|
||||
@@ -8,7 +8,7 @@ XLIBS=-lX11 -lpng -lXft
|
||||
|
||||
all: record replay extract_config textlog enb ue vcd macpdu2wireshark \
|
||||
extract_input_subframe extract_output_subframe to_vcd extract multi \
|
||||
gnb t_tracer_app_gnb t_tracer_app_ue
|
||||
gnb t_tracer_app_gnb t_tracer_app_ue gnb_mac
|
||||
|
||||
record: utils.o record.o database.o configuration.o
|
||||
$(CC) $(CFLAGS) -o record $^ $(LIBS)
|
||||
@@ -65,14 +65,18 @@ gnb: utils.o gnb.o database.o event.o handler.o configuration.o \
|
||||
filter/filter.a
|
||||
$(CC) $(CFLAGS) -o gnb $^ $(LIBS) $(XLIBS)
|
||||
|
||||
t_tracer_app_gnb: utils.o t_tracer_app_gnb.o database.o event.o handler.o configuration.o \
|
||||
logger/logger.a filter/filter.a
|
||||
t_tracer_app_gnb: utils.o t_tracer_app_gnb.o database.o event.o handler.o \
|
||||
configuration.o logger/logger.a filter/filter.a
|
||||
$(CC) $(CFLAGS) -o t_tracer_app_gnb $^ $(LIBS) $(XLIBS)
|
||||
|
||||
t_tracer_app_ue: utils.o t_tracer_app_ue.o database.o event.o handler.o configuration.o \
|
||||
logger/logger.a filter/filter.a
|
||||
t_tracer_app_ue: utils.o t_tracer_app_ue.o database.o event.o handler.o \
|
||||
configuration.o logger/logger.a filter/filter.a
|
||||
$(CC) $(CFLAGS) -o t_tracer_app_ue $^ $(LIBS) $(XLIBS)
|
||||
|
||||
gnb_mac: gnb_mac.o gui/gui.a view/view.a logger/logger.a filter/filter.a \
|
||||
utils.o database.o configuration.o handler.o event.o
|
||||
$(CC) $(CFLAGS) -o gnb_mac $^ $(LIBS) $(XLIBS)
|
||||
|
||||
multi.o: ../incgen/T_IDs.h
|
||||
|
||||
../incgen/T_IDs.h: ../T_messages.txt
|
||||
@@ -98,7 +102,8 @@ filter/filter.a:
|
||||
clean:
|
||||
rm -f *.o core tracer_remote textlog enb ue vcd record replay
|
||||
rm -f extract_config macpdu2wireshark extract_input_subframe
|
||||
rm -f extract_output_subframe to_vcd extract multi gnb t_tracer_app_gnb t_tracer_app_ue
|
||||
rm -f extract_output_subframe to_vcd extract multi gnb
|
||||
rm -f t_tracer_app_gnb t_tracer_app_ue gnb_mac
|
||||
cd gui && $(MAKE) clean
|
||||
cd view && $(MAKE) clean
|
||||
cd logger && $(MAKE) clean
|
||||
|
||||
@@ -340,12 +340,12 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database,
|
||||
xy_plot_set_range(g, w, 0, 1024*10, -10, 80);
|
||||
l = new_ttilog(h, database,
|
||||
"ENB_PHY_PUCCH_1_ENERGY", "frame", "subframe", "threshold", 0);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#ff0000"));
|
||||
v = new_view_tti(10, g, w, new_color(g, "#ff0000"), 10);
|
||||
logger_add_view(l, v);
|
||||
e->pucch1_energy_ue_threshold_logger = l;
|
||||
l = new_ttilog(h, database,
|
||||
"ENB_PHY_PUCCH_1_ENERGY", "frame", "subframe", "energy", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"));
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10);
|
||||
logger_add_view(l, v);
|
||||
e->pucch1_energy_ue_energy_logger = l;
|
||||
|
||||
@@ -368,7 +368,7 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database,
|
||||
widget_add_child(g, line, w, -1);
|
||||
l = new_ticked_ttilog(h, database, "ENB_PHY_DL_TICK", "frame", "subframe",
|
||||
"ENB_PHY_DLSCH_UE_DCI", "mcs", 0, -1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"));
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10);
|
||||
logger_add_view(l, v);
|
||||
e->dl_mcs_logger = l;
|
||||
|
||||
@@ -379,7 +379,7 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database,
|
||||
widget_add_child(g, line, w, -1);
|
||||
l = new_ticked_ttilog(h, database, "ENB_PHY_DL_TICK", "frame", "subframe",
|
||||
"ENB_PHY_ULSCH_UE_DCI", "mcs", 0, -1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"));
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10);
|
||||
logger_add_view(l, v);
|
||||
e->ul_mcs_logger = l;
|
||||
|
||||
@@ -394,8 +394,8 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database,
|
||||
widget_add_child(g, col, w, -1);
|
||||
container_set_child_growable(g, col, w, 1);
|
||||
l = new_throughputlog(h, database, "ENB_PHY_DL_TICK", "frame", "subframe",
|
||||
"ENB_PHY_DLSCH_UE_DCI", "TBS");
|
||||
v = new_view_scrolltti(10, g, w, new_color(g, "#0c0c72"), w2);
|
||||
"ENB_PHY_DLSCH_UE_DCI", "TBS", 10);
|
||||
v = new_view_scrolltti(10, g, w, new_color(g, "#0c0c72"), w2, 10);
|
||||
logger_add_view(l, v);
|
||||
|
||||
/* UE x UL PHY (truly: DCI) throughput */
|
||||
@@ -409,8 +409,8 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database,
|
||||
widget_add_child(g, col, w, -1);
|
||||
container_set_child_growable(g, col, w, 1);
|
||||
l = new_throughputlog(h, database, "ENB_PHY_DL_TICK", "frame", "subframe",
|
||||
"ENB_PHY_ULSCH_UE_DCI", "TBS");
|
||||
v = new_view_scrolltti(10, g, w, new_color(g, "#0c0c72"), w2);
|
||||
"ENB_PHY_ULSCH_UE_DCI", "TBS", 10);
|
||||
v = new_view_scrolltti(10, g, w, new_color(g, "#0c0c72"), w2, 10);
|
||||
logger_add_view(l, v);
|
||||
|
||||
/* downlink/uplink UE DCIs */
|
||||
|
||||
@@ -0,0 +1,332 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "gui/gui.h"
|
||||
#include "view/view.h"
|
||||
#include "logger/logger.h"
|
||||
#include "filter/filter.h"
|
||||
#include "database.h"
|
||||
#include "configuration.h"
|
||||
#include "handler.h"
|
||||
|
||||
typedef struct {
|
||||
int used;
|
||||
} ue_list_item;
|
||||
|
||||
typedef struct {
|
||||
widget *container;
|
||||
} gnb_gui;
|
||||
|
||||
typedef struct {
|
||||
int socket;
|
||||
gui *g;
|
||||
gnb_gui *gg;
|
||||
event_handler *h;
|
||||
void *database;
|
||||
ue_list_item ues[65536];
|
||||
int rnti_arg;
|
||||
} gnb_data;
|
||||
|
||||
void *gui_thread(void *_g)
|
||||
{
|
||||
gui *g = _g;
|
||||
gui_loop(g);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void add_ue(gnb_data *gd, int rnti, int lcid)
|
||||
{
|
||||
event_handler *h = gd->h;
|
||||
void *database = gd->database;
|
||||
gnb_gui *gg = gd->gg;
|
||||
gui *g = gd->g;
|
||||
widget *line;
|
||||
widget *w, *w2, *col;
|
||||
view *v;
|
||||
logger *l;
|
||||
|
||||
gd->ues[rnti].used = 1;
|
||||
|
||||
line = new_container(g, HORIZONTAL);
|
||||
widget_add_child(g, gg->container, line, -1);
|
||||
|
||||
/* label */
|
||||
char s[512];
|
||||
sprintf(s, "UE %d", rnti);
|
||||
widget *label = new_label(g, s);
|
||||
widget_add_child(g, line, label, -1);
|
||||
|
||||
/* DL MCS */
|
||||
w = new_xy_plot(g, 128, 55, "DL mcs", 20);
|
||||
xy_plot_set_range(g, w, 0, 1024*20, -2, 30);
|
||||
widget_add_child(g, line, w, -1);
|
||||
l = new_ticked_ttilog(h, database, "GNB_PHY_DL_TICK", "frame", "slot",
|
||||
"GNB_MAC_DL", "mcs", 0, -1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 20);
|
||||
logger_add_view(l, v);
|
||||
logger_set_filter(l,
|
||||
filter_eq(
|
||||
filter_evarg(database, "GNB_MAC_DL", "rnti"),
|
||||
filter_int(rnti)));
|
||||
|
||||
/* DL TBS */
|
||||
col = new_container(g, VERTICAL);
|
||||
widget_add_child(g, line, col, -1);
|
||||
w = new_xy_plot(g, 70, 10, "DL tbs", 35);
|
||||
w2 = new_textarea(g, 70, 11, 64);
|
||||
xy_plot_set_range(g, w, 0, 1024*20, 0, 1000);
|
||||
xy_plot_set_tick_type(g, w, XY_PLOT_SCROLL_TICK);
|
||||
widget_add_child(g, col, w2, -1);
|
||||
widget_add_child(g, col, w, -1);
|
||||
container_set_child_growable(g, col, w, 1);
|
||||
l = new_ticked_ttilog(h, database, "GNB_PHY_DL_TICK", "frame", "slot",
|
||||
"GNB_MAC_DL", "tbs", 0, -1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 20);
|
||||
view_tti_enable_automax(v, w2);
|
||||
logger_add_view(l, v);
|
||||
logger_set_filter(l,
|
||||
filter_eq(
|
||||
filter_evarg(database, "GNB_MAC_DL", "rnti"),
|
||||
filter_int(rnti)));
|
||||
|
||||
/* DL lcid throughput */
|
||||
col = new_container(g, VERTICAL);
|
||||
widget_add_child(g, line, col, -1);
|
||||
sprintf(s, "DL lcid %d", lcid);
|
||||
w = new_xy_plot(g, 70, 10, s, 35);
|
||||
w2 = new_textarea(g, 70, 11, 64);
|
||||
xy_plot_set_range(g, w, 0, 1000, 0, 100000);
|
||||
xy_plot_set_tick_type(g, w, XY_PLOT_SCROLL_TICK);
|
||||
widget_add_child(g, col, w2, -1);
|
||||
widget_add_child(g, col, w, -1);
|
||||
container_set_child_growable(g, col, w, 1);
|
||||
l = new_throughputlog(h, database, "GNB_PHY_DL_TICK", "frame", "slot",
|
||||
"GNB_MAC_LCID_DL", "data_size", 20);
|
||||
v = new_view_scrolltti(10, g, w, new_color(g, "#0c0c72"), w2, 20);
|
||||
logger_add_view(l, v);
|
||||
logger_set_filter(l,
|
||||
filter_and(
|
||||
filter_eq(
|
||||
filter_evarg(database, "GNB_MAC_LCID_DL", "rnti"),
|
||||
filter_int(rnti)),
|
||||
filter_eq(
|
||||
filter_evarg(database, "GNB_MAC_LCID_DL", "lcid"),
|
||||
filter_int(lcid))));
|
||||
|
||||
/* UL MCS */
|
||||
w = new_xy_plot(g, 128, 55, "UL mcs", 20);
|
||||
xy_plot_set_range(g, w, 0, 1024*20, -2, 30);
|
||||
widget_add_child(g, line, w, -1);
|
||||
/* GNB_PHY_DL_TICK (and not UL) because GNB_MAC_UL is from DCI */
|
||||
l = new_ticked_ttilog(h, database, "GNB_PHY_DL_TICK", "frame", "slot",
|
||||
"GNB_MAC_UL", "mcs", 0, -1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 20);
|
||||
logger_add_view(l, v);
|
||||
logger_set_filter(l,
|
||||
filter_eq(
|
||||
filter_evarg(database, "GNB_MAC_UL", "rnti"),
|
||||
filter_int(rnti)));
|
||||
|
||||
/* UL TBS */
|
||||
col = new_container(g, VERTICAL);
|
||||
widget_add_child(g, line, col, -1);
|
||||
w = new_xy_plot(g, 70, 10, "UL tbs", 35);
|
||||
w2 = new_textarea(g, 70, 11, 64);
|
||||
xy_plot_set_range(g, w, 0, 1024*20, 0, 1000);
|
||||
xy_plot_set_tick_type(g, w, XY_PLOT_SCROLL_TICK);
|
||||
widget_add_child(g, col, w2, -1);
|
||||
widget_add_child(g, col, w, -1);
|
||||
container_set_child_growable(g, col, w, 1);
|
||||
/* GNB_PHY_DL_TICK (and not UL) because GNB_MAC_UL is from DCI */
|
||||
l = new_ticked_ttilog(h, database, "GNB_PHY_DL_TICK", "frame", "slot",
|
||||
"GNB_MAC_UL", "tbs", 0, -1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 20);
|
||||
view_tti_enable_automax(v, w2);
|
||||
logger_add_view(l, v);
|
||||
logger_set_filter(l,
|
||||
filter_eq(
|
||||
filter_evarg(database, "GNB_MAC_UL", "rnti"),
|
||||
filter_int(rnti)));
|
||||
|
||||
/* UL lcid throughput */
|
||||
col = new_container(g, VERTICAL);
|
||||
widget_add_child(g, line, col, -1);
|
||||
sprintf(s, "UL lcid %d", lcid);
|
||||
w = new_xy_plot(g, 70, 10, s, 35);
|
||||
w2 = new_textarea(g, 70, 11, 64);
|
||||
xy_plot_set_range(g, w, 0, 1000, 0, 100000);
|
||||
xy_plot_set_tick_type(g, w, XY_PLOT_SCROLL_TICK);
|
||||
widget_add_child(g, col, w2, -1);
|
||||
widget_add_child(g, col, w, -1);
|
||||
container_set_child_growable(g, col, w, 1);
|
||||
l = new_throughputlog(h, database, "GNB_PHY_UL_TICK", "frame", "slot",
|
||||
"GNB_MAC_LCID_UL", "data_size", 20);
|
||||
v = new_view_scrolltti(10, g, w, new_color(g, "#0c0c72"), w2, 20);
|
||||
logger_add_view(l, v);
|
||||
logger_set_filter(l,
|
||||
filter_and(
|
||||
filter_eq(
|
||||
filter_evarg(database, "GNB_MAC_LCID_UL", "rnti"),
|
||||
filter_int(rnti)),
|
||||
filter_eq(
|
||||
filter_evarg(database, "GNB_MAC_LCID_UL", "lcid"),
|
||||
filter_int(lcid))));
|
||||
|
||||
/* lcid RLC tx buffer occupancy */
|
||||
col = new_container(g, VERTICAL);
|
||||
widget_add_child(g, line, col, -1);
|
||||
sprintf(s, "rlc tx %d", lcid);
|
||||
w = new_xy_plot(g, 70, 10, s, 35);
|
||||
w2 = new_textarea(g, 70, 11, 64);
|
||||
xy_plot_set_range(g, w, 0, 1024*20, 0, 1000);
|
||||
xy_plot_set_tick_type(g, w, XY_PLOT_SCROLL_TICK);
|
||||
widget_add_child(g, col, w2, -1);
|
||||
widget_add_child(g, col, w, -1);
|
||||
container_set_child_growable(g, col, w, 1);
|
||||
l = new_ticked_ttilog(h, database, "GNB_PHY_DL_TICK", "frame", "slot",
|
||||
"GNB_MAC_LCID_DL", "tx_list_occupancy", 0, -1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 20);
|
||||
view_tti_enable_automax(v, w2);
|
||||
logger_add_view(l, v);
|
||||
logger_set_filter(l,
|
||||
filter_and(
|
||||
filter_eq(
|
||||
filter_evarg(database, "GNB_MAC_LCID_DL", "rnti"),
|
||||
filter_int(rnti)),
|
||||
filter_eq(
|
||||
filter_evarg(database, "GNB_MAC_LCID_DL", "lcid"),
|
||||
filter_int(lcid))));
|
||||
}
|
||||
|
||||
void build_gui(gnb_gui *gg, gui *g)
|
||||
{
|
||||
widget *main_window;
|
||||
|
||||
main_window = new_toplevel_window(g, 900, 1000, "gNB MAC tracer");
|
||||
gg->container = new_container(g, VERTICAL);
|
||||
widget_add_child(g, main_window, gg->container, -1);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void check_new_ue(void *_gd, event e)
|
||||
{
|
||||
gnb_data *gd = _gd;
|
||||
int rnti = e.e[gd->rnti_arg].i;
|
||||
if (!gd->ues[rnti].used)
|
||||
add_ue(gd, rnti, 4);
|
||||
}
|
||||
|
||||
int main(int n, char **v)
|
||||
{
|
||||
gui *g;
|
||||
gnb_gui gg;
|
||||
gnb_data *gd;
|
||||
char *database_filename = NULL;
|
||||
void *database;
|
||||
char *ip = DEFAULT_REMOTE_IP;
|
||||
int port = DEFAULT_REMOTE_PORT;
|
||||
event_handler *h;
|
||||
int *is_on;
|
||||
int number_of_events;
|
||||
int i;
|
||||
|
||||
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; }
|
||||
if (!strcmp(v[i], "-ip")) { if (i > n-2) usage(); ip = v[++i]; continue; }
|
||||
if (!strcmp(v[i], "-p")) { if (i > n-2) usage(); port = atoi(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();
|
||||
|
||||
on_off(database, "GNB_PHY_DL_TICK", is_on, 1);
|
||||
on_off(database, "GNB_MAC_DL", is_on, 1);
|
||||
on_off(database, "GNB_MAC_LCID_DL", is_on, 1);
|
||||
on_off(database, "GNB_PHY_UL_TICK", is_on, 1);
|
||||
on_off(database, "GNB_MAC_UL", is_on, 1);
|
||||
on_off(database, "GNB_MAC_LCID_UL", is_on, 1);
|
||||
|
||||
gd = calloc(1, sizeof(*gd)); if (!gd) abort();
|
||||
|
||||
h = new_handler(database);
|
||||
|
||||
g = gui_init();
|
||||
new_thread(gui_thread, g);
|
||||
|
||||
build_gui(&gg, g);
|
||||
|
||||
gd->g = g;
|
||||
gd->gg = ≫
|
||||
gd->h = h;
|
||||
gd->database = database;
|
||||
|
||||
/* get rnti_arg from event GNB_MAC_DL */
|
||||
int event_id = event_id_from_name(database, "GNB_MAC_DL");
|
||||
database_event_format f = get_format(database, event_id);
|
||||
gd->rnti_arg = -1;
|
||||
for (i = 0; i < f.count; i++) {
|
||||
if (!strcmp(f.name[i], "rnti")) gd->rnti_arg = i;
|
||||
}
|
||||
if (gd->rnti_arg == -1) {
|
||||
printf("fatal: event 'GNB_MAC_DL' does not have argument 'rnti'\n");
|
||||
exit(1);
|
||||
}
|
||||
if (strcmp(f.type[gd->rnti_arg], "int") != 0) {
|
||||
printf("fatal: argument 'rnti' of event 'GNB_MAC_DL' is not 'int'\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
register_handler_function(h, event_id, check_new_ue, gd);
|
||||
|
||||
OBUF ebuf = {.osize = 0, .omaxsize = 0, .obuf = NULL};
|
||||
|
||||
gd->socket = -1;
|
||||
|
||||
restart:
|
||||
clear_remote_config();
|
||||
if (gd->socket != -1) close(gd->socket);
|
||||
gd->socket = connect_to(ip, port);
|
||||
|
||||
/* send the first message - activate selected traces */
|
||||
int t = 1;
|
||||
if (socket_send(gd->socket, &t, 1) == -1 ||
|
||||
socket_send(gd->socket, &number_of_events, sizeof(int)) == -1 ||
|
||||
socket_send(gd->socket, is_on, number_of_events * sizeof(int)) == -1)
|
||||
goto restart;
|
||||
|
||||
while (1) {
|
||||
event e;
|
||||
e = get_event(gd->socket, &ebuf, database);
|
||||
if (e.type == -1) goto restart;
|
||||
handle_event(h, e);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -54,6 +54,8 @@ void container_set_child_growable(gui *_gui, widget *_this,
|
||||
int xy_plot_new_plot(gui *gui, widget *this, int color);
|
||||
void xy_plot_set_range(gui *gui, widget *this,
|
||||
float xmin, float xmax, float ymin, float ymax);
|
||||
void xy_plot_get_range(gui *gui, widget *this,
|
||||
float *xmin, float *xmax, float *ymin, float *ymax);
|
||||
void xy_plot_set_points(gui *gui, widget *this,
|
||||
int plot, int npoints, float *x, float *y);
|
||||
void xy_plot_get_dimensions(gui *gui, widget *this, int *width, int *height);
|
||||
|
||||
@@ -280,6 +280,22 @@ void xy_plot_set_range(gui *_gui, widget *_this,
|
||||
gunlock(g);
|
||||
}
|
||||
|
||||
void xy_plot_get_range(gui *_gui, widget *_this,
|
||||
float *xmin, float *xmax, float *ymin, float *ymax)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct xy_plot_widget *this = _this;
|
||||
|
||||
glock(g);
|
||||
|
||||
*xmin = this->xmin;
|
||||
*xmax = this->xmax;
|
||||
*ymin = this->ymin;
|
||||
*ymax = this->ymax;
|
||||
|
||||
gunlock(g);
|
||||
}
|
||||
|
||||
void xy_plot_set_points(gui *_gui, widget *_this, int plot,
|
||||
int npoints, float *x, float *y)
|
||||
{
|
||||
|
||||
@@ -15,8 +15,8 @@ logger *new_ticked_ttilog(void *event_handler, void *database,
|
||||
char *event_name, char *data_varname,
|
||||
int convert_to_dB, float empty_value);
|
||||
logger *new_throughputlog(void *event_handler, void *database,
|
||||
char *tick_event_name, char *frame_varname, char *subframe_varname,
|
||||
char *event_name, char *data_varname);
|
||||
char *tick_event_name, char *frame_varname, char *tick_varname,
|
||||
char *event_name, char *data_varname, int ticks_per_frame);
|
||||
logger *new_timelog(void *event_handler, void *database, char *event_name);
|
||||
logger *new_ticklog(void *event_handler, void *database,
|
||||
char *event_name, char *frame_name, char *subframe_name);
|
||||
|
||||
@@ -13,13 +13,14 @@ struct throughputlog {
|
||||
struct logger common;
|
||||
void *database;
|
||||
int tick_frame_arg;
|
||||
int tick_subframe_arg;
|
||||
int tick_tick_arg;
|
||||
int data_frame_arg;
|
||||
int data_subframe_arg;
|
||||
int data_tick_arg;
|
||||
int data_arg;
|
||||
int last_tick_frame;
|
||||
int last_tick_subframe;
|
||||
unsigned long bits[1000];
|
||||
int last_tick_tick;
|
||||
int ticks_per_frame;
|
||||
unsigned long *bits;
|
||||
unsigned long total;
|
||||
int insert_point;
|
||||
char *tick_event_name;
|
||||
@@ -32,16 +33,16 @@ static void _event(void *p, event e)
|
||||
{
|
||||
struct throughputlog *l = p;
|
||||
int frame;
|
||||
int subframe;
|
||||
int tick;
|
||||
unsigned long value;
|
||||
|
||||
if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0)
|
||||
return;
|
||||
|
||||
frame = e.e[l->data_frame_arg].i;
|
||||
subframe = e.e[l->data_subframe_arg].i;
|
||||
tick = e.e[l->data_tick_arg].i;
|
||||
|
||||
if (frame != l->last_tick_frame || subframe != l->last_tick_subframe) {
|
||||
if (frame != l->last_tick_frame || tick != l->last_tick_tick) {
|
||||
printf("WARNING: %s:%d: data comes without previous tick!\n",
|
||||
__FILE__, __LINE__);
|
||||
return;
|
||||
@@ -62,28 +63,34 @@ static void _tick_event(void *p, event e)
|
||||
struct throughputlog *l = p;
|
||||
int i;
|
||||
int frame;
|
||||
int subframe;
|
||||
int tick;
|
||||
|
||||
if (l->tick_filter != NULL && filter_eval(l->tick_filter, e) == 0)
|
||||
return;
|
||||
|
||||
frame = e.e[l->tick_frame_arg].i;
|
||||
subframe = e.e[l->tick_subframe_arg].i;
|
||||
tick = e.e[l->tick_tick_arg].i;
|
||||
|
||||
for (i = 0; i < l->common.vsize; i++)
|
||||
l->common.v[i]->append(l->common.v[i], frame, subframe, (double)l->total);
|
||||
l->common.v[i]->append(l->common.v[i], frame, tick, (double)l->total);
|
||||
|
||||
l->insert_point = (l->insert_point + 1) % 1000;
|
||||
l->total -= l->bits[l->insert_point];
|
||||
l->bits[l->insert_point] = 0;
|
||||
while (l->last_tick_frame != frame || l->last_tick_tick != tick) {
|
||||
l->insert_point = (l->insert_point + 1) % (100 * l->ticks_per_frame);
|
||||
l->total -= l->bits[l->insert_point];
|
||||
l->bits[l->insert_point] = 0;
|
||||
l->last_tick_tick++;
|
||||
if (l->last_tick_tick == l->ticks_per_frame) {
|
||||
l->last_tick_tick = 0;
|
||||
l->last_tick_frame++;
|
||||
l->last_tick_frame %= 1024;
|
||||
}
|
||||
}
|
||||
|
||||
l->last_tick_frame = frame;
|
||||
l->last_tick_subframe = subframe;
|
||||
}
|
||||
|
||||
logger *new_throughputlog(event_handler *h, void *database,
|
||||
char *tick_event_name, char *frame_varname, char *subframe_varname,
|
||||
char *event_name, char *data_varname)
|
||||
char *tick_event_name, char *frame_varname, char *tick_varname,
|
||||
char *event_name, char *data_varname, int ticks_per_frame)
|
||||
{
|
||||
struct throughputlog *ret;
|
||||
int event_id;
|
||||
@@ -106,21 +113,21 @@ logger *new_throughputlog(event_handler *h, void *database,
|
||||
|
||||
f = get_format(database, event_id);
|
||||
|
||||
/* look for frame and subframe */
|
||||
/* look for frame and tick */
|
||||
ret->tick_frame_arg = -1;
|
||||
ret->tick_subframe_arg = -1;
|
||||
ret->tick_tick_arg = -1;
|
||||
for (i = 0; i < f.count; i++) {
|
||||
if (!strcmp(f.name[i], frame_varname)) ret->tick_frame_arg = i;
|
||||
if (!strcmp(f.name[i], subframe_varname)) ret->tick_subframe_arg = i;
|
||||
if (!strcmp(f.name[i], tick_varname)) ret->tick_tick_arg = i;
|
||||
}
|
||||
if (ret->tick_frame_arg == -1) {
|
||||
printf("%s:%d: frame argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, frame_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (ret->tick_subframe_arg == -1) {
|
||||
printf("%s:%d: subframe argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, subframe_varname, event_name);
|
||||
if (ret->tick_tick_arg == -1) {
|
||||
printf("%s:%d: tick argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, tick_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->tick_frame_arg], "int") != 0) {
|
||||
@@ -128,9 +135,9 @@ logger *new_throughputlog(event_handler *h, void *database,
|
||||
__FILE__, __LINE__, frame_varname);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->tick_subframe_arg], "int") != 0) {
|
||||
if (strcmp(f.type[ret->tick_tick_arg], "int") != 0) {
|
||||
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
|
||||
__FILE__, __LINE__, subframe_varname);
|
||||
__FILE__, __LINE__, tick_varname);
|
||||
abort();
|
||||
}
|
||||
|
||||
@@ -141,13 +148,13 @@ logger *new_throughputlog(event_handler *h, void *database,
|
||||
|
||||
f = get_format(database, event_id);
|
||||
|
||||
/* look for frame, subframe and data args */
|
||||
/* look for frame, tick and data args */
|
||||
ret->data_frame_arg = -1;
|
||||
ret->data_subframe_arg = -1;
|
||||
ret->data_tick_arg = -1;
|
||||
ret->data_arg = -1;
|
||||
for (i = 0; i < f.count; i++) {
|
||||
if (!strcmp(f.name[i], frame_varname)) ret->data_frame_arg = i;
|
||||
if (!strcmp(f.name[i], subframe_varname)) ret->data_subframe_arg = i;
|
||||
if (!strcmp(f.name[i], tick_varname)) ret->data_tick_arg = i;
|
||||
if (!strcmp(f.name[i], data_varname)) ret->data_arg = i;
|
||||
}
|
||||
if (ret->data_frame_arg == -1) {
|
||||
@@ -155,9 +162,9 @@ logger *new_throughputlog(event_handler *h, void *database,
|
||||
__FILE__, __LINE__, frame_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (ret->data_subframe_arg == -1) {
|
||||
printf("%s:%d: subframe argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, subframe_varname, event_name);
|
||||
if (ret->data_tick_arg == -1) {
|
||||
printf("%s:%d: tick argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, tick_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (ret->data_arg == -1) {
|
||||
@@ -170,9 +177,9 @@ logger *new_throughputlog(event_handler *h, void *database,
|
||||
__FILE__, __LINE__, frame_varname);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->data_subframe_arg], "int") != 0) {
|
||||
if (strcmp(f.type[ret->data_tick_arg], "int") != 0) {
|
||||
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
|
||||
__FILE__, __LINE__, subframe_varname);
|
||||
__FILE__, __LINE__, tick_varname);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->data_arg], "int") != 0 &&
|
||||
@@ -183,6 +190,10 @@ logger *new_throughputlog(event_handler *h, void *database,
|
||||
abort();
|
||||
}
|
||||
|
||||
ret->ticks_per_frame = ticks_per_frame;
|
||||
ret->bits = calloc(100 * ticks_per_frame, sizeof(unsigned long));
|
||||
if (ret->bits == NULL) abort();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
+17
-17
@@ -250,15 +250,15 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database,
|
||||
widget_add_child(g, line, w, -1);
|
||||
xy_plot_set_range(g, w, 0, 1024*10, -130, 35);
|
||||
/*l = new_ticked_ttilog(h, database,"UE_PHY_DL_TICK", "frame", "subframe","UE_PHY_MEAS", "rssi", 0, -1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#720c0c"));
|
||||
v = new_view_tti(10, g, w, new_color(g, "#720c0c"), 10);
|
||||
logger_add_view(l, v);
|
||||
e->phy_meas_logger = l;*/
|
||||
l = new_ticked_ttilog(h, database,"UE_PHY_DL_TICK", "frame", "subframe","UE_PHY_MEAS", "rsrp", 0, -1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"));
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10);
|
||||
logger_add_view(l, v);
|
||||
e->phy_meas_logger = l;
|
||||
l = new_ticked_ttilog(h, database,"UE_PHY_DL_TICK", "frame", "subframe","UE_PHY_MEAS", "snr", 0, -1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c720c"));
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c720c"), 10);
|
||||
logger_add_view(l, v);
|
||||
e->phy_meas_logger = l;
|
||||
|
||||
@@ -277,7 +277,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database,
|
||||
widget_add_child(g, line, w, -1);
|
||||
l = new_ticked_ttilog(h, database, "UE_PHY_DL_TICK", "frame", "subframe",
|
||||
"UE_PHY_DLSCH_UE_DCI", "mcs", 0, -1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"));
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10);
|
||||
logger_add_view(l, v);
|
||||
e->dl_mcs_logger = l;
|
||||
|
||||
@@ -288,7 +288,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database,
|
||||
widget_add_child(g, line, w, -1);
|
||||
l = new_ticked_ttilog(h, database, "UE_PHY_DL_TICK", "frame", "subframe",
|
||||
"UE_PHY_ULSCH_UE_DCI", "mcs", 0, -1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"));
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10);
|
||||
logger_add_view(l, v);
|
||||
e->ul_mcs_logger = l;
|
||||
|
||||
@@ -301,12 +301,12 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database,
|
||||
xy_plot_set_range(g, w, 0, 1024*10, -30, 50);
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PUSCH_TX_POWER", "frame", "subframe", "p0_pusch", 0);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"));
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10);
|
||||
logger_add_view(l, v);
|
||||
e->pusch_power_logger = l;
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PUSCH_TX_POWER", "frame", "subframe", "ampl", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#720c0c"));
|
||||
v = new_view_tti(10, g, w, new_color(g, "#720c0c"), 10);
|
||||
logger_add_view(l, v);
|
||||
e->pusch_ampl_logger = l;
|
||||
|
||||
@@ -319,12 +319,12 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database,
|
||||
xy_plot_set_range(g, w, 0, 1024*10, -30, 50);
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PUCCH_TX_POWER", "frame", "subframe", "p0_pucch", 0);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"));
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10);
|
||||
logger_add_view(l, v);
|
||||
e->pucch_power_logger = l;
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PUCCH_TX_POWER", "frame", "subframe", "ampl", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#720c0c"));
|
||||
v = new_view_tti(10, g, w, new_color(g, "#720c0c"), 10);
|
||||
logger_add_view(l, v);
|
||||
e->pucch_ampl_logger = l;
|
||||
|
||||
@@ -335,22 +335,22 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database,
|
||||
xy_plot_set_range(g, w, 0, 1024*10, -10, 80);
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDSCH_ENERGY", "frame", "subframe", "pdsch_ch_level00", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#ff0000"));
|
||||
v = new_view_tti(10, g, w, new_color(g, "#ff0000"), 10);
|
||||
logger_add_view(l, v);
|
||||
e->pdsch_energy_logger = l;
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDSCH_ENERGY", "frame", "subframe", "pdsch_ch_level01", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#00ff00"));
|
||||
v = new_view_tti(10, g, w, new_color(g, "#00ff00"), 10);
|
||||
logger_add_view(l, v);
|
||||
e->pdsch_energy_logger = l;
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDSCH_ENERGY", "frame", "subframe", "pdsch_ch_level10", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0f0f0f"));
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0f0f0f"), 10);
|
||||
logger_add_view(l, v);
|
||||
e->pdsch_energy_logger = l;
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDSCH_ENERGY", "frame", "subframe", "pdsch_ch_level11", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0000ff"));
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0000ff"), 10);
|
||||
logger_add_view(l, v);
|
||||
e->pdsch_energy_logger = l;
|
||||
|
||||
@@ -361,22 +361,22 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database,
|
||||
xy_plot_set_range(g, w, 0, 1024*10, -10, 80);
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDCCH_ENERGY", "frame", "subframe", "pdcch_ch_level00", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#ff0000"));
|
||||
v = new_view_tti(10, g, w, new_color(g, "#ff0000"), 10);
|
||||
logger_add_view(l, v);
|
||||
e->pdcch_energy_logger = l;
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDCCH_ENERGY", "frame", "subframe", "pdcch_ch_level01", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#00ff00"));
|
||||
v = new_view_tti(10, g, w, new_color(g, "#00ff00"), 10);
|
||||
logger_add_view(l, v);
|
||||
e->pdcch_energy_logger = l;
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDCCH_ENERGY", "frame", "subframe", "pdcch_ch_level10", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0f0f0f"));
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0f0f0f"), 10);
|
||||
logger_add_view(l, v);
|
||||
e->pdcch_energy_logger = l;
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDCCH_ENERGY", "frame", "subframe", "pdcch_ch_level11", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0000ff"));
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0000ff"), 10);
|
||||
logger_add_view(l, v);
|
||||
e->pdcch_energy_logger = l;
|
||||
|
||||
|
||||
@@ -15,11 +15,14 @@ struct scrolltti {
|
||||
int plot;
|
||||
float refresh_rate;
|
||||
pthread_mutex_t lock;
|
||||
unsigned long data[1000];
|
||||
unsigned long total; /* sum data[0..999] to have smoother value printed */
|
||||
float xout[1000];
|
||||
float yout[1000];
|
||||
int ticks_per_frame;
|
||||
unsigned long *data;
|
||||
unsigned long total; /* sum data[0..n] to have smoother value printed */
|
||||
float *xout;
|
||||
float *yout;
|
||||
int insert_point;
|
||||
int next_tick_frame;
|
||||
int next_tick_tick;
|
||||
};
|
||||
|
||||
/* this array is used to get Y range 1000, 2000, 5000, 10000, ... */
|
||||
@@ -38,21 +41,21 @@ static void *scrolltti_thread(void *_this)
|
||||
/* TODO: optimize */
|
||||
p = this->insert_point;
|
||||
max = 0;
|
||||
for (i = 0; i < 1000; i++) {
|
||||
for (i = 0; i < this->ticks_per_frame * 100; i++) {
|
||||
this->xout[i] = i;
|
||||
this->yout[i] = this->data[p];
|
||||
if (this->data[p] > max) max = this->data[p];
|
||||
p = (p + 1) % 1000;
|
||||
p = (p + 1) % (this->ticks_per_frame * 100);
|
||||
}
|
||||
bps(o, this->total/1000., "b/s");
|
||||
bps(o, this->total/(this->ticks_per_frame * 100.), "b/s");
|
||||
textarea_set_text(this->g, this->throughput_textarea, o);
|
||||
/* for Y range we want 1000, 2000, 5000, 10000, 20000, 50000, etc. */
|
||||
if (max < 1000) max = 1000;
|
||||
mlog = pow(10, floor(log10(max)));
|
||||
max = tolog[(int)ceil(max/mlog)] * mlog;
|
||||
xy_plot_set_range(this->g, this->w, 0, 1000, 0, max);
|
||||
xy_plot_set_range(this->g, this->w, 0, this->ticks_per_frame * 100, 0, max);
|
||||
xy_plot_set_points(this->g, this->w, this->plot,
|
||||
1000, this->xout, this->yout);
|
||||
this->ticks_per_frame * 100, this->xout, this->yout);
|
||||
if (pthread_mutex_unlock(&this->lock)) abort();
|
||||
sleepms(1000/this->refresh_rate);
|
||||
}
|
||||
@@ -65,20 +68,40 @@ static void clear(view *this)
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
static void append(view *_this, int frame, int subframe, double value)
|
||||
static void insert(struct scrolltti *this, double value)
|
||||
{
|
||||
this->total -= this->data[this->insert_point];
|
||||
this->data[this->insert_point] = value;
|
||||
this->total += this->data[this->insert_point];
|
||||
this->insert_point = (this->insert_point + 1) % (this->ticks_per_frame * 100);
|
||||
}
|
||||
|
||||
static void next_tick(struct scrolltti *this)
|
||||
{
|
||||
this->next_tick_tick++;
|
||||
if (this->next_tick_tick == this->ticks_per_frame) {
|
||||
this->next_tick_tick = 0;
|
||||
this->next_tick_frame++;
|
||||
this->next_tick_frame %= 1024;
|
||||
}
|
||||
}
|
||||
|
||||
static void append(view *_this, int frame, int tick, double value)
|
||||
{
|
||||
struct scrolltti *this = (struct scrolltti *)_this;
|
||||
|
||||
if (pthread_mutex_lock(&this->lock)) abort();
|
||||
this->total -= this->data[this->insert_point];
|
||||
this->data[this->insert_point] = value;
|
||||
this->total += this->data[this->insert_point];
|
||||
this->insert_point = (this->insert_point + 1) % 1000;
|
||||
while (this->next_tick_frame != frame || this->next_tick_tick != tick) {
|
||||
insert(this, 0);
|
||||
next_tick(this);
|
||||
}
|
||||
insert(this, value);
|
||||
next_tick(this);
|
||||
if (pthread_mutex_unlock(&this->lock)) abort();
|
||||
}
|
||||
|
||||
view *new_view_scrolltti(float refresh_rate, gui *g, widget *w, int color,
|
||||
widget *throughput_textarea)
|
||||
widget *throughput_textarea, int ticks_per_frame)
|
||||
{
|
||||
struct scrolltti *ret = calloc(1, sizeof(struct scrolltti));
|
||||
if (ret == NULL) abort();
|
||||
@@ -92,6 +115,14 @@ view *new_view_scrolltti(float refresh_rate, gui *g, widget *w, int color,
|
||||
ret->throughput_textarea = throughput_textarea;
|
||||
ret->plot = xy_plot_new_plot(g, w, color);
|
||||
|
||||
ret->ticks_per_frame = ticks_per_frame;
|
||||
ret->data = calloc(ticks_per_frame * 100, sizeof(unsigned long));
|
||||
if (ret->data == NULL) abort();
|
||||
ret->xout = calloc(ticks_per_frame * 100, sizeof(float));
|
||||
if (ret->xout == NULL) abort();
|
||||
ret->yout = calloc(ticks_per_frame * 100, sizeof(float));
|
||||
if (ret->yout == NULL) abort();
|
||||
|
||||
if (pthread_mutex_init(&ret->lock, NULL)) abort();
|
||||
|
||||
new_thread(scrolltti_thread, ret);
|
||||
|
||||
@@ -5,31 +5,36 @@
|
||||
#include <pthread.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
struct tti {
|
||||
view common;
|
||||
gui *g;
|
||||
widget *w;
|
||||
int automax;
|
||||
widget *w2;
|
||||
int plot;
|
||||
float refresh_rate;
|
||||
pthread_mutex_t lock;
|
||||
float data[1024*10];
|
||||
int valid[1024*10];
|
||||
float xout[1024*10];
|
||||
float yout[1024*10];
|
||||
float *data;
|
||||
int *valid;
|
||||
float *xout;
|
||||
float *yout;
|
||||
int last_insert_point;
|
||||
int ticks_per_frame;
|
||||
};
|
||||
|
||||
static int far_enough(int i, int last_insert, int plot_width)
|
||||
static int far_enough(int i, int last_insert, int plot_width,
|
||||
int ticks_per_frame)
|
||||
{
|
||||
int p1;
|
||||
int p2;
|
||||
int hole_size_px;
|
||||
int hole_size_tti;
|
||||
hole_size_px = 10;
|
||||
hole_size_tti = 10240 * hole_size_px / plot_width;
|
||||
hole_size_tti = 1024 * ticks_per_frame * hole_size_px / plot_width;
|
||||
p1 = last_insert;
|
||||
p2 = (last_insert + hole_size_tti) % (1024*10);
|
||||
p2 = (last_insert + hole_size_tti) % (1024 * ticks_per_frame);
|
||||
if (p1 < p2) {
|
||||
return !(i > p1 && i < p2);
|
||||
}
|
||||
@@ -48,15 +53,31 @@ static void *tti_thread(void *_this)
|
||||
if (pthread_mutex_lock(&this->lock)) abort();
|
||||
xy_plot_get_dimensions(this->g, this->w, &plot_width, &plot_height);
|
||||
length = 0;
|
||||
double max = 0;
|
||||
/* TODO: optimize */
|
||||
for (i = 0; i < 1024*10; i++)
|
||||
for (i = 0; i < 1024 * this->ticks_per_frame; i++)
|
||||
/* do not take points too close after last insertion point */
|
||||
if (this->valid[i] &&
|
||||
far_enough(i, this->last_insert_point, plot_width)) {
|
||||
far_enough(i, this->last_insert_point, plot_width,
|
||||
this->ticks_per_frame)) {
|
||||
this->xout[length] = i;
|
||||
this->yout[length] = this->data[i];
|
||||
if (this->data[i] > max) max = this->data[i];
|
||||
length++;
|
||||
}
|
||||
if (this->automax) {
|
||||
char o[128];
|
||||
sprintf(o, "%d", (int)max);
|
||||
textarea_set_text(this->g, this->w2, o);
|
||||
/* for Y range we want 10, 20, 50, 100, 200, 500, etc. */
|
||||
if (max < 10) max = 10;
|
||||
double mlog = pow(10, floor(log10(max)));
|
||||
static int tolog[11] = { -1, 1, 2, 5, 5, 5, 10, 10, 10, 10, 10 };
|
||||
max = tolog[(int)ceil(max/mlog)] * mlog;
|
||||
float xmin, xmax, ymin, ymax;
|
||||
xy_plot_get_range(this->g, this->w, &xmin, &xmax, &ymin, &ymax);
|
||||
xy_plot_set_range(this->g, this->w, xmin, xmax, 0, max);
|
||||
}
|
||||
xy_plot_set_points(this->g, this->w, this->plot,
|
||||
length, this->xout, this->yout);
|
||||
if (pthread_mutex_unlock(&this->lock)) abort();
|
||||
@@ -71,11 +92,11 @@ static void clear(view *this)
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
static void append(view *_this, int frame, int subframe, double value)
|
||||
static void append(view *_this, int frame, int tick, double value)
|
||||
{
|
||||
struct tti *this = (struct tti *)_this;
|
||||
int i;
|
||||
int index = frame * 10 + subframe;
|
||||
int index = frame * this->ticks_per_frame + tick;
|
||||
|
||||
if (pthread_mutex_lock(&this->lock)) abort();
|
||||
|
||||
@@ -84,10 +105,10 @@ static void append(view *_this, int frame, int subframe, double value)
|
||||
* this may be wrong if delay between two append is
|
||||
* greater than 1024 frames (something like that)
|
||||
*/
|
||||
i = (this->last_insert_point + 1) % (1024*10);
|
||||
i = (this->last_insert_point + 1) % (1024 * this->ticks_per_frame);
|
||||
while (i != index) {
|
||||
this->valid[i] = 0;
|
||||
i = (i + 1) % (1024*10);
|
||||
i = (i + 1) % (1024 * this->ticks_per_frame);
|
||||
}
|
||||
|
||||
this->data[index] = value;
|
||||
@@ -98,7 +119,8 @@ static void append(view *_this, int frame, int subframe, double value)
|
||||
if (pthread_mutex_unlock(&this->lock)) abort();
|
||||
}
|
||||
|
||||
view *new_view_tti(float refresh_rate, gui *g, widget *w, int color)
|
||||
view *new_view_tti(float refresh_rate, gui *g, widget *w, int color,
|
||||
int ticks_per_frame)
|
||||
{
|
||||
struct tti *ret = calloc(1, sizeof(struct tti));
|
||||
if (ret == NULL) abort();
|
||||
@@ -115,7 +137,24 @@ view *new_view_tti(float refresh_rate, gui *g, widget *w, int color)
|
||||
|
||||
if (pthread_mutex_init(&ret->lock, NULL)) abort();
|
||||
|
||||
ret->ticks_per_frame = ticks_per_frame;
|
||||
ret->data = calloc(ticks_per_frame * 1024, sizeof(float));
|
||||
if (ret->data == NULL) abort();
|
||||
ret->valid = calloc(ticks_per_frame * 1024, sizeof(int));
|
||||
if (ret->valid == NULL) abort();
|
||||
ret->xout = calloc(ticks_per_frame * 1024, sizeof(float));
|
||||
if (ret->xout == NULL) abort();
|
||||
ret->yout = calloc(ticks_per_frame * 1024, sizeof(float));
|
||||
if (ret->yout == NULL) abort();
|
||||
|
||||
new_thread(tti_thread, ret);
|
||||
|
||||
return (view *)ret;
|
||||
}
|
||||
|
||||
void view_tti_enable_automax(view *_tti, widget *w2)
|
||||
{
|
||||
struct tti *tti = (struct tti *)_tti;
|
||||
tti->automax = 1;
|
||||
tti->w2 = w2;
|
||||
}
|
||||
|
||||
@@ -17,15 +17,16 @@ view *new_view_stdout(void);
|
||||
view *new_view_textlist(int maxsize, float refresh_rate, gui *g, widget *w);
|
||||
view *new_view_xy(int length, float refresh_rate, gui *g, widget *w,
|
||||
int color, enum xy_mode mode);
|
||||
view *new_view_tti(float refresh_rate, gui *g, widget *w,
|
||||
int color);
|
||||
view *new_view_tti(float refresh_rate, gui *g, widget *w, int color,
|
||||
int ticks_per_frame);
|
||||
view *new_view_scrolltti(float refresh_rate, gui *g, widget *w,
|
||||
int color, widget *throughput_label);
|
||||
int color, widget *throughput_label, int ticks_per_frame);
|
||||
view *new_view_time(int number_of_seconds, float refresh_rate,
|
||||
gui *g, widget *w);
|
||||
view *new_subview_time(view *time, int line, int color, int size);
|
||||
view *new_view_ticktime(float refresh_rate, gui *g, widget *w);
|
||||
view *new_subview_ticktime(view *ticktime, int line, int color, int size);
|
||||
void ticktime_set_tick(view *ticktime, void *logger);
|
||||
void view_tti_enable_automax(view *tti, widget *w2);
|
||||
|
||||
#endif /* _VIEW_H_ */
|
||||
|
||||
Reference in New Issue
Block a user