#[macro_export]
macro_rules! register_precompiles {
(
$(
$variant:ident [
op: $op:expr,
air: $air:expr,
rank_assign: $rank_assign:expr $(,)?
] => $mgr:ty
),* $(,)?
) => {
pub enum Precompiles<F: ::proofman_fields::PrimeField64> {
$(
#[doc = concat!(
"`", stringify!($variant),
"` precompile, backed by `", stringify!($mgr), "`.",
)]
$variant(::std::sync::Arc<$mgr>),
)*
}
impl<F: ::proofman_fields::PrimeField64> Precompiles<F> {
pub fn planner_for_air_id(
air_id: ::std::primitive::usize,
is_asm_emulator: ::std::primitive::bool,
) -> ::std::boxed::Box<dyn ::zisk_common::Planner> {
match air_id {
$(
id if $air.contains(&id) => <$mgr as
::zisk_common::ComponentPlanBuilder<F>>::planner(is_asm_emulator),
)*
_ => panic!("planner_for_air_id: unknown precompile air_id {air_id}"),
}
}
pub fn configure_instances(
&self,
pctx: &::proofman_common::ProofCtx<F>,
plans: &[::zisk_common::Plan],
) {
match self {
$( Self::$variant(sm) => (**sm).configure_instances(pctx, plans), )*
}
}
pub fn build_instance(
&self,
ictx: ::zisk_common::InstanceCtx,
) -> ::std::boxed::Box<dyn ::zisk_common::Instance<F>> {
match self {
$( Self::$variant(sm) => (**sm).build_instance(ictx), )*
}
}
pub(crate) fn all(
std: ::std::sync::Arc<::pil2_std_lib::Std<F>>,
) -> ::std::vec::Vec<(&'static [::std::primitive::usize], Self)> {
::std::vec![
$(
($air, Self::$variant(<$mgr>::new(std.clone()))),
)*
]
}
}
#[allow(dead_code, non_camel_case_types)]
#[repr(usize)]
enum __PrecompileSlot { $( $variant, )* }
pub(crate) const PRECOMPILE_AIR_IDS: &[::std::primitive::usize] = &[
$( $air[0], )*
];
pub(crate) const PRECOMPILE_RANK_ASSIGN: &[::std::primitive::bool] = &[
$( $rank_assign, )*
];
::paste::paste! {
pub struct PrecompileCounters<F: ::proofman_fields::PrimeField64> {
$(
#[doc = concat!(
"Counter for the `", stringify!($variant),
"` precompile: `(bundle_position, ",
stringify!($variant), "CounterInputGen<F>)`.",
)]
pub [<$variant:snake>]: (
::std::primitive::usize,
[<$variant CounterInputGen>]<F>,
),
)*
}
impl<F: ::proofman_fields::PrimeField64> PrecompileCounters<F> {
pub fn build(is_asm_emulator: ::std::primitive::bool) -> Self {
Self {
$(
[<$variant:snake>]: (
$crate::BUILTIN_COUNT + __PrecompileSlot::$variant as usize,
<$mgr as ::zisk_common::ComponentPlanBuilder<F>>::counter(is_asm_emulator),
),
)*
}
}
#[inline(always)]
pub fn dispatch_op(
&mut self,
op_type: ::std::primitive::u32,
bus_id: &::zisk_common::BusId,
data: &[::zisk_common::PayloadType],
mem_counter: ::std::option::Option<&mut ::zisk_sm_mem_common::MemCounters>,
) -> ::std::primitive::bool {
$(
const [<__ $variant:upper _OP>]: ::std::primitive::u32 = $op;
)*
let mut mem_processor =
::zisk_precomp_common::MemCounterProcessor::new(mem_counter);
match op_type {
$(
[<__ $variant:upper _OP>] => self.[<$variant:snake>].1.process_data(
bus_id,
data,
&mut mem_processor,
),
)*
_ => true,
}
}
pub fn into_device_entries(
self,
) -> ::std::vec::Vec<(
::std::primitive::usize,
::std::boxed::Box<dyn ::zisk_common::BusDeviceMetrics>,
)> {
::std::vec![
$(
(
self.[<$variant:snake>].0,
::std::boxed::Box::new(self.[<$variant:snake>].1),
),
)*
]
}
}
pub struct PrecompileCollectors<F: ::proofman_fields::PrimeField64> {
$(
#[doc = concat!(
"Per-chunk collectors for the `", stringify!($variant),
"` precompile, each tagged with the `global_idx` of the ",
"instance it feeds. Populated by `try_push_collector`.",
)]
pub [<$variant:snake _collector>]: ::std::vec::Vec<(
::std::primitive::usize,
[<$variant Collector>],
)>,
#[doc = concat!(
"Input generator for the `", stringify!($variant),
"` precompile. Used by the bus to emit derived mem-ops ",
"on each matching operation message.",
)]
pub [<$variant:snake _inputs_generator>]: [<$variant CounterInputGen>]<F>,
)*
}
impl<F: ::proofman_fields::PrimeField64> PrecompileCollectors<F> {
pub fn new() -> Self {
Self {
$(
[<$variant:snake _collector>]: ::std::vec::Vec::new(),
[<$variant:snake _inputs_generator>]:
[<$variant CounterInputGen>]::<F>::new(
::zisk_common::BusDeviceMode::InputGenerator,
),
)*
}
}
pub fn try_push_collector(
&mut self,
air_id: ::std::primitive::usize,
secn_instance: &dyn ::zisk_common::Instance<F>,
chunk_id: ::zisk_common::ChunkId,
global_idx: ::std::primitive::usize,
) -> $crate::error::ExecutorResult<::std::primitive::bool> {
$(
if $air.contains(&air_id) {
let inst = secn_instance
.as_any()
.downcast_ref::<[<$variant Instance>]<F>>()
.ok_or(
$crate::error::ExecutorError::InstanceTypeMismatch {
global_id: global_idx,
air_id,
expected: concat!(stringify!($variant), "Instance"),
}
)?;
self.[<$variant:snake _collector>].push((
global_idx,
inst.[<build_ $variant:snake _collector>](
chunk_id,
),
));
return ::std::result::Result::Ok(true);
}
)*
::std::result::Result::Ok(false)
}
#[inline(always)]
#[allow(clippy::ptr_arg)]
pub fn dispatch_op(
&mut self,
op_type: ::std::primitive::u32,
bus_id: &::zisk_common::BusId,
data: &[::zisk_common::PayloadType],
mem_collector: &mut ::std::vec::Vec<(
::std::primitive::usize,
::zisk_sm_mem::MemModuleCollector,
)>,
mem_align_collector: &mut ::std::vec::Vec<(
::std::primitive::usize,
::zisk_sm_mem::MemAlignCollector,
)>,
) -> ::std::primitive::bool {
$(
const [<__ $variant:upper _OP>]: ::std::primitive::u32 = $op;
)*
match op_type {
$(
[<__ $variant:upper _OP>] => {
for (_, c) in &mut self.[<$variant:snake _collector>] {
c.process_data(bus_id, data);
}
self.[<$variant:snake _inputs_generator>].process_data(
bus_id,
data,
&mut ::zisk_precomp_common::MemCollectorProcessor::new(
mem_collector,
mem_align_collector,
),
);
true
}
)*
_ => false,
}
}
pub fn into_device_entries(
self,
) -> ::std::vec::Vec<(
::std::primitive::usize,
::std::boxed::Box<dyn ::zisk_common::BusDevice<::zisk_common::PayloadType>>,
)> {
let mut result = ::std::vec::Vec::new();
$(
for (id, c) in self.[<$variant:snake _collector>] {
result.push((
id,
::std::boxed::Box::new(c) as ::std::boxed::Box<
dyn ::zisk_common::BusDevice<::zisk_common::PayloadType>,
>,
));
}
)*
result
}
}
}
};
}