use crate::{BusDevice, CheckPoint, ChunkId, PayloadType, StatsType};
use proofman_common::{AirInstance, ProofCtx, ProofmanResult, SetupCtx};
use proofman_fields::PrimeField64;
use std::any::Any;
#[derive(Debug, PartialEq)]
pub enum InstanceType {
Instance,
Table,
}
pub trait Instance<F: PrimeField64>: Any + Send + Sync {
fn compute_witness(
&self,
_pctx: &ProofCtx<F>,
_sctx: &SetupCtx<F>,
_collectors: Vec<(usize, Box<dyn BusDevice<PayloadType>>)>,
_trace_buffer: Vec<F>,
_packed: bool,
) -> ProofmanResult<Option<AirInstance<F>>> {
Ok(None)
}
fn check_point(&self) -> &CheckPoint;
fn instance_type(&self) -> InstanceType;
fn build_inputs_collector(
&self,
_chunk_id: ChunkId,
) -> Option<Box<dyn BusDevice<PayloadType>>> {
None
}
fn debug(&self, _pctx: &ProofCtx<F>, _sctx: &SetupCtx<F>) {}
fn as_any(&self) -> &dyn Any;
fn stats_type(&self) -> StatsType {
StatsType::Other
}
fn reset(&self) {}
}
#[macro_export]
macro_rules! table_instance {
($InstanceName:ident, $TableSM:ident, $Trace:ident) => {
use std::collections::VecDeque;
use std::sync::Arc;
use proofman_fields::PrimeField64;
use proofman_common::{AirInstance, FromTrace, ProofCtx, SetupCtx};
use zisk_common::{
BusDevice, BusId, CheckPoint, Instance, InstanceCtx, InstanceType, PayloadType,
};
use zisk_pil::$Trace;
use rayon::prelude::*;
pub struct $InstanceName {
/// The table state machine.
table_sm: Arc<$TableSM>,
ictx: InstanceCtx,
bus_id: BusId,
}
impl $InstanceName {
pub fn new(table_sm: Arc<$TableSM>, ictx: InstanceCtx, bus_id: BusId) -> Self {
Self { table_sm, ictx, bus_id }
}
pub fn process_data(&mut self, _bus_id: &BusId, _data: &[u64]) -> bool {
true
}
}
impl<F: PrimeField64> Instance<F> for $InstanceName {
fn compute_witness(
&self,
pctx: &ProofCtx<F>,
_sctx: &SetupCtx<F>,
_collectors: Vec<(usize, Box<dyn BusDevice<PayloadType>>)>,
_trace_buffer: Vec<F>,
_packed: bool,
) -> ProofmanResult<Option<AirInstance<F>>> {
let multiplicity = self.table_sm.detach_multiplicity();
self.table_sm.set_calculated();
pctx.dctx_distribute_multiplicity(multiplicity, self.ictx.global_id);
if pctx.dctx_is_my_instance(self.ictx.global_id) {
let mut trace = $Trace::new();
trace.row_slice_mut().par_iter_mut().enumerate().for_each(|(i, input)| {
input.multiplicity = F::from_u64(
multiplicity[i].swap(0, std::sync::atomic::Ordering::Relaxed),
)
});
Ok(Some(AirInstance::new_from_trace(FromTrace::new(&mut trace))))
} else {
multiplicity.par_iter().for_each(|m| {
m.swap(0, std::sync::atomic::Ordering::Relaxed);
});
Ok(None)
}
}
fn check_point(&self) -> &CheckPoint {
&self.ictx.plan.check_point
}
fn instance_type(&self) -> InstanceType {
InstanceType::Table
}
fn reset(&self) {
self.table_sm.reset_calculated();
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
impl BusDevice<u64> for $InstanceName {
fn as_any(self: Box<Self>) -> Box<dyn std::any::Any> {
self
}
}
};
}
#[macro_export]
macro_rules! table_instance_array {
($InstanceName:ident, $TableSM:ident, $Trace:ident) => {
use std::collections::VecDeque;
use std::sync::Arc;
use proofman_fields::PrimeField64;
use proofman_common::{AirInstance, ProofCtx, SetupCtx, TraceInfo};
use zisk_common::{
BusDevice, BusId, CheckPoint, Instance, InstanceCtx, InstanceType, PayloadType,
};
use zisk_pil::$Trace;
use rayon::prelude::*;
pub struct $InstanceName {
/// The table state machine.
table_sm: Arc<$TableSM>,
ictx: InstanceCtx,
bus_id: BusId,
}
impl $InstanceName {
pub fn new(table_sm: Arc<$TableSM>, ictx: InstanceCtx, bus_id: BusId) -> Self {
Self { table_sm, ictx, bus_id }
}
pub fn process_data(&mut self, bus_id: &BusId, data: &[u64]) -> bool {
true
}
}
impl<F: PrimeField64> Instance<F> for $InstanceName {
fn compute_witness(
&self,
pctx: &ProofCtx<F>,
_sctx: &SetupCtx<F>,
_collectors: Vec<(usize, Box<dyn BusDevice<PayloadType>>)>,
_trace_buffer: Vec<F>,
_packed: bool,
) -> ProofmanResult<Option<AirInstance<F>>> {
let multiplicities = self.table_sm.detach_multiplicities();
self.table_sm.set_calculated();
pctx.dctx_distribute_multiplicities(multiplicities, self.ictx.global_id);
if pctx.dctx_is_my_instance(self.ictx.global_id) {
let mut trace = $Trace::new();
let mut buffer = trace.get_buffer();
buffer.par_chunks_mut(trace.row_size).enumerate().for_each(|(row, chunk)| {
for (col, vec) in multiplicities.iter().enumerate() {
chunk[col] =
F::from_u64(vec[row].swap(0, std::sync::atomic::Ordering::Relaxed));
}
});
Ok(Some(AirInstance::new(TraceInfo::new(
trace.airgroup_id,
trace.air_id,
buffer,
false,
))))
} else {
multiplicities.par_iter().for_each(|vec| {
for i in 0..vec.len() {
vec[i].swap(0, std::sync::atomic::Ordering::Relaxed);
}
});
Ok(None)
}
}
fn check_point(&self) -> &CheckPoint {
&self.ictx.plan.check_point
}
fn instance_type(&self) -> InstanceType {
InstanceType::Table
}
fn reset(&self) {
self.table_sm.reset_calculated();
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
impl BusDevice<u64> for $InstanceName {
fn as_any(self: Box<Self>) -> Box<dyn std::any::Any> {
self
}
}
};
}
#[macro_export]
macro_rules! instance {
($name:ident, $sm:ty, $num_rows:path, $operation:path) => {
use proofman_common::{AirInstance, ProofCtx};
use sm_common::{CheckPointSkip, Instance, InstanceType};
use $crate::BusId;
pub struct $name {
/// The state machine.
sm: Arc<$sm>,
ictx: InstanceCtx,
inputs: Vec<zisk_core::ZiskRequiredOperation>,
}
impl<F: PrimeField64> $name<F> {
pub fn new(sm: Arc<$sm>, ictx: InstanceCtx) -> Self {
Self { sm, ictx, inputs: Vec::new() }
}
}
impl<F: PrimeField64> Instance<F> for $name {
fn compute_witness(
&self,
_pctx: &ProofCtx<F>,
_sctx: &SetupCtx<F>,
) -> ProofmanResult<Option<AirInstance<F>>> {
Some(self.sm.compute_witness(&self.inputs))
}
fn check_point(&self) -> Option<CheckPointSkip> {
self.ictx.plan.check_point
}
fn instance_type(&self) -> InstanceType {
InstanceType::Instance
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
impl<F: PrimeField64> $crate::BusDevice<u64> for $name {}
};
}