kicad/qa/tests/spice/test_sim_model_ngspice.cpp

311 lines
12 KiB
C++

/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 KiCad Developers, see AUTHORS.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <qa_utils/wx_utils/unit_test_utils.h>
#include <sim/sim_model_ngspice.h>
#include <boost/algorithm/string/predicate.hpp>
class TEST_SIM_MODEL_NGSPICE_FIXTURE : public SIM_MODEL_NGSPICE
{
public:
TEST_SIM_MODEL_NGSPICE_FIXTURE() :
SIM_MODEL_NGSPICE( TYPE::NONE )
{}
};
BOOST_FIXTURE_TEST_SUITE( SimModelNgspice, TEST_SIM_MODEL_NGSPICE_FIXTURE )
BOOST_AUTO_TEST_CASE( ParamDuplicates )
{
for( MODEL_TYPE type : MODEL_TYPE_ITERATOR() )
{
BOOST_TEST_CONTEXT( "Model name: " << ModelInfo( type ).name )
{
const std::vector<SIM_MODEL::PARAM::INFO> modelParams = ModelInfo( type ).modelParams;
const std::vector<SIM_MODEL::PARAM::INFO> instanceParams = ModelInfo( type ).instanceParams;
for( const SIM_MODEL::PARAM::INFO& modelParam : modelParams )
{
BOOST_TEST_CONTEXT( "Model param name: " << modelParam.name )
{
// Ensure there's no model parameters that have the same name.
BOOST_CHECK( std::none_of( modelParams.begin(), modelParams.end(),
[modelParam]( const auto& aOtherModelParam )
{
return modelParam.id != aOtherModelParam.id
&& modelParam.name == aOtherModelParam.name;
} ) );
// Ensure there's no model parameters that have the same name as an instance parameter.
BOOST_CHECK( std::none_of( instanceParams.begin(), instanceParams.end(),
[modelParam]( const auto& aInstanceParam )
{
return modelParam.name == aInstanceParam.name;
} ) );
if( boost::ends_with( modelParam.name, "_" ) )
{
// Ensure that for each model parameter ending with a "_" there exists an
// instance parameter with the same name but without this final character.
// We append an "_" to model parameters to disambiguate from these
// corresponding instance parameters.
BOOST_CHECK( std::any_of( instanceParams.begin(), instanceParams.end(),
[modelParam]( const auto& aInstanceParam )
{
return modelParam.name.substr( 0, modelParam.name.length() - 1 )
== aInstanceParam.name;
} ) );
}
}
}
// Ensure there's no instance parameters that have the same name.
for( const SIM_MODEL::PARAM::INFO& instanceParam : instanceParams )
{
BOOST_TEST_CONTEXT( "Instance param name: " << instanceParam.name )
{
BOOST_CHECK( std::none_of( instanceParams.begin(), instanceParams.end(),
[instanceParam]( const auto& aOtherInstanceParam )
{
return instanceParam.id != aOtherInstanceParam.id
&& instanceParam.dir != SIM_MODEL::PARAM::DIR_OUT
&& aOtherInstanceParam.dir != SIM_MODEL::PARAM::DIR_OUT
&& instanceParam.name == aOtherInstanceParam.name;
} ) );
}
}
}
}
}
BOOST_AUTO_TEST_CASE( ParamCount )
{
// Count the total number of model and instance parameters for each model so that there will be
// an error if someone accidentally removes a parameter.
for( MODEL_TYPE type : MODEL_TYPE_ITERATOR() )
{
const std::vector<SIM_MODEL::PARAM::INFO> modelParams = ModelInfo( type ).modelParams;
const std::vector<SIM_MODEL::PARAM::INFO> instanceParams = ModelInfo( type ).instanceParams;
switch( type )
{
case MODEL_TYPE::NONE:
case MODEL_TYPE::_ENUM_END:
break;
/*case MODEL_TYPE::RESISTOR:
BOOST_CHECK_EQUAL( modelParams.size(), 22 );
BOOST_CHECK_EQUAL( instanceParams.size(), 25 );
break;
case MODEL_TYPE::CAPACITOR:
BOOST_CHECK_EQUAL( modelParams.size(), 19 );
BOOST_CHECK_EQUAL( instanceParams.size(), 22 );
break;
case MODEL_TYPE::INDUCTOR:
BOOST_CHECK_EQUAL( modelParams.size(), 9 );
BOOST_CHECK_EQUAL( instanceParams.size(), 20 );
break;*/
/*case MODEL_TYPE::LTRA:
BOOST_CHECK_EQUAL( modelParams.size(), 18 );
BOOST_CHECK_EQUAL( instanceParams.size(), 9 );
break;
case MODEL_TYPE::TRANLINE:
BOOST_CHECK_EQUAL( modelParams.size(), 0 );
BOOST_CHECK_EQUAL( instanceParams.size(), 17 );
break;
case MODEL_TYPE::URC:
BOOST_CHECK_EQUAL( modelParams.size(), 7 );
BOOST_CHECK_EQUAL( instanceParams.size(), 5 );
break;*/
/*case MODEL_TYPE::TRANSLINE:
BOOST_CHECK_EQUAL( modelParams.size(), 6 );
BOOST_CHECK_EQUAL( instanceParams.size(), 3 );
break;*/
/*case MODEL_TYPE::SWITCH:
BOOST_CHECK_EQUAL( modelParams.size(), 7 );
BOOST_CHECK_EQUAL( instanceParams.size(), 8 );
break;
case MODEL_TYPE::CSWITCH:
BOOST_CHECK_EQUAL( modelParams.size(), 7 );
BOOST_CHECK_EQUAL( instanceParams.size(), 7 );
break;*/
case MODEL_TYPE::DIODE:
BOOST_CHECK_EQUAL( modelParams.size(), 76 );
BOOST_CHECK_EQUAL( instanceParams.size(), 30 );
break;
case MODEL_TYPE::BJT:
BOOST_CHECK_EQUAL( modelParams.size(), 152 );
BOOST_CHECK_EQUAL( instanceParams.size(), 53 );
break;
case MODEL_TYPE::VBIC:
BOOST_CHECK_EQUAL( modelParams.size(), 117 );
BOOST_CHECK_EQUAL( instanceParams.size(), 45 );
break;
case MODEL_TYPE::HICUM2:
BOOST_CHECK_EQUAL( modelParams.size(), 149 );
BOOST_CHECK_EQUAL( instanceParams.size(), 61 );
break;
case MODEL_TYPE::JFET:
BOOST_CHECK_EQUAL( modelParams.size(), 34 );
BOOST_CHECK_EQUAL( instanceParams.size(), 28 );
break;
case MODEL_TYPE::JFET2:
BOOST_CHECK_EQUAL( modelParams.size(), 46 );
BOOST_CHECK_EQUAL( instanceParams.size(), 30 );
break;
case MODEL_TYPE::MES:
BOOST_CHECK_EQUAL( modelParams.size(), 22 );
BOOST_CHECK_EQUAL( instanceParams.size(), 25 );
break;
case MODEL_TYPE::MESA:
BOOST_CHECK_EQUAL( modelParams.size(), 71 );
BOOST_CHECK_EQUAL( instanceParams.size(), 30 );
break;
case MODEL_TYPE::HFET1:
BOOST_CHECK_EQUAL( modelParams.size(), 68 );
BOOST_CHECK_EQUAL( instanceParams.size(), 28 );
break;
case MODEL_TYPE::HFET2:
BOOST_CHECK_EQUAL( modelParams.size(), 40 );
BOOST_CHECK_EQUAL( instanceParams.size(), 28 );
break;
case MODEL_TYPE::VDMOS:
BOOST_CHECK_EQUAL( modelParams.size(), 69 );
BOOST_CHECK_EQUAL( instanceParams.size(), 36 );
break;
case MODEL_TYPE::MOS1:
BOOST_CHECK_EQUAL( modelParams.size(), 35 );
BOOST_CHECK_EQUAL( instanceParams.size(), 76 );
break;
case MODEL_TYPE::MOS2:
BOOST_CHECK_EQUAL( modelParams.size(), 42 );
BOOST_CHECK_EQUAL( instanceParams.size(), 76 );
break;
case MODEL_TYPE::MOS3:
BOOST_CHECK_EQUAL( modelParams.size(), 48 );
BOOST_CHECK_EQUAL( instanceParams.size(), 81 );
break;
case MODEL_TYPE::BSIM1:
BOOST_CHECK_EQUAL( modelParams.size(), 81 );
BOOST_CHECK_EQUAL( instanceParams.size(), 14 );
break;
case MODEL_TYPE::BSIM2:
BOOST_CHECK_EQUAL( modelParams.size(), 137 );
BOOST_CHECK_EQUAL( instanceParams.size(), 14 );
break;
case MODEL_TYPE::MOS6:
BOOST_CHECK_EQUAL( modelParams.size(), 42 );
BOOST_CHECK_EQUAL( instanceParams.size(), 78 );
break;
case MODEL_TYPE::BSIM3:
BOOST_CHECK_EQUAL( modelParams.size(), 429 );
BOOST_CHECK_EQUAL( instanceParams.size(), 46 );
break;
case MODEL_TYPE::MOS9:
BOOST_CHECK_EQUAL( modelParams.size(), 48 );
BOOST_CHECK_EQUAL( instanceParams.size(), 81 );
break;
case MODEL_TYPE::B4SOI:
BOOST_CHECK_EQUAL( modelParams.size(), 915 );
BOOST_CHECK_EQUAL( instanceParams.size(), 74 );
break;
case MODEL_TYPE::BSIM4:
BOOST_CHECK_EQUAL( modelParams.size(), 892 );
BOOST_CHECK_EQUAL( instanceParams.size(), 84 );
break;
case MODEL_TYPE::B3SOIFD:
BOOST_CHECK_EQUAL( modelParams.size(), 393 );
BOOST_CHECK_EQUAL( instanceParams.size(), 27 );
break;
case MODEL_TYPE::B3SOIDD:
BOOST_CHECK_EQUAL( modelParams.size(), 393 );
BOOST_CHECK_EQUAL( instanceParams.size(), 27 );
break;
case MODEL_TYPE::B3SOIPD:
BOOST_CHECK_EQUAL( modelParams.size(), 470 );
BOOST_CHECK_EQUAL( instanceParams.size(), 36 );
break;
case MODEL_TYPE::HISIM2:
BOOST_CHECK_EQUAL( modelParams.size(), 486 );
BOOST_CHECK_EQUAL( instanceParams.size(), 59 );
break;
case MODEL_TYPE::HISIMHV1:
BOOST_CHECK_EQUAL( modelParams.size(), 610 );
BOOST_CHECK_EQUAL( instanceParams.size(), 72 );
break;
case MODEL_TYPE::HISIMHV2:
BOOST_CHECK_EQUAL( modelParams.size(), 730 );
BOOST_CHECK_EQUAL( instanceParams.size(), 74 );
break;
default:
BOOST_FAIL( wxString::Format(
"Unhandled type: %d "
"(if you created a new type you need to handle it in this switch statement)",
type ) );
}
}
}
BOOST_AUTO_TEST_SUITE_END()