Skip to content

Commit bac0ffb

Browse files
committed
Fix missing instructions
1 parent 9039365 commit bac0ffb

File tree

1 file changed

+24
-48
lines changed

1 file changed

+24
-48
lines changed

openvm/src/empirical_constraints.rs

Lines changed: 24 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use itertools::Itertools;
22
use openvm_circuit::arch::VmCircuitConfig;
33
use openvm_sdk::StdIn;
4+
use openvm_stark_backend::p3_maybe_rayon::prelude::IntoParallelIterator;
5+
use openvm_stark_backend::p3_maybe_rayon::prelude::ParallelIterator;
46
use openvm_stark_sdk::openvm_stark_backend::p3_field::PrimeField32;
57
use powdr_autoprecompiles::empirical_constraints::{
68
intersect_partitions, DebugInfo, EmpiricalConstraints,
@@ -91,26 +93,29 @@ fn collect_trace(program: &CompiledProgram, inputs: StdIn) -> (Trace, DebugInfo)
9193
.collect::<HashMap<_, _>>();
9294

9395
for (air_id, proving_context) in &ctx.per_air {
94-
if !proving_context.cached_mains.is_empty() {
95-
// Not the case for instruction circuits
96-
continue;
97-
}
98-
let main = proving_context.common_main.as_ref().unwrap();
99-
10096
let air = &global_airs[air_id];
10197
let Some(column_names) = air.columns() else {
98+
// Instruction chips always have column names.
10299
continue;
103100
};
101+
102+
if !proving_context.cached_mains.is_empty() {
103+
// Instruction chips always have a cached main.
104+
continue;
105+
}
106+
let main = proving_context.common_main.as_ref().unwrap();
104107
assert_eq!(main.width, column_names.len());
105108

106-
// This is the case for all instruction circuits
107-
let Some(pc_index) = column_names
108-
.iter()
109-
.position(|name| name == "from_state__pc")
110-
else {
109+
// Instruction chips have a PC and time stamp
110+
let find_col = |name: &str| -> Option<usize> {
111+
column_names.iter().position(|col_name| {
112+
col_name == name || col_name == &format!("inner__{}", name)
113+
})
114+
};
115+
let Some(pc_index) = find_col("from_state__pc") else {
111116
continue;
112117
};
113-
let ts_index = 1;
118+
let ts_index = find_col("from_state__timestamp").unwrap();
114119

115120
for row in main.row_slices() {
116121
let row = row.iter().map(|v| v.as_canonical_u32()).collect::<Vec<_>>();
@@ -222,8 +227,11 @@ impl ConstraintDetector {
222227
&self,
223228
trace: &Trace,
224229
) -> BTreeMap<u64, BTreeSet<BTreeSet<(usize, usize)>>> {
225-
self.get_blocks(trace)
226-
.into_iter()
230+
tracing::info!(" Segmenting trace into blocks...");
231+
let blocks = self.get_blocks(trace);
232+
tracing::info!(" Finding equivalence classes...");
233+
blocks
234+
.into_par_iter()
227235
.map(|(block_id, block_instances)| {
228236
// Segment each block instance into equivalence classes
229237
let classes = block_instances
@@ -252,36 +260,15 @@ impl ConstraintDetector {
252260
let mut row_index = 0;
253261
let rows_by_time = trace.rows_by_time();
254262

255-
// Maps Block ID -> (successful instances, unsuccessful instances) for reporting
256-
let mut block_stats = BTreeMap::new();
257-
258263
while row_index < rows_by_time.len() {
259264
let first_row = rows_by_time[row_index];
260265
let block_id = first_row.pc as u64;
261266

262267
if let Some(instruction_count) = self.instruction_counts.get(&block_id) {
263268
let block_row_slice = &rows_by_time[row_index..row_index + instruction_count];
264269

265-
// Check that we do indeed have all instructions of the block
266-
// TODO: I'm not sure in which cases don't have them. In practice, this seems to
267-
// happen rarely.
268-
let has_all_instructions = block_row_slice
269-
.iter()
270-
.tuple_windows()
271-
.all(|(row1, row2)| row2.pc == row1.pc + 4);
272-
if !has_all_instructions {
273-
// Incomplete block instance, skip.
274-
row_index += 1;
275-
block_stats
276-
.entry(block_id)
277-
.and_modify(|(_successful, unsuccessful)| *unsuccessful += 1)
278-
.or_insert((0, 1));
279-
continue;
280-
} else {
281-
block_stats
282-
.entry(block_id)
283-
.and_modify(|(successful, _unsuccessful)| *successful += 1)
284-
.or_insert((1, 0));
270+
for (row1, row2) in block_row_slice.iter().tuple_windows() {
271+
assert_eq!(row2.pc, row1.pc + 4);
285272
}
286273

287274
block_rows
@@ -295,17 +282,6 @@ impl ConstraintDetector {
295282
}
296283
}
297284

298-
for (block_id, (successful, unsuccessful)) in block_stats {
299-
if unsuccessful > 0 {
300-
tracing::warn!(
301-
" Block {:#x}: {} / {} instances skipped due to incomplete execution",
302-
block_id,
303-
unsuccessful,
304-
unsuccessful + successful
305-
);
306-
}
307-
}
308-
309285
block_rows
310286
}
311287

0 commit comments

Comments
 (0)