diff --git a/bank.c b/bank.c index 87a0c8f..34950ac 100644 --- a/bank.c +++ b/bank.c @@ -1,16 +1,9 @@ #include "bank.h" +#include -#define ORCA_BANK_ENTRY_HEADER (sizeof(U32) + sizeof(U8)) -#define ORCA_BANK_ENTRY_ALIGN sizeof(Bank_entry) - -ORCA_FORCE_STATIC_INLINE -Usz bank_entry_padding(Usz glyph_count) { - return ORCA_BANK_ENTRY_ALIGN - - (ORCA_BANK_ENTRY_HEADER + glyph_count) % ORCA_BANK_ENTRY_ALIGN; -} ORCA_FORCE_STATIC_INLINE -Usz bank_entry_size(Usz glyph_count) { - return ORCA_BANK_ENTRY_HEADER + glyph_count + bank_entry_padding(glyph_count); +Usz bank_entry_size(Usz num_vals) { + return sizeof(Bank_entry) + sizeof(I32) * num_vals; } void bank_init(Bank* bank) { @@ -21,7 +14,7 @@ void bank_init(Bank* bank) { void bank_deinit(Bank* bank) { free(bank->data); } void bank_enlarge_to(Bank* bank, Usz bytes) { - Usz new_cap = bytes < 256 ? 256 : orca_round_up_power2(bytes); + Usz new_cap = bytes < 512 ? 512 : orca_round_up_power2(bytes); bank->data = realloc(bank->data, new_cap); bank->capacity = new_cap; } @@ -36,35 +29,38 @@ void bank_reserve(Bank* bank, Usz entries, Usz avg_count) { } Usz bank_append(Bank* restrict bank, Usz cur_size, Usz index, - Glyph* restrict glyphs, Usz glyph_count) { + I32 const* restrict vals, Usz vals_count) { assert(index <= ORCA_BANK_INDEX_MAX); - assert(glyph_count <= ORCA_BANK_ENTRY_GLYPHS_MAX); + assert(vals_count <= ORCA_BANK_ENTRY_VALS_MAX); // no overflow check - Usz new_size = cur_size + bank_entry_size(glyph_count); + Usz new_size = cur_size + bank_entry_size(vals_count); if (new_size > bank->capacity) bank_enlarge_to(bank, new_size); char* data = bank->data + cur_size; Bank_entry* entry = (Bank_entry*)ORCA_ASSUME_ALIGNED(data, ORCA_BANK_ENTRY_ALIGN); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" entry->index = (U32)index; - entry->size = (U8)glyph_count; - data += ORCA_BANK_ENTRY_HEADER; - memcpy(data, glyphs, glyph_count); -#ifndef NDEBUG - Usz padding = bank_entry_padding(glyph_count); - memset(data + glyph_count, 0x1c, padding); -#endif + entry->count = (U32)vals_count; +#pragma GCC diagnostic pop + I32* restrict out_vals = + (I32*)ORCA_ASSUME_ALIGNED(data + ORCA_BANK_ENTRY_HEADER, sizeof(I32)); + for (size_t i = 0; i < vals_count; ++i) { + out_vals[i] = vals[i]; + } + // memcpy(data, vals, vals_count * sizeof(I32)); return new_size; } -Usz bank_read(char const* bank_data, Usz bank_size, - Bank_cursor* restrict cursor, Usz index, Glyph* restrict dest, +Usz bank_read(char const* restrict bank_data, Usz bank_size, + Bank_cursor* restrict cursor, Usz index, I32* restrict dest, Usz dest_count) { assert(index <= ORCA_BANK_INDEX_MAX); Usz offset = *cursor; Bank_entry* entry; Usz entry_index; - Usz entry_size; + Usz entry_count; Usz num_to_copy; next: @@ -75,22 +71,26 @@ next: entry_index = entry->index; if (entry_index > index) goto fail; - entry_size = entry->size; + entry_count = entry->count; if (entry_index < index) { - offset += - ORCA_BANK_ENTRY_HEADER + entry_size + bank_entry_padding(entry_size); + offset += bank_entry_size(entry_count); goto next; } - num_to_copy = dest_count < entry_size ? dest_count : entry_size; - memcpy(dest, bank_data + offset + ORCA_BANK_ENTRY_HEADER, num_to_copy); - if (num_to_copy < dest_count) - memset(dest, '.', dest_count - num_to_copy); - *cursor = offset + ORCA_BANK_ENTRY_HEADER + entry_size + - bank_entry_padding(entry_size); + num_to_copy = dest_count < entry_count ? dest_count : entry_count; + I32 const* src = (I32 const*)ORCA_ASSUME_ALIGNED( + bank_data + offset + ORCA_BANK_ENTRY_HEADER, sizeof(I32)); + Usz i = 0; + for (; i < num_to_copy; ++i) { + dest[i] = src[i]; + } + for (; i < dest_count; ++i) { + dest[i] = 0; + } + *cursor = offset + ORCA_BANK_ENTRY_HEADER + entry_count * sizeof(I32); return num_to_copy; fail: - memset(dest, '.', dest_count); + memset(dest, 0, dest_count * sizeof(I32)); *cursor = offset; return 0; } diff --git a/bank.h b/bank.h index e4a37c2..7fae139 100644 --- a/bank.h +++ b/bank.h @@ -2,8 +2,8 @@ #include "base.h" typedef struct { - U32 index; - U8 size; + U32 index : 28; + U32 count : 4; } Bank_entry; typedef struct { @@ -13,17 +13,19 @@ typedef struct { typedef size_t Bank_cursor; -#define ORCA_BANK_INDEX_MAX UINT32_MAX -#define ORCA_BANK_ENTRY_GLYPHS_MAX UINT8_MAX +#define ORCA_BANK_ENTRY_HEADER sizeof(Bank_entry) +#define ORCA_BANK_ENTRY_ALIGN sizeof(Bank_entry) +#define ORCA_BANK_INDEX_MAX ((size_t)UINT32_C(0x0FFFFFFF)) +#define ORCA_BANK_ENTRY_VALS_MAX ((size_t)UINT32_C(0xF)) void bank_init(Bank* bank); void bank_deinit(Bank* bank); void bank_enlarge_to(Bank* bank, Usz bytes); -void bank_reserve_average(Bank* bank, Usz num_entries, Usz avg_glyph_count); +void bank_reserve_average(Bank* bank, Usz num_entries, Usz avg_entry_count); static inline void bank_cursor_reset(Bank_cursor* cursor) { *cursor = 0; } Usz bank_append(Bank* restrict bank, Usz cur_size, Usz index, - Glyph* restrict glyphs, Usz glyph_count); -Usz bank_read(char const* bank_data, Usz bank_size, - Bank_cursor* restrict cursor, Usz index, Glyph* restrict dest, + I32 const* restrict vals, Usz vals_count); +Usz bank_read(char const* restrict bank_data, Usz bank_size, + Bank_cursor* restrict cursor, Usz index, I32* restrict dest, Usz dest_count); diff --git a/sim.c b/sim.c index d780cd3..15d66b3 100644 --- a/sim.c +++ b/sim.c @@ -87,23 +87,23 @@ typedef struct { // static may cause warning if programmer doesn't use bank storage void oper_bank_store(Oper_bank_write_params* bank_params, Usz width, Usz y, - Usz x, Glyph* restrict glyphs, Usz num_glyphs) { - assert(num_glyphs > 0); + Usz x, I32* restrict vals, Usz num_vals) { + assert(num_vals > 0); Usz index = y * width + x; assert(index < ORCA_BANK_INDEX_MAX); - bank_params->size = bank_append(bank_params->bank, bank_params->size, index, - glyphs, num_glyphs); + bank_params->size = + bank_append(bank_params->bank, bank_params->size, index, vals, num_vals); } Usz oper_bank_load(Oper_bank_read_params* bank_params, Usz width, Usz y, Usz x, - Glyph* restrict out_glyphs, Usz out_count) { + I32* restrict out_vals, Usz out_count) { Usz index = y * width + x; assert(index < ORCA_BANK_INDEX_MAX); return bank_read(bank_params->bank->data, bank_params->size, - &bank_params->cursor, index, out_glyphs, out_count); + &bank_params->cursor, index, out_vals, out_count); } ORCA_FORCE_STATIC_INLINE -Usz UCLAMP(Usz val, Usz min, Usz max) { +Usz usz_clamp(Usz val, Usz min, Usz max) { if (val < min) return min; if (val > max) @@ -185,10 +185,10 @@ Usz UCLAMP(Usz val, Usz min, Usz max) { mbuffer_poke_relative_flags_or(mbuffer, height, width, y, x, _delta_y, \ _delta_x, Mark_flag_lock) -#define STORE(_glyph_array) \ - oper_bank_store(bank_params, width, y, x, _glyph_array, sizeof(_glyph_array)) -#define LOAD(_glyph_array) \ - oper_bank_load(bank_params, width, y, x, _glyph_array, sizeof(_glyph_array)) +#define STORE(_i32_array) \ + oper_bank_store(bank_params, width, y, x, _i32_array, sizeof(_i32_array) / sizeof(I32)) +#define LOAD(_i32_array) \ + oper_bank_load(bank_params, width, y, x, _i32_array, sizeof(_i32_array) / sizeof(I32)) #define IN Mark_flag_input #define OUT Mark_flag_output @@ -480,50 +480,44 @@ END_PHASE BEGIN_DUAL_PHASE_0(offset) REALIZE_DUAL; - Usz read_y = 0; - Usz read_x = 1; + I32 coords[2]; + coords[0] = 0; // y + coords[1] = 1; // x if (DUAL_IS_ACTIVE) { - Glyph coords[2]; - coords[0] = PEEK(0, -1); - coords[1] = PEEK(0, -2); + coords[0] = (I32)usz_clamp(INDEX(PEEK(0, -1)), 0, 16); + coords[1] = (I32)usz_clamp(INDEX(PEEK(0, -2)) + 1, 1, 16); STORE(coords); - read_y = UCLAMP(INDEX(coords[0]), 0, 16); - read_x = UCLAMP(INDEX(coords[1]) + 1, 1, 16); } BEGIN_DUAL_PORTS PORT(0, -1, IN | HASTE); PORT(0, -2, IN | HASTE); - PORT((Isz)read_y, (Isz)read_x, IN); + PORT(coords[0], coords[1], IN); PORT(1, 0, OUT); END_PORTS END_PHASE BEGIN_DUAL_PHASE_1(offset) REALIZE_DUAL; STOP_IF_DUAL_INACTIVE; - Isz read_y = 0; - Isz read_x = 1; - Glyph coords[2]; - if (LOAD(coords)) { - read_y = (Isz)UCLAMP(INDEX(coords[0]), 0, 16); - read_x = (Isz)UCLAMP(INDEX(coords[1]) + 1, 1, 16); + I32 coords[2]; + if (!LOAD(coords)) { + coords[0] = 0; + coords[1] = 1; } - POKE(1, 0, PEEK(read_y, read_x)); - STUN(0, 1); + POKE(1, 0, PEEK(coords[0], coords[1])); + STUN(1, 0); END_PHASE BEGIN_DUAL_PHASE_0(push) REALIZE_DUAL; - Usz write_val_x = 0; + I32 write_val_x[1]; + write_val_x[0] = 0; if (DUAL_IS_ACTIVE && IS_AWAKE) { - Glyph params[2]; - params[0] = PEEK(0, -1); // len - params[1] = PEEK(0, -2); // key - STORE(params); - Usz len = UCLAMP(INDEX(params[0]), 1, 16); - Usz key = INDEX(params[1]); - write_val_x = key % len; - for (Usz i = 0; i < write_val_x; ++i) { - LOCK(1, (Isz)i); + Usz len = usz_clamp(INDEX(PEEK(0, -1)), 1, 16); + Usz key = INDEX(PEEK(0, -2)); + write_val_x[0] = (I32)(key % len); + STORE(write_val_x); + for (Isz i = 0; i < write_val_x[0]; ++i) { + LOCK(1, i); } } BEGIN_DUAL_PORTS @@ -535,29 +529,25 @@ BEGIN_DUAL_PHASE_0(push) END_PHASE BEGIN_DUAL_PHASE_1(push) STOP_IF_NOT_BANGED; - Usz write_val_x = 0; - Glyph params[2]; - if (LOAD(params)) { - Usz len = UCLAMP(INDEX(params[0]), 1, 16); - Usz key = INDEX(params[1]); - write_val_x = key % len; + I32 write_val_x[1]; + if (!LOAD(write_val_x)) { + write_val_x[0] = 0; } - POKE(1, (Isz)write_val_x, PEEK(0, 1)); + POKE(1, write_val_x[0], PEEK(0, 1)); END_PHASE BEGIN_DUAL_PHASE_0(track) PSEUDO_DUAL; - Usz read_val_x = 1; + Isz read_val_x = 1; if (IS_AWAKE) { - Glyph params[2]; - params[0] = PEEK(0, -1); // len - params[1] = PEEK(0, -2); // key - STORE(params); - Usz len = UCLAMP(INDEX(params[0]), 1, 16); - Usz key = INDEX(params[1]); - read_val_x = key % len + 1; - for (Usz i = 0; i < read_val_x; ++i) { - LOCK(0, (Isz)(i + 1)); + Usz len = usz_clamp(INDEX(PEEK(0, -1)), 1, 16); + Usz key = INDEX(PEEK(0, -2)); + read_val_x = (Isz)(key % len + 1); + I32 ival[1]; + ival[0] = (I32)read_val_x; + STORE(ival); + for (Isz i = 0; i < read_val_x; ++i) { + LOCK(0, i + 1); } } BEGIN_DUAL_PORTS @@ -568,14 +558,11 @@ BEGIN_DUAL_PHASE_0(track) END_PORTS END_PHASE BEGIN_DUAL_PHASE_1(track) - Usz read_val_x = 1; - Glyph params[2]; - if (LOAD(params)) { - Usz len = UCLAMP(INDEX(params[0]), 1, 16); - Usz key = INDEX(params[1]); - read_val_x = key % len + 1; + I32 ival[1]; + if (!LOAD(ival)) { + ival[0] = 1; } - POKE(1, 0, PEEK(0, (Isz)read_val_x)); + POKE(1, 0, PEEK(0, ival[0])); STUN(1, 0); END_PHASE @@ -626,34 +613,30 @@ END_PHASE BEGIN_DUAL_PHASE_0(teleport) REALIZE_DUAL; - Usz write_y = 0; - Usz write_x = 1; + I32 coords[2]; + coords[0] = 0; // y + coords[1] = 1; // x if (DUAL_IS_ACTIVE) { - Glyph coords[2]; - coords[0] = PEEK(0, -1); - coords[1] = PEEK(0, -2); + coords[0] = (I32)usz_clamp(INDEX(PEEK(0, -1)), 0, 16); + coords[1] = (I32)usz_clamp(INDEX(PEEK(0, -2)), 1, 16); STORE(coords); - write_y = UCLAMP(INDEX(coords[0]), 0, 16); - write_x = UCLAMP(INDEX(coords[1]), 1, 16); } BEGIN_DUAL_PORTS PORT(0, -1, IN | HASTE); PORT(0, -2, IN | HASTE); PORT(1, 0, IN); - PORT((Isz)write_y, (Isz)write_x, OUT | NONLOCKING); + PORT(coords[0], coords[1], OUT | NONLOCKING); END_PORTS END_PHASE BEGIN_DUAL_PHASE_1(teleport) STOP_IF_NOT_BANGED; - Isz write_y = 0; - Isz write_x = 1; - Glyph coords[2]; - if (LOAD(coords)) { - write_y = (Isz)UCLAMP(INDEX(coords[0]), 0, 16); - write_x = (Isz)UCLAMP(INDEX(coords[1]), 1, 16); + I32 coords[2]; + if (!LOAD(coords)) { + coords[0] = 0; + coords[1] = 1; } - POKE(write_y, write_x, PEEK(0, 1)); - STUN(write_y, write_x); + POKE(coords[0], coords[1], PEEK(0, 1)); + STUN(coords[0], coords[1]); END_PHASE //////// Run simulation