eeschema,sim: add SIMULATOR and SIM_MODEL interface

SIMULATOR has now an Attach() method, which should be called
with proper SIMULATION_MODEL that should be simulated, before calling Run()

Concrete class of SIMULATION_MODEL for ngspice is NGSPICE_CIRCUIT_MODEL,
renamed from NETLIST_EXPORTER_PSPICE_SIM. DIALOG_SIM_SETTINGS relies
on above mentioned object, so it was added as an argument of the constructor.
This commit is contained in:
Sylwester Kocjan 2022-03-06 00:49:25 +01:00 committed by Mikolaj Wielgus
parent be6379a8f6
commit f5dedd77c6
19 changed files with 225 additions and 108 deletions

View File

@ -305,7 +305,7 @@ if( KICAD_SPICE )
dialogs/dialog_sim_settings_base.cpp dialogs/dialog_sim_settings_base.cpp
dialogs/dialog_spice_model.cpp dialogs/dialog_spice_model.cpp
dialogs/dialog_spice_model_base.cpp dialogs/dialog_spice_model_base.cpp
sim/netlist_exporter_pspice_sim.cpp sim/ngspice_helpers.cpp
sim/ngspice.cpp sim/ngspice.cpp
sim/sim_panel_base.cpp sim/sim_panel_base.cpp
sim/sim_plot_colors.cpp sim/sim_plot_colors.cpp

View File

