1use crate::{ErrPreset, InstanceTail, SimSignal, Spectre};
4use arcstr::ArcStr;
5use rust_decimal::Decimal;
6use scir::{NamedSliceOne, SliceOnePath};
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9use std::sync::Arc;
10use substrate::schematic::conv::ConvertedNodePath;
11use substrate::simulation::data::{Save, SaveOutput, SaveTime};
12use substrate::simulation::waveform::{TimePoint, TimeWaveform, WaveformRef};
13use substrate::simulation::{Analysis, SimulationContext, Simulator, SupportedBy};
14use substrate::types::schematic::{NestedNode, NestedTerminal, RawNestedNode};
15
16#[derive(Clone, Default, Debug, Eq, PartialEq, Serialize, Deserialize)]
18pub struct Tran {
19 pub stop: Decimal,
21 pub start: Option<Decimal>,
25
26 pub errpreset: Option<ErrPreset>,
28
29 pub noise_fmax: Option<Decimal>,
35
36 pub noise_fmin: Option<Decimal>,
38}
39
40#[derive(Debug, Clone)]
42pub struct Output {
43 pub time: Arc<Vec<f64>>,
45 pub raw_values: HashMap<ArcStr, Arc<Vec<f64>>>,
47 pub(crate) saved_values: HashMap<u64, ArcStr>,
49}
50
51#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
53pub struct OutputWaveform {
54 pub t: Arc<Vec<f64>>,
56 pub x: Arc<Vec<f64>>,
58}
59
60impl OutputWaveform {
61 pub fn as_ref(&self) -> WaveformRef<'_, f64> {
63 WaveformRef::new(&self.t, &self.x)
64 }
65}
66
67impl TimeWaveform for OutputWaveform {
68 type Data = f64;
69 fn get(&self, idx: usize) -> Option<TimePoint<f64>> {
70 self.as_ref().get(idx)
71 }
72
73 fn len(&self) -> usize {
74 self.t.len()
75 }
76}
77
78impl Save<Spectre, Tran> for SaveOutput {
79 type SaveKey = ();
80 type Saved = Output;
81
82 fn save(
83 &self,
84 _ctx: &SimulationContext<Spectre>,
85 _opts: &mut <Spectre as Simulator>::Options,
86 ) -> <Self as Save<Spectre, Tran>>::SaveKey {
87 }
88
89 fn from_saved(
90 output: &<Tran as Analysis>::Output,
91 _key: &<Self as Save<Spectre, Tran>>::SaveKey,
92 ) -> <Self as Save<Spectre, Tran>>::Saved {
93 output.clone()
94 }
95}
96
97impl Save<Spectre, Tran> for SaveTime {
98 type SaveKey = ();
99 type Saved = Arc<Vec<f64>>;
100
101 fn save(
102 &self,
103 _ctx: &SimulationContext<Spectre>,
104 _opts: &mut <Spectre as Simulator>::Options,
105 ) -> <Self as Save<Spectre, Tran>>::SaveKey {
106 }
107
108 fn from_saved(
109 output: &<Tran as Analysis>::Output,
110 _key: &<Self as Save<Spectre, Tran>>::SaveKey,
111 ) -> <Self as Save<Spectre, Tran>>::Saved {
112 output.time.clone()
113 }
114}
115
116#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Serialize, Deserialize)]
118pub struct VoltageSaveKey(pub(crate) u64);
119
120impl Save<Spectre, Tran> for NestedNode {
121 type SaveKey = VoltageSaveKey;
122 type Saved = OutputWaveform;
123
124 fn save(
125 &self,
126 ctx: &SimulationContext<Spectre>,
127 opts: &mut <Spectre as Simulator>::Options,
128 ) -> <Self as Save<Spectre, Tran>>::SaveKey {
129 opts.save_tran_voltage(SimSignal::ScirVoltage(
130 match ctx.lib.convert_node_path(&self.path()).unwrap() {
131 ConvertedNodePath::Cell(path) => path.clone(),
132 ConvertedNodePath::Primitive {
133 instances, port, ..
134 } => SliceOnePath::new(instances.clone(), NamedSliceOne::new(port.clone())),
135 },
136 ))
137 }
138
139 fn from_saved(
140 output: &<Tran as Analysis>::Output,
141 key: &<Self as Save<Spectre, Tran>>::SaveKey,
142 ) -> <Self as Save<Spectre, Tran>>::Saved {
143 OutputWaveform {
144 t: output.time.clone(),
145 x: output
146 .raw_values
147 .get(output.saved_values.get(&key.0).unwrap())
148 .unwrap()
149 .clone(),
150 }
151 }
152}
153
154impl Save<Spectre, Tran> for RawNestedNode {
155 type SaveKey = VoltageSaveKey;
156 type Saved = OutputWaveform;
157
158 fn save(
159 &self,
160 ctx: &SimulationContext<Spectre>,
161 opts: &mut <Spectre as Simulator>::Options,
162 ) -> <Self as Save<Spectre, Tran>>::SaveKey {
163 let itail = InstanceTail {
164 instance: ctx.lib.convert_instance_path(self.instances()).unwrap(),
165 tail: self.tail().clone(),
166 };
167 opts.save_tran_voltage(itail)
168 }
169
170 fn from_saved(
171 output: &<Tran as Analysis>::Output,
172 key: &<Self as Save<Spectre, Tran>>::SaveKey,
173 ) -> <Self as Save<Spectre, Tran>>::Saved {
174 let name = output
175 .saved_values
176 .get(&key.0)
177 .expect("failed to retrieve name corresponding to saved key");
178 OutputWaveform {
179 t: output.time.clone(),
180 x: output
181 .raw_values
182 .get(name.as_str())
183 .unwrap_or_else(|| panic!("no value for {name} found"))
184 .clone(),
185 }
186 }
187}
188
189#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
191pub struct CurrentSaveKey(pub(crate) Vec<u64>);
192
193pub struct NestedTerminalOutput {
195 pub v: OutputWaveform,
197 pub i: OutputWaveform,
199}
200
201impl Save<Spectre, Tran> for NestedTerminal {
202 type SaveKey = (VoltageSaveKey, CurrentSaveKey);
203 type Saved = NestedTerminalOutput;
204
205 fn save(
206 &self,
207 ctx: &SimulationContext<Spectre>,
208 opts: &mut <Spectre as Simulator>::Options,
209 ) -> <Self as Save<Spectre, Tran>>::SaveKey {
210 (
211 <NestedNode as Save<Spectre, Tran>>::save(self, ctx, opts),
212 CurrentSaveKey(
213 ctx.lib
214 .convert_terminal_path(&self.path())
215 .unwrap()
216 .into_iter()
217 .flat_map(|path| {
218 opts.save_tran_current(SimSignal::ScirCurrent(match path {
219 ConvertedNodePath::Cell(path) => path.clone(),
220 ConvertedNodePath::Primitive {
221 instances, port, ..
222 } => SliceOnePath::new(
223 instances.clone(),
224 NamedSliceOne::new(port.clone()),
225 ),
226 }))
227 .0
228 })
229 .collect(),
230 ),
231 )
232 }
233
234 fn from_saved(
235 output: &<Tran as Analysis>::Output,
236 key: &<Self as Save<Spectre, Tran>>::SaveKey,
237 ) -> <Self as Save<Spectre, Tran>>::Saved {
238 let v = OutputWaveform {
239 t: output.time.clone(),
240 x: output
241 .raw_values
242 .get(output.saved_values.get(&key.0.0).unwrap())
243 .unwrap()
244 .clone(),
245 };
246 let currents: Vec<Arc<Vec<f64>>> = key
247 .1
248 .0
249 .iter()
250 .map(|key| {
251 output
252 .raw_values
253 .get(output.saved_values.get(key).unwrap())
254 .unwrap()
255 .clone()
256 })
257 .collect();
258
259 let mut total_current = vec![0.; output.time.len()];
260 for tran_current in currents {
261 for (i, current) in tran_current.iter().enumerate() {
262 total_current[i] += *current;
263 }
264 }
265 NestedTerminalOutput {
266 v,
267 i: OutputWaveform {
268 t: output.time.clone(),
269 x: Arc::new(total_current),
270 },
271 }
272 }
273}
274
275impl Analysis for Tran {
276 type Output = Output;
277}
278
279impl SupportedBy<Spectre> for Tran {
280 fn into_input(self, inputs: &mut Vec<<Spectre as Simulator>::Input>) {
281 inputs.push(self.into());
282 }
283 fn from_output(
284 outputs: &mut impl Iterator<Item = <Spectre as Simulator>::Output>,
285 ) -> <Self as Analysis>::Output {
286 let item = outputs.next().unwrap();
287 item.try_into().unwrap()
288 }
289}