Spice simulator: add Ngspce model behavior mode settings.

ADDED: Ngspice simulator model behavior mode settings for PSpice, LTSpice,
       PSpice and LTSpice, and HSpice.

Fixes https://gitlab.com/kicad/code/kicad/issues/5810
This commit is contained in:
Wayne Stambaugh 2021-03-18 15:31:02 -04:00
parent 1641d6da79
commit acec6ad7fc
16 changed files with 1065 additions and 198 deletions

View File

@ -123,6 +123,7 @@
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
@ -133,6 +134,7 @@
0,
0,
0,
0,
1,
0,
0,
@ -146,6 +148,7 @@
0,
1,
0,
0,
1,
0,
2,
@ -159,6 +162,7 @@
0,
0,
0,
0,
1,
0,
1,
@ -172,6 +176,7 @@
0,
0,
0,
0,
1,
1,
2,
@ -185,6 +190,7 @@
0,
0,
0,
0,
1,
0,
0,
@ -192,12 +198,27 @@
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
@ -211,6 +232,7 @@
0,
1,
0,
0,
1,
0,
0,
@ -224,6 +246,7 @@
1,
2,
0,
0,
1,
0,
2,
@ -237,6 +260,7 @@
0,
1,
0,
0,
1,
0,
2,
@ -250,6 +274,7 @@
1,
1,
0,
0,
1,
0,
2,
@ -268,6 +293,7 @@
2,
2,
2,
2,
2
]
],
@ -278,7 +304,9 @@
"bus_to_net_conflict": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
@ -292,6 +320,8 @@
"pin_to_pin": "warning",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
@ -348,6 +378,7 @@
"default_text_size": 60.0,
"default_wire_thickness": 6.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
@ -362,6 +393,12 @@
"version": 0
},
"net_format_name": "",
"ngspice": {
"meta": {
"version": 0
},
"model_mode": 0
},
"page_layout_descr_file": "",
"plot_directory": "",
"spice_adjust_passive_values": false,

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016-2021 CERN
* Copyright (C) 2016-2021 KiCad Developers, see CHANGELOG.TXT for contributors.
* Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
@ -25,6 +25,8 @@
#include "dialog_sim_settings.h"
#include <sim/netlist_exporter_pspice_sim.h>
#include <sim/ngspice.h>
#include <confirm.h>
#include <wx/tokenzr.h>
@ -54,9 +56,11 @@ static wxString getStringSelection( const wxRadioBox* aCtrl )
}
DIALOG_SIM_SETTINGS::DIALOG_SIM_SETTINGS( wxWindow* aParent ) :
DIALOG_SIM_SETTINGS::DIALOG_SIM_SETTINGS( wxWindow* aParent,
std::shared_ptr<SPICE_SIMULATOR_SETTINGS>& aSettings ) :
DIALOG_SIM_SETTINGS_BASE( aParent ),
m_exporter( nullptr ),
m_settings( aSettings ),
m_spiceEmptyValidator( true )
{
m_posIntValidator.SetMin( 1 );
@ -91,6 +95,9 @@ DIALOG_SIM_SETTINGS::DIALOG_SIM_SETTINGS( wxWindow* aParent ) :
m_simPages->RemovePage( m_simPages->FindPage( m_pgSensitivity ) );
m_simPages->RemovePage( m_simPages->FindPage( m_pgTransferFunction ) );
if( dynamic_cast<NGSPICE_SIMULATOR_SETTINGS*>( aSettings.get() ) == nullptr )
m_simPages->RemovePage( m_simPages->FindPage( m_pgNgspice ) );
m_sdbSizerOK->SetDefault();
updateNetlistOpts();
@ -155,6 +162,26 @@ bool DIALOG_SIM_SETTINGS::TransferDataFromWindow()
if( !wxDialog::TransferDataFromWindow() )
return false;
// The simulator dependent settings always get transferred.
NGSPICE_SIMULATOR_SETTINGS* ngspiceSettings =
dynamic_cast<NGSPICE_SIMULATOR_SETTINGS*>( m_settings.get() );
if( ngspiceSettings )
{
if( m_rbNgspiceDefaultModelMode->GetValue() )
ngspiceSettings->SetModelMode( NGSPICE_MODEL_MODE::USER_CONFIG );
else if( m_rbNgspiceSpiceModelMode->GetValue() )
ngspiceSettings->SetModelMode( NGSPICE_MODEL_MODE::NGSPICE );
else if( m_rbNgspicePSpiceModelMode->GetValue() )
ngspiceSettings->SetModelMode( NGSPICE_MODEL_MODE::PSPICE );
else if( m_rbNgspiceLTSpiceModelMode->GetValue() )
ngspiceSettings->SetModelMode( NGSPICE_MODEL_MODE::LTSPICE );
else if( m_rbNgspicePLTSpiceModelMode->GetValue() )
ngspiceSettings->SetModelMode( NGSPICE_MODEL_MODE::LT_PSPICE );
else if( m_rbNgspiceHSpiceModelMode->GetValue() )
ngspiceSettings->SetModelMode( NGSPICE_MODEL_MODE::HSPICE );
}
wxWindow* page = m_simPages->GetCurrentPage();
// AC analysis
@ -279,10 +306,48 @@ bool DIALOG_SIM_SETTINGS::TransferDataFromWindow()
bool DIALOG_SIM_SETTINGS::TransferDataToWindow()
{
/// @todo one day it could interpret the sim command and fill out appropriate fields..
/// @todo one day it could interpret the sim command and fill out appropriate fields.
if( empty( m_customTxt ) )
loadDirectives();
NGSPICE_SIMULATOR_SETTINGS* ngspiceSettings =
dynamic_cast<NGSPICE_SIMULATOR_SETTINGS*>( m_settings.get() );
if( ngspiceSettings )
{
switch( ngspiceSettings->GetModelMode() )
{
case NGSPICE_MODEL_MODE::USER_CONFIG:
m_rbNgspiceDefaultModelMode->SetValue( true );
break;
case NGSPICE_MODEL_MODE::NGSPICE:
m_rbNgspiceSpiceModelMode->SetValue( true );
break;
case NGSPICE_MODEL_MODE::PSPICE:
m_rbNgspicePSpiceModelMode->SetValue( true );
break;
case NGSPICE_MODEL_MODE::LTSPICE:
m_rbNgspiceLTSpiceModelMode->SetValue( true );
break;
case NGSPICE_MODEL_MODE::LT_PSPICE:
m_rbNgspicePLTSpiceModelMode->SetValue( true );
break;
case NGSPICE_MODEL_MODE::HSPICE:
m_rbNgspiceHSpiceModelMode->SetValue( true );
break;
default:
wxFAIL_MSG( wxString::Format( "Unkown NGSPICE_MODEL_MODE %d.",
ngspiceSettings->GetModelMode() ) );
break;
}
}
if( m_simCommand.IsEmpty() && !empty( m_customTxt ) )
return parseCommand( m_customTxt->GetValue() );
@ -320,6 +385,7 @@ int DIALOG_SIM_SETTINGS::ShowModal()
return DIALOG_SIM_SETTINGS_BASE::ShowModal();
}
void DIALOG_SIM_SETTINGS::updateDCSources( wxChar aType, wxChoice* aSource )
{
wxString prevSelection;
@ -396,7 +462,6 @@ bool DIALOG_SIM_SETTINGS::parseCommand( const wxString& aCommand )
m_acFreqStart->SetValue( SPICE_VALUE( tokenizer.GetNextToken() ).ToSpiceString() );
m_acFreqStop->SetValue( SPICE_VALUE( tokenizer.GetNextToken() ).ToSpiceString() );
}
else if( tkn == ".dc" )
{
SPICE_DC_PARAMS src1, src2;
@ -436,7 +501,6 @@ bool DIALOG_SIM_SETTINGS::parseCommand( const wxString& aCommand )
refreshUIControls();
}
else if( tkn == ".tran" )
{
m_simPages->SetSelection( m_simPages->FindPage( m_pgTransient ) );
@ -451,14 +515,11 @@ bool DIALOG_SIM_SETTINGS::parseCommand( const wxString& aCommand )
if( !tkn.IsEmpty() )
m_transInitial->SetValue( SPICE_VALUE( tkn ).ToSpiceString() );
}
else if( tkn == ".op" )
{
m_simPages->SetSelection( m_simPages->FindPage( m_pgOP ) );
}
// Custom directives
else if( !empty( m_customTxt ) )
else if( !empty( m_customTxt ) ) // Custom directives
{
m_simPages->SetSelection( m_simPages->FindPage( m_pgCustom ) );
}

View File

@ -2,6 +2,8 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 CERN
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
@ -31,11 +33,13 @@
#include <wx/valnum.h>
class NETLIST_EXPORTER_PSPICE_SIM;
class SPICE_SIMULATOR_SETTINGS;
class DIALOG_SIM_SETTINGS : public DIALOG_SIM_SETTINGS_BASE
{
public:
DIALOG_SIM_SETTINGS( wxWindow* aParent );
DIALOG_SIM_SETTINGS( wxWindow* aParent, std::shared_ptr<SPICE_SIMULATOR_SETTINGS>& aSettings );
const wxString& GetSimCommand() const
{
@ -67,7 +71,7 @@ public:
// The default dialog Validate() calls the validators of all widgets.
// This is not what we want; We want only validators of the selected page
// of the notbooks. So disable the wxDialog::Validate(), and let our
// of the notebooks. So disable the wxDialog::Validate(), and let our
// TransferDataFromWindow doing the job.
virtual bool Validate() override
{
@ -84,7 +88,7 @@ private:
LINEAR
};
///!> Generates events to update UI state
///< Generate events to update UI state.
void refreshUIControls()
{
wxQueueEvent( m_dcEnable2, new wxCommandEvent( wxEVT_CHECKBOX ) );
@ -93,19 +97,20 @@ private:
}
/**
* @brief Reads values from one DC sweep source to form a part of sim command
* Read values from one DC sweep source to form a part of simulation command.
*
* @return string of four SPICE values if values are correct, empty string upon error.
*/
wxString evaluateDCControls( wxChoice* aDcSource, wxTextCtrl* aDcStart, wxTextCtrl* aDcStop,
wxTextCtrl* aDcIncr );
/**
* @brief Updates DC sweep source with components from schematic
* Update DC sweep source with components from schematic.
*/
void updateDCSources( wxChar aType, wxChoice* aSource );
/**
* @brief Updates units on labels depending on selected source
* Update units on labels depending on selected source.
*/
void updateDCUnits( wxChar aType, wxChoice* aSource, wxStaticText* aStartValUnit,
wxStaticText* aEndValUnit, wxStaticText* aStepUnit );
@ -120,9 +125,10 @@ private:
}
/**
* @brief Parses a Spice directive.
* Parse a Spice directive.
*
* @param aCommand is the directive to be parsed (e.g. ".tran 10n 1000n").
* @return bool if the directive was parsed correctly.
* @return true if the directive was parsed correctly.
*/
bool parseCommand( const wxString& aCommand );
@ -155,14 +161,14 @@ private:
{
switch( aOption )
{
case DECADE:
return wxString( "dec" );
case DECADE:
return wxString( "dec" );
case OCTAVE:
return wxString( "oct" );
case OCTAVE:
return wxString( "oct" );
case LINEAR:
return wxString( "lin" );
case LINEAR:
return wxString( "lin" );
}
wxASSERT_MSG( false, "Unhandled scale type" );
@ -176,7 +182,7 @@ private:
wxString m_simCommand;
int m_netlistOpts;
NETLIST_EXPORTER_PSPICE_SIM* m_exporter;
std::shared_ptr<SPICE_SIMULATOR_SETTINGS> m_settings;
SPICE_VALIDATOR m_spiceValidator;
SPICE_VALIDATOR m_spiceEmptyValidator;
wxIntegerValidator<int> m_posIntValidator;

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Oct 26 2018)
// C++ code generated with wxFormBuilder (version 3.9.0 Jun 18 2020)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -17,8 +17,6 @@ DIALOG_SIM_SETTINGS_BASE::DIALOG_SIM_SETTINGS_BASE( wxWindow* parent, wxWindowID
bSizer1 = new wxBoxSizer( wxVERTICAL );
m_simPages = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
m_simPages->SetMinSize( wxSize( 650,-1 ) );
m_pgAC = new wxPanel( m_simPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizer3;
bSizer3 = new wxBoxSizer( wxVERTICAL );
@ -199,7 +197,7 @@ DIALOG_SIM_SETTINGS_BASE::DIALOG_SIM_SETTINGS_BASE( wxWindow* parent, wxWindowID
m_pgDC->SetSizer( bSizer82 );
m_pgDC->Layout();
bSizer82->Fit( m_pgDC );
m_simPages->AddPage( m_pgDC, _("DC Transfer"), true );
m_simPages->AddPage( m_pgDC, _("DC Transfer"), false );
m_pgDistortion = new wxPanel( m_simPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
m_simPages->AddPage( m_pgDistortion, _("Distortion"), false );
m_pgNoise = new wxPanel( m_simPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
@ -417,6 +415,51 @@ DIALOG_SIM_SETTINGS_BASE::DIALOG_SIM_SETTINGS_BASE( wxWindow* parent, wxWindowID
m_pgCustom->Layout();
bSizer2->Fit( m_pgCustom );
m_simPages->AddPage( m_pgCustom, _("Custom"), false );
m_pgNgspice = new wxPanel( m_simPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizer21;
bSizer21 = new wxBoxSizer( wxVERTICAL );
wxStaticBoxSizer* sbSizer4;
sbSizer4 = new wxStaticBoxSizer( new wxStaticBox( m_pgNgspice, wxID_ANY, _("Model Mode") ), wxVERTICAL );
m_rbNgspiceDefaultModelMode = new wxRadioButton( sbSizer4->GetStaticBox(), wxID_ANY, _("User configuration"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
m_rbNgspiceDefaultModelMode->SetToolTip( _("Use the settings in the Ngspice configuration file or any settings defined in the schematic") );
sbSizer4->Add( m_rbNgspiceDefaultModelMode, 0, wxLEFT|wxRIGHT, 5 );
m_rbNgspiceSpiceModelMode = new wxRadioButton( sbSizer4->GetStaticBox(), wxID_ANY, _("Spice"), wxDefaultPosition, wxDefaultSize, 0 );
m_rbNgspiceSpiceModelMode->SetToolTip( _("Enable default spice model simulation") );
sbSizer4->Add( m_rbNgspiceSpiceModelMode, 0, wxALL, 5 );
m_rbNgspicePSpiceModelMode = new wxRadioButton( sbSizer4->GetStaticBox(), wxID_ANY, _("PSpice"), wxDefaultPosition, wxDefaultSize, 0 );
m_rbNgspicePSpiceModelMode->SetToolTip( _("Enable PSpice model simulation") );
sbSizer4->Add( m_rbNgspicePSpiceModelMode, 0, wxALL, 5 );
m_rbNgspiceLTSpiceModelMode = new wxRadioButton( sbSizer4->GetStaticBox(), wxID_ANY, _("LTSpice"), wxDefaultPosition, wxDefaultSize, 0 );
m_rbNgspiceLTSpiceModelMode->SetToolTip( _("Enable LTSpice model simulation") );
sbSizer4->Add( m_rbNgspiceLTSpiceModelMode, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 );
m_rbNgspicePLTSpiceModelMode = new wxRadioButton( sbSizer4->GetStaticBox(), wxID_ANY, _("PSpice and LTSpice"), wxDefaultPosition, wxDefaultSize, 0 );
m_rbNgspicePLTSpiceModelMode->SetToolTip( _("Enable PSpice and LTSpice model simulation") );
sbSizer4->Add( m_rbNgspicePLTSpiceModelMode, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 );
m_rbNgspiceHSpiceModelMode = new wxRadioButton( sbSizer4->GetStaticBox(), wxID_ANY, _("HSpice"), wxDefaultPosition, wxDefaultSize, 0 );
m_rbNgspiceHSpiceModelMode->SetToolTip( _("Enable HSpice model simulation") );
sbSizer4->Add( m_rbNgspiceHSpiceModelMode, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 );
bSizer21->Add( sbSizer4, 0, wxALL, 5 );
m_pgNgspice->SetSizer( bSizer21 );
m_pgNgspice->Layout();
bSizer21->Fit( m_pgNgspice );
m_simPages->AddPage( m_pgNgspice, _("Ngspice"), true );
bSizer1->Add( m_simPages, 1, wxEXPAND | wxALL, 5 );

View File

@ -14,6 +14,7 @@
<property name="file">dialog_sim_settings_base</property>
<property name="first_id">1000</property>
<property name="help_provider">none</property>
<property name="image_path_wrapper_function_name"></property>
<property name="indent_with_spaces"></property>
<property name="internationalize">1</property>
<property name="name">DIALOG_SIM_SETTINGS_BASE</property>
@ -25,6 +26,7 @@
<property name="skip_php_events">1</property>
<property name="skip_python_events">1</property>
<property name="ui_table">UI</property>
<property name="use_array_enum">0</property>
<property name="use_enum">0</property>
<property name="use_microsoft_bom">0</property>
<object class="Dialog" expanded="1">
@ -97,7 +99,7 @@
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">650,-1</property>
<property name="minimum_size">-1,-1</property>
<property name="moveable">1</property>
<property name="name">m_simPages</property>
<property name="pane_border">1</property>
@ -803,7 +805,7 @@
<object class="notebookpage" expanded="1">
<property name="bitmap"></property>
<property name="label">DC Transfer</property>
<property name="select">1</property>
<property name="select">0</property>
<object class="wxPanel" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
@ -879,7 +881,7 @@
<property name="name">bSizer151</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="0">
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
@ -2294,6 +2296,7 @@
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="auth_needed">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="bitmap"></property>
@ -3467,7 +3470,7 @@
</object>
</object>
</object>
<object class="notebookpage" expanded="0">
<object class="notebookpage" expanded="1">
<property name="bitmap"></property>
<property name="label">Operating Point</property>
<property name="select">0</property>
@ -4522,7 +4525,7 @@
</object>
</object>
</object>
<object class="notebookpage" expanded="0">
<object class="notebookpage" expanded="1">
<property name="bitmap"></property>
<property name="label">Custom</property>
<property name="select">0</property>
@ -4720,6 +4723,7 @@
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="auth_needed">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="bitmap"></property>
@ -4783,13 +4787,474 @@
</object>
</object>
</object>
<object class="notebookpage" expanded="1">
<property name="bitmap"></property>
<property name="label">Ngspice</property>
<property name="select">1</property>
<object class="wxPanel" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_pgNgspice</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bSizer21</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxStaticBoxSizer" expanded="1">
<property name="id">wxID_ANY</property>
<property name="label">Model Mode</property>
<property name="minimum_size"></property>
<property name="name">sbSizer4</property>
<property name="orient">wxVERTICAL</property>
<property name="parent">1</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxLEFT|wxRIGHT</property>
<property name="proportion">0</property>
<object class="wxRadioButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">User configuration</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_rbNgspiceDefaultModelMode</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxRB_GROUP</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Use the settings in the Ngspice configuration file or any settings defined in the schematic</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxRadioButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Spice</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_rbNgspiceSpiceModelMode</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Enable default spice model simulation</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxRadioButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">PSpice</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_rbNgspicePSpiceModelMode</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Enable PSpice model simulation</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxBOTTOM|wxLEFT|wxRIGHT</property>
<property name="proportion">0</property>
<object class="wxRadioButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">LTSpice</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_rbNgspiceLTSpiceModelMode</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Enable LTSpice model simulation</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxBOTTOM|wxLEFT|wxRIGHT</property>
<property name="proportion">0</property>
<object class="wxRadioButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">PSpice and LTSpice</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_rbNgspicePLTSpiceModelMode</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Enable PSpice and LTSpice model simulation</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxBOTTOM|wxLEFT|wxRIGHT</property>
<property name="proportion">0</property>
<object class="wxRadioButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">HSpice</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_rbNgspiceHSpiceModelMode</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Enable HSpice model simulation</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="0">
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxALL</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="0">
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bSizer88</property>
<property name="orient">wxVERTICAL</property>

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Oct 26 2018)
// C++ code generated with wxFormBuilder (version 3.9.0 Jun 18 2020)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -30,6 +30,8 @@
#include <wx/button.h>
#include <wx/gbsizer.h>
#include <wx/combobox.h>
#include <wx/radiobut.h>
#include <wx/statbox.h>
#include <wx/notebook.h>
#include <wx/dialog.h>
@ -114,6 +116,13 @@ class DIALOG_SIM_SETTINGS_BASE : public DIALOG_SHIM
wxStaticText* m_staticText18;
wxTextCtrl* m_customTxt;
wxButton* m_loadDirectives;
wxPanel* m_pgNgspice;
wxRadioButton* m_rbNgspiceDefaultModelMode;
wxRadioButton* m_rbNgspiceSpiceModelMode;
wxRadioButton* m_rbNgspicePSpiceModelMode;
wxRadioButton* m_rbNgspiceLTSpiceModelMode;
wxRadioButton* m_rbNgspicePLTSpiceModelMode;
wxRadioButton* m_rbNgspiceHSpiceModelMode;
wxCheckBox* m_fixPassiveVals;
wxCheckBox* m_fixIncludePaths;
wxStdDialogButtonSizer* m_sdbSizer;

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2020-2021 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
@ -26,6 +26,7 @@
#include <project/net_settings.h>
#include <schematic.h>
#include <sch_screen.h>
#include <sim/ngspice.h>
SCHEMATIC::SCHEMATIC( PROJECT* aPrj ) :
@ -92,6 +93,7 @@ void SCHEMATIC::SetProject( PROJECT* aPrj )
project.m_SchematicSettings = new SCHEMATIC_SETTINGS( &project, "schematic" );
project.m_SchematicSettings->LoadFromFile();
project.m_SchematicSettings->m_NgspiceSimulatorSettings->LoadFromFile();
project.m_ErcSettings->LoadFromFile();
}
}

View File

@ -2,6 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 CERN
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
* @author Jon Evans <jon@craftyjon.com>
*
* This program is free software: you can redistribute it and/or modify it
@ -27,6 +28,7 @@
#include <kiface_i.h>
#include <schematic_settings.h>
#include <settings/parameters.h>
#include <sim/ngspice.h>
const int schSettingsSchemaVersion = 0;
@ -47,7 +49,8 @@ SCHEMATIC_SETTINGS::SCHEMATIC_SETTINGS( JSON_SETTINGS* aParent, const std::strin
m_IntersheetRefsFormatShort( false ),
m_IntersheetRefsPrefix( DEFAULT_IREF_PREFIX ),
m_IntersheetRefsSuffix( DEFAULT_IREF_SUFFIX ),
m_SpiceAdjustPassiveValues( false )
m_SpiceAdjustPassiveValues( false ),
m_NgspiceSimulatorSettings( nullptr )
{
EESCHEMA_SETTINGS* appSettings = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
@ -206,6 +209,9 @@ SCHEMATIC_SETTINGS::SCHEMATIC_SETTINGS( JSON_SETTINGS* aParent, const std::strin
m_params.emplace_back( new PARAM<int>( "subpart_first_id",
LIB_PART::SubpartFirstIdPtr(), 'A', '1', 'z' ) );
m_NgspiceSimulatorSettings =
std::make_shared<NGSPICE_SIMULATOR_SETTINGS>( this, "ngspice" );
}

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2020-2021 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
@ -25,12 +25,14 @@
#include <settings/nested_settings.h>
#include <template_fieldnames.h>
class NGSPICE_SIMULATOR_SETTINGS;
/**
* These settings were stored in SCH_BASE_FRAME previously.
* The backing store is currently the project file.
* They should likely move to a project settings file (JSON) once that framework exists.
*
* These are loaded from eeschema settings but then overwritten by the project settings.
* These are loaded from Eeschema settings but then overwritten by the project settings.
* All of the values are stored in IU, but the backing file stores in mils.
*/
class SCHEMATIC_SETTINGS : public NESTED_SETTINGS
@ -64,10 +66,16 @@ public:
wxString m_NetFormatName;
///< @todo These should probably be moved to the "schematic.simulator" path.
bool m_SpiceAdjustPassiveValues;
wxString m_SpiceCommandString; // A command string to run external spice
TEMPLATES m_TemplateFieldNames;
/**
* Ngspice simulator settings.
*/
std::shared_ptr<NGSPICE_SIMULATOR_SETTINGS> m_NgspiceSimulatorSettings;
};
#endif

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016-2018 CERN
* Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2018-2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Maciej Suminski <maciej.suminski@cern.ch>
@ -31,6 +31,9 @@
#include "ngspice.h"
#include "spice_reporter.h"
#include <schematic_settings.h>
#include <settings/parameters.h>
#include <common.h>
#include <locale_io.h>
@ -45,18 +48,50 @@
using namespace std;
/**
* Flag to enable debug output of Ngspice simulator.
*
* Use "KICAD_NGSPICE" to enable Ngspice simulator tracing.
*
* @ingroup trace_env_vars
*/
static const wxChar* const traceNgspice = wxT( "KICAD_NGSPICE" );
NGSPICE::NGSPICE()
: m_ngSpice_Init( nullptr ),
m_ngSpice_Circ( nullptr ),
m_ngSpice_Command( nullptr ),
m_ngGet_Vec_Info( nullptr ),
m_ngSpice_CurPlot( nullptr ),
m_ngSpice_AllPlots( nullptr ),
m_ngSpice_AllVecs( nullptr ),
m_ngSpice_Running( nullptr ),
m_error( false )
NGSPICE_SIMULATOR_SETTINGS::NGSPICE_SIMULATOR_SETTINGS(
JSON_SETTINGS* aParent, const std::string& aPath ) :
SPICE_SIMULATOR_SETTINGS( aParent, aPath ),
m_modelMode( NGSPICE_MODEL_MODE::USER_CONFIG )
{
m_params.emplace_back( new PARAM_ENUM<NGSPICE_MODEL_MODE>( "model_mode", &m_modelMode,
NGSPICE_MODEL_MODE::USER_CONFIG,
NGSPICE_MODEL_MODE::USER_CONFIG,
NGSPICE_MODEL_MODE::HSPICE ) );
}
bool NGSPICE_SIMULATOR_SETTINGS::operator==( const SPICE_SIMULATOR_SETTINGS& aRhs ) const
{
const NGSPICE_SIMULATOR_SETTINGS* settings =
dynamic_cast<const NGSPICE_SIMULATOR_SETTINGS*>( &aRhs );
wxCHECK( settings, false );
return m_modelMode == settings->m_modelMode;
}
NGSPICE::NGSPICE() :
m_ngSpice_Init( nullptr ),
m_ngSpice_Circ( nullptr ),
m_ngSpice_Command( nullptr ),
m_ngGet_Vec_Info( nullptr ),
m_ngSpice_CurPlot( nullptr ),
m_ngSpice_AllPlots( nullptr ),
m_ngSpice_AllVecs( nullptr ),
m_ngSpice_Running( nullptr ),
m_error( false )
{
init_dll();
}
@ -67,9 +102,15 @@ NGSPICE::~NGSPICE()
}
void NGSPICE::Init()
void NGSPICE::Init( const SPICE_SIMULATOR_SETTINGS* aSettings )
{
Command( "reset" );
for( const std::string& command : GetSettingCommands() )
{
wxLogTrace( traceNgspice, "Sending Ngspice configuration command '%s'.", command );
Command( command );
}
}
@ -81,6 +122,7 @@ vector<string> NGSPICE::AllPlots() const
int noOfPlots = 0;
vector<string> retVal;
if( allPlots != nullptr )
{
for( char** plot = allPlots; *plot != nullptr; plot++ )
@ -297,35 +339,86 @@ string NGSPICE::GetXAxis( SIM_TYPE aType ) const
{
switch( aType )
{
case ST_AC:
case ST_NOISE:
return string( "frequency" );
case ST_AC:
case ST_NOISE:
return string( "frequency" );
case ST_DC:
// find plot, which ends with "-sweep"
for( auto& plot : AllPlots() )
case ST_DC:
// find plot, which ends with "-sweep"
for( auto& plot : AllPlots() )
{
const string sweepEnding = "-sweep";
unsigned int len = sweepEnding.length();
if( plot.length() > len
&& plot.substr( plot.length() - len, len ).compare( sweepEnding ) == 0 )
{
const string sweepEnding = "-sweep";
unsigned int len = sweepEnding.length();
if( plot.length() > len
&& plot.substr( plot.length() - len, len ).compare( sweepEnding ) == 0 )
{
return string( plot );
}
return string( plot );
}
break;
}
break;
case ST_TRANSIENT:
return string( "time" );
case ST_TRANSIENT:
return string( "time" );
default:
break;
default:
break;
}
return string( "" );
}
std::vector<std::string> NGSPICE::GetSettingCommands() const
{
const NGSPICE_SIMULATOR_SETTINGS* settings =
dynamic_cast<const NGSPICE_SIMULATOR_SETTINGS*>( Settings().get() );
std::vector<std::string> commands;
wxCHECK( settings, commands );
switch( settings->GetModelMode() )
{
case NGSPICE_MODEL_MODE::USER_CONFIG:
break;
case NGSPICE_MODEL_MODE::NGSPICE:
commands.emplace_back( "unset ngbehavior" );
break;
case NGSPICE_MODEL_MODE::PSPICE:
commands.emplace_back( "set ngbehavior=ps" );
break;
case NGSPICE_MODEL_MODE::LTSPICE:
commands.emplace_back( "set ngbehavior=lt" );
break;
case NGSPICE_MODEL_MODE::LT_PSPICE:
commands.emplace_back( "set ngbehavior=ltps" );
break;
case NGSPICE_MODEL_MODE::HSPICE:
commands.emplace_back( "set ngbehavior=hs" );
break;
default:
wxFAIL_MSG( wxString::Format( "Undefined NGSPICE_MODEL_MODE %d.",
settings->GetModelMode() ) );
break;
}
return commands;
}
const std::string NGSPICE::GetNetlist() const
{
return m_netlist;
}
void NGSPICE::init_dll()
{
if( m_initialized )
@ -337,22 +430,26 @@ void NGSPICE::init_dll()
if( m_dll.IsLoaded() ) // enable force reload
m_dll.Unload();
// Extra effort to find libngspice
// Extra effort to find libngspice
// @todo Shouldn't we be using the normal KiCad path searching mechanism here?
wxFileName dllFile( "", NGSPICE_DLL_FILE );
#if defined(__WINDOWS__)
#if defined( _MSC_VER )
#if defined( _MSC_VER )
const vector<string> dllPaths = { "" };
#else
#else
const vector<string> dllPaths = { "", "/mingw64/bin", "/mingw32/bin" };
#endif
#endif
#elif defined(__WXMAC__)
const vector<string> dllPaths = {
PATHS::GetOSXKicadUserDataDir().ToStdString() + "/PlugIns/ngspice",
PATHS::GetOSXKicadMachineDataDir().ToStdString() + "/PlugIns/ngspice",
// when running kicad.app
stdPaths.GetPluginsDir().ToStdString() + "/sim",
// when running eeschema.app
wxFileName( stdPaths.GetExecutablePath() ).GetPath().ToStdString() + "/../../../../../Contents/PlugIns/sim"
wxFileName( stdPaths.GetExecutablePath() ).GetPath().ToStdString() +
"/../../../../../Contents/PlugIns/sim"
};
#else // Unix systems
const vector<string> dllPaths = { "/usr/local/lib" };
@ -374,8 +471,7 @@ void NGSPICE::init_dll()
if( !m_dll.IsLoaded() ) // try also the system libraries
m_dll.Load( wxDynamicLibrary::CanonicalizeName( "ngspice" ) );
#else // here: __LINUX__
#else
// First, try the system libraries
m_dll.Load( NGSPICE_DLL_FILE, wxDL_VERBATIM | wxDL_QUIET | wxDL_NOW );
@ -412,7 +508,8 @@ void NGSPICE::init_dll()
m_ngSpice_AllVecs = (ngSpice_AllVecs) m_dll.GetSymbol( "ngSpice_AllVecs" );
m_ngSpice_Running = (ngSpice_Running) m_dll.GetSymbol( "ngSpice_running" ); // it is not a typo
m_ngSpice_Init( &cbSendChar, &cbSendStat, &cbControlledExit, NULL, NULL, &cbBGThreadRunning, this );
m_ngSpice_Init( &cbSendChar, &cbSendStat, &cbControlledExit, NULL, NULL,
&cbBGThreadRunning, this );
// Load a custom spinit file, to fix the problem with loading .cm files
// Switch to the executable directory, so the relative paths are correct
@ -433,8 +530,9 @@ void NGSPICE::init_dll()
".",
#ifdef __WXMAC__
stdPaths.GetPluginsDir().ToStdString() + "/sim/ngspice/scripts",
wxFileName( stdPaths.GetExecutablePath() ).GetPath().ToStdString() + "/../../../../../Contents/PlugIns/sim/ngspice/scripts"
#endif /* __WXMAC__ */
wxFileName( stdPaths.GetExecutablePath() ).GetPath().ToStdString() +
"/../../../../../Contents/PlugIns/sim/ngspice/scripts"
#endif
"../share/kicad",
"../share",
"../../share/kicad",
@ -498,9 +596,10 @@ string NGSPICE::findCmPath() const
"/Applications/ngspice/lib/ngspice",
"Contents/Frameworks",
wxStandardPaths::Get().GetPluginsDir().ToStdString() + "/sim/ngspice",
wxFileName( wxStandardPaths::Get().GetExecutablePath() ).GetPath().ToStdString() + "/../../../../../Contents/PlugIns/sim/ngspice",
wxFileName( wxStandardPaths::Get().GetExecutablePath() ).GetPath().ToStdString() +
"/../../../../../Contents/PlugIns/sim/ngspice",
"../Plugins/sim/ngspice",
#endif /* __WXMAC__ */
#endif
"../lib/ngspice",
"../../lib/ngspice",
"lib/ngspice",
@ -554,10 +653,6 @@ int NGSPICE::cbSendChar( char* what, int id, void* user )
int NGSPICE::cbSendStat( char* what, int id, void* user )
{
/* NGSPICE* sim = reinterpret_cast<NGSPICE*>( user );
if( sim->m_consoleReporter )
sim->m_consoleReporter->Report( what );*/
return 0;
}
@ -594,10 +689,4 @@ void NGSPICE::validate()
}
const std::string NGSPICE::GetNetlist() const
{
return m_netlist;
}
bool NGSPICE::m_initialized = false;

View File

@ -34,14 +34,47 @@
class wxDynamicLibrary;
class NGSPICE : public SPICE_SIMULATOR {
/**
* Spice model compatibility modes.
*
* @note The ngspice model modes are mutually exclusive.
*/
enum class NGSPICE_MODEL_MODE {
USER_CONFIG,
NGSPICE,
PSPICE,
LTSPICE,
LT_PSPICE,
HSPICE
};
/**
* Container for Ngspice simulator settings.
*/
class NGSPICE_SIMULATOR_SETTINGS : public SPICE_SIMULATOR_SETTINGS
{
public:
NGSPICE_SIMULATOR_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath );
bool operator==( const SPICE_SIMULATOR_SETTINGS& aRhs ) const override;
NGSPICE_MODEL_MODE GetModelMode() const { return m_modelMode; }
void SetModelMode( NGSPICE_MODEL_MODE aMode ) { m_modelMode = aMode; }
private:
NGSPICE_MODEL_MODE m_modelMode;
};
class NGSPICE : public SPICE_SIMULATOR
{
public:
NGSPICE();
virtual ~NGSPICE();
///< @copydoc SPICE_SIMULATOR::Init()
void Init() override;
void Init( const SPICE_SIMULATOR_SETTINGS* aSettings = nullptr ) override;
///< @copydoc SPICE_SIMULATOR::LoadNetlist()
bool LoadNetlist( const std::string& aNetlist ) override;
@ -79,6 +112,8 @@ public:
///< @copydoc SPICE_SIMULATOR::GetPhasePlot()
std::vector<double> GetPhasePlot( const std::string& aName, int aMaxLen = -1 ) override;
std::vector<std::string> GetSettingCommands() const override;
///< @copydoc SPICE_SIMULATOR::GetNetlist()
virtual const std::string GetNetlist() const override;
@ -89,15 +124,15 @@ private:
void init_dll();
// ngspice library functions
typedef void (*ngSpice_Init)( SendChar*, SendStat*, ControlledExit*,
SendData*, SendInitData*, BGThreadRunning*, void* );
typedef int (*ngSpice_Circ)( char** circarray );
typedef int (*ngSpice_Command)( char* command );
typedef pvector_info (*ngGet_Vec_Info)( char* vecname );
typedef void ( *ngSpice_Init )( SendChar*, SendStat*, ControlledExit*, SendData*, SendInitData*,
BGThreadRunning*, void* );
typedef int ( *ngSpice_Circ )( char** circarray );
typedef int ( *ngSpice_Command )( char* command );
typedef pvector_info ( *ngGet_Vec_Info )( char* vecname );
typedef char* ( *ngSpice_CurPlot )( void );
typedef char** (*ngSpice_AllPlots)( void );
typedef char** (*ngSpice_AllVecs)( char* plotname );
typedef bool (*ngSpice_Running)( void );
typedef char** ( *ngSpice_AllPlots )( void );
typedef char** ( *ngSpice_AllVecs )( char* plotname );
typedef bool ( *ngSpice_Running )( void );
///< Handle to DLL functions
ngSpice_Init m_ngSpice_Init;
@ -133,7 +168,7 @@ private:
///< Error flag indicating that ngspice needs to be reloaded
bool m_error;
///< NGspice should be initialized only once
///< Ngspice should be initialized only once
static bool m_initialized;
///< current netlist

View File

@ -26,6 +26,7 @@
#include <wx/stc/stc.h>
#include <project/project_file.h>
#include <sch_edit_frame.h>
#include <eeschema_id.h>
#include <kiway.h>
@ -36,6 +37,7 @@
#include <dialogs/dialog_signal_list.h>
#include "netlist_exporter_pspice_sim.h"
#include <pgm_base.h>
#include "ngspice.h"
#include "sim_plot_colors.h"
#include "sim_plot_frame.h"
#include "sim_plot_panel.h"
@ -59,8 +61,8 @@ SIM_PLOT_TYPE operator|( SIM_PLOT_TYPE aFirst, SIM_PLOT_TYPE aSecond )
class SIM_THREAD_REPORTER : public SPICE_REPORTER
{
public:
SIM_THREAD_REPORTER( SIM_PLOT_FRAME* aParent )
: m_parent( aParent )
SIM_THREAD_REPORTER( SIM_PLOT_FRAME* aParent ) :
m_parent( aParent )
{
}
@ -83,17 +85,17 @@ public:
switch( aNewState )
{
case SIM_IDLE:
event = new wxCommandEvent( EVT_SIM_FINISHED );
break;
case SIM_IDLE:
event = new wxCommandEvent( EVT_SIM_FINISHED );
break;
case SIM_RUNNING:
event = new wxCommandEvent( EVT_SIM_STARTED );
break;
case SIM_RUNNING:
event = new wxCommandEvent( EVT_SIM_STARTED );
break;
default:
wxFAIL;
return;
default:
wxFAIL;
return;
}
wxQueueEvent( m_parent, event );
@ -105,8 +107,10 @@ private:
TRACE_DESC::TRACE_DESC( const NETLIST_EXPORTER_PSPICE_SIM& aExporter, const wxString& aName,
SIM_PLOT_TYPE aType, const wxString& aParam )
: m_name( aName ), m_type( aType ), m_param( aParam )
SIM_PLOT_TYPE aType, const wxString& aParam ) :
m_name( aName ),
m_type( aType ),
m_param( aParam )
{
// Title generation
m_title = wxString::Format( "%s(%s)", aParam, aName );
@ -117,14 +121,16 @@ TRACE_DESC::TRACE_DESC( const NETLIST_EXPORTER_PSPICE_SIM& aExporter, const wxSt
m_title += " (phase)";
}
// Store the path of saved workbooks during the session
wxString SIM_PLOT_FRAME::m_savedWorkbooksPath;
SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent )
: SIM_PLOT_FRAME_BASE( aParent ),
m_lastSimPlot( nullptr ),
m_welcomePanel( nullptr ),
m_plotNumber( 0 )
SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
SIM_PLOT_FRAME_BASE( aParent ),
m_lastSimPlot( nullptr ),
m_welcomePanel( nullptr ),
m_plotNumber( 0 )
{
SetKiway( this, aKiway );
m_signalsIconColorList = NULL;
@ -139,6 +145,14 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent )
icon.CopyFromBitmap( KiBitmap( BITMAPS::simulator ) );
SetIcon( icon );
m_simulator = SPICE_SIMULATOR::CreateInstance( "ngspice" );
if( !m_simulator )
{
throw std::runtime_error( "Could not create simulator instance" );
return;
}
// Get the previous size and position of windows:
LoadSettings( config() );
@ -148,14 +162,6 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent )
// Give icons to menuitems
setIconsForMenuItems();
m_simulator = SPICE_SIMULATOR::CreateInstance( "ngspice" );
if( !m_simulator )
{
throw std::runtime_error( "Could not create simulator instance" );
return;
}
m_simulator->Init();
if( m_savedWorkbooksPath.IsEmpty() )
@ -178,7 +184,8 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent )
Connect( EVT_SIM_REPORT, wxCommandEventHandler( SIM_PLOT_FRAME::onSimReport ), NULL, this );
Connect( EVT_SIM_STARTED, wxCommandEventHandler( SIM_PLOT_FRAME::onSimStarted ), NULL, this );
Connect( EVT_SIM_FINISHED, wxCommandEventHandler( SIM_PLOT_FRAME::onSimFinished ), NULL, this );
Connect( EVT_SIM_CURSOR_UPDATE, wxCommandEventHandler( SIM_PLOT_FRAME::onCursorUpdate ), NULL, this );
Connect( EVT_SIM_CURSOR_UPDATE, wxCommandEventHandler( SIM_PLOT_FRAME::onCursorUpdate ),
NULL, this );
// Toolbar buttons
m_toolSimulate = m_toolBar->AddTool( ID_SIM_RUN, _( "Run/Stop Simulation" ),
@ -204,12 +211,14 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent )
wxCommandEventHandler( SIM_PLOT_FRAME::onSettings ), NULL, this );
// Bind toolbar buttons event to existing menu event handlers, so they behave the same
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onSimulate, this, m_runSimulation->GetId() );
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onAddSignal, this, m_addSignals->GetId() );
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onProbe, this, m_probeSignals->GetId() );
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onTune, this, m_tuneValue->GetId() );
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onShowNetlist, this, m_showNetlist->GetId() );
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onSettings, this, m_settings->GetId() );
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onSimulate, this,
m_runSimulation->GetId() );
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onAddSignal, this, m_addSignals->GetId() );
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onProbe, this, m_probeSignals->GetId() );
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onTune, this, m_tuneValue->GetId() );
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onShowNetlist, this,
m_showNetlist->GetId() );
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onSettings, this, m_settings->GetId() );
m_toolBar->Realize();
@ -258,6 +267,14 @@ void SIM_PLOT_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
cfg->m_Simulator.cursors_panel_height = m_splitterTuneValues->GetSashPosition();
cfg->m_Simulator.white_background = m_plotUseWhiteBg;
}
if( m_schematicFrame )
{
PROJECT_FILE& project = Prj().GetProjectFile();
project.m_SchematicSettings->m_NgspiceSimulatorSettings->SaveToFile();
m_schematicFrame->SaveProjectSettings();
}
}
@ -277,6 +294,13 @@ void SIM_PLOT_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
m_splitterTuneValuesSashPosition = cfg->m_Simulator.cursors_panel_height;
m_plotUseWhiteBg = cfg->m_Simulator.white_background;
}
PROJECT_FILE& project = Prj().GetProjectFile();
NGSPICE* currentSim = dynamic_cast<NGSPICE*>( m_simulator.get() );
if( currentSim )
m_simulator->Settings() = project.m_SchematicSettings->m_NgspiceSimulatorSettings;
}
@ -345,7 +369,8 @@ void SIM_PLOT_FRAME::setIconsForMenuItems()
continue;
wxMenu* menu = item->GetMenu();
// Calculate the initial index of item inside the wxMenu parent
// Calculate the initial index of item inside the wxMenu parent.
wxMenuItemList& mlist = menu->GetMenuItems();
int mpos = mlist.IndexOf( item );
@ -354,6 +379,7 @@ void SIM_PLOT_FRAME::setIconsForMenuItems()
// Modify the bitmap
menu->Remove( item );
AddBitmapToMenuItem( item, KiBitmap( bm_list[ii].m_Bitmap ) );
// Insert item to its the initial index
menu->Insert( mpos, item );
}
@ -382,7 +408,7 @@ void SIM_PLOT_FRAME::StartSimulation( const wxString& aSimCommand )
STRING_FORMATTER formatter;
if( !m_settingsDlg )
m_settingsDlg = new DIALOG_SIM_SETTINGS( this );
m_settingsDlg = new DIALOG_SIM_SETTINGS( this, m_simulator->Settings() );
m_simConsole->Clear();
updateNetlistExporter();
@ -490,7 +516,8 @@ void SIM_PLOT_FRAME::AddTuner( SCH_COMPONENT* aComponent )
// For now limit the tuner tool to RLC components
char primitiveType = NETLIST_EXPORTER_PSPICE::GetSpiceField( SF_PRIMITIVE, aComponent, 0 )[0];
if( primitiveType != SP_RESISTOR && primitiveType != SP_CAPACITOR && primitiveType != SP_INDUCTOR )
if( primitiveType != SP_RESISTOR && primitiveType != SP_CAPACITOR
&& primitiveType != SP_INDUCTOR )
return;
const wxString componentName = aComponent->GetField( REFERENCE_FIELD )->GetText();
@ -546,6 +573,14 @@ const NETLIST_EXPORTER_PSPICE_SIM* SIM_PLOT_FRAME::GetExporter() const
}
std::shared_ptr<SPICE_SIMULATOR_SETTINGS>& SIM_PLOT_FRAME::GetSimulatorSettings()
{
wxASSERT( m_simulator->Settings() );
return m_simulator->Settings();
}
void SIM_PLOT_FRAME::addPlot( const wxString& aName, SIM_PLOT_TYPE aType, const wxString& aParam )
{
SIM_TYPE simType = m_exporter->GetSimType();
@ -586,7 +621,8 @@ void SIM_PLOT_FRAME::addPlot( const wxString& aName, SIM_PLOT_TYPE aType, const
// Add two plots: magnitude & phase
TRACE_DESC mag_desc( *m_exporter, descriptor, (SIM_PLOT_TYPE)( baseType | SPT_AC_MAG ) );
TRACE_DESC phase_desc( *m_exporter, descriptor, (SIM_PLOT_TYPE)( baseType | SPT_AC_PHASE ) );
TRACE_DESC phase_desc( *m_exporter, descriptor,
(SIM_PLOT_TYPE)( baseType | SPT_AC_PHASE ) );
updated |= updatePlot( mag_desc, plotPanel );
updated |= updatePlot( phase_desc, plotPanel );
@ -631,6 +667,7 @@ void SIM_PLOT_FRAME::removePlot( const wxString& aPlotName, bool aErase )
void SIM_PLOT_FRAME::updateNetlistExporter()
{
m_exporter.reset( new NETLIST_EXPORTER_PSPICE_SIM( &m_schematicFrame->Schematic() ) );
if( m_settingsDlg )
m_settingsDlg->SetNetlistExporter( m_exporter.get() );
}
@ -668,31 +705,28 @@ bool SIM_PLOT_FRAME::updatePlot( const TRACE_DESC& aDescriptor, SIM_PLOT_PANEL*
// Now, Y axis data
switch( m_exporter->GetSimType() )
{
case ST_AC:
{
wxASSERT_MSG( !( ( plotType & SPT_AC_MAG ) && ( plotType & SPT_AC_PHASE ) ),
"Cannot set both AC_PHASE and AC_MAG bits" );
case ST_AC:
wxASSERT_MSG( !( ( plotType & SPT_AC_MAG ) && ( plotType & SPT_AC_PHASE ) ),
"Cannot set both AC_PHASE and AC_MAG bits" );
if( plotType & SPT_AC_MAG )
data_y = m_simulator->GetMagPlot( (const char*) spiceVector.c_str() );
else if( plotType & SPT_AC_PHASE )
data_y = m_simulator->GetPhasePlot( (const char*) spiceVector.c_str() );
else
wxASSERT_MSG( false, "Plot type missing AC_PHASE or AC_MAG bit" );
}
break;
case ST_NOISE:
case ST_DC:
case ST_TRANSIENT:
{
if( plotType & SPT_AC_MAG )
data_y = m_simulator->GetMagPlot( (const char*) spiceVector.c_str() );
}
else if( plotType & SPT_AC_PHASE )
data_y = m_simulator->GetPhasePlot( (const char*) spiceVector.c_str() );
else
wxASSERT_MSG( false, "Plot type missing AC_PHASE or AC_MAG bit" );
break;
default:
wxASSERT_MSG( false, "Unhandled plot type" );
return false;
case ST_NOISE:
case ST_DC:
case ST_TRANSIENT:
data_y = m_simulator->GetMagPlot( (const char*) spiceVector.c_str() );
break;
default:
wxASSERT_MSG( false, "Unhandled plot type" );
return false;
}
if( data_y.size() != size )
@ -1177,7 +1211,7 @@ void SIM_PLOT_FRAME::menuWhiteBackground( wxCommandEvent& event )
if( curPage == m_welcomePanel )
continue;
// ensure it is truely a plot panel and not the (zero plots) placeholder
// ensure it is truly a plot panel and not the (zero plots) placeholder
// which is only SIM_PLOT_PANEL_BASE
SIM_PLOT_PANEL* panel = dynamic_cast<SIM_PLOT_PANEL*>( curPage );
@ -1256,7 +1290,7 @@ void SIM_PLOT_FRAME::onSettings( wxCommandEvent& event )
SIM_PANEL_BASE* plotPanelWindow = currentPlotWindow();
if( !m_settingsDlg )
m_settingsDlg = new DIALOG_SIM_SETTINGS( this );
m_settingsDlg = new DIALOG_SIM_SETTINGS( this, m_simulator->Settings() );
// Initial processing is required to e.g. display a list of power sources
updateNetlistExporter();
@ -1277,7 +1311,8 @@ void SIM_PLOT_FRAME::onSettings( wxCommandEvent& event )
SIM_TYPE newSimType = NETLIST_EXPORTER_PSPICE_SIM::CommandToSimType( newCommand );
// 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', 'i', 'r' or 't'
// For the DC sim, check if sweep source type has changed (char 4 will contain 'v',
// 'i', 'r' or 't'.
if( !plotPanelWindow
|| ( plotPanelWindow && plotPanelWindow->GetType() != newSimType )
|| ( newSimType == ST_DC
@ -1287,6 +1322,7 @@ void SIM_PLOT_FRAME::onSettings( wxCommandEvent& event )
}
m_plots[plotPanelWindow].m_simCommand = newCommand;
m_simulator->Init();
}
}
@ -1325,6 +1361,7 @@ void SIM_PLOT_FRAME::onTune( wxCommandEvent& event )
m_schematicFrame->Raise();
}
void SIM_PLOT_FRAME::onShowNetlist( wxCommandEvent& event )
{
class NETLIST_VIEW_DIALOG : public DIALOG_SHIM
@ -1369,7 +1406,7 @@ void SIM_PLOT_FRAME::onShowNetlist( wxCommandEvent& event )
SetSizer( sizer );
Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( NETLIST_VIEW_DIALOG::onClose ), NULL,
this );
this );
finishDialogSettings();
}
@ -1411,7 +1448,8 @@ void SIM_PLOT_FRAME::onCursorUpdate( wxCommandEvent& event )
// Fill the signals listctrl
m_cursors->AppendColumn( _( "Signal" ), wxLIST_FORMAT_LEFT, size.x / 2 );
const long X_COL = m_cursors->AppendColumn( plotPanel->GetLabelX(), wxLIST_FORMAT_LEFT, size.x / 4 );
const long X_COL = m_cursors->AppendColumn( plotPanel->GetLabelX(), wxLIST_FORMAT_LEFT,
size.x / 4 );
wxString labelY1 = plotPanel->GetLabelY1();
wxString labelY2 = plotPanel->GetLabelY2();
@ -1570,7 +1608,8 @@ SIM_PLOT_FRAME::SIGNAL_CONTEXT_MENU::SIGNAL_CONTEXT_MENU( const wxString& aSigna
else
AddMenuItem( this, SHOW_CURSOR, _( "Show Cursor" ), KiBitmap( BITMAPS::pcb_target ) );
Connect( wxEVT_COMMAND_MENU_SELECTED, wxMenuEventHandler( SIGNAL_CONTEXT_MENU::onMenuEvent ), NULL, this );
Connect( wxEVT_COMMAND_MENU_SELECTED, wxMenuEventHandler( SIGNAL_CONTEXT_MENU::onMenuEvent ),
NULL, this );
}
@ -1580,20 +1619,21 @@ void SIM_PLOT_FRAME::SIGNAL_CONTEXT_MENU::onMenuEvent( wxMenuEvent& aEvent )
switch( aEvent.GetId() )
{
case HIDE_SIGNAL:
m_plotFrame->removePlot( m_signal );
break;
case HIDE_SIGNAL:
m_plotFrame->removePlot( m_signal );
break;
case SHOW_CURSOR:
plot->EnableCursor( m_signal, true );
break;
case SHOW_CURSOR:
plot->EnableCursor( m_signal, true );
break;
case HIDE_CURSOR:
plot->EnableCursor( m_signal, false );
break;
case HIDE_CURSOR:
plot->EnableCursor( m_signal, false );
break;
}
}
wxDEFINE_EVENT( EVT_SIM_UPDATE, wxCommandEvent );
wxDEFINE_EVENT( EVT_SIM_REPORT, wxCommandEvent );

