Skip to content
Draft

[WIP] #215

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
6039a8d
tests: pin every operator's arg spec before the spec refactor
hunhoffe Sep 18, 2026
7d61112
tests: cover the shape relationships equal-size cases hide
hunhoffe Sep 18, 2026
d12210b
tests: pin RoPE's broadcast angles
hunhoffe Sep 18, 2026
e553f76
operators: separate the shape rule from the design
hunhoffe Sep 18, 2026
9e57e5e
operators: derive get_arg_spec from a declared shape function
hunhoffe Sep 18, 2026
e02bf16
operators: convert the remaining specs to shape functions
hunhoffe Sep 18, 2026
ee9d87c
tests: check catalog laziness in a fresh interpreter, against the cat…
hunhoffe Sep 18, 2026
4340332
operators: bind design parameters instead of restating them
hunhoffe Sep 18, 2026
f29bdaf
operators: bind the shared bases' design parameters too
hunhoffe Sep 19, 2026
d24f483
compilation: link arch-scoped kernel objects before flat ones
hunhoffe Sep 19, 2026
035e0a7
softmax: one operator, one file
hunhoffe Sep 19, 2026
88feb81
transpose, repeat, rope: one operator, one file
hunhoffe Sep 19, 2026
769450b
strided_copy, gemv, gemm, mha: one operator, one file
hunhoffe Sep 19, 2026
ff2abc6
mem_copy, dequant, axpy, leaky_relu: one operator, one file
hunhoffe Sep 19, 2026
a3b037a
rms_norm: one operator, one file
hunhoffe Sep 19, 2026
be07564
allocator: liveness-based static memory planning
hunhoffe Sep 19, 2026
518fbe0
tests: rename the allocator test module to avoid a basename collision
hunhoffe Sep 19, 2026
83d17c6
sequence: accept a planned buffer layout
hunhoffe Sep 19, 2026
2842b83
sequence: plan scratch offsets from liveness, opt-in
hunhoffe Sep 19, 2026
1c44ec4
capture: record a graph from ordinary Python dataflow
hunhoffe Sep 19, 2026
9ce8490
sequence: dispatch a captured graph, ahead of time or just in time
hunhoffe Sep 19, 2026
ef52102
tests: check the captured graph on the fused ELF path too
hunhoffe Sep 19, 2026
9966c93
sequence: never pool a sliced buffer
hunhoffe Sep 19, 2026
b5cd8e4
sequence: infer the buffer layout by default, and name it that way
hunhoffe Sep 19, 2026
e46ae42
tests: pin what CompilableDesign's cache key does and does not distin…
hunhoffe Sep 19, 2026
ae2ffb1
jit_compile: compile a fused sequence through CompilableDesign
hunhoffe Sep 19, 2026
35f5068
jit_compile: pass the aiecc flags a fused ELF needs
hunhoffe Sep 19, 2026
4f4a9c1
jit_compile: handle tracing, and key the cache on it
hunhoffe Sep 19, 2026
571041b
sequence: ask for the ELF path, not the artifact that produced it
hunhoffe Sep 19, 2026
d8a34a6
FusedDispatch: build the ELF through CompilableDesign
hunhoffe Sep 19, 2026
cb62952
compilation: delete FullElfArtifact and its rule
hunhoffe Sep 19, 2026
f12dade
jit_compile: stage inside the generator, and add the xclbin path
hunhoffe Sep 19, 2026
7335940
sequence: give fused MLIR its own filename
hunhoffe Sep 19, 2026
10503a6
compilation: key PythonGeneratedMLIRArtifact on a recipe hash
hunhoffe Sep 19, 2026
0d411ef
SeparateDispatch: build xclbin/insts through CompilableDesign
hunhoffe Sep 19, 2026
261aafc
compilation: delete dead xclbin_input chaining
hunhoffe Sep 19, 2026
02f78d8
compilation: turn fuse_mlir() into a plain generator function
hunhoffe Sep 19, 2026
870e65b
jit_compile: don't rebuild through aiecc when nothing changed
hunhoffe Sep 19, 2026
351747c
base: build standalone operator xclbin+insts through CompilableDesign
hunhoffe Sep 19, 2026
6ecdc36
requirements: bump mlir_aie to 1.4.4.dev26
hunhoffe Sep 19, 2026
68afbf6
compilation: use upstream symbol-prefix and binutil resolution
hunhoffe Sep 19, 2026
aa835da
models: declare llama 3.2's parameters as a module tree
hunhoffe Sep 19, 2026
4a98aee
llama: upload weights from the module tree, by name
hunhoffe Sep 19, 2026
55894e7
base: make compile() actually compile a standalone operator
hunhoffe Sep 19, 2026
d5cf6a5
gemv: pick a legal kernel vector size instead of asserting in C++
hunhoffe Sep 19, 2026
d71eb3f
jit_compile: compile an operator from its design, not from MLIR text
hunhoffe Sep 19, 2026
a9ac50f
jit_compile: key a device parameter by identity, not by its name
hunhoffe Sep 19, 2026
af5c32a
gemv: declare kernels as ExternalFunctions, and fuse children as chil…
hunhoffe Sep 19, 2026
0e9dd8e
operators: declare kernels once in the two shared bases
hunhoffe Sep 19, 2026
e98938b
operators: declare kernels once in axpy, dequant, mem_copy, transpose…
hunhoffe Sep 19, 2026
e52c035
operators: declare kernels once in rope, rms_norm and softmax
hunhoffe Sep 19, 2026
6eeb5aa
operators: declare kernels once in gemm and mha
hunhoffe Sep 19, 2026
cfd8530
flm/gemm: compile through CompilableDesign, and bind the device befor…
hunhoffe Sep 19, 2026
d5ce0e6
jit_compile: guard the device bind, and make its test actually catch …
hunhoffe Sep 19, 2026
08f707b
operators: compile lut_based_ops into the kernel, and delete the archive
hunhoffe Sep 19, 2026
38be4fc
flm/mm_prebuilt: compile insts through CompilableDesign, and delete w…
hunhoffe Sep 19, 2026
a48058c
stream: declare kernels as ExternalFunctions, and delete rename_symbols
hunhoffe Sep 19, 2026
a7d31a8
compilation: retire the kernel build path, and the tests that guarded it
hunhoffe Sep 19, 2026
2db48db
operator model: two draft plans for the interface/overlay rework
hunhoffe Sep 21, 2026
7819e54
operator model: consolidate the two drafts into one plan
hunhoffe Sep 21, 2026
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
1,205 changes: 1,205 additions & 0 deletions OPERATOR_MODEL_PLAN.md

