code wiki / (root) / nx_engram.nx

nx_engram.nx source

↩ module page · 130 lines · 4259 B

1// nx_engram.nx -- short-term memory / cache (hippocampal-class). 2// 3// Biology: an engram is a physical/chemical change that represents 4// a stored memory. Hippocampal short-term memory consolidates into 5// long-term storage via repeated activation. 6 7import "nx_syscalls.nx" 8import "nx_tier.nx" 9 10const NX_EG_V_OK: nx_int = 0 11const NX_EG_V_HIT: nx_int = 1 12const NX_EG_V_MISS: nx_int = 2 13const NX_EG_V_EVICTED: nx_int = 3 14const NX_EG_V_NULL: nx_int = 4 15const NX_EG_V_N: nx_int = 5 16 17struct NxEngramEntry { 18 key_hash: nx_size, 19 value_hash: nx_size, 20 inserted_at_us: nx_size, 21 last_accessed_us: nx_size, 22 access_count: nx_int, 23 consolidation_score: nx_int, // 0=fresh; high=consolidated to long-term 24} 25 26const NX_EG_ENT_BYTES: nx_int = 40 27 28struct NxEngramCache { 29 entries: *u8, // array of NxEngramEntry 30 n_entries: nx_int, 31 capacity: nx_int, 32 next_idx: nx_int, // ring buffer head 33} 34 35const NX_EG_CACHE_BYTES: nx_int = 32 36 37func nx_eg_v_is_valid(v: nx_int) -> nx_int { 38 if v < 0 { return 0 } 39 if v >= NX_EG_V_N { return 0 } 40 return 1 41} 42 43func _eg_at(c: *NxEngramCache, idx: nx_int) -> *NxEngramEntry { 44 if idx < 0 { return 0 as *NxEngramEntry } 45 if idx >= c.capacity { return 0 as *NxEngramEntry } 46 return (c.entries + idx * NX_EG_ENT_BYTES) as *NxEngramEntry 47} 48 49func nx_eg_cache_new(capacity: nx_int) -> *NxEngramCache { 50 if capacity <= 0 { return 0 as *NxEngramCache } 51 let raw: *u8 = sys_mmap(NX_EG_CACHE_BYTES) 52 let c: *NxEngramCache = raw as *NxEngramCache 53 c.entries = sys_mmap(capacity * NX_EG_ENT_BYTES) 54 c.n_entries = 0 55 c.capacity = capacity 56 c.next_idx = 0 57 return c 58} 59 60func nx_eg_find(c: *NxEngramCache, key_hash: nx_size) -> *NxEngramEntry { 61 if (c as i64) == 0 { return 0 as *NxEngramEntry } 62 var i: nx_int = 0 63 while i < c.n_entries { 64 let e: *NxEngramEntry = _eg_at(c, i) 65 if e.key_hash == key_hash { return e } 66 i = i + 1 67 } 68 return 0 as *NxEngramEntry 69} 70 71func nx_eg_insert(c: *NxEngramCache, 72 key_hash: nx_size, 73 value_hash: nx_size, 74 now_us: nx_size) -> nx_int { 75 if (c as i64) == 0 { return NX_EG_V_NULL } 76 let existing: *NxEngramEntry = nx_eg_find(c, key_hash) 77 if (existing as i64) != 0 { 78 existing.value_hash = value_hash 79 existing.last_accessed_us = now_us 80 existing.access_count = existing.access_count + 1 81 if existing.access_count >= 3 { 82 existing.consolidation_score = existing.consolidation_score + 1 83 } 84 return NX_EG_V_OK 85 } 86 // Ring-buffer insertion 87 let slot: *NxEngramEntry = _eg_at(c, c.next_idx) 88 let evicted: nx_int = 0 89 var v: nx_int = NX_EG_V_OK 90 if c.n_entries >= c.capacity { v = NX_EG_V_EVICTED } 91 slot.key_hash = key_hash 92 slot.value_hash = value_hash 93 slot.inserted_at_us = now_us 94 slot.last_accessed_us = now_us 95 slot.access_count = 1 96 slot.consolidation_score = 0 97 c.next_idx = c.next_idx + 1 98 if c.next_idx >= c.capacity { c.next_idx = 0 } 99 if c.n_entries < c.capacity { c.n_entries = c.n_entries + 1 } 100 return v 101} 102 103func nx_eg_lookup(c: *NxEngramCache, 104 key_hash: nx_size, 105 now_us: nx_size) -> nx_int { 106 if (c as i64) == 0 { return NX_EG_V_NULL } 107 let e: *NxEngramEntry = nx_eg_find(c, key_hash) 108 if (e as i64) == 0 { return NX_EG_V_MISS } 109 e.last_accessed_us = now_us 110 e.access_count = e.access_count + 1 111 if e.access_count >= 3 { 112 e.consolidation_score = e.consolidation_score + 1 113 } 114 return NX_EG_V_HIT 115} 116 117func nx_eg_value_of(c: *NxEngramCache, key_hash: nx_size) -> nx_size { 118 if (c as i64) == 0 { return 0 } 119 let e: *NxEngramEntry = nx_eg_find(c, key_hash) 120 if (e as i64) == 0 { return 0 } 121 return e.value_hash 122} 123 124func nx_eg_should_consolidate(c: *NxEngramCache, key_hash: nx_size) -> nx_int { 125 if (c as i64) == 0 { return 0 } 126 let e: *NxEngramEntry = nx_eg_find(c, key_hash) 127 if (e as i64) == 0 { return 0 } 128 if e.consolidation_score >= 1 { return 1 } 129 return 0 130}