spectre/analysis/
montecarlo.rsuse crate::{Input, Spectre};
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
use std::ops::Deref;
use substrate::simulation::data::Save;
use substrate::simulation::{Analysis, Simulator, SupportedBy};
use substrate::types::schematic::{NestedNode, NestedTerminal, RawNestedNode};
use type_dispatch::impl_dispatch;
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum Variations {
#[default]
Process,
Mismatch,
All,
}
impl Display for Variations {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
Self::Process => "process",
Self::Mismatch => "mismatch",
Self::All => "all",
}
)
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct MonteCarlo<A> {
pub variations: Variations,
pub numruns: usize,
pub seed: Option<u64>,
pub firstrun: Option<usize>,
pub analysis: A,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Output<T>(pub(crate) Vec<T>);
impl<T> Deref for Output<T> {
type Target = Vec<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> Output<T> {
pub fn into_inner(self) -> Vec<T> {
self.0
}
}
impl<A: SupportedBy<Spectre>> From<MonteCarlo<A>> for MonteCarlo<Vec<Input>> {
fn from(value: MonteCarlo<A>) -> Self {
let mut analysis = Vec::new();
value.analysis.into_input(&mut analysis);
MonteCarlo {
variations: value.variations,
numruns: value.numruns,
seed: value.seed,
firstrun: value.firstrun,
analysis,
}
}
}
#[impl_dispatch({NestedNode; RawNestedNode; NestedTerminal})]
impl<T, A: Analysis> Save<Spectre, MonteCarlo<A>> for T
where
T: Save<Spectre, A>,
{
type SaveKey = <T as Save<Spectre, A>>::SaveKey;
type Saved = Vec<<T as Save<Spectre, A>>::Saved>;
fn save(
&self,
ctx: &substrate::simulation::SimulationContext<Spectre>,
opts: &mut <Spectre as Simulator>::Options,
) -> <Self as Save<Spectre, MonteCarlo<A>>>::SaveKey {
self.save(ctx, opts)
}
fn from_saved(
output: &<MonteCarlo<A> as Analysis>::Output,
key: &<Self as Save<Spectre, MonteCarlo<A>>>::SaveKey,
) -> <Self as Save<Spectre, MonteCarlo<A>>>::Saved {
output
.0
.iter()
.map(|output| T::from_saved(output, key))
.collect()
}
}
impl<A: Analysis> Analysis for MonteCarlo<A> {
type Output = Output<A::Output>;
}
impl<A: SupportedBy<Spectre>> SupportedBy<Spectre> for MonteCarlo<A> {
fn into_input(self, inputs: &mut Vec<<Spectre as Simulator>::Input>) {
inputs.push(self.into());
}
fn from_output(
outputs: &mut impl Iterator<Item = <Spectre as Simulator>::Output>,
) -> <Self as Analysis>::Output {
let item = outputs.next().unwrap();
let output: Output<Vec<crate::Output>> = item.try_into().unwrap();
Output(
output
.0
.into_iter()
.map(|out| A::from_output(&mut out.into_iter()))
.collect(),
)
}
}