Research-Stack/5-Applications/scripts/burgers_avm_trace_generator.py

126 lines
3.9 KiB
Python

#!/usr/bin/env python3
"""
burgers_avm_trace_generator.py
==============================
Generates bit-exact execution traces for the Burgers AVM kernels
(nuEffProgram and qEffProgram). These traces are used for
hardware loopback verification on the Tang Nano 9K.
"""
import json
from pathlib import Path
# OpCodes from AVM.lean
OP_PUSH = 0x01
OP_ADD = 0x02
OP_MUL = 0x03
OP_SUB = 0x04
OP_DIV = 0x05
OP_SQRT = 0x06
OP_HALT = 0xFF
class AVMSimulator:
def __init__(self):
self.stack = []
self.pc = 0
self.trace = []
def execute(self, program: list, initial_stack: list):
self.stack = initial_stack.copy()
self.pc = 0
self.trace = []
while self.pc < len(program):
op = program[self.pc]
self.pc += 1
if op == OP_PUSH:
val = program[self.pc]
self.pc += 1
self.stack.append(val)
self.trace.append({"op": "PUSH", "val": val, "stack": self.stack.copy()})
elif op == OP_ADD:
b = self.stack.pop()
a = self.stack.pop()
res = self.saturating_add(a, b)
self.stack.append(res)
self.trace.append({"op": "ADD", "res": res, "stack": self.stack.copy()})
elif op == OP_MUL:
b = self.stack.pop()
a = self.stack.pop()
# (a * b) >>> 16
res = (a * b) >> 16
# Mask to 32-bit (simplified for trace)
res &= 0xFFFFFFFF
self.stack.append(res)
self.trace.append({"op": "MUL", "res": res, "stack": self.stack.copy()})
elif op == OP_SUB:
b = self.stack.pop()
a = self.stack.pop()
res = self.saturating_sub(a, b)
self.stack.append(res)
self.trace.append({"op": "SUB", "res": res, "stack": self.stack.copy()})
elif op == OP_HALT:
self.trace.append({"op": "HALT", "stack": self.stack.copy()})
break
return self.stack, self.trace
def saturating_add(self, a, b):
res = a + b
if res > 0x7FFFFFFF: return 0x7FFFFFFF
if res < -0x80000000: return -0x80000000
return res
def saturating_sub(self, a, b):
res = a - b
if res > 0x7FFFFFFF: return 0x7FFFFFFF
if res < -0x80000000: return -0x80000000
return res
def generate_traces():
# Programs from BurgersAVM.lean
# nuEffProgram: [PUSH, 1.0, ADD, MUL, HALT]
# In Q16.16, 1.0 = 0x00010000
nu_eff_prog = [OP_PUSH, 0x00010000, OP_ADD, OP_MUL, OP_HALT]
# qEffProgram: [PUSH, kappa, MUL, PUSH, 1.0, ADD, MUL, HALT]
# kappa = 0.3547 * 65536 = 23245 = 0x00005ACE
q_eff_prog = [OP_PUSH, 0x00005ACE, OP_MUL, OP_PUSH, 0x00010000, OP_ADD, OP_MUL, OP_HALT]
sim = AVMSimulator()
# Inputs for 3-mode toy (Omega = 0.725 = 47513 = 0x0000B999)
# nu_0 = 0.1 = 6554 = 0x0000199A
# Q_0 = 1.0 = 65536 = 0x00010000
omega = 47513
nu0 = 6554
q0 = 65536
print("Generating nu_eff trace...")
res_nu, trace_nu = sim.execute(nu_eff_prog, [nu0, omega])
print("Generating Q_eff trace...")
res_q, trace_q = sim.execute(q_eff_prog, [q0, omega])
bundle = {
"nu_eff": {
"inputs": {"nu0": nu0, "omega": omega},
"program": nu_eff_prog,
"trace": trace_nu,
"final_result": res_nu[0]
},
"q_eff": {
"inputs": {"q0": q0, "omega": omega},
"program": q_eff_prog,
"trace": trace_q,
"final_result": res_q[0]
}
}
out_file = Path("/home/allaun/Documents/Research Stack/shared-data/burgers_avm_gold_traces.json")
out_file.write_text(json.dumps(bundle, indent=2))
print(f"Traces saved to {out_file}")
if __name__ == "__main__":
generate_traces()