Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ directories:
mkdir -p $(BIN_DIR)

# --- Shared Libraries ---
$(BIN_DIR)/libtfmbs_device$(SHLIB_EXT): $(SRC_DIR)/libtfmbs_device.c $(SRC_DIR)/fabric_emulator.c $(SRC_DIR)/tfmbs_driver_mock.c
$(BIN_DIR)/libtfmbs_device$(SHLIB_EXT): $(SRC_DIR)/libtfmbs_device.c $(SRC_DIR)/fabric_emulator.c $(SRC_DIR)/tfmbs_driver_mock.c $(SRC_DIR)/libtfmbs_api.c
$(CC) $(CFLAGS) -fPIC $(LDFLAGS_SHARED) -o $@ $^

$(BIN_DIR)/libtfmbs_intercept$(SHLIB_EXT): $(SRC_DIR)/libtfmbs_intercept.c $(BIN_DIR)/libtfmbs_device$(SHLIB_EXT)
Expand Down
16 changes: 16 additions & 0 deletions benchmarks/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
CC=gcc
CFLAGS=-O3 -I../include -I../src
LDFLAGS=-L../bin -ltfmbs_device -lpthread

TARGETS=layer1_synthetic layer2_kernels

all: $(TARGETS)

layer1_synthetic: layer1_synthetic.c
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)

layer2_kernels: layer2_kernels.c
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)

clean:
rm -f $(TARGETS)
84 changes: 84 additions & 0 deletions benchmarks/layer1_synthetic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "tfmbs_device.h"

void benchmark_tile_saturation() {
printf("\n--- [Layer 1] Tile Saturation Test ---\n");
int rows = 1024;
int cols = 1024;

void* w = fabric_alloc(rows * cols);
void* i = fabric_alloc(cols);
void* o = fabric_alloc(rows * sizeof(int32_t));

int8_t* host_w = malloc(rows * cols);
int8_t* host_i = malloc(cols);
memset(host_w, 1, rows * cols); // All ones to avoid zero-skips
memset(host_i, 1, cols);

fabric_memcpy_to(w, host_w, rows * cols, 1);
fabric_memcpy_to(i, host_i, cols, 1);

for (int mask = 1; mask <= 15; mask = (mask << 1) | 1) {
char mask_str[10];
snprintf(mask_str, sizeof(mask_str), "0x%02x", mask);
setenv("FABRIC_TILE_MASK", mask_str, 1);

struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);

fabric_handle_t h = fabric_exec_gemv_async(w, i, o, rows, cols);
fabric_wait(h);

clock_gettime(CLOCK_MONOTONIC, &end);
double diff = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9;

fabric_metrics_t m;
fabric_get_metrics(&m);
printf("Mask 0x%02x: %.6f s, Zero-Skips: %ld, Pool: %zu MB\n",
mask, diff, m.zero_skips, m.pool_used / (1024*1024));
}

fabric_free(w); fabric_free(i); fabric_free(o);
free(host_w); free(host_i);
}

void benchmark_zero_skip_density() {
printf("\n--- [Layer 1] Zero-Skip Density Curves ---\n");
int size = 1024 * 512;
void* w = fabric_alloc(size);
void* i = fabric_alloc(1024);
void* o = fabric_alloc(512 * sizeof(int32_t));

int8_t* host_w = malloc(size);
int8_t* host_i = malloc(1024);
memset(host_i, 1, 1024);

float densities[] = {0.0, 0.25, 0.5, 0.75, 0.9, 1.0};
for (int d = 0; d < 6; d++) {
float density = densities[d];
for (int j = 0; j < size; j++) {
host_w[j] = ((float)rand() / RAND_MAX > density) ? 1 : 0;
}
fabric_memcpy_to(w, host_w, size, 1);
fabric_memcpy_to(i, host_i, 1024, 1);

fabric_handle_t h = fabric_exec_gemv_async(w, i, o, 512, 1024);
fabric_wait(h);

fabric_metrics_t m;
fabric_get_metrics(&m);
printf("Density %.2f: Skip Ratio %.1f%%\n", density, m.sim_cycle_reduction);
}

fabric_free(w); fabric_free(i); fabric_free(o);
free(host_w); free(host_i);
}

int main() {
benchmark_tile_saturation();
benchmark_zero_skip_density();
return 0;
}
75 changes: 75 additions & 0 deletions benchmarks/layer2_kernels.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "tfmbs_api.h"

