diff options
Diffstat (limited to 'arch/salis-v1/arch.j2.c')
| -rw-r--r-- | arch/salis-v1/arch.j2.c | 1134 |
1 files changed, 0 insertions, 1134 deletions
diff --git a/arch/salis-v1/arch.j2.c b/arch/salis-v1/arch.j2.c deleted file mode 100644 index 06a701d..0000000 --- a/arch/salis-v1/arch.j2.c +++ /dev/null @@ -1,1134 +0,0 @@ -// Author: Paul Oliver <contact@pauloliver.dev> -// Project: Salis - -// Based on the original salis-v1 VM architecture: -// https://git.pauloliver.dev/salis-v1/about/ - -enum { - {% for i in arch_vars.inst_set %} - {{ i[0]|join(' ') }}, - {% endfor %} -}; - -{% if args.command in ["bench", "new"] and anc_bytes is defined %} -void arch_core_init(struct Core *core) { - assert(core); - - {% if arch_vars.mvec_loop %} - uint64_t addr = {{ uint64_half }}; - {% else %} - uint64_t addr = 0; - {% endif %} - - for (uint64_t i = 0; i < {{ args.clones }}; ++i) { - uint64_t addr_clone = addr + (({{ mvec_size }} / {{ args.clones }})) * i; - - struct Proc *panc = proc_fetch(core, i); - - panc->mb0a = addr_clone; - panc->mb0s = {{ anc_bytes|length }}; - panc->ip = addr_clone; - panc->sp = addr_clone; - } -} -{% 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); - assert(core); - - fwrite( core->iexe, sizeof(uint64_t), {{ arch_vars.inst_count }}, f); - fwrite( core->iwrt, sizeof(uint64_t), {{ arch_vars.inst_count }}, f); - fwrite(&core->emb0, sizeof(uint64_t), 1, f); - fwrite(&core->emb1, sizeof(uint64_t), 1, f); - fwrite(&core->eliv, sizeof(uint64_t), 1, f); - fwrite(&core->edea, sizeof(uint64_t), 1, f); - 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->aeva, sizeof(uint64_t), {{ mvec_size }}, f); -} -{% endif %} - -{% if args.command in ["load"] %} -void arch_core_load(FILE *f, struct Core *core) { - assert(f); - assert(core); - - fread( core->iexe, sizeof(uint64_t), {{ arch_vars.inst_count }}, f); - fread( core->iwrt, sizeof(uint64_t), {{ arch_vars.inst_count }}, f); - fread(&core->emb0, sizeof(uint64_t), 1, f); - fread(&core->emb1, sizeof(uint64_t), 1, f); - fread(&core->eliv, sizeof(uint64_t), 1, f); - fread(&core->edea, sizeof(uint64_t), 1, f); - 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->aeva, sizeof(uint64_t), {{ mvec_size }}, f); -} -{% endif %} - -uint64_t arch_proc_mb0_addr(const struct Core *core, uint64_t pix) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - return proc_get(core, pix)->mb0a; -} - -uint64_t arch_proc_mb0_size(const struct Core *core, uint64_t pix) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - return proc_get(core, pix)->mb0s; -} - -uint64_t arch_proc_mb1_addr(const struct Core *core, uint64_t pix) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - return proc_get(core, pix)->mb1a; -} - -uint64_t arch_proc_mb1_size(const struct Core *core, uint64_t pix) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - return proc_get(core, pix)->mb1s; -} - -uint64_t arch_proc_ip_addr(const struct Core *core, uint64_t pix) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - return proc_get(core, pix)->ip; -} - -uint64_t arch_proc_sp_addr(const struct Core *core, uint64_t pix) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - return proc_get(core, pix)->sp; -} - -uint64_t arch_proc_slice(const struct Core *core, uint64_t pix) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - - (void)core; - (void)pix; - - return 1; -} - -void _free_memory_block(struct Core *core, uint64_t addr, uint64_t size) { - assert(core); - assert(size); - - for (uint64_t i = 0; i < size; ++i) { - mvec_free(core, addr + i); - - // Record deallocation event - ++core->aeva[addr]; - } -} - -void arch_on_proc_kill(struct Core *core) { - assert(core); - assert(core->pnum > 1); - - struct Proc *pfst = proc_fetch(core, core->pfst); - - _free_memory_block(core, pfst->mb0a, pfst->mb0s); - - if (pfst->mb1s) { - _free_memory_block(core, pfst->mb1a, pfst->mb1s); - } - - memcpy(pfst, &g_dead_proc, sizeof(struct Proc)); -} - -uint8_t _get_inst(const struct Core *core, uint64_t addr) { - assert(core); - - return mvec_get_inst(core, addr) % {{ arch_vars.inst_count }}; -} - -void _increment_ip(struct Core *core, uint64_t pix) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - - struct Proc *proc = proc_fetch(core, pix); - - proc->ip++; - proc->sp = proc->ip; -} - -bool _is_between(uint8_t inst, uint8_t lo, uint8_t hi) { - assert(inst < {{ arch_vars.inst_count }}); - assert(lo < {{ arch_vars.inst_count }}); - assert(hi < {{ arch_vars.inst_count }}); - assert(lo < hi); - - return (inst >= lo) && (inst <= hi); -} - -bool _is_key(uint8_t inst) { - assert(inst < {{ arch_vars.inst_count }}); - - return _is_between(inst, keya, keyp); -} - -bool _is_lock(uint8_t inst) { - assert(inst < {{ arch_vars.inst_count }}); - - return _is_between(inst, loka, lokp); -} - -bool _is_rmod(uint8_t inst) { - assert(inst < {{ arch_vars.inst_count }}); - - return _is_between(inst, nop0, nop3); -} - -bool _key_lock_match(uint8_t key, uint8_t lock) { - assert(key < {{ arch_vars.inst_count }}); - assert(lock < {{ arch_vars.inst_count }}); - assert(_is_key(key)); - - return (key - keya) == (lock - loka); -} - -bool _seek(struct Core *core, uint64_t pix, bool fwrd) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - - struct Proc *proc = proc_fetch(core, pix); - uint8_t next = _get_inst(core, proc->ip + 1); - - if (!_is_key(next)) { - _increment_ip(core, pix); - return false; - } - - uint8_t spin = _get_inst(core, proc->sp); - - if (_key_lock_match(next, spin)) { - return true; - } - - if (fwrd) { - proc->sp++; - } else { - proc->sp--; - } - - return false; -} - -void _jump(struct Core *core, uint64_t pix) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - - struct Proc *proc = proc_fetch(core, pix); - - {% if not args.optimized %} - uint8_t next = _get_inst(core, proc->ip + 1); - uint8_t spin = _get_inst(core, proc->sp); - assert(_is_key(next)); - assert(_is_lock(spin)); - assert(_key_lock_match(next, spin)); - {% endif %} - - proc->ip = proc->sp; -} - -void _get_reg_addr_list(struct Core *core, uint64_t pix, uint64_t **rlist, int rcount, bool offset) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - - assert(rlist); - assert(rcount); - assert(rcount < 4); - - struct Proc *proc = proc_fetch(core, pix); - uint64_t madr = proc->ip + (offset ? 2 : 1); - - for (int i = 0; i < rcount; ++i) { - rlist[i] = &proc->r0x; - } - - for (int i = 0; i < rcount; ++i) { - uint64_t mnxt = madr + i; - uint8_t mins = _get_inst(core, mnxt); - - if (!_is_rmod(mins)) { - break; - } - - switch (mins) { - case nop0: - rlist[i] = &proc->r0x; - break; - case nop1: - rlist[i] = &proc->r1x; - break; - case nop2: - rlist[i] = &proc->r2x; - break; - case nop3: - rlist[i] = &proc->r3x; - break; - } - } -} - -void _addr(struct Core *core, uint64_t pix) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - - struct Proc *proc = proc_fetch(core, pix); - uint64_t *reg; - - {% if not args.optimized %} - uint8_t next = _get_inst(core, proc->ip + 1); - uint8_t spin = _get_inst(core, proc->sp); - assert(_is_key(next)); - assert(_is_lock(spin)); - assert(_key_lock_match(next, spin)); - {% endif %} - - _get_reg_addr_list(core, pix, ®, 1, true); - *reg = proc->sp; - - _increment_ip(core, pix); -} - -void _ifnz(struct Core *core, uint64_t pix) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - - struct Proc *proc = proc_fetch(core, pix); - uint64_t *reg; - - _get_reg_addr_list(core, pix, ®, 1, false); - - uint64_t jmod = _is_rmod(_get_inst(core, proc->ip + 1)) ? 1 : 0; - uint64_t rmod = *reg ? 1 : 2; - - proc->ip += jmod + rmod; - proc->sp = proc->ip; -} - -void _free_child_memory_of(struct Core *core, uint64_t pix) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - - struct Proc *proc = proc_fetch(core, pix); - - assert(proc->mb1s); - - _free_memory_block(core, proc->mb1a, proc->mb1s); - - proc->mb1a = 0; - proc->mb1s = 0; -} - -// Organisms allocate new memory blocks by means of their seek pointer (sp), -// which sweeps memory 1 byte per simulation step, extending the block as it goes. -// In case allocated memory is found mid-way, current allocation is discarded. -void _alloc(struct Core *core, uint64_t pix, bool fwrd) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - - struct Proc *proc = proc_fetch(core, pix); - uint64_t *regs[2]; - - _get_reg_addr_list(core, pix, regs, 2, false); - - uint64_t bsize = *regs[0]; - - // Do nothing if block-size is zero - if (!bsize) { - _increment_ip(core, pix); - return; - } - - // Do nothing if seek pointer is not adjacent to allocated memory block - // This is an error condition - if (proc->mb1s) { - uint64_t exp_addr = proc->mb1a; - - if (fwrd) { - exp_addr += proc->mb1s; - } else { - exp_addr--; - } - - if (proc->sp != exp_addr) { - _increment_ip(core, pix); - return; - } - } - - // Allocation was successful - // Store block address on register - if (proc->mb1s == bsize) { - _increment_ip(core, pix); - *regs[1] = proc->mb1a; - return; - } - - // Seek pointer collided with another allocated block - // Discard and keep trying - if (mvec_is_alloc(core, proc->sp)) { - if (proc->mb1s) { - _free_child_memory_of(core, pix); - } - - if (fwrd) { - proc->sp++; - } else { - proc->sp--; - } - - return; - } - - // Free (non-allocated) byte found - // Enlarge child block 1 byte - mvec_alloc(core, proc->sp); - - // Record allocation event - ++core->aeva[proc->sp]; - - if (!proc->mb1s || !fwrd) { - proc->mb1a = proc->sp; - } - - proc->mb1s++; - - // Move seek pointer - if (fwrd) { - proc->sp++; - } else { - proc->sp--; - } -} - -void _bswap(struct Core *core, uint64_t pix) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - - struct Proc *proc = proc_fetch(core, pix); - - if (proc->mb1s) { - uint64_t tmpa = proc->mb0a; - uint64_t tmps = proc->mb0s; - - proc->mb0a = proc->mb1a; - proc->mb0s = proc->mb1s; - proc->mb1a = tmpa; - proc->mb1s = tmps; - } - - _increment_ip(core, pix); -} - -void _bclear(struct Core *core, uint64_t pix) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - - struct Proc *proc = proc_fetch(core, pix); - - if (proc->mb1s) { - _free_child_memory_of(core, pix); - } - - _increment_ip(core, pix); -} - -void _split(struct Core *core, uint64_t pix) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - - struct Proc *proc = proc_fetch(core, pix); - - if (proc->mb1s) { - struct Proc child = {0}; - - child.ip = proc->mb1a; - child.sp = proc->mb1a; - child.mb0a = proc->mb1a; - child.mb0s = proc->mb1s; - - proc->mb1a = 0; - proc->mb1s = 0; - - // A new organism is born :) - proc_new(core, &child); - } else { - assert(!proc->mb1a); - } - - _increment_ip(core, pix); -} - -void _3rop(struct Core *core, uint64_t pix, uint8_t inst) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - - uint64_t *regs[3]; - - _get_reg_addr_list(core, pix, regs, 3, false); - - // Organisms can do arithmetic using any sequence of 3 registers - switch (inst) { - case addn: - *regs[0] = *regs[1] + *regs[2]; - break; - case subn: - *regs[0] = *regs[1] - *regs[2]; - break; - case muln: - *regs[0] = *regs[1] * *regs[2]; - break; - case divn: - // Division by zero - // Do nothing - if (*regs[2]) { - *regs[0] = *regs[1] / *regs[2]; - } - - break; - default: - assert(false); - } - - _increment_ip(core, pix); -} - -void _1rop(struct Core *core, uint64_t pix, uint8_t inst) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - - uint64_t *reg; - - _get_reg_addr_list(core, pix, ®, 1, false); - - switch (inst) { - case incn: - (*reg)++; - break; - case decn: - (*reg)--; - break; - case notn: - *reg = !(*reg); - break; - case shfl: - *reg <<= 1; - break; - case shfr: - *reg >>= 1; - break; - case zero: - *reg = 0; - break; - case unit: - *reg = 1; - break; - default: - assert(false); - } - - _increment_ip(core, pix); -} - -void _push(struct Core *core, uint64_t pix) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - - struct Proc *proc = proc_fetch(core, pix); - uint64_t *reg; - - _get_reg_addr_list(core, pix, ®, 1, false); - - proc->s7 = proc->s6; - proc->s6 = proc->s5; - proc->s5 = proc->s4; - proc->s4 = proc->s3; - proc->s3 = proc->s2; - proc->s2 = proc->s1; - proc->s1 = proc->s0; - proc->s0 = *reg; - - _increment_ip(core, pix); -} - -void _pop(struct Core *core, uint64_t pix) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - - struct Proc *proc = proc_fetch(core, pix); - uint64_t *reg; - - _get_reg_addr_list(core, pix, ®, 1, false); - - *reg = proc->s0; - proc->s0 = proc->s1; - proc->s1 = proc->s2; - proc->s2 = proc->s3; - proc->s3 = proc->s4; - proc->s4 = proc->s5; - proc->s5 = proc->s6; - proc->s6 = proc->s7; - proc->s7 = 0; - - _increment_ip(core, pix); -} - -int _sp_dir(uint64_t src, uint64_t dst) { - if (src == dst) { - return 0; - } else if (src - dst <= dst - src) { - return -1; - } else { - return 1; - } -} - -void _load(struct Core *core, uint64_t pix) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - - struct Proc *proc = proc_fetch(core, pix); - uint64_t *regs[2]; - - _get_reg_addr_list(core, pix, regs, 2, false); - - int sp_dir = _sp_dir(proc->sp, *regs[0]); - - if (sp_dir == 1) { - proc->sp++; - } else if (sp_dir == -1) { - proc->sp--; - } else { - *regs[1] = mvec_get_inst(core, *regs[0]); - _increment_ip(core, pix); - } -} - -bool _is_writeable_by(const struct Core *core, uint64_t addr, uint64_t pix) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - - return !mvec_is_alloc(core, addr) || mvec_is_proc_owner(core, addr, pix); -} - -void _write(struct Core *core, uint64_t pix) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - - struct Proc *proc = proc_fetch(core, pix); - uint64_t *regs[2]; - - _get_reg_addr_list(core, pix, regs, 2, false); - - int sp_dir = _sp_dir(proc->sp, *regs[0]); - - if (sp_dir == 1) { - proc->sp++; - } else if (sp_dir == -1) { - proc->sp--; - } else { - if (_is_writeable_by(core, *regs[0], pix)) { - // Store write event - uint8_t inst = *regs[1] % {{ arch_vars.inst_count }}; - - ++core->iwrt[inst]; - - if (mvec_is_in_mb0_of_proc(core, *regs[0], pix)) { - ++core->wmb0; - } else if (mvec_is_in_mb1_of_proc(core, *regs[0], pix)) { - ++core->wmb1; - } else { - ++core->wdea; - } - - // Write instruction - mvec_set_inst(core, *regs[0], *regs[1] % {{ inst_cap }}); - } - - _increment_ip(core, pix); - } -} - -void _2rop(struct Core *core, uint64_t pix, uint8_t inst) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - - uint64_t *regs[2]; - - _get_reg_addr_list(core, pix, regs, 2, false); - - switch (inst) { - case dupl: - *regs[1] = *regs[0]; - break; - case swap: - { - uint64_t tmp = *regs[0]; - *regs[0] = *regs[1]; - *regs[1] = tmp; - } - - break; - default: - assert(false); - } - - _increment_ip(core, pix); -} - -void arch_proc_step(struct Core *core, uint64_t pix) { - assert(core); - assert(mvec_proc_is_live(core, pix)); - - struct Proc *proc = proc_fetch(core, pix); - uint8_t inst = _get_inst(core, proc->ip); - - // Store execute event - ++core->iexe[inst]; - - if (mvec_is_in_mb0_of_proc(core, proc->ip, pix)) { - ++core->emb0; - } else if (mvec_is_in_mb1_of_proc(core, proc->ip, pix)) { - ++core->emb1; - } else if (mvec_is_alloc(core, proc->ip)) { - ++core->eliv; - } else { - ++core->edea; - } - - // Execute instruction - switch (inst) { - case jmpb: - if (_seek(core, pix, false)) { - _jump(core, pix); - } - - break; - case jmpf: - if (_seek(core, pix, true)) { - _jump(core, pix); - } - - break; - case adrb: - if (_seek(core, pix, false)) { - _addr(core, pix); - } - - break; - case adrf: - if (_seek(core, pix, true)) { - _addr(core, pix); - } - - break; - case ifnz: - _ifnz(core, pix); - break; - case allb: - _alloc(core, pix, false); - break; - case allf: - _alloc(core, pix, true); - break; - case bswp: - _bswap(core, pix); - break; - case bclr: - _bclear(core, pix); - break; - case splt: - _split(core, pix); - break; - case addn: - case subn: - case muln: - case divn: - _3rop(core, pix, inst); - break; - case incn: - case decn: - case notn: - case shfl: - case shfr: - case zero: - case unit: - _1rop(core, pix, inst); - break; - case pshn: - _push(core, pix); - break; - case popn: - _pop(core, pix); - break; - case load: - _load(core, pix); - break; - case wrte: - _write(core, pix); - break; - case dupl: - case swap: - _2rop(core, pix, inst); - break; - default: - _increment_ip(core, pix); - break; - } - - return; -} - -{% if not args.optimized %} -void arch_validate_proc(const struct Core *core, uint64_t pix) { - assert(core); - - const struct Proc *proc = proc_get(core, pix); - - assert(proc->mb0s); - - if (proc->mb1a) { - assert(proc->mb1s); - } - - for (uint64_t i = 0; i < proc->mb0s; ++i) { - uint64_t addr = proc->mb0a + i; - assert(mvec_is_alloc(core, addr)); - assert(mvec_is_proc_owner(core, addr, pix)); - } - - for (uint64_t i = 0; i < proc->mb1s; ++i) { - uint64_t addr = proc->mb1a + i; - assert(mvec_is_alloc(core, addr)); - assert(mvec_is_proc_owner(core, addr, pix)); - } -} -{% endif %} - -wchar_t arch_symbol(uint8_t inst) { - switch (inst % {{ arch_vars.inst_count }}) { - {% for i in arch_vars.inst_set %} - case {{ i[0]|join(' ') }}: return L'{{ i[1] }}'; - {% endfor %} - } - - assert(false); - return L'\0'; -} - -const char *arch_mnemonic(uint8_t inst) { - switch (inst % {{ arch_vars.inst_count }}) { - {% for i in arch_vars.inst_set %} - case {{ i[0]|join(' ') }}: return "{{ i[0]|join(' ') }}"; - {% endfor %} - } - - assert(false); - return NULL; -} - -// ---------------------------------------------------------------------------- -// Data aggregation functions -// ---------------------------------------------------------------------------- -{% if data_push_path is defined %} -void arch_push_data_header() { - assert(g_sim_data); - - // Creates general trend table for all cores - g_info("Creating 'trend' table in SQLite database"); - salis_exec_sql( - 0, NULL, NULL, - "create table trend (" - "step int not null, " - {% for i in range(args.cores) %} - "cycl_{{ i }} int not null, " - "mall_{{ i }} int not null, " - "pnum_{{ i }} int not null, " - "pfst_{{ i }} int not null, " - "plst_{{ i }} int not null, " - "amb0_{{ i }} real not null, " - "amb1_{{ i }} real not null, " - "emb0_{{ i }} int not null, " - "emb1_{{ i }} int not null, " - "eliv_{{ i }} int not null, " - "edea_{{ i }} int not null, " - "wmb0_{{ i }} int not null, " - "wmb1_{{ i }} int not null, " - "wdea_{{ i }} int not null{% if not loop.last %},{% endif %} " - {% endfor %} - ");" - ); - - // Creates core-specific instruction data tables - char *iprefs[] = { "pop", "exe", "wrt" }; - int iprefs_cnt = sizeof(iprefs) / sizeof(iprefs[0]); - - for (int i = 0; i < {{ args.cores }}; ++i) { - for (int j = 0; j < iprefs_cnt; ++j) { - g_info("Creating '%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 - 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("Creating '%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() { - assert(g_sim_data); - - // Measure current instruction population and average memory block sizes - uint64_t ipop[{{ args.cores }}][{{ arch_vars.inst_count }}] = { 0 }; - - double amb0[{{ args.cores }}] = { 0 }; - double amb1[{{ args.cores }}] = { 0 }; - - for (int i = 0; i < {{ args.cores }}; ++i) { - struct Core *core = &g_cores[i]; - - for (uint64_t j = core->pfst; j <= core->plst; ++j) { - const struct Proc *proc = proc_get(core, j); - - amb0[i] += (double)proc->mb0s; - amb1[i] += (double)proc->mb1s; - } - - amb0[i] /= core->pnum; - amb1[i] /= core->pnum; - - for (uint64_t j = 0; j < {{ mvec_size }}; ++j) { - ++ipop[i][_get_inst(core, j)]; - } - - {% if not args.optimized %} - // Make sure the counting was done right - uint64_t pop_tot = 0; - - for (int j = 0; j < {{ arch_vars.inst_count }}; ++j) { - pop_tot += ipop[i][j]; - } - - assert(pop_tot == {{ mvec_size }}); - {% endif %} - } - - // 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) %} - "cycl_{{ i }}, " - "mall_{{ i }}, " - "pnum_{{ i }}, " - "pfst_{{ i }}, " - "plst_{{ i }}, " - "amb0_{{ i }}, " - "amb1_{{ i }}, " - "emb0_{{ i }}, " - "emb1_{{ i }}, " - "eliv_{{ i }}, " - "edea_{{ i }}, " - "wmb0_{{ i }}, " - "wmb1_{{ i }}, " - "wdea_{{ i }}{% if not loop.last %},{% endif %} " - {% endfor %} - ") values (" - "%ld, " - {% for i in range(args.cores) %} - "%ld, %ld, %ld, %ld, %ld, %f, %f, %ld, %ld, %ld, %ld, %ld, %ld, %ld{% if not loop.last %},{% endif %} " - {% endfor %} - ");", - g_steps, - {% for i in range(args.cores) +%} - g_cores[{{ i }}].cycl, - g_cores[{{ i }}].mall, - g_cores[{{ i }}].pnum, - g_cores[{{ i }}].pfst, - g_cores[{{ i }}].plst, - amb0[{{ i }}], - amb1[{{ i }}], - g_cores[{{ i }}].emb0, - g_cores[{{ i }}].emb1, - g_cores[{{ i }}].eliv, - g_cores[{{ i }}].edea, - g_cores[{{ i }}].wmb0, - g_cores[{{ i }}].wmb1, - g_cores[{{ i }}].wdea{% if not loop.last %},{% endif %} - {% endfor +%} - ); - - // Insert row into instruction data tables - char *iprefs[] = { "pop", "exe", "wrt" }; - int iprefs_cnt = sizeof(iprefs) / sizeof(iprefs[0]); - - for (int i = 0; i < {{ args.cores }}; ++i) { - for (int j = 0; j < iprefs_cnt; ++j) { - uint64_t *ia; - - if (!strcmp("pop", iprefs[j])) { - // Population is generated above, prior to push - ia = ipop[i]; - } else if (!strcmp("exe", iprefs[j])) { - ia = g_cores[i].iexe; - } else if (!strcmp("wrt", iprefs[j])) { - ia = g_cores[i].iwrt; - } - - 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) %} - ia[{{ j }}]{% if not loop.last %},{% endif +%} - {% endfor %} - ); - } - } - - // Insert row into memory event tables - char *eprefs[] = { "aev" }; - int eprefs_cnt = sizeof(eprefs) / sizeof(eprefs[0]); - - // Event run-length data array is defined as static - // This prevents heap errors - static uint64_t erl_data[{{ mvec_size }} * 2]; - - for (int i = 0; i < {{ args.cores }}; ++i) { - for (int j = 0; j < eprefs_cnt; ++j) { - uint64_t *eva; - - if (!strcmp("aev", eprefs[j])) { - eva = g_cores[i].aeva; - } - - // Assume event data to be sparse in most cases - // Run-length encoding should help keep database size manageable, - // while making it easy to decode events array, wherever the - // database is consumed. - uint64_t addr = 0; - uint64_t eix = 0; - - while (addr < {{ mvec_size }}) { - assert(eix < {{ mvec_size }} * 2); - - erl_data[eix] = eva[addr]; - erl_data[eix + 1] = 0; - - while (addr < {{ mvec_size }} && eva[addr] == erl_data[eix]) { - ++erl_data[eix + 1]; - ++addr; - } - - eix += 2; - } - - {% if not args.optimized %} - uint64_t el = 0; - - for (uint64_t k = 0; k < eix; k += 2) { - el += erl_data[k + 1]; - } - - assert(el == {{ mvec_size }}); - {% endif %} - - // Insert blob into database - const void *blob_ptr = erl_data; - int blob_size = eix * sizeof(uint64_t); - - g_info("Pushing row to '%s_%d' table in SQLite database", eprefs[j], i); - salis_exec_sql( - 1, &blob_ptr, &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) { - struct Core *core = &g_cores[i]; - - memset(core->iexe, 0, sizeof(uint64_t) * {{ arch_vars.inst_count }}); - memset(core->iwrt, 0, sizeof(uint64_t) * {{ arch_vars.inst_count }}); - - core->emb0 = 0; - core->emb1 = 0; - core->eliv = 0; - core->edea = 0; - core->wmb0 = 0; - core->wmb1 = 0; - core->wdea = 0; - - // Event vectors - memset(core->aeva, 0, sizeof(uint64_t) * {{ mvec_size }}); - } -} -{% endif %} |
