KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_sim_model_source_pwl.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, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
25#include <reporter.h>
26#include <sim/sim_model.h>
27#include <sim/spice_generator.h>
28
29
30// Regression coverage for issue #24050: PWL sources must emit scale prefixes (u, m, k, Meg)
31// and pass simulator parameter references through to ngspice.
32
34{
35public:
36 std::string GeneratePwlItemLine( SIM_MODEL::TYPE aType, const std::string& aPwlValue ) const
37 {
38 WX_STRING_REPORTER reporter;
39 std::vector<SCH_PIN*> pins;
40 std::unique_ptr<SIM_MODEL> model = SIM_MODEL::Create( aType, pins, reporter );
41
43 model->SetParamValue( "pwl", aPwlValue );
44
45 SPICE_ITEM item;
46 item.refName = "1";
47 item.pinNetNames = { "a", "b" };
48 item.model = model.get();
49
50 return model->SpiceGenerator().ItemLine( item );
51 }
52};
53
54
55BOOST_FIXTURE_TEST_SUITE( SimModelSourcePwl, TEST_SIM_MODEL_SOURCE_PWL_FIXTURE )
56
57
58BOOST_AUTO_TEST_CASE( PwlPlainNumbers )
59{
60 const std::string out = GeneratePwlItemLine( SIM_MODEL::TYPE::V_PWL, "0 0 1 1 2 0" );
61 BOOST_TEST_INFO( out );
62 BOOST_CHECK( out.find( "PWL(" ) != std::string::npos );
63 BOOST_CHECK( out.find( "0 0 1 1 2 0" ) != std::string::npos );
64}
65
66
67BOOST_AUTO_TEST_CASE( PwlMicroPrefix )
68{
69 // Issue #24050: "1u 0 2u 1" must survive netlist generation.
70 const std::string out = GeneratePwlItemLine( SIM_MODEL::TYPE::V_PWL, "0 0 1u 0 2u 1" );
71 BOOST_TEST_INFO( out );
72 BOOST_CHECK( out.find( "1u" ) != std::string::npos );
73 BOOST_CHECK( out.find( "2u" ) != std::string::npos );
74 BOOST_CHECK( out.find( "PWL( )" ) == std::string::npos );
75}
76
77
78BOOST_AUTO_TEST_CASE( PwlMilliPrefix )
79{
80 const std::string out = GeneratePwlItemLine( SIM_MODEL::TYPE::V_PWL, "0 0 1m 1 2m 0" );
81 BOOST_TEST_INFO( out );
82 BOOST_CHECK( out.find( "1m" ) != std::string::npos );
83 BOOST_CHECK( out.find( "PWL( )" ) == std::string::npos );
84}
85
86
87BOOST_AUTO_TEST_CASE( PwlMegaPrefix )
88{
89 // KiCad SI notation uses "M" for mega; ngspice requires "Meg".
90 const std::string out = GeneratePwlItemLine( SIM_MODEL::TYPE::V_PWL, "0 0 1M 1" );
91 BOOST_TEST_INFO( out );
92 BOOST_CHECK( out.find( "1Meg" ) != std::string::npos );
93}
94
95
96BOOST_AUTO_TEST_CASE( PwlParameterReference )
97{
98 // Issue #24050: "{t_start}" parameter references must pass through to ngspice.
99 const std::string out = GeneratePwlItemLine( SIM_MODEL::TYPE::V_PWL, "0 0 {t_start} 1" );
100 BOOST_TEST_INFO( out );
101 BOOST_CHECK( out.find( "{t_start}" ) != std::string::npos );
102 BOOST_CHECK( out.find( "PWL( )" ) == std::string::npos );
103}
104
105
106BOOST_AUTO_TEST_CASE( PwlMixedParamsAndPrefixes )
107{
108 const std::string out = GeneratePwlItemLine( SIM_MODEL::TYPE::V_PWL,
109 "0 0 {t_rise} 1u {t_fall} 0" );
110 BOOST_TEST_INFO( out );
111 BOOST_CHECK( out.find( "{t_rise}" ) != std::string::npos );
112 BOOST_CHECK( out.find( "{t_fall}" ) != std::string::npos );
113 BOOST_CHECK( out.find( "1u" ) != std::string::npos );
114}
115
116
117BOOST_AUTO_TEST_CASE( IpwlPrefixesAndParams )
118{
119 const std::string out = GeneratePwlItemLine( SIM_MODEL::TYPE::I_PWL,
120 "0 0 1u 500m {t_end} 1" );
121 BOOST_TEST_INFO( out );
122 BOOST_CHECK( out.find( "1u" ) != std::string::npos );
123 BOOST_CHECK( out.find( "500m" ) != std::string::npos );
124 BOOST_CHECK( out.find( "{t_end}" ) != std::string::npos );
125}
126
127
128BOOST_AUTO_TEST_CASE( PwlBraceExpressionWithSpaces )
129{
130 // Brace expressions may contain whitespace; they must not be split by the tokenizer.
131 const std::string out = GeneratePwlItemLine( SIM_MODEL::TYPE::V_PWL,
132 "0 0 {t_start + 1u} 1" );
133 BOOST_TEST_INFO( out );
134 BOOST_CHECK( out.find( "{t_start + 1u}" ) != std::string::npos );
135 BOOST_CHECK( out.find( "PWL( )" ) == std::string::npos );
136}
137
138
139BOOST_AUTO_TEST_CASE( PwlNestedBraces )
140{
141 const std::string out = GeneratePwlItemLine( SIM_MODEL::TYPE::V_PWL,
142 "0 0 {max( {t_a}, {t_b} )} 1" );
143 BOOST_TEST_INFO( out );
144 BOOST_CHECK( out.find( "{max( {t_a}, {t_b} )}" ) != std::string::npos );
145}
146
147
148BOOST_AUTO_TEST_CASE( PwlBraceMegaPrefix )
149{
150 // KiCad's 'M' is mega; ngspice reads 'M' as milli. A brace expression must rewrite
151 // numeric literals so the value matches the same number written outside braces.
152 const std::string out = GeneratePwlItemLine( SIM_MODEL::TYPE::V_PWL,
153 "0 0 {t_start + 1M} 1" );
154 BOOST_TEST_INFO( out );
155 BOOST_CHECK( out.find( "1Meg" ) != std::string::npos );
156 BOOST_CHECK( out.find( "1M}" ) == std::string::npos );
157}
158
159
160BOOST_AUTO_TEST_CASE( PwlBracePreservesIdentifiersAndOperators )
161{
162 // Identifiers, operators, and whitespace inside braces must pass through untouched
163 // even when the expression contains numeric literals to rewrite.
164 const std::string out = GeneratePwlItemLine( SIM_MODEL::TYPE::V_PWL,
165 "0 0 {t_start + 1u * scale} 1" );
166 BOOST_TEST_INFO( out );
167 BOOST_CHECK( out.find( "{t_start + 1u * scale}" ) != std::string::npos );
168}
169
170
171BOOST_AUTO_TEST_CASE( PwlBraceLeavesExistingMegSpelling )
172{
173 // A user who already typed ngspice's 'Meg' inside a brace must not see it mangled.
174 const std::string out = GeneratePwlItemLine( SIM_MODEL::TYPE::V_PWL,
175 "0 0 {1Meg + t_start} 1" );
176 BOOST_TEST_INFO( out );
177 BOOST_CHECK( out.find( "{1Meg + t_start}" ) != std::string::npos );
178}
179
180
static std::unique_ptr< SIM_MODEL > Create(TYPE aType, const std::vector< SCH_PIN * > &aPins, REPORTER &aReporter)
std::string GeneratePwlItemLine(SIM_MODEL::TYPE aType, const std::string &aPwlValue) const
A wrapper for reporting to a wxString object.
Definition reporter.h:193
std::string refName
const SIM_MODEL * model
std::vector< std::string > pinNetNames
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
KIBIS_MODEL * model
BOOST_TEST_INFO("Parsed: "<< path)
BOOST_AUTO_TEST_CASE(PwlPlainNumbers)