@@ -1576,6 +1576,9 @@ pub struct Traces {
15761576 /// CPU execution traces (split into chunks of max_rows::CPU)
15771577 pub cpus : Vec < TraceTable < GoldilocksField , GoldilocksExtension > > ,
15781578
1579+ /// CPU_BITWISE traces for AND/OR/XOR instructions (split into chunks)
1580+ pub cpu_bitwises : Vec < TraceTable < GoldilocksField , GoldilocksExtension > > ,
1581+
15791582 /// BITWISE precomputed lookup table (2^20 rows)
15801583 pub bitwise : TraceTable < GoldilocksField , GoldilocksExtension > ,
15811584
@@ -1646,6 +1649,7 @@ impl Traces {
16461649 pub fn table_counts ( & self ) -> crate :: TableCounts {
16471650 crate :: TableCounts {
16481651 cpu : self . cpus . len ( ) ,
1652+ cpu_bitwise : self . cpu_bitwises . len ( ) ,
16491653 lt : self . lts . len ( ) ,
16501654 memw : self . memws . len ( ) ,
16511655 memw_aligned : self . memw_aligneds . len ( ) ,
@@ -1908,14 +1912,6 @@ impl Traces {
19081912 // COMMIT table sends IsByte and IsHalfword lookups
19091913 bitwise_ops. extend ( collect_bitwise_from_commit ( & commit_ops) ) ;
19101914
1911- // CPU padding rows send IS_BYTE with all-zero values.
1912- // Add corresponding ops so the bitwise table multiplicities balance.
1913- let num_padding_rows: usize = cpu_ops
1914- . chunks ( max_rows. cpu )
1915- . map ( |chunk| chunk. len ( ) . next_power_of_two ( ) . max ( 4 ) - chunk. len ( ) )
1916- . sum ( ) ;
1917- bitwise_ops. extend ( collect_byte_check_ops_for_padding ( num_padding_rows) ) ;
1918-
19191915 // =====================================================================
19201916 // PHASE 5: Generate final traces (parallelized)
19211917 // =====================================================================
@@ -1928,7 +1924,28 @@ impl Traces {
19281924 . ok_or ( Error :: MissingHaltEcall ) ?;
19291925 let halt_timestamp = halt_op. timestamp ;
19301926
1927+ // Route bitwise instructions (AND, OR, XOR) to CPU_BITWISE chip
1928+ let ( cpu_bitwise_ops, cpu_ops) : ( Vec < _ > , Vec < _ > ) =
1929+ cpu_ops. into_iter ( ) . partition ( |op| op. is_bitwise ( ) ) ;
1930+
1931+ // CPU and CPU_BITWISE padding rows send IS_BYTE with all-zero values.
1932+ // Computed after partition so padding reflects actual chunk sizes.
1933+ let num_padding_rows: usize = cpu_ops
1934+ . chunks ( max_rows. cpu )
1935+ . map ( |chunk| chunk. len ( ) . next_power_of_two ( ) . max ( 4 ) - chunk. len ( ) )
1936+ . sum :: < usize > ( )
1937+ + cpu_bitwise_ops
1938+ . chunks ( max_rows. cpu )
1939+ . map ( |chunk| chunk. len ( ) . next_power_of_two ( ) . max ( 4 ) - chunk. len ( ) )
1940+ . sum :: < usize > ( ) ;
1941+ bitwise_ops. extend ( collect_byte_check_ops_for_padding ( num_padding_rows) ) ;
1942+
19311943 let cpus = chunk_and_generate ( & cpu_ops, max_rows. cpu , cpu:: generate_cpu_trace) ;
1944+ let cpu_bitwises = if cpu_bitwise_ops. is_empty ( ) {
1945+ Vec :: new ( )
1946+ } else {
1947+ chunk_and_generate ( & cpu_bitwise_ops, max_rows. cpu , cpu:: generate_cpu_trace)
1948+ } ;
19321949 let memws = chunk_and_generate ( & memw_ops, max_rows. memw , memw:: generate_memw_trace) ;
19331950 let memw_aligneds = chunk_and_generate (
19341951 & memw_aligned_ops,
@@ -1952,16 +1969,21 @@ impl Traces {
19521969 bitwise:: update_multiplicities ( & mut bitwise, & bitwise_ops) ;
19531970
19541971 // Update DECODE multiplicities
1955- // Each CPU operation looks up the DECODE table once
1956- // Padding rows also look up pc=1 (the CPU padding entry)
1957- // When CPU is split, each chunk pads independently
1972+ // Each CPU operation (from both CPU and CPU_BITWISE chips) looks up the DECODE table once.
1973+ // Padding rows also look up pc=1 (the CPU padding entry).
1974+ // When CPU is split, each chunk pads independently.
19581975 let mut decode = decode_trace;
19591976 let pc_to_row = decode_pc_to_row;
19601977 let num_padding_rows: usize = cpu_ops
19611978 . chunks ( max_rows. cpu )
19621979 . map ( |chunk| chunk. len ( ) . next_power_of_two ( ) . max ( 4 ) - chunk. len ( ) )
1963- . sum ( ) ;
1980+ . sum :: < usize > ( )
1981+ + cpu_bitwise_ops
1982+ . chunks ( max_rows. cpu )
1983+ . map ( |chunk| chunk. len ( ) . next_power_of_two ( ) . max ( 4 ) - chunk. len ( ) )
1984+ . sum :: < usize > ( ) ;
19641985 let mut decode_lookups: Vec < u64 > = cpu_ops. iter ( ) . map ( |op| op. decode . pc ) . collect ( ) ;
1986+ decode_lookups. extend ( cpu_bitwise_ops. iter ( ) . map ( |op| op. decode . pc ) ) ;
19651987 decode_lookups. extend ( std:: iter:: repeat_n ( cpu:: CPU_PADDING_PC , num_padding_rows) ) ;
19661988 decode:: update_multiplicities ( & mut decode, & pc_to_row, & decode_lookups) ;
19671989
@@ -2006,6 +2028,7 @@ impl Traces {
20062028
20072029 Ok ( Traces {
20082030 cpus,
2031+ cpu_bitwises,
20092032 bitwise,
20102033 lts,
20112034 shifts,
@@ -2152,13 +2175,6 @@ impl Traces {
21522175 // COMMIT table sends IsHalfword lookups
21532176 bitwise_ops. extend ( collect_bitwise_from_commit ( & commit_ops) ) ;
21542177
2155- // CPU padding rows send IS_BYTE with all-zero values.
2156- let num_padding_rows: usize = cpu_ops
2157- . chunks ( max_rows. cpu )
2158- . map ( |chunk| chunk. len ( ) . next_power_of_two ( ) . max ( 4 ) - chunk. len ( ) )
2159- . sum ( ) ;
2160- bitwise_ops. extend ( collect_byte_check_ops_for_padding ( num_padding_rows) ) ;
2161-
21622178 // =====================================================================
21632179 // PHASE 5: Generate final traces (parallelized)
21642180 // =====================================================================
@@ -2171,7 +2187,27 @@ impl Traces {
21712187 . ok_or ( Error :: MissingHaltEcall ) ?;
21722188 let halt_timestamp = halt_op. timestamp ;
21732189
2190+ // Route bitwise instructions (AND, OR, XOR) to CPU_BITWISE chip
2191+ let ( cpu_bitwise_ops, cpu_ops) : ( Vec < _ > , Vec < _ > ) =
2192+ cpu_ops. into_iter ( ) . partition ( |op| op. is_bitwise ( ) ) ;
2193+
2194+ // CPU and CPU_BITWISE padding rows send IS_BYTE with all-zero values.
2195+ let num_padding_rows: usize = cpu_ops
2196+ . chunks ( max_rows. cpu )
2197+ . map ( |chunk| chunk. len ( ) . next_power_of_two ( ) . max ( 4 ) - chunk. len ( ) )
2198+ . sum :: < usize > ( )
2199+ + cpu_bitwise_ops
2200+ . chunks ( max_rows. cpu )
2201+ . map ( |chunk| chunk. len ( ) . next_power_of_two ( ) . max ( 4 ) - chunk. len ( ) )
2202+ . sum :: < usize > ( ) ;
2203+ bitwise_ops. extend ( collect_byte_check_ops_for_padding ( num_padding_rows) ) ;
2204+
21742205 let cpus = chunk_and_generate ( & cpu_ops, max_rows. cpu , cpu:: generate_cpu_trace) ;
2206+ let cpu_bitwises = if cpu_bitwise_ops. is_empty ( ) {
2207+ Vec :: new ( )
2208+ } else {
2209+ chunk_and_generate ( & cpu_bitwise_ops, max_rows. cpu , cpu:: generate_cpu_trace)
2210+ } ;
21752211 let memws = chunk_and_generate ( & memw_ops, max_rows. memw , memw:: generate_memw_trace) ;
21762212 let memw_aligneds = chunk_and_generate (
21772213 & memw_aligned_ops,
@@ -2195,15 +2231,18 @@ impl Traces {
21952231 bitwise:: update_multiplicities ( & mut bitwise, & bitwise_ops) ;
21962232
21972233 // Generate DECODE trace and update multiplicities
2198- // Each CPU operation looks up the DECODE table once
2199- // Padding rows also look up pc=1 (the CPU padding entry)
2200- // When CPU is split, each chunk pads independently
2234+ // Both CPU and CPU_BITWISE chips look up DECODE once per row
22012235 let ( mut decode, pc_to_row) = decode:: generate_decode_trace ( & instructions) ;
22022236 let num_padding_rows: usize = cpu_ops
22032237 . chunks ( max_rows. cpu )
22042238 . map ( |chunk| chunk. len ( ) . next_power_of_two ( ) . max ( 4 ) - chunk. len ( ) )
2205- . sum ( ) ;
2239+ . sum :: < usize > ( )
2240+ + cpu_bitwise_ops
2241+ . chunks ( max_rows. cpu )
2242+ . map ( |chunk| chunk. len ( ) . next_power_of_two ( ) . max ( 4 ) - chunk. len ( ) )
2243+ . sum :: < usize > ( ) ;
22062244 let mut decode_lookups: Vec < u64 > = cpu_ops. iter ( ) . map ( |op| op. decode . pc ) . collect ( ) ;
2245+ decode_lookups. extend ( cpu_bitwise_ops. iter ( ) . map ( |op| op. decode . pc ) ) ;
22072246 decode_lookups. extend ( std:: iter:: repeat_n ( cpu:: CPU_PADDING_PC , num_padding_rows) ) ;
22082247 decode:: update_multiplicities ( & mut decode, & pc_to_row, & decode_lookups) ;
22092248 let register_final_state = register_state. to_final_state_map ( ) ;
@@ -2235,6 +2274,7 @@ impl Traces {
22352274
22362275 Ok ( Traces {
22372276 cpus,
2277+ cpu_bitwises,
22382278 bitwise,
22392279 lts,
22402280 shifts,
0 commit comments