@@ -3,7 +3,6 @@ use std::{
3
3
collections:: BTreeMap ,
4
4
iter,
5
5
marker:: PhantomData ,
6
- mem,
7
6
sync:: { Arc , Mutex } ,
8
7
} ;
9
8
@@ -62,7 +61,7 @@ pub const BOUNDARY_AIR_OFFSET: usize = 0;
62
61
#[ derive( Debug , Clone , Copy , PartialEq , Eq , Serialize , Deserialize ) ]
63
62
pub struct RecordId ( pub usize ) ;
64
63
65
- pub type MemoryImage < F > = AddressMap < F , PAGE_SIZE > ;
64
+ pub type MemoryImage = AddressMap < PAGE_SIZE > ;
66
65
67
66
#[ repr( C ) ]
68
67
#[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
@@ -98,7 +97,7 @@ pub struct MemoryController<F> {
98
97
// Store separately to avoid smart pointer reference each time
99
98
range_checker_bus : VariableRangeCheckerBus ,
100
99
// addr_space -> Memory data structure
101
- memory : Memory < F > ,
100
+ memory : Memory ,
102
101
/// A reference to the `OfflineMemory`. Will be populated after `finalize()`.
103
102
offline_memory : Arc < Mutex < OfflineMemory < F > > > ,
104
103
pub access_adapters : AccessAdapterInventory < F > ,
@@ -314,7 +313,7 @@ impl<F: PrimeField32> MemoryController<F> {
314
313
}
315
314
}
316
315
317
- pub fn memory_image ( & self ) -> & MemoryImage < F > {
316
+ pub fn memory_image ( & self ) -> & MemoryImage {
318
317
& self . memory . data
319
318
}
320
319
@@ -344,7 +343,7 @@ impl<F: PrimeField32> MemoryController<F> {
344
343
}
345
344
}
346
345
347
- pub fn set_initial_memory ( & mut self , memory : MemoryImage < F > ) {
346
+ pub fn set_initial_memory ( & mut self , memory : MemoryImage ) {
348
347
if self . timestamp ( ) > INITIAL_TIMESTAMP + 1 {
349
348
panic ! ( "Cannot set initial memory after first timestamp" ) ;
350
349
}
@@ -379,58 +378,67 @@ impl<F: PrimeField32> MemoryController<F> {
379
378
( record_id, data)
380
379
}
381
380
382
- pub fn read < const N : usize > ( & mut self , address_space : F , pointer : F ) -> ( RecordId , [ F ; N ] ) {
381
+ // TEMP[jpw]: Function is safe temporarily for refactoring
382
+ /// # Safety
383
+ /// The type `T` must be stack-allocated `repr(C)` or `repr(transparent)`, and it must be the
384
+ /// exact type used to represent a single memory cell in address space `address_space`. For
385
+ /// standard usage, `T` is either `u8` or `F` where `F` is the base field of the ZK backend.
386
+ pub fn read < T : Copy , const N : usize > (
387
+ & mut self ,
388
+ address_space : F ,
389
+ pointer : F ,
390
+ ) -> ( RecordId , [ T ; N ] ) {
383
391
let address_space_u32 = address_space. as_canonical_u32 ( ) ;
384
392
let ptr_u32 = pointer. as_canonical_u32 ( ) ;
385
393
assert ! (
386
394
address_space == F :: ZERO || ptr_u32 < ( 1 << self . mem_config. pointer_max_bits) ,
387
395
"memory out of bounds: {ptr_u32:?}" ,
388
396
) ;
389
397
390
- let ( record_id, values) = self . memory . read :: < N > ( address_space_u32, ptr_u32) ;
398
+ let ( record_id, values) = unsafe { self . memory . read :: < T , N > ( address_space_u32, ptr_u32) } ;
391
399
392
400
( record_id, values)
393
401
}
394
402
395
403
/// Reads a word directly from memory without updating internal state.
396
404
///
397
405
/// Any value returned is unconstrained.
398
- pub fn unsafe_read_cell ( & self , addr_space : F , ptr : F ) -> F {
399
- self . unsafe_read :: < 1 > ( addr_space, ptr) [ 0 ]
406
+ pub fn unsafe_read_cell < T : Copy > ( & self , addr_space : F , ptr : F ) -> T {
407
+ self . unsafe_read :: < T , 1 > ( addr_space, ptr) [ 0 ]
400
408
}
401
409
402
410
/// Reads a word directly from memory without updating internal state.
403
411
///
404
412
/// Any value returned is unconstrained.
405
- pub fn unsafe_read < const N : usize > ( & self , addr_space : F , ptr : F ) -> [ F ; N ] {
413
+ pub fn unsafe_read < T : Copy , const N : usize > ( & self , addr_space : F , ptr : F ) -> [ T ; N ] {
406
414
let addr_space = addr_space. as_canonical_u32 ( ) ;
407
415
let ptr = ptr. as_canonical_u32 ( ) ;
408
- array:: from_fn ( |i| self . memory . get ( addr_space, ptr + i as u32 ) )
416
+ unsafe { array:: from_fn ( |i| self . memory . get :: < T > ( addr_space, ptr + i as u32 ) ) }
409
417
}
410
418
411
419
/// Writes `data` to the given cell.
412
420
///
413
421
/// Returns the `RecordId` and previous data.
414
- pub fn write_cell ( & mut self , address_space : F , pointer : F , data : F ) -> ( RecordId , F ) {
415
- let ( record_id, [ data] ) = self . write ( address_space, pointer, [ data] ) ;
422
+ pub fn write_cell < T : Copy > ( & mut self , address_space : F , pointer : F , data : T ) -> ( RecordId , T ) {
423
+ let ( record_id, [ data] ) = self . write ( address_space, pointer, & [ data] ) ;
416
424
( record_id, data)
417
425
}
418
426
419
- pub fn write < const N : usize > (
427
+ pub fn write < T : Copy , const N : usize > (
420
428
& mut self ,
421
429
address_space : F ,
422
430
pointer : F ,
423
- data : [ F ; N ] ,
424
- ) -> ( RecordId , [ F ; N ] ) {
425
- assert_ne ! ( address_space, F :: ZERO ) ;
431
+ data : & [ T ; N ] ,
432
+ ) -> ( RecordId , [ T ; N ] ) {
433
+ debug_assert_ne ! ( address_space, F :: ZERO ) ;
426
434
let address_space_u32 = address_space. as_canonical_u32 ( ) ;
427
435
let ptr_u32 = pointer. as_canonical_u32 ( ) ;
428
436
assert ! (
429
437
ptr_u32 < ( 1 << self . mem_config. pointer_max_bits) ,
430
438
"memory out of bounds: {ptr_u32:?}" ,
431
439
) ;
432
440
433
- self . memory . write ( address_space_u32, ptr_u32, data)
441
+ unsafe { self . memory . write :: < T , N > ( address_space_u32, ptr_u32, data) }
434
442
}
435
443
436
444
pub fn aux_cols_factory ( & self ) -> MemoryAuxColsFactory < F > {
@@ -455,26 +463,27 @@ impl<F: PrimeField32> MemoryController<F> {
455
463
}
456
464
457
465
fn replay_access_log ( & mut self ) {
458
- let log = mem:: take ( & mut self . memory . log ) ;
459
- if log. is_empty ( ) {
460
- // Online memory logs may be empty, but offline memory may be replayed from external
461
- // sources. In these cases, we skip the calls to replay access logs because
462
- // `set_log_capacity` would panic.
463
- tracing:: debug!( "skipping replay_access_log" ) ;
464
- return ;
465
- }
466
-
467
- let mut offline_memory = self . offline_memory . lock ( ) . unwrap ( ) ;
468
- offline_memory. set_log_capacity ( log. len ( ) ) ;
469
-
470
- for entry in log {
471
- Self :: replay_access (
472
- entry,
473
- & mut offline_memory,
474
- & mut self . interface_chip ,
475
- & mut self . access_adapters ,
476
- ) ;
477
- }
466
+ unimplemented ! ( ) ;
467
+ // let log = mem::take(&mut self.memory.log);
468
+ // if log.is_empty() {
469
+ // // Online memory logs may be empty, but offline memory may be replayed from external
470
+ // sources. // In these cases, we skip the calls to replay access logs because
471
+ // `set_log_capacity` would // panic.
472
+ // tracing::debug!("skipping replay_access_log");
473
+ // return;
474
+ // }
475
+
476
+ // let mut offline_memory = self.offline_memory.lock().unwrap();
477
+ // offline_memory.set_log_capacity(log.len());
478
+
479
+ // for entry in log {
480
+ // Self::replay_access(
481
+ // entry,
482
+ // &mut offline_memory,
483
+ // &mut self.interface_chip,
484
+ // &mut self.access_adapters,
485
+ // );
486
+ // }
478
487
}
479
488
480
489
/// Low-level API to replay a single memory access log entry and populate the [OfflineMemory],
@@ -704,13 +713,13 @@ impl<F: PrimeField32> MemoryController<F> {
704
713
pub fn offline_memory ( & self ) -> Arc < Mutex < OfflineMemory < F > > > {
705
714
self . offline_memory . clone ( )
706
715
}
707
- pub fn get_memory_logs ( & self ) -> & Vec < MemoryLogEntry < F > > {
716
+ pub fn get_memory_logs ( & self ) -> & Vec < MemoryLogEntry < u8 > > {
708
717
& self . memory . log
709
718
}
710
- pub fn set_memory_logs ( & mut self , logs : Vec < MemoryLogEntry < F > > ) {
719
+ pub fn set_memory_logs ( & mut self , logs : Vec < MemoryLogEntry < u8 > > ) {
711
720
self . memory . log = logs;
712
721
}
713
- pub fn take_memory_logs ( & mut self ) -> Vec < MemoryLogEntry < F > > {
722
+ pub fn take_memory_logs ( & mut self ) -> Vec < MemoryLogEntry < u8 > > {
714
723
std:: mem:: take ( & mut self . memory . log )
715
724
}
716
725
}
@@ -857,9 +866,9 @@ mod tests {
857
866
858
867
if rng. gen_bool ( 0.5 ) {
859
868
let data = F :: from_canonical_u32 ( rng. gen_range ( 0 ..1 << 30 ) ) ;
860
- memory_controller. write ( address_space, pointer, [ data] ) ;
869
+ memory_controller. write ( address_space, pointer, & [ data] ) ;
861
870
} else {
862
- memory_controller. read :: < 1 > ( address_space, pointer) ;
871
+ memory_controller. read :: < F , 1 > ( address_space, pointer) ;
863
872
}
864
873
}
865
874
assert ! ( memory_controller
0 commit comments