KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_kibis.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.TXT for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
21
22#include <sim/kibis/kibis.h>
25#include <sim/sim_model_ibis.h>
26#include <sim/spice_generator.h>
27#include <sim/spice_simulator.h>
28#include <sch_pin.h>
29#include <wx/utils.h>
30
31namespace
32{
33std::string GetLibraryPath( const std::string& aBaseName )
34{
35 wxFileName fn( KI_TEST::GetEeschemaTestDataDir() );
36 fn.SetName( aBaseName );
37 fn.SetExt( "ibs" );
38 return std::string( fn.GetFullPath().ToUTF8() );
39}
40} // namespace
41
42
44
45
47{
48 KIBIS kibis;
49
50 BOOST_TEST( !kibis.m_valid );
51
52 // IBIS_BASE interface
53 // If this isn't null, it's uninited and access will crash
54 BOOST_REQUIRE( !kibis.m_Reporter );
55
56 // Doesn't crash (also doesn't do anything)
57 kibis.Report( "Dummy", RPT_SEVERITY_INFO );
58}
59
60
62{
64
65 std::string path = GetLibraryPath( "ibis_v1_1" );
67
68 BOOST_TEST_INFO( "Parsed: " << path );
69 BOOST_TEST_INFO( "Reported: " << reporter.GetMessages() );
70
71 BOOST_TEST( top.m_valid );
72
73 KIBIS_MODEL* model = top.GetModel( "Input" );
74
75 BOOST_REQUIRE( model != nullptr );
76 BOOST_TEST_INFO( "Model: " << model->m_name );
77
78 BOOST_TEST( model->m_name == "Input" );
79 BOOST_TEST( (int) model->m_type == (int) IBIS_MODEL_TYPE::INPUT_STD );
80 BOOST_TEST( (int) model->m_polarity == (int) IBIS_MODEL_POLARITY::NON_INVERTING );
81 BOOST_TEST( (int) model->m_enable = (int) IBIS_MODEL_ENABLE::ACTIVE_HIGH );
82
83 BOOST_TEST( model->HasGNDClamp() );
84
85 KIBIS_COMPONENT* comp = top.GetComponent( "Virtual" );
86
87 BOOST_REQUIRE( comp != nullptr );
88
89 BOOST_TEST_INFO( "Component: " << comp->m_name );
90
91 BOOST_TEST( comp->m_name == "Virtual" );
92 BOOST_TEST( comp->m_pins.size() == 4 );
93}
94
95BOOST_AUTO_TEST_CASE( Load_v5_1, * boost::unit_test::tolerance( 1e-15 ) )
96{
98
99 std::string path = GetLibraryPath( "ibis_v5_1" );
101
102 BOOST_TEST_INFO( "Parsed: " << path );
103 BOOST_TEST_INFO( "Reported: " << reporter.GetMessages() );
104
105 BOOST_TEST( top.m_valid );
106
107 KIBIS_COMPONENT* comp = top.GetComponent( "Virtual" );
108
109 BOOST_REQUIRE( comp != nullptr );
110 BOOST_TEST_INFO( "Component: " << comp->m_name );
111
112 BOOST_TEST( comp->m_name == "Virtual" );
113 BOOST_TEST( comp->m_manufacturer == "KiCad" );
114 BOOST_TEST( comp->m_pins.size() == 4 );
115
117
118 pin = comp->GetPin( "A1" );
119
120 BOOST_REQUIRE( pin != nullptr );
121
122 BOOST_TEST( pin->m_signalName == "VSS" );
123 BOOST_TEST( pin->m_pinNumber == "A1" );
124 BOOST_TEST( pin->m_Rpin.value[0] == 0.246 );
125 BOOST_TEST( pin->m_Rpin.value[1] == 0.165 );
126 BOOST_TEST( pin->m_Rpin.value[2] == 0.377 );
127 BOOST_TEST( pin->m_Lpin.value[0] == 1.49e-9 );
128 BOOST_TEST( pin->m_Lpin.value[1] == 0.98e-9 );
129 BOOST_TEST( pin->m_Lpin.value[2] == 2.23e-9 );
130 BOOST_TEST( pin->m_Cpin.value[0] == 0.40e-12 );
131 BOOST_TEST( pin->m_Cpin.value[1] == 0.29e-12 );
132 BOOST_TEST( pin->m_Cpin.value[2] == 0.56e-12 );
133 BOOST_TEST( pin->m_models.size() == 0 );
134
135 pin = comp->GetPin( "A2" );
136
137 BOOST_REQUIRE( pin != nullptr );
138
139 BOOST_TEST( pin->m_signalName == "VDD" );
140 BOOST_TEST( pin->m_pinNumber == "A2" );
141 BOOST_TEST( pin->m_Rpin.value[0] == 0.246 );
142 BOOST_TEST( pin->m_Rpin.value[1] == 0.165 );
143 BOOST_TEST( pin->m_Rpin.value[2] == 0.377 );
144 BOOST_TEST( pin->m_Lpin.value[0] == 1.49e-9 );
145 BOOST_TEST( pin->m_Lpin.value[1] == 0.98e-9 );
146 BOOST_TEST( pin->m_Lpin.value[2] == 2.23e-9 );
147 BOOST_TEST( pin->m_Cpin.value[0] == 0.40e-12 );
148 BOOST_TEST( pin->m_Cpin.value[1] == 0.29e-12 );
149 BOOST_TEST( pin->m_Cpin.value[2] == 0.56e-12 );
150 BOOST_TEST( pin->m_models.size() == 0 );
151
152 pin = comp->GetPin( "B1" );
153
154 BOOST_REQUIRE( pin != nullptr );
155
156 BOOST_TEST( pin->m_signalName == "A0" );
157 BOOST_TEST( pin->m_pinNumber == "B1" );
158 BOOST_TEST( pin->m_Rpin.value[0] == 0.225 );
159 BOOST_TEST( pin->m_Rpin.value[1] == 0.225 );
160 BOOST_TEST( pin->m_Rpin.value[2] == 0.225 );
161 BOOST_TEST( pin->m_Lpin.value[0] == 1.18e-9 );
162 BOOST_TEST( pin->m_Lpin.value[1] == 1.18e-9 );
163 BOOST_TEST( pin->m_Lpin.value[2] == 1.18e-9 );
164 BOOST_TEST( pin->m_Cpin.value[0] == 0.39e-12 );
165 BOOST_TEST( pin->m_Cpin.value[1] == 0.39e-12 );
166 BOOST_TEST( pin->m_Cpin.value[2] == 0.39e-12 );
167 BOOST_TEST( pin->m_models.size() == 1 );
168 BOOST_TEST( pin->m_models[0]->m_name == "AC40" );
169
170 pin = comp->GetPin( "B2" );
171
172 BOOST_REQUIRE( pin != nullptr );
173
174 BOOST_TEST( pin->m_signalName == "DQ0" );
175 BOOST_TEST( pin->m_pinNumber == "B2" );
176 BOOST_TEST( pin->m_Rpin.value[0] == 0.214 );
177 BOOST_TEST( pin->m_Rpin.value[1] == 0.214 );
178 BOOST_TEST( pin->m_Rpin.value[2] == 0.214 );
179 BOOST_TEST( pin->m_Lpin.value[0] == 1.05e-9 );
180 BOOST_TEST( pin->m_Lpin.value[1] == 1.05e-9 );
181 BOOST_TEST( pin->m_Lpin.value[2] == 1.05e-9 );
182 BOOST_TEST( pin->m_Cpin.value[0] == 0.39e-12 );
183 BOOST_TEST( pin->m_Cpin.value[1] == 0.39e-12 );
184 BOOST_TEST( pin->m_Cpin.value[2] == 0.39e-12 );
185 BOOST_TEST( pin->m_models.size() == 2 );
186 BOOST_TEST( pin->m_models[0]->m_name == "DQ40" );
187 BOOST_TEST( pin->m_models[1]->m_name == "DQ40_ODT40" );
188
190
191 model = top.GetModel( "AC40" );
192
193 BOOST_REQUIRE( model != nullptr );
194 BOOST_TEST_INFO( "Model: " << model->m_name );
195
196 BOOST_TEST( model->m_name == "AC40" );
197 BOOST_TEST( (int) model->m_type == (int) IBIS_MODEL_TYPE::OUTPUT );
198 BOOST_TEST( (int) model->m_polarity == (int) IBIS_MODEL_POLARITY::NON_INVERTING );
199 BOOST_TEST( (int) model->m_enable = (int) IBIS_MODEL_ENABLE::ACTIVE_HIGH );
200 BOOST_TEST( model->m_vmeas == 0.675 );
201 BOOST_TEST( model->m_cref == 5e-12 );
202 BOOST_TEST( model->m_rref == 50.0 );
203 BOOST_TEST( model->m_vref == 0.675 );
204 BOOST_TEST( model->m_C_comp.value[0] == 2.68e-12 );
205 BOOST_TEST( model->m_C_comp.value[1] == 2.64e-12 );
206 BOOST_TEST( model->m_C_comp.value[2] == 2.75e-12 );
207 BOOST_TEST( model->m_voltageRange.value[0] == 1.35 );
208 BOOST_TEST( model->m_voltageRange.value[1] == 1.28 );
209 BOOST_TEST( model->m_voltageRange.value[2] == 1.42 );
210 BOOST_TEST( model->m_temperatureRange.value[0] == 50.0 );
211 BOOST_TEST( model->m_temperatureRange.value[1] == 100.0 );
212 BOOST_TEST( model->m_temperatureRange.value[2] == 0.0 );
213
214 BOOST_TEST( model->HasGNDClamp() );
215 BOOST_TEST( model->m_GNDClamp.m_entries.size() == 4 );
216 BOOST_TEST( model->m_GNDClamp.m_entries[0].V == -1.35 );
217 BOOST_TEST( model->m_GNDClamp.m_entries[0].I.value[0] == -26.89e-3 );
218 BOOST_TEST( model->m_GNDClamp.m_entries[0].I.value[1] == -20.44e-3 );
219 BOOST_TEST( model->m_GNDClamp.m_entries[0].I.value[2] == -35.94e-3 );
220 BOOST_TEST( model->m_GNDClamp.m_entries[1].V == 0.0 );
221 BOOST_TEST( model->m_GNDClamp.m_entries[1].I.value[0] == -29.09e-9 );
222 BOOST_TEST( model->m_GNDClamp.m_entries[1].I.value[1] == -44.53e-9 );
223 BOOST_TEST( model->m_GNDClamp.m_entries[1].I.value[2] == -51.87e-9 );
224 BOOST_TEST( model->m_GNDClamp.m_entries[2].V == 1.35 );
225 BOOST_TEST( model->m_GNDClamp.m_entries[2].I.value[0] == 0.518e-6 );
226 BOOST_TEST( model->m_GNDClamp.m_entries[2].I.value[1] == 0.0 );
227 BOOST_TEST( model->m_GNDClamp.m_entries[2].I.value[2] == 0.444e-6 );
228 BOOST_TEST( model->m_GNDClamp.m_entries[3].V == 2.7 );
229 BOOST_TEST( model->m_GNDClamp.m_entries[3].I.value[0] == 0.0 );
230 BOOST_TEST( model->m_GNDClamp.m_entries[3].I.value[1] == 0.0 );
231 BOOST_TEST( model->m_GNDClamp.m_entries[3].I.value[2] == 0.0 );
232
233 BOOST_TEST( model->HasPOWERClamp() );
234 BOOST_TEST( model->m_POWERClamp.m_entries.size() == 4 );
235 BOOST_TEST( model->m_POWERClamp.m_entries[0].V == -1.35 );
236 BOOST_TEST( model->m_POWERClamp.m_entries[0].I.value[0] == 55.06e-3 );
237 BOOST_TEST( model->m_POWERClamp.m_entries[0].I.value[1] == 46.76e-3 );
238 BOOST_TEST( model->m_POWERClamp.m_entries[0].I.value[2] == 74.09e-3 );
239 BOOST_TEST( model->m_POWERClamp.m_entries[1].V == 0.0 );
240 BOOST_TEST( model->m_POWERClamp.m_entries[1].I.value[0] == 0.0 );
241 BOOST_TEST( model->m_POWERClamp.m_entries[1].I.value[1] == 0.515e-6 );
242 BOOST_TEST( model->m_POWERClamp.m_entries[1].I.value[2] == 74.94e-9 );
243 BOOST_TEST( model->m_POWERClamp.m_entries[2].V == 1.35 );
244 BOOST_TEST( model->m_POWERClamp.m_entries[2].I.value[0] == 0.0 );
245 BOOST_TEST( model->m_POWERClamp.m_entries[2].I.value[1] == 0.0 );
246 BOOST_TEST( model->m_POWERClamp.m_entries[2].I.value[2] == 0.0 );
247 BOOST_TEST( model->m_POWERClamp.m_entries[3].V == 2.7 );
248 BOOST_TEST( model->m_POWERClamp.m_entries[3].I.value[0] == 0.0 );
249 BOOST_TEST( model->m_POWERClamp.m_entries[3].I.value[1] == 0.0 );
250 BOOST_TEST( model->m_POWERClamp.m_entries[3].I.value[2] == 0.0 );
251
252 BOOST_TEST( model->HasPullup() );
253 BOOST_TEST( model->m_pullup.m_entries.size() == 4 );
254 BOOST_TEST( model->m_pullup.m_entries[0].V == -1.35 );
255 BOOST_TEST( model->m_pullup.m_entries[0].I.value[0] == 18.04e-3 );
256 BOOST_TEST( model->m_pullup.m_entries[0].I.value[1] == 16.15e-3 );
257 BOOST_TEST( model->m_pullup.m_entries[0].I.value[2] == 17.46e-3 );
258 BOOST_TEST( model->m_pullup.m_entries[1].V == 0.0 );
259 BOOST_TEST( model->m_pullup.m_entries[1].I.value[0] == 3.412e-9 );
260 BOOST_TEST( model->m_pullup.m_entries[1].I.value[1] == 0.527e-6 );
261 BOOST_TEST( model->m_pullup.m_entries[1].I.value[2] == 0.327e-6 );
262 BOOST_TEST( model->m_pullup.m_entries[2].V == 1.35 );
263 BOOST_TEST( model->m_pullup.m_entries[2].I.value[0] == -26.46e-3 );
264 BOOST_TEST( model->m_pullup.m_entries[2].I.value[1] == -24.75e-3 );
265 BOOST_TEST( model->m_pullup.m_entries[2].I.value[2] == -22.82e-3 );
266 BOOST_TEST( model->m_pullup.m_entries[3].V == 2.7 );
267 BOOST_TEST( model->m_pullup.m_entries[3].I.value[0] == -31.03e-3 );
268 BOOST_TEST( model->m_pullup.m_entries[3].I.value[1] == -28.82e-3 );
269 BOOST_TEST( model->m_pullup.m_entries[3].I.value[2] == -27.31e-3 );
270
271 BOOST_TEST( model->HasPulldown() );
272 BOOST_TEST( model->m_pulldown.m_entries.size() == 4 );
273 BOOST_TEST( model->m_pulldown.m_entries[0].V == -1.35 );
274 BOOST_TEST( model->m_pulldown.m_entries[0].I.value[0] == -23.01e-3 );
275 BOOST_TEST( model->m_pulldown.m_entries[0].I.value[1] == -20.02e-3 );
276 BOOST_TEST( model->m_pulldown.m_entries[0].I.value[2] == -20.46e-3 );
277 BOOST_TEST( model->m_pulldown.m_entries[1].V == 0.0 );
278 BOOST_TEST( model->m_pulldown.m_entries[1].I.value[0] == -38.81e-9 );
279 BOOST_TEST( model->m_pulldown.m_entries[1].I.value[1] == -32.33e-9 );
280 BOOST_TEST( model->m_pulldown.m_entries[1].I.value[2] == -49.77e-9 );
281 BOOST_TEST( model->m_pulldown.m_entries[2].V == 1.35 );
282 BOOST_TEST( model->m_pulldown.m_entries[2].I.value[0] == 26.98e-3 );
283 BOOST_TEST( model->m_pulldown.m_entries[2].I.value[1] == 23.63e-3 );
284 BOOST_TEST( model->m_pulldown.m_entries[2].I.value[2] == 26.60e-3 );
285 BOOST_TEST( model->m_pulldown.m_entries[3].V == 2.7 );
286 BOOST_TEST( model->m_pulldown.m_entries[3].I.value[0] == 29.20e-3 );
287 BOOST_TEST( model->m_pulldown.m_entries[3].I.value[1] == 25.40e-3 );
288 BOOST_TEST( model->m_pulldown.m_entries[3].I.value[2] == 29.03e-3 );
289
290 BOOST_TEST( model->m_ramp.m_Rload == 50.0 );
291 BOOST_TEST( model->m_ramp.m_rising.value[0].m_dv == 0.462 );
292 BOOST_TEST( model->m_ramp.m_rising.value[0].m_dt == 0.131e-9 );
293 BOOST_TEST( model->m_ramp.m_rising.value[1].m_dv == 0.439 );
294 BOOST_TEST( model->m_ramp.m_rising.value[1].m_dt == 0.138e-9 );
295 BOOST_TEST( model->m_ramp.m_rising.value[2].m_dv == 0.462 );
296 BOOST_TEST( model->m_ramp.m_rising.value[2].m_dt == 0.158e-9 );
297 BOOST_TEST( model->m_ramp.m_falling.value[0].m_dv == 0.465 );
298 BOOST_TEST( model->m_ramp.m_falling.value[0].m_dt == 0.116e-9 );
299 BOOST_TEST( model->m_ramp.m_falling.value[1].m_dv == 0.438 );
300 BOOST_TEST( model->m_ramp.m_falling.value[1].m_dt == 0.126e-9 );
301 BOOST_TEST( model->m_ramp.m_falling.value[2].m_dv == 0.468 );
302 BOOST_TEST( model->m_ramp.m_falling.value[2].m_dt == 0.117e-9 );
303
304 BOOST_TEST( model->m_risingWaveforms.size() == 2 );
305 BOOST_TEST( (int) model->m_risingWaveforms[1]->m_type == (int) IBIS_WAVEFORM_TYPE::RISING );
306 BOOST_TEST( model->m_risingWaveforms[1]->m_R_fixture == 50.0 );
307 BOOST_TEST( model->m_risingWaveforms[1]->m_V_fixture == 1.35 );
308 BOOST_TEST( model->m_risingWaveforms[1]->m_V_fixture_min == 1.28 );
309 BOOST_TEST( model->m_risingWaveforms[1]->m_V_fixture_max == 1.42 );
310 BOOST_TEST( model->m_risingWaveforms[1]->m_table.m_entries.size() == 5 );
311 BOOST_TEST( model->m_risingWaveforms[1]->m_table.m_entries[0].t == 0 );
312 BOOST_TEST( model->m_risingWaveforms[1]->m_table.m_entries[0].V.value[0] == 0.573 );
313 BOOST_TEST( model->m_risingWaveforms[1]->m_table.m_entries[0].V.value[1] == 0.550 );
314 BOOST_TEST( model->m_risingWaveforms[1]->m_table.m_entries[0].V.value[2] == 0.636 );
315 BOOST_TEST( model->m_risingWaveforms[1]->m_table.m_entries[1].t == 1.001e-9 );
316 BOOST_TEST( model->m_risingWaveforms[1]->m_table.m_entries[1].V.value[0] == 0.574 );
317 BOOST_TEST( model->m_risingWaveforms[1]->m_table.m_entries[1].V.value[1] == 0.551 );
318 BOOST_TEST( model->m_risingWaveforms[1]->m_table.m_entries[1].V.value[2] == 0.906 );
319 BOOST_TEST( model->m_risingWaveforms[1]->m_table.m_entries[2].t == 2e-9 );
320 BOOST_TEST( model->m_risingWaveforms[1]->m_table.m_entries[2].V.value[0] == 1.348 );
321 BOOST_TEST( model->m_risingWaveforms[1]->m_table.m_entries[2].V.value[1] == 1.269 );
322 BOOST_TEST( model->m_risingWaveforms[1]->m_table.m_entries[2].V.value[2] == 1.416 );
323 BOOST_TEST( model->m_risingWaveforms[1]->m_table.m_entries[3].t == 2.491e-9 );
324 BOOST_TEST( model->m_risingWaveforms[1]->m_table.m_entries[3].V.value[0] == 1.349 );
325 BOOST_TEST( model->m_risingWaveforms[1]->m_table.m_entries[3].V.value[1] == 1.280 );
326 BOOST_TEST( model->m_risingWaveforms[1]->m_table.m_entries[3].V.value[2] == 1.416 );
327 BOOST_TEST( model->m_risingWaveforms[1]->m_table.m_entries[4].t == 10e-9 );
328 BOOST_TEST( model->m_risingWaveforms[1]->m_table.m_entries[4].V.value[0] == 1.349 );
329 BOOST_TEST( model->m_risingWaveforms[1]->m_table.m_entries[4].V.value[1] == 1.282 );
330 BOOST_TEST( model->m_risingWaveforms[1]->m_table.m_entries[4].V.value[2] == 1.417 );
331
332 BOOST_TEST( model->m_fallingWaveforms.size() == 2 );
333 BOOST_TEST( (int) model->m_fallingWaveforms[1]->m_type == (int) IBIS_WAVEFORM_TYPE::FALLING );
334 BOOST_TEST( model->m_fallingWaveforms[1]->m_R_fixture == 50.0 );
335 BOOST_TEST( model->m_fallingWaveforms[1]->m_V_fixture == 1.35 );
336 BOOST_TEST( model->m_fallingWaveforms[1]->m_V_fixture_min == 1.28 );
337 BOOST_TEST( model->m_fallingWaveforms[1]->m_V_fixture_max == 1.42 );
338 BOOST_TEST( model->m_fallingWaveforms[1]->m_table.m_entries.size() == 5 );
339 BOOST_TEST( model->m_fallingWaveforms[1]->m_table.m_entries[0].t == 0 );
340 BOOST_TEST( model->m_fallingWaveforms[1]->m_table.m_entries[0].V.value[0] == 1.349 );
341 BOOST_TEST( model->m_fallingWaveforms[1]->m_table.m_entries[0].V.value[1] == 1.282 );
342 BOOST_TEST( model->m_fallingWaveforms[1]->m_table.m_entries[0].V.value[2] == 1.417 );
343 BOOST_TEST( model->m_fallingWaveforms[1]->m_table.m_entries[1].t == 1.02e-9 );
344 BOOST_TEST( model->m_fallingWaveforms[1]->m_table.m_entries[1].V.value[0] == 1.350 );
345 BOOST_TEST( model->m_fallingWaveforms[1]->m_table.m_entries[1].V.value[1] == 1.283 );
346 BOOST_TEST( model->m_fallingWaveforms[1]->m_table.m_entries[1].V.value[2] == 1.382 );
347 BOOST_TEST( model->m_fallingWaveforms[1]->m_table.m_entries[2].t == 1.988e-9 );
348 BOOST_TEST( model->m_fallingWaveforms[1]->m_table.m_entries[2].V.value[0] == 0.576 );
349 BOOST_TEST( model->m_fallingWaveforms[1]->m_table.m_entries[2].V.value[1] == 0.606 );
350 BOOST_TEST( model->m_fallingWaveforms[1]->m_table.m_entries[2].V.value[2] == 0.638 );
351 BOOST_TEST( model->m_fallingWaveforms[1]->m_table.m_entries[3].t == 2.51e-9 );
352 BOOST_TEST( model->m_fallingWaveforms[1]->m_table.m_entries[3].V.value[0] == 0.574 );
353 BOOST_TEST( model->m_fallingWaveforms[1]->m_table.m_entries[3].V.value[1] == 0.552 );
354 BOOST_TEST( model->m_fallingWaveforms[1]->m_table.m_entries[3].V.value[2] == 0.637 );
355 BOOST_TEST( model->m_fallingWaveforms[1]->m_table.m_entries[4].t == 10e-9 );
356 BOOST_TEST( model->m_fallingWaveforms[1]->m_table.m_entries[4].V.value[0] == 0.573 );
357 BOOST_TEST( model->m_fallingWaveforms[1]->m_table.m_entries[4].V.value[1] == 0.550 );
358 BOOST_TEST( model->m_fallingWaveforms[1]->m_table.m_entries[4].V.value[2] == 0.636 );
359
360 BOOST_TEST( model->m_submodels.size() == 0 );
361
362 model = top.GetModel( "DQ40_ODT40" );
363
364 BOOST_REQUIRE( model != nullptr );
365 BOOST_TEST_INFO( "Model: " << model->m_name );
366
367 BOOST_TEST( model->m_name == "DQ40_ODT40" );
368 BOOST_TEST( (int) model->m_type == (int) IBIS_MODEL_TYPE::IO );
369 BOOST_TEST( model->m_vinl == 0.515 );
370 BOOST_TEST( model->m_vinh == 0.835 );
371 BOOST_TEST( model->m_vmeas == 0.675 );
372 BOOST_TEST( model->m_cref == 0.0 );
373 BOOST_TEST( model->m_rref == 25.0 );
374 BOOST_TEST( model->m_vref == 0.675 );
375 BOOST_TEST( model->m_C_comp.value[0] == 1.36e-12 );
376 BOOST_TEST( model->m_C_comp.value[1] == 1.26e-12 );
377 BOOST_TEST( model->m_C_comp.value[2] == 1.46e-12 );
378 BOOST_TEST( model->m_voltageRange.value[0] == 1.35 );
379 BOOST_TEST( model->m_voltageRange.value[1] == 1.28 );
380 BOOST_TEST( model->m_voltageRange.value[2] == 1.42 );
381 BOOST_TEST( model->m_temperatureRange.value[0] == 50.0 );
382 BOOST_TEST( model->m_temperatureRange.value[1] == 100.0 );
383 BOOST_TEST( model->m_temperatureRange.value[2] == 0.0 );
384
385 BOOST_TEST( model->HasGNDClamp() );
386 BOOST_TEST( model->m_GNDClamp.m_entries.size() == 4 );
387 BOOST_TEST( model->m_GNDClamp.m_entries[0].V == -1.35 );
388 BOOST_TEST( model->m_GNDClamp.m_entries[0].I.value[0] == -39.74e-3 );
389 BOOST_TEST( model->m_GNDClamp.m_entries[0].I.value[1] == -37.76e-3 );
390 BOOST_TEST( model->m_GNDClamp.m_entries[0].I.value[2] == -41.37e-3 );
391 BOOST_TEST( model->m_GNDClamp.m_entries[1].V == -0.175 );
392 BOOST_TEST( std::isnan( model->m_GNDClamp.m_entries[1].I.value[0] ) );
393 BOOST_TEST( std::isnan( model->m_GNDClamp.m_entries[1].I.value[1] ) );
394 BOOST_TEST( model->m_GNDClamp.m_entries[1].I.value[2] == 0.0 );
395 BOOST_TEST( model->m_GNDClamp.m_entries[2].V == 1.35 );
396 BOOST_TEST( model->m_GNDClamp.m_entries[2].I.value[0] == 0.0 );
397 BOOST_TEST( model->m_GNDClamp.m_entries[2].I.value[1] == 0.0 );
398 BOOST_TEST( model->m_GNDClamp.m_entries[2].I.value[2] == 0.0 );
399 BOOST_TEST( model->m_GNDClamp.m_entries[3].V == 2.7 );
400 BOOST_TEST( model->m_GNDClamp.m_entries[3].I.value[0] == 0.0 );
401 BOOST_TEST( model->m_GNDClamp.m_entries[3].I.value[1] == 0.0 );
402 BOOST_TEST( model->m_GNDClamp.m_entries[3].I.value[2] == 0.0 );
403
404 BOOST_TEST( model->HasPOWERClamp() );
405 BOOST_TEST( model->m_POWERClamp.m_entries.size() == 4 );
406 BOOST_TEST( model->m_POWERClamp.m_entries[0].V == -1.35 );
407 BOOST_TEST( model->m_POWERClamp.m_entries[0].I.value[0] == 88.45e-3 );
408 BOOST_TEST( model->m_POWERClamp.m_entries[0].I.value[1] == 79.46e-3 );
409 BOOST_TEST( model->m_POWERClamp.m_entries[0].I.value[2] == 95.25e-3 );
410 BOOST_TEST( model->m_POWERClamp.m_entries[1].V == -0.28 );
411 BOOST_TEST( std::isnan( model->m_POWERClamp.m_entries[1].I.value[0] ) );
412 BOOST_TEST( model->m_POWERClamp.m_entries[1].I.value[1] == 0.0 );
413 BOOST_TEST( std::isnan( model->m_POWERClamp.m_entries[1].I.value[2] ) );
414 BOOST_TEST( model->m_POWERClamp.m_entries[2].V == 1.35 );
415 BOOST_TEST( model->m_POWERClamp.m_entries[2].I.value[0] == 0.0 );
416 BOOST_TEST( model->m_POWERClamp.m_entries[2].I.value[1] == 0.0 );
417 BOOST_TEST( model->m_POWERClamp.m_entries[2].I.value[2] == 0.0 );
418 BOOST_TEST( model->m_POWERClamp.m_entries[3].V == 2.7 );
419 BOOST_TEST( model->m_POWERClamp.m_entries[3].I.value[0] == 0.0 );
420 BOOST_TEST( model->m_POWERClamp.m_entries[3].I.value[1] == 0.0 );
421 BOOST_TEST( model->m_POWERClamp.m_entries[3].I.value[2] == 0.0 );
422
423 BOOST_TEST( model->HasPullup() );
424 BOOST_TEST( model->m_pullup.m_entries.size() == 4 );
425 BOOST_TEST( model->m_pullup.m_entries[0].V == -1.35 );
426 BOOST_TEST( model->m_pullup.m_entries[0].I.value[0] == 7.027e-3 );
427 BOOST_TEST( model->m_pullup.m_entries[0].I.value[1] == 7.411e-3 );
428 BOOST_TEST( model->m_pullup.m_entries[0].I.value[2] == 8.620e-3 );
429 BOOST_TEST( model->m_pullup.m_entries[1].V == 0.0 );
430 BOOST_TEST( model->m_pullup.m_entries[1].I.value[0] == 31.17e-6 );
431 BOOST_TEST( model->m_pullup.m_entries[1].I.value[1] == 35.34e-6 );
432 BOOST_TEST( model->m_pullup.m_entries[1].I.value[2] == 10.66e-6 );
433 BOOST_TEST( model->m_pullup.m_entries[2].V == 1.35 );
434 BOOST_TEST( model->m_pullup.m_entries[2].I.value[0] == -21.21e-3 );
435 BOOST_TEST( model->m_pullup.m_entries[2].I.value[1] == -19.19e-3 );
436 BOOST_TEST( model->m_pullup.m_entries[2].I.value[2] == -25.02e-3 );
437 BOOST_TEST( model->m_pullup.m_entries[3].V == 2.7 );
438 BOOST_TEST( model->m_pullup.m_entries[3].I.value[0] == -25.77e-3 );
439 BOOST_TEST( model->m_pullup.m_entries[3].I.value[1] == -23.32e-3 );
440 BOOST_TEST( model->m_pullup.m_entries[3].I.value[2] == -30.53e-3 );
441
442 BOOST_TEST( model->HasPulldown() );
443 BOOST_TEST( model->m_pulldown.m_entries.size() == 4 );
444 BOOST_TEST( model->m_pulldown.m_entries[0].V == -1.35 );
445 BOOST_TEST( model->m_pulldown.m_entries[0].I.value[0] == -13.96e-3 );
446 BOOST_TEST( model->m_pulldown.m_entries[0].I.value[1] == -12.59e-3 );
447 BOOST_TEST( model->m_pulldown.m_entries[0].I.value[2] == -15.56e-3 );
448 BOOST_TEST( model->m_pulldown.m_entries[1].V == 0.0 );
449 BOOST_TEST( model->m_pulldown.m_entries[1].I.value[0] == -3.893e-6 );
450 BOOST_TEST( model->m_pulldown.m_entries[1].I.value[1] == -4.109e-6 );
451 BOOST_TEST( model->m_pulldown.m_entries[1].I.value[2] == -1.483e-6 );
452 BOOST_TEST( model->m_pulldown.m_entries[2].V == 1.35 );
453 BOOST_TEST( model->m_pulldown.m_entries[2].I.value[0] == 26.08e-3 );
454 BOOST_TEST( model->m_pulldown.m_entries[2].I.value[1] == 22.37e-3 );
455 BOOST_TEST( model->m_pulldown.m_entries[2].I.value[2] == 30.44e-3 );
456 BOOST_TEST( model->m_pulldown.m_entries[3].V == 2.7 );
457 BOOST_TEST( model->m_pulldown.m_entries[3].I.value[0] == 30.20e-3 );
458 BOOST_TEST( model->m_pulldown.m_entries[3].I.value[1] == 25.46e-3 );
459 BOOST_TEST( model->m_pulldown.m_entries[3].I.value[2] == 36.99e-3 );
460
461 BOOST_TEST( model->m_ramp.m_Rload == 50.0 );
462 BOOST_TEST( model->m_ramp.m_rising.value[0].m_dv == 0.451 );
463 BOOST_TEST( model->m_ramp.m_rising.value[0].m_dt == 134e-12 );
464 BOOST_TEST( model->m_ramp.m_rising.value[1].m_dv == 0.424 );
465 BOOST_TEST( model->m_ramp.m_rising.value[1].m_dt == 184e-12 );
466 BOOST_TEST( model->m_ramp.m_rising.value[2].m_dv == 0.495 );
467 BOOST_TEST( model->m_ramp.m_rising.value[2].m_dt == 103e-12 );
468 BOOST_TEST( model->m_ramp.m_falling.value[0].m_dv == 0.438 );
469 BOOST_TEST( model->m_ramp.m_falling.value[0].m_dt == 120e-12 );
470 BOOST_TEST( model->m_ramp.m_falling.value[1].m_dv == 0.411 );
471 BOOST_TEST( model->m_ramp.m_falling.value[1].m_dt == 159e-12 );
472 BOOST_TEST( model->m_ramp.m_falling.value[2].m_dv == 0.475 );
473 BOOST_TEST( model->m_ramp.m_falling.value[2].m_dt == 90e-12 );
474
475 BOOST_TEST( model->m_risingWaveforms.size() == 2 );
476 BOOST_TEST( (int) model->m_risingWaveforms[0]->m_type == (int) IBIS_WAVEFORM_TYPE::RISING );
477 BOOST_TEST( model->m_risingWaveforms[0]->m_R_fixture == 50.0 );
478 BOOST_TEST( model->m_risingWaveforms[0]->m_V_fixture == 1.35 );
479 BOOST_TEST( model->m_risingWaveforms[0]->m_V_fixture_min == 1.28 );
480 BOOST_TEST( model->m_risingWaveforms[0]->m_V_fixture_max == 1.42 );
481 BOOST_TEST( model->m_risingWaveforms[0]->m_table.m_entries.size() == 4 );
482 BOOST_TEST( model->m_risingWaveforms[0]->m_table.m_entries[0].t == 0 );
483 BOOST_TEST( model->m_risingWaveforms[0]->m_table.m_entries[0].V.value[0] == 0.6179 );
484 BOOST_TEST( model->m_risingWaveforms[0]->m_table.m_entries[0].V.value[1] == 0.5969 );
485 BOOST_TEST( model->m_risingWaveforms[0]->m_table.m_entries[0].V.value[2] == 0.6325 );
486 BOOST_TEST( model->m_risingWaveforms[0]->m_table.m_entries[1].t == 199e-12 );
487 BOOST_TEST( model->m_risingWaveforms[0]->m_table.m_entries[1].V.value[0] == 0.9465 );
488 BOOST_TEST( model->m_risingWaveforms[0]->m_table.m_entries[1].V.value[1] == 0.8243 );
489 BOOST_TEST( model->m_risingWaveforms[0]->m_table.m_entries[1].V.value[2] == 1.1430 );
490 BOOST_TEST( model->m_risingWaveforms[0]->m_table.m_entries[2].t == 399e-12 );
491 BOOST_TEST( model->m_risingWaveforms[0]->m_table.m_entries[2].V.value[0] == 1.340 );
492 BOOST_TEST( model->m_risingWaveforms[0]->m_table.m_entries[2].V.value[1] == 1.261 );
493 BOOST_TEST( model->m_risingWaveforms[0]->m_table.m_entries[2].V.value[2] == 1.420 );
494 BOOST_TEST( model->m_risingWaveforms[0]->m_table.m_entries[3].t == 937e-12 );
495 BOOST_TEST( model->m_risingWaveforms[0]->m_table.m_entries[3].V.value[0] == 1.349 );
496 BOOST_TEST( model->m_risingWaveforms[0]->m_table.m_entries[3].V.value[1] == 1.282 );
497 BOOST_TEST( model->m_risingWaveforms[0]->m_table.m_entries[3].V.value[2] == 1.424 );
498
499 BOOST_TEST( model->m_fallingWaveforms.size() == 2 );
500 BOOST_TEST( (int) model->m_fallingWaveforms[0]->m_type == (int) IBIS_WAVEFORM_TYPE::FALLING );
501 BOOST_TEST( model->m_fallingWaveforms[0]->m_R_fixture == 50.0 );
502 BOOST_TEST( model->m_fallingWaveforms[0]->m_V_fixture == 1.35 );
503 BOOST_TEST( model->m_fallingWaveforms[0]->m_V_fixture_min == 1.28 );
504 BOOST_TEST( model->m_fallingWaveforms[0]->m_V_fixture_max == 1.42 );
505 BOOST_TEST( model->m_fallingWaveforms[0]->m_table.m_entries.size() == 4 );
506 BOOST_TEST( model->m_fallingWaveforms[0]->m_table.m_entries[0].t == 0 );
507 BOOST_TEST( model->m_fallingWaveforms[0]->m_table.m_entries[0].V.value[0] == 1.349 );
508 BOOST_TEST( model->m_fallingWaveforms[0]->m_table.m_entries[0].V.value[1] == 1.282 );
509 BOOST_TEST( model->m_fallingWaveforms[0]->m_table.m_entries[0].V.value[2] == 1.424 );
510 BOOST_TEST( model->m_fallingWaveforms[0]->m_table.m_entries[1].t == 198e-12 );
511 BOOST_TEST( model->m_fallingWaveforms[0]->m_table.m_entries[1].V.value[0] == 1.270 );
512 BOOST_TEST( model->m_fallingWaveforms[0]->m_table.m_entries[1].V.value[1] == 1.248 );
513 BOOST_TEST( model->m_fallingWaveforms[0]->m_table.m_entries[1].V.value[2] == 1.203 );
514 BOOST_TEST( model->m_fallingWaveforms[0]->m_table.m_entries[2].t == 398e-12 );
515 BOOST_TEST( model->m_fallingWaveforms[0]->m_table.m_entries[2].V.value[0] == 0.6815 );
516 BOOST_TEST( model->m_fallingWaveforms[0]->m_table.m_entries[2].V.value[1] == 0.7726 );
517 BOOST_TEST( model->m_fallingWaveforms[0]->m_table.m_entries[2].V.value[2] == 0.6551 );
518 BOOST_TEST( model->m_fallingWaveforms[0]->m_table.m_entries[3].t == 937e-12 );
519 BOOST_TEST( model->m_fallingWaveforms[0]->m_table.m_entries[3].V.value[0] == 0.6179 );
520 BOOST_TEST( model->m_fallingWaveforms[0]->m_table.m_entries[3].V.value[1] == 0.5969);
521 BOOST_TEST( model->m_fallingWaveforms[0]->m_table.m_entries[3].V.value[2] == 0.6325 );
522
523 BOOST_TEST( model->m_submodels.size() == 1 );
524 BOOST_TEST( model->m_submodels[0].m_name == "40ohm_ODT" );
525 BOOST_TEST( (int) model->m_submodels[0].m_type == (int) IBIS_SUBMODEL_TYPE::DYNAMIC_CLAMP );
526 BOOST_TEST( (int) model->m_submodels[0].m_mode == (int) IBIS_SUBMODEL_MODE::NON_DRIVING );
527
528 BOOST_TEST( model->m_submodels[0].HasGNDClamp() );
529 BOOST_TEST( model->m_submodels[0].m_GNDClamp.m_entries.size() == 4 );
530 BOOST_TEST( model->m_submodels[0].m_GNDClamp.m_entries[0].V == -1.35 );
531 BOOST_TEST( model->m_submodels[0].m_GNDClamp.m_entries[0].I.value[0] == -6.975e-3 );
532 BOOST_TEST( model->m_submodels[0].m_GNDClamp.m_entries[0].I.value[1] == -6.287e-3 );
533 BOOST_TEST( model->m_submodels[0].m_GNDClamp.m_entries[0].I.value[2] == -7.776e-3 );
534 BOOST_TEST( model->m_submodels[0].m_GNDClamp.m_entries[1].V == 0.0 );
535 BOOST_TEST( model->m_submodels[0].m_GNDClamp.m_entries[1].I.value[0] == -1.585e-6 );
536 BOOST_TEST( model->m_submodels[0].m_GNDClamp.m_entries[1].I.value[1] == -2.224e-6 );
537 BOOST_TEST( model->m_submodels[0].m_GNDClamp.m_entries[1].I.value[2] == -819.6e-9 );
538 BOOST_TEST( model->m_submodels[0].m_GNDClamp.m_entries[2].V == 1.35 );
539 BOOST_TEST( model->m_submodels[0].m_GNDClamp.m_entries[2].I.value[0] == 12.86e-3 );
540 BOOST_TEST( model->m_submodels[0].m_GNDClamp.m_entries[2].I.value[1] == 11.10e-3 );
541 BOOST_TEST( model->m_submodels[0].m_GNDClamp.m_entries[2].I.value[2] == 14.96e-3 );
542 BOOST_TEST( model->m_submodels[0].m_GNDClamp.m_entries[3].V == 2.7 );
543 BOOST_TEST( model->m_submodels[0].m_GNDClamp.m_entries[3].I.value[0] == 15.10e-3 );
544 BOOST_TEST( model->m_submodels[0].m_GNDClamp.m_entries[3].I.value[1] == 12.73e-3 );
545 BOOST_TEST( model->m_submodels[0].m_GNDClamp.m_entries[3].I.value[2] == 18.50e-3 );
546
547 BOOST_TEST( model->m_submodels[0].HasPOWERClamp() );
548 BOOST_TEST( model->m_submodels[0].m_POWERClamp.m_entries.size() == 4 );
549 BOOST_TEST( model->m_submodels[0].m_POWERClamp.m_entries[0].V == -1.35 );
550 BOOST_TEST( model->m_submodels[0].m_POWERClamp.m_entries[0].I.value[0] == 3.515e-3 );
551 BOOST_TEST( model->m_submodels[0].m_POWERClamp.m_entries[0].I.value[1] == 3.706e-3 );
552 BOOST_TEST( model->m_submodels[0].m_POWERClamp.m_entries[0].I.value[2] == 4.312e-3 );
553 BOOST_TEST( model->m_submodels[0].m_POWERClamp.m_entries[1].V == 0.0 );
554 BOOST_TEST( model->m_submodels[0].m_POWERClamp.m_entries[1].I.value[0] == 13.01e-6 );
555 BOOST_TEST( model->m_submodels[0].m_POWERClamp.m_entries[1].I.value[1] == 18.85e-6 );
556 BOOST_TEST( model->m_submodels[0].m_POWERClamp.m_entries[1].I.value[2] == 5.723e-6 );
557 BOOST_TEST( model->m_submodels[0].m_POWERClamp.m_entries[2].V == 1.35 );
558 BOOST_TEST( model->m_submodels[0].m_POWERClamp.m_entries[2].I.value[0] == -10.50e-3 );
559 BOOST_TEST( model->m_submodels[0].m_POWERClamp.m_entries[2].I.value[1] == -9.514e-3 );
560 BOOST_TEST( model->m_submodels[0].m_POWERClamp.m_entries[2].I.value[2] == -12.39e-3 );
561 BOOST_TEST( model->m_submodels[0].m_POWERClamp.m_entries[3].V == 2.7 );
562 BOOST_TEST( model->m_submodels[0].m_POWERClamp.m_entries[3].I.value[0] == -12.88e-3 );
563 BOOST_TEST( model->m_submodels[0].m_POWERClamp.m_entries[3].I.value[1] == -11.66e-3 );
564 BOOST_TEST( model->m_submodels[0].m_POWERClamp.m_entries[3].I.value[2] == -15.26e-3 );
565}
566
567// Regression test for https://gitlab.com/kicad/code/kicad/-/issues/23568
568// The [Series Pin Mapping] keyword was added in IBIS 4.1. Before this fix,
569// encountering it inside a [Component] section produced the fatal parse error
570// "Unknown keyword in COMPONENT context: series_pin_mapping".
571BOOST_AUTO_TEST_CASE( Load_v4_1_SeriesPinMapping )
572{
574
575 std::string path = GetLibraryPath( "ibis_v4_1_series_pin_mapping" );
576 KIBIS top( path, &reporter );
577
578 BOOST_TEST_INFO( "Parsed: " << path );
579 BOOST_TEST_INFO( "Reported: " << reporter.GetMessages() );
580
581 BOOST_TEST( top.m_valid );
582 BOOST_TEST( !reporter.HasMessageOfSeverity( RPT_SEVERITY_ERROR ) );
583
584 KIBIS_COMPONENT* comp = top.GetComponent( "SeriesSwitchDevice" );
585
586 BOOST_REQUIRE( comp != nullptr );
587 BOOST_TEST( comp->m_name == "SeriesSwitchDevice" );
588 BOOST_TEST( comp->m_pins.size() == 4 );
589}
590
591
592// Regression test for #24228: parse → KIBIS_MODEL → writeSpiceDevice.
593BOOST_AUTO_TEST_CASE( Load_v4_1_RSeries, *boost::unit_test::tolerance( 1e-15 ) )
594{
596
597 std::string path = GetLibraryPath( "ibis_v4_1_r_series" );
598 KIBIS top( path, &reporter );
599
600 BOOST_TEST_INFO( "Parsed: " << path );
601 BOOST_TEST_INFO( "Reported: " << reporter.GetMessages() );
602
603 BOOST_TEST( top.m_valid );
604 BOOST_TEST( !reporter.HasMessageOfSeverity( RPT_SEVERITY_ERROR ) );
605
606 KIBIS_MODEL* model = top.GetModel( "series_r" );
607 BOOST_REQUIRE( model != nullptr );
608 BOOST_TEST( model->m_name == "series_r" );
609 BOOST_TEST( (int) model->m_type == (int) IBIS_MODEL_TYPE::SERIES );
610
611 KIBIS_MODEL* swModel = top.GetModel( "series_sw" );
612 BOOST_REQUIRE( swModel != nullptr );
614
615 KIBIS_MODEL* mosfetModel = top.GetModel( "series_mosfet" );
618
620 BOOST_REQUIRE( parser.ParseFile( path ) );
621
622 const IbisModel* parsedSeries = nullptr;
623 const IbisModel* parsedSwitch = nullptr;
624 const IbisModel* parsedMosfet = nullptr;
625
626 for( const IbisModel& m : parser.m_ibisFile.m_models )
627 {
628 if( m.m_name == "series_r" )
629 parsedSeries = &m;
630 else if( m.m_name == "series_sw" )
631 parsedSwitch = &m;
632 else if( m.m_name == "series_mosfet" )
633 parsedMosfet = &m;
634 }
635
637 BOOST_TEST( parsedSeries->m_series.m_Rseries.value[0] == 25.0 );
638 BOOST_TEST( parsedSeries->m_series.m_Rseries.value[1] == 22.0 );
639 BOOST_TEST( parsedSeries->m_series.m_Rseries.value[2] == 28.0 );
640 BOOST_TEST( parsedSeries->m_series.m_Lseries.value[0] == 1.0e-9 );
641 BOOST_TEST( parsedSeries->m_series.m_Cseries.value[0] == 0.5e-12 );
642 BOOST_TEST( parsedSeries->m_series.m_RlSeries.value[0] == 0.1 );
643 BOOST_TEST( parsedSeries->m_series.m_RcSeries.value[0] == 1.0 );
644 BOOST_TEST( parsedSeries->m_series.m_LcSeries.value[0] == 0.5e-9 );
645
646 BOOST_TEST( parsedSeries->m_series.m_seriesCurrent.m_entries.size() == 3 );
647 BOOST_TEST( parsedSeries->m_series.m_seriesCurrent.m_entries[0].V == -1.0 );
648 BOOST_TEST( parsedSeries->m_series.m_seriesCurrent.m_entries[0].I.value[0] == -40.0e-3 );
649 BOOST_TEST( parsedSeries->m_series.m_seriesCurrent.m_entries[2].V == 1.0 );
650 BOOST_TEST( parsedSeries->m_series.m_seriesCurrent.m_entries[2].I.value[0] == 40.0e-3 );
651
653 BOOST_TEST( parsedSwitch->m_seriesOn.m_Rseries.value[0] == 5.0 );
654 BOOST_TEST( parsedSwitch->m_seriesOff.m_Rseries.value[0] == 1.0e6 );
655 BOOST_TEST( parsedSwitch->m_seriesOn.m_seriesCurrent.m_entries.size() == 3 );
656 BOOST_TEST( parsedSwitch->m_seriesOn.m_seriesCurrent.m_entries[0].I.value[0] == -200.0e-3 );
657 BOOST_TEST( parsedSwitch->m_seriesOff.m_seriesCurrent.m_entries.size() == 0 );
658
660 BOOST_REQUIRE( parsedMosfet->m_seriesOn.m_seriesMosfet.size() == 1 );
661
662 const IbisMosfetEntry& mosfet = parsedMosfet->m_seriesOn.m_seriesMosfet[0];
663 BOOST_TEST( mosfet.m_Vds == 1.0 );
664 BOOST_REQUIRE( mosfet.m_table.m_entries.size() == 4 );
665 BOOST_TEST( mosfet.m_table.m_entries[0].V == 0.0 );
666 BOOST_TEST( mosfet.m_table.m_entries[3].V == 3.3 );
667 BOOST_TEST( mosfet.m_table.m_entries[3].I.value[0] == 180.0e-3 );
668
669 KIBIS_COMPONENT* comp = top.GetComponent( "SeriesDevice" );
670 BOOST_REQUIRE( comp != nullptr );
671 BOOST_REQUIRE( comp->m_seriesPinMappings.size() == 3 );
672 BOOST_TEST( comp->m_seriesPinMappings[0].m_pin1 == "1" );
673 BOOST_TEST( comp->m_seriesPinMappings[0].m_pin2 == "2" );
674 BOOST_TEST( comp->m_seriesPinMappings[0].m_modelName == "series_r" );
675 BOOST_TEST( comp->m_seriesPinMappings[1].m_modelName == "series_sw" );
676 BOOST_TEST( comp->m_seriesPinMappings[1].m_groupName == "group_a" );
677
678 KIBIS_PIN* pin1 = comp->GetPin( "1" );
679 BOOST_REQUIRE( pin1 != nullptr );
680
681 std::string seriesModelName;
682 KIBIS_PIN* partner = pin1->SeriesPartner( &seriesModelName );
683 BOOST_REQUIRE( partner != nullptr );
684 BOOST_TEST( partner->m_pinNumber == "2" );
685 BOOST_TEST( seriesModelName == "series_r" );
686
687 BOOST_TEST( model->m_series.m_Rseries.value[0] == 25.0 );
688 BOOST_TEST( swModel->m_seriesOn.m_Rseries.value[0] == 5.0 );
689 BOOST_TEST( swModel->m_seriesOff.m_Rseries.value[0] == 1.0e6 );
690 BOOST_TEST( mosfetModel->m_seriesOn.m_seriesMosfet.size() == 1 );
691
692 std::string netlist;
694 BOOST_REQUIRE( pin1->writeSpiceDevice( netlist, "DEVICE_R", *model, kparams ) );
695
696 BOOST_TEST_INFO( "Emitted netlist for series_r:\n" << netlist );
697 BOOST_TEST( netlist.find( ".SUBCKT DEVICE_R PIN_A PIN_B" ) != std::string::npos );
698 BOOST_TEST( netlist.find( "R_S0 DIE_A " ) != std::string::npos );
699 BOOST_TEST( netlist.find( "L_S0 DIE_A " ) != std::string::npos );
700 BOOST_TEST( netlist.find( "C_S0 " ) != std::string::npos );
701 BOOST_TEST( netlist.find( "B_SC0 " ) != std::string::npos );
702 BOOST_TEST( netlist.find( ".ENDS DEVICE" ) != std::string::npos );
703 BOOST_TEST( netlist.find( "SW_STATE" ) == std::string::npos );
704
705 KIBIS_PIN* pin3 = comp->GetPin( "3" );
706 BOOST_REQUIRE( pin3 != nullptr );
707
708 netlist.clear();
709 BOOST_REQUIRE( pin3->writeSpiceDevice( netlist, "DEVICE_SW", *swModel, kparams ) );
710
711 BOOST_TEST_INFO( "Emitted netlist for series_sw:\n" << netlist );
712 BOOST_TEST( netlist.find( ".SUBCKT DEVICE_SW PIN_A PIN_B" ) != std::string::npos );
713 BOOST_TEST( netlist.find( ".param SW_STATE=1" ) != std::string::npos );
714 BOOST_TEST( netlist.find( "R_S1 DIE_A ARM_OUT1" ) != std::string::npos );
715 BOOST_TEST( netlist.find( "R_S2 DIE_A ARM_OUT2" ) != std::string::npos );
716 BOOST_TEST( netlist.find( "R_G1 ARM_OUT1 DIE_B R='0.001 / ((SW_STATE)" ) != std::string::npos );
717 BOOST_TEST( netlist.find( "R_G2 ARM_OUT2 DIE_B R='0.001 / (((1 - SW_STATE))" )
718 != std::string::npos );
719
720 KIBIS_PIN* pin5 = comp->GetPin( "5" );
721 BOOST_REQUIRE( pin5 != nullptr );
722
723 netlist.clear();
724 BOOST_REQUIRE( pin5->writeSpiceDevice( netlist, "DEVICE_M", *mosfetModel, kparams ) );
725
726 BOOST_TEST_INFO( "Emitted netlist for series_mosfet:\n" << netlist );
727 BOOST_TEST( netlist.find( "B_M1_0" ) != std::string::npos );
728 BOOST_TEST( netlist.find( "pwl(" ) != std::string::npos );
729}
730
731
732namespace
733{
734// Wrap an emitted SUBCKT in a 1V .op rig. Returns NaN if ngspice fails.
735double RunSeriesOP( const std::string& aSubckt, const std::string& aSubcktName,
736 const std::string& aExtraParams = "" )
737{
738 auto sim = SPICE_SIMULATOR::CreateInstance( "ngspice" );
739
740 if( !sim )
741 {
742 BOOST_TEST_MESSAGE( "RunSeriesOP: CreateInstance(ngspice) returned null" );
743 return std::nan( "" );
744 }
745
747 sim->SetReporter( &reporter );
748
749 // ngspice is a singleton; clear prior plots/circuits.
750 sim->Command( "bg_halt" );
751 sim->Command( "remcirc" );
752 sim->Command( "destroy all" );
753
754 // 1Ω sense resistor exposes current as a node-voltage delta.
755 std::string deck = "* KiCad QA Series harness\n";
756 deck += "V1 SRC 0 1\n";
757 deck += "R_sense SRC PIN_A 1\n";
758 deck += "V2 PIN_B 0 0\n";
759 deck += "X_dut PIN_A PIN_B " + aSubcktName;
760
761 if( !aExtraParams.empty() )
762 deck += " PARAMS: " + aExtraParams;
763
764 deck += "\n";
765 deck += aSubckt;
766 deck += "\n.save all\n.op\n.end\n";
767
768 if( !sim->LoadNetlist( deck ) )
769 {
770 BOOST_TEST_MESSAGE( "RunSeriesOP: LoadNetlist failed for deck:\n" << deck );
771 return std::nan( "" );
772 }
773
774 if( !sim->Run() )
775 {
776 BOOST_TEST_MESSAGE( "RunSeriesOP: Run() failed" );
777 return std::nan( "" );
778 }
779
780 while( sim->IsRunning() )
781 wxMilliSleep( 20 );
782
783 // bg callbacks may still fire briefly after IsRunning() flips.
784 sim->SetReporter( nullptr );
785
786 BOOST_TEST_MESSAGE( "RunSeriesOP: ngspice log:\n" << reporter.GetMessages() );
787 BOOST_TEST_MESSAGE( "RunSeriesOP: current plot = " << sim->CurrentPlotName().ToStdString() );
788
789 // Node voltages survive plot indirection that branch currents do not.
790 std::vector<double> vSrc = sim->GetRealVector( "src" );
791 std::vector<double> vPinA = sim->GetRealVector( "pin_a" );
792
793 if( vSrc.empty() || vPinA.empty() )
794 {
795 BOOST_TEST_MESSAGE( "RunSeriesOP: node-voltage vectors unavailable. Available:" );
796
797 for( const std::string& name : sim->AllVectors() )
798 BOOST_TEST_MESSAGE( " " << name );
799
800 return std::nan( "" );
801 }
802
803 return ( vSrc.back() - vPinA.back() ) / 1.0;
804}
805} // namespace
806
807
808// End-to-end ngspice .op against the emitted SUBCKT. Disabled by default;
809// ngspice singleton state from prior suites can segfault subsequent runs.
810BOOST_AUTO_TEST_CASE( Run_v4_1_RSeries_Ngspice, * boost::unit_test::disabled() )
811{
813 std::string path = GetLibraryPath( "ibis_v4_1_r_series" );
814 KIBIS top( path, &reporter );
815
816 BOOST_REQUIRE( top.m_valid );
817
818 KIBIS_COMPONENT* comp = top.GetComponent( "SeriesDevice" );
820
822
823 // Cold-start warmup: ngspice singleton can drop the first .op otherwise.
824 {
825 auto warmup = SPICE_SIMULATOR::CreateInstance( "ngspice" );
826
827 if( warmup && warmup->LoadNetlist( "* warmup\nR1 1 0 1k\nV1 1 0 1\n.op\n.end\n" )
828 && warmup->Run() )
829 {
830 while( warmup->IsRunning() )
831 wxMilliSleep( 20 );
832 }
833 }
834
835 // Branches parallel per BIRD 41.8; L+Rl path (Rl=0.1Ω) dominates DC.
836 // Expect 0 < I < ~2A; exact value covered by static asserts.
837 {
838 KIBIS_PIN* pinA = comp->GetPin( "1" );
839 KIBIS_MODEL* model = top.GetModel( "series_r" );
841
842 std::string subckt;
843 BOOST_REQUIRE( pinA->writeSpiceDevice( subckt, "DEV_R", *model, kparams ) );
844
845 double iSeries = RunSeriesOP( subckt, "DEV_R" );
846
847 if( std::isnan( iSeries ) )
848 {
849 BOOST_TEST_MESSAGE( "ngspice unavailable; skipping Series .op" );
850 }
851 else
852 {
853 BOOST_TEST_INFO( "Series device .op current = " << iSeries );
855 BOOST_TEST( iSeries < 2.0 );
856 }
857 }
858
859 // Series_switch: On state 5Ω + 200 mA IV table; Off state 1 MΩ.
860 {
861 KIBIS_PIN* pinB = comp->GetPin( "3" );
862 KIBIS_MODEL* model = top.GetModel( "series_sw" );
864
865 std::string subckt;
867
868 double iOn = RunSeriesOP( subckt, "DEV_SW", "SW_STATE=1" );
869 double iOff = RunSeriesOP( subckt, "DEV_SW", "SW_STATE=0" );
870
871 if( std::isnan( iOn ) || std::isnan( iOff ) )
872 {
873 BOOST_TEST_MESSAGE( "ngspice unavailable; skipping Series_switch .op" );
874 }
875 else
876 {
877 BOOST_TEST_INFO( "SW On current = " << iOn << ", Off current = " << iOff );
878 BOOST_TEST( iOn > 0.1 );
879 BOOST_TEST( iOff < 1.0e-5 );
880 BOOST_TEST( iOn / iOff > 1.0e4 );
881 }
882 }
883}
884
885
886namespace
887{
888// Load fixture and return the SeriesDevice's SIM_MODEL_IBIS.
889std::unique_ptr<SIM_LIBRARY_IBIS> MakeLoadedSeriesLibrary( const std::string& aIbsPath,
890 SIM_MODEL_IBIS** aOutModel )
891{
892 auto lib = std::make_unique<SIM_LIBRARY_IBIS>();
894 lib->ReadFile( aIbsPath, reporter );
895
896 if( reporter.HasMessageOfSeverity( RPT_SEVERITY_ERROR ) )
897 return nullptr;
898
899 for( const SIM_LIBRARY::MODEL& sm : lib->GetModels() )
900 {
901 SIM_MODEL_IBIS* candidate = dynamic_cast<SIM_MODEL_IBIS*>( &sm.model );
902
903 if( candidate && candidate->GetComponentName() == "SeriesDevice" )
904 {
905 *aOutModel = candidate;
906 return lib;
907 }
908 }
909
910 return nullptr;
911}
912} // namespace
913
914
915// SetIbisModel picks SERIES IO mode and resolves the [Series Pin Mapping] partner.
916BOOST_AUTO_TEST_CASE( Dialog_Series_PinMap_v4_1 )
917{
918 SIM_MODEL_IBIS* ibisModel = nullptr;
919 auto lib = MakeLoadedSeriesLibrary( GetLibraryPath( "ibis_v4_1_r_series" ), &ibisModel );
920
921 BOOST_REQUIRE( lib );
922 BOOST_REQUIRE( ibisModel );
923
924 BOOST_REQUIRE( ibisModel->ChangePin( *lib, "1" ) );
925
926 BOOST_TEST( !ibisModel->IsSeries() );
927 BOOST_TEST( ibisModel->GetPinCount() == 2 );
928 BOOST_TEST( ibisModel->GetPin( 0 ).modelPinName == "GND" );
929 BOOST_TEST( ibisModel->GetPin( 1 ).modelPinName == "IN/OUT" );
930
931 BOOST_REQUIRE( ibisModel->SetIbisModel( *lib, "1", "series_r" ) );
932
933 BOOST_TEST( ibisModel->IsSeries() );
934 BOOST_TEST( (int) ibisModel->GetIOMode() == (int) IBIS_IO_MODE::SERIES );
935 BOOST_TEST( ibisModel->GetPinCount() == 2 );
936 BOOST_TEST( ibisModel->GetPin( 0 ).modelPinName == "PIN_A" );
937 BOOST_TEST( ibisModel->GetPin( 1 ).modelPinName == "PIN_B" );
938 BOOST_TEST( ibisModel->GetSeriesPartnerPin() == "2" );
939 BOOST_TEST( ibisModel->FindParam( "sw_state" ) == nullptr );
940
941 // Series → single-ended round-trip must drop the SERIES layout.
942 BOOST_REQUIRE( ibisModel->SetIbisModel( *lib, "1", "series_r" ) );
943 ibisModel->SwitchSingleEndedDiff( false );
944 BOOST_TEST( !ibisModel->IsSeries() );
945 BOOST_TEST( ibisModel->GetPin( 0 ).modelPinName == "GND" );
946 BOOST_TEST( ibisModel->FindParam( "sw_state" ) == nullptr );
947}
948
949
950// Series_switch carries a sw_state instance param (default 1) onto the X-line.
951BOOST_AUTO_TEST_CASE( Dialog_Series_Switch_Params_v4_1 )
952{
953 SIM_MODEL_IBIS* ibisModel = nullptr;
954 auto lib = MakeLoadedSeriesLibrary( GetLibraryPath( "ibis_v4_1_r_series" ), &ibisModel );
955
956 BOOST_REQUIRE( lib );
957 BOOST_REQUIRE( ibisModel );
958 BOOST_REQUIRE( ibisModel->ChangePin( *lib, "3" ) );
959 BOOST_REQUIRE( ibisModel->SetIbisModel( *lib, "3", "series_sw" ) );
960
961 BOOST_TEST( ibisModel->IsSeries() );
962 BOOST_TEST( ibisModel->GetSeriesPartnerPin() == "4" );
963
964 const SIM_MODEL::PARAM* sw = ibisModel->FindParam( "sw_state" );
965 BOOST_REQUIRE( sw != nullptr );
967 BOOST_TEST( sw->info.spiceInstanceName == "SW_STATE" );
968 BOOST_TEST( sw->info.defaultValue == "1" );
969
970 ibisModel->SetParamValue( "sw_state", "0.5" );
971
972 std::string itemParams = ibisModel->SpiceGenerator().ItemParams();
973 BOOST_TEST_INFO( "Emitted ItemParams: " << itemParams );
974 BOOST_TEST( itemParams.find( "SW_STATE=0.5" ) != std::string::npos );
975
976 // Waveform-choice path copy-constructs the model; sw_state must come along.
977 {
978 ibisModel->SetParamValue( "sw_state", "0.25" );
979 SIM_MODEL_IBIS copy( SIM_MODEL::TYPE::KIBIS_DEVICE, *ibisModel );
980
981 BOOST_TEST( copy.IsSeries() );
982 BOOST_TEST( copy.GetSeriesPartnerPin() == "4" );
983
984 const SIM_MODEL::PARAM* copiedSw = copy.FindParam( "sw_state" );
985 BOOST_REQUIRE( copiedSw != nullptr );
986 BOOST_TEST( copiedSw->value == "0.25" );
987 }
988
989 BOOST_REQUIRE( ibisModel->SetIbisModel( *lib, "1", "series_r" ) );
990 BOOST_TEST( ibisModel->FindParam( "sw_state" ) == nullptr );
991}
992
993
994// Two-port SUBCKT round-trip through ngspice. Disabled by default — see
995// Run_v4_1_RSeries_Ngspice.
996BOOST_AUTO_TEST_CASE( Run_Series_Schematic_Ngspice, * boost::unit_test::disabled() )
997{
999 std::string path = GetLibraryPath( "ibis_v4_1_r_series" );
1000 KIBIS top( path, &reporter );
1001 BOOST_REQUIRE( top.m_valid );
1002
1003 KIBIS_COMPONENT* comp = top.GetComponent( "SeriesDevice" );
1004 KIBIS_PIN* pinA = comp ? comp->GetPin( "1" ) : nullptr;
1005 KIBIS_MODEL* model = top.GetModel( "series_r" );
1006 BOOST_REQUIRE( pinA && model );
1007
1009 std::string subckt;
1010 BOOST_REQUIRE( pinA->writeSpiceDevice( subckt, "DEV_R", *model, kparams ) );
1011
1012 // Header must be two-port; a stray GND there breaks X-line port mapping.
1013 BOOST_TEST( subckt.find( ".SUBCKT DEV_R PIN_A PIN_B" ) != std::string::npos );
1014 BOOST_TEST( subckt.find( ".SUBCKT DEV_R GND" ) == std::string::npos );
1015
1018
1019 std::string deck = "* QA harness for two-port Series subckt\n";
1020 deck += "V1 SRC 0 1\n";
1021 deck += "R_sense SRC PIN_A 1\n";
1022 deck += "X_dut PIN_A 0 DEV_R\n"; // PIN_B tied to global ground via 0
1023 deck += subckt;
1024 deck += "\n.save all\n.op\n.end\n";
1025
1026 sim->Command( "bg_halt" );
1027 sim->Command( "remcirc" );
1028 sim->Command( "destroy all" );
1029
1030 if( !sim->LoadNetlist( deck ) || !sim->Run() )
1031 {
1032 BOOST_TEST_MESSAGE( "ngspice unavailable; skipping Run_Series_Schematic_Ngspice .op" );
1033 return;
1034 }
1035
1036 while( sim->IsRunning() )
1037 wxMilliSleep( 20 );
1038
1039 std::vector<double> vSrc = sim->GetRealVector( "src" );
1040 std::vector<double> vA = sim->GetRealVector( "pin_a" );
1041
1042 if( vSrc.empty() || vA.empty() )
1043 {
1044 BOOST_TEST_MESSAGE( "ngspice OP vectors unavailable; skipping current check" );
1045 return;
1046 }
1047
1048 double iDevice = ( vSrc.back() - vA.back() ) / 1.0;
1049 BOOST_TEST_INFO( "Two-port Series .op current = " << iDevice );
1051 BOOST_TEST( iDevice < 2.0 );
1052}
1053
1054
1055// Regression test for https://gitlab.com/kicad/code/kicad/-/issues/23583
1056// A rectangular-wave driver on a model with exactly two waveform pairs (the
1057// common case, e.g. the bundled IBIS demo) used to emit the spurious warning
1058// "Model has more than 2 waveform pairs, using the first two." The warning
1059// fired because the default accuracy is LEVEL_2 and the emission condition
1060// OR-ed in "accuracy <= LEVEL_2", so it triggered even when nothing was
1061// discarded. Any simulation warning pops a modal dialog on every run, so the
1062// user saw an error message each time the simulation started.
1063BOOST_AUTO_TEST_CASE( RectangularDriver_TwoWaveformPairs_NoSpuriousWarning )
1064{
1066
1067 std::string path = GetLibraryPath( "ibis_v5_1" );
1068 KIBIS top( path, &reporter );
1069
1070 BOOST_REQUIRE( top.m_valid );
1071
1072 KIBIS_COMPONENT* comp = top.GetComponent( "Virtual" );
1073 BOOST_REQUIRE( comp != nullptr );
1074
1075 // Pin B1 maps to model AC40, an OUTPUT driver with two waveform pairs.
1076 KIBIS_PIN* pin = comp->GetPin( "B1" );
1077 KIBIS_MODEL* model = top.GetModel( "AC40" );
1078 BOOST_REQUIRE( pin != nullptr );
1079 BOOST_REQUIRE( model != nullptr );
1080
1081 // The whole point of the bug is that exactly two pairs are present, so
1082 // nothing is being discarded and no warning is warranted.
1083 BOOST_TEST( model->waveformPairs().size() == 2 );
1084
1086 waveform->m_ton = 20e-9;
1087 waveform->m_toff = 50e-9;
1088 waveform->m_delay = 10e-9;
1089 waveform->m_cycles = 1;
1090
1092 kparams.m_waveform = waveform;
1093
1094 std::string result;
1095
1096 // writeSpiceDriver emits the waveform-pair warning before delegating to the
1097 // two-waveform Ku/Kd extraction, which spins up ngspice. ngspice has no
1098 // settings object in the QA harness, so that step throws a wxASSERT. The
1099 // warning we are checking for is already in the reporter by then, so swallow
1100 // only that assertion and inspect what was reported up to that point. Any
1101 // other exception is unexpected and must fail the test.
1102 try
1103 {
1104 pin->writeSpiceDriver( result, "DRIVER", *model, kparams );
1105 }
1106 catch( const KI_TEST::WX_ASSERT_ERROR& )
1107 {
1108 }
1109
1110 BOOST_TEST_INFO( "Reported: " << reporter.GetMessages() );
1111
1112 // The discard warning must not appear when exactly two pairs are present.
1113 BOOST_TEST( reporter.GetMessages().Find( wxS( "more than 2 waveform pairs" ) ) == wxNOT_FOUND );
1114
1115 delete waveform;
1116}
1117
1118
const char * name
void Report(const std::string &aMsg, SEVERITY aSeverity=RPT_SEVERITY_INFO) const
Print a message.
Definition ibis_parser.h:70
REPORTER * m_Reporter
Definition ibis_parser.h:77
std::string m_name
bool m_valid
Definition kibis.h:57
bool writeSpiceDevice(std::string &aDest, const std::string &aName, KIBIS_MODEL &aModel, const KIBIS_PARAMETER &aParam)
Definition kibis.cpp:1507
Definition kibis.h:513
An exception class to represent a WX assertion.
Definition wx_assert.h:43
static std::shared_ptr< SPICE_SIMULATOR > CreateInstance(const std::string &aName)
bool SetIbisModel(const SIM_LIBRARY_IBIS &aLib, const std::string &aPinNumber, const std::string &aModelName)
Bind to a KIBIS model, set IO mode from its type, manage sw_state.
void SwitchSingleEndedDiff(bool aDiff) override
IBIS_IO_MODE GetIOMode() const
bool IsSeries() const
const std::string & GetSeriesPartnerPin() const
bool ChangePin(const SIM_LIBRARY_IBIS &aLib, const std::string &aPinNumber)
update the list of available models based on the pin number.
std::string GetComponentName() const
int GetPinCount() const
Definition sim_model.h:478
const SPICE_GENERATOR & SpiceGenerator() const
Definition sim_model.h:429
const PARAM * FindParam(const std::string &aParamName) const
void SetParamValue(int aParamIndex, const std::string &aValue, SIM_VALUE::NOTATION aNotation=SIM_VALUE::NOTATION::SI)
const SIM_MODEL_PIN & GetPin(unsigned aIndex) const
Definition sim_model.h:479
virtual std::string ItemParams() const
A wrapper for reporting to a wxString object.
Definition reporter.h:225
std::string GetEeschemaTestDataDir()
Get the configured location of Eeschema test data.
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
std::string defaultValue
Definition sim_model.h:380
std::string spiceInstanceName
Definition sim_model.h:385
std::string value
Definition sim_model.h:398
const INFO & info
Definition sim_model.h:399
const std::string modelPinName
Definition sim_model.h:68
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_AUTO_TEST_SUITE_END()
double iDevice
std::string deck
BOOST_TEST(netlist.find("R_G1 ARM_OUT1 DIE_B R='0.001 / ((SW_STATE)") !=std::string::npos)
std::string netlist
double iOff
KIBIS_PIN * pin3
std::string subckt
auto sim
std::string path
IbisParser parser & reporter
BOOST_AUTO_TEST_CASE(Null)
std::string seriesModelName
KIBIS_PIN * partner
KIBIS_MODEL * swModel
double iSeries
double iOn
KIBIS top(path, &reporter)
KIBIS_PIN * pin1
KIBIS_MODEL * model
const IbisMosfetEntry & mosfet
std::vector< double > vSrc
KIBIS_PARAMETER kparams
std::vector< double > vA
KIBIS_PIN * pin5
const IbisModel * parsedSwitch
const IbisModel * parsedMosfet
KIBIS_COMPONENT * comp
KIBIS_MODEL * mosfetModel
const IbisModel * parsedSeries
KIBIS_PIN * pin
BOOST_TEST_INFO("Two-port Series .op current = "<< iDevice)
BOOST_REQUIRE(comp !=nullptr)
KIBIS_PIN * pinA
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")
wxString result
Test unit parsing edge cases and error handling.