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, pub ports: Vec<String>, #[builder(default)]
13 pub components: Vec<Component>, #[builder(default)]
15 pub instances: Vec<Instance>, }
17
18#[derive(Debug, Clone)]
19pub struct Instance {
20 pub name: String, pub pins: Vec<String>, pub subckt_name: String, }
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}