diff --git a/.gitignore b/.gitignore index 585adbbca..994af9557 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,8 @@ GPATH GRTAGS GSYMS GTAGS + +# gnuplot files +gnuplot_script.gnu +data.txt +*.png diff --git a/Makefile b/Makefile index dc613fd07..dbcb0658e 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ $(GIT_HOOKS): @echo OBJS := qtest.o report.o console.o harness.o queue.o \ - random.o dudect/constant.o dudect/fixture.o dudect/ttest.o \ + random.o dudect/constant.o dudect/fixture.o dudect/ttest.o dudect/plot.o \ shannon_entropy.o \ linenoise.o web.o diff --git a/dudect/fixture.c b/dudect/fixture.c index 8733cef14..02515bafd 100644 --- a/dudect/fixture.c +++ b/dudect/fixture.c @@ -38,11 +38,9 @@ #include "constant.h" #include "fixture.h" +#include "plot.h" #include "ttest.h" -#define ENOUGH_MEASURE 10000 -#define TEST_TRIES 10 - static t_context_t *t; /* threshold values for Welch's t-test */ @@ -83,6 +81,8 @@ static bool report(void) double number_traces_max_t = t->n[0] + t->n[1]; double max_tau = max_t / sqrt(number_traces_max_t); + add_data(max_t); + printf("\033[A\033[2K"); printf("meas: %7.2lf M, ", (number_traces_max_t / 1e6)); if (number_traces_max_t < ENOUGH_MEASURE) { @@ -156,6 +156,7 @@ static bool test_const(char *text, int mode) bool result = false; t = malloc(sizeof(t_context_t)); + init_data_buffer(); for (int cnt = 0; cnt < TEST_TRIES; ++cnt) { printf("Testing %s...(%d/%d)\n\n", text, cnt, TEST_TRIES); init_once(); @@ -163,9 +164,11 @@ static bool test_const(char *text, int mode) ++i) result = doit(mode); printf("\033[A\033[2K\033[A\033[2K"); + next_try(); if (result) break; } + plot_graph(t_threshold_moderate, text); free(t); return result; } diff --git a/dudect/fixture.h b/dudect/fixture.h index cc7d6f39f..7418bee57 100644 --- a/dudect/fixture.h +++ b/dudect/fixture.h @@ -4,6 +4,9 @@ #include #include "constant.h" +#define ENOUGH_MEASURE 10000 +#define TEST_TRIES 10 + /* Interface to test if function is constant */ #define _(x) bool is_##x##_const(void); DUT_FUNCS diff --git a/dudect/plot.c b/dudect/plot.c new file mode 100644 index 000000000..71cece7c5 --- /dev/null +++ b/dudect/plot.c @@ -0,0 +1,131 @@ +#include +#include +#include +#include +#include "fixture.h" + +#define GNUPLOT_SCRIPT "gnuplot_script.gnu" +#define DATA_FILE "data.txt" + +int n_tries = 0; + +struct { + double y[ENOUGH_MEASURE]; + int n_measures; +} data_buffer[TEST_TRIES]; + +static double max_data_value() +{ + double mx = 0; + for (int i = 0; i < TEST_TRIES; i++) { + double value = data_buffer[i].y[data_buffer[i].n_measures - 1]; + if (value > mx) + mx = value; + } + return mx; +} + +void init_data_buffer() +{ + n_tries = 0; + for (int i = 0; i < TEST_TRIES; i++) { + data_buffer[i].n_measures = 0; + } +} + +void next_try() +{ + n_tries++; +} + +void add_data(double y) +{ + if (n_tries >= TEST_TRIES) { + fprintf(stderr, "Buffer overflow\n"); + exit(1); + } + data_buffer[n_tries].y[data_buffer[n_tries].n_measures++] = y; +} + +void save_data() +{ + FILE *fp = fopen(DATA_FILE, "w"); + if (!fp) { + perror("Error opening file"); + exit(1); + } + fprintf(fp, "# X "); + for (int i = 0; i < TEST_TRIES; i++) { + fprintf(fp, "t%d ", i); + } + fprintf(fp, "\n"); + for (int i = 0; i < data_buffer[0].n_measures; i++) { + fprintf(fp, "%d ", (int) i); + for (int j = 0; j < TEST_TRIES; j++) { + fprintf(fp, "%lf ", data_buffer[j].y[i]); + } + fprintf(fp, "\n"); + } + fclose(fp); +} + +void generate_gnuplot_script(double threshold, + const char *title, + const char *output_file) +{ + FILE *gp = fopen(GNUPLOT_SCRIPT, "w"); + if (!gp) { + perror("Error opening Gnuplot script file"); + exit(1); + } + + int mx_val = (int) max_data_value(); + int y_range = mx_val < 25 ? 50 : mx_val * 2; + + + fprintf(gp, + "set terminal pngcairo enhanced size 800,400\n" + "set output '%s'\n" + "set title '%s'\n" + "set xlabel '# measurements'\n" + "set ylabel '|t| statistic'\n" + "set grid front\n" + "set xrange [0:%d]\n" + "set yrange [0:%d]\n" + + // #Define the threshold as a function + "f(x) = %lf\n" + + // #Fill the lower part(green) and upper part(red) + "set style fill solid 0.3\n" + "plot '%s' using 1:(f($1)) with filledcurves y1=0 lc rgb 'green' " + "notitle, \\\n" + " '%s' using 1:(f($1)) with filledcurves y1=%d lc rgb 'red' " + "notitle, \\\n" + " for [i=2:%d] '%s' using 1:i:(i) with lines lw 2 lc variable " + "title sprintf('Test %%d', i-1)\n", + output_file, title, data_buffer[0].n_measures, y_range, threshold, + DATA_FILE, DATA_FILE, y_range, n_tries + 1, DATA_FILE); + + fclose(gp); +} + +void plot_graph(double threshold, const char *title) +{ + save_data(); + char *output_file = malloc(strlen(title) + 5); + if (!output_file) { + perror("Error allocating memory"); + exit(1); + } + strncpy(output_file, title, strlen(title) + 1); + strcat(output_file, ".png"); + generate_gnuplot_script(threshold, title, output_file); + int ret = system("gnuplot " GNUPLOT_SCRIPT); + if (ret != 0) { + fprintf(stderr, "Error generating graph\n"); + exit(1); + } + printf("Graph generated: %s\n", output_file); + free(output_file); +} \ No newline at end of file diff --git a/dudect/plot.h b/dudect/plot.h new file mode 100644 index 000000000..b3a2b1661 --- /dev/null +++ b/dudect/plot.h @@ -0,0 +1,8 @@ +#ifndef DUDECT_PLOT_H +#define DUDECT_PLOT_H + +void init_data_buffer(); +void next_try(); +void add_data(double y); +void plot_graph(double threshold, char *title); +#endif