aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/dummy/arch_plots.cpp5
-rw-r--r--arch/v1/arch.c3
-rw-r--r--arch/v1/arch_plots.cpp41
-rw-r--r--core/client.cpp423
-rw-r--r--core/tui.c98
-rw-r--r--ui/curses/ui.c97
6 files changed, 407 insertions, 260 deletions
diff --git a/arch/dummy/arch_plots.cpp b/arch/dummy/arch_plots.cpp
index 3631339..15d6a7b 100644
--- a/arch/dummy/arch_plots.cpp
+++ b/arch/dummy/arch_plots.cpp
@@ -1,2 +1,3 @@
-std::array<const char *, 0> g_arch_traces;
-std::array<Plot, 0> g_arch_plots;
+std::vector<TraceNamed<ImS64>> g_arch_traces = {};
+std::vector<Plot> g_arch_plots = {};
+std::vector<PlotStacked> g_arch_plots_stacked = {};
diff --git a/arch/v1/arch.c b/arch/v1/arch.c
index 0053ec9..b200e5e 100644
--- a/arch/v1/arch.c
+++ b/arch/v1/arch.c
@@ -5,7 +5,6 @@
INST_EVENT_ARRAY(core, 0, pop) /* instruction population */ \
INST_EVENT_ARRAY(core, 1, exe) /* instruction executions */ \
INST_EVENT_ARRAY(core, 2, wrt) /* instruction writes */
-#define INST_EVENT_ARRAYS_COUNT 3
#define ARCH_EVENT_ARRAYS(core) \
ARCH_EVENT_ARRAY(core, 0, wev) /* write events array*/ \
@@ -987,7 +986,7 @@ void arch_push_data_line(void) {
"%ld"
");",
#define INST(core, pref, index, label, mnemonic, symbol) \
- g_cores[core].i##pref,
+ g_cores[core].i##pref[index],
#define INST_EVENT_ARRAY(core, index, iv) \
INST_SET(core, iv)
#define ARCH_EVENT_ARRAY(core, index, ev) \
diff --git a/arch/v1/arch_plots.cpp b/arch/v1/arch_plots.cpp
index 8d35c87..d88a2a1 100644
--- a/arch/v1/arch_plots.cpp
+++ b/arch/v1/arch_plots.cpp
@@ -1,16 +1,43 @@
-std::array g_arch_traces = std::to_array<const char *>({
+#define INST_EVENT_ARRAYS(core) \
+ INST_EVENT_ARRAY(core, pop) /* instruction population */ \
+ INST_EVENT_ARRAY(core, exe) /* instruction executions */ \
+ INST_EVENT_ARRAY(core, wrt) /* instruction writes */
+
+std::vector<TraceNamed<ImS64>> g_arch_traces = {
+#define INST(core, pref, index, label, mnemonic, symbol) \
+ {#label "_" #pref "_" #core, #label},
+#define INST_EVENT_ARRAY(core, iv) \
+ INST_SET(core, iv)
#define FOR_CORE(i) \
- "wmb0_" #i, \
- "wmb1_" #i, \
- "wdea_" #i,
+ {"wmb0_" #i, "wmb0_" #i}, \
+ {"wmb1_" #i, "wmb1_" #i}, \
+ {"wdea_" #i, "wdea_" #i}, \
+ INST_EVENT_ARRAYS(i)
FOR_CORES
#undef FOR_CORE
-});
+#undef INST_EVENT_ARRAY
+#undef INST
+};
-std::array g_arch_plots = std::to_array<Plot>({
+std::vector<Plot> g_arch_plots = {
{"wevs", "general", {
#define FOR_CORE(i) "wmb0_" #i, "wmb1_" #i, "wdea_" #i,
FOR_CORES
#undef FOR_CORE
}},
-});
+};
+
+std::vector<PlotStacked> g_arch_plots_stacked = {
+#define INST(core, pref, index, label, mnemonic, symbol) \
+ #label "_" #pref "_" #core,
+#define INST_EVENT_ARRAY(core, iv) \
+ {"i" #iv "%_" #core, "population", { \
+ INST_SET(core, iv) \
+ }},
+#define FOR_CORE(i) \
+ INST_EVENT_ARRAYS(i)
+ FOR_CORES
+#undef FOR_CORE
+#undef INST_EVENT_ARRAY
+#undef INST
+};
diff --git a/core/client.cpp b/core/client.cpp
index 227ebaa..1c63540 100644
--- a/core/client.cpp
+++ b/core/client.cpp
@@ -3,15 +3,14 @@
#include <imgui_impl_glfw.h>
#include <imgui_impl_opengl3.h>
#include <implot.h>
+#include <implot_internal.h>
#include <json-c/json.h>
-#include <math.h>
#include <signal.h>
#include <threads.h>
#include <algorithm>
-#include <array>
#include <map>
-#include <tuple>
+#include <string>
#include <vector>
#include "logger.c"
@@ -21,7 +20,6 @@
// ----------------------------------------------------------------------------
#define COLOR_BLACK ImVec4(0.f, 0.f, 0.f, 1.f)
#define FONT_SIZE 12.f
-#define FONT_SOURCE "/usr/share/fonts/droid/DroidSansMono.ttf"
#define GLSL_VERSION "#version 130"
#define PLOT_MAX_COLS 8
#define PLOT_MIN_COLS 1
@@ -54,16 +52,37 @@ enum Status {
STATUS_STOPPING,
};
-struct CompString {
- bool operator()(const char *a, const char *b) const {
- return strcmp(a, b) < 0;
- }
+template <class T> struct Trace : public std::vector<T> {
+ Trace();
+ T *start();
+ void trim();
+
+#if !defined(NDEBUG)
+ T &operator[](size_t n);
+#endif
+};
+
+template <class T> struct TraceNamed : public Trace<T> {
+ std::string m_name;
+ std::string m_name_fmt;
+ TraceNamed(std::string name, std::string name_fmt);
};
struct Plot {
- const char *name;
- const char *section;
- std::vector<const char *> traces;
+ std::string m_name;
+ std::string m_section;
+ std::vector<std::string> m_trace_keys;
+ Plot(std::string name, std::string section, std::vector<std::string> trace_keys);
+ virtual ~Plot();
+ virtual void render();
+};
+
+struct PlotStacked : public Plot {
+ std::vector<ImS64> m_totals;
+ std::vector<double> m_old_trace;
+ std::vector<double> m_new_trace;
+ PlotStacked(std::string name, std::string section, std::vector<std::string> trace_keys);
+ void render();
};
// ----------------------------------------------------------------------------
@@ -71,34 +90,26 @@ struct Plot {
// ----------------------------------------------------------------------------
#include "arch_plots.cpp"
-template <class T, size_t N, size_t M>
-std::array<T, N + M> merge_array(const std::array<T, N> &first, const std::array<T, M> &second) {
- std::array<T, N + M> result{};
- for (size_t i = 0; i < N; i++) result[i] = first[i];
- for (size_t i = 0; i < M; i++) result[N + i] = second[i];
- return result;
-}
-
-std::array g_core_traces = std::to_array<const char *>({
- "rowid",
- "step",
+std::vector<TraceNamed<ImS64>> g_core_traces = {
+ {"rowid", "rowid"},
+ {"step", "step"},
#define FOR_CORE(i) \
- "cycl_" #i, \
- "mall_" #i, \
- "pnum_" #i, \
- "pfst_" #i, \
- "plst_" #i, \
- "amb0_" #i, \
- "amb1_" #i, \
- "emb0_" #i, \
- "emb1_" #i, \
- "eliv_" #i, \
- "edea_" #i,
+ {"cycl_" #i, "cycl_" #i}, \
+ {"mall_" #i, "mall_" #i}, \
+ {"pnum_" #i, "pnum_" #i}, \
+ {"pfst_" #i, "pfst_" #i}, \
+ {"plst_" #i, "plst_" #i}, \
+ {"amb0_" #i, "amb0_" #i}, \
+ {"amb1_" #i, "amb1_" #i}, \
+ {"emb0_" #i, "emb0_" #i}, \
+ {"emb1_" #i, "emb1_" #i}, \
+ {"eliv_" #i, "eliv_" #i}, \
+ {"edea_" #i, "edea_" #i},
FOR_CORES
#undef FOR_CORE
-});
+};
-std::array g_core_plots = std::to_array<Plot>({
+std::vector<Plot> g_core_plots = {
{"cycl", "general", {
#define FOR_CORE(i) "cycl_" #i,
FOR_CORES
@@ -129,14 +140,7 @@ std::array g_core_plots = std::to_array<Plot>({
FOR_CORES
#undef FOR_CORE
}},
-});
-
-std::map<const char *, std::vector<ImS64>, CompString> g_trace_map;
-std::array g_traces = merge_array(g_core_traces, g_arch_traces);
-std::array g_plots = merge_array(g_core_plots, g_arch_plots);
-
-#define TRACE_COUNT g_traces.size()
-#define PLOT_COUNT g_plots.size()
+};
// ----------------------------------------------------------------------------
// Globals
@@ -146,7 +150,8 @@ ImGuiIO *g_imgui_io;
ImGuiStyle *g_imgui_style;
ImPlotStyle *g_implot_style;
-const char *g_x_axes[] = {
+// Data
+std::vector<std::string> g_x_axes = {
"rowid",
"step",
#define FOR_CORE(i) "cycl_" #i,
@@ -162,29 +167,121 @@ int64_t g_x_low = DEFVAL_X_LOW;
int64_t g_x_high = DEFVAL_X_HIGH;
int64_t g_hm_left = DEFVAL_HM_LEFT;
int64_t g_hm_pixel_count = DEFVAL_HM_PIXEL_COUNT;
-int64_t g_hm_pixel_pow; // calculate on startup
+int64_t g_hm_pixel_pow; // calculate on init
int64_t g_x_current = -1l;
-thrd_t g_fetching_thread;
-mtx_t g_fetching_mutex;
int g_trace_len;
int g_trace_offset;
-// Layout globals
+thrd_t g_fetching_thread;
+mtx_t g_fetching_mutex;
+
+// Layout
bool g_data_col_visible = true;
bool g_plot_maximized;
bool g_plot_scroll;
float g_plot_scroll_current;
float g_plot_scroll_to;
float g_data_col_width;
-float g_plot_cells_top[PLOT_MAX_COLS][PLOT_COUNT];
-float g_plot_cells_bottom[PLOT_MAX_COLS][PLOT_COUNT];
-Plot *g_plot_cells[PLOT_MAX_COLS][PLOT_COUNT];
-Plot *g_plot_selected = &g_plots[0];
+std::vector<Plot *> g_plot_cells;
+std::vector<float> g_plot_cells_top;
+std::vector<float> g_plot_cells_bottom;
+std::vector<bool> g_plots_covered;
+Plot *g_plot_selected;
int g_plot_cols = 2;
int g_plot_col_selected;
int g_plot_row_selected;
+// Plots
+std::map<std::string, TraceNamed<ImS64> *> g_trace_map;
+std::vector<TraceNamed<ImS64> *> g_traces;
+std::vector<Plot *> g_plots;
+Trace<double> g_x_axis_normal;
+
+// ----------------------------------------------------------------------------
+// Trace definitions
+// ----------------------------------------------------------------------------
+template <class T> Trace<T>::Trace() : std::vector<T>() {}
+
+template <class T> T *Trace<T>::start() {
+ return this->size() ? &this->operator[](g_trace_offset) : nullptr;
+}
+
+template <class T> void Trace<T>::trim() {
+ assert((int64_t)this->size() >= g_entries * 2);
+ this->erase(this->begin(), this->end() - g_entries);
+}
+
+#if !defined(NDEBUG)
+template <class T> T &Trace<T>::operator[](size_t n) {
+ return this->at(n);
+}
+#endif
+
+// ----------------------------------------------------------------------------
+// TraceNamed definitions
+// ----------------------------------------------------------------------------
+template <class T> TraceNamed<T>::TraceNamed(std::string name, std::string name_fmt) : m_name(name), m_name_fmt(name_fmt) {}
+
+// ----------------------------------------------------------------------------
+// Plot definitions
+// ----------------------------------------------------------------------------
+Plot::Plot(std::string name, std::string section, std::vector<std::string> trace_keys) : m_name(name), m_section(section), m_trace_keys(trace_keys) {}
+
+Plot::~Plot() {}
+
+void Plot::render() {
+ ImS64 *x = g_trace_map[g_x_axes[g_x_axis]]->start();
+
+ for (auto &trace : m_trace_keys) {
+ TraceNamed<ImS64> *trace_obj = g_trace_map[trace];
+ ImS64 *y = trace_obj->start();
+ ImPlot::PlotLine(trace_obj->m_name_fmt.c_str(), x, y, g_trace_len);
+ }
+}
+
+// ----------------------------------------------------------------------------
+// PlotStacked definitions
+// ----------------------------------------------------------------------------
+PlotStacked::PlotStacked(std::string name, std::string section, std::vector<std::string> trace_keys) : Plot(name, section, trace_keys) {}
+
+void PlotStacked::render() {
+ m_totals.resize(g_trace_len);
+ m_old_trace.resize(g_trace_len);
+ m_new_trace.resize(g_trace_len);
+
+ for (size_t i = 0; i < m_trace_keys.size(); i++) {
+ ImPlot::PlotDummy(g_trace_map[m_trace_keys[i]]->m_name_fmt.c_str());
+ }
+
+ for (int i = 0; i < (int)m_trace_keys.size(); i++) {
+ if (GImPlot->CurrentPlot->Items.GetLegendItem(i)->Show) {
+ for (int j = 0; j < g_trace_len; j++) {
+ m_totals[j] += g_trace_map[m_trace_keys[i]]->start()[j];
+ }
+ }
+ }
+
+ for (int i = 0; i < (int)m_trace_keys.size(); i++) {
+ if (GImPlot->CurrentPlot->Items.GetLegendItem(i)->Show) {
+ ImPlotSpec spec = ImPlotSpec(ImPlotProp_FillAlpha, GImPlot->CurrentPlot->Items.GetLegendItem(i)->LegendHovered ? 0.9f : 0.7f);
+
+ for (int j = 0; j < g_trace_len; j++) {
+ m_new_trace[j] = m_totals[j] ? (m_old_trace[j] + (double)g_trace_map[m_trace_keys[i]]->start()[j] / (double)m_totals[j]) : 0.;
+ }
+
+ ImPlot::PlotShaded(g_trace_map[m_trace_keys[i]]->m_name_fmt.c_str(), g_x_axis_normal.start(), m_old_trace.data(), m_new_trace.data(), g_trace_len, spec);
+ ImPlot::PlotLine(g_trace_map[m_trace_keys[i]]->m_name_fmt.c_str(), g_x_axis_normal.start(), m_old_trace.data(), g_trace_len);
+ ImPlot::PlotLine(g_trace_map[m_trace_keys[i]]->m_name_fmt.c_str(), g_x_axis_normal.start(), m_new_trace.data(), g_trace_len);
+ std::swap(m_old_trace, m_new_trace);
+ }
+ }
+
+ m_totals.clear();
+ m_old_trace.clear();
+ m_new_trace.clear();
+}
+
// ----------------------------------------------------------------------------
// Data functions
// ----------------------------------------------------------------------------
@@ -197,17 +294,18 @@ void data_on_field_change(void) {
g_nth = std::clamp(g_nth, DEFVAL_NTH, INT64_MAX);
g_x_low = std::clamp(g_x_low, DEFVAL_X_LOW, INT64_MAX);
g_x_high = std::clamp(g_x_high, g_x_low + 1l, DEFVAL_X_HIGH);
- #if !defined(MVEC_LOOP)
+#if !defined(MVEC_LOOP)
g_hm_left = std::clamp(g_hm_left, DEFVAL_HM_LEFT, (int64_t)MVEC_SIZE);
- #endif
+#endif
g_hm_pixel_count = std::clamp(g_hm_pixel_count, 1l, DEFVAL_HM_PIXEL_COUNT);
g_hm_pixel_pow = std::clamp(g_hm_pixel_pow, 0l, data_max_hm_pixel_pow());
-
g_x_current = -1l;
- for (auto &trace : g_trace_map) {
- trace.second.clear();
- }
+ g_trace_len = 0;
+ g_trace_offset = 0;
+
+ for (auto &trace : g_traces) trace->clear();
+ g_x_axis_normal.clear();
}
void data_reset_fields(void) {
@@ -220,46 +318,49 @@ void data_reset_fields(void) {
g_hm_pixel_count = DEFVAL_HM_PIXEL_COUNT;
g_hm_pixel_pow = data_max_hm_pixel_pow();
- g_trace_len = 0;
- g_trace_offset = 0;
-
data_on_field_change();
}
void data_reset_plot_cells(void) {
- memset(g_plot_cells, 0, PLOT_MAX_COLS * PLOT_COUNT * sizeof(nullptr));
- memset(g_plot_cells_top, 0, PLOT_MAX_COLS * PLOT_COUNT * sizeof(float));
- memset(g_plot_cells_bottom, 0, PLOT_MAX_COLS * PLOT_COUNT * sizeof(float));
+ std::fill(g_plot_cells.begin(), g_plot_cells.end(), nullptr);
+ std::fill(g_plot_cells_top.begin(), g_plot_cells_top.end(), 0.f);
+ std::fill(g_plot_cells_bottom.begin(), g_plot_cells_bottom.end(), 0.f);
}
+#if !defined(NDEBUG)
+void data_validate_traces(void) {
+ for (auto &trace : g_traces) assert(trace->size() == g_traces[0]->size());
+}
+#endif
+
void data_fetch(void) {
- struct json_object *request = json_object_new_object();
+ json_object *request = json_object_new_object();
json_object_object_add(request, "request", json_object_new_string("data"));
json_object_object_add(request, "entries", json_object_new_int64(g_entries));
json_object_object_add(request, "nth", json_object_new_int64(g_nth));
- json_object_object_add(request, "x-axis", json_object_new_string(g_x_axes[g_x_axis]));
+ json_object_object_add(request, "x-axis", json_object_new_string(g_x_axes[g_x_axis].c_str()));
json_object_object_add(request, "x-low", json_object_new_int64(g_x_low));
json_object_object_add(request, "x-high", json_object_new_int64(g_x_high));
json_object_object_add(request, "hm-left", json_object_new_int64(g_hm_left));
json_object_object_add(request, "hm-pixel-count", json_object_new_int64(g_hm_pixel_count));
json_object_object_add(request, "hm-pixel-pow", json_object_new_int64(g_hm_pixel_pow));
json_object_object_add(request, "x-current", json_object_new_int64(g_x_current));
- const char *request_str = json_object_to_json_string(request);
+ std::string request_str = json_object_to_json_string(request);
- log_info("Sending request to server: %s", request_str);
+ log_info("Sending request to server: %s", request_str.c_str());
int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
- struct sockaddr_in socket_addr;
- memset(&socket_addr, 0, sizeof(struct sockaddr_in));
+ sockaddr_in socket_addr;
+ memset(&socket_addr, 0, sizeof(sockaddr_in));
socket_addr.sin_family = AF_INET;
socket_addr.sin_port = htons(PORT);
inet_pton(AF_INET, IP, &socket_addr.sin_addr);
- if (connect(socket_fd, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr_in))) assert(false);
+ if (connect(socket_fd, (sockaddr *)&socket_addr, sizeof(sockaddr_in))) assert(false);
json_object_to_fd(socket_fd, request, 0);
shutdown(socket_fd, SHUT_WR);
- struct json_object *response = json_object_from_fd(socket_fd);
- const char *response_str = json_object_to_json_string(response);
- log_info("Server responded with: %s", response_str);
+ json_object *response = json_object_from_fd(socket_fd);
+ std::string response_str = json_object_to_json_string(response);
+ log_info("Server responded with: %s", response_str.c_str());
mtx_lock(&g_fetching_mutex);
@@ -267,31 +368,38 @@ void data_fetch(void) {
if (g_trace_map.contains(key)) {
for (size_t i = 0; i < json_object_array_length(value); i++) {
ImS64 point = json_object_get_int64(json_object_array_get_idx(value, i));
- g_trace_map.at(key).push_back(point);
+ g_trace_map[key]->push_back(point);
+ }
+ }
+
+ if (std::string(key) == g_x_axes[g_x_axis]) {
+ for (size_t i = 0; i < json_object_array_length(value); i++) {
+ ImS64 point = json_object_get_int64(json_object_array_get_idx(value, i));
+ g_x_axis_normal.push_back((double)point);
}
}
}
- g_x_current = g_trace_map.at(g_x_axes[g_x_axis]).back();
+ g_x_current = g_trace_map[g_x_axes[g_x_axis]]->back();
json_object_put(request);
json_object_put(response);
- g_trace_len = g_trace_map.at("rowid").size();
-
- if (g_trace_len >= g_entries * 2) {
- for (auto &trace : g_trace_map) {
- trace.second.erase(trace.second.begin(), trace.second.end() - g_entries);
- }
+#if !defined(NDEBUG)
+ data_validate_traces();
+#endif
- g_trace_len = g_trace_map.at("rowid").size();
+ if ((int64_t)g_traces[0]->size() >= g_entries * 2) {
+ for (auto &trace : g_traces) trace->trim();
+ g_x_axis_normal.trim();
}
- g_trace_offset = 0;
+#if !defined(NDEBUG)
+ data_validate_traces();
+#endif
- if (g_trace_len > g_entries) {
- g_trace_offset = g_trace_len - g_entries;
- g_trace_len = g_entries;
- }
+ int64_t current_size = g_traces[0]->size();
+ g_trace_len = std::min(current_size, g_entries);
+ g_trace_offset = current_size > g_entries ? current_size - g_entries : 0l;
mtx_unlock(&g_fetching_mutex);
}
@@ -331,11 +439,10 @@ void data_stop_fetching(void) {
// ----------------------------------------------------------------------------
// GUI functions
// ----------------------------------------------------------------------------
-void gui_render_data_input(const char *label, int64_t *target) {
- assert(label);
+void gui_render_data_input(std::string label, int64_t *target) {
assert(target);
- if (ImGui::InputScalar(label, ImGuiDataType_U64, target, nullptr, nullptr, "%#lx")) {
+ if (ImGui::InputScalar(label.c_str(), ImGuiDataType_U64, target, nullptr, nullptr, "%#lx")) {
data_on_field_change();
}
}
@@ -371,9 +478,9 @@ void gui_render_data_col(void) {
gui_render_data_input("entries", &g_entries);
gui_render_data_input("nth", &g_nth);
- if (ImGui::BeginCombo("x-axis", g_x_axes[g_x_axis])) {
+ if (ImGui::BeginCombo("x-axis", g_x_axes[g_x_axis].c_str())) {
for (int i = 0; i < CORES + 2; i++) {
- if (ImGui::Selectable(g_x_axes[i], g_x_axis == i)) {
+ if (ImGui::Selectable(g_x_axes[i].c_str(), g_x_axis == i)) {
data_reset_fields();
g_x_axis = i;
}
@@ -392,7 +499,7 @@ void gui_render_data_col(void) {
case STATUS_STOPPING:
ImGui::LabelText("entries", "%#lx", g_entries);
ImGui::LabelText("nth", "%#lx", g_nth);
- ImGui::LabelText("x-axis", "%s", g_x_axes[g_x_axis]);
+ ImGui::LabelText("x-axis", "%s", g_x_axes[g_x_axis].c_str());
ImGui::LabelText("x-low", "%#lx", g_x_low);
ImGui::LabelText("x-high", "%#lx", g_x_high);
ImGui::LabelText("hm-left", "%#lx", g_hm_left);
@@ -428,7 +535,17 @@ void gui_render_data_col(void) {
ImGui::End();
}
-void gui_render_plot(const Plot *plot, const ImVec2 &frame_size=ImVec2(-1.f, 0.f)) {
+int gui_plot_cell_index(int col, int row) {
+ int index = col * PLOT_MAX_COLS + row;
+ assert(index < (int)g_plot_cells.size());
+ assert(index < (int)g_plot_cells_top.size());
+ assert(index < (int)g_plot_cells_bottom.size());
+ return index;
+}
+
+void gui_render_plot(Plot *plot, const ImVec2 &frame_size=ImVec2(-1.f, 0.f)) {
+ assert(plot);
+
int plot_flags = ImPlotFlags_NoMenus;
int axis_flags = ImPlotAxisFlags_NoMenus;
@@ -438,23 +555,19 @@ void gui_render_plot(const Plot *plot, const ImVec2 &frame_size=ImVec2(-1.f, 0.f
axis_flags |= ImPlotAxisFlags_NoHighlight;
}
- if (ImPlot::BeginPlot(plot->name, frame_size, plot_flags)) {
+ if (ImPlot::BeginPlot(plot->m_name.c_str(), frame_size, plot_flags)) {
ImPlot::SetupAxes(nullptr, nullptr, axis_flags, axis_flags);
- ImS64 *x = g_trace_map.at(g_x_axes[g_x_axis]).data() + g_trace_offset;
-
- for (auto &trace : plot->traces) {
- ImS64 *y = g_trace_map.at(trace).data() + g_trace_offset;
- ImPlot::PlotLine(trace, x, y, g_trace_len);
- }
-
+ plot->render();
ImPlot::EndPlot();
}
}
void gui_render_plots(void) {
- const char *section_current = g_plots[0].section;
- const char *section_next = nullptr;
- bool plots_covered[PLOT_COUNT] = { 0 };
+ std::string section_current = g_plots[0]->m_section;
+ std::string section_next;
+
+ g_plots_covered.clear();
+ g_plots_covered.resize(g_plots.size(), false);
const ImGuiViewport *viewport = ImGui::GetMainViewport();
const ImVec2 win_pos = g_data_col_visible ? ImVec2(g_data_col_width, viewport->Pos.y) : viewport->Pos;
@@ -476,40 +589,40 @@ void gui_render_plots(void) {
mtx_lock(&g_fetching_mutex);
- while (section_current) {
- ImGui::SeparatorText(section_current);
+ while (section_current.length()) {
+ ImGui::SeparatorText(section_current.c_str());
ImGui::BeginTable("plots-table", g_plot_cols);
- for (size_t i = 0; i < PLOT_COUNT; i++) {
- if (g_plots[i].section != section_current) {
- section_next = (!section_next && !plots_covered[i]) ? g_plots[i].section : section_next;
+ for (size_t i = 0; i < g_plots.size(); i++) {
+ if (g_plots[i]->m_section != section_current) {
+ section_next = (!section_next.length() && !g_plots_covered[i]) ? g_plots[i]->m_section : section_next;
continue;
}
ImGui::TableNextColumn();
- g_plot_cells[col][row] = &g_plots[i];
- g_plot_cells_top[col][row] = ImGui::GetCursorPosY();
+ g_plot_cells[gui_plot_cell_index(col, row)] = g_plots[i];
+ g_plot_cells_top[gui_plot_cell_index(col, row)] = ImGui::GetCursorPosY();
- if (&g_plots[i] == g_plot_selected) {
+ if (g_plots[i] == g_plot_selected) {
g_plot_col_selected = col;
g_plot_row_selected = row;
g_implot_style->Colors[ImPlotCol_FrameBg] = g_imgui_style->Colors[ImGuiCol_FrameBg];
}
- gui_render_plot(&g_plots[i]);
+ gui_render_plot(g_plots[i]);
- if (&g_plots[i] == g_plot_selected) {
+ if (g_plots[i] == g_plot_selected) {
g_implot_style->Colors[ImPlotCol_FrameBg] = COLOR_BLACK;
}
- g_plot_cells_bottom[col][row] = ImGui::GetCursorPosY();
+ g_plot_cells_bottom[gui_plot_cell_index(col, row)] = ImGui::GetCursorPosY();
col = (col + 1) % g_plot_cols;
row += col ? 0 : 1;
- plots_covered[i] = true;
+ g_plots_covered[i] = true;
}
section_current = section_next;
- section_next = nullptr;
+ section_next = std::string();
ImGui::EndTable();
row += col ? 1 : 0;
col = 0;
@@ -533,8 +646,8 @@ void gui_render_plot_maximized(void) {
void gui_plot_queue_scroll(int col_selected, int row_selected) {
const ImGuiViewport *viewport = ImGui::GetMainViewport();
- float plot_top = g_plot_cells_top[col_selected][row_selected];
- float plot_bottom = g_plot_cells_bottom[col_selected][row_selected];
+ float plot_top = g_plot_cells_top[gui_plot_cell_index(col_selected, row_selected)];
+ float plot_bottom = g_plot_cells_bottom[gui_plot_cell_index(col_selected, row_selected)];
float win_top = g_plot_scroll_current;
float win_bottom = win_top + viewport->Size.y;
@@ -555,17 +668,14 @@ void gui_render(void) {
return;
}
- if (g_data_col_visible) {
- gui_render_data_col();
- }
-
+ if (g_data_col_visible) gui_render_data_col();
gui_render_plots();
}
// ----------------------------------------------------------------------------
// Main functions
// ----------------------------------------------------------------------------
-void win_sig_handler(int signo) {
+void app_sig_handler(int signo) {
(void)signo;
log_warn("Signal received, will stop SALIS data client...");
@@ -577,11 +687,11 @@ void win_sig_handler(int signo) {
glfwSetWindowShouldClose(g_window, GLFW_TRUE);
}
-void win_error_callback(int error, const char* description) {
+void app_error_callback(int error, const char* description) {
log_warn("GLFW error %d: %s", error, description);
}
-void win_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
+void app_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
(void)window;
(void)scancode;
@@ -626,20 +736,20 @@ void win_key_callback(GLFWwindow* window, int key, int scancode, int action, int
switch (key) {
case GLFW_KEY_LEFT:
g_plot_col_selected -= g_plot_col_selected ? 1 : 0;
- g_plot_selected = g_plot_cells[g_plot_col_selected][g_plot_row_selected];
+ g_plot_selected = g_plot_cells[gui_plot_cell_index(g_plot_col_selected, g_plot_row_selected)];
break;
case GLFW_KEY_RIGHT:
- g_plot_col_selected += (g_plot_col_selected < PLOT_MAX_COLS - 1 && g_plot_cells[g_plot_col_selected + 1][g_plot_row_selected]) ? 1 : 0;
- g_plot_selected = g_plot_cells[g_plot_col_selected][g_plot_row_selected];
+ g_plot_col_selected += (g_plot_col_selected < PLOT_MAX_COLS - 1 && g_plot_cells[gui_plot_cell_index(g_plot_col_selected + 1, g_plot_row_selected)]) ? 1 : 0;
+ g_plot_selected = g_plot_cells[gui_plot_cell_index(g_plot_col_selected, g_plot_row_selected)];
break;
case GLFW_KEY_UP:
- g_plot_row_selected -= g_plot_row_selected ? 1 : 0;
- g_plot_selected = g_plot_cells[g_plot_col_selected][g_plot_row_selected];
+ g_plot_row_selected -= (g_plot_row_selected && g_plot_cells[gui_plot_cell_index(g_plot_col_selected, g_plot_row_selected - 1)]) ? 1 : 0;
+ g_plot_selected = g_plot_cells[gui_plot_cell_index(g_plot_col_selected, g_plot_row_selected)];
gui_plot_queue_scroll(g_plot_col_selected, g_plot_row_selected);
break;
case GLFW_KEY_DOWN:
- g_plot_row_selected += (g_plot_row_selected < (int)PLOT_COUNT - 1 && g_plot_cells[g_plot_col_selected][g_plot_row_selected + 1]) ? 1 : 0;
- g_plot_selected = g_plot_cells[g_plot_col_selected][g_plot_row_selected];
+ g_plot_row_selected += (g_plot_row_selected < (int)g_plots.size() - 1 && g_plot_cells[gui_plot_cell_index(g_plot_col_selected, g_plot_row_selected + 1)]) ? 1 : 0;
+ g_plot_selected = g_plot_cells[gui_plot_cell_index(g_plot_col_selected, g_plot_row_selected)];
gui_plot_queue_scroll(g_plot_col_selected, g_plot_row_selected);
break;
case GLFW_KEY_F:
@@ -662,24 +772,21 @@ void win_key_callback(GLFWwindow* window, int key, int scancode, int action, int
}
}
-int main(int argc, char **argv) {
- (void)argc;
- (void)argv;
-
- signal(SIGINT, win_sig_handler);
- signal(SIGTERM, win_sig_handler);
+void init() {
+ signal(SIGINT, app_sig_handler);
+ signal(SIGTERM, app_sig_handler);
log_info("Starting SALIS data client");
log_info("Initializing GLFW");
- glfwSetErrorCallback(win_error_callback);
+ glfwSetErrorCallback(app_error_callback);
glfwInitHint(GLFW_WAYLAND_LIBDECOR, GLFW_WAYLAND_DISABLE_LIBDECOR);
if (!glfwInit()) assert(false);
float scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor());
g_window = glfwCreateWindow((int)(800 * scale), (int)(600 * scale), "SALIS data client", nullptr, nullptr);
assert(g_window);
- glfwSetKeyCallback(g_window, win_key_callback);
+ glfwSetKeyCallback(g_window, app_key_callback);
glfwMakeContextCurrent(g_window);
glfwSwapInterval(1); // enable vsync
@@ -689,7 +796,7 @@ int main(int argc, char **argv) {
ImPlot::CreateContext();
g_imgui_io = &ImGui::GetIO();
- g_imgui_io->Fonts->AddFontFromFileTTF(FONT_SOURCE);
+ g_imgui_io->Fonts->AddFontDefaultVector();
g_imgui_io->IniFilename = nullptr;
g_imgui_style = &ImGui::GetStyle();
@@ -705,15 +812,24 @@ int main(int argc, char **argv) {
ImGui_ImplGlfw_InitForOpenGL(g_window, true);
ImGui_ImplOpenGL3_Init(GLSL_VERSION);
- for (auto &i : g_traces) {
- g_trace_map[i] = {};
- g_trace_map[i].reserve(g_entries);
- }
+ for (auto &trace : g_core_traces) g_traces.push_back(&trace);
+ for (auto &trace : g_arch_traces) g_traces.push_back(&trace);
+ for (auto &plot : g_core_plots) g_plots.push_back(&plot);
+ for (auto &plot : g_arch_plots) g_plots.push_back(&plot);
+ for (auto &plot : g_arch_plots_stacked) g_plots.push_back(&plot);
+ for (auto &i : g_traces) g_trace_map[i->m_name] = i;
+
+ g_plot_cells = std::vector<Plot *>(g_plots.size() * PLOT_MAX_COLS);
+ g_plot_cells_top = std::vector<float>(g_plots.size() * PLOT_MAX_COLS);
+ g_plot_cells_bottom = std::vector<float>(g_plots.size() * PLOT_MAX_COLS);
+ g_plot_selected = g_plots[0];
g_hm_pixel_pow = data_max_hm_pixel_pow();
mtx_init(&g_fetching_mutex, mtx_plain);
+}
+void exec() {
while (!glfwWindowShouldClose(g_window)) {
glfwPollEvents();
@@ -733,7 +849,9 @@ int main(int argc, char **argv) {
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(g_window);
}
+}
+void quit() {
mtx_destroy(&g_fetching_mutex);
ImGui_ImplOpenGL3_Shutdown();
@@ -744,6 +862,15 @@ int main(int argc, char **argv) {
log_info("Stopping SALIS data client");
glfwDestroyWindow(g_window);
glfwTerminate();
+}
+
+int main(int argc, char **argv) {
+ (void)argc;
+ (void)argv;
+
+ init();
+ exec();
+ quit();
return 0;
}
diff --git a/core/tui.c b/core/tui.c
deleted file mode 100644
index 4fc2ce4..0000000
--- a/core/tui.c
+++ /dev/null
@@ -1,98 +0,0 @@
-#define PANE_WIDTH 27
-#define PANE_AND_MARGIN_WIDTH (PANE_WIDTH + 2)
-
-enum {
- PAIR_NORMAL = 0,
-};
-
-char *g_line_buff;
-
-void tui_line_buff_free(void) {
- if (g_line_buff) {
- free(g_line_buff);
- }
-
- g_line_buff = NULL;
-}
-
-void tui_line_buff_resize(void) {
- tui_line_buff_free();
-
- g_line_buff = calloc(COLS + 1, sizeof(char));
-}
-
-void tui_line(bool clear, int line, int color, int attr, const char *format, ...) {
- assert(line >= 0);
- assert(format);
-
- if (line >= LINES) {
- return;
- }
-
- if (clear) {
- move(line, 0);
- clrtoeol();
- }
-
- va_list args;
-
- attron(COLOR_PAIR(color) | attr);
- va_start(args, format);
-
- vsnprintf(g_line_buff, COLS, format, args);
- mvprintw(line, 1, "%s", g_line_buff);
-
- va_end(args);
- attroff(COLOR_PAIR(color) | attr);
-}
-
-void tui_clear_line(int l) {
- tui_line(true, l, PAIR_NORMAL, A_NORMAL, "");
-}
-
-void tui_field(int line, int col, int color, int attr, const char *format, ...) {
- assert(line >= 0);
- assert(col >= 0);
- assert(format);
-
- if (line >= LINES || col >= COLS) {
- return;
- }
-
- va_list args;
-
- attron(COLOR_PAIR(color) | attr);
- va_start(args, format);
-
- vsnprintf(g_line_buff, COLS - col, format, args);
- mvprintw(line, col, "%s", g_line_buff);
-
- va_end(args);
- attroff(COLOR_PAIR(color) | attr);
-}
-
-void tui_str_field(int l, const char *label, const char *value) {
- assert(label);
- assert(strlen(label) <= 4);
- assert(value);
- tui_line(false, l, PAIR_NORMAL, A_NORMAL, "%-4s : %18s", label, value);
-}
-
-void tui_ulx_field(int l, const char *label, uint64_t value) {
- assert(label);
- assert(strlen(label) <= 4);
- tui_line(false, l, PAIR_NORMAL, A_NORMAL, "%-4s : %#18lx", label, value);
-}
-
-void tui_uld_field(int l, const char *label, uint64_t value) {
- assert(label);
- assert(strlen(label) <= 4);
- tui_line(false, l, PAIR_NORMAL, A_NORMAL, "%-4s : %#18ld", label, value);
-}
-
-void tui_float_field(int l, const char *label, float value) {
- assert(label);
- assert(strlen(label) <= 4);
- tui_line(false, l, PAIR_NORMAL, A_NORMAL, "%-4s : %18.1f", label, value);
-}
-
diff --git a/ui/curses/ui.c b/ui/curses/ui.c
index ce73c01..950f109 100644
--- a/ui/curses/ui.c
+++ b/ui/curses/ui.c
@@ -1,9 +1,9 @@
#include <curses.h>
#include <locale.h>
-#include "tui.c"
-
#define LOG_LINE_COUNT 1024
+#define PANE_AND_MARGIN_WIDTH (PANE_WIDTH + 2)
+#define PANE_WIDTH 27
#define PROC_FIELD_WIDTH 21
#define PROC_PAGE_LINES 12
@@ -27,6 +27,7 @@ enum {
};
enum {
+ PAIR_NORMAL = 0,
PAIR_HEADER = 1,
PAIR_LIVE_PROC = 2,
PAIR_SELECTED_PROC = 3,
@@ -56,6 +57,7 @@ bool g_exit;
bool g_running;
unsigned g_core;
unsigned g_page;
+char *g_line_buff;
bool g_proc_genes;
uint64_t g_proc_scroll;
uint64_t g_proc_field_scroll;
@@ -310,8 +312,97 @@ void gfx_render(const struct Core *core, uint64_t pos, uint64_t zoom, uint64_t p
}
// ----------------------------------------------------------------------------
-// Core page functions
+// TUI functions
// ----------------------------------------------------------------------------
+void tui_line_buff_free(void) {
+ if (g_line_buff) {
+ free(g_line_buff);
+ }
+
+ g_line_buff = NULL;
+}
+
+void tui_line_buff_resize(void) {
+ tui_line_buff_free();
+
+ g_line_buff = calloc(COLS + 1, sizeof(char));
+}
+
+void tui_line(bool clear, int line, int color, int attr, const char *format, ...) {
+ assert(line >= 0);
+ assert(format);
+
+ if (line >= LINES) {
+ return;
+ }
+
+ if (clear) {
+ move(line, 0);
+ clrtoeol();
+ }
+
+ va_list args;
+
+ attron(COLOR_PAIR(color) | attr);
+ va_start(args, format);
+
+ vsnprintf(g_line_buff, COLS, format, args);
+ mvprintw(line, 1, "%s", g_line_buff);
+
+ va_end(args);
+ attroff(COLOR_PAIR(color) | attr);
+}
+
+void tui_clear_line(int l) {
+ tui_line(true, l, PAIR_NORMAL, A_NORMAL, "");
+}
+
+void tui_field(int line, int col, int color, int attr, const char *format, ...) {
+ assert(line >= 0);
+ assert(col >= 0);
+ assert(format);
+
+ if (line >= LINES || col >= COLS) {
+ return;
+ }
+
+ va_list args;
+
+ attron(COLOR_PAIR(color) | attr);
+ va_start(args, format);
+
+ vsnprintf(g_line_buff, COLS - col, format, args);
+ mvprintw(line, col, "%s", g_line_buff);
+
+ va_end(args);
+ attroff(COLOR_PAIR(color) | attr);
+}
+
+void tui_str_field(int l, const char *label, const char *value) {
+ assert(label);
+ assert(strlen(label) <= 4);
+ assert(value);
+ tui_line(false, l, PAIR_NORMAL, A_NORMAL, "%-4s : %18s", label, value);
+}
+
+void tui_ulx_field(int l, const char *label, uint64_t value) {
+ assert(label);
+ assert(strlen(label) <= 4);
+ tui_line(false, l, PAIR_NORMAL, A_NORMAL, "%-4s : %#18lx", label, value);
+}
+
+void tui_uld_field(int l, const char *label, uint64_t value) {
+ assert(label);
+ assert(strlen(label) <= 4);
+ tui_line(false, l, PAIR_NORMAL, A_NORMAL, "%-4s : %#18ld", label, value);
+}
+
+void tui_float_field(int l, const char *label, float value) {
+ assert(label);
+ assert(strlen(label) <= 4);
+ tui_line(false, l, PAIR_NORMAL, A_NORMAL, "%-4s : %18.1f", label, value);
+}
+
void tui_print_core(int l) {
tui_line(false, ++l, PAIR_HEADER, A_BOLD, "CORE [%d]", g_core);
tui_ulx_field(++l, "cycl", g_cores[g_core].cycl);