KiCad PCB EDA Suite
Loading...
Searching...
No Matches
simulator_frame.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2016-2023 CERN
5 * Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Tomasz Wlostowski <[email protected]>
7 * @author Maciej Suminski <[email protected]>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 3
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * https://www.gnu.org/licenses/gpl-3.0.html
22 * or you may search the http://www.gnu.org website for the version 3 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27#include <wx/debug.h>
28
29// For some obscure reason, needed on msys2 with some wxWidgets versions (3.0) to avoid
30// undefined symbol at link stage (due to use of #include <pegtl.hpp>)
31// Should not create issues on other platforms
32#include <wx/menu.h>
33
35#include <sch_edit_frame.h>
36#include <kiway.h>
37#include <confirm.h>
38#include <bitmaps.h>
42#include <widgets/wx_grid.h>
43#include <tool/tool_manager.h>
45#include <tool/action_manager.h>
46#include <tool/action_toolbar.h>
47#include <tool/common_control.h>
49#include <tools/ee_actions.h>
50#include <string_utils.h>
51#include <pgm_base.h>
52#include "ngspice.h"
53#include <sim/simulator_frame.h>
55#include <sim/sim_plot_tab.h>
56#include <sim/spice_simulator.h>
58#include <eeschema_settings.h>
59#include <advanced_config.h>
60
61#include <memory>
62
63
64// Reporter is stored by pointer in KIBIS, so keep this here to avoid crashes
66
67
69{
70public:
72 m_parent( aParent )
73 {
74 }
75
76 REPORTER& Report( const wxString& aText, SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override
77 {
78 wxCommandEvent* event = new wxCommandEvent( EVT_SIM_REPORT );
79 event->SetString( aText );
80 wxQueueEvent( m_parent, event );
81 return *this;
82 }
83
84 bool HasMessage() const override
85 {
86 return false; // Technically "indeterminate" rather than false.
87 }
88
89 void OnSimStateChange( SIMULATOR* aObject, SIM_STATE aNewState ) override
90 {
91 wxCommandEvent* event = nullptr;
92
93 switch( aNewState )
94 {
95 case SIM_IDLE: event = new wxCommandEvent( EVT_SIM_FINISHED ); break;
96 case SIM_RUNNING: event = new wxCommandEvent( EVT_SIM_STARTED ); break;
97 default: wxFAIL; return;
98 }
99
100 wxQueueEvent( m_parent, event );
101 }
102
103private:
105};
106
107
108BEGIN_EVENT_TABLE( SIMULATOR_FRAME, KIWAY_PLAYER )
109 EVT_MENU( wxID_EXIT, SIMULATOR_FRAME::onExit )
110 EVT_MENU( wxID_CLOSE, SIMULATOR_FRAME::onExit )
111END_EVENT_TABLE()
112
113
114SIMULATOR_FRAME::SIMULATOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
115 KIWAY_PLAYER( aKiway, aParent, FRAME_SIMULATOR, _( "Simulator" ), wxDefaultPosition,
116 wxDefaultSize, wxDEFAULT_FRAME_STYLE, wxT( "simulator" ), unityScale ),
117 m_schematicFrame( nullptr ),
118 m_toolBar( nullptr ),
119 m_ui( nullptr ),
120 m_simFinished( false ),
121 m_workbookModified( false )
122{
123 m_schematicFrame = (SCH_EDIT_FRAME*) Kiway().Player( FRAME_SCH, false );
124 wxASSERT( m_schematicFrame );
125
126 // Give an icon
127 wxIcon icon;
128 icon.CopyFromBitmap( KiBitmap( BITMAPS::simulator ) );
129 SetIcon( icon );
130
131 wxBoxSizer* mainSizer = new wxBoxSizer( wxVERTICAL );
132 SetSizer( mainSizer );
133
134 m_infoBar = new WX_INFOBAR( this );
135 mainSizer->Add( m_infoBar, 0, wxEXPAND, 0 );
136
137 m_toolBar = new ACTION_TOOLBAR( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
138 wxAUI_TB_DEFAULT_STYLE|wxAUI_TB_HORZ_LAYOUT|wxAUI_TB_PLAIN_BACKGROUND );
139 m_toolBar->Realize();
140 mainSizer->Add( m_toolBar, 0, wxEXPAND, 5 );
141
142 m_ui = new SIMULATOR_FRAME_UI( this, m_schematicFrame );
143 mainSizer->Add( m_ui, 1, wxEXPAND, 5 );
144
145 m_simulator = SIMULATOR::CreateInstance( "ngspice" );
146 wxASSERT( m_simulator );
147
148 LoadSettings( config() );
149
150 NGSPICE_SETTINGS* settings = dynamic_cast<NGSPICE_SETTINGS*>( m_simulator->Settings().get() );
151
152 wxCHECK2( settings, /* do nothing in release builds*/ );
153
154 if( settings && settings->GetWorkbookFilename().IsEmpty() )
156
157 m_simulator->Init();
158
159 m_reporter = new SIM_THREAD_REPORTER( this );
160 m_simulator->SetReporter( m_reporter );
161
162 m_circuitModel = std::make_shared<SPICE_CIRCUIT_MODEL>( &m_schematicFrame->Schematic() );
163
164 setupTools();
165 setupUIConditions();
166
167 ReCreateHToolbar();
168 ReCreateMenuBar();
169
170 Bind( wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( SIMULATOR_FRAME::onExit ), this,
171 wxID_EXIT );
172
173 Bind( EVT_SIM_UPDATE, &SIMULATOR_FRAME::onUpdateSim, this );
174 Bind( EVT_SIM_REPORT, &SIMULATOR_FRAME::onSimReport, this );
175 Bind( EVT_SIM_STARTED, &SIMULATOR_FRAME::onSimStarted, this );
176 Bind( EVT_SIM_FINISHED, &SIMULATOR_FRAME::onSimFinished, this );
177
178 // Ensure new items are taken in account by sizers:
179 Layout();
180
181 // resize the subwindows size. At least on Windows, calling wxSafeYield before
182 // resizing the subwindows forces the wxSplitWindows size events automatically generated
183 // by wxWidgets to be executed before our resize code.
184 // Otherwise, the changes made by setSubWindowsSashSize are overwritten by one these
185 // events
186 wxSafeYield();
187 m_ui->SetSubWindowsSashSize();
188
189 // Ensure the window is on top
190 Raise();
191
192 m_ui->InitWorkbook();
193 UpdateTitle();
194}
195
196
198{
199 NULL_REPORTER devnull;
200
201 m_simulator->Attach( nullptr, wxEmptyString, 0, wxEmptyString, devnull );
202 m_simulator->SetReporter( nullptr );
203 delete m_reporter;
204}
205
206
208{
209 // Create the manager
211 m_toolManager->SetEnvironment( nullptr, nullptr, nullptr, config(), this );
212
214
215 // Attach the events to the tool dispatcher
217 Bind( wxEVT_CHAR_HOOK, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher );
218
219 // Register tools
223}
224
225
227{
229
230 UpdateTitle();
231
233}
234
235
237{
238 EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( aCfg );
239 wxASSERT( cfg );
240
241 if( cfg )
242 {
244 m_ui->LoadSettings( cfg );
245 }
246
248
249 NGSPICE* currentSim = dynamic_cast<NGSPICE*>( m_simulator.get() );
250
251 if( currentSim )
252 m_simulator->Settings() = project.m_SchematicSettings->m_NgspiceSettings;
253}
254
255
257{
258 EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( aCfg );
259 wxASSERT( cfg );
260
261 if( cfg )
262 {
264 m_ui->SaveSettings( cfg );
265 }
266
268
269 if( project.m_SchematicSettings )
270 {
271 bool modified = project.m_SchematicSettings->m_NgspiceSettings->SaveToFile();
272
273 if( m_schematicFrame && modified )
275 }
276}
277
278
279void SIMULATOR_FRAME::CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVarsChanged )
280{
281 KIWAY_PLAYER::CommonSettingsChanged( aEnvVarsChanged, aTextVarsChanged );
282
283 auto* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( m_toolManager->GetSettings() );
284 wxASSERT( cfg != nullptr );
285 m_ui->ApplyPreferences( cfg->m_Simulator.preferences );
286}
287
288
290{
291 EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( aCfg );
292 wxASSERT( cfg );
293
294 return cfg ? &cfg->m_Simulator.window : nullptr;
295}
296
297
299{
300 if( m_ui->GetCurrentSimTab() )
302 else
303 return m_circuitModel->GetSchTextSimCommand();
304}
305
306
308{
310}
311
312
314{
315 if( SIM_TAB* simTab = m_ui->GetCurrentSimTab() )
316 return simTab->GetSimOptions();
317 else
319}
320
321
323{
324 bool unsaved = true;
325 bool readOnly = false;
326 wxString title;
327 wxFileName filename = Prj().AbsolutePath( m_simulator->Settings()->GetWorkbookFilename() );
328
329 if( filename.IsOk() && filename.FileExists() )
330 {
331 unsaved = false;
332 readOnly = !filename.IsFileWritable();
333 }
334
336 title = wxT( "*" ) + filename.GetName();
337 else
338 title = filename.GetName();
339
340 if( readOnly )
341 title += wxS( " " ) + _( "[Read Only]" );
342
343 if( unsaved )
344 title += wxS( " " ) + _( "[Unsaved]" );
345
346 title += wxT( " \u2014 " ) + _( "SPICE Simulator" );
347
348 SetTitle( title );
349}
350
351
352// Don't let the dialog grow too tall: you may not be able to get to the OK button
353#define MAX_MESSAGES 20
354
356{
357 if( !aReporter.HasMessage() )
358 return;
359
360 wxArrayString lines = wxSplit( aReporter.GetMessages(), '\n' );
361
362 if( lines.size() > MAX_MESSAGES )
363 {
364 lines.RemoveAt( MAX_MESSAGES, lines.size() - MAX_MESSAGES );
365 lines.Add( wxS( "..." ) );
366 }
367
369 {
370 DisplayErrorMessage( this, _( "Errors during netlist generation." ),
371 wxJoin( lines, '\n' ) );
372 }
373 else if( aReporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) )
374 {
375 DisplayInfoMessage( this, _( "Warnings during netlist generation." ),
376 wxJoin( lines, '\n' ) );
377 }
378}
379
380
381bool SIMULATOR_FRAME::LoadSimulator( const wxString& aSimCommand, unsigned aSimOptions )
382{
384
385 if( !m_schematicFrame->ReadyToNetlist( _( "Simulator requires a fully annotated schematic." ) ) )
386 return false;
387
388 // If we are using the new connectivity, make sure that we do a full-rebuild
389 if( ADVANCED_CFG::GetCfg().m_IncrementalConnectivity )
391
392 bool success = m_simulator->Attach( m_circuitModel, aSimCommand, aSimOptions,
393 Prj().GetProjectPath(), s_reporter );
394
396
397 return success;
398}
399
400
401void SIMULATOR_FRAME::ReloadSimulator( const wxString& aSimCommand, unsigned aSimOptions )
402{
404
405 m_simulator->Attach( m_circuitModel, aSimCommand, aSimOptions, Prj().GetProjectPath(),
406 s_reporter );
407
409}
410
411
413{
414 SIM_TAB* simTab = m_ui->GetCurrentSimTab();
415
416 if( !simTab )
417 return;
418
419 if( simTab->GetSimCommand().Upper().StartsWith( wxT( "FFT" ) )
420 || simTab->GetSimCommand().Upper().Contains( wxT( "\nFFT" ) ) )
421 {
422 wxString tranSpicePlot;
423
424 if( SIM_TAB* tranPlotTab = m_ui->GetSimTab( ST_TRAN ) )
425 tranSpicePlot = tranPlotTab->GetSpicePlotName();
426
427 if( tranSpicePlot.IsEmpty() )
428 {
429 DisplayErrorMessage( this, _( "You must run a TRAN simulation first; its results"
430 "will be used for the fast Fourier transform." ) );
431 }
432 else
433 {
434 m_simulator->Command( "setplot " + tranSpicePlot.ToStdString() );
435
436 wxArrayString commands = wxSplit( simTab->GetSimCommand(), '\n' );
437
438 for( const wxString& command : commands )
439 {
440 wxBusyCursor wait;
441 m_simulator->Command( command.ToStdString() );
442 }
443
444 simTab->SetSpicePlotName( m_simulator->CurrentPlotName() );
445 m_ui->OnSimRefresh( true );
446
447#if 0
448 m_simulator->Command( "setplot" ); // Print available plots to console
449 m_simulator->Command( "display" ); // Print vectors in current plot to console
450#endif
451 }
452
453 return;
454 }
455 else
456 {
457 if( m_ui->GetSimTabIndex( simTab ) == 0
458 && m_circuitModel->GetSchTextSimCommand() != simTab->GetLastSchTextSimCommand() )
459 {
460 if( simTab->GetLastSchTextSimCommand().IsEmpty()
461 || IsOK( this, _( "Schematic sheet simulation command directive has changed. "
462 "Do you wish to update the Simulation Command?" ) ) )
463 {
464 simTab->SetSimCommand( m_circuitModel->GetSchTextSimCommand() );
465 simTab->SetLastSchTextSimCommand( simTab->GetSimCommand() );
466 OnModify();
467 }
468 }
469 }
470
471 if( !LoadSimulator( simTab->GetSimCommand(), simTab->GetSimOptions() ) )
472 return;
473
474 std::unique_lock<std::mutex> simulatorLock( m_simulator->GetMutex(), std::try_to_lock );
475
476 if( simulatorLock.owns_lock() )
477 {
478 m_simFinished = false;
479
480 m_ui->OnSimUpdate();
481 m_simulator->Run();
482
483 // Netlist from schematic may have changed; update signals list, measurements list,
484 // etc.
486 }
487 else
488 {
489 DisplayErrorMessage( this, _( "Another simulation is already running." ) );
490 }
491}
492
493
494SIM_TAB* SIMULATOR_FRAME::NewSimTab( const wxString& aSimCommand )
495{
496 return m_ui->NewSimTab( aSimCommand );
497}
498
499
500const std::vector<wxString> SIMULATOR_FRAME::SimPlotVectors()
501{
502 return m_ui->SimPlotVectors();
503}
504
505
506const std::vector<wxString> SIMULATOR_FRAME::Signals()
507{
508 return m_ui->Signals();
509}
510
511
512const std::map<int, wxString>& SIMULATOR_FRAME::UserDefinedSignals()
513{
514 return m_ui->UserDefinedSignals();
515}
516
517
518void SIMULATOR_FRAME::SetUserDefinedSignals( const std::map<int, wxString>& aSignals )
519{
520 m_ui->SetUserDefinedSignals( aSignals );
521}
522
523
524void SIMULATOR_FRAME::AddVoltageTrace( const wxString& aNetName )
525{
526 m_ui->AddTrace( aNetName, SPT_VOLTAGE );
527}
528
529
530void SIMULATOR_FRAME::AddCurrentTrace( const wxString& aDeviceName )
531{
532 m_ui->AddTrace( aDeviceName, SPT_CURRENT );
533}
534
535
536void SIMULATOR_FRAME::AddTuner( const SCH_SHEET_PATH& aSheetPath, SCH_SYMBOL* aSymbol )
537{
538 m_ui->AddTuner( aSheetPath, aSymbol );
539}
540
541
543{
544 return m_ui->GetCurrentSimTab();
545}
546
547
548bool SIMULATOR_FRAME::LoadWorkbook( const wxString& aPath )
549{
550 if( m_ui->LoadWorkbook( aPath ) )
551 {
552 UpdateTitle();
553
554 // Successfully loading a workbook does not count as modifying it. Clear the modified
555 // flag after all the EVT_WORKBOOK_MODIFIED events have been processed.
556 CallAfter( [this]()
557 {
558 m_workbookModified = false;
559 } );
560
561 return true;
562 }
563
564 DisplayErrorMessage( this, wxString::Format( _( "Unable to load or parse file %s" ), aPath ) );
565 return false;
566}
567
568
569bool SIMULATOR_FRAME::SaveWorkbook( const wxString& aPath )
570{
571 if( m_ui->SaveWorkbook( aPath ) )
572 {
573 m_workbookModified = false;
574 UpdateTitle();
575
576 return true;
577 }
578
579 return false;
580}
581
582
584{
586}
587
588
590{
591 SIM_TAB* simTab = m_ui->GetCurrentSimTab();
592 DIALOG_SIM_COMMAND dlg( this, m_circuitModel, m_simulator->Settings() );
593
595
596 if( !simTab )
597 return false;
598
600 s_reporter );
601
603
604 dlg.SetSimCommand( simTab->GetSimCommand() );
605 dlg.SetSimOptions( simTab->GetSimOptions() );
606 dlg.SetPlotSettings( simTab );
607
608 if( dlg.ShowModal() == wxID_OK )
609 {
610 simTab->SetSimCommand( dlg.GetSimCommand() );
611 dlg.ApplySettings( simTab );
613 OnModify();
614 return true;
615 }
616
617 return false;
618}
619
620
621bool SIMULATOR_FRAME::canCloseWindow( wxCloseEvent& aEvent )
622{
624 {
625 wxFileName filename = m_simulator->Settings()->GetWorkbookFilename();
626
627 if( filename.GetName().IsEmpty() )
628 {
629 if( Prj().GetProjectName().IsEmpty() )
630 filename.SetFullName( wxT( "noname.wbk" ) );
631 else
632 filename.SetFullName( Prj().GetProjectName() + wxT( ".wbk" ) );
633 }
634
635 return HandleUnsavedChanges( this, _( "Save changes to workbook?" ),
636 [&]() -> bool
637 {
638 return SaveWorkbook( Prj().AbsolutePath( filename.GetFullName() ) );
639 } );
640 }
641
642 return true;
643}
644
645
647{
648 if( m_simulator->IsRunning() )
649 m_simulator->Stop();
650
651 // Prevent memory leak on exit by deleting all simulation vectors
652 m_simulator->Clean();
653
654 // Cancel a running simProbe or simTune tool
656
657 SaveSettings( config() );
658
659 m_simulator->Settings() = nullptr;
660
661 Destroy();
662}
663
664
666{
668
670 wxASSERT( mgr );
671
672 auto showGridCondition =
673 [this]( const SELECTION& aSel )
674 {
675 SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( GetCurrentSimTab() );
676 return plotTab && plotTab->IsGridShown();
677 };
678
679 auto showLegendCondition =
680 [this]( const SELECTION& aSel )
681 {
682 SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( GetCurrentSimTab() );
683 return plotTab && plotTab->IsLegendShown();
684 };
685
686 auto showDottedCondition =
687 [this]( const SELECTION& aSel )
688 {
689 SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( GetCurrentSimTab() );
690 return plotTab && plotTab->GetDottedSecondary();
691 };
692
693 auto darkModePlotCondition =
694 [this]( const SELECTION& aSel )
695 {
696 return m_ui->DarkModePlots();
697 };
698
699 auto simRunning =
700 [this]( const SELECTION& aSel )
701 {
702 return m_simulator && m_simulator->IsRunning();
703 };
704
705 auto simFinished =
706 [this]( const SELECTION& aSel )
707 {
708 return m_simFinished;
709 };
710
711 auto haveSim =
712 [this]( const SELECTION& aSel )
713 {
714 return GetCurrentSimTab() != nullptr;
715 };
716
717 auto havePlot =
718 [this]( const SELECTION& aSel )
719 {
720 return dynamic_cast<SIM_PLOT_TAB*>( GetCurrentSimTab() ) != nullptr;
721 };
722
723 auto haveZoomUndo =
724 [this]( const SELECTION& aSel )
725 {
726 SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( GetCurrentSimTab() );
727 return plotTab && plotTab->GetPlotWin()->UndoZoomStackSize() > 0;
728 };
729
730 auto haveZoomRedo =
731 [this]( const SELECTION& aSel )
732 {
733 SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( GetCurrentSimTab() );
734 return plotTab && plotTab->GetPlotWin()->RedoZoomStackSize() > 0;
735 };
736
737#define ENABLE( x ) ACTION_CONDITIONS().Enable( x )
738#define CHECK( x ) ACTION_CONDITIONS().Check( x )
739
743
748
749 mgr->SetConditions( ACTIONS::zoomUndo, ENABLE( haveZoomUndo ) );
750 mgr->SetConditions( ACTIONS::zoomRedo, ENABLE( haveZoomRedo ) );
751 mgr->SetConditions( EE_ACTIONS::toggleGrid, CHECK( showGridCondition ) );
752 mgr->SetConditions( EE_ACTIONS::toggleLegend, CHECK( showLegendCondition ) );
753 mgr->SetConditions( EE_ACTIONS::toggleDottedSecondary, CHECK( showDottedCondition ) );
754 mgr->SetConditions( EE_ACTIONS::toggleDarkModePlots, CHECK( darkModePlotCondition ) );
755
758 mgr->SetConditions( EE_ACTIONS::runSimulation, ENABLE( !simRunning ) );
759 mgr->SetConditions( EE_ACTIONS::stopSimulation, ENABLE( simRunning ) );
760 mgr->SetConditions( EE_ACTIONS::simProbe, ENABLE( simFinished ) );
761 mgr->SetConditions( EE_ACTIONS::simTune, ENABLE( simFinished ) );
763
764#undef CHECK
765#undef ENABLE
766}
767
768
769void SIMULATOR_FRAME::onSimStarted( wxCommandEvent& aEvent )
770{
771 SetCursor( wxCURSOR_ARROWWAIT );
772}
773
774
775void SIMULATOR_FRAME::onSimFinished( wxCommandEvent& aEvent )
776{
777 // Sometimes (for instance with a directive like wrdata my_file.csv "my_signal")
778 // the simulator is in idle state (simulation is finished), but still running, during
779 // the time the file is written. So gives a slice of time to fully finish the work:
780 if( m_simulator->IsRunning() )
781 {
782 int max_time = 40; // For a max timeout = 2s
783
784 do
785 {
786 wxMilliSleep( 50 );
787 wxYield();
788
789 if( max_time )
790 max_time--;
791
792 } while( max_time && m_simulator->IsRunning() );
793 }
794
795 // ensure the shown cursor is the default cursor, not the wxCURSOR_ARROWWAIT set when
796 // staring the simulator in onSimStarted:
797 SetCursor( wxNullCursor );
798
799 // Is a warning message useful if the simulatior is still running?
800 SCHEMATIC& schematic = m_schematicFrame->Schematic();
801 schematic.ClearOperatingPoints();
802
803 m_simFinished = true;
804
805 m_ui->OnSimRefresh( true );
806
809}
810
811
812void SIMULATOR_FRAME::onUpdateSim( wxCommandEvent& aEvent )
813{
814 static bool updateInProgress = false;
815
816 // skip update when events are triggered too often and previous call didn't end yet
817 if( updateInProgress )
818 return;
819
820 updateInProgress = true;
821
822 if( m_simulator->IsRunning() )
823 m_simulator->Stop();
824
825 std::unique_lock<std::mutex> simulatorLock( m_simulator->GetMutex(), std::try_to_lock );
826
827 if( simulatorLock.owns_lock() )
828 {
829 m_ui->OnSimUpdate();
830 m_simulator->Run();
831 }
832 else
833 {
834 DisplayErrorMessage( this, _( "Another simulation is already running." ) );
835 }
836
837 updateInProgress = false;
838}
839
840
841void SIMULATOR_FRAME::onSimReport( wxCommandEvent& aEvent )
842{
843 m_ui->OnSimReport( aEvent.GetString() );
844}
845
846
847void SIMULATOR_FRAME::onExit( wxCommandEvent& aEvent )
848{
849 if( aEvent.GetId() == wxID_EXIT )
850 Kiway().OnKiCadExit();
851
852 if( aEvent.GetId() == wxID_CLOSE )
853 Close( false );
854}
855
856
858{
860 m_workbookModified = true;
861 UpdateTitle();
862}
863
864
865wxDEFINE_EVENT( EVT_SIM_UPDATE, wxCommandEvent );
866wxDEFINE_EVENT( EVT_SIM_REPORT, wxCommandEvent );
867
868wxDEFINE_EVENT( EVT_SIM_STARTED, wxCommandEvent );
869wxDEFINE_EVENT( EVT_SIM_FINISHED, wxCommandEvent );
constexpr EDA_IU_SCALE unityScale
Definition: base_units.h:111
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:104
static TOOL_ACTION toggleGrid
Definition: actions.h:187
static TOOL_ACTION cancelInteractive
Definition: actions.h:65
static TOOL_ACTION zoomRedo
Definition: actions.h:140
static TOOL_ACTION zoomUndo
Definition: actions.h:139
Manage TOOL_ACTION objects.
void SetConditions(const TOOL_ACTION &aAction, const ACTION_CONDITIONS &aConditions)
Set the conditions the UI elements for activating a specific tool action should use for determining t...
Define the structure of a toolbar with buttons that invoke ACTIONs.
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
Definition: app_settings.h:92
Handle actions that are shared between different applications.
int ShowModal() override
void SetPlotSettings(const SIM_TAB *aSimTab)
void SetSimCommand(const wxString &aCommand)
void ApplySettings(SIM_TAB *aTab)
void SetSimOptions(int aOptions)
const wxString & GetSimCommand() const
virtual APP_SETTINGS_BASE * config() const
Returns the settings object used in SaveSettings(), and is overloaded in KICAD_MANAGER_FRAME.
void ShowChangedLanguage() override
Redraw the menus and what not in current language.
virtual void setupUIConditions()
Setup the UI conditions for the various actions and their controls in this frame.
virtual void OnModify()
Must be called after a model change in order to set the "modify" flag and do other frame-specific pro...
virtual void LoadSettings(APP_SETTINGS_BASE *aCfg)
Load common frame parameters from a configuration file.
void CommonSettingsChanged(bool aEnvVarsChanged, bool aTextVarsChanged) override
Notification event that some of the common (suite-wide) settings have changed.
virtual void SaveSettings(APP_SETTINGS_BASE *aCfg)
Save common frame parameters to a configuration data file.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
static TOOL_ACTION simAnalysisProperties
Definition: ee_actions.h:301
static TOOL_ACTION openWorkbook
Definition: ee_actions.h:288
static TOOL_ACTION stopSimulation
Definition: ee_actions.h:303
static TOOL_ACTION toggleLegend
Definition: ee_actions.h:298
static TOOL_ACTION saveWorkbook
Definition: ee_actions.h:289
static TOOL_ACTION saveWorkbookAs
Definition: ee_actions.h:290
static TOOL_ACTION exportPlotAsCSV
Definition: ee_actions.h:292
static TOOL_ACTION simTune
Definition: ee_actions.h:297
static TOOL_ACTION toggleDarkModePlots
Definition: ee_actions.h:300
static TOOL_ACTION exportPlotAsPNG
Definition: ee_actions.h:291
static TOOL_ACTION showNetlist
Definition: ee_actions.h:305
static TOOL_ACTION simProbe
Definition: ee_actions.h:296
static TOOL_ACTION toggleDottedSecondary
Definition: ee_actions.h:299
static TOOL_ACTION exportPlotToSchematic
Definition: ee_actions.h:294
static TOOL_ACTION runSimulation
Definition: ee_actions.h:302
static TOOL_ACTION newAnalysisTab
Definition: ee_actions.h:287
static TOOL_ACTION exportPlotToClipboard
Definition: ee_actions.h:293
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:55
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
Definition: kiway_player.h:65
bool Destroy() override
Our version of Destroy() which is virtual from wxWidgets.
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition: kiway.h:284
void OnKiCadExit()
Definition: kiway.cpp:725
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:406
Container for Ngspice simulator settings.
void SetCompatibilityMode(NGSPICE_COMPATIBILITY_MODE aMode)
A singleton reporter that reports to nowhere.
Definition: reporter.h:203
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:72
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:200
virtual const wxString AbsolutePath(const wxString &aFileName) const
Fix up aFileName if it is relative to the project's directory to be an absolute path and filename.
Definition: project.cpp:359
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:72
Holds all the data relating to one schematic.
Definition: schematic.h:77
void ClearOperatingPoints()
Clear operating points from a .op simulation.
Definition: schematic.h:238
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
Schematic editor (Eeschema) main window.
void RefreshOperatingPointDisplay()
Refresh the display of any operaintg points.
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag and update other data struc...
bool ReadyToNetlist(const wxString &aAnnotateMessage)
Check if we are ready to write a netlist file for the current schematic.
SCHEMATIC & Schematic() const
void RecalculateConnections(SCH_COMMIT *aCommit, SCH_CLEANUP_FLAGS aCleanupFlags)
Generate the connection data for the entire schematic hierarchy.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Schematic symbol object.
Definition: sch_symbol.h:104
static bool ShowAlways(const SELECTION &aSelection)
The default condition function (always returns true).
Handle actions for the various symbol editor and viewers.
The SIMULATOR_FRAME_UI holds the main user-interface for running simulations.
SIM_TAB * NewSimTab(const wxString &aSimCommand)
Create a new simulation tab for a given simulation type.
void SetUserDefinedSignals(const std::map< int, wxString > &aSignals)
void OnSimRefresh(bool aFinal)
SIM_TAB * GetSimTab(SIM_TYPE aType) const
std::vector< wxString > SimPlotVectors() const
std::vector< wxString > Signals() const
bool SaveWorkbook(const wxString &aPath)
Save plot, signal, cursor, measurement, etc.
SIM_TAB * GetCurrentSimTab() const
Return the currently opened plot panel (or NULL if there is none).
bool LoadWorkbook(const wxString &aPath)
Load plot, signal, cursor, measurement, etc.
bool DarkModePlots() const
const std::map< int, wxString > & UserDefinedSignals()
void AddTrace(const wxString &aName, SIM_TRACE_TYPE aType)
Add a new trace to the current plot.
void SaveSettings(EESCHEMA_SETTINGS *aCfg)
int GetSimTabIndex(SIM_TAB *aPlot) const
void OnSimReport(const wxString &aMsg)
void ApplyPreferences(const SIM_PREFERENCES &aPrefs)
Called when settings are changed via the common Preferences dialog.
void AddTuner(const SCH_SHEET_PATH &aSheetPath, SCH_SYMBOL *aSymbol)
Add a tuner for a symbol.
void LoadSettings(EESCHEMA_SETTINGS *aCfg)
The SIMULATOR_FRAME holds the main user-interface for running simulations.
SIM_TAB * GetCurrentSimTab() const
Return the current tab (or NULL if there is none).
void ShowChangedLanguage() override
bool canCloseWindow(wxCloseEvent &aEvent) override
void onSimFinished(wxCommandEvent &aEvent)
void CommonSettingsChanged(bool aEnvVarsChanged, bool aTextVarsChanged) override
Notification event that some of the common (suite-wide) settings have changed.
bool LoadSimulator(const wxString &aSimCommand, unsigned aSimOptions)
Check and load the current netlist into the simulator.
void onSimReport(wxCommandEvent &aEvent)
wxString GetCurrentSimCommand() const
void showNetlistErrors(const WX_STRING_REPORTER &aReporter)
void onExit(wxCommandEvent &event)
std::shared_ptr< SPICE_SIMULATOR > m_simulator
SIM_TYPE GetCurrentSimType() const
void setupUIConditions() override
Setup the UI conditions for the various actions and their controls in this frame.
void SaveSettings(APP_SETTINGS_BASE *aCfg) override
Save common frame parameters to a configuration data file.
void AddCurrentTrace(const wxString &aDeviceName)
Add a current trace for a given device to the current plot.
void OnModify() override
Must be called after a model change in order to set the "modify" flag and do other frame-specific pro...
bool SaveWorkbook(const wxString &aPath)
Save plot, signal, cursor, measurement, etc.
const std::vector< wxString > Signals()
void doCloseWindow() override
const std::vector< wxString > SimPlotVectors()
void AddVoltageTrace(const wxString &aNetName)
Add a voltage trace for a given net to the current plot.
void ToggleDarkModePlots()
Toggle dark-mode of the plot tabs.
SIM_THREAD_REPORTER * m_reporter
void AddTuner(const SCH_SHEET_PATH &aSheetPath, SCH_SYMBOL *aSymbol)
Add a tuner for a symbol.
void onSimStarted(wxCommandEvent &aEvent)
void LoadSettings(APP_SETTINGS_BASE *aCfg) override
Load common frame parameters from a configuration file.
std::shared_ptr< SPICE_CIRCUIT_MODEL > m_circuitModel
SIM_TAB * NewSimTab(const wxString &aSimCommand)
Create a new plot tab for a given simulation type.
bool EditAnalysis()
Shows a dialog for editing the current tab's simulation command, or creating a new tab with a differe...
int GetCurrentOptions() const
bool LoadWorkbook(const wxString &aPath)
Load plot, signal, cursor, measurement, etc.
WINDOW_SETTINGS * GetWindowSettings(APP_SETTINGS_BASE *aCfg) override
Return a pointer to the window settings for this frame.
void onUpdateSim(wxCommandEvent &aEvent)
void UpdateTitle()
Set the main window title bar text.
const std::map< int, wxString > & UserDefinedSignals()
void SetUserDefinedSignals(const std::map< int, wxString > &aSignals)
void ReloadSimulator(const wxString &aSimCommand, unsigned aSimOptions)
Re-send the current command and settings to the simulator.
SCH_EDIT_FRAME * m_schematicFrame
SIMULATOR_FRAME_UI * m_ui
Interface to receive simulation updates from SPICE_SIMULATOR class.
static std::shared_ptr< SPICE_SIMULATOR > CreateInstance(const std::string &aName)
mpWindow * GetPlotWin() const
Definition: sim_plot_tab.h:350
bool IsGridShown() const
Definition: sim_plot_tab.h:285
bool GetDottedSecondary() const
Toggle cursor for a particular trace.
Definition: sim_plot_tab.h:329
bool IsLegendShown() const
Definition: sim_plot_tab.h:299
int GetSimOptions() const
Definition: sim_tab.h:55
const wxString & GetSpicePlotName() const
Definition: sim_tab.h:61
void SetLastSchTextSimCommand(const wxString &aCmd)
Definition: sim_tab.h:59
void SetSimCommand(const wxString &aSimCommand)
Definition: sim_tab.h:53
const wxString & GetSimCommand() const
Definition: sim_tab.h:52
wxString GetLastSchTextSimCommand() const
Definition: sim_tab.h:58
void SetSpicePlotName(const wxString &aPlotName)
Definition: sim_tab.h:62
SIMULATOR_FRAME * m_parent
SIM_THREAD_REPORTER(SIMULATOR_FRAME *aParent)
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
bool HasMessage() const override
Returns true if the reporter client is non-empty.
void OnSimStateChange(SIMULATOR *aObject, SIM_STATE aNewState) override
static SIM_TYPE CommandToSimType(const wxString &aCmd)
Return simulation type basing on a simulation command directive.
wxString GetWorkbookFilename() const
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:167
TOOL_DISPATCHER * m_toolDispatcher
Definition: tools_holder.h:169
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
virtual void DispatchWxEvent(wxEvent &aEvent)
Process wxEvents (mostly UI events), translate them to TOOL_EVENTs, and make tools handle those.
Master controller class:
Definition: tool_manager.h:62
ACTION_MANAGER * GetActionManager() const
Definition: tool_manager.h:302
APP_SETTINGS_BASE * GetSettings() const
Definition: tool_manager.h:400
bool PostAction(const std::string &aActionName, T aParam)
Run the specified action after the current action (coroutine) ends.
Definition: tool_manager.h:235
void RegisterTool(TOOL_BASE *aTool)
Add a tool to the manager set and sets it up.
void SetEnvironment(EDA_ITEM *aModel, KIGFX::VIEW *aView, KIGFX::VIEW_CONTROLS *aViewControls, APP_SETTINGS_BASE *aSettings, TOOLS_HOLDER *aFrame)
Set the work environment (model, view, view controls and the parent window).
void InitTools()
Initializes all registered tools.
A modified version of the wxInfoBar class that allows us to:
Definition: wx_infobar.h:76
A wrapper for reporting to a wxString object.
Definition: reporter.h:171
bool HasMessage() const override
Returns true if the reporter client is non-empty.
Definition: reporter.cpp:97
bool HasMessageOfSeverity(int aSeverityMask) const override
Returns true if the reporter has one or more messages matching the specified severity mask.
Definition: reporter.cpp:103
const wxString & GetMessages() const
Definition: reporter.cpp:84
int RedoZoomStackSize() const
Definition: mathplot.h:1269
int UndoZoomStackSize() const
Definition: mathplot.h:1268
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:250
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:222
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Display a dialog with Save, Cancel and Discard Changes buttons.
Definition: confirm.cpp:130
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:195
This file is part of the common library.
#define CHECK(x)
#define ENABLE(x)
#define _(s)
@ FRAME_SCH
Definition: frame_type.h:34
@ FRAME_SIMULATOR
Definition: frame_type.h:38
see class PGM_BASE
SEVERITY
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_UNDEFINED
@ GLOBAL_CLEANUP
@ SPT_VOLTAGE
Definition: sim_types.h:52
@ SPT_CURRENT
Definition: sim_types.h:53
SIM_TYPE
< Possible simulation types
Definition: sim_types.h:32
@ ST_TRAN
Definition: sim_types.h:42
wxDEFINE_EVENT(EVT_SIM_UPDATE, wxCommandEvent)
#define MAX_MESSAGES
static WX_STRING_REPORTER s_reporter
@ SIM_IDLE
@ SIM_RUNNING
KIWAY Kiway(KFCTL_STANDALONE)
Stores the common settings that are saved and loaded for each window / frame.
Definition: app_settings.h:74
Definition of file extensions used in Kicad.