View File

@ -50,6 +50,7 @@ class SCH_EDIT_FRAME;
class SCH_COMPONENT;
class SPICE_SIMULATOR;
class SPICE_SIMULATOR_SETTINGS;
class NETLIST_EXPORTER_PSPICE_SIM;
#include "sim_plot_panel.h"
@ -59,7 +60,7 @@ class SIM_THREAD_REPORTER;
class TUNER_SLIDER;
///> Trace descriptor class
///< Trace descriptor class
class TRACE_DESC
{
public:
@ -110,11 +111,12 @@ private:
};
/** Implementing SIM_PLOT_FRAME_BASE */
/**
* Implementing SIM_PLOT_FRAME_BASE
*/
class SIM_PLOT_FRAME : public SIM_PLOT_FRAME_BASE
{
public:
/** Constructor */
SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent );
~SIM_PLOT_FRAME();
@ -147,7 +149,6 @@ public:
/**
* Add a tuner for a component.
*
*/
void AddTuner( SCH_COMPONENT* aComponent );
@ -185,6 +186,8 @@ public:
// Simulator doesn't host a tool framework
wxWindow* GetToolCanvas() const override { return nullptr; }
std::shared_ptr<SPICE_SIMULATOR_SETTINGS>& GetSimulatorSettings();
private:
/**
* Give icons to menuitems of the main menubar
@ -238,7 +241,8 @@ private:
/**
* Filter out tuners for components that do not exist anymore.
* Decisions are based on the current NETLIST_EXPORTER_BASE data.
*
* Decisions are based on the current #NETLIST_EXPORTER_BASE data.
*/
void updateTuners();

