50#include <boost/algorithm/string.hpp>
52#include <pegtl/contrib/parse_tree.hpp>
57using TYPE = SIM_MODEL::TYPE;
67 case DEVICE_T::NONE:
return {
"",
"",
true };
68 case DEVICE_T::R:
return {
"R",
"Resistor",
true };
69 case DEVICE_T::C:
return {
"C",
"Capacitor",
true };
70 case DEVICE_T::L:
return {
"L",
"Inductor",
true };
71 case DEVICE_T::K:
return {
"K",
"Mutual Inductance Statement",
true };
72 case DEVICE_T::TLINE:
return {
"TLINE",
"Transmission Line",
true };
73 case DEVICE_T::SW:
return {
"SW",
"Switch",
true };
75 case DEVICE_T::D:
return {
"D",
"Diode",
true };
76 case DEVICE_T::NPN:
return {
"NPN",
"NPN BJT",
true };
77 case DEVICE_T::PNP:
return {
"PNP",
"PNP BJT",
true };
79 case DEVICE_T::NJFET:
return {
"NJFET",
"N-channel JFET",
true };
80 case DEVICE_T::PJFET:
return {
"PJFET",
"P-channel JFET",
true };
82 case DEVICE_T::NMOS:
return {
"NMOS",
"N-channel MOSFET",
true };
83 case DEVICE_T::PMOS:
return {
"PMOS",
"P-channel MOSFET",
true };
84 case DEVICE_T::NMES:
return {
"NMES",
"N-channel MESFET",
true };
85 case DEVICE_T::PMES:
return {
"PMES",
"P-channel MESFET",
true };
87 case DEVICE_T::V:
return {
"V",
"Voltage Source",
true };
88 case DEVICE_T::I:
return {
"I",
"Current Source",
true };
89 case DEVICE_T::E:
return {
"E",
"Voltage Source",
false };
90 case DEVICE_T::F:
return {
"F",
"Current Source",
false };
91 case DEVICE_T::G:
return {
"G",
"Current Source",
false };
92 case DEVICE_T::H:
return {
"H",
"Voltage Source",
false };
94 case DEVICE_T::KIBIS:
return {
"IBIS",
"IBIS Model",
false };
96 case DEVICE_T::SUBCKT:
return {
"SUBCKT",
"Subcircuit",
false };
97 case DEVICE_T::XSPICE:
return {
"XSPICE",
"XSPICE Code Model",
true };
98 case DEVICE_T::SPICE:
return {
"SPICE",
"Raw SPICE Element",
true };
100 default: wxFAIL;
return {};
112 case TYPE::NONE:
return { DEVICE_T::NONE,
"",
"" };
114 case TYPE::R:
return { DEVICE_T::R,
"",
"Ideal" };
115 case TYPE::R_POT:
return { DEVICE_T::R,
"POT",
"Potentiometer" };
116 case TYPE::R_BEHAVIORAL:
return { DEVICE_T::R,
"=",
"Behavioral" };
118 case TYPE::C:
return { DEVICE_T::C,
"",
"Ideal" };
119 case TYPE::C_BEHAVIORAL:
return { DEVICE_T::C,
"=",
"Behavioral" };
121 case TYPE::L:
return { DEVICE_T::L,
"",
"Ideal" };
122 case TYPE::L_BEHAVIORAL:
return { DEVICE_T::L,
"=",
"Behavioral" };
124 case TYPE::K:
return { DEVICE_T::K,
"",
"Mutual Inductance Statement" };
126 case TYPE::TLINE_Z0:
return { DEVICE_T::TLINE,
"",
"Characteristic impedance" };
127 case TYPE::TLINE_RLGC:
return { DEVICE_T::TLINE,
"RLGC",
"RLGC" };
129 case TYPE::SW_V:
return { DEVICE_T::SW,
"V",
"Voltage-controlled" };
130 case TYPE::SW_I:
return { DEVICE_T::SW,
"I",
"Current-controlled" };
132 case TYPE::D:
return { DEVICE_T::D,
"",
"" };
134 case TYPE::NPN_VBIC:
return { DEVICE_T::NPN,
"VBIC",
"VBIC" };
135 case TYPE::PNP_VBIC:
return { DEVICE_T::PNP,
"VBIC",
"VBIC" };
136 case TYPE::NPN_GUMMELPOON:
return { DEVICE_T::NPN,
"GUMMELPOON",
"Gummel-Poon" };
137 case TYPE::PNP_GUMMELPOON:
return { DEVICE_T::PNP,
"GUMMELPOON",
"Gummel-Poon" };
139 case TYPE::NPN_HICUM2:
return { DEVICE_T::NPN,
"HICUML2",
"HICUM level 2" };
140 case TYPE::PNP_HICUM2:
return { DEVICE_T::PNP,
"HICUML2",
"HICUM level 2" };
143 case TYPE::NJFET_SHICHMANHODGES:
return { DEVICE_T::NJFET,
"SHICHMANHODGES",
"Shichman-Hodges" };
144 case TYPE::PJFET_SHICHMANHODGES:
return { DEVICE_T::PJFET,
"SHICHMANHODGES",
"Shichman-Hodges" };
145 case TYPE::NJFET_PARKERSKELLERN:
return { DEVICE_T::NJFET,
"PARKERSKELLERN",
"Parker-Skellern" };
146 case TYPE::PJFET_PARKERSKELLERN:
return { DEVICE_T::PJFET,
"PARKERSKELLERN",
"Parker-Skellern" };
148 case TYPE::NMES_STATZ:
return { DEVICE_T::NMES,
"STATZ",
"Statz" };
149 case TYPE::PMES_STATZ:
return { DEVICE_T::PMES,
"STATZ",
"Statz" };
150 case TYPE::NMES_YTTERDAL:
return { DEVICE_T::NMES,
"YTTERDAL",
"Ytterdal" };
151 case TYPE::PMES_YTTERDAL:
return { DEVICE_T::PMES,
"YTTERDAL",
"Ytterdal" };
152 case TYPE::NMES_HFET1:
return { DEVICE_T::NMES,
"HFET1",
"HFET1" };
153 case TYPE::PMES_HFET1:
return { DEVICE_T::PMES,
"HFET1",
"HFET1" };
154 case TYPE::NMES_HFET2:
return { DEVICE_T::NMES,
"HFET2",
"HFET2" };
155 case TYPE::PMES_HFET2:
return { DEVICE_T::PMES,
"HFET2",
"HFET2" };
157 case TYPE::NMOS_VDMOS:
return { DEVICE_T::NMOS,
"VDMOS",
"VDMOS" };
158 case TYPE::PMOS_VDMOS:
return { DEVICE_T::PMOS,
"VDMOS",
"VDMOS" };
159 case TYPE::NMOS_MOS1:
return { DEVICE_T::NMOS,
"MOS1",
"Classical quadratic (MOS1)" };
160 case TYPE::PMOS_MOS1:
return { DEVICE_T::PMOS,
"MOS1",
"Classical quadratic (MOS1)" };
161 case TYPE::NMOS_MOS2:
return { DEVICE_T::NMOS,
"MOS2",
"Grove-Frohman (MOS2)" };
162 case TYPE::PMOS_MOS2:
return { DEVICE_T::PMOS,
"MOS2",
"Grove-Frohman (MOS2)" };
163 case TYPE::NMOS_MOS3:
return { DEVICE_T::NMOS,
"MOS3",
"MOS3" };
164 case TYPE::PMOS_MOS3:
return { DEVICE_T::PMOS,
"MOS3",
"MOS3" };
165 case TYPE::NMOS_BSIM1:
return { DEVICE_T::NMOS,
"BSIM1",
"BSIM1" };
166 case TYPE::PMOS_BSIM1:
return { DEVICE_T::PMOS,
"BSIM1",
"BSIM1" };
167 case TYPE::NMOS_BSIM2:
return { DEVICE_T::NMOS,
"BSIM2",
"BSIM2" };
168 case TYPE::PMOS_BSIM2:
return { DEVICE_T::PMOS,
"BSIM2",
"BSIM2" };
169 case TYPE::NMOS_MOS6:
return { DEVICE_T::NMOS,
"MOS6",
"MOS6" };
170 case TYPE::PMOS_MOS6:
return { DEVICE_T::PMOS,
"MOS6",
"MOS6" };
171 case TYPE::NMOS_BSIM3:
return { DEVICE_T::NMOS,
"BSIM3",
"BSIM3" };
172 case TYPE::PMOS_BSIM3:
return { DEVICE_T::PMOS,
"BSIM3",
"BSIM3" };
173 case TYPE::NMOS_MOS9:
return { DEVICE_T::NMOS,
"MOS9",
"MOS9" };
174 case TYPE::PMOS_MOS9:
return { DEVICE_T::PMOS,
"MOS9",
"MOS9" };
175 case TYPE::NMOS_B4SOI:
return { DEVICE_T::NMOS,
"B4SOI",
"BSIM4 SOI (B4SOI)" };
176 case TYPE::PMOS_B4SOI:
return { DEVICE_T::PMOS,
"B4SOI",
"BSIM4 SOI (B4SOI)" };
177 case TYPE::NMOS_BSIM4:
return { DEVICE_T::NMOS,
"BSIM4",
"BSIM4" };
178 case TYPE::PMOS_BSIM4:
return { DEVICE_T::PMOS,
"BSIM4",
"BSIM4" };
183 case TYPE::NMOS_B3SOIFD:
return { DEVICE_T::NMOS,
"B3SOIFD",
"B3SOIFD (BSIM3 FD-SOI)" };
184 case TYPE::PMOS_B3SOIFD:
return { DEVICE_T::PMOS,
"B3SOIFD",
"B3SOIFD (BSIM3 FD-SOI)" };
185 case TYPE::NMOS_B3SOIDD:
return { DEVICE_T::NMOS,
"B3SOIDD",
"B3SOIDD (BSIM3 SOI)" };
186 case TYPE::PMOS_B3SOIDD:
return { DEVICE_T::PMOS,
"B3SOIDD",
"B3SOIDD (BSIM3 SOI)" };
187 case TYPE::NMOS_B3SOIPD:
return { DEVICE_T::NMOS,
"B3SOIPD",
"B3SOIPD (BSIM3 PD-SOI)" };
188 case TYPE::PMOS_B3SOIPD:
return { DEVICE_T::PMOS,
"B3SOIPD",
"B3SOIPD (BSIM3 PD-SOI)" };
191 case TYPE::NMOS_HISIM2:
return { DEVICE_T::NMOS,
"HISIM2",
"HiSIM2" };
192 case TYPE::PMOS_HISIM2:
return { DEVICE_T::PMOS,
"HISIM2",
"HiSIM2" };
193 case TYPE::NMOS_HISIMHV1:
return { DEVICE_T::NMOS,
"HISIMHV1",
"HiSIM_HV1" };
194 case TYPE::PMOS_HISIMHV1:
return { DEVICE_T::PMOS,
"HISIMHV1",
"HiSIM_HV1" };
195 case TYPE::NMOS_HISIMHV2:
return { DEVICE_T::NMOS,
"HISIMHV2",
"HiSIM_HV2" };
196 case TYPE::PMOS_HISIMHV2:
return { DEVICE_T::PMOS,
"HISIMHV2",
"HiSIM_HV2" };
198 case TYPE::V:
return { DEVICE_T::V,
"DC",
"DC", };
199 case TYPE::V_SIN:
return { DEVICE_T::V,
"SIN",
"Sine" };
200 case TYPE::V_PULSE:
return { DEVICE_T::V,
"PULSE",
"Pulse" };
201 case TYPE::V_EXP:
return { DEVICE_T::V,
"EXP",
"Exponential" };
202 case TYPE::V_AM:
return { DEVICE_T::V,
"AM",
"Amplitude modulated" };
203 case TYPE::V_SFFM:
return { DEVICE_T::V,
"SFFM",
"Single-frequency FM" };
204 case TYPE::V_VCL:
return { DEVICE_T::E,
"",
"Voltage-controlled" };
205 case TYPE::V_CCL:
return { DEVICE_T::H,
"",
"Current-controlled" };
206 case TYPE::V_PWL:
return { DEVICE_T::V,
"PWL",
"Piecewise linear" };
207 case TYPE::V_WHITENOISE:
return { DEVICE_T::V,
"WHITENOISE",
"White noise" };
208 case TYPE::V_PINKNOISE:
return { DEVICE_T::V,
"PINKNOISE",
"Pink noise (1/f)" };
209 case TYPE::V_BURSTNOISE:
return { DEVICE_T::V,
"BURSTNOISE",
"Burst noise" };
210 case TYPE::V_RANDUNIFORM:
return { DEVICE_T::V,
"RANDUNIFORM",
"Random uniform" };
211 case TYPE::V_RANDGAUSSIAN:
return { DEVICE_T::V,
"RANDGAUSSIAN",
"Random Gaussian" };
212 case TYPE::V_RANDEXP:
return { DEVICE_T::V,
"RANDEXP",
"Random exponential" };
213 case TYPE::V_RANDPOISSON:
return { DEVICE_T::V,
"RANDPOISSON",
"Random Poisson" };
214 case TYPE::V_BEHAVIORAL:
return { DEVICE_T::V,
"=",
"Behavioral" };
216 case TYPE::I:
return { DEVICE_T::I,
"DC",
"DC", };
217 case TYPE::I_SIN:
return { DEVICE_T::I,
"SIN",
"Sine" };
218 case TYPE::I_PULSE:
return { DEVICE_T::I,
"PULSE",
"Pulse" };
219 case TYPE::I_EXP:
return { DEVICE_T::I,
"EXP",
"Exponential" };
220 case TYPE::I_AM:
return { DEVICE_T::I,
"AM",
"Amplitude modulated" };
221 case TYPE::I_SFFM:
return { DEVICE_T::I,
"SFFM",
"Single-frequency FM" };
222 case TYPE::I_VCL:
return { DEVICE_T::G,
"",
"Voltage-controlled" };
223 case TYPE::I_CCL:
return { DEVICE_T::F,
"",
"Current-controlled" };
224 case TYPE::I_PWL:
return { DEVICE_T::I,
"PWL",
"Piecewise linear" };
225 case TYPE::I_WHITENOISE:
return { DEVICE_T::I,
"WHITENOISE",
"White noise" };
226 case TYPE::I_PINKNOISE:
return { DEVICE_T::I,
"PINKNOISE",
"Pink noise (1/f)" };
227 case TYPE::I_BURSTNOISE:
return { DEVICE_T::I,
"BURSTNOISE",
"Burst noise" };
228 case TYPE::I_RANDUNIFORM:
return { DEVICE_T::I,
"RANDUNIFORM",
"Random uniform" };
229 case TYPE::I_RANDGAUSSIAN:
return { DEVICE_T::I,
"RANDGAUSSIAN",
"Random Gaussian" };
230 case TYPE::I_RANDEXP:
return { DEVICE_T::I,
"RANDEXP",
"Random exponential" };
231 case TYPE::I_RANDPOISSON:
return { DEVICE_T::I,
"RANDPOISSON",
"Random Poisson" };
232 case TYPE::I_BEHAVIORAL:
return { DEVICE_T::I,
"=",
"Behavioral" };
234 case TYPE::SUBCKT:
return { DEVICE_T::SUBCKT,
"",
"Subcircuit" };
235 case TYPE::XSPICE:
return { DEVICE_T::XSPICE,
"",
"" };
237 case TYPE::KIBIS_DEVICE:
return { DEVICE_T::KIBIS,
"DEVICE",
"Device" };
238 case TYPE::KIBIS_DRIVER_DC:
return { DEVICE_T::KIBIS,
"DCDRIVER",
"DC driver" };
239 case TYPE::KIBIS_DRIVER_RECT:
return { DEVICE_T::KIBIS,
"RECTDRIVER",
"Rectangular wave driver" };
240 case TYPE::KIBIS_DRIVER_PRBS:
return { DEVICE_T::KIBIS,
"PRBSDRIVER",
"PRBS driver" };
242 case TYPE::RAWSPICE:
return { DEVICE_T::SPICE,
"",
"" };
244 default: wxFAIL;
return {};
255 case TYPE::R:
return {
"R",
"" };
256 case TYPE::R_POT:
return {
"A",
"" };
257 case TYPE::R_BEHAVIORAL:
return {
"R",
"",
"",
"0",
false,
true };
259 case TYPE::C:
return {
"C",
"" };
260 case TYPE::C_BEHAVIORAL:
return {
"C",
"",
"",
"0",
false,
true };
262 case TYPE::L:
return {
"L",
"" };
263 case TYPE::L_BEHAVIORAL:
return {
"L",
"",
"",
"0",
false,
true };
265 case TYPE::K:
return {
"K",
"" };
268 case TYPE::TLINE_Z0:
return {
"O",
"LTRA" };
269 case TYPE::TLINE_RLGC:
return {
"O",
"LTRA" };
271 case TYPE::SW_V:
return {
"S",
"SW" };
272 case TYPE::SW_I:
return {
"W",
"CSW" };
274 case TYPE::D:
return {
"D",
"D" };
276 case TYPE::NPN_VBIC:
return {
"Q",
"NPN",
"",
"4" };
277 case TYPE::PNP_VBIC:
return {
"Q",
"PNP",
"",
"4" };
278 case TYPE::NPN_GUMMELPOON:
return {
"Q",
"NPN",
"",
"1",
true };
279 case TYPE::PNP_GUMMELPOON:
return {
"Q",
"PNP",
"",
"1",
true };
280 case TYPE::NPN_HICUM2:
return {
"Q",
"NPN",
"",
"8" };
281 case TYPE::PNP_HICUM2:
return {
"Q",
"PNP",
"",
"8" };
283 case TYPE::NJFET_SHICHMANHODGES:
return {
"J",
"NJF",
"",
"1",
true };
284 case TYPE::PJFET_SHICHMANHODGES:
return {
"J",
"PJF",
"",
"1",
true };
285 case TYPE::NJFET_PARKERSKELLERN:
return {
"J",
"NJF",
"",
"2" };
286 case TYPE::PJFET_PARKERSKELLERN:
return {
"J",
"PJF",
"",
"2" };
288 case TYPE::NMES_STATZ:
return {
"Z",
"NMF",
"",
"1",
true };
289 case TYPE::PMES_STATZ:
return {
"Z",
"PMF",
"",
"1",
true };
290 case TYPE::NMES_YTTERDAL:
return {
"Z",
"NMF",
"",
"2" };
291 case TYPE::PMES_YTTERDAL:
return {
"Z",
"PMF",
"",
"2" };
292 case TYPE::NMES_HFET1:
return {
"Z",
"NMF",
"",
"5" };
293 case TYPE::PMES_HFET1:
return {
"Z",
"PMF",
"",
"5" };
294 case TYPE::NMES_HFET2:
return {
"Z",
"NMF",
"",
"6" };
295 case TYPE::PMES_HFET2:
return {
"Z",
"PMF",
"",
"6" };
297 case TYPE::NMOS_VDMOS:
return {
"M",
"VDMOS NCHAN" };
298 case TYPE::PMOS_VDMOS:
return {
"M",
"VDMOS PCHAN" };
299 case TYPE::NMOS_MOS1:
return {
"M",
"NMOS",
"",
"1",
true };
300 case TYPE::PMOS_MOS1:
return {
"M",
"PMOS",
"",
"1",
true };
301 case TYPE::NMOS_MOS2:
return {
"M",
"NMOS",
"",
"2" };
302 case TYPE::PMOS_MOS2:
return {
"M",
"PMOS",
"",
"2" };
303 case TYPE::NMOS_MOS3:
return {
"M",
"NMOS",
"",
"3" };
304 case TYPE::PMOS_MOS3:
return {
"M",
"PMOS",
"",
"3" };
305 case TYPE::NMOS_BSIM1:
return {
"M",
"NMOS",
"",
"4" };
306 case TYPE::PMOS_BSIM1:
return {
"M",
"PMOS",
"",
"4" };
307 case TYPE::NMOS_BSIM2:
return {
"M",
"NMOS",
"",
"5" };
308 case TYPE::PMOS_BSIM2:
return {
"M",
"PMOS",
"",
"5" };
309 case TYPE::NMOS_MOS6:
return {
"M",
"NMOS",
"",
"6" };
310 case TYPE::PMOS_MOS6:
return {
"M",
"PMOS",
"",
"6" };
311 case TYPE::NMOS_BSIM3:
return {
"M",
"NMOS",
"",
"8" };
312 case TYPE::PMOS_BSIM3:
return {
"M",
"PMOS",
"",
"8" };
313 case TYPE::NMOS_MOS9:
return {
"M",
"NMOS",
"",
"9" };
314 case TYPE::PMOS_MOS9:
return {
"M",
"PMOS",
"",
"9" };
315 case TYPE::NMOS_B4SOI:
return {
"M",
"NMOS",
"",
"10" };
316 case TYPE::PMOS_B4SOI:
return {
"M",
"PMOS",
"",
"10" };
317 case TYPE::NMOS_BSIM4:
return {
"M",
"NMOS",
"",
"14" };
318 case TYPE::PMOS_BSIM4:
return {
"M",
"PMOS",
"",
"14" };
323 case TYPE::NMOS_B3SOIFD:
return {
"M",
"NMOS",
"",
"55" };
324 case TYPE::PMOS_B3SOIFD:
return {
"M",
"PMOS",
"",
"55" };
325 case TYPE::NMOS_B3SOIDD:
return {
"M",
"NMOS",
"",
"56" };
326 case TYPE::PMOS_B3SOIDD:
return {
"M",
"PMOS",
"",
"56" };
327 case TYPE::NMOS_B3SOIPD:
return {
"M",
"NMOS",
"",
"57" };
328 case TYPE::PMOS_B3SOIPD:
return {
"M",
"PMOS",
"",
"57" };
331 case TYPE::NMOS_HISIM2:
return {
"M",
"NMOS",
"",
"68" };
332 case TYPE::PMOS_HISIM2:
return {
"M",
"PMOS",
"",
"68" };
333 case TYPE::NMOS_HISIMHV1:
return {
"M",
"NMOS",
"",
"73",
false,
false,
"1.2.4" };
334 case TYPE::PMOS_HISIMHV1:
return {
"M",
"PMOS",
"",
"73",
false,
false,
"1.2.4" };
335 case TYPE::NMOS_HISIMHV2:
return {
"M",
"NMOS",
"",
"73",
false,
false,
"2.2.0" };
336 case TYPE::PMOS_HISIMHV2:
return {
"M",
"PMOS",
"",
"73",
false,
false,
"2.2.0" };
338 case TYPE::V:
return {
"V",
"",
"DC" };
339 case TYPE::V_SIN:
return {
"V",
"",
"SIN" };
340 case TYPE::V_PULSE:
return {
"V",
"",
"PULSE" };
341 case TYPE::V_EXP:
return {
"V",
"",
"EXP" };
342 case TYPE::V_AM:
return {
"V",
"",
"AM" };
343 case TYPE::V_SFFM:
return {
"V",
"",
"SFFM" };
344 case TYPE::V_VCL:
return {
"E",
"",
"" };
345 case TYPE::V_CCL:
return {
"H",
"",
"" };
346 case TYPE::V_PWL:
return {
"V",
"",
"PWL" };
347 case TYPE::V_WHITENOISE:
return {
"V",
"",
"TRNOISE" };
348 case TYPE::V_PINKNOISE:
return {
"V",
"",
"TRNOISE" };
349 case TYPE::V_BURSTNOISE:
return {
"V",
"",
"TRNOISE" };
350 case TYPE::V_RANDUNIFORM:
return {
"V",
"",
"TRRANDOM" };
351 case TYPE::V_RANDGAUSSIAN:
return {
"V",
"",
"TRRANDOM" };
352 case TYPE::V_RANDEXP:
return {
"V",
"",
"TRRANDOM" };
353 case TYPE::V_RANDPOISSON:
return {
"V",
"",
"TRRANDOM" };
354 case TYPE::V_BEHAVIORAL:
return {
"B" };
356 case TYPE::I:
return {
"I",
"",
"DC" };
357 case TYPE::I_PULSE:
return {
"I",
"",
"PULSE" };
358 case TYPE::I_SIN:
return {
"I",
"",
"SIN" };
359 case TYPE::I_EXP:
return {
"I",
"",
"EXP" };
360 case TYPE::I_AM:
return {
"I",
"",
"AM" };
361 case TYPE::I_SFFM:
return {
"I",
"",
"SFFM" };
362 case TYPE::I_VCL:
return {
"G",
"",
"" };
363 case TYPE::I_CCL:
return {
"F",
"",
"" };
364 case TYPE::I_PWL:
return {
"I",
"",
"PWL" };
365 case TYPE::I_WHITENOISE:
return {
"I",
"",
"TRNOISE" };
366 case TYPE::I_PINKNOISE:
return {
"I",
"",
"TRNOISE" };
367 case TYPE::I_BURSTNOISE:
return {
"I",
"",
"TRNOISE" };
368 case TYPE::I_RANDUNIFORM:
return {
"I",
"",
"TRRANDOM" };
369 case TYPE::I_RANDGAUSSIAN:
return {
"I",
"",
"TRRANDOM" };
370 case TYPE::I_RANDEXP:
return {
"I",
"",
"TRRANDOM" };
371 case TYPE::I_RANDPOISSON:
return {
"I",
"",
"TRRANDOM" };
372 case TYPE::I_BEHAVIORAL:
return {
"B" };
374 case TYPE::SUBCKT:
return {
"X" };
375 case TYPE::XSPICE:
return {
"A" };
377 case TYPE::KIBIS_DEVICE:
return {
"X" };
378 case TYPE::KIBIS_DRIVER_DC:
return {
"X" };
379 case TYPE::KIBIS_DRIVER_RECT:
return {
"X" };
380 case TYPE::KIBIS_DRIVER_PRBS:
return {
"X" };
383 case TYPE::RAWSPICE:
return {};
385 default: wxFAIL;
return {};
396 if( !deviceTypeFieldValue.empty() )
398 for(
TYPE type : TYPE_ITERATOR() )
400 if( typeFieldValue ==
TypeInfo( type ).fieldValue )
408 if( typeFieldValue.empty() )
411 wxString reference =
GetFieldValue( &aFields, FIELD_T::REFERENCE );
413 if( !reference.IsEmpty() )
415 aReporter.
Report( wxString::Format(
_(
"No simulation model definition found for "
422 aReporter.
Report(
_(
"No simulation model definition found." ),
431 const std::vector<SCH_PIN*>& aPins )
451 for(
size_t ii = aFields.size() - 1; ii > 0; ii-- )
453 wxString currFieldName = aFields[ii].GetName();
455 auto end_candidate_list = aFields.begin() + ii - 1;
457 auto fieldIt = std::find_if( aFields.begin(), end_candidate_list,
460 return f.GetName() == currFieldName;
464 if( fieldIt != end_candidate_list )
465 aFields.erase( aFields.begin() + ii );
485 std::unique_ptr<SIM_MODEL> model =
Create( aType );
490 model->ReadDataFields(
static_cast<const std::vector<SCH_FIELD>*
>(
nullptr ),
495 wxFAIL_MSG(
"Shouldn't throw reading empty fields!" );
503 const std::vector<SCH_PIN*>& aPins,
506 std::unique_ptr<SIM_MODEL> model;
513 model = std::make_unique<SIM_MODEL_SPICE_FALLBACK>( type );
515 model = std::make_unique<SIM_MODEL_RAW_SPICE>();
519 model->SetBaseModel( *aBaseModel );
523 model = std::make_unique<SIM_MODEL_SPICE_FALLBACK>( TYPE::NONE );
528 model->ReadDataFields(
static_cast<const std::vector<SCH_FIELD>*
>(
nullptr ),
533 wxFAIL_MSG(
"Shouldn't throw reading empty fields!" );
541 const std::vector<SCH_PIN*>& aPins,
542 const std::vector<SCH_FIELD>& aFields,
543 bool aResolve,
int aDepth,
REPORTER& aReporter )
545 std::unique_ptr<SIM_MODEL> model;
556 type_override != TYPE::NONE )
558 type = type_override;
562 model = std::make_unique<SIM_MODEL_SPICE_FALLBACK>( type );
564 model = std::make_unique<SIM_MODEL_RAW_SPICE>();
568 model->SetBaseModel( *aBaseModel );
573 model = std::make_unique<SIM_MODEL_SPICE_FALLBACK>( type );
578 model->ReadDataFields( &aFields, aResolve, aDepth, aPins );
582 aReporter.
Report( wxString::Format(
_(
"Error reading simulation model from symbol '%s':\n%s" ),
593 bool aResolve,
int aDepth,
594 const std::vector<SCH_PIN*>& aPins,
REPORTER& aReporter )
601 model->ReadDataFields( &aFields, aResolve, aDepth, aPins );
616 if( modelData.empty() )
619 model = std::make_unique<SIM_MODEL_RAW_SPICE>( modelData );
623 model->createPins( aPins );
629 aReporter.
Report( wxString::Format(
_(
"Error reading simulation model from symbol '%s':\n%s" ),
657 for(
int modelPinIndex = 0; modelPinIndex <
GetPinCount(); ++modelPinIndex )
660 return modelPinIndex;
680 wxS(
"Simulation model type must be the same as its base class!" ) );
688 std::vector<std::reference_wrapper<const SIM_MODEL_PIN>> pins;
690 for(
int modelPinIndex = 0; modelPinIndex <
GetPinCount(); ++modelPinIndex )
691 pins.emplace_back(
GetPin( modelPinIndex ) );
697 const wxString& aSymbolPinNumber )
699 if( aModelPinIndex >= 0 && aModelPinIndex < (
int)
m_modelPins.size() )
700 m_modelPins.at( aModelPinIndex ).symbolPinNumber = aSymbolPinNumber;
705 const wxString& aSymbolPinNumber )
709 if(
pin.modelPinName == aModelPinName )
711 pin.symbolPinNumber = aSymbolPinNumber;
718 int pinIndex = (int) strtol( aModelPinName.c_str(),
nullptr, 10 );
720 if( pinIndex < 1 || pinIndex > (
int)
m_modelPins.size() )
721 THROW_IO_ERROR( wxString::Format(
_(
"Unknown simulation model pin '%s'" ), aModelPinName ) );
723 m_modelPins[ --pinIndex ].symbolPinNumber = aSymbolPinNumber;
738 return boost::iequals(
name, aParamName );
758 return idx >= 0 ? &
GetParam( idx ) :
nullptr;
779 m_params.at( aParamIndex ).value = aValue;
789 [](
const std::string& aString )
791 for(
char c : aString )
793 if( c !=
'.' && ( c <
'0' || c >
'9' ) )
801 if( aValue.find(
',' ) != std::string::npos )
804 SIM_VALUE::NOTATION::SI ) );
806 else if( aNotation != SIM_VALUE::NOTATION::SI && !plainNumber( aValue ) )
809 SIM_VALUE::NOTATION::SI ) );
824 THROW_IO_ERROR( wxString::Format(
"Unknown simulation model parameter '%s'", aParamName ) );
837 return std::make_unique<SIM_MODEL_IDEAL>( aType );
840 return std::make_unique<SIM_MODEL_R_POT>();
843 return std::make_unique<SIM_MODEL_L_MUTUAL>();
845 case TYPE::R_BEHAVIORAL:
846 case TYPE::C_BEHAVIORAL:
847 case TYPE::L_BEHAVIORAL:
848 case TYPE::V_BEHAVIORAL:
849 case TYPE::I_BEHAVIORAL:
850 return std::make_unique<SIM_MODEL_BEHAVIORAL>( aType );
853 case TYPE::TLINE_RLGC:
854 return std::make_unique<SIM_MODEL_TLINE>( aType );
858 return std::make_unique<SIM_MODEL_SWITCH>( aType );
878 case TYPE::V_WHITENOISE:
879 case TYPE::I_WHITENOISE:
880 case TYPE::V_PINKNOISE:
881 case TYPE::I_PINKNOISE:
882 case TYPE::V_BURSTNOISE:
883 case TYPE::I_BURSTNOISE:
884 case TYPE::V_RANDUNIFORM:
885 case TYPE::I_RANDUNIFORM:
886 case TYPE::V_RANDGAUSSIAN:
887 case TYPE::I_RANDGAUSSIAN:
888 case TYPE::V_RANDEXP:
889 case TYPE::I_RANDEXP:
890 case TYPE::V_RANDPOISSON:
891 case TYPE::I_RANDPOISSON:
892 return std::make_unique<SIM_MODEL_SOURCE>( aType );
895 return std::make_unique<SIM_MODEL_SUBCKT>();
898 return std::make_unique<SIM_MODEL_XSPICE>( aType );
900 case TYPE::KIBIS_DEVICE:
901 case TYPE::KIBIS_DRIVER_DC:
902 case TYPE::KIBIS_DRIVER_RECT:
903 case TYPE::KIBIS_DRIVER_PRBS:
904 return std::make_unique<SIM_MODEL_IBIS>( aType );
907 return std::make_unique<SIM_MODEL_RAW_SPICE>();
910 return std::make_unique<SIM_MODEL_NGSPICE>( aType );
930 std::unique_ptr<SIM_MODEL_SERIALIZER> aSerializer ) :
931 m_baseModel( nullptr ),
932 m_serializer(
std::
move( aSerializer ) ),
933 m_spiceGenerator(
std::
move( aSpiceGenerator ) ),
936 m_isStoredInValue( false )
952 for(
unsigned modelPinIndex = 0; modelPinIndex < pinNames.size(); ++modelPinIndex )
954 wxString pinName = pinNames[ modelPinIndex ];
955 bool optional =
false;
957 if( pinName.StartsWith(
'<' ) && pinName.EndsWith(
'>' ) )
959 pinName = pinName.Mid( 1, pinName.Length() - 2 );
963 if( modelPinIndex < aSymbolPins.size() )
965 AddPin( { pinNames.at( modelPinIndex ),
966 aSymbolPins[ modelPinIndex ]->GetNumber().ToStdString() } );
970 AddPin( { pinNames.at( modelPinIndex ),
"" } );
979 if(
m_type == TYPE::SUBCKT )
995 if ( param.
value ==
"" )
1000 const std::string& baseValue = baseModel->m_params[ii].value;
1002 if( param.
value == baseValue )
1022 wxString* aModelType, wxString* aModelParams, wxString* aPinMap )
1051 auto convertNotation =
1052 [&](
const wxString& units ) -> wxString
1056 if( units == wxS(
"µ" ) || units == wxS(
"μ" ) )
1061 if( units == wxT(
"M" ) )
1062 return wxT(
"Meg" );
1066 if( units.Capitalize() == wxT(
"Meg" ) )
1074 []( wxString* mantissa )
1076 mantissa->Replace( wxS(
" " ), wxEmptyString );
1078 wxChar ambiguousSeparator =
'?';
1079 wxChar thousandsSeparator =
'?';
1080 bool thousandsSeparatorFound =
false;
1081 wxChar decimalSeparator =
'?';
1082 bool decimalSeparatorFound =
false;
1085 for(
int ii = (
int) mantissa->length() - 1; ii >= 0; --ii )
1087 wxChar c = mantissa->GetChar( ii );
1089 if( c >=
'0' && c <=
'9' )
1093 else if( c ==
'.' || c ==
',' )
1095 if( decimalSeparator !=
'?' || thousandsSeparator !=
'?' )
1099 if( c == decimalSeparator )
1101 if( thousandsSeparatorFound )
1103 else if( decimalSeparatorFound )
1106 decimalSeparatorFound =
true;
1108 else if( c == thousandsSeparator )
1113 thousandsSeparatorFound =
true;
1116 else if( ambiguousSeparator !=
'?' )
1121 if( c == ambiguousSeparator )
1124 thousandsSeparator = ambiguousSeparator;
1125 thousandsSeparatorFound =
true;
1126 decimalSeparator = c ==
'.' ?
',' :
'.';
1132 decimalSeparator = ambiguousSeparator;
1133 decimalSeparatorFound =
true;
1134 thousandsSeparator = c;
1135 thousandsSeparatorFound =
true;
1148 if( ( ii == 1 && mantissa->GetChar( 0 ) ==
'0' ) || digits != 3 )
1150 decimalSeparator = c;
1151 decimalSeparatorFound =
true;
1152 thousandsSeparator = c ==
'.' ?
',' :
'.';
1156 ambiguousSeparator = c;
1169 if( decimalSeparator ==
'?' && thousandsSeparator ==
'?' )
1171 decimalSeparator =
'.';
1172 thousandsSeparator =
',';
1175 mantissa->Replace( thousandsSeparator, wxEmptyString );
1176 mantissa->Replace( decimalSeparator,
'.' );
1181 wxString prefix = aSymbol.GetPrefix();
1185 std::vector<SCH_PIN*> pins = aSymbol.GetPins();
1190 std::sort( pins.begin(), pins.end(),
1193 return a->GetNumber() < b->GetNumber();
1201 if( pins.size() != 2 )
1204 if( ( ( *aDeviceType ==
"R" || *aDeviceType ==
"L" || *aDeviceType ==
"C" )
1205 && aModelType->IsEmpty() )
1207 (
library.IsEmpty() && modelName.IsEmpty()
1208 && aDeviceType->IsEmpty()
1209 && aModelType->IsEmpty()
1211 && ( prefix.StartsWith(
"R" ) || prefix.StartsWith(
"L" ) || prefix.StartsWith(
"C" ) ) ) )
1213 if( aModelParams->IsEmpty() )
1215 wxRegEx idealVal( wxT(
"^"
1217 "([fFpPnNuUmMkKgGtTμµ𝛍𝜇𝝁 ]|M(e|E)(g|G))?"
1218 "([fFhHΩΩ𝛀𝛺𝝮rR]|ohm)?"
1220 "([fFhHΩΩ𝛀𝛺𝝮rR]|ohm)?"
1223 if( idealVal.Matches( value ) )
1225 wxString valueMantissa( idealVal.GetMatch( value, 1 ) );
1226 wxString valueExponent( idealVal.GetMatch( value, 2 ) );
1227 wxString valueFraction( idealVal.GetMatch( value, 6 ) );
1232 if( valueMantissa.Contains( wxT(
"." ) ) || valueFraction.IsEmpty() )
1234 aModelParams->Printf( wxT(
"%s=\"%s%s\"" ),
1235 prefix.Left(1).Lower(),
1236 std::move( valueMantissa ),
1237 convertNotation( valueExponent ) );
1241 aModelParams->Printf( wxT(
"%s=\"%s.%s%s\"" ),
1242 prefix.Left(1).Lower(),
1243 std::move( valueMantissa ),
1244 std::move( valueFraction ),
1245 convertNotation( valueExponent ) );
1250 *aModelType = wxT(
"=" );
1251 aModelParams->Printf( wxT(
"%s=\"%s\"" ), prefix.Left(1).Lower(), std::move( value ) );
1255 if( aDeviceType->IsEmpty() )
1256 *aDeviceType = prefix.Left( 1 );
1258 if( aPinMap->IsEmpty() )
1259 aPinMap->Printf( wxT(
"%s=+ %s=-" ), pins[0]->GetNumber(), pins[1]->GetNumber() );
1264 if( ( ( *aDeviceType == wxT(
"V" ) || *aDeviceType == wxT(
"I" ) )
1265 && ( aModelType->IsEmpty() || *aModelType == wxT(
"DC" ) ) )
1267 ( aDeviceType->IsEmpty()
1268 && aModelType->IsEmpty()
1270 && ( prefix.StartsWith(
"V" ) || prefix.StartsWith(
"I" ) ) ) )
1272 if( !value.IsEmpty() )
1274 wxString param =
"dc";
1276 if( value.StartsWith( wxT(
"DC " ) ) )
1278 value = value.Right( value.Length() - 3 );
1280 else if( value.StartsWith( wxT(
"AC " ) ) )
1282 value = value.Right( value.Length() - 3 );
1286 wxRegEx sourceVal( wxT(
"^"
1288 "([fFpPnNuUmMkKgGtTμµ𝛍𝜇𝝁 ]|M(e|E)(g|G))?"
1294 if( sourceVal.Matches( value ) )
1296 wxString valueMantissa( sourceVal.GetMatch( value, 1 ) );
1297 wxString valueExponent( sourceVal.GetMatch( value, 2 ) );
1298 wxString valueFraction( sourceVal.GetMatch( value, 6 ) );
1303 if( valueMantissa.Contains( wxT(
"." ) ) || valueFraction.IsEmpty() )
1305 aModelParams->Printf( wxT(
"%s=\"%s%s\" %s" ),
1307 std::move( valueMantissa ),
1308 convertNotation( valueExponent ),
1313 aModelParams->Printf( wxT(
"%s=\"%s.%s%s\" %s" ),
1315 std::move( valueMantissa ),
1316 std::move( valueFraction ),
1317 convertNotation( valueExponent ),
1323 aModelParams->Printf( wxT(
"%s=\"%s\" %s" ),
1330 if( aDeviceType->IsEmpty() )
1331 *aDeviceType = prefix.Left( 1 );
1333 if( aModelType->IsEmpty() )
1334 *aModelType = wxT(
"DC" );
1336 if( aPinMap->IsEmpty() )
1337 aPinMap->Printf( wxT(
"%s=+ %s=-" ), pins[0]->GetNumber(), pins[1]->GetNumber() );
1346template bool SIM_MODEL::InferSimModel<SCH_SYMBOL>(
SCH_SYMBOL& aSymbol, std::vector<SCH_FIELD>* aFields,
1347 bool aResolve,
int aDepth,
1349 wxString* aDeviceType, wxString* aModelType,
1350 wxString* aModelParams, wxString* aPinMap );
1351template bool SIM_MODEL::InferSimModel<LIB_SYMBOL>(
LIB_SYMBOL& aSymbol, std::vector<SCH_FIELD>* aFields,
1352 bool aResolve,
int aDepth,
1354 wxString* aDeviceType, wxString* aModelType,
1355 wxString* aModelParams, wxString* aPinMap );
1358template <
typename T>
1371 FIELD_INFO(
const wxString& aText,
SCH_FIELD* aField ) :
1378 bool IsEmpty()
const {
return m_Text.IsEmpty(); }
1380 SCH_FIELD CreateField(
T* aSymbol,
const wxString& aFieldName )
1382 SCH_FIELD field( aSymbol, FIELD_T::USER, aFieldName );
1404 wxString existing_deviceSubtype;
1406 if( existing_deviceSubtypeField )
1407 existing_deviceSubtype = existing_deviceSubtypeField->
GetShownText(
false ).Upper();
1409 if( existing_deviceField
1410 || existing_deviceSubtypeField
1411 || existing_pinsField
1412 || existing_paramsField )
1418 if( existing_deviceSubtype == wxS(
"POT" ) )
1420 if( existing_pinsField )
1422 wxString pinMap = existing_pinsField->
GetText();
1423 pinMap.Replace( wxS(
"=+" ), wxS(
"=r1" ) );
1424 pinMap.Replace( wxS(
"=-" ), wxS(
"=r0" ) );
1425 existing_pinsField->
SetText( pinMap );
1430 if( existing_deviceSubtype.StartsWith( wxS(
"RAND" ) ) )
1434 existing_deviceSubtype = existing_deviceSubtypeField->
GetText().Upper();
1436 if( existing_deviceSubtype.Replace( wxS(
"NORMAL" ), wxS(
"GAUSSIAN" ) ) )
1437 existing_deviceSubtypeField->
SetText( existing_deviceSubtype );
1439 if( existing_paramsField )
1441 wxString params = existing_paramsField->
GetText().Lower();
1448 count += params.Replace( wxS(
"min=0 " ), wxEmptyString );
1449 count += params.Replace( wxS(
"max=0 " ), wxEmptyString );
1452 count += params.Replace( wxS(
"dt=" ), wxS(
"ts=" ) );
1455 existing_paramsField->
SetText( params );
1461 if( existing_deviceSubtype == wxS(
"MUTUAL" ) )
1463 if( existing_deviceSubtypeField )
1464 aSymbol.RemoveField( existing_deviceSubtypeField );
1466 if( existing_deviceField )
1468 existing_deviceField->
SetText( wxS(
"K" ) );
1472 FIELD_INFO deviceFieldInfo;
1473 deviceFieldInfo.m_Text = wxS(
"K" );
1476 aSymbol.AddField( deviceField );
1487 return wxString( wxEmptyString );
1489 wxRegEx regex( wxT(
"([^a-z])(M)(e|E)(g|G)($|[^a-z])" ) );
1490 wxString value = aField->GetText();
1493 regex.ReplaceAll( &value, wxT(
"\\1\\2\\5" ) );
1498 auto generateDefaultPinMapFromSymbol =
1499 [](
const std::vector<SCH_PIN*>& sourcePins )
1506 for(
unsigned ii = 0; ii < sourcePins.size(); ++ii )
1509 pinMap.Append( wxS(
" " ) );
1511 pinMap.Append( wxString::Format( wxT(
"%s=%u" ),
1512 sourcePins[ii]->GetNumber(),
1519 wxString prefix = aSymbol.GetPrefix();
1520 SCH_FIELD* valueField = aSymbol.GetField( FIELD_T::VALUE );
1521 std::vector<SCH_PIN*> sourcePins = aSymbol.GetPins();
1522 bool sourcePinsSorted =
false;
1524 auto lazySortSourcePins =
1525 [&sourcePins, &sourcePinsSorted]()
1527 if( !sourcePinsSorted )
1529 std::sort( sourcePins.begin(), sourcePins.end(),
1532 return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0;
1536 sourcePinsSorted =
true;
1539 FIELD_INFO deviceInfo;
1540 FIELD_INFO modelInfo;
1541 FIELD_INFO deviceSubtypeInfo;
1543 FIELD_INFO spiceParamsInfo;
1544 FIELD_INFO pinMapInfo;
1545 bool modelFromValueField =
false;
1555 deviceInfo = FIELD_INFO( primitiveField->GetText(), primitiveField );
1556 aSymbol.RemoveField( primitiveField );
1561 const wxString delimiters(
"{:,; }" );
1562 const wxString& nodeSequence = nodeSequenceField->GetText();
1565 if( nodeSequence !=
"" )
1567 wxStringTokenizer tkz( nodeSequence, delimiters );
1569 for(
long modelPinNumber = 1; tkz.HasMoreTokens(); ++modelPinNumber )
1571 long symbolPinNumber = 1;
1572 tkz.GetNextToken().ToLong( &symbolPinNumber );
1574 if( modelPinNumber != 1 )
1575 pinMap.Append(
" " );
1577 pinMap.Append( wxString::Format(
"%ld=%ld", symbolPinNumber, modelPinNumber ) );
1581 pinMapInfo = FIELD_INFO( pinMap, nodeSequenceField );
1582 aSymbol.RemoveField( nodeSequenceField );
1587 modelInfo = FIELD_INFO( getSIValue( modelField ), modelField );
1588 aSymbol.RemoveField( modelField );
1590 else if( valueField )
1592 modelInfo = FIELD_INFO( getSIValue( valueField ), valueField );
1593 modelFromValueField =
true;
1598 libInfo = FIELD_INFO( libFileField->GetText(), libFileField );
1599 aSymbol.RemoveField( libFileField );
1606 if(
SCH_FIELD* legacyType = aSymbol.GetField( wxT(
"Sim_Type" ) ) )
1611 if(
SCH_FIELD* legacyDevice = aSymbol.GetField( wxT(
"Sim_Device" ) ) )
1616 if(
SCH_FIELD* legacyPins = aSymbol.GetField( wxT(
"Sim_Pins" ) ) )
1618 bool isPassive = prefix.StartsWith( wxT(
"R" ) )
1619 || prefix.StartsWith( wxT(
"L" ) )
1620 || prefix.StartsWith( wxT(
"C" ) );
1624 wxArrayString pinIndexes;
1628 lazySortSourcePins();
1630 if( isPassive && pinIndexes.size() == 2 && sourcePins.size() == 2 )
1632 if( pinIndexes[0] == wxT(
"2" ) )
1634 pinMap.Printf( wxT(
"%s=- %s=+" ),
1635 sourcePins[0]->GetNumber(),
1636 sourcePins[1]->GetNumber() );
1640 pinMap.Printf( wxT(
"%s=+ %s=-" ),
1641 sourcePins[0]->GetNumber(),
1642 sourcePins[1]->GetNumber() );
1647 for(
unsigned ii = 0; ii < pinIndexes.size() && ii < sourcePins.size(); ++ii )
1650 pinMap.Append( wxS(
" " ) );
1652 pinMap.Append( wxString::Format( wxT(
"%s=%s" ),
1653 sourcePins[ii]->GetNumber(),
1654 pinIndexes[ ii ] ) );
1659 legacyPins->SetText( pinMap );
1662 if(
SCH_FIELD* legacyParams = aSymbol.GetField( wxT(
"Sim_Params" ) ) )
1670 wxString device = deviceInfo.m_Text.Trim(
true ).Trim(
false );
1671 wxString lib = libInfo.m_Text.Trim(
true ).Trim(
false );
1672 wxString model = modelInfo.m_Text.Trim(
true ).Trim(
false );
1673 wxString modelLineParams;
1675 bool libraryModel =
false;
1676 bool inferredModel =
false;
1677 bool internalModel =
false;
1679 if( !lib.IsEmpty() )
1683 std::vector<SCH_FIELD> emptyFields;
1684 std::vector<EMBEDDED_FILES*> embeddedFilesStack;
1686 if constexpr (std::is_same_v<T, SCH_SYMBOL>)
1692 embeddedFilesStack.push_back( aSymbol.GetEmbeddedFiles() );
1697 model = model.BeforeFirst(
' ', &modelLineParams );
1698 modelInfo.m_Text = model;
1700 lazySortSourcePins();
1703 emptyFields,
false, 0,
1704 sourcePins, reporter );
1707 libraryModel =
false;
1709 libraryModel =
true;
1711 if( pinMapInfo.IsEmpty() )
1717 if( pinMapInfo.IsEmpty() )
1718 pinMapInfo.m_Text = generateDefaultPinMapFromSymbol( sourcePins );
1721 else if( ( device == wxS(
"R" )
1722 || device == wxS(
"L" )
1723 || device == wxS(
"C" )
1724 || device == wxS(
"V" )
1725 || device == wxS(
"I" ) )
1726 && prefix.StartsWith( device )
1727 && modelFromValueField )
1729 inferredModel =
true;
1731 else if( device == wxS(
"V" ) || device == wxS(
"I" ) )
1736 wxStringTokenizer tokenizer( model, wxT(
"() " ), wxTOKEN_STRTOK );
1738 if( tokenizer.HasMoreTokens() )
1740 deviceSubtypeInfo.m_Text = tokenizer.GetNextToken();
1741 deviceSubtypeInfo.m_Text.MakeUpper();
1743 for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
1752 if( deviceSubtypeInfo.m_Text == wxT(
"DC" ) && tokenizer.CountTokens() == 1 )
1754 wxCHECK( valueField, );
1755 valueField->
SetText( tokenizer.GetNextToken() );
1756 modelFromValueField =
false;
1760 for(
int ii = 0; tokenizer.HasMoreTokens(); ++ii )
1762 simModel->SetParamValue( ii, tokenizer.GetNextToken().ToStdString(),
1768 spiceParamsInfo = modelInfo;
1769 spiceParamsInfo.m_Text = wxString( simModel->Serializer().GenerateParams() );
1772 internalModel =
true;
1774 if( pinMapInfo.IsEmpty() )
1776 lazySortSourcePins();
1779 simModel->createPins( sourcePins );
1780 pinMapInfo.m_Text = wxString( simModel->Serializer().GeneratePins() );
1797 aSymbol.AddField( libField );
1800 aSymbol.AddField( nameField );
1802 if( !modelLineParams.IsEmpty() )
1804 spiceParamsInfo = modelInfo;
1806 spiceParamsInfo.m_Text = modelLineParams;
1809 int nameWidth = nameBBox.
GetWidth();
1815 spiceParamsInfo.m_Pos.x -= nameWidth;
1817 spiceParamsInfo.m_Pos.x += nameWidth;
1820 aSymbol.AddField( paramsField );
1823 if( modelFromValueField )
1824 valueField->
SetText( wxT(
"${SIM.NAME}" ) );
1826 else if( inferredModel )
1831 else if( internalModel )
1834 aSymbol.AddField( deviceField );
1836 if( !deviceSubtypeInfo.m_Text.IsEmpty() )
1839 aSymbol.AddField( subtypeField );
1842 if( !spiceParamsInfo.IsEmpty() )
1845 aSymbol.AddField( paramsField );
1848 if( modelFromValueField )
1849 valueField->
SetText( wxT(
"${SIM.PARAMS}" ) );
1853 if( device.IsEmpty() && lib.IsEmpty() )
1855 spiceParamsInfo = modelInfo;
1859 spiceParamsInfo.m_Text.Printf( wxT(
"type=\"%s\" model=\"%s\" lib=\"%s\"" ), device,
1866 aSymbol.AddField( deviceField );
1869 aSymbol.AddField( paramsField );
1871 if( modelFromValueField )
1874 valueField = aSymbol.GetField( FIELD_T::VALUE );
1877 valueField->
SetText( wxT(
"${SIM.PARAMS}" ) );
1883 if( pinMapInfo.IsEmpty() )
1885 lazySortSourcePins();
1886 pinMapInfo.m_Text = generateDefaultPinMapFromSymbol( sourcePins );
1890 if( !pinMapInfo.IsEmpty() )
1893 aSymbol.AddField( pinsField );
1898template void SIM_MODEL::MigrateSimModel<SCH_SYMBOL>(
SCH_SYMBOL& aSymbol,
1900template void SIM_MODEL::MigrateSimModel<LIB_SYMBOL>(
LIB_SYMBOL& aSymbol,
constexpr EDA_IU_SCALE schIUScale
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
constexpr size_type GetWidth() const
constexpr size_type GetHeight() const
virtual const wxString & GetText() const
Return the string associated with the text object.
virtual bool IsVisible() const
void SetAttributes(const EDA_TEXT &aSrc, bool aSetPosition=true)
Set the text attributes from another instance.
GR_TEXT_H_ALIGN_T GetHorizJustify() const
virtual void SetVisible(bool aVisible)
const TEXT_ATTRIBUTES & GetAttributes() const
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
virtual const wxString Problem() const
what was the problem?
Define a library symbol object.
A singleton reporter that reports to nowhere.
Container for project specific data.
A pure virtual class used to derive REPORTER objects from.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
EMBEDDED_FILES * GetEmbeddedFiles() override
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
VECTOR2I GetPosition() const override
void SetPosition(const VECTOR2I &aPosition) override
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
void SetText(const wxString &aText) override
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
static constexpr auto DIFF_FIELD
SIM_MODEL & CreateModel(SIM_MODEL::TYPE aType, const std::vector< SCH_PIN * > &aPins, REPORTER &aReporter)
void SetFilesStack(std::vector< EMBEDDED_FILES * > aFilesStack)
Serializes/deserializes a SIM_MODEL for storage in LIB_FIELDs/SCH_FIELDs.
std::string GeneratePins() const
int FindModelPinIndex(const std::string &aSymbolPinNumber)
static void MigrateSimModel(T &aSymbol, const PROJECT *aProject)
const PARAM & GetBaseParam(unsigned aParamIndex) const
void AddParam(const PARAM::INFO &aInfo)
bool IsStoredInValue() const
virtual std::vector< std::string > GetPinNames() const
virtual bool requiresSpiceModelLine(const SPICE_ITEM &aItem) const
std::vector< SIM_MODEL_PIN > m_modelPins
static INFO TypeInfo(TYPE aType)
void AddPin(const SIM_MODEL_PIN &aPin)
static SPICE_INFO SpiceInfo(TYPE aType)
const SIM_MODEL_SERIALIZER & Serializer() const
void ReadDataFields(const std::vector< SCH_FIELD > *aFields, bool aResolve, int aDepth, const std::vector< SCH_PIN * > &aPins)
static bool InferSimModel(T &aSymbol, std::vector< SCH_FIELD > *aFields, bool aResolve, int aDepth, SIM_VALUE_GRAMMAR::NOTATION aNotation, wxString *aDeviceType, wxString *aModelType, wxString *aModelParams, wxString *aPinMap)
virtual const PARAM & GetParam(unsigned aParamIndex) const
void createPins(const std::vector< SCH_PIN * > &aSymbolPins)
void WriteFields(std::vector< SCH_FIELD > &aFields) const
virtual void SetBaseModel(const SIM_MODEL &aBaseModel)
static TYPE ReadTypeFromFields(const std::vector< SCH_FIELD > &aFields, bool aResolve, int aDepth, REPORTER &aReporter)
int GetParamCount() const
void AssignSymbolPinNumberToModelPin(int aPinIndex, const wxString &aSymbolPinNumber)
static DEVICE_INFO DeviceInfo(DEVICE_T aDeviceType)
const PARAM * FindParam(const std::string &aParamName) const
virtual void doSetParamValue(int aParamIndex, const std::string &aValue)
std::vector< PARAM > m_params
const PARAM & GetParamOverride(unsigned aParamIndex) const
static std::unique_ptr< SIM_MODEL > Create(TYPE aType, const std::vector< SCH_PIN * > &aPins, REPORTER &aReporter)
void SetParamValue(int aParamIndex, const std::string &aValue, SIM_VALUE::NOTATION aNotation=SIM_VALUE::NOTATION::SI)
virtual void SwitchSingleEndedDiff(bool aDiff)
const SIM_MODEL_PIN & GetPin(unsigned aIndex) const
std::unique_ptr< SIM_MODEL_SERIALIZER > m_serializer
virtual int doFindParam(const std::string &aParamName) const
std::vector< std::reference_wrapper< const SIM_MODEL_PIN > > GetPins() const
const SIM_MODEL * m_baseModel
static std::string Normalize(double aValue)
static std::string ConvertNotation(const std::string &aString, NOTATION aFromNotation, NOTATION aToNotation)
static double ToDouble(const std::string &aString, double aDefault=NAN)
A wrapper for reporting to a wxString object.
bool HasMessage() const override
Returns true if the reporter client is non-empty.
#define DEFAULT_SIZE_TEXT
This is the "default-of-the-default" hardcoded text size; individual application define their own def...
#define THROW_IO_ERROR(msg)
wxString GetFieldValue(const std::vector< SCH_FIELD > *aFields, FIELD_T aFieldType)
void SetFieldValue(std::vector< SCH_FIELD > &aFields, const wxString &aFieldName, const std::string &aValue, bool aIsVisible=true)
#define SIM_LIBRARY_FIELD
#define SIM_LEGACY_ENABLE_FIELD
#define SIM_LEGACY_ENABLE_FIELD_V7
#define SIM_LEGACY_MODEL_FIELD
#define SIM_LEGACY_PINS_FIELD
#define SIM_LEGACY_LIBRARY_FIELD
#define SIM_LEGACY_PRIMITIVE_FIELD
#define SIM_DEVICE_SUBTYPE_FIELD
bool convertSeparators(wxString *value)
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Split aString to a string list separated at aSplitter.
std::vector< std::string > enumValues
bool Matches(const std::string &aName) const
bool isSpiceInstanceParam
bool Matches(const std::string &aName) const
static constexpr auto NOT_CONNECTED
std::string baseModelName
VECTOR2< int32_t > VECTOR2I