reda_sp/model/subckt/
mod.rs

1use derive_builder::Builder;
2use reda_unit::{Capacitance, Inductance, Length, Resistance};
3
4use super::{BJTBuilder, CapacitorBuilder, Component, DiodeBuilder, InductorBuilder, MosFETBuilder, ResistorBuilder, ToSpice};
5
6#[derive(Debug, Clone, Builder)]
7#[builder(setter(into))]
8pub struct Subckt {
9    pub name: String,                  // 子电路名
10    pub ports: Vec<String>,            // 接口节点列表(按顺序)
11
12    #[builder(default)]
13    pub components: Vec<Component>,     // 子电路内部元件
14    #[builder(default)]
15    pub instances: Vec<Instance>,      // 实例化
16}
17
18#[derive(Debug, Clone)]
19pub struct Instance {
20    pub name: String,                 // 实例名称,如 XU1
21    pub pins: Vec<String>,            // 接口节点连接到外部的节点
22    pub subckt_name: String,          // 被实例化的子电路名称
23}
24
25impl Subckt {
26    pub fn add_resistor<S1, S2, S3, N>(&mut self, name: S1, node_pos: S2, node_neg: S3, resistance: N) 
27    where 
28        S1: Into<String>,
29        S2: Into<String>,
30        S3: Into<String>,
31        N: Into<Resistance>,
32    {
33        let r = ResistorBuilder::default()
34            .name(name)
35            .node_neg(node_neg)
36            .node_pos(node_pos)
37            .resistance(resistance).build().unwrap();
38        self.components.push(Component::R(r));
39    }
40
41    pub fn add_capacitor<S1, S2, S3, N>(&mut self, name: S1, node_pos: S2, node_neg: S3, capacitance: N) 
42    where 
43        S1: Into<String>,
44        S2: Into<String>,
45        S3: Into<String>,
46        N: Into<Capacitance>,
47    {
48        let c = CapacitorBuilder::default()
49            .name(name)
50            .node_neg(node_neg)
51            .node_pos(node_pos)
52            .capacitance(capacitance).build().unwrap();
53        self.components.push(Component::C(c));
54    }
55
56    pub fn add_inductor<S1, S2, S3, N>(&mut self, name: S1, node_pos: S2, node_neg: S3, inductance: N) 
57    where 
58        S1: Into<String>,
59        S2: Into<String>,
60        S3: Into<String>,
61        N: Into<Inductance>,
62    {
63        let l = InductorBuilder::default()
64            .name(name)
65            .node_neg(node_neg)
66            .node_pos(node_pos)
67            .inductance(inductance).build().unwrap();
68        self.components.push(Component::L(l));
69    }
70
71    pub fn add_diode<S1, S2, S3>(&mut self, name: S1, node_p: S2, node_n: S3, model_name: S1)
72    where
73        S1: Into<String>,
74        S2: Into<String>,
75        S3: Into<String>,
76    {
77        let d = DiodeBuilder::default()
78            .name(name)
79            .node_pos(node_p)
80            .node_neg(node_n)
81            .model_name(model_name)
82            .build()
83            .unwrap();
84        self.components.push(Component::D(d));
85    }
86
87    pub fn add_bjt<S1, S2, S3, S4, S5>(&mut self, name: S1, collector: S2, base: S3, emitter: S4, model_name: S5)
88    where
89        S1: Into<String>,
90        S2: Into<String>,
91        S3: Into<String>,
92        S4: Into<String>,
93        S5: Into<String>,
94    {
95        let q = BJTBuilder::default()
96            .name(name)
97            .collector(collector)
98            .base(base)
99            .emitter(emitter)
100            .model_name(model_name)
101            .build()
102            .unwrap();
103        self.components.push(Component::Q(q));
104    }
105
106    pub fn add_mosfet<S1, S2, S3, S4, S5, S6, N1, N2>(
107        &mut self,
108        name: S1,
109        drain: S2,
110        gate: S3,
111        source: S4,
112        bulk: S5,
113        model_name: S6,
114        length: N1,
115        width: N2,
116    )
117    where
118        S1: Into<String>,
119        S2: Into<String>,
120        S3: Into<String>,
121        S4: Into<String>,
122        S5: Into<String>,
123        S6: Into<String>,
124        N1: Into<Length>,
125        N2: Into<Length>,
126    {
127        let m = MosFETBuilder::default()
128            .name(name)
129            .drain(drain)
130            .gate(gate)
131            .source(source)
132            .bulk(bulk)
133            .model_name(model_name)
134            .length(length)
135            .width(width)
136            .build()
137            .unwrap();
138        self.components.push(Component::M(m));
139    }
140}
141
142impl ToSpice for Subckt {
143    fn to_spice(&self) -> String {
144        let mut lines = vec![];
145        lines.push(format!(
146            ".SUBCKT {} {}\n",
147            self.name,
148            self.ports.join(" ")
149        ));
150
151        for c in self.components.iter() {
152            lines.push(c.to_spice());
153        }
154
155        for i in self.instances.iter() {
156            lines.push(i.to_spice());
157        }
158
159        lines.push(format!(".ENDS {}", self.name));
160
161        lines.join("\n")
162    }
163}
164
165impl ToSpice for Instance {
166    fn to_spice(&self) -> String {
167        format!(
168            "X{} {} {}",
169            self.name,
170            self.pins.join(" "),
171            self.subckt_name
172        )
173    }
174}