From b6281dd91c1c16f356debde73a8628a5b21e8403 Mon Sep 17 00:00:00 2001 From: TlatoaniHJ Date: Thu, 19 Dec 2024 19:18:42 -0500 Subject: [PATCH] Commit --- Cargo.lock | 39 +++ Cargo.toml | 6 + benchmarks/Cargo.toml | 1 + .../programs/test_kernel/.cargo/config.toml | 10 + benchmarks/programs/test_kernel/Cargo.toml | 13 + .../programs/test_kernel/instructions.txt | 20 ++ .../programs/test_kernel/macro_output.txt | 235 +++++++++++++ benchmarks/programs/test_kernel/src/main.rs | 257 +++++++++++++++ benchmarks/src/bin/test_kernel.rs | 99 ++++++ crates/toolchain/edsl-deserialize/Cargo.toml | 30 ++ .../edsl-deserialize/src/castf_extension.rs | 56 ++++ .../toolchain/edsl-deserialize/src/config.rs | 44 +++ .../src/deserialize_instruction.rs | 54 +++ crates/toolchain/edsl-deserialize/src/lib.rs | 8 + crates/toolchain/edsl-kernel/Cargo.toml | 25 ++ crates/toolchain/edsl-kernel/src/execute.rs | 53 +++ .../edsl-kernel/src/generate_edsl.rs | 98 ++++++ crates/toolchain/edsl-kernel/src/lib.rs | 39 +++ crates/toolchain/edsl-kernel/src/main.rs | 55 ++++ .../edsl-kernel/src/parse_compiler_output.rs | 78 +++++ .../toolchain/edsl-kernel/src/parse_kernel.rs | 77 +++++ .../edsl-kernel/src/transportation.rs | 309 ++++++++++++++++++ crates/toolchain/instructions/src/program.rs | 23 +- crates/toolchain/transpiler/src/extension.rs | 30 +- crates/toolchain/transpiler/src/lib.rs | 4 +- crates/toolchain/transpiler/src/transpiler.rs | 27 +- crates/vm/src/arch/segment.rs | 2 + extensions/algebra/transpiler/src/lib.rs | 10 +- extensions/bigint/transpiler/src/lib.rs | 6 +- extensions/ecc/transpiler/src/lib.rs | 21 +- extensions/keccak256/transpiler/src/lib.rs | 6 +- extensions/native/circuit/src/castf/core.rs | 2 + .../circuit/src/field_arithmetic/core.rs | 1 + .../native/compiler/src/conversion/mod.rs | 3 +- extensions/pairing/transpiler/src/lib.rs | 25 +- extensions/rv32im/transpiler/src/lib.rs | 18 +- 36 files changed, 1725 insertions(+), 59 deletions(-) create mode 100644 benchmarks/programs/test_kernel/.cargo/config.toml create mode 100644 benchmarks/programs/test_kernel/Cargo.toml create mode 100644 benchmarks/programs/test_kernel/instructions.txt create mode 100644 benchmarks/programs/test_kernel/macro_output.txt create mode 100644 benchmarks/programs/test_kernel/src/main.rs create mode 100644 benchmarks/src/bin/test_kernel.rs create mode 100644 crates/toolchain/edsl-deserialize/Cargo.toml create mode 100644 crates/toolchain/edsl-deserialize/src/castf_extension.rs create mode 100644 crates/toolchain/edsl-deserialize/src/config.rs create mode 100644 crates/toolchain/edsl-deserialize/src/deserialize_instruction.rs create mode 100644 crates/toolchain/edsl-deserialize/src/lib.rs create mode 100644 crates/toolchain/edsl-kernel/Cargo.toml create mode 100644 crates/toolchain/edsl-kernel/src/execute.rs create mode 100644 crates/toolchain/edsl-kernel/src/generate_edsl.rs create mode 100644 crates/toolchain/edsl-kernel/src/lib.rs create mode 100644 crates/toolchain/edsl-kernel/src/main.rs create mode 100644 crates/toolchain/edsl-kernel/src/parse_compiler_output.rs create mode 100644 crates/toolchain/edsl-kernel/src/parse_kernel.rs create mode 100644 crates/toolchain/edsl-kernel/src/transportation.rs diff --git a/Cargo.lock b/Cargo.lock index 6763958aa1..95ea222799 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3508,6 +3508,7 @@ dependencies = [ "openvm-circuit-primitives-derive", "openvm-ecc-circuit", "openvm-ecc-transpiler", + "openvm-edsl-deserialize", "openvm-keccak256-circuit", "openvm-keccak256-guest", "openvm-keccak256-transpiler", @@ -3822,6 +3823,44 @@ dependencies = [ "strum", ] +[[package]] +name = "openvm-edsl-deserialize" +version = "0.1.0-alpha" +dependencies = [ + "derive-new", + "derive_more 1.0.0", + "openvm-circuit", + "openvm-circuit-derive", + "openvm-circuit-primitives-derive", + "openvm-instructions", + "openvm-native-circuit", + "openvm-native-compiler", + "openvm-rv32im-circuit", + "openvm-stark-backend", + "openvm-transpiler", + "p3-baby-bear", + "p3-field", + "serde", + "strum", + "strum_macros", +] + +[[package]] +name = "openvm-edsl-kernel" +version = "0.1.0-alpha" +dependencies = [ + "openvm-instructions", + "openvm-native-compiler", + "openvm-stark-backend", + "p3-baby-bear", + "p3-field", + "proc-macro2", + "quote", + "strum", + "strum_macros", + "syn 2.0.90", +] + [[package]] name = "openvm-instructions" version = "0.1.0-alpha" diff --git a/Cargo.toml b/Cargo.toml index 720e26efde..3a95de160a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,8 @@ members = [ "crates/toolchain/transpiler", "crates/toolchain/openvm", "crates/toolchain/build", + "crates/toolchain/edsl-deserialize", + "crates/toolchain/edsl-kernel", "crates/toolchain/instructions", "crates/toolchain/instructions/derive", "crates/toolchain/macros", @@ -115,6 +117,10 @@ openvm-circuit-derive = { path = "crates/vm/derive", default-features = false } openvm-stark-backend = { git = "https://github.com/openvm-org/stark-backend.git", tag = "v0.1.1-alpha", default-features = false } openvm-stark-sdk = { git = "https://github.com/openvm-org/stark-backend.git", tag = "v0.1.1-alpha", default-features = false } +# eDSL Kernel +openvm-edsl-kernel = { path = "crates/toolchain/edsl-kernel", default-features = false } +openvm-edsl-deserialize = { path = "crates/toolchain/edsl-deserialize", default-features = false } + # Extensions openvm-algebra-circuit = { path = "extensions/algebra/circuit", default-features = false } openvm-algebra-transpiler = { path = "extensions/algebra/transpiler", default-features = false } diff --git a/benchmarks/Cargo.toml b/benchmarks/Cargo.toml index b90d657548..41fa0dcf5b 100644 --- a/benchmarks/Cargo.toml +++ b/benchmarks/Cargo.toml @@ -15,6 +15,7 @@ openvm-sdk.workspace = true openvm-stark-backend.workspace = true openvm-stark-sdk.workspace = true openvm-transpiler.workspace = true +openvm-edsl-deserialize.workspace = true openvm-algebra-circuit.workspace = true openvm-algebra-transpiler.workspace = true diff --git a/benchmarks/programs/test_kernel/.cargo/config.toml b/benchmarks/programs/test_kernel/.cargo/config.toml new file mode 100644 index 0000000000..9f22c1345e --- /dev/null +++ b/benchmarks/programs/test_kernel/.cargo/config.toml @@ -0,0 +1,10 @@ +# Uncomment to build for openvm +# [build] +# target = "riscv32im-risc0-zkvm-elf" + +# [target.riscv32im-risc0-zkvm-elf] +# rustflags = ["-C", "passes=lower-atomic", "-C", "link-arg=-Ttext=0x002008000"] + +# [unstable] +# build-std = ["core", "alloc", "proc_macro", "panic_abort", "std"] +# build-std-features = ["compiler-builtins-mem"] \ No newline at end of file diff --git a/benchmarks/programs/test_kernel/Cargo.toml b/benchmarks/programs/test_kernel/Cargo.toml new file mode 100644 index 0000000000..3287245c0e --- /dev/null +++ b/benchmarks/programs/test_kernel/Cargo.toml @@ -0,0 +1,13 @@ +[workspace] +[package] +name = "test_kernel" +version = "0.0.0" +edition = "2021" + +[dependencies] +openvm = { path = "../../../crates/toolchain/openvm" } +openvm-edsl-kernel = { path = "../../../crates/toolchain/edsl-kernel" } + +[features] +default = [] +std = ["openvm/std"] diff --git a/benchmarks/programs/test_kernel/instructions.txt b/benchmarks/programs/test_kernel/instructions.txt new file mode 100644 index 0000000000..b4c3e9c25a --- /dev/null +++ b/benchmarks/programs/test_kernel/instructions.txt @@ -0,0 +1,20 @@ +MacroInstruction { opcode: VmOpcode(304), operands: [Literal(16777148), Literal(0), Variable("var_foo", 3), Literal(5), Literal(0), Literal(1)] } +MacroInstruction { opcode: VmOpcode(306), operands: [Literal(16777148), Literal(16777148), Literal(256), Literal(5), Literal(5), Literal(0)] } +MacroInstruction { opcode: VmOpcode(304), operands: [Literal(16777148), Literal(16777148), Variable("var_foo", 2), Literal(5), Literal(5), Literal(1)] } +MacroInstruction { opcode: VmOpcode(306), operands: [Literal(16777148), Literal(16777148), Literal(256), Literal(5), Literal(5), Literal(0)] } +MacroInstruction { opcode: VmOpcode(304), operands: [Literal(16777148), Literal(16777148), Variable("var_foo", 1), Literal(5), Literal(5), Literal(1)] } +MacroInstruction { opcode: VmOpcode(306), operands: [Literal(16777148), Literal(16777148), Literal(256), Literal(5), Literal(5), Literal(0)] } +MacroInstruction { opcode: VmOpcode(304), operands: [Literal(16777148), Literal(16777148), Variable("var_foo", 0), Literal(5), Literal(5), Literal(1)] } +MacroInstruction { opcode: VmOpcode(304), operands: [Literal(16777141), Literal(0), Variable("var_bar", 3), Literal(5), Literal(0), Literal(1)] } +MacroInstruction { opcode: VmOpcode(306), operands: [Literal(16777141), Literal(16777141), Literal(256), Literal(5), Literal(5), Literal(0)] } +MacroInstruction { opcode: VmOpcode(304), operands: [Literal(16777141), Literal(16777141), Variable("var_bar", 2), Literal(5), Literal(5), Literal(1)] } +MacroInstruction { opcode: VmOpcode(306), operands: [Literal(16777141), Literal(16777141), Literal(256), Literal(5), Literal(5), Literal(0)] } +MacroInstruction { opcode: VmOpcode(304), operands: [Literal(16777141), Literal(16777141), Variable("var_bar", 1), Literal(5), Literal(5), Literal(1)] } +MacroInstruction { opcode: VmOpcode(306), operands: [Literal(16777141), Literal(16777141), Literal(256), Literal(5), Literal(5), Literal(0)] } +MacroInstruction { opcode: VmOpcode(304), operands: [Literal(16777141), Literal(16777141), Variable("var_bar", 0), Literal(5), Literal(5), Literal(1)] } +MacroInstruction { opcode: VmOpcode(257), operands: [Literal(0), Literal(0), Literal(0), Literal(0), Literal(5), Literal(0), Literal(0)] } +MacroInstruction { opcode: VmOpcode(257), operands: [Literal(16777216), Literal(0), Literal(16777212), Literal(0), Literal(5), Literal(0), Literal(0)] } +MacroInstruction { opcode: VmOpcode(277), operands: [Literal(16777208), Literal(8), Literal(0), Literal(5), Literal(0), Literal(0), Literal(0)] } +MacroInstruction { opcode: VmOpcode(1), operands: [Literal(0), Literal(0), Literal(1), Literal(0), Literal(0), Literal(0), Literal(0)] } +MacroInstruction { opcode: VmOpcode(304), operands: [Literal(16777140), Literal(16777148), Literal(16777141), Literal(5), Literal(5), Literal(5), Literal(0)] } +MacroInstruction { opcode: VmOpcode(293), operands: [Variable("result", 0), Literal(16777140), Literal(0), Literal(1), Literal(5)] } diff --git a/benchmarks/programs/test_kernel/macro_output.txt b/benchmarks/programs/test_kernel/macro_output.txt new file mode 100644 index 0000000000..8f0637b957 --- /dev/null +++ b/benchmarks/programs/test_kernel/macro_output.txt @@ -0,0 +1,235 @@ +fn function_name(var_foo: usize, var_bar: usize, ) -> usize { + let result: usize; + unsafe { + core::arch::asm!( + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 48, 0, x2, x0, 0", + ".insn i 60, 7, x31, x31, 15", + ".insn i 0, 0, x0, x0, 0", + ".insn i 116, 0, x0, x0, -2048", + ".insn i 0, 0, {var_foo}, x0, 3", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 50, 0, x2, x0, 0", + ".insn i 60, 7, x31, x31, 15", + ".insn i 60, 7, x31, x31, 15", + ".insn i 0, 0, x2, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 48, 0, x2, x0, 0", + ".insn i 60, 7, x31, x31, 15", + ".insn i 60, 7, x31, x31, 15", + ".insn i 116, 0, x0, x0, -2048", + ".insn i 0, 0, {var_foo}, x0, 2", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 50, 0, x2, x0, 0", + ".insn i 60, 7, x31, x31, 15", + ".insn i 60, 7, x31, x31, 15", + ".insn i 0, 0, x2, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 48, 0, x2, x0, 0", + ".insn i 60, 7, x31, x31, 15", + ".insn i 60, 7, x31, x31, 15", + ".insn i 116, 0, x0, x0, -2048", + ".insn i 0, 0, {var_foo}, x0, 1", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 50, 0, x2, x0, 0", + ".insn i 60, 7, x31, x31, 15", + ".insn i 60, 7, x31, x31, 15", + ".insn i 0, 0, x2, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 48, 0, x2, x0, 0", + ".insn i 60, 7, x31, x31, 15", + ".insn i 60, 7, x31, x31, 15", + ".insn i 116, 0, x0, x0, -2048", + ".insn i 0, 0, {var_foo}, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 48, 0, x2, x0, 0", + ".insn i 53, 7, x31, x31, 15", + ".insn i 0, 0, x0, x0, 0", + ".insn i 116, 0, x0, x0, -2048", + ".insn i 0, 0, {var_bar}, x0, 3", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 50, 0, x2, x0, 0", + ".insn i 53, 7, x31, x31, 15", + ".insn i 53, 7, x31, x31, 15", + ".insn i 0, 0, x2, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 48, 0, x2, x0, 0", + ".insn i 53, 7, x31, x31, 15", + ".insn i 53, 7, x31, x31, 15", + ".insn i 116, 0, x0, x0, -2048", + ".insn i 0, 0, {var_bar}, x0, 2", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 50, 0, x2, x0, 0", + ".insn i 53, 7, x31, x31, 15", + ".insn i 53, 7, x31, x31, 15", + ".insn i 0, 0, x2, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 48, 0, x2, x0, 0", + ".insn i 53, 7, x31, x31, 15", + ".insn i 53, 7, x31, x31, 15", + ".insn i 116, 0, x0, x0, -2048", + ".insn i 0, 0, {var_bar}, x0, 1", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 50, 0, x2, x0, 0", + ".insn i 53, 7, x31, x31, 15", + ".insn i 53, 7, x31, x31, 15", + ".insn i 0, 0, x2, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 48, 0, x2, x0, 0", + ".insn i 53, 7, x31, x31, 15", + ".insn i 53, 7, x31, x31, 15", + ".insn i 116, 0, x0, x0, -2048", + ".insn i 0, 0, {var_bar}, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 7, 0, x0, x0, 0", + ".insn i 1, 0, x2, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 7, 0, x0, x0, 0", + ".insn i 1, 0, x2, x0, 0", + ".insn i 0, 0, x0, x0, 16", + ".insn i 0, 0, x0, x0, 0", + ".insn i 124, 7, x31, x31, 15", + ".insn i 0, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 7, 0, x0, x0, 0", + ".insn i 21, 0, x2, x0, 0", + ".insn i 120, 7, x31, x31, 15", + ".insn i 8, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 7, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 7, 0, x0, x0, 0", + ".insn i 48, 0, x2, x0, 0", + ".insn i 52, 7, x31, x31, 15", + ".insn i 60, 7, x31, x31, 15", + ".insn i 53, 7, x31, x31, 15", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 5, 0, x0, x0, 0", + ".insn i 37, 0, x2, x0, 0", + ".insn i 116, 0, x0, x0, -2048", + ".insn i 0, 0, {result}, x0, 0", + ".insn i 52, 7, x31, x31, 15", + ".insn i 0, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 4, 0, x0, x0, 0", + ".insn i 21, 0, x2, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 88, 0, x5, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + + ".insn i 25, 7, x16, x27, -1941", + ".insn i 53, 0, x1, x0, 0", + + var_foo = in(reg) var_foo, + var_bar = in(reg) var_bar, + result = out(reg) result, + ) + } + result +} diff --git a/benchmarks/programs/test_kernel/src/main.rs b/benchmarks/programs/test_kernel/src/main.rs new file mode 100644 index 0000000000..27e3a08638 --- /dev/null +++ b/benchmarks/programs/test_kernel/src/main.rs @@ -0,0 +1,257 @@ +#![cfg_attr(not(feature = "std"), no_main)] +#![cfg_attr(not(feature = "std"), no_std)] + +/*openvm_edsl_kernel::edsl_kernel! { + fn function_name(foo: usize | Felt, bar: usize | Felt) -> usize | Felt { + return builder.eval(foo + bar); + } +}*/ + +fn function_name(var_foo: usize, var_bar: usize, ) -> usize { + let result: usize; + unsafe { + core::arch::asm!( + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 48, 0, x2, x0, 0", + ".insn i 60, 7, x31, x31, 15", + ".insn i 0, 0, x0, x0, 0", + ".insn i 116, 0, x0, x0, -2048", + ".insn i 0, 0, {var_foo}, x0, 3", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 50, 0, x2, x0, 0", + ".insn i 60, 7, x31, x31, 15", + ".insn i 60, 7, x31, x31, 15", + ".insn i 0, 0, x2, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 48, 0, x2, x0, 0", + ".insn i 60, 7, x31, x31, 15", + ".insn i 60, 7, x31, x31, 15", + ".insn i 116, 0, x0, x0, -2048", + ".insn i 0, 0, {var_foo}, x0, 2", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 50, 0, x2, x0, 0", + ".insn i 60, 7, x31, x31, 15", + ".insn i 60, 7, x31, x31, 15", + ".insn i 0, 0, x2, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 48, 0, x2, x0, 0", + ".insn i 60, 7, x31, x31, 15", + ".insn i 60, 7, x31, x31, 15", + ".insn i 116, 0, x0, x0, -2048", + ".insn i 0, 0, {var_foo}, x0, 1", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 50, 0, x2, x0, 0", + ".insn i 60, 7, x31, x31, 15", + ".insn i 60, 7, x31, x31, 15", + ".insn i 0, 0, x2, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 48, 0, x2, x0, 0", + ".insn i 60, 7, x31, x31, 15", + ".insn i 60, 7, x31, x31, 15", + ".insn i 116, 0, x0, x0, -2048", + ".insn i 0, 0, {var_foo}, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 48, 0, x2, x0, 0", + ".insn i 53, 7, x31, x31, 15", + ".insn i 0, 0, x0, x0, 0", + ".insn i 116, 0, x0, x0, -2048", + ".insn i 0, 0, {var_bar}, x0, 3", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 50, 0, x2, x0, 0", + ".insn i 53, 7, x31, x31, 15", + ".insn i 53, 7, x31, x31, 15", + ".insn i 0, 0, x2, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 48, 0, x2, x0, 0", + ".insn i 53, 7, x31, x31, 15", + ".insn i 53, 7, x31, x31, 15", + ".insn i 116, 0, x0, x0, -2048", + ".insn i 0, 0, {var_bar}, x0, 2", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 50, 0, x2, x0, 0", + ".insn i 53, 7, x31, x31, 15", + ".insn i 53, 7, x31, x31, 15", + ".insn i 0, 0, x2, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 48, 0, x2, x0, 0", + ".insn i 53, 7, x31, x31, 15", + ".insn i 53, 7, x31, x31, 15", + ".insn i 116, 0, x0, x0, -2048", + ".insn i 0, 0, {var_bar}, x0, 1", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 50, 0, x2, x0, 0", + ".insn i 53, 7, x31, x31, 15", + ".insn i 53, 7, x31, x31, 15", + ".insn i 0, 0, x2, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 6, 0, x0, x0, 0", + ".insn i 48, 0, x2, x0, 0", + ".insn i 53, 7, x31, x31, 15", + ".insn i 53, 7, x31, x31, 15", + ".insn i 116, 0, x0, x0, -2048", + ".insn i 0, 0, {var_bar}, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 7, 0, x0, x0, 0", + ".insn i 1, 0, x2, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 7, 0, x0, x0, 0", + ".insn i 1, 0, x2, x0, 0", + ".insn i 0, 0, x0, x0, 16", + ".insn i 0, 0, x0, x0, 0", + ".insn i 124, 7, x31, x31, 15", + ".insn i 0, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 7, 0, x0, x0, 0", + ".insn i 21, 0, x2, x0, 0", + ".insn i 120, 7, x31, x31, 15", + ".insn i 8, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 7, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 7, 0, x0, x0, 0", + ".insn i 48, 0, x2, x0, 0", + ".insn i 52, 7, x31, x31, 15", + ".insn i 60, 7, x31, x31, 15", + ".insn i 53, 7, x31, x31, 15", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + ".insn i 0, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 5, 0, x0, x0, 0", + ".insn i 37, 0, x2, x0, 0", + ".insn i 116, 0, x0, x0, -2048", + ".insn i 0, 0, {result}, x0, 0", + ".insn i 52, 7, x31, x31, 15", + ".insn i 0, 0, x0, x0, 0", + ".insn i 1, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + + ".insn i 107, 0, x8, x25, -1939", + ".insn i 4, 0, x0, x0, 0", + ".insn i 21, 0, x2, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 88, 0, x5, x0, 0", + ".insn i 0, 0, x0, x0, 0", + ".insn i 5, 0, x0, x0, 0", + + ".insn i 25, 7, x16, x27, -1941", + ".insn i 53, 0, x1, x0, 0", + + var_foo = in(reg) var_foo, + var_bar = in(reg) var_bar, + result = out(reg) result, + ) + } + result +} + + +openvm::entry!(main); + +fn main() { + let x = 333; + let y = 444; + let z = function_name(x, y); + if z != 777 { + panic!(); + } + //println!("Hello, world!"); +} diff --git a/benchmarks/src/bin/test_kernel.rs b/benchmarks/src/bin/test_kernel.rs new file mode 100644 index 0000000000..79a787fc75 --- /dev/null +++ b/benchmarks/src/bin/test_kernel.rs @@ -0,0 +1,99 @@ +#![allow(unused_variables)] +#![allow(unused_imports)] + +use clap::Parser; +use eyre::Result; +use openvm_benchmarks::utils::{bench_from_exe, build_bench_program, BenchmarkCli}; +use openvm_circuit::arch::{instructions::exe::VmExe, VmConfig}; +use openvm_edsl_deserialize::{ + config::Rv32WithKernelsConfig, deserialize_instruction::LongFormTranspilerExtension, +}; +use openvm_rv32im_transpiler::{ + Rv32ITranspilerExtension, Rv32IoTranspilerExtension, Rv32MTranspilerExtension, +}; +use openvm_sdk::{config::AppConfig, StdIn}; +use openvm_stark_sdk::{ + config::{ + baby_bear_poseidon2::BabyBearPoseidon2Engine, + fri_params::standard_fri_params_with_100_bits_conjectured_security, FriParameters, + }, + engine::StarkFriEngine, + p3_baby_bear::BabyBear, +}; +use openvm_transpiler::{transpiler::Transpiler, FromElf}; + +fn main() -> Result<()> { + let cli_args = BenchmarkCli::parse(); + let app_log_blowup = cli_args.app_log_blowup.unwrap_or(2); + let agg_log_blowup = cli_args.agg_log_blowup.unwrap_or(2); + + let elf = build_bench_program("test_kernel")?; + let exe = VmExe::from_elf( + elf, + Transpiler::::default() + .with_extension(Rv32ITranspilerExtension) + .with_extension(Rv32MTranspilerExtension) + .with_extension(Rv32IoTranspilerExtension) + .with_extension(LongFormTranspilerExtension), + )?; + + let app_fri_params = standard_fri_params_with_100_bits_conjectured_security( + cli_args.app_log_blowup.unwrap_or(2), + ); + let app_config = AppConfig::new(app_fri_params, Rv32WithKernelsConfig::default()); + + bench_from_exe("test_kernel", app_config, exe, StdIn::default(), false)?; + + Ok(()) + + /*run_with_metric_collection("OUTPUT_PATH", || -> Result<()> { + let vdata = + info_span!("Base64 Json Program", group = "base64_json_program").in_scope(|| { + let engine = BabyBearPoseidon2Engine::new( + FriParameters::standard_with_100_bits_conjectured_security(app_log_blowup), + ); + + let data = include_str!("../../programs/base64_json/json_payload_encoded.txt"); + + let fe_bytes = data.to_owned().into_bytes(); + bench_from_exe( + engine, + Keccak256Rv32Config::default(), + exe, + StdIn::from_bytes(&fe_bytes), + ) + })?; + + #[cfg(feature = "aggregation")] + { + // Leaf aggregation: 1->1 proof "aggregation" + let max_constraint_degree = ((1 << agg_log_blowup) + 1).min(7); + let config = + NativeConfig::aggregation(DEFAULT_MAX_NUM_PUBLIC_VALUES, max_constraint_degree) + .with_continuations(); + let compiler_options = CompilerOptions { + enable_cycle_tracker: true, + ..Default::default() + }; + for (seg_idx, vdata) in vdata.into_iter().enumerate() { + info_span!( + "Leaf Aggregation", + group = "leaf_aggregation", + segment = seg_idx + ) + .in_scope(|| { + let (program, input_stream) = + build_verification_program(vdata, compiler_options); + let engine = BabyBearPoseidon2Engine::new( + FriParameters::standard_with_100_bits_conjectured_security(agg_log_blowup), + ); + bench_from_exe(engine, config.clone(), program, input_stream.into()) + .unwrap_or_else(|e| { + panic!("Leaf aggregation failed for segment {}: {e}", seg_idx) + }) + }); + } + } + Ok(()) + })*/ +} diff --git a/crates/toolchain/edsl-deserialize/Cargo.toml b/crates/toolchain/edsl-deserialize/Cargo.toml new file mode 100644 index 0000000000..3b865dc6eb --- /dev/null +++ b/crates/toolchain/edsl-deserialize/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "openvm-edsl-deserialize" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +authors.workspace = true +homepage.workspace = true +repository.workspace = true + +[dependencies] +openvm-instructions = { workspace = true } +openvm-native-compiler = { workspace = true } +openvm-transpiler = { workspace = true } +p3-field = { workspace = true } +p3-baby-bear = { workspace = true } +openvm-circuit-derive = { workspace = true } +openvm-rv32im-circuit = { workspace = true } +derive-new = { workspace = true } +openvm-circuit = { workspace = true } +openvm-native-circuit = { workspace = true } +derive_more = { workspace = true } +serde = { workspace = true } +strum = { workspace = true } +openvm-circuit-primitives-derive = { workspace = true } +openvm-stark-backend = { workspace = true } + +[dev-dependencies] +strum.workspace = true +strum_macros.workspace = true +openvm-instructions.workspace = true diff --git a/crates/toolchain/edsl-deserialize/src/castf_extension.rs b/crates/toolchain/edsl-deserialize/src/castf_extension.rs new file mode 100644 index 0000000000..ccc7a21e4a --- /dev/null +++ b/crates/toolchain/edsl-deserialize/src/castf_extension.rs @@ -0,0 +1,56 @@ +use derive_more::From; +use openvm_circuit::{ + arch::{SystemPort, VmExtension, VmInventory, VmInventoryBuilder, VmInventoryError}, + circuit_derive::{Chip, ChipUsageGetter}, +}; +use openvm_circuit_derive::{AnyEnum, InstructionExecutor}; +use openvm_instructions::{UsizeOpcode, VmOpcode}; +use openvm_native_circuit::{ + adapters::convert_adapter::ConvertAdapterChip, CastFChip, CastFCoreChip, +}; +use openvm_native_compiler::CastfOpcode; +use p3_field::PrimeField32; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)] +pub struct CastF; + +#[derive(ChipUsageGetter, Chip, InstructionExecutor, From, AnyEnum)] +pub enum CastFExecutor { + CastF(CastFChip), +} + +#[derive(From, ChipUsageGetter, Chip, AnyEnum)] +pub enum CastFPeriphery { + Placeholder(CastFChip), +} + +impl VmExtension for CastF { + type Executor = CastFExecutor; + type Periphery = CastFPeriphery; + + fn build( + &self, + builder: &mut VmInventoryBuilder, + ) -> Result, VmInventoryError> { + let mut inventory = VmInventory::new(); + let SystemPort { + execution_bus, + program_bus, + memory_controller, + } = builder.system_port(); + let range_checker = builder.system_base().range_checker_chip.clone(); + + let castf_chip = CastFChip::new( + ConvertAdapterChip::new(execution_bus, program_bus, memory_controller.clone()), + CastFCoreChip::new(range_checker.clone(), CastfOpcode::default_offset()), + memory_controller.clone(), + ); + inventory.add_executor( + castf_chip, + [VmOpcode::with_default_offset(CastfOpcode::CASTF)], + )?; + + Ok(inventory) + } +} diff --git a/crates/toolchain/edsl-deserialize/src/config.rs b/crates/toolchain/edsl-deserialize/src/config.rs new file mode 100644 index 0000000000..a3b17d1fe5 --- /dev/null +++ b/crates/toolchain/edsl-deserialize/src/config.rs @@ -0,0 +1,44 @@ +use derive_more::derive::From; +use openvm_circuit::arch::{ + SystemConfig, SystemExecutor, SystemPeriphery, VmChipComplex, VmConfig, VmInventoryError, +}; +use openvm_circuit_derive::{AnyEnum, InstructionExecutor, VmConfig}; +use openvm_circuit_primitives_derive::{Chip, ChipUsageGetter}; +use openvm_native_circuit::{Native, *}; +use openvm_rv32im_circuit::{ + Rv32I, Rv32IExecutor, Rv32IPeriphery, Rv32Io, Rv32IoExecutor, Rv32IoPeriphery, Rv32M, + Rv32MExecutor, Rv32MPeriphery, +}; +use p3_field::PrimeField32; +use serde::{Deserialize, Serialize}; + +use crate::castf_extension::{CastF, CastFExecutor, CastFPeriphery}; + +#[derive(Clone, Debug, VmConfig, derive_new::new, Serialize, Deserialize)] +pub struct Rv32WithKernelsConfig { + #[system] + pub system: SystemConfig, + #[extension] + pub rv32i: Rv32I, + #[extension] + pub rv32m: Rv32M, + #[extension] + pub io: Rv32Io, + #[extension] + pub native: Native, + #[extension] + pub castf: CastF, +} + +impl Default for Rv32WithKernelsConfig { + fn default() -> Self { + Self { + system: SystemConfig::default().with_continuations(), + rv32i: Rv32I, + rv32m: Rv32M::default(), + io: Rv32Io, + native: Native, + castf: CastF, + } + } +} diff --git a/crates/toolchain/edsl-deserialize/src/deserialize_instruction.rs b/crates/toolchain/edsl-deserialize/src/deserialize_instruction.rs new file mode 100644 index 0000000000..faaed2a85c --- /dev/null +++ b/crates/toolchain/edsl-deserialize/src/deserialize_instruction.rs @@ -0,0 +1,54 @@ +use openvm_instructions::{instruction::Instruction, VmOpcode}; +use openvm_transpiler::{TranspilerExtension, TranspilerOutput}; +use p3_field::PrimeField32; + +use crate::{ + GAP_INDICATOR, LONG_FORM_INSTRUCTION_INDICATOR, REGISTER_LIMBS, VARIABLE_REGISTER_INDICATOR, +}; + +pub struct LongFormTranspilerExtension; + +impl TranspilerExtension for LongFormTranspilerExtension { + fn process_custom(&self, instruction_stream: &[u32]) -> Option> { + if instruction_stream[0] == LONG_FORM_INSTRUCTION_INDICATOR { + let num_operands = instruction_stream[1] as usize; + let opcode = VmOpcode::from_usize(instruction_stream[2] as usize); + let mut operands = vec![]; + let mut j = 3; + for _ in 0..num_operands { + if instruction_stream[j] == VARIABLE_REGISTER_INDICATOR { + let register = (instruction_stream[j + 1] >> 7) & 0x1f; + let offset = instruction_stream[j + 1] >> 20; + let mut operand = (REGISTER_LIMBS * register) + offset; + if offset >= 1 << 12 { + operand -= 1 << 12; + } + operands.push(F::from_canonical_u32(operand)); + j += 2; + } else { + operands.push(F::from_canonical_u32(instruction_stream[j])); + j += 1; + } + } + while operands.len() < 7 { + operands.push(F::ZERO); + } + let instruction = Instruction { + opcode, + a: operands[0], + b: operands[1], + c: operands[2], + d: operands[3], + e: operands[4], + f: operands[5], + g: operands[6], + }; + println!("deserialized instruction = {:?}", instruction); + Some(TranspilerOutput::many_to_one(instruction, j)) + } else if instruction_stream[0] == GAP_INDICATOR { + Some(TranspilerOutput::gap(instruction_stream[1] as usize, 2)) + } else { + None + } + } +} diff --git a/crates/toolchain/edsl-deserialize/src/lib.rs b/crates/toolchain/edsl-deserialize/src/lib.rs new file mode 100644 index 0000000000..dcb8c51bd1 --- /dev/null +++ b/crates/toolchain/edsl-deserialize/src/lib.rs @@ -0,0 +1,8 @@ +mod castf_extension; +pub mod config; +pub mod deserialize_instruction; + +const LONG_FORM_INSTRUCTION_INDICATOR: u32 = (1 << 31) + 115115115; +const GAP_INDICATOR: u32 = (1 << 31) + 113113113; +const VARIABLE_REGISTER_INDICATOR: u32 = (1 << 31) + 116; +const REGISTER_LIMBS: u32 = 4; diff --git a/crates/toolchain/edsl-kernel/Cargo.toml b/crates/toolchain/edsl-kernel/Cargo.toml new file mode 100644 index 0000000000..c1be27d345 --- /dev/null +++ b/crates/toolchain/edsl-kernel/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "openvm-edsl-kernel" +version.workspace = true +authors.workspace = true +edition.workspace = true +homepage.workspace = true +repository.workspace = true + +[lib] +proc-macro = true + +[dependencies] +syn = { version = "2.0", features = ["parsing"] } +quote = "1.0" +proc-macro2 = "1.0" +openvm-instructions = { workspace = true } +openvm-native-compiler = { workspace = true } +p3-field = { workspace = true } +p3-baby-bear = { workspace = true } +openvm-stark-backend = { workspace = true } + +[dev-dependencies] +strum.workspace = true +strum_macros.workspace = true +openvm-instructions.workspace = true diff --git a/crates/toolchain/edsl-kernel/src/execute.rs b/crates/toolchain/edsl-kernel/src/execute.rs new file mode 100644 index 0000000000..5ec59d11a6 --- /dev/null +++ b/crates/toolchain/edsl-kernel/src/execute.rs @@ -0,0 +1,53 @@ +use std::{ + fs::{create_dir, remove_dir_all}, + io::{BufRead, BufReader, Error}, + path::Path, + process::Stdio, +}; + +const DIR_NAME: &str = "_edsl-kernel"; +const SRC_DIR_NAME: &str = "_edsl-kernel/src"; + +pub fn execute_edsl(source: String, config: String) -> Result { + let dir = Path::new(DIR_NAME); + let _ = remove_dir_all(dir); + + create_dir(dir)?; + let src_dir = Path::new(SRC_DIR_NAME); + create_dir(src_dir)?; + + let src_file = Path::new(SRC_DIR_NAME).join("main.rs"); + std::fs::write(src_file, source)?; + let config_file = Path::new(DIR_NAME).join("Cargo.toml"); + std::fs::write(config_file, config)?; + + let mut cmd = std::process::Command::new("cargo"); + + cmd.arg("run").current_dir(dir); + + let mut child = cmd + .stderr(Stdio::piped()) + .env("CARGO_TERM_COLOR", "always") + .spawn() + .expect("cargo build failed"); + let stderr = child.stderr.take().unwrap(); + for line in BufReader::new(stderr).lines() { + println!("edsl kernel macro: {}", line.unwrap()); + } + + let output = cmd.output(); + + let output = output?; + + let result = std::str::from_utf8(&output.stdout) + .expect("failed to convert output to string") + .to_string(); + + //let err = std::str::from_utf8(&output.stderr).expect("failed to convert stderr to string").to_string(); + + //let working_dir = std::env::current_dir().expect("failed to get current dir"); + + remove_dir_all(dir)?; + + Ok(result) +} diff --git a/crates/toolchain/edsl-kernel/src/generate_edsl.rs b/crates/toolchain/edsl-kernel/src/generate_edsl.rs new file mode 100644 index 0000000000..963e697086 --- /dev/null +++ b/crates/toolchain/edsl-kernel/src/generate_edsl.rs @@ -0,0 +1,98 @@ +use crate::parse_kernel::ParsedKernel; + +const MAIN_PLACEHOLDER: &str = "<...>"; +const OUTSIDE_PLACEHOLDER: &str = "<===>"; +const EDSL_TEMPLATE: &str = " +use openvm_native_compiler::{ + asm::{AsmBuilder, AsmCompiler}, + conversion::{convert_program, CompilerOptions}, + ir::{Array, Ext, Felt}, +}; +use p3_baby_bear::BabyBear; +use p3_field::{extension::BinomialExtensionField, AbstractField}; + +type F = BabyBear; +type EF = BinomialExtensionField; + +<===> + +fn main() { + let mut builder = AsmBuilder::::default(); + +<...> + + let mut compiler = AsmCompiler::new(1); + compiler.build(builder.operations); + let asm_code = compiler.code(); + let program = convert_program::(asm_code, CompilerOptions::default()); + println!(\"{}\", program);a stru +} +"; + +pub const CONFIG: &str = " +[package] +name = \"root\" +version = \"0.1.0\" +edition = \"2021\" + +[dependencies] +openvm-native-compiler = { path = \"../../../../extensions/native/compiler\" } +p3-field = { git = \"https://github.com/Plonky3/Plonky3.git\", rev = \"9b267c4\" } +p3-baby-bear = { git = \"https://github.com/Plonky3/Plonky3.git\", features = [ +\"nightly-features\", +], rev = \"9b267c4\" } + +[workspace] +"; + +fn produce_edsl_function(parsed_kernel: &ParsedKernel) -> String { + let mut result = String::new(); + + result.push_str("fn edsl_function(builder: &mut AsmBuilder"); + for argument in &parsed_kernel.arguments { + result.push_str(", "); + result.push_str(&argument.name); + result.push_str(": "); + result.push_str(&argument.edsl_type); + } + result.push_str(") -> "); + result.push_str(&parsed_kernel.edsl_return_type); + result.push_str(" {\n"); + result.push_str(&parsed_kernel.body); + result.push_str("\n}"); + + result +} + +fn produce_main_portion(parsed_kernel: &ParsedKernel) -> String { + let mut result = String::new(); + + for argument in &parsed_kernel.arguments { + result.push_str(&format!( + "\tlet var_{}: {} = builder.uninit();\n", + argument.name, argument.edsl_type + )); + result.push_str(&format!( + "\tprintln!(\"{{}}\", var_{}.fp());\n", + argument.name + )); + } + + result.push_str("\tlet result = edsl_function(&mut builder"); + for argument in &parsed_kernel.arguments { + result.push_str(&format!(", var_{}", argument.name)); + } + result.push_str(");\n"); + result.push_str("\tprintln!(\"{}\", result.fp());\n"); + + result +} + +pub fn produce_edsl_code(parsed_kernel: &ParsedKernel) -> String { + let mut result = EDSL_TEMPLATE.to_string(); + + result = result.replace(MAIN_PLACEHOLDER, &produce_main_portion(parsed_kernel)); + result = result.replace(OUTSIDE_PLACEHOLDER, &produce_edsl_function(parsed_kernel)); + + result +} diff --git a/crates/toolchain/edsl-kernel/src/lib.rs b/crates/toolchain/edsl-kernel/src/lib.rs new file mode 100644 index 0000000000..600069ab74 --- /dev/null +++ b/crates/toolchain/edsl-kernel/src/lib.rs @@ -0,0 +1,39 @@ +use p3_baby_bear::BabyBear; + +use crate::parse_compiler_output::CompiledKernel; + +mod execute; +mod generate_edsl; +mod parse_compiler_output; +mod parse_kernel; +mod transportation; + +const IMMEDIATE_ADDRESS_SPACE: usize = 0; +const RUST_REGISTER_ADDRESS_SPACE: usize = 1; +const KERNEL_ADDRESS_SPACE: usize = 5; +const LONG_FORM_INSTRUCTION_INDICATOR: u32 = (1 << 31) + 115115115; +const GAP_INDICATOR: u32 = (1 << 31) + 113113113; +const UTILITY_CELL: usize = 0; +const VARIABLE_REGISTER_INDICATOR: u32 = (1 << 31) + 116; +const PC_STEP: usize = 4; +const REGISTER_LIMBS: usize = 4; +const REGISTER_LIMB_SIZE: usize = 256; + +#[proc_macro] +pub fn edsl_kernel(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let input = proc_macro2::TokenStream::from(input); + + let parsed_kernel = parse_kernel::parse_raw_kernel(input); + let edsl_code = generate_edsl::produce_edsl_code(&parsed_kernel); + let config = generate_edsl::CONFIG.to_string(); + let compiler_output = execute::execute_edsl(edsl_code, config).unwrap(); + let compiled_kernel: CompiledKernel = + parse_compiler_output::parse_compiled_kernel(parsed_kernel, compiler_output); + let rust_function = transportation::compiled_kernel_to_function(compiled_kernel); + + std::fs::write("macro_output.txt", rust_function.clone()).unwrap(); + + let output: proc_macro2::TokenStream = rust_function.parse().unwrap(); + + proc_macro::TokenStream::from(output) +} diff --git a/crates/toolchain/edsl-kernel/src/main.rs b/crates/toolchain/edsl-kernel/src/main.rs new file mode 100644 index 0000000000..64a0954c2d --- /dev/null +++ b/crates/toolchain/edsl-kernel/src/main.rs @@ -0,0 +1,55 @@ +/*use axvm_edsl_kernel::{ + execute::execute_edsl, + generate_edsl::{produce_edsl_code, CONFIG}, + parse_compiler_output::{parse_compiled_kernel, CompiledKernel}, + parse_kernel::parse_raw_kernel, + transportation::compiled_kernel_to_function, +};*/ +use p3_baby_bear::BabyBear; +use quote::quote; + +pub fn main() { + //println!("Hello, world!"); + + /*let kernel_source = quote! { + fn function_name(foo: usize | Felt, bar: usize | Felt) -> usize | Felt { + return builder.eval(foo + bar); + } + }; + + let parsed_kernel = parse_raw_kernel(kernel_source); + + //println!("{:?}", parse_raw_kernel(kernel_source)); + + /*let parsed_kernel = ParsedKernel { + function_name: "function_name".to_string(), + arguments: vec![ + KernelArgument { + name: "foo".to_string(), + rust_type: "usize".to_string(), + edsl_type: "Felt".to_string(), + }, + KernelArgument { + name: "bar".to_string(), + rust_type: "usize".to_string(), + edsl_type: "Felt".to_string(), + }, + ], + body: " + return builder.eval(foo + bar); + ".to_string(), + rust_return_type: "usize".to_string(), + edsl_return_type: "Felt".to_string(), + };*/ + let edsl_code = produce_edsl_code(&parsed_kernel); + let config = CONFIG.to_string(); + let compiler_output = execute_edsl(edsl_code, config).unwrap(); + println!("compiler_output = {}", compiler_output); + + let compiled_kernel: CompiledKernel = + parse_compiled_kernel(parsed_kernel, compiler_output); + println!("compiled_kernel = {:?}", compiled_kernel); + + let rust_function = compiled_kernel_to_function(compiled_kernel); + println!("rust_function = {}", rust_function);*/ +} diff --git a/crates/toolchain/edsl-kernel/src/parse_compiler_output.rs b/crates/toolchain/edsl-kernel/src/parse_compiler_output.rs new file mode 100644 index 0000000000..05c2ea9ad5 --- /dev/null +++ b/crates/toolchain/edsl-kernel/src/parse_compiler_output.rs @@ -0,0 +1,78 @@ +use openvm_instructions::{instruction::Instruction, VmOpcode}; +use p3_field::Field; + +use crate::parse_kernel::ParsedKernel; + +#[derive(Debug)] +pub struct CompiledKernelArgument { + pub name: String, + pub rust_type: String, + pub edsl_type: String, + pub fp: usize, +} + +#[derive(Debug)] +pub struct CompiledKernel { + pub function_name: String, + pub arguments: Vec, + pub body: Vec>, + pub rust_return_type: String, + pub edsl_return_type: String, + pub return_fp: usize, +} + +pub fn parse_compiled_kernel( + parsed_kernel: ParsedKernel, + compiler_output: String, +) -> CompiledKernel { + let mut lines = compiler_output.lines(); + let arguments = parsed_kernel + .arguments + .into_iter() + .map(|argument| { + let name = argument.name; + let rust_type = argument.rust_type; + let edsl_type = argument.edsl_type; + let fp = lines.next().unwrap().parse::().unwrap(); + CompiledKernelArgument { + name, + rust_type, + edsl_type, + fp, + } + }) + .collect::>(); + let return_fp = lines.next().unwrap().parse::().unwrap(); + let instructions = lines + .filter(|line| !line.is_empty()) + .map(|line| { + let tokens = line.split_whitespace().collect::>(); + let opcode = tokens[0][tokens[0].find('(').unwrap() + 1..tokens[0].len() - 1] + .parse::() + .unwrap(); + let operands = tokens[1..] + .iter() + .map(|token| F::from_canonical_usize(token.parse::().unwrap())) + .collect::>(); + Instruction { + opcode: VmOpcode::from_usize(opcode), + a: operands[0], + b: operands[1], + c: operands[2], + d: operands[3], + e: operands[4], + f: operands[5], + g: operands[6], + } + }) + .collect(); + + CompiledKernel { + function_name: parsed_kernel.function_name, + arguments, + body: instructions, + rust_return_type: parsed_kernel.rust_return_type, + edsl_return_type: parsed_kernel.edsl_return_type, + return_fp, + } +} diff --git a/crates/toolchain/edsl-kernel/src/parse_kernel.rs b/crates/toolchain/edsl-kernel/src/parse_kernel.rs new file mode 100644 index 0000000000..04290aad32 --- /dev/null +++ b/crates/toolchain/edsl-kernel/src/parse_kernel.rs @@ -0,0 +1,77 @@ +use proc_macro2::{TokenStream, TokenTree}; + +#[derive(Debug)] +pub struct ParsedKernelArgument { + pub name: String, + pub rust_type: String, + pub edsl_type: String, +} + +#[derive(Debug)] +pub struct ParsedKernel { + pub function_name: String, + pub arguments: Vec, + pub body: String, + pub rust_return_type: String, + pub edsl_return_type: String, +} + +pub fn parse_raw_kernel(source: TokenStream) -> ParsedKernel { + let token_trees = source.into_iter().collect::>(); + + let function_name = match token_trees[1].clone() { + TokenTree::Ident(ident) => ident.to_string(), + _ => panic!("First token must be the function name"), + }; + + let arguments = match token_trees[2].clone() { + TokenTree::Group(group) => { + assert_eq!(group.delimiter(), proc_macro2::Delimiter::Parenthesis); + + let as_string = group.stream().to_string(); + let argument_strings = as_string + .split(',') + .map(|argument| argument.trim()) + .collect::>(); + + argument_strings + .into_iter() + .map(|argument_string| { + let colon_index = argument_string.find(':').unwrap(); + let bar_index = argument_string.find('|').unwrap(); + let name = argument_string[..colon_index].trim().to_string(); + let rust_type = argument_string[colon_index + 1..bar_index] + .trim() + .to_string(); + let edsl_type = argument_string[bar_index + 1..].trim().to_string(); + ParsedKernelArgument { + name, + rust_type, + edsl_type, + } + }) + .collect::>() + } + _ => panic!("Second token must be the list of arguments"), + }; + + let return_type_token_trees = token_trees[5..token_trees.len() - 1].to_vec(); + let return_type_stream = TokenStream::from_iter(return_type_token_trees); + let return_type_string = return_type_stream.to_string(); + let bar_index = return_type_string.find('|').unwrap(); + let rust_return_type = return_type_string[..bar_index].trim().to_string(); + let edsl_return_type = return_type_string[bar_index + 1..].trim().to_string(); + + let body = match token_trees[token_trees.len() - 1].clone() { + TokenTree::Group(group) => group.stream().to_string(), + _ => panic!("Last token must be the function body"), + }; + + ParsedKernel { + function_name, + arguments, + body, + rust_return_type, + edsl_return_type, + } +} diff --git a/crates/toolchain/edsl-kernel/src/transportation.rs b/crates/toolchain/edsl-kernel/src/transportation.rs new file mode 100644 index 0000000000..f790be8435 --- /dev/null +++ b/crates/toolchain/edsl-kernel/src/transportation.rs @@ -0,0 +1,309 @@ +use openvm_instructions::{instruction::Instruction, VmOpcode}; +use openvm_native_compiler::{CastfOpcode, FieldArithmeticOpcode, NativeJalOpcode}; +use p3_field::{Field, PrimeField32}; + +use crate::{ + parse_compiler_output::CompiledKernel, + transportation::Operand::{Literal, Variable}, + GAP_INDICATOR, IMMEDIATE_ADDRESS_SPACE, KERNEL_ADDRESS_SPACE, LONG_FORM_INSTRUCTION_INDICATOR, + PC_STEP, REGISTER_LIMBS, REGISTER_LIMB_SIZE, RUST_REGISTER_ADDRESS_SPACE, UTILITY_CELL, + VARIABLE_REGISTER_INDICATOR, +}; + +#[derive(Clone, Debug)] +pub enum Operand { + Literal(F), + Variable(String, usize), +} + +impl Operand { + pub fn usize(val: usize) -> Self { + Literal(F::from_canonical_usize(val)) + } + + pub fn whatever() -> Self { + Literal(F::ZERO) + } +} + +#[derive(Clone, Debug)] +pub struct MacroInstruction { + pub opcode: VmOpcode, + pub operands: Vec>, +} + +impl MacroInstruction { + fn literal(instruction: Instruction) -> Self { + Self { + opcode: instruction.opcode, + operands: vec![ + Literal(instruction.a), + Literal(instruction.b), + Literal(instruction.c), + Literal(instruction.d), + Literal(instruction.e), + Literal(instruction.f), + Literal(instruction.g), + ], + } + } + + fn new(opcode: VmOpcode, operands: [Operand; N]) -> Self { + Self { + opcode, + operands: operands.to_vec(), + } + } +} + +/* + +how things are going to go: + +transportation will provide some MacroInstructions + +the body will be converted to MacroInstructions + +MacroInstructions are converted to an asm! call + */ + +pub fn compiled_kernel_to_function(compiled_kernel: CompiledKernel) -> String { + let mut instructions = vec![]; + let mut input_vars = vec![]; + let return_name = "result".to_string(); + + let mut result = "fn ".to_string(); + result.push_str(&compiled_kernel.function_name); + result.push('('); + + for argument in compiled_kernel.arguments { + let var_name = "var_".to_string() + &argument.name; + result.push_str(&var_name); + result.push_str(": "); + result.push_str(&argument.rust_type); + result.push_str(", "); + + input_vars.push(var_name); + instructions.extend(transport_rust_to_edsl( + argument.rust_type, + argument.edsl_type, + "var_".to_string() + &argument.name, + argument.fp, + )); + } + result.push_str(") -> "); + result.push_str(&compiled_kernel.rust_return_type); + result.push_str(" {\n"); + + result.push_str("\tlet result: "); + result.push_str(&compiled_kernel.rust_return_type); + result.push_str(";\n"); + + instructions.extend( + compiled_kernel + .body + .into_iter() + .map(MacroInstruction::literal), + ); + instructions.extend(transport_edsl_to_rust( + compiled_kernel.rust_return_type, + compiled_kernel.edsl_return_type, + return_name.clone(), + compiled_kernel.return_fp, + )); + + let mut instructions_string = String::new(); + for instruction in instructions.iter() { + instructions_string.push_str(&format!("{:?}\n", instruction)); + } + std::fs::write("instructions.txt", instructions_string).expect("Failed to write file"); + + let asm_call = instructions_to_asm_call(instructions, input_vars, vec![return_name.clone()]); + result.push_str(&asm_call); + result.push('\t'); + result.push_str(&return_name); + result.push('\n'); + result.push_str("}\n"); + + result +} + +fn u32_to_directive(x: u32) -> String { + let opcode = x & 0b1111111; + let funct3 = (x >> 12) & 0b111; + let rd = (x >> 7) & 0b11111; + let rs1 = (x >> 15) & 0b11111; + let mut simm12 = (x >> 20) as i32; + if simm12 >= 1 << 11 { + simm12 -= 1 << 12; + } + format!( + ".insn i {}, {}, x{}, x{}, {}", + opcode, funct3, rd, rs1, simm12 + ) +} + +fn operand_to_directives(operand: Operand) -> Vec { + match operand { + Literal(x) => vec![u32_to_directive(x.as_canonical_u32())], + Variable(var, offset) => vec![ + u32_to_directive(VARIABLE_REGISTER_INDICATOR), + format!(".insn i 0, 0, {{{}}}, x0, {}", var, offset), + ], + } +} + +fn instruction_to_directives(instruction: MacroInstruction) -> Vec { + let mut directives = vec![]; + + directives.push(u32_to_directive(LONG_FORM_INSTRUCTION_INDICATOR)); + directives.push(u32_to_directive(instruction.operands.len() as u32)); + directives.push(u32_to_directive(instruction.opcode.as_usize() as u32)); + for operand in instruction.operands { + directives.extend(operand_to_directives(operand)); + } + + directives +} + +pub fn instructions_to_asm_call( + instructions: Vec>, + input_vars: Vec, + output_vars: Vec, +) -> String { + let mut result = String::new(); + result.push_str("\tunsafe {\n"); + result.push_str("\t\tcore::arch::asm!(\n"); + + let mut add_directives = |directives: Vec| { + for directive in directives { + result.push_str(&format!("\t\t\t\"{}\",\n", directive)); + } + result.push('\n'); + }; + + let mut pc_diff = 2; + for instruction in instructions { + let directives = instruction_to_directives(instruction); + pc_diff += directives.len() - 1; + add_directives(directives); + } + + let mut jal_instruction: MacroInstruction = MacroInstruction::new( + VmOpcode::with_default_offset(NativeJalOpcode::JAL), + [ + Operand::usize(UTILITY_CELL), + Operand::whatever(), + Operand::whatever(), + Operand::usize(KERNEL_ADDRESS_SPACE), + ], + ); + let jal_example_directives = instruction_to_directives(jal_instruction.clone()); + pc_diff += jal_example_directives.len() - 1; + + jal_instruction.operands[1] = Operand::usize(PC_STEP * (pc_diff + 1)); + add_directives(instruction_to_directives(jal_instruction)); + + add_directives(vec![ + u32_to_directive(GAP_INDICATOR), + u32_to_directive(pc_diff as u32), + ]); + + for input_var in input_vars { + result.push_str(&format!("\t\t\t{} = in(reg) {},\n", input_var, input_var)); + } + for output_var in output_vars { + result.push_str(&format!( + "\t\t\t{} = out(reg) {},\n", + output_var, output_var + )); + } + result.push_str("\t\t)\n"); + result.push_str("\t}\n"); + result +} + +pub fn transport_rust_to_edsl( + rust_type: String, + edsl_type: String, + rust_name: String, + edsl_fp: usize, +) -> Vec> { + match (rust_type.as_str(), edsl_type.as_str()) { + ("usize", "Felt") => transport_usize_to_felt(rust_name, edsl_fp), + _ => panic!( + "Unsupported conversion from rust type {:?} to edsl type {:?}", + rust_type, edsl_type + ), + } +} + +fn transport_usize_to_felt( + rust_name: String, + edsl_fp: usize, +) -> Vec> { + let mut result = vec![]; + for i in (0..REGISTER_LIMBS).rev() { + // add [{rust_name} + i] to [edsl_fp] + result.push(MacroInstruction::new( + VmOpcode::with_default_offset(FieldArithmeticOpcode::ADD), + [ + Operand::usize(edsl_fp), + Operand::usize(if i == REGISTER_LIMBS - 1 { 0 } else { edsl_fp }), + Variable(rust_name.clone(), i), + Operand::usize(KERNEL_ADDRESS_SPACE), + Operand::usize(if i == REGISTER_LIMBS - 1 { + IMMEDIATE_ADDRESS_SPACE + } else { + KERNEL_ADDRESS_SPACE + }), + Operand::usize(RUST_REGISTER_ADDRESS_SPACE), + ], + )); + if i > 0 { + result.push(MacroInstruction::new( + VmOpcode::with_default_offset(FieldArithmeticOpcode::MUL), + [ + Operand::usize(edsl_fp), + Operand::usize(edsl_fp), + Operand::usize(REGISTER_LIMB_SIZE), + Operand::usize(KERNEL_ADDRESS_SPACE), + Operand::usize(KERNEL_ADDRESS_SPACE), + Operand::usize(IMMEDIATE_ADDRESS_SPACE), + ], + )); + } + } + result +} + +pub fn transport_edsl_to_rust( + rust_type: String, + edsl_type: String, + rust_name: String, + edsl_fp: usize, +) -> Vec> { + match (rust_type.as_str(), edsl_type.as_str()) { + ("usize", "Felt < F >") => transport_felt_to_usize(rust_name, edsl_fp), + _ => panic!( + "Unsupported conversion from edsl type {:?} to rust type {:?}", + edsl_type, rust_type, + ), + } +} + +fn transport_felt_to_usize( + rust_name: String, + edsl_fp: usize, +) -> Vec> { + vec![MacroInstruction::new( + VmOpcode::with_default_offset(CastfOpcode::CASTF), + [ + Variable(rust_name, 0), + Operand::usize(edsl_fp), + Operand::usize(0), + Operand::usize(RUST_REGISTER_ADDRESS_SPACE), + Operand::usize(KERNEL_ADDRESS_SPACE), + ], + )] +} diff --git a/crates/toolchain/instructions/src/program.rs b/crates/toolchain/instructions/src/program.rs index 20299395a6..7c62a3bb5d 100644 --- a/crates/toolchain/instructions/src/program.rs +++ b/crates/toolchain/instructions/src/program.rs @@ -58,6 +58,27 @@ impl Program { } } + pub fn new_without_debug_infos_with_option( + instructions: &[Option>], + step: u32, + pc_base: u32, + max_num_public_values: usize, + ) -> Self { + assert!( + instructions.is_empty() + || pc_base + (instructions.len() as u32 - 1) * step <= MAX_ALLOWED_PC + ); + Self { + instructions_and_debug_infos: instructions + .iter() + .map(|instruction| instruction.clone().map(|instruction| (instruction, None))) + .collect(), + step, + pc_base, + max_num_public_values, + } + } + /// We assume that pc_start = pc_base = 0 everywhere except the RISC-V programs, until we need otherwise /// We use [DEFAULT_PC_STEP] for consistency with RISC-V pub fn from_instructions_and_debug_infos( @@ -179,7 +200,7 @@ impl Display for Program { f, g, } = instruction; - write!( + writeln!( formatter, "{:?} {} {} {} {} {} {} {}", opcode, a, b, c, d, e, f, g, diff --git a/crates/toolchain/transpiler/src/extension.rs b/crates/toolchain/transpiler/src/extension.rs index 8163301fff..92e57f6168 100644 --- a/crates/toolchain/transpiler/src/extension.rs +++ b/crates/toolchain/transpiler/src/extension.rs @@ -10,5 +10,33 @@ pub trait TranspilerExtension { /// the next contiguous section of RISC-V instructions into an [`Instruction`]. /// It returns `None` if it cannot transpile. Otherwise it returns `(instruction, how_many_u32s)` to indicate that /// `instruction_stream[..how_many_u32s]` should be transpiled into `instruction`. - fn process_custom(&self, instruction_stream: &[u32]) -> Option<(Instruction, usize)>; + fn process_custom(&self, instruction_stream: &[u32]) -> Option>; +} + +pub struct TranspilerOutput { + pub instructions: Vec>>, + pub used_u32s: usize, +} + +impl TranspilerOutput { + pub fn one_to_one(instruction: Instruction) -> Self { + Self { + instructions: vec![Some(instruction)], + used_u32s: 1, + } + } + + pub fn many_to_one(instruction: Instruction, used_u32s: usize) -> Self { + Self { + instructions: vec![Some(instruction)], + used_u32s, + } + } + + pub fn gap(gap_length: usize, used_u32s: usize) -> Self { + Self { + instructions: (0..gap_length).map(|_| None).collect(), + used_u32s, + } + } } diff --git a/crates/toolchain/transpiler/src/lib.rs b/crates/toolchain/transpiler/src/lib.rs index 8305437595..bf88d25a8e 100644 --- a/crates/toolchain/transpiler/src/lib.rs +++ b/crates/toolchain/transpiler/src/lib.rs @@ -16,7 +16,7 @@ pub mod transpiler; pub mod util; mod extension; -pub use extension::TranspilerExtension; +pub use extension::{TranspilerExtension, TranspilerOutput}; pub trait FromElf { type ElfContext; @@ -29,7 +29,7 @@ impl FromElf for VmExe { type ElfContext = Transpiler; fn from_elf(elf: Elf, transpiler: Self::ElfContext) -> Result { let instructions = transpiler.transpile(&elf.instructions)?; - let program = Program::new_without_debug_infos( + let program = Program::new_without_debug_infos_with_option( &instructions, DEFAULT_PC_STEP, elf.pc_base, diff --git a/crates/toolchain/transpiler/src/transpiler.rs b/crates/toolchain/transpiler/src/transpiler.rs index 5102e3ec39..ac681f8643 100644 --- a/crates/toolchain/transpiler/src/transpiler.rs +++ b/crates/toolchain/transpiler/src/transpiler.rs @@ -50,7 +50,7 @@ impl Transpiler { pub fn transpile( &self, instructions_u32: &[u32], - ) -> Result>, TranspilerError> { + ) -> Result>>, TranspilerError> { let mut instructions = Vec::new(); let mut ptr = 0; while ptr < instructions_u32.len() { @@ -60,15 +60,22 @@ impl Transpiler { .map(|proc| proc.process_custom(&instructions_u32[ptr..])) .filter(|opt| opt.is_some()) .collect::>(); - if options.is_empty() { - return Err(TranspilerError::ParseError(instructions_u32[ptr])); - } - if options.len() > 1 { - return Err(TranspilerError::AmbiguousNextInstruction); - } - let (instruction, advance) = options.pop().unwrap().unwrap(); - instructions.push(instruction); - ptr += advance; + assert!( + !options.is_empty(), + //"couldn't parse the next instruction: {:032b}", + "couldn't parse the next instruction: {} = {:032b}", + instructions_u32[ptr], + instructions_u32[ptr], + ); + assert!( + options.len() < 2, + "ambiguous next instruction: {} = {:032b}", + instructions_u32[ptr], + instructions_u32[ptr], + ); + let transpiler_output = options.pop().unwrap().unwrap(); + instructions.extend(transpiler_output.instructions); + ptr += transpiler_output.used_u32s; } Ok(instructions) } diff --git a/crates/vm/src/arch/segment.rs b/crates/vm/src/arch/segment.rs index 6f7cb813fa..d81633b44f 100644 --- a/crates/vm/src/arch/segment.rs +++ b/crates/vm/src/arch/segment.rs @@ -128,6 +128,8 @@ impl> ExecutionSegment { let (instruction, debug_info) = self.chip_complex.program_chip_mut().get_instruction(pc)?; tracing::trace!("pc: {pc:#x} | time: {timestamp} | {:?}", instruction); + println!(); + println!("pc: {pc:#x} | time: {timestamp} | {:?}", instruction); let (dsl_instr, trace) = debug_info.map_or( (None, None), diff --git a/extensions/algebra/transpiler/src/lib.rs b/extensions/algebra/transpiler/src/lib.rs index f85bf8f672..a5f82d9f18 100644 --- a/extensions/algebra/transpiler/src/lib.rs +++ b/extensions/algebra/transpiler/src/lib.rs @@ -7,7 +7,7 @@ use openvm_instructions::{ }; use openvm_instructions_derive::UsizeOpcode; use openvm_stark_backend::p3_field::PrimeField32; -use openvm_transpiler::{util::from_r_type, TranspilerExtension}; +use openvm_transpiler::{util::from_r_type, TranspilerExtension, TranspilerOutput}; use rrs_lib::instruction_formats::RType; use strum::{EnumCount, EnumIter, FromRepr}; @@ -50,7 +50,7 @@ pub struct ModularTranspilerExtension; pub struct Fp2TranspilerExtension; impl TranspilerExtension for ModularTranspilerExtension { - fn process_custom(&self, instruction_stream: &[u32]) -> Option<(Instruction, usize)> { + fn process_custom(&self, instruction_stream: &[u32]) -> Option> { if instruction_stream.is_empty() { return None; } @@ -122,12 +122,12 @@ impl TranspilerExtension for ModularTranspilerExtension { Some(from_r_type(global_opcode, 2, &dec_insn)) } }; - instruction.map(|instruction| (instruction, 1)) + instruction.map(TranspilerOutput::one_to_one) } } impl TranspilerExtension for Fp2TranspilerExtension { - fn process_custom(&self, instruction_stream: &[u32]) -> Option<(Instruction, usize)> { + fn process_custom(&self, instruction_stream: &[u32]) -> Option> { if instruction_stream.is_empty() { return None; } @@ -190,6 +190,6 @@ impl TranspilerExtension for Fp2TranspilerExtension { Some(from_r_type(global_opcode, 2, &dec_insn)) } }; - instruction.map(|instruction| (instruction, 1)) + instruction.map(TranspilerOutput::one_to_one) } } diff --git a/extensions/bigint/transpiler/src/lib.rs b/extensions/bigint/transpiler/src/lib.rs index 472e54ab49..964d1e1843 100644 --- a/extensions/bigint/transpiler/src/lib.rs +++ b/extensions/bigint/transpiler/src/lib.rs @@ -8,7 +8,7 @@ use openvm_rv32im_transpiler::{ BaseAluOpcode, BranchEqualOpcode, BranchLessThanOpcode, LessThanOpcode, MulOpcode, ShiftOpcode, }; use openvm_stark_backend::p3_field::PrimeField32; -use openvm_transpiler::{util::from_r_type, TranspilerExtension}; +use openvm_transpiler::{util::from_r_type, TranspilerExtension, TranspilerOutput}; use rrs_lib::instruction_formats::{BType, RType}; use strum::IntoEnumIterator; @@ -80,7 +80,7 @@ impl Rv32Mul256Opcode { pub struct Int256TranspilerExtension; impl TranspilerExtension for Int256TranspilerExtension { - fn process_custom(&self, instruction_stream: &[u32]) -> Option<(Instruction, usize)> { + fn process_custom(&self, instruction_stream: &[u32]) -> Option> { if instruction_stream.is_empty() { return None; } @@ -154,6 +154,6 @@ impl TranspilerExtension for Int256TranspilerExtension { } _ => None, }; - instruction.map(|instruction| (instruction, 1)) + instruction.map(TranspilerOutput::one_to_one) } } diff --git a/extensions/ecc/transpiler/src/lib.rs b/extensions/ecc/transpiler/src/lib.rs index 956fb1ad0e..25a2ddaef5 100644 --- a/extensions/ecc/transpiler/src/lib.rs +++ b/extensions/ecc/transpiler/src/lib.rs @@ -5,7 +5,7 @@ use openvm_instructions::{ }; use openvm_instructions_derive::UsizeOpcode; use openvm_stark_backend::p3_field::PrimeField32; -use openvm_transpiler::{util::from_r_type, TranspilerExtension}; +use openvm_transpiler::{util::from_r_type, TranspilerExtension, TranspilerOutput}; use rrs_lib::instruction_formats::RType; use strum::{EnumCount, EnumIter, FromRepr}; @@ -32,7 +32,7 @@ pub enum EccPhantom { pub struct EccTranspilerExtension; impl TranspilerExtension for EccTranspilerExtension { - fn process_custom(&self, instruction_stream: &[u32]) -> Option<(Instruction, usize)> { + fn process_custom(&self, instruction_stream: &[u32]) -> Option> { if instruction_stream.is_empty() { return None; } @@ -59,15 +59,12 @@ impl TranspilerExtension for EccTranspilerExtension { let curve_idx_shift = curve_idx * Rv32WeierstrassOpcode::COUNT; if let Some(SwBaseFunct7::HintDecompress) = SwBaseFunct7::from_repr(base_funct7) { assert_eq!(dec_insn.rd, 0); - return Some(( - Instruction::phantom( - PhantomDiscriminant(EccPhantom::HintDecompress as u16), - F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs1), - F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs2), - curve_idx as u16, - ), - 1, - )); + return Some(TranspilerOutput::one_to_one(Instruction::phantom( + PhantomDiscriminant(EccPhantom::HintDecompress as u16), + F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs1), + F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs2), + curve_idx as u16, + ))); } if base_funct7 == SwBaseFunct7::SwSetup as u8 { let local_opcode = match dec_insn.rs2 { @@ -101,6 +98,6 @@ impl TranspilerExtension for EccTranspilerExtension { Some(from_r_type(global_opcode, 2, &dec_insn)) } }; - instruction.map(|instruction| (instruction, 1)) + instruction.map(TranspilerOutput::one_to_one) } } diff --git a/extensions/keccak256/transpiler/src/lib.rs b/extensions/keccak256/transpiler/src/lib.rs index d3bb5351bf..a638425a0d 100644 --- a/extensions/keccak256/transpiler/src/lib.rs +++ b/extensions/keccak256/transpiler/src/lib.rs @@ -2,7 +2,7 @@ use openvm_instructions::{instruction::Instruction, UsizeOpcode}; use openvm_instructions_derive::UsizeOpcode; use openvm_keccak256_guest::{FUNCT3, OPCODE}; use openvm_stark_backend::p3_field::PrimeField32; -use openvm_transpiler::{util::from_r_type, TranspilerExtension}; +use openvm_transpiler::{util::from_r_type, TranspilerExtension, TranspilerOutput}; use rrs_lib::instruction_formats::RType; use strum::{EnumCount, EnumIter, FromRepr}; @@ -19,7 +19,7 @@ pub enum Rv32KeccakOpcode { pub struct Keccak256TranspilerExtension; impl TranspilerExtension for Keccak256TranspilerExtension { - fn process_custom(&self, instruction_stream: &[u32]) -> Option<(Instruction, usize)> { + fn process_custom(&self, instruction_stream: &[u32]) -> Option> { if instruction_stream.is_empty() { return None; } @@ -36,6 +36,6 @@ impl TranspilerExtension for Keccak256TranspilerExtension { 2, &dec_insn, ); - Some((instruction, 1)) + Some(TranspilerOutput::one_to_one(instruction)) } } diff --git a/extensions/native/circuit/src/castf/core.rs b/extensions/native/circuit/src/castf/core.rs index 9ba2b70c81..3e817f4af6 100644 --- a/extensions/native/circuit/src/castf/core.rs +++ b/extensions/native/circuit/src/castf/core.rs @@ -144,6 +144,8 @@ where let y = reads.into()[0][0]; let x = CastF::solve(y.as_canonical_u32()); + println!("castf {y} = {x:?}"); + //panic!("adios"); for (i, limb) in x.iter().enumerate() { if i == 3 { self.range_checker_chip.add_count(*limb, FINAL_LIMB_BITS); diff --git a/extensions/native/circuit/src/field_arithmetic/core.rs b/extensions/native/circuit/src/field_arithmetic/core.rs index 854ee10c6b..ebf1705b19 100644 --- a/extensions/native/circuit/src/field_arithmetic/core.rs +++ b/extensions/native/circuit/src/field_arithmetic/core.rs @@ -145,6 +145,7 @@ where let b = data[0][0]; let c = data[1][0]; let a = FieldArithmetic::run_field_arithmetic(local_opcode, b, c).unwrap(); + println!("{b} ({local_opcode:?}) {c} = {a}"); let output: AdapterRuntimeContext = AdapterRuntimeContext { to_pc: None, diff --git a/extensions/native/compiler/src/conversion/mod.rs b/extensions/native/compiler/src/conversion/mod.rs index 482215c905..5dc4762a6e 100644 --- a/extensions/native/compiler/src/conversion/mod.rs +++ b/extensions/native/compiler/src/conversion/mod.rs @@ -119,7 +119,8 @@ impl AS { match self { AS::Immediate => F::ZERO, AS::Register => F::ONE, - AS::Memory => F::TWO, + // for kernel stuff + AS::Memory => F::from_canonical_usize(5), } } } diff --git a/extensions/pairing/transpiler/src/lib.rs b/extensions/pairing/transpiler/src/lib.rs index 846b9e6526..b268b13be5 100644 --- a/extensions/pairing/transpiler/src/lib.rs +++ b/extensions/pairing/transpiler/src/lib.rs @@ -4,7 +4,7 @@ use openvm_instructions::{ use openvm_instructions_derive::UsizeOpcode; use openvm_pairing_guest::{PairingBaseFunct7, OPCODE, PAIRING_FUNCT3}; use openvm_stark_backend::p3_field::PrimeField32; -use openvm_transpiler::{util::from_r_type, TranspilerExtension}; +use openvm_transpiler::{util::from_r_type, TranspilerExtension, TranspilerOutput}; use rrs_lib::instruction_formats::RType; use strum::{EnumCount, EnumIter, FromRepr}; @@ -81,7 +81,7 @@ pub enum PairingPhantom { pub struct PairingTranspilerExtension; impl TranspilerExtension for PairingTranspilerExtension { - fn process_custom(&self, instruction_stream: &[u32]) -> Option<(Instruction, usize)> { + fn process_custom(&self, instruction_stream: &[u32]) -> Option> { if instruction_stream.is_empty() { return None; } @@ -102,15 +102,12 @@ impl TranspilerExtension for PairingTranspilerExtension { if let Some(PairingBaseFunct7::HintFinalExp) = PairingBaseFunct7::from_repr(base_funct7) { assert_eq!(dec_insn.rd, 0); // Return exits the outermost function - return Some(( - Instruction::phantom( - PhantomDiscriminant(PairingPhantom::HintFinalExp as u16), - F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs1), - F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs2), - pairing_idx as u16, - ), - 1, - )); + return Some(TranspilerOutput::one_to_one(Instruction::phantom( + PhantomDiscriminant(PairingPhantom::HintFinalExp as u16), + F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs1), + F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs2), + pairing_idx as u16, + ))); } let global_opcode = match PairingBaseFunct7::from_repr(base_funct7) { Some(PairingBaseFunct7::MillerDoubleStep) => { @@ -151,6 +148,10 @@ impl TranspilerExtension for PairingTranspilerExtension { }; let global_opcode = global_opcode + pairing_idx_shift; - Some((from_r_type(global_opcode, 2, &dec_insn), 1)) + Some(TranspilerOutput::one_to_one(from_r_type( + global_opcode, + 2, + &dec_insn, + ))) } } diff --git a/extensions/rv32im/transpiler/src/lib.rs b/extensions/rv32im/transpiler/src/lib.rs index bbecccb443..69ae849fc3 100644 --- a/extensions/rv32im/transpiler/src/lib.rs +++ b/extensions/rv32im/transpiler/src/lib.rs @@ -11,7 +11,7 @@ use openvm_rv32im_guest::{ use openvm_stark_backend::p3_field::PrimeField32; use openvm_transpiler::{ util::{nop, unimp}, - TranspilerExtension, + TranspilerExtension, TranspilerOutput, }; use rrs::InstructionTranspiler; use rrs_lib::{ @@ -33,7 +33,7 @@ pub struct Rv32MTranspilerExtension; pub struct Rv32IoTranspilerExtension; impl TranspilerExtension for Rv32ITranspilerExtension { - fn process_custom(&self, instruction_stream: &[u32]) -> Option<(Instruction, usize)> { + fn process_custom(&self, instruction_stream: &[u32]) -> Option> { let mut transpiler = InstructionTranspiler::(PhantomData); if instruction_stream.is_empty() { return None; @@ -50,14 +50,14 @@ impl TranspilerExtension for Rv32ITranspilerExtension { // CSRRW if dec_insn.rs1 == 0 && dec_insn.rd == 0 { // This resets the CSR counter to zero. Since we don't have any CSR registers, this is a nop. - return Some((nop(), 1)); + return Some(TranspilerOutput::one_to_one(nop())); } } eprintln!( "Transpiling system / CSR instruction: {:b} (opcode = {:07b}, funct3 = {:03b}) to unimp", instruction_u32, opcode, funct3 ); - return Some((unimp(), 1)); + return Some(TranspilerOutput::one_to_one(unimp())); } (SYSTEM_OPCODE, TERMINATE_FUNCT3) => { let dec_insn = IType::new(instruction_u32); @@ -98,12 +98,12 @@ impl TranspilerExtension for Rv32ITranspilerExtension { _ => process_instruction(&mut transpiler, instruction_u32), }; - instruction.map(|ret| (ret, 1)) + instruction.map(TranspilerOutput::one_to_one) } } impl TranspilerExtension for Rv32MTranspilerExtension { - fn process_custom(&self, instruction_stream: &[u32]) -> Option<(Instruction, usize)> { + fn process_custom(&self, instruction_stream: &[u32]) -> Option> { if instruction_stream.is_empty() { return None; } @@ -125,12 +125,12 @@ impl TranspilerExtension for Rv32MTranspilerExtension { instruction_u32, ); - instruction.map(|instruction| (instruction, 1)) + instruction.map(TranspilerOutput::one_to_one) } } impl TranspilerExtension for Rv32IoTranspilerExtension { - fn process_custom(&self, instruction_stream: &[u32]) -> Option<(Instruction, usize)> { + fn process_custom(&self, instruction_stream: &[u32]) -> Option> { if instruction_stream.is_empty() { return None; } @@ -175,6 +175,6 @@ impl TranspilerExtension for Rv32IoTranspilerExtension { _ => return None, }; - instruction.map(|instruction| (instruction, 1)) + instruction.map(TranspilerOutput::one_to_one) } }