diff --git a/tests/benchmark/compute/instruction/test_memory.py b/tests/benchmark/compute/instruction/test_memory.py index e4a9decb8e..b737fe1ae7 100644 --- a/tests/benchmark/compute/instruction/test_memory.py +++ b/tests/benchmark/compute/instruction/test_memory.py @@ -111,3 +111,72 @@ def test_mcopy( attack_block=attack_block, cleanup=mem_touch ), ) + + +@pytest.mark.parametrize("opcode", [Op.MLOAD, Op.MSTORE, Op.MSTORE8]) +@pytest.mark.parametrize( + "memory_layout", + [ + pytest.param("sequential", id="sequential"), + pytest.param("sparse", id="sparse"), + pytest.param("overlapping", id="overlapping"), + ], +) +@pytest.mark.parametrize("overwrite_existing", [True, False]) +def test_memory_layout_access( + benchmark_test: BenchmarkTestFiller, + opcode: Op, + memory_layout: str, + overwrite_existing: bool, +) -> None: + """ + Benchmark memory access with custom layouts and overwriting scenarios. + + Variants: + - memory_layout: Memory initialization pattern + (sequential=stride 32, sparse=stride 1000, overlapping=stride 16) + - overwrite_existing: Pre-write to the access offset before operations + - opcode: Memory operation (MLOAD, MSTORE, MSTORE8) + """ + setup = Bytecode() + + # Initialize memory with pattern + if memory_layout == "sequential": + # Write sequential 32-byte words: 0, 32, 64, 96, 128... + for i in range(10): + setup += Op.MSTORE(i * 32, i) + access_offset = 64 # Access middle of initialized memory + elif memory_layout == "sparse": + # Write to sparse locations: 0, 1000, 2000, 3000... + for i in range(10): + setup += Op.MSTORE(i * 1000, i) + access_offset = 2000 # Access sparse location + elif memory_layout == "overlapping": + # Overlapping 32-byte words (16-byte stride) + for i in range(20): + setup += Op.MSTORE(i * 16, i) + access_offset = 48 # Access overlapping region + + # Overwrite pattern: pre-write to the access offset + if overwrite_existing: + if opcode == Op.MSTORE8: + setup += Op.MSTORE8(access_offset, 0xEF) + else: + setup += Op.MSTORE(access_offset, 0xDEADBEEF) + + # Prepare stack for operation + setup += Op.PUSH1(42) + Op.PUSH2(access_offset) + + # Attack block performs the memory operation + attack_block = ( + Op.POP(Op.MLOAD(Op.DUP1)) + if opcode == Op.MLOAD + else opcode(Op.DUP2, Op.DUP2) + ) + + benchmark_test( + code_generator=JumpLoopGenerator( + setup=setup, + attack_block=attack_block, + ), + )