|
1 |
| -use std::{borrow::BorrowMut, cmp::max, sync::Arc}; |
| 1 | +use std::{borrow::BorrowMut, cmp::max, io::Cursor, sync::Arc}; |
2 | 2 |
|
3 | 3 | pub use air::*;
|
4 | 4 | pub use columns::*;
|
@@ -145,6 +145,39 @@ impl<F> AccessAdapterInventory<F> {
|
145 | 145 | None
|
146 | 146 | }
|
147 | 147 | }
|
| 148 | + |
| 149 | + pub(crate) fn execute_split( |
| 150 | + &mut self, |
| 151 | + address: MemoryAddress<u32, u32>, |
| 152 | + values: &[F], |
| 153 | + timestamp: u32, |
| 154 | + row_slice: &mut [F], |
| 155 | + ) where |
| 156 | + F: PrimeField32, |
| 157 | + { |
| 158 | + let index = get_chip_index(values.len()); |
| 159 | + self.chips[index].execute_split(address, values, timestamp, row_slice); |
| 160 | + } |
| 161 | + |
| 162 | + pub(crate) fn execute_merge( |
| 163 | + &mut self, |
| 164 | + address: MemoryAddress<u32, u32>, |
| 165 | + values: &[F], |
| 166 | + left_timestamp: u32, |
| 167 | + right_timestamp: u32, |
| 168 | + row_slice: &mut [F], |
| 169 | + ) where |
| 170 | + F: PrimeField32, |
| 171 | + { |
| 172 | + let index = get_chip_index(values.len()); |
| 173 | + self.chips[index].execute_merge( |
| 174 | + address, |
| 175 | + values, |
| 176 | + left_timestamp, |
| 177 | + right_timestamp, |
| 178 | + row_slice, |
| 179 | + ); |
| 180 | + } |
148 | 181 | }
|
149 | 182 |
|
150 | 183 | #[derive(Debug, Clone, PartialEq, Eq)]
|
@@ -173,6 +206,25 @@ pub trait GenericAccessAdapterChipTrait<F> {
|
173 | 206 | fn generate_trace(self) -> RowMajorMatrix<F>
|
174 | 207 | where
|
175 | 208 | F: PrimeField32;
|
| 209 | + |
| 210 | + fn execute_split( |
| 211 | + &mut self, |
| 212 | + address: MemoryAddress<u32, u32>, |
| 213 | + values: &[F], |
| 214 | + timestamp: u32, |
| 215 | + row_slice: &mut [F], |
| 216 | + ) where |
| 217 | + F: PrimeField32; |
| 218 | + |
| 219 | + fn execute_merge( |
| 220 | + &mut self, |
| 221 | + address: MemoryAddress<u32, u32>, |
| 222 | + values: &[F], |
| 223 | + left_timestamp: u32, |
| 224 | + right_timestamp: u32, |
| 225 | + row_slice: &mut [F], |
| 226 | + ) where |
| 227 | + F: PrimeField32; |
176 | 228 | }
|
177 | 229 |
|
178 | 230 | #[derive(Chip, ChipUsageGetter)]
|
@@ -216,6 +268,7 @@ impl<F> GenericAccessAdapterChip<F> {
|
216 | 268 | }
|
217 | 269 | }
|
218 | 270 | }
|
| 271 | + |
219 | 272 | pub struct AccessAdapterChip<F, const N: usize> {
|
220 | 273 | air: AccessAdapterAir<N>,
|
221 | 274 | range_checker: SharedVariableRangeCheckerChip,
|
@@ -294,6 +347,72 @@ impl<F, const N: usize> GenericAccessAdapterChipTrait<F> for AccessAdapterChip<F
|
294 | 347 | });
|
295 | 348 | RowMajorMatrix::new(values, width)
|
296 | 349 | }
|
| 350 | + |
| 351 | + fn execute_split( |
| 352 | + &mut self, |
| 353 | + address: MemoryAddress<u32, u32>, |
| 354 | + values: &[F], |
| 355 | + timestamp: u32, |
| 356 | + row_slice: &mut [F], |
| 357 | + ) where |
| 358 | + F: PrimeField32, |
| 359 | + { |
| 360 | + let row: &mut AccessAdapterCols<F, N> = row_slice.borrow_mut(); |
| 361 | + row.is_valid = F::ONE; |
| 362 | + row.is_split = F::ONE; |
| 363 | + row.address = MemoryAddress::new( |
| 364 | + F::from_canonical_u32(address.address_space), |
| 365 | + F::from_canonical_u32(address.pointer), |
| 366 | + ); |
| 367 | + let timestamp = F::from_canonical_u32(timestamp); |
| 368 | + row.left_timestamp = timestamp; |
| 369 | + row.right_timestamp = timestamp; |
| 370 | + row.is_right_larger = F::ZERO; |
| 371 | + debug_assert_eq!( |
| 372 | + values.len(), |
| 373 | + N, |
| 374 | + "Input values slice length must match the access adapter type" |
| 375 | + ); |
| 376 | + |
| 377 | + // SAFETY: `values` slice is asserted to have length N. `row.values` is an array of length |
| 378 | + // N. Pointers are valid and regions do not overlap because exactly one of them is a |
| 379 | + // part of the trace. |
| 380 | + unsafe { |
| 381 | + std::ptr::copy_nonoverlapping(values.as_ptr(), row.values.as_mut_ptr(), N); |
| 382 | + } |
| 383 | + } |
| 384 | + |
| 385 | + fn execute_merge( |
| 386 | + &mut self, |
| 387 | + address: MemoryAddress<u32, u32>, |
| 388 | + values: &[F], |
| 389 | + left_timestamp: u32, |
| 390 | + right_timestamp: u32, |
| 391 | + row_slice: &mut [F], |
| 392 | + ) where |
| 393 | + F: PrimeField32, |
| 394 | + { |
| 395 | + let row: &mut AccessAdapterCols<F, N> = row_slice.borrow_mut(); |
| 396 | + row.is_valid = F::ONE; |
| 397 | + row.is_split = F::ZERO; |
| 398 | + row.address = MemoryAddress::new( |
| 399 | + F::from_canonical_u32(address.address_space), |
| 400 | + F::from_canonical_u32(address.pointer), |
| 401 | + ); |
| 402 | + row.left_timestamp = F::from_canonical_u32(left_timestamp); |
| 403 | + row.right_timestamp = F::from_canonical_u32(right_timestamp); |
| 404 | + debug_assert_eq!( |
| 405 | + values.len(), |
| 406 | + N, |
| 407 | + "Input values slice length must match the access adapter type" |
| 408 | + ); |
| 409 | + // SAFETY: `values` slice is asserted to have length N. `row.values` is an array of length |
| 410 | + // N. Pointers are valid and regions do not overlap because exactly one of them is a |
| 411 | + // part of the trace. |
| 412 | + unsafe { |
| 413 | + std::ptr::copy_nonoverlapping(values.as_ptr(), row.values.as_mut_ptr(), N); |
| 414 | + } |
| 415 | + } |
297 | 416 | }
|
298 | 417 |
|
299 | 418 | impl<SC: StarkGenericConfig, const N: usize> Chip<SC> for AccessAdapterChip<Val<SC>, N>
|
@@ -328,3 +447,42 @@ impl<F, const N: usize> ChipUsageGetter for AccessAdapterChip<F, N> {
|
328 | 447 | fn air_name(n: usize) -> String {
|
329 | 448 | format!("AccessAdapter<{}>", n)
|
330 | 449 | }
|
| 450 | + |
| 451 | +#[inline(always)] |
| 452 | +pub fn get_chip_index(block_size: usize) -> usize { |
| 453 | + assert!( |
| 454 | + block_size.is_power_of_two() && block_size >= 2, |
| 455 | + "Invalid block size {} for split operation", |
| 456 | + block_size |
| 457 | + ); |
| 458 | + let index = block_size.trailing_zeros() - 1; |
| 459 | + index as usize |
| 460 | +} |
| 461 | + |
| 462 | +pub struct AdapterInventoryTraceCursor<F> { |
| 463 | + // [AG] TODO: replace with a pre-allocated space |
| 464 | + cursors: Vec<Cursor<Vec<F>>>, |
| 465 | + widths: Vec<usize>, |
| 466 | +} |
| 467 | + |
| 468 | +impl<F: PrimeField32> AdapterInventoryTraceCursor<F> { |
| 469 | + pub fn new(as_cnt: usize) -> Self { |
| 470 | + let cursors = vec![Cursor::new(Vec::new()); as_cnt]; |
| 471 | + let widths = vec![ |
| 472 | + size_of::<AccessAdapterCols<u8, 2>>(), |
| 473 | + size_of::<AccessAdapterCols<u8, 4>>(), |
| 474 | + size_of::<AccessAdapterCols<u8, 8>>(), |
| 475 | + size_of::<AccessAdapterCols<u8, 16>>(), |
| 476 | + size_of::<AccessAdapterCols<u8, 32>>(), |
| 477 | + ]; |
| 478 | + Self { cursors, widths } |
| 479 | + } |
| 480 | + |
| 481 | + pub fn get_row_slice(&mut self, block_size: usize) -> &mut [F] { |
| 482 | + let index = get_chip_index(block_size); |
| 483 | + let begin = self.cursors[index].position() as usize; |
| 484 | + let end = begin + self.widths[index]; |
| 485 | + self.cursors[index].set_position(end as u64); |
| 486 | + &mut self.cursors[index].get_mut()[begin..end] |
| 487 | + } |
| 488 | +} |
0 commit comments