mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
126 lines
3.9 KiB
Python
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()
|