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