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