substrate/simulation/
data.rs

1//! Interfaces for interacting with simulation data.
2
3use std::ops::Deref;
4
5use codegen::impl_save_tuples;
6
7use crate::{
8    schematic::{HasNestedView, NestedInstance, NestedView, Schematic},
9    simulation::{Analysis, SimulationContext, Simulator},
10    types::{
11        ArrayBundle, HasBundleKind,
12        schematic::{IoTerminalBundle, NestedNode},
13    },
14};
15
16/// Saves the raw output of a simulation.
17#[derive(Debug, Clone, Copy)]
18pub struct SaveOutput;
19
20/// Saves the transient time waveform.
21#[derive(Debug, Clone, Copy)]
22pub struct SaveTime;
23
24/// Saves the frequency vector of an AC (frequency sweep) simulation.
25#[derive(Debug, Clone, Copy)]
26pub struct SaveFreq;
27
28impl HasNestedView for SaveOutput {
29    type NestedView = SaveOutput;
30
31    fn nested_view(&self, _parent: &substrate::schematic::InstancePath) -> Self::NestedView {
32        *self
33    }
34}
35
36impl HasNestedView for SaveTime {
37    type NestedView = SaveTime;
38
39    fn nested_view(&self, _parent: &substrate::schematic::InstancePath) -> Self::NestedView {
40        *self
41    }
42}
43
44/// Gets the [`Save::SaveKey`] corresponding to type `T`.
45pub type SaveKey<T, S, A> = <T as Save<S, A>>::SaveKey;
46
47/// Gets the [`Save::Saved`] corresponding to type `T`.
48pub type Saved<T, S, A> = <T as Save<S, A>>::Saved;
49
50/// A schematic object that can be saved in an analysis within a given simulator.
51pub trait Save<S: Simulator, A: Analysis> {
52    /// The key type used to address the saved output within the analysis.
53    ///
54    /// This key is assigned in [`Save::save`].
55    type SaveKey;
56    /// The saved data associated with things object.
57    type Saved;
58
59    /// Marks the given output for saving, returning a key that can be used to recover
60    /// the output once the simulation is complete.
61    fn save(
62        &self,
63        ctx: &SimulationContext<S>,
64        opts: &mut <S as Simulator>::Options,
65    ) -> <Self as Save<S, A>>::SaveKey;
66
67    /// Recovers the desired simulation output from the analysis's output.
68    fn from_saved(
69        output: &<A as Analysis>::Output,
70        key: &<Self as Save<S, A>>::SaveKey,
71    ) -> <Self as Save<S, A>>::Saved;
72}
73
74impl_save_tuples! {64, NestedNode}
75
76impl<T: Save<S, A>, S: Simulator, A: Analysis> Save<S, A> for Option<T> {
77    type SaveKey = Option<SaveKey<T, S, A>>;
78    type Saved = Option<Saved<T, S, A>>;
79
80    fn save(
81        &self,
82        ctx: &SimulationContext<S>,
83        opts: &mut <S as Simulator>::Options,
84    ) -> <Self as Save<S, A>>::SaveKey {
85        self.as_ref().map(|x| x.save(ctx, opts))
86    }
87
88    fn from_saved(
89        output: &<A as Analysis>::Output,
90        key: &<Self as Save<S, A>>::SaveKey,
91    ) -> <Self as Save<S, A>>::Saved {
92        key.as_ref().map(|k| T::from_saved(output, k))
93    }
94}
95
96impl<T: Save<S, A>, S: Simulator, A: Analysis> Save<S, A> for Vec<T> {
97    type SaveKey = Vec<SaveKey<T, S, A>>;
98    type Saved = Vec<Saved<T, S, A>>;
99
100    fn save(
101        &self,
102        ctx: &SimulationContext<S>,
103        opts: &mut <S as Simulator>::Options,
104    ) -> <Self as Save<S, A>>::SaveKey {
105        self.iter().map(|x| x.save(ctx, opts)).collect()
106    }
107
108    fn from_saved(
109        output: &<A as Analysis>::Output,
110        key: &<Self as Save<S, A>>::SaveKey,
111    ) -> <Self as Save<S, A>>::Saved {
112        key.iter().map(|k| T::from_saved(output, k)).collect()
113    }
114}
115
116impl<T: HasBundleKind + Save<S, A>, S: Simulator, A: Analysis> Save<S, A> for ArrayBundle<T> {
117    type SaveKey = Vec<SaveKey<T, S, A>>;
118    type Saved = Vec<Saved<T, S, A>>;
119
120    fn save(
121        &self,
122        ctx: &SimulationContext<S>,
123        opts: &mut <S as Simulator>::Options,
124    ) -> <Self as Save<S, A>>::SaveKey {
125        (0..self.num_elems())
126            .map(|i| self[i].save(ctx, opts))
127            .collect()
128    }
129
130    fn from_saved(
131        output: &<A as Analysis>::Output,
132        key: &<Self as Save<S, A>>::SaveKey,
133    ) -> <Self as Save<S, A>>::Saved {
134        <Vec<T>>::from_saved(output, key)
135    }
136}
137
138/// The result of saving a nested instance in a simulation.
139///
140/// Saves the nested instance's data and IO.
141#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
142pub struct NestedInstanceOutput<D, I> {
143    /// The nested data of the instance.
144    data: D,
145    /// The IO of the instance.
146    io: I,
147}
148
149impl<D, I> Deref for NestedInstanceOutput<D, I> {
150    type Target = D;
151    fn deref(&self) -> &Self::Target {
152        &self.data
153    }
154}
155
156impl<D, I> NestedInstanceOutput<D, I> {
157    /// The ports of this instance.
158    pub fn io(&self) -> &I {
159        &self.io
160    }
161
162    /// The nested data.
163    pub fn data(&self) -> &D {
164        &self.data
165    }
166}
167
168impl<S: Simulator, A: Analysis> Save<S, A> for () {
169    type SaveKey = ();
170    type Saved = ();
171
172    fn save(
173        &self,
174        _ctx: &SimulationContext<S>,
175        _opts: &mut <S as Simulator>::Options,
176    ) -> <Self as Save<S, A>>::SaveKey {
177    }
178
179    fn from_saved(
180        _output: &<A as Analysis>::Output,
181        _key: &<Self as Save<S, A>>::SaveKey,
182    ) -> <Self as Save<S, A>>::Saved {
183    }
184}
185
186impl<T, S, A> Save<S, A> for NestedInstance<T>
187where
188    T: Schematic,
189    S: Simulator,
190    A: Analysis,
191    NestedView<T::NestedData>: Save<S, A>,
192    NestedView<IoTerminalBundle<T>>: Save<S, A>,
193{
194    type SaveKey = (
195        <NestedView<T::NestedData> as Save<S, A>>::SaveKey,
196        <NestedView<IoTerminalBundle<T>> as Save<S, A>>::SaveKey,
197    );
198    type Saved = NestedInstanceOutput<
199        <NestedView<T::NestedData> as Save<S, A>>::Saved,
200        <NestedView<IoTerminalBundle<T>> as Save<S, A>>::Saved,
201    >;
202
203    fn save(
204        &self,
205        ctx: &SimulationContext<S>,
206        opts: &mut <S as Simulator>::Options,
207    ) -> <Self as Save<S, A>>::SaveKey {
208        let data = self.data().save(ctx, opts);
209        let io = self.io().save(ctx, opts);
210        (data, io)
211    }
212
213    fn from_saved(
214        output: &<A as Analysis>::Output,
215        key: &<Self as Save<S, A>>::SaveKey,
216    ) -> <Self as Save<S, A>>::Saved {
217        NestedInstanceOutput {
218            data: <NestedView<T::NestedData> as Save<S, A>>::from_saved(output, &key.0),
219            io: <NestedView<IoTerminalBundle<T>> as Save<S, A>>::from_saved(output, &key.1),
220        }
221    }
222}