From 24811b4c6a6592b08dbb41243db188a8b310312d Mon Sep 17 00:00:00 2001 From: Paul Oliver Date: Wed, 3 Dec 2025 22:14:38 +0100 Subject: Improve SQL handling & aggregate memory events (WIP) --- arch/dummy/arch.j2.c | 6 ++ arch/salis-v1/arch.j2.c | 238 ++++++++++++++++++++++++++++++--------------- arch/salis-v1/arch_vars.py | 24 +++-- 3 files changed, 182 insertions(+), 86 deletions(-) (limited to 'arch') diff --git a/arch/dummy/arch.j2.c b/arch/dummy/arch.j2.c index c331b34..f51494f 100644 --- a/arch/dummy/arch.j2.c +++ b/arch/dummy/arch.j2.c @@ -28,6 +28,12 @@ void arch_core_init(struct Core *core) { } {% endif %} +void arch_core_free(struct Core *core) { + assert(core); + + (void)core; +} + {% if args.command in ["load", "new"] %} void arch_core_save(FILE *f, const struct Core *core) { assert(f); diff --git a/arch/salis-v1/arch.j2.c b/arch/salis-v1/arch.j2.c index 9c3ea45..269ebe2 100644 --- a/arch/salis-v1/arch.j2.c +++ b/arch/salis-v1/arch.j2.c @@ -30,9 +30,26 @@ void arch_core_init(struct Core *core) { panc->ip = addr_clone; panc->sp = addr_clone; } + + // Prepare event data aggregators + // Allocation event vector + core->aevc = 1; + core->aeva = malloc(sizeof(uint64_t)); + assert(core->aeva); } {% endif %} +void arch_core_free(struct Core *core) { + assert(core); + + // Free event data aggregators + assert(core->aeva); + + free(core->aeva); + + core->aeva = NULL; +} + {% if args.command in ["load", "new"] %} void arch_core_save(FILE *f, const struct Core *core) { assert(f); @@ -47,6 +64,10 @@ void arch_core_save(FILE *f, const struct Core *core) { fwrite(&core->wmb0, sizeof(uint64_t), 1, f); fwrite(&core->wmb1, sizeof(uint64_t), 1, f); fwrite(&core->wdea, sizeof(uint64_t), 1, f); + + fwrite(&core->aevp, sizeof(uint64_t), 1, f); + fwrite(&core->aevc, sizeof(uint64_t), 1, f); + fwrite( core->aeva, sizeof(uint64_t), core->aevp, f); } {% endif %} @@ -64,6 +85,11 @@ void arch_core_load(FILE *f, struct Core *core) { fread(&core->wmb0, sizeof(uint64_t), 1, f); fread(&core->wmb1, sizeof(uint64_t), 1, f); fread(&core->wdea, sizeof(uint64_t), 1, f); + + fread(&core->aevp, sizeof(uint64_t), 1, f); + fread(&core->aevc, sizeof(uint64_t), 1, f); + core->aeva = calloc(core->aevc, sizeof(uint64_t)); + fread( core->aeva, sizeof(uint64_t), core->aevp, f); } {% endif %} @@ -388,6 +414,17 @@ void _alloc(struct Core *core, uint64_t pix, bool fwrd) { // Enlarge child block 1 byte mvec_alloc(core, proc->sp); + // Record allocation event + if (core->aevp == core->aevc) { + core->aeva = realloc(core->aeva, sizeof(uint64_t) * core->aevc * 2); + core->aevc *= 2; + + assert(core->aeva); + } + + core->aeva[core->aevp] = proc->sp; + ++core->aevp; + if (!proc->mb1s || !fwrd) { proc->mb1a = proc->sp; } @@ -832,8 +869,10 @@ const char *arch_mnemonic(uint8_t inst) { void arch_push_data_header() { assert(g_sim_data); - // General trends from all cores will be queried together - const char *trend_sql = ( + // Creates general trend table for all cores + g_info("Generating 'trend' table in SQLite database"); + salis_exec_sql( + 0, NULL, NULL, "create table trend (" "step int not null, " {% for i in range(args.cores) %} @@ -855,30 +894,48 @@ void arch_push_data_header() { ");" ); - g_info("Generating 'trend' table in SQLite database"); - salis_exec_sql(trend_sql); - - // Core-specific instruction data will be queried separately - // A table is created for each core - {% for t in ["pop", "exe", "wrt"] %} - {% for i in range(args.cores) %} - const char *{{ t }}_sql_{{ i }} = ( - "create table {{ t }}_{{ i }} (" - "step int not null, " - // Cycle data allows normalizing against each core's cycle speed - {% for j in range(args.cores) %} - "cycl_{{ j }} int not null, " - {% endfor %} - {% for j in arch_vars.inst_set %} - "inst_{{ j[0]|join(' ') }} int not null{% if not loop.last %},{% endif %} " - {% endfor %} - ");" - ); + // Creates core-specific instruction data tables + const char *iprefs[] = { "pop", "exe", "wrt" }; + int iprefs_cnt = sizeof(iprefs) / sizeof(iprefs[0]); - g_info("Generating '{{ t }}_{{ i }}' table in SQLite database"); - salis_exec_sql({{ t }}_sql_{{ i }}); - {% endfor %} - {% endfor %} + for (int i = 0; i < {{ args.cores }}; ++i) { + for (int j = 0; j < iprefs_cnt; ++j) { + g_info("Generating '%s_%d' table in SQLite database", iprefs[j], i); + salis_exec_sql( + 0, NULL, NULL, + "create table %s_%d (" + "step int not null, " + // Cycle data for all cores allows + // normalizing against each core's cycle speed + {% for i in range(args.cores) %} + "cycl_{{ i }} int not null, " + {% endfor %} + {% for i in arch_vars.inst_set %} + "{{ i[0][0] }} int not null{% if not loop.last %},{% endif %} " + {% endfor %} + ");", + iprefs[j], i + ); + } + } + + // Creates core-specific memory event tables + const char *eprefs[] = { "aev" }; + int eprefs_cnt = sizeof(eprefs) / sizeof(eprefs[0]); + + for (int i = 0; i < {{ args.cores }}; ++i) { + for (int j = 0; j < eprefs_cnt; ++j) { + g_info("Generating '%s_%d' table in SQLite database", eprefs[j], i); + salis_exec_sql( + 0, NULL, NULL, + "create table %s_%d (" + "step int not null, " + "evts blob not null" + ");", + eprefs[j], i + ); + } + } } void arch_push_data_line() { @@ -920,11 +977,10 @@ void arch_push_data_line() { {% endif %} } - // Insert new row - char *trend_sql = NULL; - - asprintf( - &trend_sql, + // Insert row into trend table + g_info("Pushing row to 'trend' table in SQLite database"); + salis_exec_sql( + 0, NULL, NULL, "insert into trend (" "step, " {% for i in range(args.cores) %} @@ -950,7 +1006,7 @@ void arch_push_data_line() { {% endfor %} ");", g_steps, - {% for i in range(args.cores) %} + {% for i in range(args.cores) +%} g_cores[{{ i }}].cycl, g_cores[{{ i }}].mall, g_cores[{{ i }}].pnum, @@ -965,59 +1021,83 @@ void arch_push_data_line() { g_cores[{{ i }}].wmb0, g_cores[{{ i }}].wmb1, g_cores[{{ i }}].wdea{% if not loop.last %},{% endif %} - {% endfor %} + {% endfor +%} ); - g_info("Pushing row to 'trend' table in SQLite database"); - salis_exec_sql(trend_sql); - free(trend_sql); + // Insert row into instruction data tables + const char *iprefs[] = { "pop", "exe", "wrt" }; + int iprefs_cnt = sizeof(iprefs) / sizeof(iprefs[0]); - {% for t in ["pop", "exe", "wrt"] %} - {% for i in range(args.cores) %} + for (int i = 0; i < {{ args.cores }}; ++i) { + for (int j = 0; j < iprefs_cnt; ++j) { + uint64_t *table; + + if (!strcmp("pop", iprefs[j])) { + // Population is generated above, prior to push + table = ipop[i]; + } else if (!strcmp("exe", iprefs[j])) { + table = g_cores[i].iexe; + } else if (!strcmp("wrt", iprefs[j])) { + table = g_cores[i].iwrt; + } - {% if t == "pop" %} - // Reference instruction population vector that was - // manually generated above - {% set table = "ipop[%d]"|format(i) %} - {% else %} - {% set table = "g_cores[%d].i%s"|format(i, t) %} - {% endif %} + g_info("Pushing row to '%s_%d' table in SQLite database", iprefs[j], i); + salis_exec_sql( + 0, NULL, NULL, + "insert into %s_%d (" + "step, " + {% for i in range(args.cores) %} + "cycl_{{ i }}, " + {% endfor %} + {% for i in arch_vars.inst_set %} + "{{ i[0][0] }}{% if not loop.last %},{% endif %} " + {% endfor %} + ") values (" + "%ld, " + {% for _ in range(args.cores) %} + "%ld, " + {% endfor %} + {% for _ in range(arch_vars.inst_count) %} + "%ld{% if not loop.last %},{% endif %} " + {% endfor %} + ");", + iprefs[j], + i, + g_steps, + {% for j in range(args.cores) %} + g_cores[{{ j }}].cycl, + {% endfor %} + {% for j in range(arch_vars.inst_count) %} + table[{{ j }}]{% if not loop.last %},{% endif +%} + {% endfor %} + ); + } + } - char *{{ t }}_sql_{{ i }} = NULL; + // Insert row into memory event tables + const char *eprefs[] = { "aev" }; + int eprefs_cnt = sizeof(eprefs) / sizeof(eprefs[0]); - asprintf( - &{{ t }}_sql_{{ i }}, - "insert into {{ t }}_{{ i }} (" - "step, " - {% for j in range(args.cores) %} - "cycl_{{ j }}, " - {% endfor %} - {% for j in arch_vars.inst_set %} - "inst_{{ j[0]|join(' ') }}{% if not loop.last %},{% endif %} " - {% endfor %} - ") values (" - "%ld, " - {% for _ in range(args.cores) %} - "%ld, " - {% endfor %} - {% for _ in range(arch_vars.inst_count) %} - "%ld{% if not loop.last %},{% endif %} " - {% endfor %} - ");", - g_steps, - {% for j in range(args.cores) %} - g_cores[{{ j }}].cycl, - {% endfor %} - {% for j in range(arch_vars.inst_count) %} - {{ table }}[{{ j }}]{% if not loop.last %},{% endif %} - {% endfor %} - ); + for (int i = 0; i < {{ args.cores }}; ++i) { + for (int j = 0; j < eprefs_cnt; ++j) { + uint64_t ptr; + uint64_t *table; - g_info("Pushing row to '{{ t }}_{{ i }}' table in SQLite database"); - salis_exec_sql({{ t }}_sql_{{ i }}); - free({{ t }}_sql_{{ i }}); - {% endfor %} - {% endfor %} + if (!strcmp("aev", eprefs[j])) { + ptr = g_cores[i].aevp; + table = g_cores[i].aeva; + } + + int blob_size = ptr * sizeof(uint64_t); + + g_info("Pushing row to '%s_%d' table in SQLite database", eprefs[j], i); + salis_exec_sql( + 1, (const void **)&table, &blob_size, + "insert into %s_%d (step, evts) values (%ld, ?);", + eprefs[j], i, g_steps + ); + } + } // Reset all data aggregation core fields to zero for (int i = 0; i < {{ args.cores }}; ++i) { @@ -1033,6 +1113,10 @@ void arch_push_data_line() { core->wmb0 = 0; core->wmb1 = 0; core->wdea = 0; + + // Event vectors + memset(core->aeva, 0, sizeof(uint64_t) * core->aevp); + core->aevp = 0; } } {% endif %} diff --git a/arch/salis-v1/arch_vars.py b/arch/salis-v1/arch_vars.py index f469ad6..8bf40a7 100644 --- a/arch/salis-v1/arch_vars.py +++ b/arch/salis-v1/arch_vars.py @@ -107,13 +107,19 @@ inst_count = len(inst_set) # Extra fields used exclusively for data aggregation core_fields = [ - ("uint64_t", f"iexe[{inst_count}]"), - ("uint64_t", f"iwrt[{inst_count}]"), - ("uint64_t", "emb0"), - ("uint64_t", "emb1"), - ("uint64_t", "eliv"), - ("uint64_t", "edea"), - ("uint64_t", "wmb0"), - ("uint64_t", "wmb1"), - ("uint64_t", "wdea"), + ("uint64_t", f"iexe[{inst_count}]", False), + ("uint64_t", f"iwrt[{inst_count}]", False), + ("uint64_t", "emb0", True), + ("uint64_t", "emb1", True), + ("uint64_t", "eliv", True), + ("uint64_t", "edea", True), + ("uint64_t", "wmb0", True), + ("uint64_t", "wmb1", True), + ("uint64_t", "wdea", True), + + # Event data aggregators + # Allocation event vector + ("uint64_t", "aevp", True), + ("uint64_t", "aevc", True), + ("uint64_t *", "aeva", False), ] -- cgit v1.2.1