@ -28,11 +28,11 @@
#include <string_utils.h> #include <string_utils.h>
#include <sim/sim_plot_frame.h> #include <sim/sim_plot_frame.h>
#include <sim/netlist_exporter_pspice_sim.h> #include <sim/ngspice_helpers.h>
DIALOG_SIGNAL_LIST::DIALOG_SIGNAL_LIST( SIM_PLOT_FRAME* aParent, DIALOG_SIGNAL_LIST::DIALOG_SIGNAL_LIST( SIM_PLOT_FRAME* aParent,
NETLIST_EXPORTER_PSPICE_SIM* aExporter ) : NGSPICE_CIRCUIT_MODEL* aExporter ) :
DIALOG_SIGNAL_LIST_BASE( aParent ), DIALOG_SIGNAL_LIST_BASE( aParent ),
m_plotFrame( aParent ), m_plotFrame( aParent ),
m_exporter( aExporter ) m_exporter( aExporter )
@ -76,7 +76,7 @@ bool DIALOG_SIGNAL_LIST::TransferDataToWindow()
{ {
// Add all possible currents for the primitive // Add all possible currents for the primitive
for( const auto& current : for( const auto& current :
NETLIST_EXPORTER_PSPICE_SIM::GetCurrents( (SPICE_PRIMITIVE) item.m_primitive ) ) NGSPICE_CIRCUIT_MODEL::GetCurrents( (SPICE_PRIMITIVE) item.m_primitive ) )
{ {
m_signals->Append( wxString::Format( "%s(%s)", current, item.m_refName ) ); m_signals->Append( wxString::Format( "%s(%s)", current, item.m_refName ) );
} }

View File

@ -28,12 +28,12 @@
#include "dialog_signal_list_base.h" #include "dialog_signal_list_base.h"
class SIM_PLOT_FRAME; class SIM_PLOT_FRAME;
class NETLIST_EXPORTER_PSPICE_SIM; class NGSPICE_CIRCUIT_MODEL;
class DIALOG_SIGNAL_LIST : public DIALOG_SIGNAL_LIST_BASE class DIALOG_SIGNAL_LIST : public DIALOG_SIGNAL_LIST_BASE
{ {
public: public:
DIALOG_SIGNAL_LIST( SIM_PLOT_FRAME* aParent, NETLIST_EXPORTER_PSPICE_SIM* aExporter ); DIALOG_SIGNAL_LIST( SIM_PLOT_FRAME* aParent, NGSPICE_CIRCUIT_MODEL* aExporter );
bool TransferDataFromWindow() override; bool TransferDataFromWindow() override;
bool TransferDataToWindow() override; bool TransferDataToWindow() override;
@ -48,7 +48,7 @@ private:
bool addSignalToPlotFrame( const wxString& aPlotName ); bool addSignalToPlotFrame( const wxString& aPlotName );
SIM_PLOT_FRAME* m_plotFrame; SIM_PLOT_FRAME* m_plotFrame;
NETLIST_EXPORTER_PSPICE_SIM* m_exporter; NGSPICE_CIRCUIT_MODEL* m_exporter;
}; };
#endif /* DIALOG_SIGNAL_LIST_H */ #endif /* DIALOG_SIGNAL_LIST_H */

View File

@ -24,7 +24,7 @@
*/ */
#include "dialog_sim_settings.h" #include "dialog_sim_settings.h"
#include <sim/netlist_exporter_pspice_sim.h> #include <sim/ngspice_helpers.h>
#include <sim/ngspice.h> #include <sim/ngspice.h>
#include <confirm.h> #include <confirm.h>
@ -57,7 +57,7 @@ static wxString getStringSelection( const wxChoice* aCtrl )
DIALOG_SIM_SETTINGS::DIALOG_SIM_SETTINGS( wxWindow* aParent, DIALOG_SIM_SETTINGS::DIALOG_SIM_SETTINGS( wxWindow* aParent,
std::shared_ptr<NETLIST_EXPORTER_PSPICE_SIM> aExporter, std::shared_ptr<NGSPICE_CIRCUIT_MODEL> aExporter,
std::shared_ptr<SPICE_SIMULATOR_SETTINGS>& aSettings ) : std::shared_ptr<SPICE_SIMULATOR_SETTINGS>& aSettings ) :
DIALOG_SIM_SETTINGS_BASE( aParent ), DIALOG_SIM_SETTINGS_BASE( aParent ),
m_exporter( aExporter ), m_exporter( aExporter ),

View File

@ -32,14 +32,14 @@
#include <wx/valnum.h> #include <wx/valnum.h>
class NETLIST_EXPORTER_PSPICE_SIM; class NGSPICE_CIRCUIT_MODEL;
class SPICE_SIMULATOR_SETTINGS; class SPICE_SIMULATOR_SETTINGS;
class DIALOG_SIM_SETTINGS : public DIALOG_SIM_SETTINGS_BASE class DIALOG_SIM_SETTINGS : public DIALOG_SIM_SETTINGS_BASE
{ {
public: public:
DIALOG_SIM_SETTINGS( wxWindow* aParent, std::shared_ptr<NETLIST_EXPORTER_PSPICE_SIM> aExporter, DIALOG_SIM_SETTINGS( wxWindow* aParent, std::shared_ptr<NGSPICE_CIRCUIT_MODEL> aExporter,
std::shared_ptr<SPICE_SIMULATOR_SETTINGS>& aSettings ); std::shared_ptr<SPICE_SIMULATOR_SETTINGS>& aSettings );
const wxString& GetSimCommand() const const wxString& GetSimCommand() const
@ -178,7 +178,7 @@ private:
wxString m_simCommand; wxString m_simCommand;
int m_netlistOpts; int m_netlistOpts;
std::shared_ptr<NETLIST_EXPORTER_PSPICE_SIM> m_exporter; std::shared_ptr<NGSPICE_CIRCUIT_MODEL> m_exporter;
std::shared_ptr<SPICE_SIMULATOR_SETTINGS> m_settings; std::shared_ptr<SPICE_SIMULATOR_SETTINGS> m_settings;
SPICE_VALIDATOR m_spiceValidator; SPICE_VALIDATOR m_spiceValidator;
SPICE_VALIDATOR m_spiceEmptyValidator; SPICE_VALIDATOR m_spiceEmptyValidator;

View File

@ -28,6 +28,7 @@
#include <config.h> // Needed for MSW compilation #include <config.h> // Needed for MSW compilation
#include <wx/log.h> #include <wx/log.h>
#include "ngspice_helpers.h"
#include "ngspice.h" #include "ngspice.h"
#include "spice_reporter.h" #include "spice_reporter.h"
#include "spice_settings.h" #include "spice_settings.h"
@ -254,6 +255,29 @@ vector<double> NGSPICE::GetPhasePlot( const string& aName, int aMaxLen )
} }
bool NGSPICE::Attach( const std::shared_ptr<SIMULATION_MODEL>& aModel )
{
NGSPICE_CIRCUIT_MODEL* model = dynamic_cast<NGSPICE_CIRCUIT_MODEL*>( aModel.get() );
wxASSERT( model != nullptr );
STRING_FORMATTER formatter;
if( model->GetNetlist( &formatter ) )
{
SIMULATOR::Attach( aModel );
LoadNetlist( formatter.GetString() );
return true;
}
else
{
SIMULATOR::Attach( nullptr );
return false;
}
}
bool NGSPICE::LoadNetlist( const string& aNetlist ) bool NGSPICE::LoadNetlist( const string& aNetlist )
{ {
LOCALE_IO c_locale; // ngspice works correctly only with C locale LOCALE_IO c_locale; // ngspice works correctly only with C locale
@ -271,6 +295,8 @@ bool NGSPICE::LoadNetlist( const string& aNetlist )
} }
lines.push_back( nullptr ); // sentinel, as requested in ngSpice_Circ description lines.push_back( nullptr ); // sentinel, as requested in ngSpice_Circ description
Command( "remcirc" );
m_ngSpice_Circ( lines.data() ); m_ngSpice_Circ( lines.data() );
for( auto line : lines ) for( auto line : lines )

View File

@ -43,6 +43,7 @@
class wxDynamicLibrary; class wxDynamicLibrary;
class NGSPICE : public SPICE_SIMULATOR class NGSPICE : public SPICE_SIMULATOR
{ {
public: public:
@ -50,48 +51,51 @@ public:
virtual ~NGSPICE(); virtual ~NGSPICE();
///< @copydoc SPICE_SIMULATOR::Init() ///< @copydoc SPICE_SIMULATOR::Init()
void Init( const SPICE_SIMULATOR_SETTINGS* aSettings = nullptr ) override; void Init( const SPICE_SIMULATOR_SETTINGS* aSettings = nullptr ) override final;
///< @copydoc SPICE_SIMULATOR::LoadNetlist() ///< @copydoc SPICE_SIMULATOR::Attach()
bool LoadNetlist( const std::string& aNetlist ) override; bool Attach( const std::shared_ptr<SIMULATION_MODEL>& aModel ) override final;
///< Load a netlist for the simulation
bool LoadNetlist( const std::string& aNetlist ) override final;
///< @copydoc SPICE_SIMULATOR::Run() ///< @copydoc SPICE_SIMULATOR::Run()
bool Run() override; bool Run() override final;
///< @copydoc SPICE_SIMULATOR::Stop() ///< @copydoc SPICE_SIMULATOR::Stop()
bool Stop() override; bool Stop() override final;
///< @copydoc SPICE_SIMULATOR::IsRunning() ///< @copydoc SPICE_SIMULATOR::IsRunning()
bool IsRunning() override; bool IsRunning() override final;
///< @copydoc SPICE_SIMULATOR::Command() ///< @copydoc SPICE_SIMULATOR::Command()
bool Command( const std::string& aCmd ) override; bool Command( const std::string& aCmd ) override final;
///< @copydoc SPICE_SIMULATOR::GetXAxis() ///< @copydoc SPICE_SIMULATOR::GetXAxis()
std::string GetXAxis( SIM_TYPE aType ) const override; std::string GetXAxis( SIM_TYPE aType ) const override final;
///< @copydoc SPICE_SIMULATOR::AllPlots() ///< @copydoc SPICE_SIMULATOR::AllPlots()
std::vector<std::string> AllPlots() const override; std::vector<std::string> AllPlots() const override final;
///< @copydoc SPICE_SIMULATOR::GetPlot() ///< @copydoc SPICE_SIMULATOR::GetPlot()
std::vector<COMPLEX> GetPlot( const std::string& aName, int aMaxLen = -1 ) override; std::vector<COMPLEX> GetPlot( const std::string& aName, int aMaxLen = -1 ) override final;
///< @copydoc SPICE_SIMULATOR::GetRealPlot() ///< @copydoc SPICE_SIMULATOR::GetRealPlot()
std::vector<double> GetRealPlot( const std::string& aName, int aMaxLen = -1 ) override; std::vector<double> GetRealPlot( const std::string& aName, int aMaxLen = -1 ) override final;
///< @copydoc SPICE_SIMULATOR::GetImagPlot() ///< @copydoc SPICE_SIMULATOR::GetImagPlot()
std::vector<double> GetImagPlot( const std::string& aName, int aMaxLen = -1 ) override; std::vector<double> GetImagPlot( const std::string& aName, int aMaxLen = -1 ) override final;
///< @copydoc SPICE_SIMULATOR::GetMagPlot() ///< @copydoc SPICE_SIMULATOR::GetMagPlot()
std::vector<double> GetMagPlot( const std::string& aName, int aMaxLen = -1 ) override; std::vector<double> GetMagPlot( const std::string& aName, int aMaxLen = -1 ) override final;
///< @copydoc SPICE_SIMULATOR::GetPhasePlot() ///< @copydoc SPICE_SIMULATOR::GetPhasePlot()
std::vector<double> GetPhasePlot( const std::string& aName, int aMaxLen = -1 ) override; std::vector<double> GetPhasePlot( const std::string& aName, int aMaxLen = -1 ) override final;
std::vector<std::string> GetSettingCommands() const override; std::vector<std::string> GetSettingCommands() const override final;
///< @copydoc SPICE_SIMULATOR::GetNetlist() ///< @copydoc SPICE_SIMULATOR::GetNetlist()
virtual const std::string GetNetlist() const override; virtual const std::string GetNetlist() const override final;
private: private:
void init(); void init();

View File

@ -24,13 +24,13 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include "netlist_exporter_pspice_sim.h" #include "ngspice_helpers.h"
#include <string_utils.h> #include <string_utils.h>
#include <macros.h> // for TO_UTF8 def #include <macros.h> // for TO_UTF8 def
#include <wx/regex.h> #include <wx/regex.h>
#include <wx/tokenzr.h> #include <wx/tokenzr.h>
wxString NETLIST_EXPORTER_PSPICE_SIM::ComponentToVector( wxString NGSPICE_CIRCUIT_MODEL::ComponentToVector(
const wxString& aName, SIM_PLOT_TYPE aType, const wxString& aParam ) const const wxString& aName, SIM_PLOT_TYPE aType, const wxString& aParam ) const
{ {
wxString res; wxString res;
@ -73,7 +73,7 @@ wxString NETLIST_EXPORTER_PSPICE_SIM::ComponentToVector(
} }
SIM_PLOT_TYPE NETLIST_EXPORTER_PSPICE_SIM::VectorToSignal( SIM_PLOT_TYPE NGSPICE_CIRCUIT_MODEL::VectorToSignal(
const std::string& aVector, wxString& aSignal ) const const std::string& aVector, wxString& aSignal ) const
{ {
using namespace std; using namespace std;
@ -108,7 +108,7 @@ SIM_PLOT_TYPE NETLIST_EXPORTER_PSPICE_SIM::VectorToSignal(
} }
const std::vector<wxString>& NETLIST_EXPORTER_PSPICE_SIM::GetCurrents( SPICE_PRIMITIVE aPrimitive ) const std::vector<wxString>& NGSPICE_CIRCUIT_MODEL::GetCurrents( SPICE_PRIMITIVE aPrimitive )
{ {
static const std::vector<wxString> passive = { "I" }; static const std::vector<wxString> passive = { "I" };
static const std::vector<wxString> diode = { "Id" }; static const std::vector<wxString> diode = { "Id" };
@ -139,7 +139,7 @@ const std::vector<wxString>& NETLIST_EXPORTER_PSPICE_SIM::GetCurrents( SPICE_PRI
} }
wxString NETLIST_EXPORTER_PSPICE_SIM::GetSheetSimCommand() wxString NGSPICE_CIRCUIT_MODEL::GetSheetSimCommand()
{ {
wxString simCmd; wxString simCmd;
@ -155,19 +155,19 @@ wxString NETLIST_EXPORTER_PSPICE_SIM::GetSheetSimCommand()
} }
wxString NETLIST_EXPORTER_PSPICE_SIM::GetUsedSimCommand() wxString NGSPICE_CIRCUIT_MODEL::GetUsedSimCommand()
{ {
return m_simCommand.IsEmpty() ? GetSheetSimCommand() : m_simCommand; return m_simCommand.IsEmpty() ? GetSheetSimCommand() : m_simCommand;
} }
SIM_TYPE NETLIST_EXPORTER_PSPICE_SIM::GetSimType() SIM_TYPE NGSPICE_CIRCUIT_MODEL::GetSimType()
{ {
return CommandToSimType( GetUsedSimCommand() ); return CommandToSimType( GetUsedSimCommand() );
} }
SIM_TYPE NETLIST_EXPORTER_PSPICE_SIM::CommandToSimType( const wxString& aCmd ) SIM_TYPE NGSPICE_CIRCUIT_MODEL::CommandToSimType( const wxString& aCmd )
{ {
const std::vector<std::pair<wxString, SIM_TYPE>> simCmds = { const std::vector<std::pair<wxString, SIM_TYPE>> simCmds = {
{ "^.ac\\M.*", ST_AC }, { "^.ac\\M.*", ST_AC },
@ -193,7 +193,7 @@ SIM_TYPE NETLIST_EXPORTER_PSPICE_SIM::CommandToSimType( const wxString& aCmd )
} }
bool NETLIST_EXPORTER_PSPICE_SIM::ParseDCCommand( const wxString& aCmd, SPICE_DC_PARAMS* aSource1, bool NGSPICE_CIRCUIT_MODEL::ParseDCCommand( const wxString& aCmd, SPICE_DC_PARAMS* aSource1,
SPICE_DC_PARAMS* aSource2 ) SPICE_DC_PARAMS* aSource2 )
{ {
if( !aCmd.Lower().StartsWith( ".dc" ) ) if( !aCmd.Lower().StartsWith( ".dc" ) )
@ -225,7 +225,7 @@ bool NETLIST_EXPORTER_PSPICE_SIM::ParseDCCommand( const wxString& aCmd, SPICE_DC
} }
void NETLIST_EXPORTER_PSPICE_SIM::writeDirectives( OUTPUTFORMATTER* aFormatter, unsigned aCtl ) const void NGSPICE_CIRCUIT_MODEL::writeDirectives( OUTPUTFORMATTER* aFormatter, unsigned aCtl ) const
{ {
// Add a directive to obtain currents // Add a directive to obtain currents
//aFormatter->Print( 0, ".options savecurrents\n" ); // does not work :( //aFormatter->Print( 0, ".options savecurrents\n" ); // does not work :(
@ -233,7 +233,7 @@ void NETLIST_EXPORTER_PSPICE_SIM::writeDirectives( OUTPUTFORMATTER* aFormatter,
for( const auto& item : GetSpiceItems() ) for( const auto& item : GetSpiceItems() )
{ {
for( const auto& current : for( const auto& current :
NETLIST_EXPORTER_PSPICE_SIM::GetCurrents( (SPICE_PRIMITIVE) item.m_primitive ) ) NGSPICE_CIRCUIT_MODEL::GetCurrents( (SPICE_PRIMITIVE) item.m_primitive ) )
{ {
if( !item.m_enabled ) if( !item.m_enabled )
continue; continue;

View File

@ -31,6 +31,7 @@
#include <vector> #include <vector>
#include "sim_types.h" #include "sim_types.h"
#include "spice_simulator.h"
#include "spice_value.h" #include "spice_value.h"
@ -43,14 +44,14 @@ struct SPICE_DC_PARAMS
}; };
/// Special netlist exporter flavor that allows one to override simulation commands /// Special netlist exporter flavor that allows one to override simulation commands
class NETLIST_EXPORTER_PSPICE_SIM : public NETLIST_EXPORTER_PSPICE class NGSPICE_CIRCUIT_MODEL : public NETLIST_EXPORTER_PSPICE, public SIMULATION_MODEL
{ {
public: public:
NETLIST_EXPORTER_PSPICE_SIM( SCHEMATIC_IFACE* aSchematic ) : NGSPICE_CIRCUIT_MODEL( SCHEMATIC_IFACE* aSchematic ) :
NETLIST_EXPORTER_PSPICE( aSchematic ) NETLIST_EXPORTER_PSPICE( aSchematic )
{ {
} }
virtual ~NETLIST_EXPORTER_PSPICE_SIM() {} virtual ~NGSPICE_CIRCUIT_MODEL() {}
/** /**
* Return name of Spice dataset for a specific plot. * Return name of Spice dataset for a specific plot.
@ -80,6 +81,16 @@ public:
*/ */
static const std::vector<wxString>& GetCurrents( SPICE_PRIMITIVE aPrimitive ); static const std::vector<wxString>& GetCurrents( SPICE_PRIMITIVE aPrimitive );
void SetOptions( int aOptions )
{
m_options = aOptions;
}
bool GetNetlist( OUTPUTFORMATTER* aFormatter )
{
return NGSPICE_CIRCUIT_MODEL::Format( aFormatter, m_options );
}
/** /**
* Override the simulation command directive. * Override the simulation command directive.
*/ */
@ -152,6 +163,7 @@ private:
///< Custom simulation command (has priority over the schematic sheet simulation commands) ///< Custom simulation command (has priority over the schematic sheet simulation commands)
wxString m_simCommand; wxString m_simCommand;
int m_options;
}; };
#endif /* NETLIST_EXPORTER_PSPICE_SIM_H */ #endif /* NETLIST_EXPORTER_PSPICE_SIM_H */

View File

@ -27,7 +27,7 @@
#include "sim_panel_base.h" #include "sim_panel_base.h"
#include "sim_plot_frame.h" #include "sim_plot_frame.h"
#include "netlist_exporter_pspice_sim.h" #include "ngspice_helpers.h"
SIM_PANEL_BASE::SIM_PANEL_BASE() : m_simCommand( wxEmptyString ) SIM_PANEL_BASE::SIM_PANEL_BASE() : m_simCommand( wxEmptyString )
@ -71,7 +71,7 @@ bool SIM_PANEL_BASE::IsPlottable( SIM_TYPE aSimType )
SIM_TYPE SIM_PANEL_BASE::GetType() const SIM_TYPE SIM_PANEL_BASE::GetType() const
{ {
return NETLIST_EXPORTER_PSPICE_SIM::CommandToSimType( m_simCommand ); return NGSPICE_CIRCUIT_MODEL::CommandToSimType( m_simCommand );
} }

View File

@ -27,7 +27,7 @@
#define __SIM_PLOT_PANEL_BASE_H #define __SIM_PLOT_PANEL_BASE_H
#include "sim_types.h" #include "sim_types.h"
#include "netlist_exporter_pspice_sim.h" #include "ngspice_helpers.h"
#include <wx/panel.h> #include <wx/panel.h>
#include <wx/sizer.h> #include <wx/sizer.h>
#include <wx/stattext.h> #include <wx/stattext.h>
@ -58,7 +58,7 @@ protected:
void setSimCommand( const wxString& aSimCommand ) void setSimCommand( const wxString& aSimCommand )
{ {
wxCHECK_RET( GetType() == NETLIST_EXPORTER_PSPICE_SIM::CommandToSimType( aSimCommand ), wxCHECK_RET( GetType() == NGSPICE_CIRCUIT_MODEL::CommandToSimType( aSimCommand ),
"Cannot change the type of simulation of the existing plot panel" ); "Cannot change the type of simulation of the existing plot panel" );
m_simCommand = aSimCommand; m_simCommand = aSimCommand;

View File

@ -37,7 +37,7 @@
#include <widgets/tuner_slider.h> #include <widgets/tuner_slider.h>
#include <dialogs/dialog_signal_list.h> #include <dialogs/dialog_signal_list.h>
#include "string_utils.h" #include "string_utils.h"
#include "netlist_exporter_pspice_sim.h" #include "ngspice_helpers.h"
#include <pgm_base.h> #include <pgm_base.h>
#include "ngspice.h" #include "ngspice.h"
#include "sim_plot_colors.h" #include "sim_plot_colors.h"
@ -129,7 +129,7 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
icon.CopyFromBitmap( KiBitmap( BITMAPS::simulator ) ); icon.CopyFromBitmap( KiBitmap( BITMAPS::simulator ) );
SetIcon( icon ); SetIcon( icon );
m_simulator = SPICE_SIMULATOR::CreateInstance( "ngspice" ); m_simulator = SIMULATOR::CreateInstance( "ngspice" );
if( !m_simulator ) if( !m_simulator )
{ {
@ -157,7 +157,7 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
// instead of being behind the dialog frame (as it does) // instead of being behind the dialog frame (as it does)
m_settingsDlg = nullptr; m_settingsDlg = nullptr;
m_exporter.reset( new NETLIST_EXPORTER_PSPICE_SIM( &m_schematicFrame->Schematic() ) ); m_exporter.reset( new NGSPICE_CIRCUIT_MODEL( &m_schematicFrame->Schematic() ) );
Bind( EVT_SIM_UPDATE, &SIM_PLOT_FRAME::onSimUpdate, this ); Bind( EVT_SIM_UPDATE, &SIM_PLOT_FRAME::onSimUpdate, this );
Bind( EVT_SIM_REPORT, &SIM_PLOT_FRAME::onSimReport, this ); Bind( EVT_SIM_REPORT, &SIM_PLOT_FRAME::onSimReport, this );
@ -239,6 +239,7 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
SIM_PLOT_FRAME::~SIM_PLOT_FRAME() SIM_PLOT_FRAME::~SIM_PLOT_FRAME()
{ {
m_simulator->Attach( nullptr );
m_simulator->SetReporter( nullptr ); m_simulator->SetReporter( nullptr );
delete m_reporter; delete m_reporter;
delete m_signalsIconColorList; delete m_signalsIconColorList;
@ -456,8 +457,6 @@ void SIM_PLOT_FRAME::StartSimulation( const wxString& aSimCommand )
wxCHECK_RET( m_exporter->CommandToSimType( getCurrentSimCommand() ) != ST_UNKNOWN, wxCHECK_RET( m_exporter->CommandToSimType( getCurrentSimCommand() ) != ST_UNKNOWN,
"Unknown simulation type" ); "Unknown simulation type" );
STRING_FORMATTER formatter;
if( !m_settingsDlg ) if( !m_settingsDlg )
m_settingsDlg = new DIALOG_SIM_SETTINGS( this, m_exporter, m_simulator->Settings() ); m_settingsDlg = new DIALOG_SIM_SETTINGS( this, m_exporter, m_simulator->Settings() );
@ -468,8 +467,9 @@ void SIM_PLOT_FRAME::StartSimulation( const wxString& aSimCommand )
else else
m_exporter->SetSimCommand( aSimCommand ); m_exporter->SetSimCommand( aSimCommand );
m_exporter->SetOptions( m_settingsDlg->GetNetlistOptions() );
if( !m_exporter->Format( &formatter, m_settingsDlg->GetNetlistOptions() ) ) if( !m_simulator->Attach( m_exporter ) )
{ {
DisplayErrorMessage( this, _( "There were errors during netlist export, aborted." ) ); DisplayErrorMessage( this, _( "There were errors during netlist export, aborted." ) );
return; return;
@ -479,7 +479,6 @@ void SIM_PLOT_FRAME::StartSimulation( const wxString& aSimCommand )
if( simulatorLock.owns_lock() ) if( simulatorLock.owns_lock() )
{ {
m_simulator->LoadNetlist( formatter.GetString() );
updateTuners(); updateTuners();
applyTuners(); applyTuners();
m_simulator->Run(); m_simulator->Run();
@ -492,7 +491,7 @@ void SIM_PLOT_FRAME::StartSimulation( const wxString& aSimCommand )
SIM_PANEL_BASE* SIM_PLOT_FRAME::NewPlotPanel( wxString aSimCommand ) SIM_PANEL_BASE* SIM_PLOT_FRAME::NewPlotPanel( wxString aSimCommand )
{ {
SIM_PANEL_BASE* plotPanel = nullptr; SIM_PANEL_BASE* plotPanel = nullptr;
SIM_TYPE simType = NETLIST_EXPORTER_PSPICE_SIM::CommandToSimType( aSimCommand ); SIM_TYPE simType = NGSPICE_CIRCUIT_MODEL::CommandToSimType( aSimCommand );
if( SIM_PANEL_BASE::IsPlottable( simType ) ) if( SIM_PANEL_BASE::IsPlottable( simType ) )
{ {
@ -614,7 +613,7 @@ SIM_PLOT_PANEL* SIM_PLOT_FRAME::GetCurrentPlot() const
} }
const NETLIST_EXPORTER_PSPICE_SIM* SIM_PLOT_FRAME::GetExporter() const const NGSPICE_CIRCUIT_MODEL* SIM_PLOT_FRAME::GetExporter() const
{ {
return m_exporter.get(); return m_exporter.get();
} }
@ -1473,7 +1472,7 @@ void SIM_PLOT_FRAME::onSettings( wxCommandEvent& event )
oldCommand = wxString(); oldCommand = wxString();
wxString newCommand = m_settingsDlg->GetSimCommand(); wxString newCommand = m_settingsDlg->GetSimCommand();
SIM_TYPE newSimType = NETLIST_EXPORTER_PSPICE_SIM::CommandToSimType( newCommand ); SIM_TYPE newSimType = NGSPICE_CIRCUIT_MODEL::CommandToSimType( newCommand );
// If it is a new simulation type, open a new plot // If it is a new simulation type, open a new plot
// For the DC sim, check if sweep source type has changed (char 4 will contain 'v', // For the DC sim, check if sweep source type has changed (char 4 will contain 'v',

View File

@ -51,7 +51,7 @@ class SCH_SYMBOL;
class SPICE_SIMULATOR; class SPICE_SIMULATOR;
class SPICE_SIMULATOR_SETTINGS; class SPICE_SIMULATOR_SETTINGS;
class NETLIST_EXPORTER_PSPICE_SIM; class NGSPICE_CIRCUIT_MODEL;
#include "sim_plot_panel.h" #include "sim_plot_panel.h"
#include "sim_panel_base.h" #include "sim_panel_base.h"
@ -126,7 +126,7 @@ public:
/** /**
* Return the netlist exporter object used for simulations. * Return the netlist exporter object used for simulations.
*/ */
const NETLIST_EXPORTER_PSPICE_SIM* GetExporter() const; const NGSPICE_CIRCUIT_MODEL* GetExporter() const;
/** /**
* @return the current background option for plotting. * @return the current background option for plotting.
@ -333,7 +333,7 @@ private:
wxToolBarToolBase* m_toolSettings; wxToolBarToolBase* m_toolSettings;
SCH_EDIT_FRAME* m_schematicFrame; SCH_EDIT_FRAME* m_schematicFrame;
std::shared_ptr<NETLIST_EXPORTER_PSPICE_SIM> m_exporter; std::shared_ptr<NGSPICE_CIRCUIT_MODEL> m_exporter;
std::shared_ptr<SPICE_SIMULATOR> m_simulator; std::shared_ptr<SPICE_SIMULATOR> m_simulator;
SIM_THREAD_REPORTER* m_reporter; SIM_THREAD_REPORTER* m_reporter;

110
eeschema/sim/simulator.h Normal file
View File

@ -0,0 +1,110 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Sylwester Kocjan <s.kocjan@o2.pl>
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <mutex>
#include <memory>
class SPICE_SIMULATOR;
class SIMULATION_MODEL
{
public:
virtual ~SIMULATION_MODEL() {};
};
class SIMULATION_RESULTS
{
public:
virtual ~SIMULATION_RESULTS() {};
};
class SIMULATION
{
virtual ~SIMULATION(){};
};
class SIMULATOR
{
public:
SIMULATOR() :
m_simModel( nullptr )
{}
virtual ~SIMULATOR() {}
///< Create a simulator instance of particular type (currently only ngspice is handled)
static std::shared_ptr<SPICE_SIMULATOR> CreateInstance( const std::string& aName );
/*
* @return mutex for exclusive access to the simulator.
*/
std::mutex& GetMutex()
{
return m_mutex;
}
/**
* Point out the model that will be used in future simulations.
*
* @return True in case of success, false otherwise.
*/
virtual bool Attach( const std::shared_ptr<SIMULATION_MODEL>& aModel )
{
m_simModel = aModel;
return true;
}
/**
* Execute the simulation with currently loaded netlist.
*
* @return True in case of success, false otherwise.
*/
virtual bool Run() = 0;
// virtual bool Run( SIMULATION* aSim ) = 0;
// virtual SIM_RESULT Run( SPICE_SIMULATION* aSim ) = 0;
/**
* Halt the simulation.
*
* @return True in case of success, false otherwise.
*/
virtual bool Stop() = 0;
/**
* Check if simulation is running at the moment.
*
* @return True if simulation is currently executed.
*/
virtual bool IsRunning() = 0;
protected:
///< Model that should be simulated.
std::shared_ptr<SIMULATION_MODEL> m_simModel;
private:
///< For interprocess synchronisation.
std::mutex m_mutex;
};

View File

@ -27,7 +27,7 @@
#include <confirm.h> #include <confirm.h>
std::shared_ptr<SPICE_SIMULATOR> SPICE_SIMULATOR::CreateInstance( const std::string& ) std::shared_ptr<SPICE_SIMULATOR> SIMULATOR::CreateInstance( const std::string& )
{ {
try try
{ {

View File

@ -29,6 +29,7 @@
#include "sim_types.h" #include "sim_types.h"
#include "spice_settings.h" #include "spice_settings.h"
#include "simulator.h"
#include <mutex> #include <mutex>
#include <string> #include <string>
@ -43,19 +44,17 @@ class SPICE_REPORTER;
typedef std::complex<double> COMPLEX; typedef std::complex<double> COMPLEX;
class SPICE_SIMULATOR class SPICE_SIMULATOR : public SIMULATOR
{ {
public: public:
SPICE_SIMULATOR() : SPICE_SIMULATOR() :
SIMULATOR(),
m_reporter( nullptr ), m_reporter( nullptr ),
m_settings( nullptr ) m_settings( nullptr )
{} {}
virtual ~SPICE_SIMULATOR() {} virtual ~SPICE_SIMULATOR() {}
///< Create a simulator instance of particular type (currently only ngspice is handled)
static std::shared_ptr<SPICE_SIMULATOR> CreateInstance( const std::string& aName );
/* /*
* Initialize the simulator using the optional \a aSettings. * Initialize the simulator using the optional \a aSettings.
* *
@ -64,14 +63,6 @@ public:
*/ */
virtual void Init( const SPICE_SIMULATOR_SETTINGS* aSettings = nullptr ) = 0; virtual void Init( const SPICE_SIMULATOR_SETTINGS* aSettings = nullptr ) = 0;
/*
* @return mutex for exclusive access to the simulator.
*/
std::mutex& GetMutex()
{
return m_mutex;
}
/** /**
* Load a netlist for the simulation. * Load a netlist for the simulation.
* *
@ -79,27 +70,6 @@ public:
*/ */
virtual bool LoadNetlist( const std::string& aNetlist ) = 0; virtual bool LoadNetlist( const std::string& aNetlist ) = 0;
/**
* Execute the simulation with currently loaded netlist.
*
* @return True in case of success, false otherwise.
*/
virtual bool Run() = 0;
/**
* Halt the simulation.
*
* @return True in case of success, false otherwise.
*/
virtual bool Stop() = 0;
/**
* Check if simulation is running at the moment.
*
* @return True if simulation is currently executed.
*/
virtual bool IsRunning() = 0;
/** /**
* Execute a Spice command as if it was typed into console. * Execute a Spice command as if it was typed into console.
* *
@ -213,10 +183,6 @@ protected:
///< We don't own this. We are just borrowing it from the #SCHEMATIC_SETTINGS. ///< We don't own this. We are just borrowing it from the #SCHEMATIC_SETTINGS.
std::shared_ptr<SPICE_SIMULATOR_SETTINGS> m_settings; std::shared_ptr<SPICE_SIMULATOR_SETTINGS> m_settings;
private:
///< For interprocess synchronisation.
std::mutex m_mutex;
}; };
#endif /* SPICE_SIMULATOR_H */ #endif /* SPICE_SIMULATOR_H */

View File

@ -29,7 +29,7 @@
#include <sim/sim_plot_frame.h> #include <sim/sim_plot_frame.h>
#include <sch_symbol.h> #include <sch_symbol.h>
#include <template_fieldnames.h> #include <template_fieldnames.h>
#include <sim/netlist_exporter_pspice_sim.h> #include <sim/ngspice_helpers.h>
#include <cmath> // log log1p expm1 #include <cmath> // log log1p expm1
#include <complex> // norm #include <complex> // norm

View File

@ -71,7 +71,7 @@ if( KICAD_SPICE )
set( QA_EESCHEMA_SRCS set( QA_EESCHEMA_SRCS
${QA_EESCHEMA_SRCS} ${QA_EESCHEMA_SRCS}
# Simulation tests # Simulation tests
sim/test_netlist_exporter_pspice_sim.cpp sim/test_ngspice_helpers.cpp
) )
endif() endif()

View File

@ -24,7 +24,7 @@
/** /**
* @file * @file
* Test suite for NETLIST_EXPORTER_PSPICE_SIM * Test suite for NGSPICE_CIRCUIT_MODEL
*/ */
#include <string.h> #include <string.h>
@ -36,12 +36,12 @@
#include <project.h> #include <project.h>
#include <schematic.h> #include <schematic.h>
#include <settings/settings_manager.h> #include <settings/settings_manager.h>
#include <sim/netlist_exporter_pspice_sim.h> #include <sim/ngspice_helpers.h>
class TEST_NETLIST_EXPORTER_PSPICE_SIM class TEST_NGSPICE_HELPERS
{ {
public: public:
TEST_NETLIST_EXPORTER_PSPICE_SIM() : TEST_NGSPICE_HELPERS() :
m_manager( true ), m_manager( true ),
m_schematic( nullptr ), m_schematic( nullptr ),
m_exporter( &m_schematic ) m_exporter( &m_schematic )
@ -50,7 +50,7 @@ public:
m_schematic.SetProject( &m_manager.Prj() ); m_schematic.SetProject( &m_manager.Prj() );
} }
virtual ~TEST_NETLIST_EXPORTER_PSPICE_SIM() virtual ~TEST_NGSPICE_HELPERS()
{ {
m_schematic.Reset(); m_schematic.Reset();
} }
@ -59,14 +59,14 @@ public:
SCHEMATIC m_schematic; SCHEMATIC m_schematic;
NETLIST_EXPORTER_PSPICE_SIM m_exporter; NGSPICE_CIRCUIT_MODEL m_exporter;
}; };
/** /**
* Declare the test suite * Declare the test suite
*/ */
BOOST_FIXTURE_TEST_SUITE( NetlistExporterPspiceSim, TEST_NETLIST_EXPORTER_PSPICE_SIM ) BOOST_FIXTURE_TEST_SUITE( NgspiceCircuitModel, TEST_NGSPICE_HELPERS )
/** /**
@ -109,7 +109,7 @@ BOOST_AUTO_TEST_CASE( CommandToSimType )
for( auto& step : testData ) for( auto& step : testData )
{ {
SIM_TYPE result = NETLIST_EXPORTER_PSPICE_SIM::CommandToSimType( step.command ); SIM_TYPE result = NGSPICE_CIRCUIT_MODEL::CommandToSimType( step.command );
BOOST_CHECK_EQUAL( result, step.type ); BOOST_CHECK_EQUAL( result, step.type );
} }
@ -117,7 +117,7 @@ BOOST_AUTO_TEST_CASE( CommandToSimType )
for( auto& step : testData ) for( auto& step : testData )
{ {
step.command.Append( "\n" ); step.command.Append( "\n" );
SIM_TYPE result = NETLIST_EXPORTER_PSPICE_SIM::CommandToSimType( step.command ); SIM_TYPE result = NGSPICE_CIRCUIT_MODEL::CommandToSimType( step.command );
BOOST_CHECK_EQUAL( result, step.type ); BOOST_CHECK_EQUAL( result, step.type );
} }