void benchmark_gemm_kernel() {
printf("\n--- [Layer 2] GEMM Kernel Benchmark ---\n");
int rows = 1024, cols = 1024;

int8_t* host_w = malloc(rows * cols);
for(int j=0; j<rows*cols; j++) host_w[j] = (rand()%3)-1;

// Using high-level API
tfmbs_tensor_t w = tfmbs_tensor_bind(host_w, rows * cols, 1);
tfmbs_tensor_t i = tfmbs_tensor_bind(NULL, cols, 1);
tfmbs_tensor_t o = tfmbs_tensor_bind(NULL, rows * sizeof(int32_t), 0);

struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);

for(int n=0; n<10; n++) {
fabric_handle_t h = tfmbs_gemm(&w, &i, &o, rows, cols);
tfmbs_sync(h);
}

clock_gettime(CLOCK_MONOTONIC, &end);
double diff = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9;
printf("10x GEMM %dx%d: %.6f s (%.2f GFLOPS effective)\n",
rows, cols, diff, (rows*cols*2.0*10.0)/diff/1e9);

tfmbs_tensor_release(&w); tfmbs_tensor_release(&i); tfmbs_tensor_release(&o);
free(host_w);
}

void benchmark_lstm_kernel() {
printf("\n--- [Layer 2] LSTM Kernel Benchmark ---\n");
int h_size = 512;
int i_size = 512;
int rows = 4 * h_size;
int cols = i_size + h_size;

int8_t* host_w = malloc(rows * cols);
memset(host_w, 0, rows * cols);
for(int j=0; j<rows*cols; j++) if(rand()%10 == 0) host_w[j] = (rand()%3)-1;

tfmbs_tensor_t w = tfmbs_tensor_bind(host_w, rows * cols, 1);
tfmbs_tensor_t i = tfmbs_tensor_bind(NULL, cols, 1);
tfmbs_tensor_t o = tfmbs_tensor_bind(NULL, rows * sizeof(int32_t), 0);

struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);

for(int n=0; n<10; n++) {
fabric_handle_t h = tfmbs_lstm_step(&w, &i, &o, h_size, i_size);
tfmbs_sync(h);
}

clock_gettime(CLOCK_MONOTONIC, &end);
double diff = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9;

fabric_metrics_t m;
fabric_get_metrics(&m);
printf("10x T-LSTM Step (H=%d, I=%d): %.6f s\n", h_size, i_size, diff);
printf("Last Step Metrics: %ld skips, %.1f%% cycle reduction\n", m.zero_skips, m.sim_cycle_reduction);

tfmbs_tensor_release(&w); tfmbs_tensor_release(&i); tfmbs_tensor_release(&o);
free(host_w);
}

int main() {
benchmark_gemm_kernel();
benchmark_lstm_kernel();
return 0;
}
52 changes: 52 additions & 0 deletions docs/18_WORKLOADS_METRICS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Phase 18: Ternary Workload Maturation & Measurement Plane

Phase 18 transitions the Ternary Fabric from an "acceleration shim" to an operational co-processing environment with defined semantics and rigorous measurement.

## 🎯 Objectives

1. **Establish Workload Realism:** Move beyond isolated GEMV to complex, stateful workloads (T-LSTM).
2. **Define the Programming Model:** Create a formal host-side API for fabric orchestration.
3. **Implement a Measurement Plane:** Build a three-tier benchmark stack and a cycle-aware cost model.

## 📊 Three-Tier Benchmarking

We define a hierarchical approach to performance validation:

### Layer 1: Synthetic (Hardware Semantics)
- **Goal:** Stress the hardware limits.
- **Benchmarks:** Tile saturation, broadcast efficiency, zero-skip density curves.
- **Metrics:** Ops/cycle, tile utilization %, memory traffic.

### Layer 2: Kernel (Primitive Performance)
- **Goal:** Compare ternary kernels against binary baselines.
- **Benchmarks:** GEMV, Attention block, LSTM step.
- **Metrics:** Latency, effective GOPS, residency reuse.

### Layer 3: Application (End-to-End)
- **Goal:** Quantify real-world impact.
- **Benchmarks:** `mock_llama++`, small RNN classifier.
- **Metrics:** End-to-end latency, tokens/sec, semantic work per cost unit.

## 🧠 T-LSTM Maturation

The T-LSTM kernel is promoted from a "reference/mock" to a primary kernel path.
- **State Persistence:** Support for `BIAS_EN` driven hidden state persistence within tile-local SRAM.
- **Recurrent Scheduling:** Optimized multi-tile scheduling for sequential time-step processing.
- **Host Integration:** Explicit `tfmbs_lstm_step` API.

## 💎 Host API Surface (C/C++ Primitives)

