spectre/analysis/
montecarlo.rs

1//! Spectre Monte Carlo analysis options and data structures.
2
3use crate::{Input, Spectre};
4use serde::{Deserialize, Serialize};
5use std::fmt::{Display, Formatter};
6use std::ops::Deref;
7use substrate::simulation::data::Save;
8use substrate::simulation::{Analysis, Simulator, SupportedBy};
9use substrate::types::schematic::{NestedNode, NestedTerminal, RawNestedNode};
10use type_dispatch::impl_dispatch;
11
12/// Level of statistical variation to apply in a Monte Carlo analysis.
13#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Serialize, Deserialize)]
14pub enum Variations {
15    /// Batch-to-batch process variations.
16    #[default]
17    Process,
18    /// Per-instance mismatch variations.
19    Mismatch,
20    /// Both process and mismatch variations.
21    All,
22}
23
24impl Display for Variations {
25    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
26        write!(
27            f,
28            "{}",
29            match self {
30                Self::Process => "process",
31                Self::Mismatch => "mismatch",
32                Self::All => "all",
33            }
34        )
35    }
36}
37
38/// A Monte Carlo analysis.
39#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
40pub struct MonteCarlo<A> {
41    /// Level of statistical variation to apply.
42    pub variations: Variations,
43    /// Number of Monte Carlo iterations to perform (not including nominal).
44    pub numruns: usize,
45    /// Starting seed for random number generator.
46    pub seed: Option<u64>,
47    /// Starting iteration number.
48    pub firstrun: Option<usize>,
49    /// The analysis to run.
50    pub analysis: A,
51}
52
53/// A Monte Carlo simulation output.
54#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
55pub struct Output<T>(pub(crate) Vec<T>);
56
57impl<T> Deref for Output<T> {
58    type Target = Vec<T>;
59
60    fn deref(&self) -> &Self::Target {
61        &self.0
62    }
63}
64
65impl<T> Output<T> {
66    /// Returns the underlying vector of outputs for each
67    /// iteration of the Monte Carlo simulation.
68    pub fn into_inner(self) -> Vec<T> {
69        self.0
70    }
71}
72
73impl<A: SupportedBy<Spectre>> From<MonteCarlo<A>> for MonteCarlo<Vec<Input>> {
74    fn from(value: MonteCarlo<A>) -> Self {
75        let mut analysis = Vec::new();
76        value.analysis.into_input(&mut analysis);
77        MonteCarlo {
78            variations: value.variations,
79            numruns: value.numruns,
80            seed: value.seed,
81            firstrun: value.firstrun,
82            analysis,
83        }
84    }
85}
86
87#[impl_dispatch({NestedNode; RawNestedNode; NestedTerminal})]
88impl<T, A: Analysis> Save<Spectre, MonteCarlo<A>> for T
89where
90    T: Save<Spectre, A>,
91{
92    type SaveKey = <T as Save<Spectre, A>>::SaveKey;
93    type Saved = Vec<<T as Save<Spectre, A>>::Saved>;
94
95    fn save(
96        &self,
97        ctx: &substrate::simulation::SimulationContext<Spectre>,
98        opts: &mut <Spectre as Simulator>::Options,
99    ) -> <Self as Save<Spectre, MonteCarlo<A>>>::SaveKey {
100        self.save(ctx, opts)
101    }
102
103    fn from_saved(
104        output: &<MonteCarlo<A> as Analysis>::Output,
105        key: &<Self as Save<Spectre, MonteCarlo<A>>>::SaveKey,
106    ) -> <Self as Save<Spectre, MonteCarlo<A>>>::Saved {
107        output
108            .0
109            .iter()
110            .map(|output| T::from_saved(output, key))
111            .collect()
112    }
113}
114
115// impl<A: Analysis, T: FromSaved<Spectre, A>> FromSaved<Spectre, MonteCarlo<A>> for Output<T> {
116//     type SavedKey = T::SavedKey;
117//
118//     fn from_saved(output: &<MonteCarlo<A> as Analysis>::Output, key: &Self::SavedKey) -> Self {
119//         Output(
120//             output
121//                 .0
122//                 .iter()
123//                 .map(|output| T::from_saved(output, key))
124//                 .collect(),
125//         )
126//     }
127// }
128//
129// impl<A: SupportedBy<Spectre>, T, S> Save<Spectre, MonteCarlo<A>, T> for Output<S>
130// where
131//     S: Save<Spectre, A, T>,
132// {
133//     fn save(
134//         ctx: &SimulationContext<Spectre>,
135//         to_save: T,
136//         opts: &mut <Spectre as Simulator>::Options,
137//     ) -> <Self as FromSaved<Spectre, MonteCarlo<A>>>::SavedKey {
138//         S::save(ctx, to_save, opts)
139//     }
140// }
141
142impl<A: Analysis> Analysis for MonteCarlo<A> {
143    type Output = Output<A::Output>;
144}
145
146impl<A: SupportedBy<Spectre>> SupportedBy<Spectre> for MonteCarlo<A> {
147    fn into_input(self, inputs: &mut Vec<<Spectre as Simulator>::Input>) {
148        inputs.push(self.into());
149    }
150    fn from_output(
151        outputs: &mut impl Iterator<Item = <Spectre as Simulator>::Output>,
152    ) -> <Self as Analysis>::Output {
153        let item = outputs.next().unwrap();
154        let output: Output<Vec<crate::Output>> = item.try_into().unwrap();
155        Output(
156            output
157                .0
158                .into_iter()
159                .map(|out| A::from_output(&mut out.into_iter()))
160                .collect(),
161        )
162    }
163}