Skip to content

Commit f029a9d

Browse files
committed
fix: add memcpy to toolchain
1 parent 75c7b0c commit f029a9d

File tree

12 files changed

+1097
-464
lines changed

12 files changed

+1097
-464
lines changed

Cargo.lock

Lines changed: 6 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ openvm-ecc-sw-macros = { path = "extensions/ecc/sw-macros", default-features = f
172172
openvm-pairing-circuit = { path = "extensions/pairing/circuit", default-features = false }
173173
openvm-pairing-transpiler = { path = "extensions/pairing/transpiler", default-features = false }
174174
openvm-pairing-guest = { path = "extensions/pairing/guest", default-features = false }
175+
openvm-memcpy-circuit = { path = "extensions/memcpy/circuit", default-features = false }
176+
openvm-memcpy-transpiler = { path = "extensions/memcpy/transpiler", default-features = false }
175177
openvm-verify-stark = { path = "guest-libs/verify_stark", default-features = false }
176178

177179
# Benchmarking

benchmarks/execute/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ openvm-pairing-guest.workspace = true
2424
openvm-pairing-transpiler.workspace = true
2525
openvm-keccak256-circuit.workspace = true
2626
openvm-keccak256-transpiler.workspace = true
27+
openvm-memcpy-circuit.workspace = true
28+
openvm-memcpy-transpiler.workspace = true
2729
openvm-rv32im-circuit.workspace = true
2830
openvm-rv32im-transpiler.workspace = true
2931
openvm-sha256-circuit.workspace = true

benchmarks/execute/benches/execute.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ use openvm_ecc_circuit::{EccCpuProverExt, WeierstrassExtension, WeierstrassExten
3232
use openvm_ecc_transpiler::EccTranspilerExtension;
3333
use openvm_keccak256_circuit::{Keccak256, Keccak256CpuProverExt, Keccak256Executor};
3434
use openvm_keccak256_transpiler::Keccak256TranspilerExtension;
35+
use openvm_memcpy_circuit::{Memcpy, MemcpyCpuProverExt, MemcpyExecutor};
36+
use openvm_memcpy_transpiler::MemcpyTranspilerExtension;
3537
use openvm_native_circuit::{NativeCpuBuilder, NATIVE_MAX_TRACE_HEIGHTS};
3638
use openvm_native_recursion::hints::Hintable;
3739
use openvm_pairing_circuit::{
@@ -107,6 +109,8 @@ pub struct ExecuteConfig {
107109
#[extension]
108110
pub keccak: Keccak256,
109111
#[extension]
112+
pub memcpy: Memcpy,
113+
#[extension]
110114
pub sha256: Sha256,
111115
#[extension]
112116
pub modular: ModularExtension,
@@ -128,6 +132,7 @@ impl Default for ExecuteConfig {
128132
io: Rv32Io,
129133
bigint: Int256::default(),
130134
keccak: Keccak256,
135+
memcpy: Memcpy,
131136
sha256: Sha256,
132137
modular: ModularExtension::new(vec![
133138
bn_config.modulus.clone(),
@@ -188,6 +193,7 @@ where
188193
&config.keccak,
189194
inventory,
190195
)?;
196+
VmProverExtension::<E, _, _>::extend_prover(&MemcpyCpuProverExt, &config.memcpy, inventory)?;
191197
VmProverExtension::<E, _, _>::extend_prover(&Sha2CpuProverExt, &config.sha256, inventory)?;
192198
VmProverExtension::<E, _, _>::extend_prover(
193199
&AlgebraCpuProverExt,
@@ -216,6 +222,7 @@ fn create_default_transpiler() -> Transpiler<BabyBear> {
216222
.with_extension(Rv32MTranspilerExtension)
217223
.with_extension(Int256TranspilerExtension)
218224
.with_extension(Keccak256TranspilerExtension)
225+
.with_extension(MemcpyTranspilerExtension)
219226
.with_extension(Sha256TranspilerExtension)
220227
.with_extension(ModularTranspilerExtension)
221228
.with_extension(Fp2TranspilerExtension)

crates/sdk/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ openvm-ecc-circuit = { workspace = true }
1818
openvm-ecc-transpiler = { workspace = true }
1919
openvm-keccak256-circuit = { workspace = true }
2020
openvm-keccak256-transpiler = { workspace = true }
21+
openvm-memcpy-circuit = { workspace = true }
22+
openvm-memcpy-transpiler = { workspace = true }
2123
openvm-sha256-circuit = { workspace = true }
2224
openvm-sha256-transpiler = { workspace = true }
2325
openvm-pairing-circuit = { workspace = true }

crates/sdk/src/config/global.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ use openvm_rv32im_circuit::{
3333
use openvm_rv32im_transpiler::{
3434
Rv32ITranspilerExtension, Rv32IoTranspilerExtension, Rv32MTranspilerExtension,
3535
};
36+
use openvm_memcpy_circuit::{Memcpy, MemcpyCpuProverExt, MemcpyExecutor};
37+
use openvm_memcpy_transpiler::MemcpyTranspilerExtension;
3638
use openvm_sha256_circuit::{Sha256, Sha256Executor, Sha2CpuProverExt};
3739
use openvm_sha256_transpiler::Sha256TranspilerExtension;
3840
use openvm_stark_backend::{
@@ -81,6 +83,7 @@ pub struct SdkVmConfig {
8183
pub rv32i: Option<UnitStruct>,
8284
pub io: Option<UnitStruct>,
8385
pub keccak: Option<UnitStruct>,
86+
pub memcpy: Option<UnitStruct>,
8487
pub sha256: Option<UnitStruct>,
8588
pub native: Option<UnitStruct>,
8689
pub castf: Option<UnitStruct>,
@@ -118,6 +121,7 @@ impl SdkVmConfig {
118121
.rv32m(Default::default())
119122
.io(Default::default())
120123
.keccak(Default::default())
124+
.memcpy(Default::default())
121125
.sha256(Default::default())
122126
.bigint(Default::default())
123127
.modular(ModularExtension::new(vec![
@@ -199,6 +203,9 @@ impl TranspilerConfig<F> for SdkVmConfig {
199203
if self.keccak.is_some() {
200204
transpiler = transpiler.with_extension(Keccak256TranspilerExtension);
201205
}
206+
if self.memcpy.is_some() {
207+
transpiler = transpiler.with_extension(MemcpyTranspilerExtension);
208+
}
202209
if self.sha256.is_some() {
203210
transpiler = transpiler.with_extension(Sha256TranspilerExtension);
204211
}
@@ -269,6 +276,7 @@ impl SdkVmConfig {
269276
let rv32i = config.rv32i.map(|_| Rv32I);
270277
let io = config.io.map(|_| Rv32Io);
271278
let keccak = config.keccak.map(|_| Keccak256);
279+
let memcpy = config.memcpy.map(|_| Memcpy);
272280
let sha256 = config.sha256.map(|_| Sha256);
273281
let native = config.native.map(|_| Native);
274282
let castf = config.castf.map(|_| CastFExtension);
@@ -284,6 +292,7 @@ impl SdkVmConfig {
284292
rv32i,
285293
io,
286294
keccak,
295+
memcpy,
287296
sha256,
288297
native,
289298
castf,
@@ -315,6 +324,8 @@ pub struct SdkVmConfigInner {
315324
pub io: Option<Rv32Io>,
316325
#[extension(executor = "Keccak256Executor")]
317326
pub keccak: Option<Keccak256>,
327+
#[extension(executor = "MemcpyExecutor")]
328+
pub memcpy: Option<Memcpy>,
318329
#[extension(executor = "Sha256Executor")]
319330
pub sha256: Option<Sha256>,
320331
#[extension(executor = "NativeExecutor<F>")]
@@ -392,6 +403,9 @@ where
392403
if let Some(keccak) = &config.keccak {
393404
VmProverExtension::<E, _, _>::extend_prover(&Keccak256CpuProverExt, keccak, inventory)?;
394405
}
406+
if let Some(memcpy) = &config.memcpy {
407+
VmProverExtension::<E, _, _>::extend_prover(&MemcpyCpuProverExt, memcpy, inventory)?;
408+
}
395409
if let Some(sha256) = &config.sha256 {
396410
VmProverExtension::<E, _, _>::extend_prover(&Sha2CpuProverExt, sha256, inventory)?;
397411
}
@@ -566,6 +580,12 @@ impl From<Keccak256> for UnitStruct {
566580
}
567581
}
568582

583+
impl From<Memcpy> for UnitStruct {
584+
fn from(_: Memcpy) -> Self {
585+
UnitStruct {}
586+
}
587+
}
588+
569589
impl From<Sha256> for UnitStruct {
570590
fn from(_: Sha256) -> Self {
571591
UnitStruct {}
@@ -592,6 +612,7 @@ struct SdkVmConfigWithDefaultDeser {
592612
pub rv32i: Option<UnitStruct>,
593613
pub io: Option<UnitStruct>,
594614
pub keccak: Option<UnitStruct>,
615+
pub memcpy: Option<UnitStruct>,
595616
pub sha256: Option<UnitStruct>,
596617
pub native: Option<UnitStruct>,
597618
pub castf: Option<UnitStruct>,
@@ -611,6 +632,7 @@ impl From<SdkVmConfigWithDefaultDeser> for SdkVmConfig {
611632
rv32i: config.rv32i,
612633
io: config.io,
613634
keccak: config.keccak,
635+
memcpy: config.memcpy,
614636
sha256: config.sha256,
615637
native: config.native,
616638
castf: config.castf,

crates/toolchain/openvm/src/memcpy.s

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,11 @@
205205
.attribute 4, 16
206206
.attribute 5, "rv32im"
207207
.file "musl_memcpy.c"
208+
209+
# Define memcpy_loop macro for custom instruction (U-type)
210+
.macro memcpy_loop shift
211+
.word 0x72000000 | (\shift << 12) # opcode 0x72 + shift in immediate field (bits 12-31)
212+
.endm
208213
.globl memcpy
209214
.p2align 2
210215
.type memcpy,@function

extensions/memcpy/circuit/src/core.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ pub type MemcpyLoopChip<F> = VmChipWrapper<F, MemcpyLoopFiller>;
311311
#[derive(AlignedBytesBorrow, Clone)]
312312
#[repr(C)]
313313
struct MemcpyLoopPreCompute {
314-
a: u8,
314+
c: u8,
315315
}
316316

317317
impl<F, RA> PreflightExecutor<F, RA> for MemcpyLoopExecutor
@@ -328,9 +328,9 @@ where
328328
state: VmStateMut<F, TracingMemory, RA>,
329329
instruction: &Instruction<F>,
330330
) -> Result<(), ExecutionError> {
331-
let Instruction { opcode, a, .. } = instruction;
331+
let Instruction { opcode, c, .. } = instruction;
332332
debug_assert_eq!(*opcode, Rv32MemcpyOpcode::MEMCPY_LOOP.global_opcode());
333-
let shift = a.as_canonical_u32() as u8;
333+
let shift = c.as_canonical_u32() as u8;
334334
debug_assert!([0, 1, 2, 3].contains(&shift));
335335
let mut record = state.ctx.alloc(EmptyMultiRowLayout::default());
336336

@@ -600,7 +600,7 @@ unsafe fn execute_e12_impl<F: PrimeField32, CTX: E1ExecutionCtx>(
600600
pre_compute: &MemcpyLoopPreCompute,
601601
vm_state: &mut VmExecState<F, GuestMemory, CTX>,
602602
) {
603-
let shift = pre_compute.a;
603+
let shift = pre_compute.c;
604604
let (dest, source) = if shift == 0 {
605605
(
606606
vm_state.vm_read::<u8, 4>(RV32_REGISTER_AS, A3_REGISTER_PTR as u32),
@@ -700,12 +700,12 @@ impl MemcpyLoopExecutor {
700700
inst: &Instruction<F>,
701701
data: &mut MemcpyLoopPreCompute,
702702
) -> Result<(), StaticProgramError> {
703-
let Instruction { opcode, a, .. } = inst;
704-
let a_u32 = a.as_canonical_u32();
705-
if ![0, 1, 2, 3].contains(&a_u32) {
703+
let Instruction { opcode, c, .. } = inst;
704+
let c_u32 = c.as_canonical_u32();
705+
if ![0, 1, 2, 3].contains(&c_u32) {
706706
return Err(StaticProgramError::InvalidInstruction(pc));
707707
}
708-
*data = MemcpyLoopPreCompute { a: a_u32 as u8 };
708+
*data = MemcpyLoopPreCompute { c: c_u32 as u8 };
709709
assert_eq!(*opcode, Rv32MemcpyOpcode::MEMCPY_LOOP.global_opcode());
710710
Ok(())
711711
}

0 commit comments

Comments
 (0)