use pil2_std_lib::Std;
use proofman_common::ProofCtx;
use proofman_fields::PrimeField64;
use std::borrow::Cow;
use std::sync::Arc;
use zisk_precomp_dma::DmaManager;
use zisk_precomp_evm::JumpDestManager;
use zisk_sm_arith::ArithSM;
use zisk_sm_binary::BinarySM;
use zisk_sm_mem::Mem;
use zisk_sm_rom::RomSM;
use zisk_common::{ComponentBuilder, ComponentPlanBuilder, Instance, InstanceCtx, Plan, Planner};
use zisk_pil::{
ARITH_AIR_IDS, BINARY_ADD_AIR_IDS, BINARY_ADD_HI_AIR_IDS, BINARY_AIR_IDS,
BINARY_EXTENSION_AIR_IDS, BINARY_EXTENSION_FULL_AIR_IDS, DMA_64_ALIGNED_AIR_IDS,
DMA_64_ALIGNED_INPUT_CPY_AIR_IDS, DMA_64_ALIGNED_MEM_AIR_IDS, DMA_64_ALIGNED_MEM_CPY_AIR_IDS,
DMA_64_ALIGNED_MEM_SET_AIR_IDS, DMA_AIR_IDS, DMA_INPUT_CPY_AIR_IDS, DMA_MEM_CPY_AIR_IDS,
DMA_PRE_POST_AIR_IDS, DMA_PRE_POST_INPUT_CPY_AIR_IDS, DMA_PRE_POST_MEM_CPY_AIR_IDS,
DMA_UNALIGNED_AIR_IDS, INPUT_DATA_AIR_IDS, JUMP_DEST_AIR_IDS, MEM_AIR_IDS, MEM_ALIGN_AIR_IDS,
MEM_ALIGN_BYTE_AIR_IDS, MEM_ALIGN_READ_BYTE_AIR_IDS, MEM_ALIGN_WRITE_BYTE_AIR_IDS, ROM_AIR_IDS,
ROM_DATA_AIR_IDS, ZISK_AIRGROUP_ID,
};
const ROM_AIR_IDS_MAP: &[(usize, usize)] = &[(ZISK_AIRGROUP_ID, ROM_AIR_IDS[0])];
const MEM_AIR_IDS_MAP: &[(usize, usize)] = &[
(ZISK_AIRGROUP_ID, MEM_AIR_IDS[0]),
(ZISK_AIRGROUP_ID, ROM_DATA_AIR_IDS[0]),
(ZISK_AIRGROUP_ID, INPUT_DATA_AIR_IDS[0]),
(ZISK_AIRGROUP_ID, MEM_ALIGN_AIR_IDS[0]),
(ZISK_AIRGROUP_ID, MEM_ALIGN_BYTE_AIR_IDS[0]),
(ZISK_AIRGROUP_ID, MEM_ALIGN_WRITE_BYTE_AIR_IDS[0]),
(ZISK_AIRGROUP_ID, MEM_ALIGN_READ_BYTE_AIR_IDS[0]),
];
const BINARY_AIR_IDS_MAP: &[(usize, usize)] = &[
(ZISK_AIRGROUP_ID, BINARY_AIR_IDS[0]),
(ZISK_AIRGROUP_ID, BINARY_ADD_AIR_IDS[0]),
(ZISK_AIRGROUP_ID, BINARY_ADD_HI_AIR_IDS[0]),
(ZISK_AIRGROUP_ID, BINARY_EXTENSION_AIR_IDS[0]),
(ZISK_AIRGROUP_ID, BINARY_EXTENSION_FULL_AIR_IDS[0]),
];
const ARITH_AIR_IDS_MAP: &[(usize, usize)] = &[(ZISK_AIRGROUP_ID, ARITH_AIR_IDS[0])];
const DMA_AIR_IDS_MAP: &[(usize, usize)] = &[
(ZISK_AIRGROUP_ID, DMA_AIR_IDS[0]),
(ZISK_AIRGROUP_ID, DMA_PRE_POST_AIR_IDS[0]),
(ZISK_AIRGROUP_ID, DMA_64_ALIGNED_AIR_IDS[0]),
(ZISK_AIRGROUP_ID, DMA_UNALIGNED_AIR_IDS[0]),
(ZISK_AIRGROUP_ID, DMA_MEM_CPY_AIR_IDS[0]),
(ZISK_AIRGROUP_ID, DMA_INPUT_CPY_AIR_IDS[0]),
(ZISK_AIRGROUP_ID, DMA_PRE_POST_MEM_CPY_AIR_IDS[0]),
(ZISK_AIRGROUP_ID, DMA_PRE_POST_INPUT_CPY_AIR_IDS[0]),
(ZISK_AIRGROUP_ID, DMA_64_ALIGNED_MEM_CPY_AIR_IDS[0]),
(ZISK_AIRGROUP_ID, DMA_64_ALIGNED_MEM_SET_AIR_IDS[0]),
(ZISK_AIRGROUP_ID, DMA_64_ALIGNED_INPUT_CPY_AIR_IDS[0]),
(ZISK_AIRGROUP_ID, DMA_64_ALIGNED_MEM_AIR_IDS[0]),
];
const JUMP_DEST_AIR_IDS_MAP: &[(usize, usize)] = &[(ZISK_AIRGROUP_ID, JUMP_DEST_AIR_IDS[0])];
pub type SMAirType = Cow<'static, [(usize, usize)]>;
pub const ROM_POSITION: usize = 0;
pub const MEM_POSITION: usize = 1;
pub const BINARY_POSITION: usize = 2;
pub const ARITH_POSITION: usize = 3;
pub const DMA_POSITION: usize = 4;
pub const JUMP_DEST_POSITION: usize = 5;
pub const BUILTIN_COUNT: usize = 6;
pub enum BuiltinSMs<F: PrimeField64> {
RomSM(Arc<RomSM>),
MemSM(Arc<Mem<F>>),
BinarySM(Arc<BinarySM<F>>),
ArithSM(Arc<ArithSM<F>>),
DmaManager(Arc<DmaManager<F>>),
JumpDestManager(Arc<JumpDestManager<F>>),
}
impl<F: PrimeField64> BuiltinSMs<F> {
pub(crate) fn all(std: Arc<Std<F>>) -> Vec<(SMAirType, Self)> {
vec![
(Cow::Borrowed(ROM_AIR_IDS_MAP), Self::RomSM(RomSM::new::<F>())),
(Cow::Borrowed(MEM_AIR_IDS_MAP), Self::MemSM(Mem::new(std.clone()))),
(Cow::Borrowed(BINARY_AIR_IDS_MAP), Self::BinarySM(BinarySM::new(std.clone()))),
(Cow::Borrowed(ARITH_AIR_IDS_MAP), Self::ArithSM(ArithSM::new(std.clone()))),
(Cow::Borrowed(DMA_AIR_IDS_MAP), Self::DmaManager(DmaManager::new(std.clone()))),
(
Cow::Borrowed(JUMP_DEST_AIR_IDS_MAP),
Self::JumpDestManager(JumpDestManager::new(std)),
),
]
}
pub(crate) fn planner_for_position(position: usize, is_asm_emulator: bool) -> Box<dyn Planner> {
match position {
ROM_POSITION => unreachable!(
"ROM planning goes through RomPlanner::plan_for_chunks, not the Planner trait"
),
MEM_POSITION => <Mem<F> as ComponentPlanBuilder<F>>::planner(is_asm_emulator),
BINARY_POSITION => <BinarySM<F> as ComponentPlanBuilder<F>>::planner(is_asm_emulator),
ARITH_POSITION => <ArithSM<F> as ComponentPlanBuilder<F>>::planner(is_asm_emulator),
DMA_POSITION => <DmaManager<F> as ComponentPlanBuilder<F>>::planner(is_asm_emulator),
JUMP_DEST_POSITION => {
<JumpDestManager<F> as ComponentPlanBuilder<F>>::planner(is_asm_emulator)
}
_ => panic!("planner_for_position: invalid builtin position {position}"),
}
}
pub(crate) fn configure_instances(&self, pctx: &ProofCtx<F>, plans: &[Plan]) {
match self {
Self::RomSM(sm) => <RomSM as ComponentBuilder<F>>::configure_instances(sm, pctx, plans),
Self::MemSM(sm) => (**sm).configure_instances(pctx, plans),
Self::BinarySM(sm) => (**sm).configure_instances(pctx, plans),
Self::ArithSM(sm) => (**sm).configure_instances(pctx, plans),
Self::DmaManager(sm) => (**sm).configure_instances(pctx, plans),
Self::JumpDestManager(sm) => (**sm).configure_instances(pctx, plans),
}
}
pub(crate) fn build_instance(&self, ictx: InstanceCtx) -> Box<dyn Instance<F>> {
match self {
Self::RomSM(sm) => <RomSM as ComponentBuilder<F>>::build_instance(sm, ictx),
Self::MemSM(sm) => (**sm).build_instance(ictx),
Self::BinarySM(sm) => (**sm).build_instance(ictx),
Self::ArithSM(sm) => (**sm).build_instance(ictx),
Self::DmaManager(sm) => (**sm).build_instance(ictx),
Self::JumpDestManager(sm) => (**sm).build_instance(ictx),
}
}
}