KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_sim_regressions.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#include <boost/test/results_collector.hpp> // To check if the current test failed (to be moved?).
22#include <eeschema_test_utils.h>
26#include <sim/spice_generator.h>
27#include <richio.h>
28#include <reporter.h>
29#include <wx/ffile.h>
30#include <wx/filename.h>
31#include <wx/tokenzr.h>
32#include <mock_pgm_base.h>
33#include <locale_io.h>
34#include <set>
35
36
37namespace
38{
39// The exporter emits absolute, machine-specific paths, so tests compare `.include` directives on
40// the file name only.
41std::set<wxString> collectIncludeFileNames( const wxString& aNetlist )
42{
43 std::set<wxString> names;
44 wxStringTokenizer lines( aNetlist, wxS( "\n" ), wxTOKEN_RET_EMPTY_ALL );
45
46 while( lines.HasMoreTokens() )
47 {
48 wxString line = lines.GetNextToken();
49
50 if( line.StartsWith( wxS( ".include " ) ) )
51 {
52 wxFileName fn( line.AfterFirst( '"' ).BeforeLast( '"' ) );
53 names.insert( fn.GetFullName() );
54 }
55 }
56
57 return names;
58}
59} // namespace
60
61
63{
64public:
69
73
74 wxFileName SchematicQAPath( const wxString& aBaseName ) override
75 {
76 wxFileName fn( KI_TEST::GetEeschemaTestDataDir() );
77 fn.SetName( aBaseName );
79
80 return fn;
81 }
82
83 wxString GetNetlistPath( bool aTest = false ) override
84 {
85 wxFileName netFile = m_schematic->Project().GetProjectFullName();
86
87 if( aTest )
88 netFile.SetName( netFile.GetName() + "_test" );
89
90 netFile.SetExt( "spice" );
91 return netFile.GetFullPath();
92 }
93
111
112public:
114 bool m_SaveVoltages = true;
115 bool m_SaveCurrents = true;
116};
117
118
120{
122
123 // const MOCK_PGM_BASE& program = static_cast<MOCK_PGM_BASE&>( Pgm() );
124 // MOCK_EXPECT( program.GetLocalEnvVariables ).returns( ENV_VAR_MAP() );
125
126 TestNetlist( "issue13591" );
127 TestTranPoint( 100e-6, { { "I(R1)", 0 }, { "I(R2)", 0 } }, 0.00001 );
128 TestTranPoint( 500e-6, { { "I(R1)", 0 }, { "I(R2)", 0 } }, 0.00001 );
129}
130
131
133{
135
136 m_SaveCurrents = false;
137
138 TestNetlist( "issue13431" );
139 TestTranPoint( 0.005, { { "V(/soft_start)", 2.489 } } );
140 TestTranPoint( 0.012, { { "V(/soft_start)", 5.100 } } );
141}
142
143
144// This test is flaky and fails on ngspice-42 / Linux.
145// Please replace it with something that is more stable
146#if 0
148{
150
151 const MOCK_PGM_BASE& program = static_cast<MOCK_PGM_BASE&>( Pgm() );
152 MOCK_EXPECT( program.GetLocalEnvVariables ).returns( ENV_VAR_MAP() );
153
154 TestNetlist( "issue13112" );
155 TestTranPoint( 0.01, { { "V(out)", -0.060 } } );
156 TestTranPoint( 0.02, { { "V(out)", 0.856 } } );
157}
158#endif
159
160
162{
164
165 // const MOCK_PGM_BASE& program = static_cast<MOCK_PGM_BASE&>( Pgm() );
166 // MOCK_EXPECT( program.GetLocalEnvVariables ).returns( ENV_VAR_MAP() );
167
168 TestNetlist( "issue13162" );
169 TestTranPoint( 0.030, { { "V(out)", 0.000829682 } } );
170 TestTranPoint( 0.035, { { "V(out)", -0.000829692 } } );
171}
172
173
175{
177
178 // const MOCK_PGM_BASE& program = static_cast<MOCK_PGM_BASE&>( Pgm() );
179 // MOCK_EXPECT( program.GetLocalEnvVariables ).returns( ENV_VAR_MAP() );
180
181 TestNetlist( "issue12505" );
182 TestTranPoint( 0.015, { { "V(Net-_R1-Pad2_)", -311 } } );
183 TestTranPoint( 0.025, { { "V(Net-_R1-Pad2_)", 311 } } );
184}
185
186
188{
190
191 // const MOCK_PGM_BASE& program = static_cast<MOCK_PGM_BASE&>( Pgm() );
192 // MOCK_EXPECT( program.GetLocalEnvVariables ).returns( ENV_VAR_MAP() );
193
194 TestNetlist( "issue16223" );
195 TestTranPoint( 0.0, { { "V(PRBS_OUTPUT)", 5.114 } } );
196 TestTranPoint( 1e-6, { { "V(PRBS_OUTPUT)", -0.1144 } } );
197}
198
199
200// An IBIS driver generates a per-reference <ref>.cache device that must be pulled into the netlist
201// as a `.include`. The include is supplied solely by SIM_MODEL_IBIS::GetSpiceIncludes(), so this
202// guards it independently of the simulator.
204{
206
207 LoadSchematic( SchematicQAPath( wxS( "issue16223" ) ) );
208 WriteNetlist();
209
210 wxFFile netlistFile( GetNetlistPath( true ), "rt" );
211 BOOST_REQUIRE( netlistFile.IsOpened() );
212
213 wxString netlist;
214 netlistFile.ReadAll( &netlist );
215 netlistFile.Close();
216
217 BOOST_TEST_INFO( "Netlist:\n" << netlist );
218
219 std::set<wxString> includes = collectIncludeFileNames( netlist );
220
221 // The fixture carries six IBIS symbols; asserting the exact names pins the per-reference
222 // cache naming.
223 for( const wxString& ref : { wxS( "U1" ), wxS( "U2" ), wxS( "U3" ),
224 wxS( "U4" ), wxS( "U5" ), wxS( "U6" ) } )
225 {
226 wxString cacheName = ref + wxS( ".cache" );
227
228 BOOST_CHECK_MESSAGE( includes.count( cacheName ) == 1,
229 "IBIS cache device " << cacheName << " was not emitted as a .include" );
230 }
231
232 Cleanup();
233}
234
235
237{
239
240 LoadSchematic( SchematicQAPath( wxS( "issue13591" ) ) );
241
242 SPICE_CIRCUIT_MODEL model( m_schematic.get() );
243 STRING_FORMATTER formatter;
244
245 const wxString fftCommand = wxS( "linearize v(/out)\nfft v(/out)" );
246
247 BOOST_REQUIRE( model.GetNetlist( fftCommand, GetNetlistOptions(), &formatter, *m_reporter ) );
248
249 wxString netlist( formatter.GetString().c_str(), wxConvUTF8 );
250 wxStringTokenizer lines( netlist, wxS( "\n" ), wxTOKEN_RET_EMPTY_ALL );
251 bool inControl = false;
252
253 while( lines.HasMoreTokens() )
254 {
255 wxString line = lines.GetNextToken().Trim( false ).Trim( true ).Lower();
256
257 if( line.IsSameAs( wxS( ".control" ) ) )
258 inControl = true;
259 else if( line.IsSameAs( wxS( ".endc" ) ) )
260 inControl = false;
261 else if( !inControl )
262 BOOST_CHECK_MESSAGE( !line.StartsWith( wxS( "linearize" ) ) && !line.StartsWith( wxS( "fft" ) ),
263 "Bare control command leaked into netlist: " << line );
264 }
265}
266
267
268// A raw-Spice model that carries a library path must offer it back through GetSpiceIncludes() so
269// the exporter can emit it as a `.include`. No schematic fixture reaches this path, because any
270// resolvable library gets registered and emitted through the SPICE library path instead.
271BOOST_AUTO_TEST_CASE( RawSpiceModelSuppliesLibraryInclude )
272{
274 SPICE_ITEM item;
275
276 BOOST_CHECK( model.GetSpiceIncludes( item, nullptr, NULL_REPORTER::GetInstance() ).empty() );
277
278 model.SetParamValue( "lib", "device.lib" );
279
280 std::vector<wxString> includes = model.GetSpiceIncludes( item, nullptr,
282
283 BOOST_REQUIRE_EQUAL( includes.size(), 1u );
284 BOOST_CHECK_EQUAL( includes.front(), wxString( wxS( "device.lib" ) ) );
285}
286
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:37
static REPORTER & GetInstance()
Definition reporter.cpp:179
Special netlist exporter flavor that allows one to override simulation commands.
Implement an OUTPUTFORMATTER to a memory buffer.
Definition richio.h:418
const std::string & GetString()
Definition richio.h:441
wxFileName SchematicQAPath(const wxString &aBaseName) override
wxString GetNetlistPath(bool aTest=false) override
static const std::string KiCadSchematicFileExtension
std::map< wxString, ENV_VAR_ITEM > ENV_VAR_MAP
std::string GetEeschemaTestDataDir()
Get the configured location of Eeschema test data.
PGM_BASE & Pgm()
The global program "get" accessor.
static void LoadSchematic(SCHEMATIC *aSchematic, SCH_SHEET *aRootSheet, const wxString &aFileName)
PGM_SINGLE_TOP program
std::vector< FAB_LAYER_COLOR > dummy
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
std::string netlist
KIBIS_MODEL * model
BOOST_TEST_INFO("Two-port Series .op current = "<< iDevice)
BOOST_FIXTURE_TEST_CASE(WindowsPaths, TEST_SIM_REGRESSIONS_FIXTURE)
BOOST_AUTO_TEST_CASE(RawSpiceModelSuppliesLibraryInclude)
BOOST_CHECK_EQUAL(result, "25.4")