@@ -475,27 +475,41 @@ impl VirtualMachine {
475
475
}
476
476
477
477
pub fn step_instruction ( & mut self ) -> Result < ( ) , VirtualMachineError > {
478
- let pc = self . run_context . pc . offset ;
478
+ if self . run_context . pc . segment_index == 0 {
479
+ // Run instructions from program segment, using instruction cache
480
+ let pc = self . run_context . pc . offset ;
479
481
480
- if self . segments . memory . data [ 0 ] . len ( ) <= pc {
481
- return Err ( MemoryError :: UnknownMemoryCell ( Box :: new ( ( 0 , pc) . into ( ) ) ) ) ?;
482
- }
482
+ if self . segments . memory . data [ 0 ] . len ( ) <= pc {
483
+ return Err ( MemoryError :: UnknownMemoryCell ( Box :: new ( ( 0 , pc) . into ( ) ) ) ) ?;
484
+ }
483
485
484
- let mut inst_cache = core:: mem:: take ( & mut self . instruction_cache ) ;
485
- inst_cache. resize ( ( pc + 1 ) . max ( inst_cache. len ( ) ) , None ) ;
486
+ let mut inst_cache = core:: mem:: take ( & mut self . instruction_cache ) ;
487
+ inst_cache. resize ( ( pc + 1 ) . max ( inst_cache. len ( ) ) , None ) ;
486
488
487
- let instruction = inst_cache. get_mut ( pc) . unwrap ( ) ;
488
- if instruction. is_none ( ) {
489
- * instruction = Some ( self . decode_current_instruction ( ) ?) ;
490
- }
491
- let instruction = instruction. as_ref ( ) . unwrap ( ) ;
492
- if !self . skip_instruction_execution {
493
- self . run_instruction ( instruction) ?;
489
+ let instruction = inst_cache. get_mut ( pc) . unwrap ( ) ;
490
+ if instruction. is_none ( ) {
491
+ * instruction = Some ( self . decode_current_instruction ( ) ?) ;
492
+ }
493
+ let instruction = instruction. as_ref ( ) . unwrap ( ) ;
494
+
495
+ if !self . skip_instruction_execution {
496
+ self . run_instruction ( instruction) ?;
497
+ } else {
498
+ self . run_context . pc += instruction. size ( ) ;
499
+ self . skip_instruction_execution = false ;
500
+ }
501
+ self . instruction_cache = inst_cache;
494
502
} else {
495
- self . run_context . pc += instruction. size ( ) ;
496
- self . skip_instruction_execution = false ;
503
+ // Run instructions from programs loaded in other segments, without instruction cache
504
+ let instruction = self . decode_current_instruction ( ) ?;
505
+
506
+ if !self . skip_instruction_execution {
507
+ self . run_instruction ( & instruction) ?;
508
+ } else {
509
+ self . run_context . pc += instruction. size ( ) ;
510
+ self . skip_instruction_execution = false ;
511
+ }
497
512
}
498
- self . instruction_cache = inst_cache;
499
513
Ok ( ( ) )
500
514
}
501
515
@@ -4301,4 +4315,180 @@ mod tests {
4301
4315
. is_err( ) ) ;
4302
4316
}
4303
4317
}
4318
+
4319
+ #[ test]
4320
+ #[ cfg_attr( target_arch = "wasm32" , wasm_bindgen_test) ]
4321
+ /// Test for a simple program execution
4322
+ /// Used program code:
4323
+ /// func main():
4324
+ /// let a = 1
4325
+ /// let b = 2
4326
+ /// let c = a + b
4327
+ /// return()
4328
+ /// end
4329
+ /// Memory taken from original vm
4330
+ /// {RelocatableValue(segment_index=0, offset=0): 2345108766317314046,
4331
+ /// RelocatableValue(segment_index=1, offset=0): RelocatableValue(segment_index=2, offset=0),
4332
+ /// RelocatableValue(segment_index=1, offset=1): RelocatableValue(segment_index=3, offset=0)}
4333
+ /// Current register values:
4334
+ /// AP 1:2
4335
+ /// FP 1:2
4336
+ /// PC 0:0
4337
+ fn test_step_for_preset_memory_program_loaded_into_user_segment ( ) {
4338
+ let mut vm = vm ! ( true ) ;
4339
+
4340
+ let mut hint_processor = BuiltinHintProcessor :: new_empty ( ) ;
4341
+
4342
+ run_context ! ( vm, 0 , 2 , 2 ) ;
4343
+
4344
+ vm. segments = segments ! [
4345
+ ( ( 2 , 0 ) , 2345108766317314046_u64 ) , // Load program into new segment
4346
+ ( ( 1 , 0 ) , ( 2 , 0 ) ) ,
4347
+ ( ( 1 , 1 ) , ( 3 , 0 ) )
4348
+ ] ;
4349
+ // set starting pc on new segemt to run loaded program
4350
+ vm. run_context . pc . segment_index = 2 ;
4351
+
4352
+ assert_matches ! (
4353
+ vm. step(
4354
+ & mut hint_processor,
4355
+ exec_scopes_ref!( ) ,
4356
+ & mut Vec :: new( ) ,
4357
+ & mut HashMap :: new( ) ,
4358
+ & HashMap :: new( )
4359
+ ) ,
4360
+ Ok ( ( ) )
4361
+ ) ;
4362
+ let trace = vm. trace . unwrap ( ) ;
4363
+ trace_check ( & trace, & [ ( ( 2 , 0 ) . into ( ) , 2 , 2 ) ] ) ;
4364
+
4365
+ assert_eq ! ( vm. run_context. pc, Relocatable :: from( ( 3 , 0 ) ) ) ;
4366
+ assert_eq ! ( vm. run_context. ap, 2 ) ;
4367
+ assert_eq ! ( vm. run_context. fp, 0 ) ;
4368
+
4369
+ //Check that the following addresses have been accessed:
4370
+ // Addresses have been copied from python execution:
4371
+ let mem = vm. segments . memory . data ;
4372
+ assert ! ( mem[ 1 ] [ 0 ] . as_ref( ) . unwrap( ) . is_accessed( ) ) ;
4373
+ assert ! ( mem[ 1 ] [ 1 ] . as_ref( ) . unwrap( ) . is_accessed( ) ) ;
4374
+ }
4375
+
4376
+ #[ test]
4377
+ #[ cfg_attr( target_arch = "wasm32" , wasm_bindgen_test) ]
4378
+ /*
4379
+ Test for a simple program execution
4380
+ Used program code:
4381
+ func myfunc(a: felt) -> (r: felt):
4382
+ let b = a * 2
4383
+ return(b)
4384
+ end
4385
+ func main():
4386
+ let a = 1
4387
+ let b = myfunc(a)
4388
+ return()
4389
+ end
4390
+ Memory taken from original vm:
4391
+ {RelocatableValue(segment_index=0, offset=0): 5207990763031199744,
4392
+ RelocatableValue(segment_index=0, offset=1): 2,
4393
+ RelocatableValue(segment_index=0, offset=2): 2345108766317314046,
4394
+ RelocatableValue(segment_index=0, offset=3): 5189976364521848832,
4395
+ RelocatableValue(segment_index=0, offset=4): 1,
4396
+ RelocatableValue(segment_index=0, offset=5): 1226245742482522112,
4397
+ RelocatableValue(segment_index=0, offset=6): 3618502788666131213697322783095070105623107215331596699973092056135872020476,
4398
+ RelocatableValue(segment_index=0, offset=7): 2345108766317314046,
4399
+ RelocatableValue(segment_index=1, offset=0): RelocatableValue(segment_index=2, offset=0),
4400
+ RelocatableValue(segment_index=1, offset=1): RelocatableValue(segment_index=3, offset=0)}
4401
+ Current register values:
4402
+ AP 1:2
4403
+ FP 1:2
4404
+ PC 0:3
4405
+ Final Pc (not executed): 3:0
4406
+ This program consists of 5 steps
4407
+ */
4408
+ fn test_step_for_preset_memory_function_call_program_loaded_into_user_segment ( ) {
4409
+ let mut vm = vm ! ( true ) ;
4410
+
4411
+ run_context ! ( vm, 3 , 2 , 2 ) ;
4412
+ // set starting pc on new segemt to run loaded program
4413
+ vm. run_context . pc . segment_index = 4 ;
4414
+
4415
+ //Insert values into memory
4416
+ vm. segments . memory =
4417
+ memory ! [
4418
+ // Load program into new segment
4419
+ ( ( 4 , 0 ) , 5207990763031199744_i64 ) ,
4420
+ ( ( 4 , 1 ) , 2 ) ,
4421
+ ( ( 4 , 2 ) , 2345108766317314046_i64 ) ,
4422
+ ( ( 4 , 3 ) , 5189976364521848832_i64 ) ,
4423
+ ( ( 4 , 4 ) , 1 ) ,
4424
+ ( ( 4 , 5 ) , 1226245742482522112_i64 ) ,
4425
+ (
4426
+ ( 4 , 6 ) ,
4427
+ ( "3618502788666131213697322783095070105623107215331596699973092056135872020476" , 10 )
4428
+ ) ,
4429
+ ( ( 4 , 7 ) , 2345108766317314046_i64 ) ,
4430
+ ( ( 1 , 0 ) , ( 2 , 0 ) ) ,
4431
+ ( ( 1 , 1 ) , ( 3 , 0 ) )
4432
+ ] ;
4433
+
4434
+ let final_pc = Relocatable :: from ( ( 3 , 0 ) ) ;
4435
+ let mut hint_processor = BuiltinHintProcessor :: new_empty ( ) ;
4436
+ //Run steps
4437
+ while vm. run_context . pc != final_pc {
4438
+ assert_matches ! (
4439
+ vm. step(
4440
+ & mut hint_processor,
4441
+ exec_scopes_ref!( ) ,
4442
+ & mut Vec :: new( ) ,
4443
+ & mut HashMap :: new( ) ,
4444
+ & HashMap :: new( )
4445
+ ) ,
4446
+ Ok ( ( ) )
4447
+ ) ;
4448
+ }
4449
+
4450
+ //Check final register values
4451
+ assert_eq ! ( vm. run_context. pc, Relocatable :: from( ( 3 , 0 ) ) ) ;
4452
+
4453
+ assert_eq ! ( vm. run_context. ap, 6 ) ;
4454
+
4455
+ assert_eq ! ( vm. run_context. fp, 0 ) ;
4456
+ //Check each TraceEntry in trace
4457
+ let trace = vm. trace . unwrap ( ) ;
4458
+ assert_eq ! ( trace. len( ) , 5 ) ;
4459
+ trace_check (
4460
+ & trace,
4461
+ & [
4462
+ ( ( 4 , 3 ) . into ( ) , 2 , 2 ) ,
4463
+ ( ( 4 , 5 ) . into ( ) , 3 , 2 ) ,
4464
+ ( ( 4 , 0 ) . into ( ) , 5 , 5 ) ,
4465
+ ( ( 4 , 2 ) . into ( ) , 6 , 5 ) ,
4466
+ ( ( 4 , 7 ) . into ( ) , 6 , 2 ) ,
4467
+ ] ,
4468
+ ) ;
4469
+ //Check that the following addresses have been accessed:
4470
+ // Addresses have been copied from python execution:
4471
+ let mem = & vm. segments . memory . data ;
4472
+ assert ! ( mem[ 4 ] [ 1 ] . as_ref( ) . unwrap( ) . is_accessed( ) ) ;
4473
+ assert ! ( mem[ 4 ] [ 4 ] . as_ref( ) . unwrap( ) . is_accessed( ) ) ;
4474
+ assert ! ( mem[ 4 ] [ 6 ] . as_ref( ) . unwrap( ) . is_accessed( ) ) ;
4475
+ assert ! ( mem[ 1 ] [ 0 ] . as_ref( ) . unwrap( ) . is_accessed( ) ) ;
4476
+ assert ! ( mem[ 1 ] [ 1 ] . as_ref( ) . unwrap( ) . is_accessed( ) ) ;
4477
+ assert ! ( mem[ 1 ] [ 2 ] . as_ref( ) . unwrap( ) . is_accessed( ) ) ;
4478
+ assert ! ( mem[ 1 ] [ 3 ] . as_ref( ) . unwrap( ) . is_accessed( ) ) ;
4479
+ assert ! ( mem[ 1 ] [ 4 ] . as_ref( ) . unwrap( ) . is_accessed( ) ) ;
4480
+ assert ! ( mem[ 1 ] [ 5 ] . as_ref( ) . unwrap( ) . is_accessed( ) ) ;
4481
+ assert_eq ! (
4482
+ vm. segments
4483
+ . memory
4484
+ . get_amount_of_accessed_addresses_for_segment( 4 ) ,
4485
+ Some ( 3 )
4486
+ ) ;
4487
+ assert_eq ! (
4488
+ vm. segments
4489
+ . memory
4490
+ . get_amount_of_accessed_addresses_for_segment( 1 ) ,
4491
+ Some ( 6 )
4492
+ ) ;
4493
+ }
4304
4494
}
0 commit comments