Defining the "Ternary Offload ABI" via high-level primitives:
- `tfmbs_tensor_bind(ptr, size, flags)`: Register and prepare a tensor for fabric residency.
- `tfmbs_gemm(...)`: Direct GEMM offload.
- `tfmbs_lstm_step(...)`: Single-step recurrent update.
- `tfmbs_sync(handle)`: Explicit synchronization points.

## 📉 Cycle-Aware Cost Model

The emulator now implements a synthetic cost function to proxy energy and efficiency:
```
fabric_cost = (active_ops * 1.0) + (mem_reads * 5.0) + (mem_writes * 8.0) + (broadcasts * 0.5)
```
- **KPI:** Semantic work per cost unit.
- **Efficiency:** Skip-weighted cost tracking to reward sparsity.
9 changes: 9 additions & 0 deletions docs/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,15 @@ Promotion of reference kernels to full hardware acceleration.
* **Deliverables:** Updated `frame_controller.v` and `ternary_lane_alu.v` with native support for 3D Convolution, LSTM, and Attention kernels.
* **Features:** Squared-stride memory addressing for CONV3D and `BIAS_EN` driven state persistence for recurrent/attention workloads.

### Phase 18 — Ternary Workload Maturation & Measurement Plane ⏳
Anchoring the fabric with workload realism and a formal programming model.
* **Status:** In Progress.
* **Deliverables:**
* **Three-Tier Benchmark Suite:** Synthetic, Kernel, and Application-level measurement.
* **T-LSTM Promotion:** Native kernel path for recurrent stateful workloads.
* **Host API Surface:** Formal C/C++ primitives for fabric orchestration.
* **Cost Model:** Cycle-aware emulator tracking "fabric_cost" (ops + memory weighted).

---

# 🔑 What This Strategy Gives You
Expand Down
55 changes: 55 additions & 0 deletions include/tfmbs_api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#ifndef TFMBS_API_H
#define TFMBS_API_H

#include <stddef.h>
#include <stdint.h>
#include "tfmbs_device.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Represents a resident tensor on the Ternary Fabric.
*/
typedef struct {
void* device_ptr;
size_t size;
uint32_t flags;
} tfmbs_tensor_t;

/**
* @brief Bind a host buffer to the Fabric, establishing residency.
* @param host_ptr Source data
* @param size Number of elements (trits)
* @param pack_pt5 Whether to pack RAW to PT-5
* @return Tensor object
*/
tfmbs_tensor_t tfmbs_tensor_bind(void* host_ptr, size_t size, int pack_pt5);

/**
* @brief Release a resident tensor.
*/
void tfmbs_tensor_release(tfmbs_tensor_t* tensor);

/**
* @brief High-level GEMM operation.
*/
fabric_handle_t tfmbs_gemm(tfmbs_tensor_t* weight, tfmbs_tensor_t* input, tfmbs_tensor_t* output, int rows, int cols);

/**
* @brief Single-step LSTM update.
* Assumes weight contains 4 gates [4*h, i+h]
*/
fabric_handle_t tfmbs_lstm_step(tfmbs_tensor_t* weight, tfmbs_tensor_t* input, tfmbs_tensor_t* output, int h_size, int i_size);

/**
* @brief Explicit synchronization point.
*/
void tfmbs_sync(fabric_handle_t handle);

#ifdef __cplusplus
}
#endif

#endif // TFMBS_API_H
7 changes: 7 additions & 0 deletions include/tfmbs_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ typedef struct {
size_t pool_used;
size_t pool_total;
int eviction_count;
// Phase 18 Metrics
long cycles;
double fabric_cost;
long mem_reads;
long mem_writes;
} fabric_metrics_t;

typedef void* fabric_handle_t;
Expand All @@ -26,12 +31,14 @@ void fabric_free(void* ptr);
int fabric_memcpy_to(void* dest_fabric, const void* src_host, size_t size, int pack_pt5);
int fabric_memcpy_from(void* dest_host, const void* src_fabric, size_t size, int unpack_pt5);
int fabric_exec_gemv(void* weight_ptr, void* input_ptr, void* output_ptr, int rows, int cols);
int fabric_exec_lstm(void* weight_ptr, void* input_ptr, void* output_ptr, int hidden_size, int input_size);

// Cooperative API (Phase 16)
void fabric_register_weight(void* ptr, size_t size);

// Async API (Phase 8)
fabric_handle_t fabric_exec_gemv_async(void* weight_ptr, void* input_ptr, void* output_ptr, int rows, int cols);
fabric_handle_t fabric_exec_lstm_async(void* weight_ptr, void* input_ptr, void* output_ptr, int hidden_size, int input_size);
int fabric_wait(fabric_handle_t handle);

// Low-level TFD submission (Phase 10)
Expand Down
Loading
Loading