netlist_db/
ast.rs

1use std::sync::{Arc, OnceLock};
2
3use crate::{
4    err::ParseError,
5    instance::InstanceBuilder,
6    self_builder,
7    span::{ParsedId, Span},
8};
9use netlist_macros::Builder;
10
11#[derive(Debug, Clone, Copy, Builder)]
12pub enum ValueBuilder {
13    Num(f64),
14    Expr(Span),
15}
16
17#[derive(Debug, Clone, Default, Copy, Builder)]
18pub struct KeyValueBuilder {
19    pub k: Span,
20    pub v: ValueBuilder,
21}
22
23#[derive(Debug, Clone, Copy, Builder)]
24pub enum TokenBuilder {
25    KV(KeyValueBuilder),
26    Value(ValueBuilder),
27    V(Span),
28    I(Span),
29}
30
31#[derive(Debug, Clone, Copy)]
32pub enum GeneralCmd {
33    /// `.ic` initial condition
34    Ic,
35    /// `.ic` initial condition
36    Meas,
37}
38self_builder!(GeneralCmd);
39#[derive(Debug, Clone, Builder)]
40pub struct GeneralBuilder {
41    pub cmd: GeneralCmd,
42    pub tokens: Vec<TokenBuilder>,
43}
44
45#[derive(Debug, Clone, Builder)]
46pub struct UnknwonBuilder {
47    pub cmd: Span,
48    pub tokens: Vec<TokenBuilder>,
49}
50
51#[derive(Debug, Clone, Builder)]
52pub struct ModelBuilder {
53    pub name: Span,
54    pub model_type: ModelTypeBuilder,
55    pub params: Vec<KeyValueBuilder>,
56}
57
58#[derive(Debug, Clone, Copy, Builder)]
59pub enum ModelTypeBuilder {
60    /// operational amplifier model
61    AMP,
62    /// capacitor model
63    C,
64    /// magnetic core model
65    CORE,
66    /// diode model
67    D,
68    /// inductor model or magnetic core mutual inductor model
69    L,
70    /// n-channel JFET model
71    NJF,
72    /// n-channel MOSFET model
73    NMOS,
74    /// npn BJT model
75    NPN,
76    /// optimization model
77    OPT,
78    /// p-channel JFET model
79    PJF,
80    /// p-channel MOSFET model
81    PMOS,
82    /// pnp BJT model
83    PNP,
84    /// resistor model
85    R,
86    /// lossy transmission line model (lumped)
87    U,
88    /// lossy transmission line model
89    W,
90    /// S-parameter
91    S,
92    Unknown(Span),
93}
94
95#[derive(Debug, Clone, Builder)]
96pub struct DataBuilder {
97    pub name: Span,
98    pub values: DataValuesBuilder,
99}
100#[derive(Debug, Clone, Builder)]
101pub enum DataValuesBuilder {
102    InlineExpr {
103        params: Vec<Span>,
104        values: Vec<ValueBuilder>,
105    },
106    InlineNum {
107        params: Vec<Span>,
108        values: Vec<f64>,
109    },
110    /// https://eda-cpu1.eias.junzhuo.site/~junzhuo/hspice/index.htm#page/hspice_14/data.htm
111    /// Concatenated (series merging) data files to use.
112    MER(DataFilesBuilder),
113    /// Column-laminated (parallel merging) data files to use.
114    LAM(DataFilesBuilder),
115}
116#[derive(Debug, Clone, Builder)]
117pub struct DataFilesBuilder {
118    pub files: Vec<DataFileBuilder>,
119    pub out: Option<Span>,
120}
121#[derive(Debug, Clone, Builder)]
122pub struct DataFileBuilder {
123    pub file: Span,
124    pub pname_col_num: Vec<PnameColNumBuilder>,
125}
126
127#[derive(Debug, Clone, Builder)]
128pub struct PnameColNumBuilder {
129    pub pname: Span,
130    pub col_num: usize,
131}
132
133/// ``` spice
134/// .subckt pulvt11ll_ckt d g s b w=1e-6 l=1e-6 sa='sar'
135/// ...
136/// .ends pulvt11ll_ckt
137/// ```
138/// Do NOT support `.include` / `.lib` in `.subckt`
139#[derive(Debug)]
140pub struct SubcktBuilder {
141    pub name: Span,
142    /// subckt/model name is the last arg
143    pub ports: Vec<Span>,
144    pub params: Vec<KeyValueBuilder>,
145    pub ast: ASTBuilder,
146}
147
148/// The `.include` and `.lib file tt` will be directly evaluated
149#[derive(Debug, Default)]
150pub struct LocalAST {
151    pub subckt: Vec<SubcktBuilder>,
152    pub instance: Vec<InstanceBuilder>,
153    pub model: Vec<ModelBuilder>,
154    pub param: Vec<KeyValueBuilder>,
155    pub option: Vec<(Span, Option<ValueBuilder>)>,
156    pub data: Vec<DataBuilder>,
157    pub general: Vec<GeneralBuilder>,
158    pub init_condition: Vec<(Span, ValueBuilder, Option<Span>)>,
159    pub nodeset: Vec<(Span, ValueBuilder, Option<Span>)>,
160    pub unknwon: Vec<UnknwonBuilder>,
161    pub errors: Vec<ParseError>,
162}
163
164impl LocalAST {
165    pub fn is_empty(&self) -> bool {
166        self.subckt.is_empty()
167            && self.instance.is_empty()
168            && self.model.is_empty()
169            && self.param.is_empty()
170            && self.option.is_empty()
171            && self.data.is_empty()
172            && self.general.is_empty()
173            && self.unknwon.is_empty()
174            && self.errors.is_empty()
175    }
176}
177
178#[derive(Debug)]
179pub enum Segment {
180    Local(Box<LocalAST>),
181    Include(Arc<OnceLock<Result<ParsedId, ParseError>>>),
182}
183#[derive(Debug, Default)]
184pub struct ASTBuilder {
185    pub segments: Vec<Segment>,
186}
187
188impl ASTBuilder {
189    pub fn new() -> Self {
190        Self {
191            segments: Vec::new(),
192        }
193    }
194}
195
196impl Default for ValueBuilder {
197    #[inline]
198    fn default() -> Self {
199        Self::Num(0.0)
200    }
201}
202
203impl From<(&str, Span)> for ModelTypeBuilder {
204    #[inline]
205    fn from(value: (&str, Span)) -> Self {
206        let (_str, _type) = value;
207        match _str.to_uppercase().as_str() {
208            "AMP" => Self::AMP,
209            "C" => Self::C,
210            "CORE" => Self::CORE,
211            "D" => Self::D,
212            "L" => Self::L,
213            "NJF" => Self::NJF,
214            "NMOS" => Self::NMOS,
215            "NPN" => Self::NPN,
216            "OPT" => Self::OPT,
217            "PJF" => Self::PJF,
218            "PMOS" => Self::PMOS,
219            "PNP" => Self::PNP,
220            "R" => Self::R,
221            "U" => Self::U,
222            "W" => Self::W,
223            "S" => Self::S,
224            _ => Self::Unknown(_type),
225        }
226    }
227}