From 098d2b30a29b044bfb51f145b99c80119cfa3f98 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sat, 14 Jan 2023 00:17:33 +0000 Subject: [PATCH] Support for simulation options in workbook and simulation command dlg. Fixes https://gitlab.com/kicad/code/kicad/issues/13524 Fixes https://gitlab.com/kicad/code/kicad/issues/13523 Fixes https://gitlab.com/kicad/code/kicad/issues/13431 --- eeschema/dialogs/dialog_export_netlist.cpp | 4 +- eeschema/dialogs/dialog_sim_command.h | 24 ++ eeschema/dialogs/dialog_sim_command_base.cpp | 14 +- eeschema/dialogs/dialog_sim_command_base.fbp | 134 ++++++++++- eeschema/dialogs/dialog_sim_command_base.h | 2 + .../netlist_exporter_spice.cpp | 28 ++- .../netlist_exporter_spice.h | 17 +- eeschema/sim/ngspice_circuit_model.cpp | 2 +- eeschema/sim/ngspice_circuit_model.h | 12 +- eeschema/sim/sim_panel_base.cpp | 24 +- eeschema/sim/sim_panel_base.h | 9 +- eeschema/sim/sim_plot_frame.cpp | 215 ++++++++++++------ eeschema/sim/sim_plot_frame.h | 21 +- eeschema/sim/sim_plot_panel.cpp | 4 +- eeschema/sim/sim_plot_panel.h | 17 +- eeschema/sim/sim_workbook.h | 11 + 16 files changed, 399 insertions(+), 139 deletions(-) diff --git a/eeschema/dialogs/dialog_export_netlist.cpp b/eeschema/dialogs/dialog_export_netlist.cpp index 5aafaa766c..af3b52cfe2 100644 --- a/eeschema/dialogs/dialog_export_netlist.cpp +++ b/eeschema/dialogs/dialog_export_netlist.cpp @@ -351,13 +351,13 @@ void DIALOG_EXPORT_NETLIST::InstallPageSpice() _( "Save all voltages" ) ); page->m_SaveAllVoltages->SetToolTip( _( "Write a directive to save all voltages (.save all)" ) ); page->m_SaveAllVoltages->SetValue( settings.m_SpiceSaveAllVoltages ); - page->m_RightBoxSizer->Add( page->m_SaveAllVoltages, 0, wxBOTTOM | wxRIGHT, 5 ); + page->m_LeftBoxSizer->Add( page->m_SaveAllVoltages, 0, wxBOTTOM | wxRIGHT, 5 ); page->m_SaveAllCurrents = new wxCheckBox( page, ID_SAVE_ALL_CURRENTS, _( "Save all currents" ) ); page->m_SaveAllCurrents->SetToolTip( _( "Write a directive to save all currents (.probe alli)" ) ); page->m_SaveAllCurrents->SetValue( settings.m_SpiceSaveAllCurrents ); - page->m_RightBoxSizer->Add( page->m_SaveAllCurrents, 0, wxBOTTOM | wxRIGHT, 5 ); + page->m_LeftBoxSizer->Add( page->m_SaveAllCurrents, 0, wxBOTTOM | wxRIGHT, 5 ); wxString simulatorCommand = settings.m_SpiceCommandString; diff --git a/eeschema/dialogs/dialog_sim_command.h b/eeschema/dialogs/dialog_sim_command.h index c6cc11eb7f..d8ac2e3afb 100644 --- a/eeschema/dialogs/dialog_sim_command.h +++ b/eeschema/dialogs/dialog_sim_command.h @@ -28,6 +28,7 @@ #define DIALOG_SIM_COMMAND_H #include "dialog_sim_command_base.h" +#include #include #include @@ -57,6 +58,29 @@ public: return res; } + int GetSimOptions() const + { + int options = NETLIST_EXPORTER_SPICE::OPTION_DEFAULT_FLAGS; + + if( !m_fixIncludePaths->GetValue() ) + options &= ~NETLIST_EXPORTER_SPICE::OPTION_ADJUST_INCLUDE_PATHS; + + if( !m_saveAllVoltages->GetValue() ) + options &= ~NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_VOLTAGES; + + if( !m_saveAllCurrents->GetValue() ) + options &= ~NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_CURRENTS; + + return options; + } + + void SetSimOptions( int aOptions ) + { + m_fixIncludePaths->SetValue( aOptions & NETLIST_EXPORTER_SPICE::OPTION_ADJUST_INCLUDE_PATHS ); + m_saveAllVoltages->SetValue( aOptions & NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_VOLTAGES ); + m_saveAllCurrents->SetValue( aOptions & NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_CURRENTS ); + } + bool TransferDataFromWindow() override; bool TransferDataToWindow() override; diff --git a/eeschema/dialogs/dialog_sim_command_base.cpp b/eeschema/dialogs/dialog_sim_command_base.cpp index 4f895f1092..8691c311f8 100644 --- a/eeschema/dialogs/dialog_sim_command_base.cpp +++ b/eeschema/dialogs/dialog_sim_command_base.cpp @@ -89,7 +89,7 @@ DIALOG_SIM_COMMAND_BASE::DIALOG_SIM_COMMAND_BASE( wxWindow* parent, wxWindowID i gbSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); m_dcEnable2 = new wxCheckBox( m_pgDC, wxID_ANY, _("Source 2"), wxDefaultPosition, wxDefaultSize, 0 ); - m_dcEnable2->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_dcEnable2->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) ); gbSizer1->Add( m_dcEnable2, wxGBPosition( 0, 3 ), wxGBSpan( 1, 2 ), wxALIGN_CENTER_VERTICAL|wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); @@ -115,7 +115,7 @@ DIALOG_SIM_COMMAND_BASE::DIALOG_SIM_COMMAND_BASE( wxWindow* parent, wxWindowID i m_staticText411 = new wxStaticText( m_pgDC, wxID_ANY, _("Source 1"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText411->Wrap( -1 ); - m_staticText411->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); + m_staticText411->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) ); gbSizer1->Add( m_staticText411, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxBOTTOM|wxRIGHT|wxLEFT, 5 ); @@ -430,7 +430,13 @@ DIALOG_SIM_COMMAND_BASE::DIALOG_SIM_COMMAND_BASE( wxWindow* parent, wxWindowID i m_fixIncludePaths = new wxCheckBox( this, wxID_ANY, _("Add full path for .include library directives"), wxDefaultPosition, wxDefaultSize, 0 ); m_fixIncludePaths->SetValue(true); - bSizer88->Add( m_fixIncludePaths, 0, wxBOTTOM|wxRIGHT|wxLEFT, 10 ); + bSizer88->Add( m_fixIncludePaths, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + m_saveAllVoltages = new wxCheckBox( this, wxID_ANY, _("Save all voltages"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer88->Add( m_saveAllVoltages, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + m_saveAllCurrents = new wxCheckBox( this, wxID_ANY, _("Save all currents"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer88->Add( m_saveAllCurrents, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); m_compatibilityMode = new wxBoxSizer( wxHORIZONTAL ); @@ -449,7 +455,7 @@ DIALOG_SIM_COMMAND_BASE::DIALOG_SIM_COMMAND_BASE( wxWindow* parent, wxWindowID i bSizer88->Add( m_compatibilityMode, 1, wxEXPAND|wxBOTTOM, 5 ); - bSizer1->Add( bSizer88, 0, wxEXPAND, 5 ); + bSizer1->Add( bSizer88, 0, wxEXPAND|wxTOP|wxLEFT, 10 ); m_sdbSizer = new wxStdDialogButtonSizer(); m_sdbSizerOK = new wxButton( this, wxID_OK ); diff --git a/eeschema/dialogs/dialog_sim_command_base.fbp b/eeschema/dialogs/dialog_sim_command_base.fbp index 543688a861..41a40e3d30 100644 --- a/eeschema/dialogs/dialog_sim_command_base.fbp +++ b/eeschema/dialogs/dialog_sim_command_base.fbp @@ -4851,8 +4851,8 @@ - 5 - wxEXPAND + 10 + wxEXPAND|wxTOP|wxLEFT 0 @@ -4860,7 +4860,7 @@ wxVERTICAL none - 10 + 5 wxBOTTOM|wxRIGHT|wxLEFT 0 @@ -4923,6 +4923,134 @@ + + 5 + wxBOTTOM|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Save all voltages + + 0 + + + 0 + + 1 + m_saveAllVoltages + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxBOTTOM|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Save all currents + + 0 + + + 0 + + 1 + m_saveAllCurrents + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + 5 wxEXPAND|wxBOTTOM diff --git a/eeschema/dialogs/dialog_sim_command_base.h b/eeschema/dialogs/dialog_sim_command_base.h index e57edd38fb..36ef021f52 100644 --- a/eeschema/dialogs/dialog_sim_command_base.h +++ b/eeschema/dialogs/dialog_sim_command_base.h @@ -117,6 +117,8 @@ class DIALOG_SIM_COMMAND_BASE : public DIALOG_SHIM wxTextCtrl* m_customTxt; wxButton* m_loadDirectives; wxCheckBox* m_fixIncludePaths; + wxCheckBox* m_saveAllVoltages; + wxCheckBox* m_saveAllCurrents; wxBoxSizer* m_compatibilityMode; wxChoice* m_compatibilityModeChoice; wxStdDialogButtonSizer* m_sdbSizer; diff --git a/eeschema/netlist_exporters/netlist_exporter_spice.cpp b/eeschema/netlist_exporters/netlist_exporter_spice.cpp index 81fbe449fb..202ea35e2c 100644 --- a/eeschema/netlist_exporters/netlist_exporter_spice.cpp +++ b/eeschema/netlist_exporters/netlist_exporter_spice.cpp @@ -620,19 +620,27 @@ void NETLIST_EXPORTER_SPICE::WriteDirectives( OUTPUTFORMATTER& aFormatter, if( aNetlistOptions & OPTION_SAVE_ALL_CURRENTS ) aFormatter.Print( 0, ".probe alli\n" ); - for( const std::string& directive : m_directives ) + for( const wxString& directive : m_directives ) { -#ifdef KICAD_SPICE - if( NGSPICE_CIRCUIT_MODEL::IsSimCommand( directive ) ) + bool simCommand = false; + + if( directive.StartsWith( "." ) ) { - if( aNetlistOptions & OPTION_SIM_COMMAND ) - aFormatter.Print( 0, "%s\n", directive.c_str() ); - } - else -#endif - { - aFormatter.Print( 0, "%s\n", directive.c_str() ); + wxString candidate = directive.Upper(); + + simCommand = ( candidate.StartsWith( wxT( ".AC" ) ) + || candidate.StartsWith( wxT( ".DC" ) ) + || candidate.StartsWith( wxT( ".TRAN" ) ) + || candidate.StartsWith( wxT( ".OP" ) ) + || candidate.StartsWith( wxT( ".DISTO" ) ) + || candidate.StartsWith( wxT( ".NOISE" ) ) + || candidate.StartsWith( wxT( ".PZ" ) ) + || candidate.StartsWith( wxT( ".SENS" ) ) + || candidate.StartsWith( wxT( ".TF" ) ) ); } + + if( !simCommand || ( aNetlistOptions & OPTION_SIM_COMMAND ) ) + aFormatter.Print( 0, "%s\n", UTF8( directive ).c_str() ); } } diff --git a/eeschema/netlist_exporters/netlist_exporter_spice.h b/eeschema/netlist_exporters/netlist_exporter_spice.h index a75d377643..bdd94fd599 100644 --- a/eeschema/netlist_exporters/netlist_exporter_spice.h +++ b/eeschema/netlist_exporters/netlist_exporter_spice.h @@ -123,7 +123,7 @@ public: */ const SPICE_ITEM* FindItem( const std::string& aRefName ) const; - const std::vector& GetDirectives() { return m_directives; } + const std::vector& GetDirectives() { return m_directives; } protected: void ReadDirectives( unsigned aNetlistOptions ); @@ -150,14 +150,13 @@ private: void writeModels( OUTPUTFORMATTER& aFormatter ); void writeItems( OUTPUTFORMATTER& aFormatter ); - SIM_LIB_MGR m_libMgr; ///< Holds libraries and models - NAME_GENERATOR m_modelNameGenerator; ///< Generates unique model names - NAME_GENERATOR m_netNameGenerator; ///< Generates unique net names (only unique for NC nets for now) - std::vector m_directives; ///< Spice directives found in the schematic sheet - //std::map> m_libraries; ///< Spice libraries - std::set m_rawIncludes; ///< include directives found in symbols - std::set m_nets; - std::list m_items; ///< Items representing schematic symbols in Spice world + SIM_LIB_MGR m_libMgr; ///< Holds libraries and models + NAME_GENERATOR m_modelNameGenerator; ///< Generates unique model names + NAME_GENERATOR m_netNameGenerator; ///< Generates unique net names (only unique for NC nets for now) + std::vector m_directives; ///< Spice directives found in the schematic sheet + std::set m_rawIncludes; ///< include directives found in symbols + std::set m_nets; + std::list m_items; ///< Items representing schematic symbols in Spice world }; diff --git a/eeschema/sim/ngspice_circuit_model.cpp b/eeschema/sim/ngspice_circuit_model.cpp index bc60cbbb62..398f16859b 100644 --- a/eeschema/sim/ngspice_circuit_model.cpp +++ b/eeschema/sim/ngspice_circuit_model.cpp @@ -71,7 +71,7 @@ wxString NGSPICE_CIRCUIT_MODEL::GetSheetSimCommand() ReadDirectives( 0 ); - for( const std::string& directive : GetDirectives() ) + for( const wxString& directive : GetDirectives() ) { if( IsSimCommand( directive ) ) simCmd += wxString::Format( wxT( "%s\r\n" ), directive ); diff --git a/eeschema/sim/ngspice_circuit_model.h b/eeschema/sim/ngspice_circuit_model.h index 5479ab8efc..88ec757119 100644 --- a/eeschema/sim/ngspice_circuit_model.h +++ b/eeschema/sim/ngspice_circuit_model.h @@ -49,9 +49,9 @@ class NGSPICE_CIRCUIT_MODEL : public NETLIST_EXPORTER_SPICE, public SIMULATION_M public: NGSPICE_CIRCUIT_MODEL( SCHEMATIC_IFACE* aSchematic ) : NETLIST_EXPORTER_SPICE( aSchematic ), - m_options( 0 ) - { - } + m_options( NETLIST_EXPORTER_SPICE::OPTION_DEFAULT_FLAGS ) + {} + virtual ~NGSPICE_CIRCUIT_MODEL() {} /** @@ -64,10 +64,8 @@ public: */ SIM_PLOT_TYPE VectorToSignal( const std::string& aVector, wxString& aSignal ) const; - void SetOptions( int aOptions ) - { - m_options = aOptions; - } + void SetSimOptions( int aOptions ) { m_options = aOptions; } + int GetSimOptions() const { return m_options; } bool GetNetlist( OUTPUTFORMATTER* aFormatter, REPORTER& aReporter ) { diff --git a/eeschema/sim/sim_panel_base.cpp b/eeschema/sim/sim_panel_base.cpp index 5533200292..0c06152374 100644 --- a/eeschema/sim/sim_panel_base.cpp +++ b/eeschema/sim/sim_panel_base.cpp @@ -30,21 +30,19 @@ #include "ngspice_circuit_model.h" -SIM_PANEL_BASE::SIM_PANEL_BASE() : m_simCommand( wxEmptyString ) +SIM_PANEL_BASE::SIM_PANEL_BASE() : + m_simCommand( wxEmptyString ), + m_simOptions( NETLIST_EXPORTER_SPICE::OPTION_DEFAULT_FLAGS ) { } -SIM_PANEL_BASE::SIM_PANEL_BASE( const wxString& aCommand ) : m_simCommand( aCommand ) -{ -} - - -SIM_PANEL_BASE::SIM_PANEL_BASE( const wxString& aCommand, wxWindow* parent, wxWindowID id, - const wxPoint& pos, const wxSize& size, long style, +SIM_PANEL_BASE::SIM_PANEL_BASE( const wxString& aCommand, int aOptions, wxWindow* parent, + wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxWindow( parent, id, pos, size, style, name ), - m_simCommand( aCommand ) + m_simCommand( aCommand ), + m_simOptions( aOptions ) { } @@ -75,10 +73,10 @@ SIM_TYPE SIM_PANEL_BASE::GetType() const } -SIM_NOPLOT_PANEL::SIM_NOPLOT_PANEL( const wxString& aCommand, wxWindow* parent, wxWindowID id, - const wxPoint& pos, const wxSize& size, long style, - const wxString& name ) : - SIM_PANEL_BASE( aCommand, parent, id, pos, size, style, name ) +SIM_NOPLOT_PANEL::SIM_NOPLOT_PANEL( const wxString& aCommand, int aOptions, wxWindow* parent, + wxWindowID id, const wxPoint& pos, const wxSize& size, + long style, const wxString& name ) : + SIM_PANEL_BASE( aCommand, aOptions, parent, id, pos, size, style, name ) { m_sizer = new wxBoxSizer( wxVERTICAL ); m_sizer->Add( 0, 1, 1, wxEXPAND, 5 ); diff --git a/eeschema/sim/sim_panel_base.h b/eeschema/sim/sim_panel_base.h index 99645a45bc..eed03acfee 100644 --- a/eeschema/sim/sim_panel_base.h +++ b/eeschema/sim/sim_panel_base.h @@ -39,8 +39,7 @@ class SIM_PANEL_BASE : public wxWindow public: SIM_PANEL_BASE(); - SIM_PANEL_BASE( const wxString& aCommand ); - SIM_PANEL_BASE( const wxString& aCommand, wxWindow* parent, wxWindowID id, + SIM_PANEL_BASE( const wxString& aCommand, int aOptions, wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxPanelNameStr ); virtual ~SIM_PANEL_BASE(); @@ -64,15 +63,19 @@ protected: m_simCommand = aSimCommand; } + const int getSimOptions() const { return m_simOptions; } + void setSimOptions( int aOptions ) { m_simOptions = aOptions; } + private: wxString m_simCommand; + int m_simOptions; }; class SIM_NOPLOT_PANEL : public SIM_PANEL_BASE { public: - SIM_NOPLOT_PANEL( const wxString& aCommand, wxWindow* parent, wxWindowID id, + SIM_NOPLOT_PANEL( const wxString& aCommand, int aOptions, wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxPanelNameStr ); diff --git a/eeschema/sim/sim_plot_frame.cpp b/eeschema/sim/sim_plot_frame.cpp index 0959593ff0..bb305e8ec5 100644 --- a/eeschema/sim/sim_plot_frame.cpp +++ b/eeschema/sim/sim_plot_frame.cpp @@ -454,15 +454,7 @@ void SIM_PLOT_FRAME::StartSimulation( const wxString& aSimCommand ) if( aSimCommand != wxEmptyString ) m_circuitModel->SetSimCommandOverride( aSimCommand ); - // Make .save all and .probe all permanent for now. - int options = NETLIST_EXPORTER_SPICE::OPTION_DEFAULT_FLAGS - | NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_VOLTAGES - | NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_CURRENTS; - - if( !m_simulator->Settings()->GetFixIncludePaths() ) - options &= ~NETLIST_EXPORTER_SPICE::OPTION_ADJUST_INCLUDE_PATHS; - - m_circuitModel->SetOptions( options ); + m_circuitModel->SetSimOptions( getCurrentOptions() ); wxString errors; WX_STRING_REPORTER reporter( &errors ); @@ -515,7 +507,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, int aOptions ) { SIM_PANEL_BASE* plotPanel = nullptr; SIM_TYPE simType = NGSPICE_CIRCUIT_MODEL::CommandToSimType( aSimCommand ); @@ -523,7 +515,7 @@ SIM_PANEL_BASE* SIM_PLOT_FRAME::NewPlotPanel( wxString aSimCommand ) if( SIM_PANEL_BASE::IsPlottable( simType ) ) { SIM_PLOT_PANEL* panel; - panel = new SIM_PLOT_PANEL( aSimCommand, m_workbook, this, wxID_ANY ); + panel = new SIM_PLOT_PANEL( aSimCommand, aOptions, m_workbook, this, wxID_ANY ); panel->GetPlotWin()->EnableMouseWheelPan( Pgm().GetCommonSettings()->m_Input.scroll_modifier_zoom != 0 ); @@ -533,7 +525,7 @@ SIM_PANEL_BASE* SIM_PLOT_FRAME::NewPlotPanel( wxString aSimCommand ) else { SIM_NOPLOT_PANEL* panel; - panel = new SIM_NOPLOT_PANEL( aSimCommand, m_workbook, wxID_ANY ); + panel = new SIM_NOPLOT_PANEL( aSimCommand, aOptions, m_workbook, wxID_ANY ); plotPanel = dynamic_cast( panel ); } @@ -674,8 +666,8 @@ void SIM_PLOT_FRAME::addPlot( const wxString& aName, SIM_PLOT_TYPE aType ) if( !plotPanel || plotPanel->GetType() != simType ) { - plotPanel = - dynamic_cast( NewPlotPanel( m_circuitModel->GetSimCommand() ) ); + plotPanel = dynamic_cast( NewPlotPanel( m_circuitModel->GetSimCommand(), + m_circuitModel->GetSimOptions() ) ); } wxASSERT( plotPanel ); @@ -949,9 +941,30 @@ bool SIM_PLOT_FRAME::loadWorkbook( const wxString& aPath ) if( !file.Open() ) return false; + long version = 1; + wxString firstLine = file.GetFirstLine(); + wxString plotCountLine; + + if( firstLine.StartsWith( wxT( "version " ) ) ) + { + if( !firstLine.substr( 8 ).ToLong( &version ) ) + { + DISPLAY_LOAD_ERROR( "Error loading workbook: Line %d is not an integer." ); + file.Close(); + + return false; + } + + plotCountLine = file.GetNextLine(); + } + else + { + plotCountLine = firstLine; + } + long plotsCount; - if( !file.GetFirstLine().ToLong( &plotsCount ) ) // GetFirstLine instead of GetNextLine + if( !plotCountLine.ToLong( &plotsCount ) ) // GetFirstLine instead of GetNextLine { DISPLAY_LOAD_ERROR( "Error loading workbook: Line %d is not an integer." ); file.Close(); @@ -971,8 +984,33 @@ bool SIM_PLOT_FRAME::loadWorkbook( const wxString& aPath ) return false; } - wxString simCommand = UnescapeString( file.GetNextLine() ); - NewPlotPanel( simCommand ); + wxString command = UnescapeString( file.GetNextLine() ); + wxString simCommand; + int simOptions = NETLIST_EXPORTER_SPICE::OPTION_DEFAULT_FLAGS; + wxStringTokenizer tokenizer( command, wxT( "\r\n" ), wxTOKEN_STRTOK ); + + if( version >= 2 ) + { + simOptions &= ~NETLIST_EXPORTER_SPICE::OPTION_ADJUST_INCLUDE_PATHS; + simOptions &= ~NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_VOLTAGES; + simOptions &= ~NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_CURRENTS; + } + + while( tokenizer.HasMoreTokens() ) + { + wxString line = tokenizer.GetNextToken(); + + if( line.StartsWith( wxT( ".kicad adjustpaths" ) ) ) + simOptions |= NETLIST_EXPORTER_SPICE::OPTION_ADJUST_INCLUDE_PATHS; + else if( line.StartsWith( wxT( ".save all" ) ) ) + simOptions |= NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_VOLTAGES; + else if( line.StartsWith( wxT( ".probe alli" ) ) ) + simOptions |= NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_CURRENTS; + else + simCommand += line + wxT( "\n" ); + } + + NewPlotPanel( simCommand, simOptions ); StartSimulation( simCommand ); // Perform simulation, so plots can be added with values @@ -1062,6 +1100,8 @@ bool SIM_PLOT_FRAME::saveWorkbook( const wxString& aPath ) file.Create(); } + file.AddLine( wxT( "version 2" ) ); + file.AddLine( wxString::Format( wxT( "%llu" ), m_workbook->GetPageCount() ) ); for( size_t i = 0; i < m_workbook->GetPageCount(); i++ ) @@ -1075,7 +1115,20 @@ bool SIM_PLOT_FRAME::saveWorkbook( const wxString& aPath ) } file.AddLine( wxString::Format( wxT( "%d" ), basePanel->GetType() ) ); - file.AddLine( EscapeString( m_workbook->GetSimCommand( basePanel ), CTX_LINE ) ); + + wxString command = m_workbook->GetSimCommand( basePanel ); + int options = m_workbook->GetSimOptions( basePanel ); + + if( options & NETLIST_EXPORTER_SPICE::OPTION_ADJUST_INCLUDE_PATHS ) + command += wxT( "\n.kicad adjustpaths" ); + + if( options & NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_VOLTAGES ) + command += wxT( "\n.save all" ); + + if( options & NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_CURRENTS ) + command += wxT( "\n.probe alli" ); + + file.AddLine( EscapeString( command, CTX_LINE ) ); const SIM_PLOT_PANEL* plotPanel = dynamic_cast( basePanel ); @@ -1161,7 +1214,7 @@ void SIM_PLOT_FRAME::menuNewPlot( wxCommandEvent& aEvent ) SIM_TYPE type = m_circuitModel->GetSimType(); if( SIM_PANEL_BASE::IsPlottable( type ) ) - NewPlotPanel( m_circuitModel->GetSimCommand() ); + NewPlotPanel( m_circuitModel->GetSimCommand(), m_circuitModel->GetSimOptions() ); } @@ -1489,7 +1542,14 @@ void SIM_PLOT_FRAME::onSettings( wxCommandEvent& event ) } if( m_workbook->GetPageIndex( plotPanelWindow ) != wxNOT_FOUND ) + { dlg.SetSimCommand( m_workbook->GetSimCommand( plotPanelWindow ) ); + dlg.SetSimOptions( m_workbook->GetSimOptions( plotPanelWindow ) ); + } + else + { + dlg.SetSimOptions( NETLIST_EXPORTER_SPICE::OPTION_DEFAULT_FLAGS ); + } if( dlg.ShowModal() == wxID_OK ) { @@ -1501,12 +1561,14 @@ void SIM_PLOT_FRAME::onSettings( wxCommandEvent& event ) oldCommand = wxString(); const wxString& newCommand = dlg.GetSimCommand(); + int newOptions = dlg.GetSimOptions(); SIM_TYPE newSimType = NGSPICE_CIRCUIT_MODEL::CommandToSimType( newCommand ); if( !plotPanelWindow ) { m_circuitModel->SetSimCommandOverride( newCommand ); - plotPanelWindow = NewPlotPanel( newCommand ); + m_circuitModel->SetSimOptions( newOptions ); + plotPanelWindow = NewPlotPanel( newCommand, newOptions ); } // 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'. @@ -1514,7 +1576,7 @@ void SIM_PLOT_FRAME::onSettings( wxCommandEvent& event ) || ( newSimType == ST_DC && oldCommand.Lower().GetChar( 4 ) != newCommand.Lower().GetChar( 4 ) ) ) { - plotPanelWindow = NewPlotPanel( newCommand ); + plotPanelWindow = NewPlotPanel( newCommand, newOptions ); } else { @@ -1523,6 +1585,7 @@ void SIM_PLOT_FRAME::onSettings( wxCommandEvent& event ) // Update simulation command in the current plot m_workbook->SetSimCommand( plotPanelWindow, newCommand ); + m_workbook->SetSimOptions( plotPanelWindow, newOptions ); } m_simulator->Init(); @@ -1581,67 +1644,70 @@ void SIM_PLOT_FRAME::onTune( wxCommandEvent& event ) } -void SIM_PLOT_FRAME::onShowNetlist( wxCommandEvent& event ) +class NETLIST_VIEW_DIALOG : public DIALOG_SHIM { - class NETLIST_VIEW_DIALOG : public DIALOG_SHIM +public: + enum { - public: - enum - { - MARGIN_LINE_NUMBERS - }; - - void onClose( wxCloseEvent& evt ) - { - wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL ) ); - } - - NETLIST_VIEW_DIALOG( wxWindow* parent, const wxString& source) : - DIALOG_SHIM( parent, wxID_ANY, _( "SPICE Netlist" ), wxDefaultPosition, - wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ) - { - wxStyledTextCtrl* textCtrl = new wxStyledTextCtrl( this, wxID_ANY ); - textCtrl->SetMinSize( wxSize( 600, 400 ) ); - - textCtrl->SetMarginWidth( MARGIN_LINE_NUMBERS, 50 ); - textCtrl->StyleSetForeground( wxSTC_STYLE_LINENUMBER, wxColour( 75, 75, 75 ) ); - textCtrl->StyleSetBackground( wxSTC_STYLE_LINENUMBER, wxColour( 220, 220, 220 ) ); - textCtrl->SetMarginType( MARGIN_LINE_NUMBERS, wxSTC_MARGIN_NUMBER ); - - wxFont fixedFont = KIUI::GetMonospacedUIFont(); - - for( int i = 0; i < wxSTC_STYLE_MAX; ++i ) - textCtrl->StyleSetFont( i, fixedFont ); - - textCtrl->StyleClearAll(); // Addresses a bug in wx3.0 where styles are not correctly set - - textCtrl->SetWrapMode( wxSTC_WRAP_WORD ); - - textCtrl->SetText( source ); - - textCtrl->SetLexer( wxSTC_LEX_SPICE ); - - wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL ); - sizer->Add( textCtrl, 1, wxEXPAND | wxALL, 5 ); - SetSizer( sizer ); - - Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( NETLIST_VIEW_DIALOG::onClose ), - nullptr, this ); - - m_scintillaTricks = std::make_unique( textCtrl, wxT( "{}" ), false ); - - finishDialogSettings(); - } - - std::unique_ptr m_scintillaTricks; + MARGIN_LINE_NUMBERS }; + void onClose( wxCloseEvent& evt ) + { + wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL ) ); + } + + NETLIST_VIEW_DIALOG( wxWindow* parent, const wxString& source) : + DIALOG_SHIM( parent, wxID_ANY, _( "SPICE Netlist" ), wxDefaultPosition, + wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ) + { + wxStyledTextCtrl* textCtrl = new wxStyledTextCtrl( this, wxID_ANY ); + textCtrl->SetMinSize( wxSize( 600, 400 ) ); + + textCtrl->SetMarginWidth( MARGIN_LINE_NUMBERS, 50 ); + textCtrl->StyleSetForeground( wxSTC_STYLE_LINENUMBER, wxColour( 75, 75, 75 ) ); + textCtrl->StyleSetBackground( wxSTC_STYLE_LINENUMBER, wxColour( 220, 220, 220 ) ); + textCtrl->SetMarginType( MARGIN_LINE_NUMBERS, wxSTC_MARGIN_NUMBER ); + + wxFont fixedFont = KIUI::GetMonospacedUIFont(); + + for( int i = 0; i < wxSTC_STYLE_MAX; ++i ) + textCtrl->StyleSetFont( i, fixedFont ); + + textCtrl->StyleClearAll(); // Addresses a bug in wx3.0 where styles are not correctly set + + textCtrl->SetWrapMode( wxSTC_WRAP_WORD ); + + textCtrl->SetText( source ); + + textCtrl->SetLexer( wxSTC_LEX_SPICE ); + + wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL ); + sizer->Add( textCtrl, 1, wxEXPAND | wxALL, 5 ); + SetSizer( sizer ); + + Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( NETLIST_VIEW_DIALOG::onClose ), + nullptr, this ); + + m_scintillaTricks = std::make_unique( textCtrl, wxT( "{}" ), false ); + + finishDialogSettings(); + } + + std::unique_ptr m_scintillaTricks; +}; + + +void SIM_PLOT_FRAME::onShowNetlist( wxCommandEvent& event ) +{ if( m_schematicFrame == nullptr || m_simulator == nullptr ) return; wxString errors; WX_STRING_REPORTER reporter( &errors ); STRING_FORMATTER formatter; + + m_circuitModel->SetSimOptions( getCurrentOptions() ); m_circuitModel->GetNetlist( &formatter, reporter ); NETLIST_VIEW_DIALOG dlg( this, errors.IsEmpty() ? formatter.GetString() : errors ); @@ -1769,7 +1835,10 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent ) SIM_PANEL_BASE* plotPanelWindow = getCurrentPlotWindow(); if( !plotPanelWindow || plotPanelWindow->GetType() != simType ) - plotPanelWindow = NewPlotPanel( m_circuitModel->GetSimCommand() ); + { + plotPanelWindow = NewPlotPanel( m_circuitModel->GetSimCommand(), + m_circuitModel->GetSimOptions() ); + } // Sometimes (for instance with a directive like wrdata my_file.csv "my_signal") // the simulator is in idle state (simulation is finished), but still running, during diff --git a/eeschema/sim/sim_plot_frame.h b/eeschema/sim/sim_plot_frame.h index f0cdcad3c1..89a5ac69ca 100644 --- a/eeschema/sim/sim_plot_frame.h +++ b/eeschema/sim/sim_plot_frame.h @@ -69,10 +69,11 @@ public: /** * Create a new plot panel for a given simulation type and adds it to the main notebook. * - * @param aSimType is requested simulation type. + * @param aSimCommand is requested simulation command. + * @param aSimOptions netlisting options * @return The new plot panel. */ - SIM_PANEL_BASE* NewPlotPanel( wxString aSimCommand ); + SIM_PANEL_BASE* NewPlotPanel( wxString aSimCommand, int aSimOptions ); /** * Add a voltage plot for a given net name. @@ -239,6 +240,14 @@ private: return m_workbook->GetSimCommand( getCurrentPlotWindow() ); } + int getCurrentOptions() const + { + if( getCurrentPlotWindow() == nullptr ) + return m_circuitModel->GetSimOptions(); + else + return m_workbook->GetSimOptions( getCurrentPlotWindow() ); + } + /** * Return X axis for a given simulation type. */ @@ -313,13 +322,13 @@ private: wxToolBarToolBase* m_toolTune; wxToolBarToolBase* m_toolSettings; - SCH_EDIT_FRAME* m_schematicFrame; + SCH_EDIT_FRAME* m_schematicFrame; std::shared_ptr m_circuitModel; - std::shared_ptr m_simulator; - SIM_THREAD_REPORTER* m_reporter; + std::shared_ptr m_simulator; + SIM_THREAD_REPORTER* m_reporter; ///< List of currently displayed tuners - std::list m_tuners; + std::list m_tuners; // Right click context menu for signals in the listbox class SIGNAL_CONTEXT_MENU : public wxMenu diff --git a/eeschema/sim/sim_plot_panel.cpp b/eeschema/sim/sim_plot_panel.cpp index 5dc9781157..fe43ad13a6 100644 --- a/eeschema/sim/sim_plot_panel.cpp +++ b/eeschema/sim/sim_plot_panel.cpp @@ -301,10 +301,10 @@ void CURSOR::UpdateReference() } -SIM_PLOT_PANEL::SIM_PLOT_PANEL( const wxString& aCommand, wxWindow* parent, +SIM_PLOT_PANEL::SIM_PLOT_PANEL( const wxString& aCommand, int aOptions, wxWindow* parent, SIM_PLOT_FRAME* aMainFrame, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) - : SIM_PANEL_BASE( aCommand, parent, id, pos, size, style, name ), + : SIM_PANEL_BASE( aCommand, aOptions, parent, id, pos, size, style, name ), m_axis_x( nullptr ), m_axis_y1( nullptr ), m_axis_y2( nullptr ), diff --git a/eeschema/sim/sim_plot_panel.h b/eeschema/sim/sim_plot_panel.h index 514f82b5bc..67bc5492e4 100644 --- a/eeschema/sim/sim_plot_panel.h +++ b/eeschema/sim/sim_plot_panel.h @@ -46,7 +46,10 @@ class CURSOR : public mpInfoLayer public: CURSOR( const TRACE* aTrace, SIM_PLOT_PANEL* aPlotPanel ) : mpInfoLayer( wxRect( 0, 0, DRAG_MARGIN, DRAG_MARGIN ), wxTRANSPARENT_BRUSH ), - m_trace( aTrace ), m_updateRequired( true ), m_updateRef( false ), m_coords( 0.0, 0.0 ), + m_trace( aTrace ), + m_updateRequired( true ), + m_updateRef( false ), + m_coords( 0.0, 0.0 ), m_window( nullptr ) { SetDrawOutsideMargins( false ); @@ -95,7 +98,9 @@ class TRACE : public mpFXYVector { public: TRACE( const wxString& aName, SIM_PLOT_TYPE aType ) : - mpFXYVector( aName ), m_cursor( nullptr ), m_type( aType ) + mpFXYVector( aName ), + m_cursor( nullptr ), + m_type( aType ) { SetContinuity( true ); SetDrawOutsideMargins( false ); @@ -178,10 +183,10 @@ class SIM_PLOT_PANEL : public SIM_PANEL_BASE friend class SIM_WORKBOOK; public: - SIM_PLOT_PANEL( const wxString& aCommand, wxWindow* parent, SIM_PLOT_FRAME* aMainFrame, - wxWindowID id, const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, long style = 0, - const wxString& name = wxPanelNameStr ); + SIM_PLOT_PANEL( const wxString& aCommand, int aOptions, wxWindow* parent, + SIM_PLOT_FRAME* aMainFrame, wxWindowID id, + const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, + long style = 0, const wxString& name = wxPanelNameStr ); virtual ~SIM_PLOT_PANEL(); diff --git a/eeschema/sim/sim_workbook.h b/eeschema/sim/sim_workbook.h index 292535d0e9..3b731849f4 100644 --- a/eeschema/sim/sim_workbook.h +++ b/eeschema/sim/sim_workbook.h @@ -63,6 +63,17 @@ public: return aPlotPanel->getSimCommand(); } + void SetSimOptions( SIM_PANEL_BASE* aPlotPanel, int aOptions ) + { + aPlotPanel->setSimOptions( aOptions ); + setModified(); + } + + int GetSimOptions( const SIM_PANEL_BASE* aPlotPanel ) + { + return aPlotPanel->getSimOptions(); + } + void ClrModified(); bool IsModified() const { return m_modified; }