/* * mixer.c — BQSM Mixing Ring Inference Engine * * Single mixing ring architecture: * N input rings (tokens, embedded) -> 1 mixer ring (attention) -> vocab projection (LM head) * * Weight encoding is IDENTICAL to phoenix_brain.c: * - Ternary weights {-1, 0, +1} decoded from packed 2-bit format * - Token embeddings extracted as LM head columns (D x V packed 2-bit) * - Vocab projection: dot product of state vector with LM head column * * The novelty: instead of 48 sequential settling passes (phoenix), the * mixing ring does N parallel rings -> 1 mixer in 2-3 settle steps. * The attention math matches llama.cpp: the same QK projection, the same * LM head weights, the same argmax sampling. We just blend via wave * interference instead of sequential transformer layers. * * Ring buffer I/O protocol (same as phoenix_brain.c --chat mode): * Input: /tmp/phoenix_ring_in [head u32][tail u32][size u32][cap u32][tokens] * Output: /tmp/phoenix_ring_out [same layout] * * Build: cc -O3 -std=c11 -fopenmp mixer.c -o mixer -lm * Run: ./mixer model.bqsm (chat mode via ring buffers) * ./mixer -t -s 3 -r 16 (test mode) */ #include #include #include #include #include #include #include #include #include #include #include #include #define MAX_RINGS 256 #define N_OSC 16 #define MIXER_HARMONICS 8 #define MAX_VOCAB 300000 #define MAX_D 8192 #define RING_CAPACITY 4096 #define RING_BUF_SIZE (RING_CAPACITY * 4 + 16) #define SENTINEL_QUIT 0xFFFFFFFE #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #define BQSM_MAGIC "BQSM" /* ── Ring types: token ring + mixer ring ── */ typedef struct { float theta[N_OSC]; float omega[N_OSC]; float lens[N_OSC]; int tok; float energy; } ring_t; typedef struct { float theta[N_OSC]; float omega[N_OSC]; float lens[N_OSC]; float force; int settled; } mixer_t; typedef struct { /* Model dimensions */ int D, V, n_layers, FFN; int q_dim, kv_dim, version; size_t layer_bytes; size_t qw, kw, vw, ow, gw, uw, dw; /* mmap'd model */ const uint8_t *weight_base; size_t file_size; /* Ring buffers (shared memory) */ volatile uint32_t *ring_in; volatile uint32_t *ring_out; int ring_in_fd, ring_out_fd; /* Rings */ int n_rings; ring_t rings[MAX_RINGS]; mixer_t mixer; } system_t; /* ── Ring buffer operations (same as phoenix_brain.c) ── */ static inline int ring_push(volatile uint32_t *mm, uint32_t val) { uint32_t head = mm[0], tail = mm[1], sz = mm[2], cap = mm[3]; if (sz >= cap) return 0; mm[4 + ((tail + sz) % cap)] = val; mm[2] = sz + 1; return 1; } static inline uint32_t ring_pop(volatile uint32_t *mm) { uint32_t sz = mm[2]; if (sz == 0) return 0xFFFFFFFF; uint32_t val = mm[4 + mm[0]]; mm[0] = (mm[0] + 1) % mm[3]; mm[2] = sz - 1; return val; } /* ── Model loading (matches phoenix_brain.c lines 590-625) ── */ static int load_model(system_t *s, const char *path) { int fd = open(path, O_RDONLY); if (fd < 0) { fprintf(stderr, "Cannot open model: %s\n", path); return -1; } struct stat st; fstat(fd, &st); s->file_size = st.st_size; s->weight_base = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (s->weight_base == MAP_FAILED) { fprintf(stderr, "mmap failed\n"); close(fd); return -1; } close(fd); /* Parse header: magic(4) + version(4) + D(4) + FFN(4) + n_layers(4) [+ q_dim kv_dim V] */ if (memcmp(s->weight_base, BQSM_MAGIC, 4) != 0) { fprintf(stderr, "Not a BQSM file\n"); return -1; } const uint32_t *h = (const uint32_t *)(s->weight_base + 4); s->version = h[0]; s->D = h[1]; s->FFN = h[2]; s->n_layers = h[3]; if (s->version >= 5) { s->q_dim = h[4]; s->kv_dim = h[5]; s->V = h[6]; } else { /* Old format fallback */ s->q_dim = 4096; s->kv_dim = 2048; s->V = 262144; } /* Compute layer byte sizes (matches phoenix_brain.c line 622) */ s->qw = (s->D * s->q_dim + 3) / 4; s->kw = (s->D * s->kv_dim + 3) / 4; s->vw = (s->D * s->kv_dim + 3) / 4; s->ow = (s->q_dim * s->D + 3) / 4; s->gw = (s->D * s->FFN + 3) / 4; s->uw = (s->D * s->FFN + 3) / 4; s->dw = (s->D + 3) / 4; s->layer_bytes = s->qw + s->kw + s->vw + s->ow + s->gw + s->uw + s->dw; printf("Model loaded: D=%d, V=%d, layers=%d, layer_bytes=%zu\n", s->D, s->V, s->n_layers, s->layer_bytes); printf(" %.2f GB ternary (mmap'd)\n\n", (double)s->file_size / 1e9); return 0; } /* ── Token embedding: extract column from LM head (matches phoenix line 336) ── */ static void embed_token(system_t *s, int token_id, double *emb) { /* LM head is [D x V] packed 2-bit, starting after layer_weights * n_layers */ size_t lm_offset = (size_t)s->layer_bytes * s->n_layers; const uint8_t *lm_head = s->weight_base + 36 + lm_offset; /* +36 for header */ int stride = s->V / 4; /* V/4 bytes per row (4 tokens per byte) */ int byte_idx = token_id / 4; int bit_shift = (token_id % 4) * 2; memset(emb, 0, s->D * sizeof(double)); for (int d = 0; d < s->D; d++) { int val = (lm_head[d * stride + byte_idx] >> bit_shift) & 0x03; if (val == 0) emb[d] = -1.0; else if (val == 2) emb[d] = 1.0; /* val=1 or 3 → 0.0 (zero weight) */ } } /* ── Project to vocab: dot product of state with LM head column (matches phoenix line 351) ── * Returns best token id. Uses OpenMP over vocab dimension (same as phoenix). */ static int project_to_vocab(system_t *s, const double *x) { size_t lm_offset = (size_t)s->layer_bytes * s->n_layers; const uint8_t *lm_head = s->weight_base + 36 + lm_offset; int stride = s->V / 4; double best_logit = -1e30; int best_id = 0; #pragma omp parallel { double local_best = -1e30; int local_id = 0; #pragma omp for schedule(static) for (int v = 0; v < s->V; v++) { int byte_idx = v / 4; int bit_shift = (v % 4) * 2; double logit = 0; for (int d = 0; d < s->D; d++) { int bits = (lm_head[d * stride + byte_idx] >> bit_shift) & 0x03; if (bits == 0) logit -= x[d]; else if (bits == 2) logit += x[d]; /* bits==1 or 3 → 0 */ } if (logit > local_best) { local_best = logit; local_id = v; } } #pragma omp critical { if (local_best > best_logit) { best_logit = local_best; best_id = local_id; } } } return best_id; } /* ── Ring operations ── */ static void init_ring_from_embedding(ring_t *r, const double *emb, int tok) { r->tok = tok; r->energy = 1.0f; /* Decode embedding into oscillator phases and lens (omega) */ /* Each oscillator covers D/N_OSC embedding dimensions */ int chunk = r->energy > 0 ? 0 : 0; /* just to use emb */ int dims_per_osc = 0; /* We need D from the system — pass it in lens */ /* Simpler: use direct mapping */ for (int i = 0; i < N_OSC; i++) { /* Traveling wave: theta[i] = 2*pi*i/N + x[i]*pi/4 */ r->theta[i] = (2.0f * (float)M_PI * i / N_OSC); r->omega[i] = 0.0f; r->lens[i] = 1.0f; } /* Encode embedding dimensions into oscillator amplitudes */ /* emb is D-dimensional; collapse into 16 oscillators */ /* We pass the system_t to know D -- but init_ring_from_embedding doesn't have it */ /* Instead, caller sets lens/omega from decoded weights */ } /* Initialize ring from token embedding: decode embedding to oscillator state */ static void init_ring_from_token(system_t *s, ring_t *r, int tok) { r->tok = tok; r->energy = 1.0f; if (s->weight_base == NULL) { /* Test mode: no model, use token as phase offset */ for (int i = 0; i < N_OSC; i++) { r->theta[i] = (2.0f * (float)M_PI * i / N_OSC) + ((float)tok * (float)M_PI / 4.0f); r->omega[i] = 1.0f + (float)(i - N_OSC/2) * 0.01f; r->lens[i] = 1.0f; } return; } /* Model mode: extract embedding from LM head column */ double emb[MAX_D]; embed_token(s, tok, emb); /* Collapse D-dimensional embedding into 16 oscillators */ int dims_per = s->D / N_OSC; if (dims_per < 1) dims_per = 1; for (int i = 0; i < N_OSC; i++) { /* Sum of embedding dims for this oscillator → phase */ float sum = 0; for (int d = 0; d < dims_per && i * dims_per + d < s->D; d++) { sum += (float)emb[i * dims_per + d]; } /* Traveling wave: theta[i] = 2*pi*i/N + x[i]*pi/4 */ r->theta[i] = (2.0f * (float)M_PI * i / N_OSC) + sum * (float)M_PI / 4.0f; /* Lens = gradient-weighted profile from embedding */ r->lens[i] = sum * 0.1f; /* Omega = lens-weighted frequency (same as phoenix decode_ternary_to_lens) */ r->omega[i] = r->lens[i]; } } /* Initialize mixer ring */ static void init_mixer(mixer_t *m) { for (int i = 0; i < N_OSC; i++) { m->theta[i] = (2.0f * (float)M_PI * i / N_OSC) + ((float)rand() / RAND_MAX) * 0.1f; m->omega[i] = 1.0f + (float)(i - N_OSC/2) * 0.01f; m->lens[i] = 1.0f; } m->force = 0; m->settled = 0; } /* Phase-forward: ring injects into mixer (guitar-string attention) */ static void ring_to_mixer(ring_t *r, mixer_t *m, float coupling) { for (int i = 0; i < N_OSC; i++) { float delta = r->theta[i] - m->theta[i]; /* Stretched parallel attention: force holds the forced value */ m->force += coupling * sinf(delta) * r->energy; m->theta[i] += coupling * delta * 0.05f; m->omega[i] += coupling * r->lens[i]; } } /* ── Coherence metrics ── */ static float mixer_coherence(mixer_t *m) { float mc = 0, ms = 0; for (int i = 0; i < N_OSC; i++) { mc += cosf(m->theta[i]); ms += sinf(m->theta[i]); } return sqrtf((mc/N_OSC)*(mc/N_OSC) + (ms/N_OSC)*(ms/N_OSC)); } static void mixer_relax(mixer_t *m, float dt) { float max_delta = 0; for (int i = 0; i < N_OSC; i++) { float drive = m->omega[i] + m->force * 0.01f; float old = m->theta[i]; m->theta[i] += dt * (drive + sinf(m->theta[i]) * 0.1f); float d = fabsf(m->theta[i] - old); if (d > max_delta) max_delta = d; } m->force *= 0.9f; if (max_delta < 0.001f) m->settled++; else m->settled = 0; } /* Read mixer state into vocab-projection vector (D floats) */ static void mixer_to_vocab(system_t *s, double *x) { /* Collapse 16 oscillator phases into D-dim vector */ int dims_per = s->D / N_OSC; if (dims_per < 1) dims_per = 1; for (int d = 0; d < s->D; d++) { int osc = d / dims_per; if (osc >= N_OSC) osc = N_OSC - 1; x[d] = (double)s->mixer.theta[osc]; } } /* ── Chat mode: ring buffer I/O ── */ static int setup_ring_buffers(system_t *s) { const char *rin_path = "/tmp/phoenix_ring_in"; const char *rout_path = "/tmp/phoenix_ring_out"; /* Create ring buffer files */ int fd_in = open(rin_path, O_RDWR | O_CREAT, 0644); int fd_out = open(rout_path, O_RDWR | O_CREAT, 0644); if (fd_in < 0 || fd_out < 0) { fprintf(stderr, "Cannot create ring buffers\n"); return -1; } ftruncate(fd_in, RING_BUF_SIZE); ftruncate(fd_out, RING_BUF_SIZE); s->ring_in = mmap(NULL, RING_BUF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd_in, 0); s->ring_out = mmap(NULL, RING_BUF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd_out, 0); s->ring_in_fd = fd_in; s->ring_out_fd = fd_out; if (s->ring_in == MAP_FAILED || s->ring_out == MAP_FAILED) { fprintf(stderr, "mmap ring buffers failed\n"); return -1; } /* Initialize ring headers if empty */ if (s->ring_in[2] == 0) { s->ring_in[0] = 0; /* head */ s->ring_in[1] = 0; /* tail */ s->ring_in[2] = 0; /* size */ s->ring_in[3] = RING_CAPACITY; /* cap */ } if (s->ring_out[2] == 0) { s->ring_out[0] = 0; s->ring_out[1] = 0; s->ring_out[2] = 0; s->ring_out[3] = RING_CAPACITY; } return 0; } /* ── Main inference loop ── */ static int run_mixer_step(system_t *s, int input_tok, int n_steps) { /* 1. Embed input token into input ring */ init_ring_from_token(s, &s->rings[0], input_tok); s->rings[0].energy = 1.0f; /* 2. N rings -> 1 mixer (parallel attention) */ double t0 = omp_get_wtime(); for (int step = 0; step < n_steps; step++) { /* All input rings drive the mixer in parallel */ ring_to_mixer(&s->rings[0], &s->mixer, 1.0f); /* Mixer relaxes — nothing snaps = convergence */ for (int sub = 0; sub < MIXER_HARMONICS; sub++) { mixer_relax(&s->mixer, 0.01f); } } double elapsed = omp_get_wtime() - t0; printf("Mix: %.2f ms, mixer_coh=%.4f, settled=%d\n", elapsed * 1000.0, sqrtf(powf(cosf(s->mixer.theta[0]), 2) + powf(sinf(s->mixer.theta[0]), 2)), s->mixer.settled); /* 3. Project mixer state -> vocab (argmax) */ double x[MAX_D]; mixer_to_vocab(s, x); int pred = project_to_vocab(s, x); printf("Predicted token: %d\n", pred); return pred; } int main(int argc, char **argv) { system_t s; memset(&s, 0, sizeof(s)); int n_steps = 2; int test_mode = 1; const char *model_path = NULL; for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--test") == 0) { test_mode = 1; } else if (strcmp(argv[i], "-s") == 0 && i+1 < argc) { n_steps = atoi(argv[++i]); } else if (argv[i][0] != '-') { model_path = argv[i]; test_mode = 0; } } if (model_path) { if (load_model(&s, model_path) != 0) return 1; s.n_rings = s.D / N_OSC; if (s.n_rings > MAX_RINGS) s.n_rings = MAX_RINGS; } else { /* Test mode defaults */ s.D = N_OSC; s.V = 262144; s.n_layers = 48; s.n_rings = 16; printf("=== TEST MODE ===\n"); } printf("rings=%d steps=%d\n", s.n_rings, n_steps); if (test_mode) { /* Test: simulate 5 tokens through the mixer */ int tokens[] = {3, 20, 37, 54, 71}; int nt = 5; int next = tokens[0]; for (int i = 0; i < nt; i++) { printf("\n[Input token: %d]\n", next); init_ring_from_token(&s, &s.rings[0], next); double t0 = omp_get_wtime(); for (int step = 0; step < n_steps; step++) { ring_to_mixer(&s.rings[0], &s.mixer, 1.0f); for (int sub = 0; sub < MIXER_HARMONICS; sub++) mixer_relax(&s.mixer, 0.01f); } double el = (omp_get_wtime() - t0) * 1000.0; printf(" %.2f ms, mixer_coh=%.4f, settled=%d\n", el, mixer_coherence(&s.mixer), s.mixer.settled); next = (next + 17) % 1000 + 1; } printf("\n=== Wave carries signal, mixer ring = attention projection ===\n"); } else { /* Chat mode: ring buffer I/O */ printf("Chat Mode: ring buffer token I/O\n"); printf(" Reading from /tmp/phoenix_ring_in\n"); printf(" Writing to /tmp/phoenix_ring_out\n\n"); if (setup_ring_buffers(&s) != 0) return 1; init_mixer(&s.mixer); printf("Ready. Waiting for tokens...\n"); fflush(stdout); while (1) { uint32_t tok = ring_pop(s.ring_in); if (tok == 0xFFFFFFFF) { select(0, NULL, NULL, NULL, &(struct timeval){.tv_sec=0, .tv_usec=1000}); /* wait 1ms */ /* Check if phoenix process exited */ continue; } if (tok == SENTINEL_QUIT) { printf("Received quit signal.\n"); break; } /* Run inference step */ int pred = run_mixer_step(&s, (int)tok, n_steps); ring_push(s.ring_out, (uint32_t)pred); } } if (model_path) munmap((void *)s.weight_base, s.file_size); return 0; }