Sim: Don't require ngspice.h for SIM_MODEL_NGSPICE

This commit is contained in:
Mikolaj Wielgus 2022-08-05 17:37:20 +02:00
parent ea914eac9a
commit c9f3507ff7
8 changed files with 144 additions and 8188 deletions

View File

@ -275,7 +275,6 @@ set( EESCHEMA_SRCS
# Some simulation features must be built even if libngspice is not linked.
sim/spice_settings.cpp
sim/ngspice_models.cpp
sim/sim_library.cpp
sim/sim_library_spice.cpp
sim/sim_model.cpp
@ -283,6 +282,7 @@ set( EESCHEMA_SRCS
sim/sim_model_xspice.cpp
sim/sim_model_ideal.cpp
sim/sim_model_ngspice.cpp
sim/sim_model_ngspice_data.cpp
sim/sim_model_spice.cpp
sim/sim_model_source.cpp
sim/sim_model_subckt.cpp

View File

@ -33,9 +33,7 @@
#include <wx/dynlib.h>
#ifdef KICAD_SPICE
#include <ngspice/sharedspice.h>
#endif
#include <enum_vector.h>
@ -54,60 +52,6 @@ class wxDynamicLibrary;
class NGSPICE : public SPICE_SIMULATOR
{
public:
DEFINE_ENUM_CLASS_WITH_ITERATOR( MODEL_TYPE,
NONE,
//RESISTOR,
//CAPACITOR,
//INDUCTOR,
//LTRA,
//TRANLINE,
//URC,
//TRANSLINE,
SWITCH,
CSWITCH,
DIODE,
BJT,
VBIC,
HICUM2,
JFET,
JFET2,
MES,
MESA,
HFET1,
HFET2,
MOS1,
MOS2,
MOS3,
BSIM1,
BSIM2,
MOS6,
BSIM3,
MOS9,
B4SOI,
BSIM4,
B3SOIFD,
B3SOIDD,
B3SOIPD,
HISIM2,
HISIMHV1,
HISIMHV2
)
// May be moved to the SPICE_MODEL class later.
struct MODEL_INFO
{
wxString name;
wxString variant1;
wxString variant2;
std::vector<wxString> pinNames;
wxString description;
std::vector<SIM_MODEL::PARAM::INFO> modelParams;
std::vector<SIM_MODEL::PARAM::INFO> instanceParams;
};
static const MODEL_INFO& ModelInfo( MODEL_TYPE aType );
NGSPICE();
virtual ~NGSPICE();
@ -167,7 +111,6 @@ private:
// Performs DLL initialization, obtains function pointers
void init_dll();
#ifdef KICAD_SPICE
// ngspice library functions
typedef void ( *ngSpice_Init )( SendChar*, SendStat*, ControlledExit*, SendData*, SendInitData*,
BGThreadRunning*, void* );
@ -207,7 +150,6 @@ private:
static int cbBGThreadRunning( NG_BOOL aFinished, int aId, void* aUser );
static int cbControlledExit( int aStatus, NG_BOOL aImmediate, NG_BOOL aExitOnQuit, int aId,
void* aUser );
#endif
// Assure ngspice is in a valid state and reinitializes it if need be.
void validate();

File diff suppressed because it is too large Load Diff

View File

@ -31,7 +31,7 @@ using TYPE = SIM_MODEL::TYPE;
SIM_MODEL_NGSPICE::SIM_MODEL_NGSPICE( TYPE aType )
: SIM_MODEL( aType )
{
const NGSPICE::MODEL_INFO& modelInfo = NGSPICE::ModelInfo( getModelType() );
const MODEL_INFO& modelInfo = ModelInfo( getModelType() );
for( const SIM_MODEL::PARAM::INFO& paramInfo : modelInfo.instanceParams )
{
@ -112,7 +112,7 @@ bool SIM_MODEL_NGSPICE::SetParamFromSpiceCode( const wxString& aParamName, const
// One Spice param can have multiple names, we need to take this into account.
std::vector<PARAM::INFO> ngspiceParams = NGSPICE::ModelInfo( getModelType() ).modelParams;
std::vector<PARAM::INFO> ngspiceParams = ModelInfo( getModelType() ).modelParams;
auto ngspiceParamIt = std::find_if( ngspiceParams.begin(), ngspiceParams.end(),
[aParamName]( const PARAM& param )
@ -143,76 +143,76 @@ bool SIM_MODEL_NGSPICE::SetParamFromSpiceCode( const wxString& aParamName, const
std::vector<wxString> SIM_MODEL_NGSPICE::getPinNames() const
{
return NGSPICE::ModelInfo( getModelType() ).pinNames;
return ModelInfo( getModelType() ).pinNames;
}
NGSPICE::MODEL_TYPE SIM_MODEL_NGSPICE::getModelType() const
SIM_MODEL_NGSPICE::MODEL_TYPE SIM_MODEL_NGSPICE::getModelType() const
{
switch( GetType() )
{
case TYPE::NONE: return NGSPICE::MODEL_TYPE::NONE;
case TYPE::SW_V: return NGSPICE::MODEL_TYPE::SWITCH;
case TYPE::SW_I: return NGSPICE::MODEL_TYPE::CSWITCH;
case TYPE::D: return NGSPICE::MODEL_TYPE::DIODE;
case TYPE::NONE: return MODEL_TYPE::NONE;
case TYPE::SW_V: return MODEL_TYPE::SWITCH;
case TYPE::SW_I: return MODEL_TYPE::CSWITCH;
case TYPE::D: return MODEL_TYPE::DIODE;
case TYPE::NPN_GUMMELPOON:
case TYPE::PNP_GUMMELPOON: return NGSPICE::MODEL_TYPE::BJT;
case TYPE::PNP_GUMMELPOON: return MODEL_TYPE::BJT;
case TYPE::NPN_VBIC:
case TYPE::PNP_VBIC: return NGSPICE::MODEL_TYPE::VBIC;
case TYPE::PNP_VBIC: return MODEL_TYPE::VBIC;
case TYPE::NPN_HICUM2:
case TYPE::PNP_HICUM2: return NGSPICE::MODEL_TYPE::HICUM2;
case TYPE::PNP_HICUM2: return MODEL_TYPE::HICUM2;
case TYPE::NJFET_SHICHMANHODGES:
case TYPE::PJFET_SHICHMANHODGES: return NGSPICE::MODEL_TYPE::JFET;
case TYPE::PJFET_SHICHMANHODGES: return MODEL_TYPE::JFET;
case TYPE::NJFET_PARKERSKELLERN:
case TYPE::PJFET_PARKERSKELLERN: return NGSPICE::MODEL_TYPE::JFET2;
case TYPE::PJFET_PARKERSKELLERN: return MODEL_TYPE::JFET2;
case TYPE::NMES_STATZ:
case TYPE::PMES_STATZ: return NGSPICE::MODEL_TYPE::MES;
case TYPE::PMES_STATZ: return MODEL_TYPE::MES;
case TYPE::NMES_YTTERDAL:
case TYPE::PMES_YTTERDAL: return NGSPICE::MODEL_TYPE::MESA;
case TYPE::PMES_YTTERDAL: return MODEL_TYPE::MESA;
case TYPE::NMES_HFET1:
case TYPE::PMES_HFET1: return NGSPICE::MODEL_TYPE::HFET1;
case TYPE::PMES_HFET1: return MODEL_TYPE::HFET1;
case TYPE::NMES_HFET2:
case TYPE::PMES_HFET2: return NGSPICE::MODEL_TYPE::HFET2;
case TYPE::PMES_HFET2: return MODEL_TYPE::HFET2;
case TYPE::NMOS_MOS1:
case TYPE::PMOS_MOS1: return NGSPICE::MODEL_TYPE::MOS1;
case TYPE::PMOS_MOS1: return MODEL_TYPE::MOS1;
case TYPE::NMOS_MOS2:
case TYPE::PMOS_MOS2: return NGSPICE::MODEL_TYPE::MOS2;
case TYPE::PMOS_MOS2: return MODEL_TYPE::MOS2;
case TYPE::NMOS_MOS3:
case TYPE::PMOS_MOS3: return NGSPICE::MODEL_TYPE::MOS3;
case TYPE::PMOS_MOS3: return MODEL_TYPE::MOS3;
case TYPE::NMOS_BSIM1:
case TYPE::PMOS_BSIM1: return NGSPICE::MODEL_TYPE::BSIM1;
case TYPE::PMOS_BSIM1: return MODEL_TYPE::BSIM1;
case TYPE::NMOS_BSIM2:
case TYPE::PMOS_BSIM2: return NGSPICE::MODEL_TYPE::BSIM2;
case TYPE::PMOS_BSIM2: return MODEL_TYPE::BSIM2;
case TYPE::NMOS_MOS6:
case TYPE::PMOS_MOS6: return NGSPICE::MODEL_TYPE::MOS6;
case TYPE::PMOS_MOS6: return MODEL_TYPE::MOS6;
case TYPE::NMOS_BSIM3:
case TYPE::PMOS_BSIM3: return NGSPICE::MODEL_TYPE::BSIM3;
case TYPE::PMOS_BSIM3: return MODEL_TYPE::BSIM3;
case TYPE::NMOS_MOS9:
case TYPE::PMOS_MOS9: return NGSPICE::MODEL_TYPE::MOS9;
case TYPE::PMOS_MOS9: return MODEL_TYPE::MOS9;
case TYPE::NMOS_B4SOI:
case TYPE::PMOS_B4SOI: return NGSPICE::MODEL_TYPE::B4SOI;
case TYPE::PMOS_B4SOI: return MODEL_TYPE::B4SOI;
case TYPE::NMOS_BSIM4:
case TYPE::PMOS_BSIM4: return NGSPICE::MODEL_TYPE::BSIM4;
case TYPE::PMOS_BSIM4: return MODEL_TYPE::BSIM4;
case TYPE::NMOS_B3SOIFD:
case TYPE::PMOS_B3SOIFD: return NGSPICE::MODEL_TYPE::B3SOIFD;
case TYPE::PMOS_B3SOIFD: return MODEL_TYPE::B3SOIFD;
case TYPE::NMOS_B3SOIDD:
case TYPE::PMOS_B3SOIDD: return NGSPICE::MODEL_TYPE::B3SOIDD;
case TYPE::PMOS_B3SOIDD: return MODEL_TYPE::B3SOIDD;
case TYPE::NMOS_B3SOIPD:
case TYPE::PMOS_B3SOIPD: return NGSPICE::MODEL_TYPE::B3SOIPD;
case TYPE::PMOS_B3SOIPD: return MODEL_TYPE::B3SOIPD;
case TYPE::NMOS_HISIM2:
case TYPE::PMOS_HISIM2: return NGSPICE::MODEL_TYPE::HISIM2;
case TYPE::PMOS_HISIM2: return MODEL_TYPE::HISIM2;
case TYPE::NMOS_HISIMHV1:
case TYPE::PMOS_HISIMHV1: return NGSPICE::MODEL_TYPE::HISIMHV1;
case TYPE::PMOS_HISIMHV1: return MODEL_TYPE::HISIMHV1;
case TYPE::NMOS_HISIMHV2:
case TYPE::PMOS_HISIMHV2: return NGSPICE::MODEL_TYPE::HISIMHV2;
case TYPE::PMOS_HISIMHV2: return MODEL_TYPE::HISIMHV2;
default:
wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_NGSPICE" );
return NGSPICE::MODEL_TYPE::NONE;
return MODEL_TYPE::NONE;
}
}

View File

@ -26,12 +26,13 @@
#define SIM_MODEL_NGSPICE_H
#include <sim/sim_model.h>
#include <sim/ngspice.h>
class SIM_MODEL_NGSPICE : public SIM_MODEL
{
public:
friend struct MODEL_INFO_MAP;
SIM_MODEL_NGSPICE( TYPE aType );
std::vector<wxString> GenerateSpiceCurrentNames( const wxString& aRefName ) const override;
@ -39,10 +40,64 @@ public:
bool SetParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue,
SIM_VALUE_GRAMMAR::NOTATION aNotation ) override;
// Protected because it's accessed by QA tests.
protected:
DEFINE_ENUM_CLASS_WITH_ITERATOR( MODEL_TYPE,
NONE,
//RESISTOR,
//CAPACITOR,
//INDUCTOR,
//LTRA,
//TRANLINE,
//URC,
//TRANSLINE,
SWITCH,
CSWITCH,
DIODE,
BJT,
VBIC,
HICUM2,
JFET,
JFET2,
MES,
MESA,
HFET1,
HFET2,
MOS1,
MOS2,
MOS3,
BSIM1,
BSIM2,
MOS6,
BSIM3,
MOS9,
B4SOI,
BSIM4,
B3SOIFD,
B3SOIDD,
B3SOIPD,
HISIM2,
HISIMHV1,
HISIMHV2
)
struct MODEL_INFO
{
wxString name;
wxString variant1;
wxString variant2;
std::vector<wxString> pinNames;
wxString description;
std::vector<SIM_MODEL::PARAM::INFO> modelParams;
std::vector<SIM_MODEL::PARAM::INFO> instanceParams;
};
static const MODEL_INFO& ModelInfo( MODEL_TYPE aType );
private:
std::vector<wxString> getPinNames() const override;
NGSPICE::MODEL_TYPE getModelType() const;
MODEL_TYPE getModelType() const;
bool getIsOtherVariant();
};

View File

@ -89,7 +89,7 @@ if( KICAD_SPICE )
${QA_EESCHEMA_SRCS}
# Simulation tests
sim/test_library_spice.cpp
sim/test_ngspice.cpp
sim/test_sim_model_ngspice.cpp
sim/test_ngspice_helpers.cpp
)
endif()

View File

@ -22,9 +22,16 @@
*/
#include <qa_utils/wx_utils/unit_test_utils.h>
#include <sim/ngspice.h>
#include <sim/sim_model_ngspice.h>
BOOST_AUTO_TEST_SUITE( Ngspice )
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( Models )
@ -32,188 +39,188 @@ BOOST_AUTO_TEST_CASE( Models )
// 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( NGSPICE::MODEL_TYPE type : NGSPICE::MODEL_TYPE_ITERATOR() )
for( MODEL_TYPE type : MODEL_TYPE_ITERATOR() )
{
unsigned modelParamCount = NGSPICE::ModelInfo( type ).modelParams.size();
unsigned instanceParamCount = NGSPICE::ModelInfo( type ).instanceParams.size();
unsigned modelParamCount = ModelInfo( type ).modelParams.size();
unsigned instanceParamCount = ModelInfo( type ).instanceParams.size();
switch( type )
{
case NGSPICE::MODEL_TYPE::NONE:
case NGSPICE::MODEL_TYPE::_ENUM_END:
case MODEL_TYPE::NONE:
case MODEL_TYPE::_ENUM_END:
break;
/*case NGSPICE::MODEL_TYPE::RESISTOR:
/*case MODEL_TYPE::RESISTOR:
BOOST_CHECK_EQUAL( modelParamCount, 22 );
BOOST_CHECK_EQUAL( instanceParamCount, 25 );
break;
case NGSPICE::MODEL_TYPE::CAPACITOR:
case MODEL_TYPE::CAPACITOR:
BOOST_CHECK_EQUAL( modelParamCount, 19 );
BOOST_CHECK_EQUAL( instanceParamCount, 22 );
break;
case NGSPICE::MODEL_TYPE::INDUCTOR:
case MODEL_TYPE::INDUCTOR:
BOOST_CHECK_EQUAL( modelParamCount, 9 );
BOOST_CHECK_EQUAL( instanceParamCount, 20 );
break;*/
/*case NGSPICE::MODEL_TYPE::LTRA:
/*case MODEL_TYPE::LTRA:
BOOST_CHECK_EQUAL( modelParamCount, 18 );
BOOST_CHECK_EQUAL( instanceParamCount, 9 );
break;
case NGSPICE::MODEL_TYPE::TRANLINE:
case MODEL_TYPE::TRANLINE:
BOOST_CHECK_EQUAL( modelParamCount, 0 );
BOOST_CHECK_EQUAL( instanceParamCount, 17 );
break;
case NGSPICE::MODEL_TYPE::URC:
case MODEL_TYPE::URC:
BOOST_CHECK_EQUAL( modelParamCount, 7 );
BOOST_CHECK_EQUAL( instanceParamCount, 5 );
break;*/
/*case NGSPICE::MODEL_TYPE::TRANSLINE:
/*case MODEL_TYPE::TRANSLINE:
BOOST_CHECK_EQUAL( modelParamCount, 6 );
BOOST_CHECK_EQUAL( instanceParamCount, 3 );
break;*/
case NGSPICE::MODEL_TYPE::SWITCH:
case MODEL_TYPE::SWITCH:
BOOST_CHECK_EQUAL( modelParamCount, 7 );
BOOST_CHECK_EQUAL( instanceParamCount, 8 );
break;
case NGSPICE::MODEL_TYPE::CSWITCH:
case MODEL_TYPE::CSWITCH:
BOOST_CHECK_EQUAL( modelParamCount, 7 );
BOOST_CHECK_EQUAL( instanceParamCount, 7 );
break;
case NGSPICE::MODEL_TYPE::DIODE:
case MODEL_TYPE::DIODE:
BOOST_CHECK_EQUAL( modelParamCount, 76 );
BOOST_CHECK_EQUAL( instanceParamCount, 30 );
break;
case NGSPICE::MODEL_TYPE::BJT:
case MODEL_TYPE::BJT:
BOOST_CHECK_EQUAL( modelParamCount, 152 );
BOOST_CHECK_EQUAL( instanceParamCount, 53 );
break;
case NGSPICE::MODEL_TYPE::VBIC:
case MODEL_TYPE::VBIC:
BOOST_CHECK_EQUAL( modelParamCount, 117 );
BOOST_CHECK_EQUAL( instanceParamCount, 45 );
break;
case NGSPICE::MODEL_TYPE::HICUM2:
case MODEL_TYPE::HICUM2:
BOOST_CHECK_EQUAL( modelParamCount, 149 );
BOOST_CHECK_EQUAL( instanceParamCount, 61 );
break;
case NGSPICE::MODEL_TYPE::JFET:
case MODEL_TYPE::JFET:
BOOST_CHECK_EQUAL( modelParamCount, 28 );
BOOST_CHECK_EQUAL( instanceParamCount, 28 );
break;
case NGSPICE::MODEL_TYPE::JFET2:
case MODEL_TYPE::JFET2:
BOOST_CHECK_EQUAL( modelParamCount, 46 );
BOOST_CHECK_EQUAL( instanceParamCount, 30 );
break;
case NGSPICE::MODEL_TYPE::MES:
case MODEL_TYPE::MES:
BOOST_CHECK_EQUAL( modelParamCount, 22 );
BOOST_CHECK_EQUAL( instanceParamCount, 25 );
break;
case NGSPICE::MODEL_TYPE::MESA:
case MODEL_TYPE::MESA:
BOOST_CHECK_EQUAL( modelParamCount, 71 );
BOOST_CHECK_EQUAL( instanceParamCount, 30 );
break;
case NGSPICE::MODEL_TYPE::HFET1:
case MODEL_TYPE::HFET1:
BOOST_CHECK_EQUAL( modelParamCount, 68 );
BOOST_CHECK_EQUAL( instanceParamCount, 28 );
break;
case NGSPICE::MODEL_TYPE::HFET2:
case MODEL_TYPE::HFET2:
BOOST_CHECK_EQUAL( modelParamCount, 40 );
BOOST_CHECK_EQUAL( instanceParamCount, 28 );
break;
case NGSPICE::MODEL_TYPE::MOS1:
case MODEL_TYPE::MOS1:
BOOST_CHECK_EQUAL( modelParamCount, 35 );
BOOST_CHECK_EQUAL( instanceParamCount, 76 );
break;
case NGSPICE::MODEL_TYPE::MOS2:
case MODEL_TYPE::MOS2:
BOOST_CHECK_EQUAL( modelParamCount, 42 );
BOOST_CHECK_EQUAL( instanceParamCount, 76 );
break;
case NGSPICE::MODEL_TYPE::MOS3:
case MODEL_TYPE::MOS3:
BOOST_CHECK_EQUAL( modelParamCount, 48 );
BOOST_CHECK_EQUAL( instanceParamCount, 81 );
break;
case NGSPICE::MODEL_TYPE::BSIM1:
case MODEL_TYPE::BSIM1:
BOOST_CHECK_EQUAL( modelParamCount, 81 );
BOOST_CHECK_EQUAL( instanceParamCount, 14 );
break;
case NGSPICE::MODEL_TYPE::BSIM2:
case MODEL_TYPE::BSIM2:
BOOST_CHECK_EQUAL( modelParamCount, 137 );
BOOST_CHECK_EQUAL( instanceParamCount, 14 );
break;
case NGSPICE::MODEL_TYPE::MOS6:
case MODEL_TYPE::MOS6:
BOOST_CHECK_EQUAL( modelParamCount, 42 );
BOOST_CHECK_EQUAL( instanceParamCount, 78 );
break;
case NGSPICE::MODEL_TYPE::BSIM3:
case MODEL_TYPE::BSIM3:
BOOST_CHECK_EQUAL( modelParamCount, 429 );
BOOST_CHECK_EQUAL( instanceParamCount, 46 );
break;
case NGSPICE::MODEL_TYPE::MOS9:
case MODEL_TYPE::MOS9:
BOOST_CHECK_EQUAL( modelParamCount, 48 );
BOOST_CHECK_EQUAL( instanceParamCount, 81 );
break;
case NGSPICE::MODEL_TYPE::B4SOI:
case MODEL_TYPE::B4SOI:
BOOST_CHECK_EQUAL( modelParamCount, 915 );
BOOST_CHECK_EQUAL( instanceParamCount, 74 );
break;
case NGSPICE::MODEL_TYPE::BSIM4:
case MODEL_TYPE::BSIM4:
BOOST_CHECK_EQUAL( modelParamCount, 892 );
BOOST_CHECK_EQUAL( instanceParamCount, 84 );
break;
case NGSPICE::MODEL_TYPE::B3SOIFD:
case MODEL_TYPE::B3SOIFD:
BOOST_CHECK_EQUAL( modelParamCount, 393 );
BOOST_CHECK_EQUAL( instanceParamCount, 27 );
break;
case NGSPICE::MODEL_TYPE::B3SOIDD:
case MODEL_TYPE::B3SOIDD:
BOOST_CHECK_EQUAL( modelParamCount, 393 );
BOOST_CHECK_EQUAL( instanceParamCount, 27 );
break;
case NGSPICE::MODEL_TYPE::B3SOIPD:
case MODEL_TYPE::B3SOIPD:
BOOST_CHECK_EQUAL( modelParamCount, 470 );
BOOST_CHECK_EQUAL( instanceParamCount, 36 );
break;
case NGSPICE::MODEL_TYPE::HISIM2:
case MODEL_TYPE::HISIM2:
BOOST_CHECK_EQUAL( modelParamCount, 486 );
BOOST_CHECK_EQUAL( instanceParamCount, 59 );
break;
case NGSPICE::MODEL_TYPE::HISIMHV1:
case MODEL_TYPE::HISIMHV1:
BOOST_CHECK_EQUAL( modelParamCount, 610 );
BOOST_CHECK_EQUAL( instanceParamCount, 72 );
break;
case NGSPICE::MODEL_TYPE::HISIMHV2:
case MODEL_TYPE::HISIMHV2:
BOOST_CHECK_EQUAL( modelParamCount, 730 );
BOOST_CHECK_EQUAL( instanceParamCount, 74 );
break;

View File

@ -125,10 +125,6 @@ public:
std::vector<double> xVector = ngspice->GetRealPlot( aXVectorName );
std::size_t i = 0;
BOOST_REQUIRE_GE( xVector.size(), 2 );
//double xStep = xVector[1] - xVector[0];
for(; i < xVector.size(); ++i )
{
double inf = std::numeric_limits<double>::infinity();