Large diffs are not rendered by default.

47 changes: 15 additions & 32 deletions iron/applications/llama_3.2_1b/llama_cpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,9 @@ def transformer_block_forward(
def llama_forward_pass(config, state):
batch, seq_len = state.token_ids.shape

# Step 1: Token embedding
tok_emb_weight = config.weights["model.embed_tokens.weight"]
# Step 1: Token embedding. Llama 3.2 ties the output head to the token
# embedding, so out_head.weight is read here and again at step 5.
tok_emb_weight = config.model.out_head.weight
x = torch.nn.functional.embedding(
state.token_ids, tok_emb_weight
) # (batch, seq_len, emb_dim)
Expand All @@ -233,53 +234,35 @@ def llama_forward_pass(config, state):
)

# Step 3: Apply transformer blocks
for layer_idx in range(config.n_layers):
for layer_idx, block in enumerate(config.model.layers):
x, state.attn_keys_caches[layer_idx], state.attn_values_caches[layer_idx] = (
transformer_block_forward(
x,
state.attn_keys_caches[layer_idx],
state.attn_values_caches[layer_idx],
config.n_heads,
config.n_kv_groups,
W_norm1=config.weights[
f"model.layers.{layer_idx}.input_layernorm.weight"
],
W_attn_query=config.weights[
f"model.layers.{layer_idx}.self_attn.q_proj.weight"
],
W_attn_key=config.weights[
f"model.layers.{layer_idx}.self_attn.k_proj.weight"
],
W_attn_value=config.weights[
f"model.layers.{layer_idx}.self_attn.v_proj.weight"
],
W_attn_out=config.weights[
f"model.layers.{layer_idx}.self_attn.o_proj.weight"
],
W_ffn_fc1=config.weights[
f"model.layers.{layer_idx}.mlp.gate_proj.weight"
],
W_ffn_fc2=config.weights[
f"model.layers.{layer_idx}.mlp.up_proj.weight"
],
W_ffn_fc3=config.weights[
f"model.layers.{layer_idx}.mlp.down_proj.weight"
],
W_norm2=config.weights[
f"model.layers.{layer_idx}.post_attention_layernorm.weight"
],
W_norm1=block.norm1.weight,
W_attn_query=block.attn.q.weight,
W_attn_key=block.attn.k.weight,
W_attn_value=block.attn.v.weight,
W_attn_out=block.attn.o.weight,
W_ffn_fc1=block.ffn.gate.weight,
W_ffn_fc2=block.ffn.up.weight,
W_ffn_fc3=block.ffn.down.weight,
W_norm2=block.norm2.weight,
rope_angles=config.angles,
attn_mask=attn_mask,
)
)

# Step 4: Final normalization
final_norm_weight = config.weights["model.norm.weight"]
final_norm_weight = config.model.norm.weight
x = rms_norm_forward(x, final_norm_weight)

# Step 5: Output projection
logits = torch.nn.functional.linear(
x, config.weights["model.embed_tokens.weight"]
x, config.model.out_head.weight
) # (batch, seq_len, vocab_size)

return logits, state
Expand Down
13 changes: 9 additions & 4 deletions iron/applications/llama_3.2_1b/llama_inference_harness.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import safetensors.torch
import tiktoken, tiktoken.load

from iron.models.llama import Llama

# Configuration
# ##########################################################################

Expand Down Expand Up @@ -59,10 +61,13 @@ def __init__(self, weights_path, tokenizer_path):
}
)

# Load model weights and tokenizer
# Load model weights and tokenizer. The module tree names every weight
# once, and load_state_dict is strict, so a checkpoint that disagrees
# with this config on any key or shape fails here rather than at the
# first dispatch. The parameters share storage with self.weights.
self.weights = safetensors.torch.load_file(weights_path)
self.model = Llama.from_hf(self, self.weights)
self.tokenizer = get_tokenizer(tokenizer_path, self.special_tokens)
# TODO: Assert that weight dimensions match config

# Compute RoPE angle look-up table
self.angles = compute_rope_angles(
Expand All @@ -86,7 +91,7 @@ def reset_kv_cache(self, config):
config.n_kv_groups,
0,
config.head_dim,
dtype=config.weights["model.layers.0.self_attn.k_proj.weight"].dtype,
dtype=config.model.layers[0].attn.k.weight.dtype,
) # (batch_size, n_kv_groups, seq_len, head_dim)
for _ in range(config.n_layers)
]
Expand All @@ -96,7 +101,7 @@ def reset_kv_cache(self, config):
config.n_kv_groups,
0,
config.head_dim,
dtype=config.weights["model.layers.0.self_attn.v_proj.weight"].dtype,
dtype=config.model.layers[0].attn.v.weight.dtype,
) # (batch_size, n_kv_groups, seq_len, head_dim)
for _ in range(config.n_layers)
]
Expand Down
Loading
Loading