1use crate::{InstanceTail, SimSignal, Spectre};
4use arcstr::ArcStr;
5use num::complex::Complex64;
6use rust_decimal::Decimal;
7use scir::{NamedSliceOne, SliceOnePath};
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10use std::sync::Arc;
11use substrate::{
12 schematic::conv::ConvertedNodePath,
13 simulation::{
14 Analysis, SimulationContext, Simulator, SupportedBy,
15 data::{Save, SaveFreq, SaveOutput},
16 },
17 types::schematic::{NestedNode, NestedTerminal, RawNestedNode},
18};
19
20use super::Sweep;
21
22#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
24pub struct Ac {
25 pub start: Decimal,
29 pub stop: Decimal,
31 pub sweep: Sweep,
33}
34
35#[derive(Debug, Clone)]
37pub struct Output {
38 pub freq: Arc<Vec<f64>>,
40 pub raw_values: HashMap<ArcStr, Arc<Vec<Complex64>>>,
42 pub(crate) saved_values: HashMap<u64, ArcStr>,
44}
45
46#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Serialize, Deserialize)]
48pub struct VoltageSaveKey(pub(crate) u64);
49
50#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
52pub struct CurrentSaveKey(pub(crate) Vec<u64>);
53
54impl Analysis for Ac {
55 type Output = Output;
56}
57
58impl SupportedBy<Spectre> for Ac {
59 fn into_input(self, inputs: &mut Vec<<Spectre as Simulator>::Input>) {
60 inputs.push(self.into());
61 }
62 fn from_output(
63 outputs: &mut impl Iterator<Item = <Spectre as Simulator>::Output>,
64 ) -> <Self as Analysis>::Output {
65 let item = outputs.next().unwrap();
66 item.try_into().unwrap()
67 }
68}
69
70impl Save<Spectre, Ac> for SaveOutput {
71 type SaveKey = ();
72 type Saved = Output;
73
74 fn save(
75 &self,
76 _ctx: &SimulationContext<Spectre>,
77 _opts: &mut <Spectre as Simulator>::Options,
78 ) -> <Self as Save<Spectre, Ac>>::SaveKey {
79 }
80
81 fn from_saved(
82 output: &<Ac as Analysis>::Output,
83 _key: &<Self as Save<Spectre, Ac>>::SaveKey,
84 ) -> <Self as Save<Spectre, Ac>>::Saved {
85 output.clone()
86 }
87}
88
89impl Save<Spectre, Ac> for SaveFreq {
90 type SaveKey = ();
91 type Saved = Arc<Vec<f64>>;
92
93 fn save(
94 &self,
95 _ctx: &SimulationContext<Spectre>,
96 _opts: &mut <Spectre as Simulator>::Options,
97 ) -> <Self as Save<Spectre, Ac>>::SaveKey {
98 }
99
100 fn from_saved(
101 output: &<Ac as Analysis>::Output,
102 _key: &<Self as Save<Spectre, Ac>>::SaveKey,
103 ) -> <Self as Save<Spectre, Ac>>::Saved {
104 output.freq.clone()
105 }
106}
107
108impl Save<Spectre, Ac> for NestedNode {
109 type SaveKey = VoltageSaveKey;
110 type Saved = Arc<Vec<Complex64>>;
111
112 fn save(
113 &self,
114 ctx: &SimulationContext<Spectre>,
115 opts: &mut <Spectre as Simulator>::Options,
116 ) -> <Self as Save<Spectre, Ac>>::SaveKey {
117 opts.save_ac_voltage(SimSignal::ScirVoltage(
118 match ctx.lib.convert_node_path(&self.path()).unwrap() {
119 ConvertedNodePath::Cell(path) => path.clone(),
120 ConvertedNodePath::Primitive {
121 instances, port, ..
122 } => SliceOnePath::new(instances.clone(), NamedSliceOne::new(port.clone())),
123 },
124 ))
125 }
126
127 fn from_saved(
128 output: &<Ac as Analysis>::Output,
129 key: &<Self as Save<Spectre, Ac>>::SaveKey,
130 ) -> <Self as Save<Spectre, Ac>>::Saved {
131 output
132 .raw_values
133 .get(output.saved_values.get(&key.0).unwrap())
134 .unwrap()
135 .clone()
136 }
137}
138
139impl Save<Spectre, Ac> for RawNestedNode {
140 type SaveKey = VoltageSaveKey;
141 type Saved = Arc<Vec<Complex64>>;
142
143 fn save(
144 &self,
145 ctx: &SimulationContext<Spectre>,
146 opts: &mut <Spectre as Simulator>::Options,
147 ) -> <Self as Save<Spectre, Ac>>::SaveKey {
148 let itail = InstanceTail {
149 instance: ctx.lib.convert_instance_path(self.instances()).unwrap(),
150 tail: self.tail().clone(),
151 };
152 opts.save_ac_voltage(itail)
153 }
154
155 fn from_saved(
156 output: &<Ac as Analysis>::Output,
157 key: &<Self as Save<Spectre, Ac>>::SaveKey,
158 ) -> <Self as Save<Spectre, Ac>>::Saved {
159 output
160 .raw_values
161 .get(output.saved_values.get(&key.0).unwrap())
162 .unwrap()
163 .clone()
164 }
165}
166
167pub struct NestedTerminalOutput {
169 pub v: Arc<Vec<Complex64>>,
171 pub i: Arc<Vec<Complex64>>,
173}
174
175impl Save<Spectre, Ac> for NestedTerminal {
176 type SaveKey = (VoltageSaveKey, CurrentSaveKey);
177 type Saved = NestedTerminalOutput;
178
179 fn save(
180 &self,
181 ctx: &SimulationContext<Spectre>,
182 opts: &mut <Spectre as Simulator>::Options,
183 ) -> <Self as Save<Spectre, Ac>>::SaveKey {
184 (
185 <NestedNode as Save<Spectre, Ac>>::save(self, ctx, opts),
186 CurrentSaveKey(
187 ctx.lib
188 .convert_terminal_path(&self.path())
189 .unwrap()
190 .into_iter()
191 .flat_map(|path| {
192 opts.save_tran_current(SimSignal::ScirCurrent(match path {
193 ConvertedNodePath::Cell(path) => path.clone(),
194 ConvertedNodePath::Primitive {
195 instances, port, ..
196 } => SliceOnePath::new(
197 instances.clone(),
198 NamedSliceOne::new(port.clone()),
199 ),
200 }))
201 .0
202 })
203 .collect(),
204 ),
205 )
206 }
207
208 fn from_saved(
209 output: &<Ac as Analysis>::Output,
210 key: &<Self as Save<Spectre, Ac>>::SaveKey,
211 ) -> <Self as Save<Spectre, Ac>>::Saved {
212 let v = output
213 .raw_values
214 .get(output.saved_values.get(&key.0.0).unwrap())
215 .unwrap()
216 .clone();
217 let currents: Vec<Arc<Vec<Complex64>>> = key
218 .1
219 .0
220 .iter()
221 .map(|key| {
222 output
223 .raw_values
224 .get(output.saved_values.get(key).unwrap())
225 .unwrap()
226 .clone()
227 })
228 .collect();
229
230 let mut total_current = vec![Complex64::ZERO; output.freq.len()];
231 for tran_current in currents {
232 for (i, current) in tran_current.iter().enumerate() {
233 total_current[i] += *current;
234 }
235 }
236 NestedTerminalOutput {
237 v,
238 i: Arc::new(total_current),
239 }
240 }
241}