substrate/simulation/
data.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//! Interfaces for interacting with simulation data.

use std::ops::Deref;

use codegen::impl_save_tuples;

use crate::{
    schematic::{HasNestedView, NestedInstance, NestedView, Schematic},
    simulation::{Analysis, SimulationContext, Simulator},
    types::schematic::{IoTerminalBundle, NestedNode},
};

/// Saves the raw output of a simulation.
#[derive(Debug, Clone, Copy)]
pub struct SaveOutput;

/// Saves the transient time waveform.
#[derive(Debug, Clone, Copy)]
pub struct SaveTime;

/// Saves the frequency vector of an AC (frequency sweep) simulation.
#[derive(Debug, Clone, Copy)]
pub struct SaveFreq;

impl HasNestedView for SaveOutput {
    type NestedView = SaveOutput;

    fn nested_view(&self, _parent: &substrate::schematic::InstancePath) -> Self::NestedView {
        *self
    }
}

impl HasNestedView for SaveTime {
    type NestedView = SaveTime;

    fn nested_view(&self, _parent: &substrate::schematic::InstancePath) -> Self::NestedView {
        *self
    }
}

/// Gets the [`Save::SaveKey`] corresponding to type `T`.
pub type SaveKey<T, S, A> = <T as Save<S, A>>::SaveKey;

/// Gets the [`Save::Saved`] corresponding to type `T`.
pub type Saved<T, S, A> = <T as Save<S, A>>::Saved;

/// A schematic object that can be saved in an analysis within a given simulator.
pub trait Save<S: Simulator, A: Analysis> {
    /// The key type used to address the saved output within the analysis.
    ///
    /// This key is assigned in [`Save::save`].
    type SaveKey;
    /// The saved data associated with things object.
    type Saved;

    /// Marks the given output for saving, returning a key that can be used to recover
    /// the output once the simulation is complete.
    fn save(
        &self,
        ctx: &SimulationContext<S>,
        opts: &mut <S as Simulator>::Options,
    ) -> <Self as Save<S, A>>::SaveKey;

    /// Recovers the desired simulation output from the analysis's output.
    fn from_saved(
        output: &<A as Analysis>::Output,
        key: &<Self as Save<S, A>>::SaveKey,
    ) -> <Self as Save<S, A>>::Saved;
}

impl_save_tuples! {64, NestedNode}

/// The result of saving a nested instance in a simulation.
///
/// Saves the nested instance's data and IO.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct NestedInstanceOutput<D, I> {
    /// The nested data of the instance.
    data: D,
    /// The IO of the instance.
    io: I,
}

impl<D, I> Deref for NestedInstanceOutput<D, I> {
    type Target = D;
    fn deref(&self) -> &Self::Target {
        &self.data
    }
}

impl<D, I> NestedInstanceOutput<D, I> {
    /// The ports of this instance.
    pub fn io(&self) -> &I {
        &self.io
    }

    /// The nested data.
    pub fn data(&self) -> &D {
        &self.data
    }
}

impl<S: Simulator, A: Analysis> Save<S, A> for () {
    type SaveKey = ();
    type Saved = ();

    fn save(
        &self,
        _ctx: &SimulationContext<S>,
        _opts: &mut <S as Simulator>::Options,
    ) -> <Self as Save<S, A>>::SaveKey {
    }

    fn from_saved(
        _output: &<A as Analysis>::Output,
        _key: &<Self as Save<S, A>>::SaveKey,
    ) -> <Self as Save<S, A>>::Saved {
    }
}

impl<T, S, A> Save<S, A> for NestedInstance<T>
where
    T: Schematic,
    S: Simulator,
    A: Analysis,
    NestedView<T::NestedData>: Save<S, A>,
    NestedView<IoTerminalBundle<T>>: Save<S, A>,
{
    type SaveKey = (
        <NestedView<T::NestedData> as Save<S, A>>::SaveKey,
        <NestedView<IoTerminalBundle<T>> as Save<S, A>>::SaveKey,
    );
    type Saved = NestedInstanceOutput<
        <NestedView<T::NestedData> as Save<S, A>>::Saved,
        <NestedView<IoTerminalBundle<T>> as Save<S, A>>::Saved,
    >;

    fn save(
        &self,
        ctx: &SimulationContext<S>,
        opts: &mut <S as Simulator>::Options,
    ) -> <Self as Save<S, A>>::SaveKey {
        let data = self.data().save(ctx, opts);
        let io = self.io().save(ctx, opts);
        (data, io)
    }

    fn from_saved(
        output: &<A as Analysis>::Output,
        key: &<Self as Save<S, A>>::SaveKey,
    ) -> <Self as Save<S, A>>::Saved {
        NestedInstanceOutput {
            data: <NestedView<T::NestedData> as Save<S, A>>::from_saved(output, &key.0),
            io: <NestedView<IoTerminalBundle<T>> as Save<S, A>>::from_saved(output, &key.1),
        }
    }
}