@@ -61,7 +61,7 @@ pub struct MemcpyIterCols<T> {
61
61
pub shift : [ T ; 2 ] ,
62
62
pub is_valid : T ,
63
63
pub is_valid_not_start : T ,
64
- pub is_shift_zero : T ,
64
+ pub is_shift_non_zero : T ,
65
65
// -1 for the first iteration, 1 for the last iteration, 0 for the middle iterations
66
66
pub is_boundary : T ,
67
67
pub data_1 : [ T ; MEMCPY_LOOP_NUM_LIMBS ] ,
@@ -99,14 +99,14 @@ impl<AB: InteractionBuilder> Air<AB> for MemcpyIterAir {
99
99
let local: & MemcpyIterCols < AB :: Var > = ( * local) . borrow ( ) ;
100
100
101
101
let timestamp: AB :: Var = local. timestamp ;
102
- let mut timestamp_delta: usize = 0 ;
103
- let mut timestamp_pp = || {
104
- timestamp_delta += 1 ;
105
- timestamp + AB :: Expr :: from_canonical_usize ( timestamp_delta - 1 )
102
+ let mut timestamp_delta: AB :: Expr = AB :: Expr :: ZERO ;
103
+ let mut timestamp_pp = |timestamp_increase_value : AB :: Expr | {
104
+ timestamp_delta += timestamp_increase_value . clone ( ) ;
105
+ timestamp + timestamp_delta. clone ( ) - timestamp_increase_value . clone ( )
106
106
} ;
107
107
108
108
let shift = local. shift [ 0 ] * AB :: Expr :: TWO + local. shift [ 1 ] ;
109
- let is_shift_non_zero = not :: < AB :: Expr > ( local. is_shift_zero ) ;
109
+ let is_shift_zero = not :: < AB :: Expr > ( local. is_shift_non_zero ) ;
110
110
let is_shift_one = and :: < AB :: Expr > ( local. shift [ 0 ] , not :: < AB :: Expr > ( local. shift [ 1 ] ) ) ;
111
111
let is_shift_two = and :: < AB :: Expr > ( not :: < AB :: Expr > ( local. shift [ 0 ] ) , local. shift [ 1 ] ) ;
112
112
let is_shift_three = and :: < AB :: Expr > ( local. shift [ 0 ] , local. shift [ 1 ] ) ;
@@ -141,7 +141,7 @@ impl<AB: InteractionBuilder> Air<AB> for MemcpyIterAir {
141
141
. iter ( )
142
142
. map ( |( prev_data, next_data) | {
143
143
array:: from_fn :: < _ , MEMCPY_LOOP_NUM_LIMBS , _ > ( |i| {
144
- local . is_shift_zero . clone ( ) * ( next_data[ i] )
144
+ is_shift_zero. clone ( ) * ( next_data[ i] )
145
145
+ is_shift_one. clone ( )
146
146
* ( if i < 3 {
147
147
next_data[ i + 1 ]
@@ -167,7 +167,7 @@ impl<AB: InteractionBuilder> Air<AB> for MemcpyIterAir {
167
167
builder. assert_bool ( local. is_valid ) ;
168
168
local. shift . iter ( ) . for_each ( |x| builder. assert_bool ( * x) ) ;
169
169
builder. assert_bool ( local. is_valid_not_start ) ;
170
- builder. assert_bool ( local. is_shift_zero ) ;
170
+ builder. assert_bool ( local. is_shift_non_zero ) ;
171
171
// is_boundary is either -1, 0 or 1
172
172
builder. assert_tern ( local. is_boundary + AB :: Expr :: ONE ) ;
173
173
@@ -178,7 +178,7 @@ impl<AB: InteractionBuilder> Air<AB> for MemcpyIterAir {
178
178
) ;
179
179
180
180
// is_shift_non_zero is correct
181
- builder. assert_eq ( local. is_shift_zero , not :: < AB :: Expr > ( or :: < AB :: Expr > ( local. shift [ 0 ] , local. shift [ 1 ] ) ) ) ;
181
+ builder. assert_eq ( local. is_shift_non_zero , or :: < AB :: Expr > ( local. shift [ 0 ] , local. shift [ 1 ] ) ) ;
182
182
183
183
// if !is_valid, then is_boundary = 0, shift = 0 (we will use this assumption later)
184
184
let mut is_not_valid_when = builder. when ( not :: < AB :: Expr > ( local. is_valid ) ) ;
@@ -205,7 +205,7 @@ impl<AB: InteractionBuilder> Air<AB> for MemcpyIterAir {
205
205
// since is_shift_non_zero degree is 2, we need to keep the degree of the condition to 1
206
206
builder
207
207
. when ( not :: < AB :: Expr > ( prev. is_valid_not_start ) - not :: < AB :: Expr > ( prev. is_valid ) )
208
- . assert_eq ( local. timestamp , prev. timestamp + is_shift_non_zero . clone ( ) ) ;
208
+ . assert_eq ( local. timestamp , prev. timestamp + local . is_shift_non_zero ) ;
209
209
210
210
// if prev.is_valid_not_start and local.is_valid_not_start, then timestamp=prev_timestamp+8
211
211
// prev.is_valid_not_start is the opposite of previous condition
@@ -247,7 +247,7 @@ impl<AB: InteractionBuilder> Air<AB> for MemcpyIterAir {
247
247
. enumerate ( )
248
248
. for_each ( |( idx, ( data, read_aux) ) | {
249
249
let is_valid_read = if idx == 3 {
250
- or :: < AB :: Expr > ( is_shift_non_zero . clone ( ) , local. is_valid_not_start )
250
+ or :: < AB :: Expr > ( local . is_shift_non_zero , local. is_valid_not_start )
251
251
} else {
252
252
local. is_valid_not_start . into ( )
253
253
} ;
@@ -259,10 +259,10 @@ impl<AB: InteractionBuilder> Air<AB> for MemcpyIterAir {
259
259
local. source - AB :: Expr :: from_canonical_usize ( 16 - idx * 4 ) ,
260
260
) ,
261
261
* data,
262
- timestamp_pp ( ) ,
262
+ timestamp_pp ( is_valid_read . clone ( ) ) ,
263
263
read_aux,
264
264
)
265
- . eval ( builder, is_valid_read) ;
265
+ . eval ( builder, is_valid_read. clone ( ) ) ;
266
266
} ) ;
267
267
268
268
// Write final data to registers
@@ -274,7 +274,7 @@ impl<AB: InteractionBuilder> Air<AB> for MemcpyIterAir {
274
274
local. dest - AB :: Expr :: from_canonical_usize ( 16 - idx * 4 ) ,
275
275
) ,
276
276
data. clone ( ) ,
277
- timestamp_pp ( ) ,
277
+ timestamp_pp ( local . is_valid_not_start . into ( ) ) ,
278
278
& local. write_aux [ idx] ,
279
279
)
280
280
. eval ( builder, local. is_valid_not_start ) ;
@@ -294,10 +294,10 @@ impl<AB: InteractionBuilder> Air<AB> for MemcpyIterAir {
294
294
) ,
295
295
] ;
296
296
self . range_bus
297
- . push ( local. len [ 0 ] . clone ( ) , len_bits_limit[ 0 ] . clone ( ) , true )
297
+ . push ( local. len [ 0 ] , len_bits_limit[ 0 ] . clone ( ) , true )
298
298
. eval ( builder, local. is_valid ) ;
299
299
self . range_bus
300
- . push ( local. len [ 1 ] . clone ( ) , len_bits_limit[ 1 ] . clone ( ) , true )
300
+ . push ( local. len [ 1 ] , len_bits_limit[ 1 ] . clone ( ) , true )
301
301
. eval ( builder, local. is_valid ) ;
302
302
}
303
303
}
@@ -560,19 +560,26 @@ impl<F: PrimeField32> TraceFiller<F> for MemcpyIterFiller {
560
560
let mut sizes = Vec :: with_capacity ( rows_used >> 1 ) ;
561
561
let mut chunks = Vec :: with_capacity ( rows_used >> 1 ) ;
562
562
563
+ let mut num_loops: usize = 0 ;
564
+ let mut num_iters: usize = 0 ;
565
+
563
566
while !trace. is_empty ( ) {
564
567
let record: & MemcpyIterRecordHeader = unsafe { get_record_from_slice ( & mut trace, ( ) ) } ;
565
568
let num_rows = ( ( record. len - record. shift as u32 ) >> 4 ) as usize + 1 ;
566
569
let ( chunk, rest) = trace. split_at_mut ( width * num_rows as usize ) ;
567
570
sizes. push ( num_rows) ;
568
571
chunks. push ( chunk) ;
569
572
trace = rest;
573
+ num_loops += 1 ;
574
+ num_iters += num_rows;
570
575
}
571
-
576
+ tracing:: info!( "num_loops: {:?}, num_iters: {:?}" , num_loops, num_iters) ;
577
+
572
578
chunks
573
579
. par_iter_mut ( )
574
580
. zip ( sizes. par_iter ( ) )
575
- . for_each ( |( chunk, & num_rows) | {
581
+ . enumerate ( )
582
+ . for_each ( |( row_idx, ( chunk, & num_rows) ) | {
576
583
let record: MemcpyIterRecordMut = unsafe {
577
584
get_record_from_slice (
578
585
chunk,
@@ -694,7 +701,7 @@ impl<F: PrimeField32> TraceFiller<F> for MemcpyIterFiller {
694
701
} else {
695
702
F :: ZERO
696
703
} ;
697
- cols. is_shift_zero = F :: from_canonical_u8 ( ( record. inner . shift = = 0 ) as u8 ) ;
704
+ cols. is_shift_non_zero = F :: from_canonical_u8 ( ( record. inner . shift ! = 0 ) as u8 ) ;
698
705
cols. is_valid_not_start = F :: from_canonical_u8 ( 1 - is_start as u8 ) ;
699
706
cols. is_valid = F :: ONE ;
700
707
cols. shift = [ record. inner . shift & 1 , record. inner . shift >> 1 ]
@@ -707,8 +714,77 @@ impl<F: PrimeField32> TraceFiller<F> for MemcpyIterFiller {
707
714
dest -= 16 ;
708
715
source -= 16 ;
709
716
len += 16 ;
717
+
718
+ if row_idx == 0 && is_start {
719
+ tracing:: info!( "first_roooooow, timestamp: {:?}, dest: {:?}, source: {:?}, len_0: {:?}, len_1: {:?}, shift: {:?}, is_valid: {:?}, is_valid_not_start: {:?}, is_shift_non_zero: {:?}, is_boundary: {:?}, data_1: {:?}, data_2: {:?}, data_3: {:?}, data_4: {:?}, read_aux: {:?}, read_aux_lt: {:?}" ,
720
+ cols. timestamp. as_canonical_u32( ) ,
721
+ cols. dest. as_canonical_u32( ) ,
722
+ cols. source. as_canonical_u32( ) ,
723
+ cols. len[ 0 ] . as_canonical_u32( ) ,
724
+ cols. len[ 1 ] . as_canonical_u32( ) ,
725
+ cols. shift[ 1 ] . as_canonical_u32( ) * 2 + cols. shift[ 0 ] . as_canonical_u32( ) ,
726
+ cols. is_valid. as_canonical_u32( ) ,
727
+ cols. is_valid_not_start. as_canonical_u32( ) ,
728
+ cols. is_shift_non_zero. as_canonical_u32( ) ,
729
+ cols. is_boundary. as_canonical_u32( ) ,
730
+ cols. data_1. map( |x| x. as_canonical_u32( ) ) . to_vec( ) ,
731
+ cols. data_2. map( |x| x. as_canonical_u32( ) ) . to_vec( ) ,
732
+ cols. data_3. map( |x| x. as_canonical_u32( ) ) . to_vec( ) ,
733
+ cols. data_4. map( |x| x. as_canonical_u32( ) ) . to_vec( ) ,
734
+ cols. read_aux. map( |x| x. get_base( ) . prev_timestamp. as_canonical_u32( ) ) . to_vec( ) ,
735
+ cols. read_aux. map( |x| x. get_base( ) . timestamp_lt_aux. lower_decomp. iter( ) . map( |x| x. as_canonical_u32( ) ) . collect:: <Vec <_>>( ) ) . to_vec( ) ) ;
736
+ }
710
737
} ) ;
711
738
} ) ;
739
+ chunks. iter ( ) . enumerate ( ) . map ( |( row_idx, chunk) | {
740
+ chunk. chunks_exact ( width)
741
+ . enumerate ( )
742
+ . for_each ( |( idx, row) | {
743
+ let cols: & MemcpyIterCols < F > = row. borrow ( ) ;
744
+ let is_valid_not_start = cols. is_valid_not_start . as_canonical_u32 ( ) != 0 ;
745
+ let is_shift_non_zero = cols. is_shift_non_zero . as_canonical_u32 ( ) != 0 ;
746
+ let mut bad_col = false ;
747
+ cols. read_aux . iter ( ) . enumerate ( ) . for_each ( |( idx, aux) | {
748
+ if is_valid_not_start || ( is_shift_non_zero && idx == 3 ) {
749
+ let prev_t = aux. get_base ( ) . prev_timestamp . as_canonical_u32 ( ) ;
750
+ let curr_t = cols. timestamp . as_canonical_u32 ( ) ;
751
+ let ts_lt = aux. get_base ( ) . timestamp_lt_aux . lower_decomp . iter ( )
752
+ . enumerate ( )
753
+ . fold ( F :: ZERO , |acc, ( i, & val) | {
754
+ acc + val * F :: from_canonical_usize ( 1 << ( i * 17 ) )
755
+ } ) . as_canonical_u32 ( ) ;
756
+ if curr_t + idx as u32 != ts_lt + prev_t + 1 {
757
+ bad_col = true ;
758
+ }
759
+ }
760
+ } ) ;
761
+ if bad_col {
762
+ tracing:: info!( "row_idx: {:?}, idx: {:?}, timestamp: {:?}, dest: {:?}, source: {:?}, len_0: {:?}, len_1: {:?}, shift_0: {:?}, shift_1: {:?}, is_valid: {:?}, is_valid_not_start: {:?}, is_shift_non_zero: {:?}, is_boundary: {:?}, data_1: {:?}, data_2: {:?}, data_3: {:?}, data_4: {:?}, read_aux: {:?}, read_aux_lt: {:?}" ,
763
+ row_idx,
764
+ idx,
765
+ cols. timestamp. as_canonical_u32( ) ,
766
+ cols. dest. as_canonical_u32( ) ,
767
+ cols. source. as_canonical_u32( ) ,
768
+ cols. len[ 0 ] . as_canonical_u32( ) ,
769
+ cols. len[ 1 ] . as_canonical_u32( ) ,
770
+ cols. shift[ 0 ] . as_canonical_u32( ) ,
771
+ cols. shift[ 1 ] . as_canonical_u32( ) ,
772
+ cols. is_valid. as_canonical_u32( ) ,
773
+ cols. is_valid_not_start. as_canonical_u32( ) ,
774
+ cols. is_shift_non_zero. as_canonical_u32( ) ,
775
+ cols. is_boundary. as_canonical_u32( ) ,
776
+ cols. data_1. map( |x| x. as_canonical_u32( ) ) . to_vec( ) ,
777
+ cols. data_2. map( |x| x. as_canonical_u32( ) ) . to_vec( ) ,
778
+ cols. data_3. map( |x| x. as_canonical_u32( ) ) . to_vec( ) ,
779
+ cols. data_4. map( |x| x. as_canonical_u32( ) ) . to_vec( ) ,
780
+ cols. read_aux. map( |x| x. get_base( ) . prev_timestamp. as_canonical_u32( ) ) . to_vec( ) ,
781
+ cols. read_aux. map( |x| x. get_base( ) . timestamp_lt_aux. lower_decomp. iter( ) . map( |x| x. as_canonical_u32( ) ) . collect:: <Vec <_>>( ) ) . to_vec( ) ) ;
782
+ // cols.write_aux.map(|x| x.get_base().prev_timestamp.as_canonical_u32()).to_vec(),
783
+ // cols.write_aux.map(|x| x.prev_data.map(|x| x.as_canonical_u32()).to_vec()).to_vec());
784
+ }
785
+ } ) ;
786
+ } ) ;
787
+ // assert!(false);
712
788
}
713
789
}
714
790
0 commit comments