View File

@ -2,6 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 CERN
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
@ -26,6 +27,19 @@
#include <confirm.h>
#include <schematic_settings.h>
const int ngspiceSettingsSchemaVersion = 0;
SPICE_SIMULATOR_SETTINGS::SPICE_SIMULATOR_SETTINGS( JSON_SETTINGS* aParent,
const std::string& aPath ) :
NESTED_SETTINGS( "simulator", ngspiceSettingsSchemaVersion, aParent, aPath )
{
}
std::shared_ptr<SPICE_SIMULATOR> SPICE_SIMULATOR::CreateInstance( const std::string& )
{
try
@ -39,12 +53,13 @@ std::shared_ptr<SPICE_SIMULATOR> SPICE_SIMULATOR::CreateInstance( const std::str
}
catch( std::exception& e )
{
DisplayError( NULL, e.what() );
DisplayError( nullptr, e.what() );
}
return NULL;
return nullptr;
}
wxString SPICE_SIMULATOR::TypeToName( SIM_TYPE aType, bool aShortName )
{
switch( aType )

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 CERN
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
@ -27,6 +27,8 @@
#ifndef SPICE_SIMULATOR_H
#define SPICE_SIMULATOR_H
#include <settings/nested_settings.h>
#include "sim_types.h"
#include <string>
@ -37,23 +39,48 @@
#include <wx/string.h>
class SPICE_REPORTER;
class SPICE_SIMULATOR;
typedef std::complex<double> COMPLEX;
/**
* Storage for simulator specific settings.
*/
class SPICE_SIMULATOR_SETTINGS : public NESTED_SETTINGS
{
public:
SPICE_SIMULATOR_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath );
virtual ~SPICE_SIMULATOR_SETTINGS() {}
virtual bool operator==( const SPICE_SIMULATOR_SETTINGS& aRhs ) const = 0;
bool operator!=( const SPICE_SIMULATOR_SETTINGS& aRhs ) const { return !( *this == aRhs ); }
};
class SPICE_SIMULATOR
{
public:
SPICE_SIMULATOR() : m_reporter( NULL ) {}
SPICE_SIMULATOR() :
m_reporter( nullptr ),
m_settings( nullptr )
{}
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
virtual void Init() = 0;
/*
* Initialize the simulator using the optional \a aSettings.
*
* @param aSettings [in] are the simulator specific settings. Can be null if no settings need
* to be initialized.
*/
virtual void Init( const SPICE_SIMULATOR_SETTINGS* aSettings = nullptr ) = 0;
/**
* Load a netlist for the simulation.
*
* @return True in case of success, false otherwise.
@ -91,7 +118,7 @@ public:
///< Return X axis name for a given simulation type
virtual std::string GetXAxis( SIM_TYPE aType ) const = 0;
///< Set a SPICE_REPORTER object to receive the simulation log.
///< Set a #SPICE_REPORTER object to receive the simulation log.
virtual void SetReporter( SPICE_REPORTER* aReporter )
{
m_reporter = aReporter;
@ -99,7 +126,7 @@ public:
/**
* Return a list with all vectors generated in current simulation.
* @param none
*
* @return List of vector names. ?May not match to the net name elements.
*/
virtual std::vector<std::string> AllPlots() const = 0;
@ -164,6 +191,20 @@ public:
*/
virtual const std::string GetNetlist() const = 0;
/**
* @return a list of simulator setting command strings.
*/
virtual std::vector<std::string> GetSettingCommands() const = 0;
/**
* Return the simulator configuration settings.
*
* @return the simulator specific settings.
*/
std::shared_ptr<SPICE_SIMULATOR_SETTINGS>& Settings() { return m_settings; }
const std::shared_ptr<SPICE_SIMULATOR_SETTINGS>& Settings() const { return m_settings; }
/**
* Return a string with simulation name based on enum.
*
@ -177,6 +218,9 @@ public:
protected:
///< Reporter object to receive simulation log.
SPICE_REPORTER* m_reporter;
///< We don't own this. We are just borrowing it from the #SCHEMATIC_SETTINGS.
std::shared_ptr<SPICE_SIMULATOR_SETTINGS> m_settings;
};
#endif /* SPICE_SIMULATOR_H */

View File

@ -2,6 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 CERN
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
* @author Jon Evans <jon@craftyjon.com>
*
* This program is free software: you can redistribute it and/or modify it
@ -22,6 +23,7 @@
#define KICAD_PROJECT_FILE_H
#include <common.h> // needed for wxstring hash template
#include <kiid.h>
#include <project/board_project_settings.h>
#include <settings/json_settings.h>
#include <settings/nested_settings.h>
@ -54,7 +56,7 @@ enum LAST_PATH_TYPE : unsigned int
};
/**
* PROJECT_FILE is the backing store for a PROJECT, in JSON format.
* The backing store for a PROJECT, in JSON format.
*
* There is either zero or one PROJECT_FILE for every PROJECT
* (you can have a dummy PROJECT that has no file)
@ -63,7 +65,7 @@ class PROJECT_FILE : public JSON_SETTINGS
{
public:
/**
* Constructs the project file for a project
* Construct the project file for a project
* @param aFullPath is the full disk path to the project
*/
PROJECT_FILE( const wxString& aFullPath );
@ -168,11 +170,12 @@ public:
/**
* Net settings for this project (owned here)
* NOTE: If we go multi-board in the future, we have to decide whether to use a global
* NET_SETTINGS or have one per board. Right now I think global makes more sense (one set of
* schematics, one netlist partitioned into multiple boards)
*
* @note If we go multi-board in the future, we have to decide whether to use a global
* NET_SETTINGS or have one per board. Right now I think global makes more sense
* (one set of schematics, one netlist partitioned into multiple boards)
*/
std::shared_ptr<NET_SETTINGS> m_NetSettings;
std::shared_ptr<NET_SETTINGS> m_NetSettings;
/// List of stored layer presets
std::vector<LAYER_PRESET> m_LayerPresets;