netlist_db/
_impl_display.rs

1use core::fmt;
2use std::{borrow::Borrow as _, fmt::Display};
3
4use super::*;
5
6#[derive(Debug, Clone, Copy)]
7pub struct FloatDisplay(pub f64);
8impl fmt::Display for FloatDisplay {
9    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
10        write!(f, "{:.7e}", self.0)
11    }
12}
13
14pub struct TableFloatDisplay(pub f64);
15impl fmt::Display for TableFloatDisplay {
16    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
17        if self.0.is_sign_positive() {
18            write!(f, " {: <13.7e}", self.0)
19        } else {
20            write!(f, "{: <14.7e}", self.0)
21        }
22    }
23}
24
25pub struct OptionDispaly<'a, T, F: Fn(&T, &mut fmt::Formatter<'_>) -> fmt::Result>(
26    pub &'a Option<T>,
27    pub F,
28);
29impl<T, F: Fn(&T, &mut fmt::Formatter<'_>) -> fmt::Result> Display for OptionDispaly<'_, T, F> {
30    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
31        if let Some(t) = self.0 {
32            self.1(t, f)
33        } else {
34            Ok(())
35        }
36    }
37}
38
39pub fn display_wrap<
40    W: fmt::Write,
41    T,
42    I: Iterator<Item = T>,
43    SEP: fmt::Display,
44    F: FnMut(T, &mut W) -> fmt::Result,
45>(
46    f: &mut W,
47    iter: I,
48    mut fmt_one: F,
49    line_sep: SEP,
50    item_sep: char,
51    wrap_size: usize,
52) -> fmt::Result {
53    use itertools::Itertools as _;
54    for mut ts in iter.into_iter().chunks(wrap_size).into_iter() {
55        write!(f, "\n{line_sep}")?;
56        if let Some(first) = ts.next() {
57            fmt_one(first, f)?;
58            for t in ts {
59                write!(f, "{item_sep}")?;
60                fmt_one(t, f)?;
61            }
62        }
63    }
64    Ok(())
65}
66
67pub fn display_inline_res<
68    E: From<fmt::Error>,
69    W: fmt::Write,
70    T,
71    I: Iterator<Item = Result<T, E>>,
72    F: FnMut(T, &mut W) -> fmt::Result,
73>(
74    f: &mut W,
75    iter: I,
76    mut fmt_one: F,
77    sep: char,
78    skip_first_sep: bool,
79) -> Result<(), E> {
80    let mut iter = iter.into_iter();
81    if skip_first_sep {
82        if let Some(first) = iter.next() {
83            fmt_one(first?, f)?;
84        }
85    }
86    for t in iter {
87        write!(f, "{sep}")?;
88        fmt_one(t?, f)?;
89    }
90    Ok(())
91}
92
93pub fn display_inline<
94    W: fmt::Write,
95    T,
96    I: Iterator<Item = T>,
97    F: FnMut(T, &mut W) -> fmt::Result,
98>(
99    f: &mut W,
100    iter: I,
101    mut fmt_one: F,
102    sep: char,
103    skip_first_sep: bool,
104) -> fmt::Result {
105    let mut iter = iter.into_iter();
106    if skip_first_sep {
107        if let Some(first) = iter.next() {
108            fmt_one(first, f)?;
109        }
110    }
111    for t in iter {
112        write!(f, "{sep}")?;
113        fmt_one(t, f)?;
114    }
115    Ok(())
116}
117
118pub fn display_multiline<
119    W: fmt::Write,
120    T,
121    I: Iterator<Item = T>,
122    F: FnMut(T, &mut W) -> fmt::Result,
123>(
124    f: &mut W,
125    iter: I,
126    mut fmt_one: F,
127) -> fmt::Result {
128    for t in iter.into_iter() {
129        writeln!(f)?;
130        fmt_one(t, f)?;
131    }
132    Ok(())
133}
134
135impl fmt::Display for AST<'_> {
136    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
137        DefaultFmt.ast(self, f)
138    }
139}
140impl fmt::Display for Subckt<'_> {
141    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
142        DefaultFmt.subckt(self, f)
143    }
144}
145
146#[derive(Debug, Clone, Copy)]
147pub struct DefaultFmt;
148impl SpiceFmt for DefaultFmt {}
149
150pub trait SpiceFmt: Sized {
151    fn value<W: fmt::Write>(&self, t: &ast::Value<'_>, f: &mut W) -> fmt::Result {
152        match t {
153            ast::Value::Num(float) => write!(f, "{}", FloatDisplay(*float)),
154            ast::Value::Expr(expr) => write!(f, "'{expr}'"),
155        }
156    }
157    fn key_value<W: fmt::Write>(&self, t: &ast::KeyValue<'_>, f: &mut W) -> fmt::Result {
158        write!(f, "{}=", t.k)?;
159        self.value(&t.v, f)
160    }
161    fn token<W: fmt::Write>(&self, t: &ast::Token<'_>, f: &mut W) -> fmt::Result {
162        match t {
163            ast::Token::KV(t) => self.key_value(t, f),
164            ast::Token::Value(t) => self.value(t, f),
165            ast::Token::V(name) => write!(f, "V({name})"),
166            ast::Token::I(name) => write!(f, "I({name})"),
167        }
168    }
169    fn data_files<W: fmt::Write>(&self, t: &ast::DataFiles<'_>, f: &mut W) -> fmt::Result {
170        display_multiline(f, t.files.iter(), |file, f| {
171            write!(f, "+ FILE='{}'", file.file)?;
172            display_inline(
173                f,
174                file.pname_col_num.iter(),
175                |pname_col_num, f| write!(f, "{}={}", pname_col_num.pname, pname_col_num.col_num),
176                ' ',
177                false,
178            )
179        })?;
180        write!(
181            f,
182            "{}",
183            OptionDispaly(&t.out, |out, f| write!(f, "\n+ OUT='{out}'")),
184        )
185    }
186    fn data<W: fmt::Write>(&self, t: &ast::Data<'_>, f: &mut W) -> fmt::Result {
187        write!(f, ".DATA {}", t.name)?;
188        match &t.values {
189            ast::DataValues::InlineExpr { params, values } => {
190                write!(f, "\n+",)?;
191                display_inline(f, params.iter(), |t, f| write!(f, "{t}"), ' ', false)?;
192                write!(f, " DATAFORM")?;
193                display_wrap(
194                    f,
195                    values.iter(),
196                    |t, f| self.value(t, f),
197                    "+ ",
198                    ' ',
199                    params.len(),
200                )?;
201            }
202            ast::DataValues::InlineNum { params, values } => {
203                write!(f, "\n+",)?;
204                display_inline(f, params.iter(), |t, f| write!(f, "{t}"), ' ', false)?;
205                display_wrap(
206                    f,
207                    values.iter(),
208                    |float, f| write!(f, "{}", FloatDisplay(*float)),
209                    "+ ",
210                    ' ',
211                    params.len(),
212                )?;
213            }
214            ast::DataValues::MER(t) => {
215                write!(f, " MER")?;
216                self.data_files(t, f)?;
217            }
218            ast::DataValues::LAM(t) => {
219                write!(f, " LAM")?;
220                self.data_files(t, f)?;
221            }
222        }
223        write!(f, "\n.ENDDATA")
224    }
225    fn instance<W: fmt::Write>(&self, t: &instance::Instance<'_>, f: &mut W) -> fmt::Result {
226        write!(f, "{} ", t.name)?;
227        self.instance_ctx(&t.ctx, f)
228    }
229    fn instance_ctx<W: fmt::Write>(&self, t: &instance::InstanceCtx<'_>, f: &mut W) -> fmt::Result {
230        match t {
231            instance::InstanceCtx::Resistor(t) => self.resistor(t, f),
232            instance::InstanceCtx::Capacitor(t) => self.capacitor(t, f),
233            instance::InstanceCtx::Inductor(t) => self.inductor(t, f),
234            instance::InstanceCtx::Voltage(t) => self.voltage(t, f),
235            instance::InstanceCtx::Current(t) => self.current(t, f),
236            instance::InstanceCtx::MOSFET(t) => self.mosfet(t, f),
237            instance::InstanceCtx::BJT(t) => self.bjt(t, f),
238            instance::InstanceCtx::Diode(t) => self.diode(t, f),
239            instance::InstanceCtx::Subckt(t) => self.inst_subckt(t, f),
240            instance::InstanceCtx::Unknown {
241                r#type: _,
242                nodes,
243                params,
244            } => {
245                display_inline(f, nodes.iter(), |t, f| write!(f, "{t}"), ' ', true)?;
246                display_inline(f, params.iter(), |t, f| self.key_value(t, f), ' ', false)
247            }
248        }
249    }
250    fn inst_subckt<W: fmt::Write>(&self, t: &instance::Subckt<'_>, f: &mut W) -> fmt::Result {
251        self.ports(t.nodes.iter().map(|s| s.borrow()), f)?;
252        write!(f, " {}", t.cktname)?;
253        display_inline(f, t.params.iter(), |t, f| self.key_value(t, f), ' ', false)
254    }
255    fn voltage<W: fmt::Write>(&self, t: &instance::Voltage<'_>, f: &mut W) -> fmt::Result {
256        write!(f, "{} {} ", t.n1, t.n2)?;
257        self.voltage_source(&t.source, f)
258    }
259    fn current<W: fmt::Write>(&self, t: &instance::Current<'_>, f: &mut W) -> fmt::Result {
260        write!(f, "{} {} ", t.n1, t.n2)?;
261        self.current_source(&t.source, f)
262    }
263    fn voltage_source<W: fmt::Write>(
264        &self,
265        t: &instance::VoltageSource<'_>,
266        f: &mut W,
267    ) -> fmt::Result {
268        match t {
269            instance::VoltageSource::Params(params) => {
270                display_inline(f, params.iter(), |t, f| self.key_value(t, f), ' ', false)
271            }
272            instance::VoltageSource::Value(t) => self.value(t, f),
273            instance::VoltageSource::PWL(t) => self.pwl(t, f),
274        }
275    }
276    fn current_source<W: fmt::Write>(
277        &self,
278        t: &instance::CurrentSource<'_>,
279        f: &mut W,
280    ) -> fmt::Result {
281        match t {
282            instance::CurrentSource::Params(params) => {
283                display_inline(f, params.iter(), |t, f| self.key_value(t, f), ' ', false)
284            }
285            instance::CurrentSource::Value(t) => self.value(t, f),
286            instance::CurrentSource::PWL(t) => self.pwl(t, f),
287        }
288    }
289    fn time_value_point<W: fmt::Write>(
290        &self,
291        t: &instance::TimeValuePoint<'_>,
292        f: &mut W,
293    ) -> fmt::Result {
294        self.value(&t.time, f)?;
295        write!(f, " ")?;
296        self.value(&t.value, f)
297    }
298    fn pwl<W: fmt::Write>(&self, t: &instance::PWL<'_>, f: &mut W) -> fmt::Result {
299        write!(f, "PWL(",)?;
300        display_wrap(
301            f,
302            t.points.iter(),
303            |t, f| self.time_value_point(t, f),
304            "+ ",
305            ' ',
306            1,
307        )?;
308        write!(f, ")",)
309    }
310    fn resistor<W: fmt::Write>(&self, t: &instance::Resistor<'_>, f: &mut W) -> fmt::Result {
311        write!(f, "{} {} ", t.n1, t.n2)?;
312        self.value(&t.value, f)
313    }
314    fn capacitor<W: fmt::Write>(&self, t: &instance::Capacitor<'_>, f: &mut W) -> fmt::Result {
315        write!(f, "{} {} ", t.n1, t.n2)?;
316        self.value(&t.value, f)
317    }
318    fn inductor<W: fmt::Write>(&self, t: &instance::Inductor<'_>, f: &mut W) -> fmt::Result {
319        write!(f, "{} {} ", t.n1, t.n2)?;
320        self.value(&t.value, f)
321    }
322    fn mosfet<W: fmt::Write>(&self, t: &instance::MOSFET<'_>, f: &mut W) -> fmt::Result {
323        write!(
324            f,
325            "{} {} {}{} {}",
326            t.nd,
327            t.ng,
328            t.ns,
329            OptionDispaly(&t.nb, |nb, f| write!(f, " {nb}")),
330            t.mname,
331        )?;
332        display_inline(f, t.params.iter(), |t, f| self.key_value(t, f), ' ', false)
333    }
334    fn bjt<W: fmt::Write>(&self, t: &instance::BJT<'_>, f: &mut W) -> fmt::Result {
335        write!(
336            f,
337            "{} {} {}{} {}",
338            t.nc,
339            t.nb,
340            t.ne,
341            OptionDispaly(&t.ns, |ns, f| write!(f, " {ns}")),
342            t.mname,
343        )?;
344        display_inline(f, t.params.iter(), |t, f| self.key_value(t, f), ' ', false)
345    }
346    fn diode<W: fmt::Write>(&self, t: &instance::Diode<'_>, f: &mut W) -> fmt::Result {
347        write!(f, "{} {} {}", t.nplus, t.nminus, t.mname,)?;
348        display_inline(f, t.params.iter(), |t, f| self.key_value(t, f), ' ', false)
349    }
350    fn model_type<W: fmt::Write>(&self, t: &ast::ModelType<'_>, f: &mut W) -> fmt::Result {
351        match t {
352            ast::ModelType::AMP => write!(f, "AMP"),
353            ast::ModelType::C => write!(f, "C"),
354            ast::ModelType::CORE => write!(f, "CORE"),
355            ast::ModelType::D => write!(f, "D"),
356            ast::ModelType::L => write!(f, "L"),
357            ast::ModelType::NJF => write!(f, "NJF"),
358            ast::ModelType::NMOS => write!(f, "NMOS"),
359            ast::ModelType::NPN => write!(f, "NPN"),
360            ast::ModelType::OPT => write!(f, "OPT"),
361            ast::ModelType::PJF => write!(f, "PJF"),
362            ast::ModelType::PMOS => write!(f, "PMOS"),
363            ast::ModelType::PNP => write!(f, "PNP"),
364            ast::ModelType::R => write!(f, "R"),
365            ast::ModelType::U => write!(f, "U"),
366            ast::ModelType::W => write!(f, "W"),
367            ast::ModelType::S => write!(f, "S"),
368            ast::ModelType::Unknown(span) => write!(f, "{span}"),
369        }
370    }
371    fn model<W: fmt::Write>(&self, t: &ast::Model<'_>, f: &mut W) -> fmt::Result {
372        write!(f, ".MODEL {} ", t.name)?;
373        self.model_type(&t.model_type, f)?;
374        display_wrap(
375            f,
376            t.params.iter(),
377            |t, f| self.key_value(t, f),
378            "+ ",
379            ' ',
380            4,
381        )
382    }
383    fn ports<'a, W: fmt::Write, I: Iterator<Item = &'a str>>(
384        &self,
385        t: I,
386        f: &mut W,
387    ) -> fmt::Result {
388        display_inline(f, t, |t, f| write!(f, "{t}"), ' ', true)
389    }
390    fn subckt<W: fmt::Write>(&self, t: &Subckt<'_>, f: &mut W) -> fmt::Result {
391        write!(f, ".SUBCKT {} ", t.name)?;
392        self.ports(t.ports.iter().map(|s| s.borrow()), f)?;
393        display_inline(f, t.params.iter(), |t, f| self.key_value(t, f), ' ', false)?;
394        self.ast(&t.ast, f)?;
395        write!(f, "\n.ENDS {}", t.name)
396    }
397    fn unknwon<W: fmt::Write>(&self, t: &ast::Unknwon<'_>, f: &mut W) -> fmt::Result {
398        write!(f, ".{}", t.cmd)?;
399        display_inline(f, t.tokens.iter(), |t, f| self.token(t, f), ' ', false)
400    }
401    fn general_cmd<W: fmt::Write>(&self, t: &ast::GeneralCmd, f: &mut W) -> fmt::Result {
402        _ = (t, f);
403        todo!()
404    }
405    fn general<W: fmt::Write>(&self, t: &ast::General<'_>, f: &mut W) -> fmt::Result {
406        write!(f, ".")?;
407        self.general_cmd(&t.cmd, f)?;
408        display_inline(f, t.tokens.iter(), |t, f| self.token(t, f), ' ', false)
409    }
410    fn ast<W: fmt::Write>(&self, t: &AST<'_>, f: &mut W) -> fmt::Result {
411        if !t.option.is_empty() {
412            write!(f, ".OPTION ",)?;
413            display_wrap(
414                f,
415                t.option.iter(),
416                |option, f| {
417                    if let Some(v) = &option.1 {
418                        write!(f, "{}=", option.0)?;
419                        self.value(v, f)
420                    } else {
421                        write!(f, "{}", option.0)
422                    }
423                },
424                "+ ",
425                ' ',
426                4,
427            )?;
428        }
429        if !t.param.is_empty() {
430            write!(f, "\n.PARAM ",)?;
431            display_wrap(f, t.param.iter(), |t, f| self.key_value(t, f), "+ ", ' ', 4)?;
432        }
433        display_multiline(f, t.model.iter(), |t, f| self.model(t, f))?;
434        display_multiline(f, t.subckt.values(), |t, f| self.subckt(t, f))?;
435        display_multiline(f, t.instance.iter(), |t, f| self.instance(t, f))?;
436        display_multiline(f, t.init_condition.iter(), |ic, f| {
437            write!(f, ".IC V({})=", ic.0)?;
438            self.value(&ic.1, f)?;
439            if let Some(subckt) = &ic.2 {
440                write!(f, " suckt={subckt}")
441            } else {
442                Ok(())
443            }
444        })?;
445        display_multiline(f, t.nodeset.iter(), |ic, f| {
446            write!(f, ".NODESET {}=", ic.0)?;
447            self.value(&ic.1, f)?;
448            if let Some(subckt) = &ic.2 {
449                write!(f, " suckt={subckt}")
450            } else {
451                Ok(())
452            }
453        })?;
454        display_multiline(f, t.data.iter(), |t, f| self.data(t, f))?;
455        display_multiline(f, t.general.iter(), |t, f| self.general(t, f))?;
456        display_multiline(f, t.unknwon.iter(), |t, f| self.unknwon(t, f))?;
457        Ok(())
458    }
459}