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 The 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, see <https://www.gnu.org/licenses/>.
21 */
22
23#include <wx/debug.h>
24
25// For some obscure reason, needed on msys2 with some wxWidgets versions (3.0) to avoid
26// undefined symbol at link stage (due to use of #include <pegtl.hpp>)
27// Should not create issues on other platforms
28#include <wx/menu.h>
29
31#include <sch_edit_frame.h>
32#include <widgets/wx_infobar.h>
33#include <kiway.h>
34#include <confirm.h>
35#include <bitmaps.h>
39#include <widgets/wx_grid.h>
40#include <tool/tool_manager.h>
42#include <tool/action_manager.h>
43#include <tool/action_toolbar.h>
44#include <tool/common_control.h>
46#include <tools/sch_actions.h>
47#include <string_utils.h>
48#include <pgm_base.h>
49#include "ngspice.h"
50#include <sim/simulator_frame.h>
52#include <sim/sim_plot_tab.h>
53#include <sim/spice_simulator.h>
55#include <eeschema_settings.h>
56#include <advanced_config.h>
59
60#include <memory>
61
62
63// Reporter is stored by pointer in KIBIS, so keep this here to avoid crashes
65
66
68{
69public:
71 m_parent( aParent )
72 {
73 }
74
75 REPORTER& Report( const wxString& aText, SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override
76 {
77 wxCommandEvent* event = new wxCommandEvent( EVT_SIM_REPORT );
78 event->SetString( aText );
79 wxQueueEvent( m_parent, event );
80 return *this;
81 }
82
83 bool HasMessage() const override
84 {
85 return false; // Technically "indeterminate" rather than false.
86 }
87
88 void OnSimStateChange( SIMULATOR* aObject, SIM_STATE aNewState ) override
89 {
90 wxCommandEvent* event = nullptr;
91
92 switch( aNewState )
93 {
94 case SIM_IDLE: event = new wxCommandEvent( EVT_SIM_FINISHED ); break;
95 case SIM_RUNNING: event = new wxCommandEvent( EVT_SIM_STARTED ); break;
96 default: wxFAIL; return;
97 }
98
99 wxQueueEvent( m_parent, event );
100 }
101
102private:
104};
105
106
107BEGIN_EVENT_TABLE( SIMULATOR_FRAME, KIWAY_PLAYER )
109 EVT_MENU( wxID_CLOSE, SIMULATOR_FRAME::onExit )
110END_EVENT_TABLE()
111
112
113SIMULATOR_FRAME::SIMULATOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
114 KIWAY_PLAYER( aKiway, aParent, FRAME_SIMULATOR, _( "Simulator" ), wxDefaultPosition,
115 wxDefaultSize, wxDEFAULT_FRAME_STYLE, wxT( "simulator" ), unityScale ),
116 m_schematicFrame( nullptr ),
117 m_toolBar( nullptr ),
118 m_ui( nullptr ),
119 m_simFinished( false ),
120 m_workbookModified( false )
121{
122 m_schematicFrame = (SCH_EDIT_FRAME*) Kiway().Player( FRAME_SCH, false );
123 wxASSERT( m_schematicFrame );
124
125 // Give an icon
126 wxIcon icon;
127 icon.CopyFromBitmap( KiBitmap( BITMAPS::simulator ) );
128 SetIcon( icon );
129
130 wxBoxSizer* mainSizer = new wxBoxSizer( wxVERTICAL );
131 SetSizer( mainSizer );
132
133 m_infoBar = new WX_INFOBAR( this );
134 mainSizer->Add( m_infoBar, 0, wxEXPAND, 0 );
135
136 m_tbTopMain = new ACTION_TOOLBAR( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
137 wxAUI_TB_DEFAULT_STYLE|wxAUI_TB_HORZ_LAYOUT|wxAUI_TB_PLAIN_BACKGROUND );
138 m_tbTopMain->Realize();
139 mainSizer->Add( m_tbTopMain, 0, wxEXPAND, 5 );
140
142 mainSizer->Add( m_ui, 1, wxEXPAND, 5 );
143
145
146 if( !m_simulator )
147 throw SIMULATOR_INIT_ERR( "Failed to create simulator instance" );
148
149 LoadSettings( config() );
150
151 std::shared_ptr<NGSPICE_SETTINGS> cfg = Prj().GetProjectFile().m_SchematicSettings->m_NgspiceSettings;
152
153 if( cfg->GetWorkbookFilename().IsEmpty() )
154 cfg->SetCompatibilityMode( NGSPICE_COMPATIBILITY_MODE::LT_PSPICE );
155
156 m_simulator->Init();
157
158 m_reporter = new SIM_THREAD_REPORTER( this );
159 m_simulator->SetReporter( m_reporter );
160
161 m_circuitModel = std::make_shared<SPICE_CIRCUIT_MODEL>( &m_schematicFrame->Schematic() );
162
163 setupTools();
165
166 // Set the tool manager for the toolbar here, since the tool manager didn't exist when the toolbar
167 // was created.
168 m_tbTopMain->SetToolManager( m_toolManager );
169
174
175 Bind( wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( SIMULATOR_FRAME::onExit ), this, wxID_EXIT );
176
177 Bind( EVT_SIM_UPDATE, &SIMULATOR_FRAME::onUpdateSim, this );
178 Bind( EVT_SIM_REPORT, &SIMULATOR_FRAME::onSimReport, this );
179 Bind( EVT_SIM_STARTED, &SIMULATOR_FRAME::onSimStarted, this );
180 Bind( EVT_SIM_FINISHED, &SIMULATOR_FRAME::onSimFinished, this );
181
182 // Ensure new items are taken in account by sizers:
183 Layout();
184
185 // resize the subwindows size. At least on Windows, calling wxSafeYield before
186 // resizing the subwindows forces the wxSplitWindows size events automatically generated
187 // by wxWidgets to be executed before our resize code.
188 // Otherwise, the changes made by setSubWindowsSashSize are overwritten by one these
189 // events
190 wxSafeYield();
191 m_ui->SetSubWindowsSashSize();
192
193 // Ensure the window is on top
194 Raise();
195
196 m_ui->InitWorkbook();
197 UpdateTitle();
198}
199
200
202{
203 NULL_REPORTER devnull;
204
205 m_simulator->Attach( nullptr, wxEmptyString, 0, wxEmptyString, devnull );
206 m_simulator->SetReporter( nullptr );
207 delete m_reporter;
208}
209
210
212{
213 // Create the manager
215 m_toolManager->SetEnvironment( nullptr, nullptr, nullptr, config(), this );
216
218
219 // Attach the events to the tool dispatcher
221 Bind( wxEVT_CHAR_HOOK, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher );
222
223 // Register tools
224 m_toolManager->RegisterTool( new COMMON_CONTROL );
225 m_toolManager->RegisterTool( new SIMULATOR_CONTROL );
226 m_toolManager->InitTools();
227}
228
229
231{
233
234 UpdateTitle();
235
236 m_ui->ShowChangedLanguage();
237}
238
239
241{
242 if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( aCfg ) )
243 {
245 m_ui->LoadSettings( cfg );
246 }
247
248 if( m_simulator )
250}
251
252
254{
255 if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( aCfg ) )
256 {
258 m_ui->SaveSettings( cfg );
259 }
260
262
263 if( m_schematicFrame && modified )
264 m_schematicFrame->OnModify();
265}
266
267
269{
271
273 m_ui->ApplyPreferences( cfg->m_Simulator.preferences );
274}
275
276
278{
280 return &cfg->m_Simulator.window;
281
282 wxFAIL_MSG( wxT( "SIMULATOR not running with EESCHEMA_SETTINGS" ) );
283 return &aCfg->m_Window; // non-null fail-safe
284}
285
286
288{
289 if( m_ui->GetCurrentSimTab() )
290 return m_ui->GetCurrentSimTab()->GetSimCommand();
291 else
292 return m_circuitModel->GetSchTextSimCommand();
293}
294
295
300
301
303{
304 if( SIM_TAB* simTab = m_ui->GetCurrentSimTab() )
305 return simTab->GetSimOptions();
306 else
308}
309
310
312{
313 bool unsaved = true;
314 bool readOnly = false;
315 wxString title;
316 std::shared_ptr<NGSPICE_SETTINGS> cfg = Prj().GetProjectFile().m_SchematicSettings->m_NgspiceSettings;
317 wxFileName filename = Prj().AbsolutePath( cfg->GetWorkbookFilename() );
318
319 if( filename.IsOk() && filename.FileExists() )
320 {
321 unsaved = false;
322 readOnly = !filename.IsFileWritable();
323 }
324
326 title = wxT( "*" ) + filename.GetName();
327 else
328 title = filename.GetName();
329
330 if( readOnly )
331 title += wxS( " " ) + _( "[Read Only]" );
332
333 if( unsaved )
334 title += wxS( " " ) + _( "[Unsaved]" );
335
336 title += wxT( " \u2014 " ) + _( "SPICE Simulator" );
337
338 SetTitle( title );
339}
340
341
342// Don't let the dialog grow too tall: you may not be able to get to the OK button
343#define MAX_MESSAGES 20
344
346{
347 if( !aReporter.HasMessage() )
348 return;
349
350 wxArrayString lines = wxSplit( aReporter.GetMessages(), '\n' );
351
352 if( lines.size() > MAX_MESSAGES )
353 {
354 lines.RemoveAt( MAX_MESSAGES, lines.size() - MAX_MESSAGES );
355 lines.Add( wxS( "..." ) );
356 }
357
359 {
360 DisplayErrorMessage( this, _( "Errors during netlist generation." ),
361 wxJoin( lines, '\n' ) );
362 }
363 else if( aReporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) )
364 {
365 DisplayInfoMessage( this, _( "Warnings during netlist generation." ),
366 wxJoin( lines, '\n' ) );
367 }
368}
369
370
371bool SIMULATOR_FRAME::LoadSimulator( const wxString& aSimCommand, unsigned aSimOptions )
372{
373 s_reporter.Clear();
374
375 if( !m_schematicFrame->ReadyToNetlist( _( "Simulator requires a fully annotated schematic." ) ) )
376 return false;
377
378 // If we are using the new connectivity, make sure that we do a full-rebuild
379 if( ADVANCED_CFG::GetCfg().m_IncrementalConnectivity )
380 m_schematicFrame->RecalculateConnections( nullptr, GLOBAL_CLEANUP );
381
382 bool success = m_simulator->Attach( m_circuitModel, aSimCommand, aSimOptions,
383 Prj().GetProjectPath(), s_reporter );
384
386
387 return success;
388}
389
390
391void SIMULATOR_FRAME::ReloadSimulator( const wxString& aSimCommand, unsigned aSimOptions )
392{
393 s_reporter.Clear();
394
395 m_simulator->Attach( m_circuitModel, aSimCommand, aSimOptions, Prj().GetProjectPath(),
396 s_reporter );
397
399}
400
401
403{
404 SIM_TAB* simTab = m_ui->GetCurrentSimTab();
405
406 if( !simTab )
407 return;
408
409 if( simTab->GetSimCommand().Upper().StartsWith( wxT( "FFT" ) )
410 || simTab->GetSimCommand().Upper().Contains( wxT( "\nFFT" ) ) )
411 {
412 wxString tranSpicePlot;
413
414 if( SIM_TAB* tranPlotTab = m_ui->GetSimTab( ST_TRAN ) )
415 tranSpicePlot = tranPlotTab->GetSpicePlotName();
416
417 if( tranSpicePlot.IsEmpty() )
418 {
419 DisplayErrorMessage( this, _( "You must run a TRAN simulation first; its results "
420 "will be used for the fast Fourier transform." ) );
421 }
422 else
423 {
424 m_simulator->Command( "setplot " + tranSpicePlot.ToStdString() );
425
426 wxArrayString commands = wxSplit( simTab->GetSimCommand(), '\n' );
427
428 for( const wxString& command : commands )
429 {
430 wxBusyCursor wait;
431 m_simulator->Command( command.ToStdString() );
432 }
433
434 simTab->SetSpicePlotName( m_simulator->CurrentPlotName() );
435 m_ui->OnSimRefresh( true );
436
437#if 0
438 m_simulator->Command( "setplot" ); // Print available plots to console
439 m_simulator->Command( "display" ); // Print vectors in current plot to console
440#endif
441 }
442
443 return;
444 }
445 else
446 {
447 if( m_ui->GetSimTabIndex( simTab ) == 0
448 && m_circuitModel->GetSchTextSimCommand() != simTab->GetLastSchTextSimCommand() )
449 {
450 if( simTab->GetLastSchTextSimCommand().IsEmpty()
451 || IsOK( this, _( "Schematic sheet simulation command directive has changed. "
452 "Do you wish to update the Simulation Command?" ) ) )
453 {
454 simTab->SetSimCommand( m_circuitModel->GetSchTextSimCommand() );
455 simTab->SetLastSchTextSimCommand( simTab->GetSimCommand() );
456 OnModify();
457 }
458 }
459 }
460
461 if( !LoadSimulator( simTab->GetSimCommand(), simTab->GetSimOptions() ) )
462 return;
463
464 std::unique_lock<std::mutex> simulatorLock( m_simulator->GetMutex(), std::try_to_lock );
465
466 if( simulatorLock.owns_lock() )
467 {
468 m_simFinished = false;
469
470 m_ui->OnSimUpdate();
471 m_simulator->Run();
472
473 // Netlist from schematic may have changed; update signals list, measurements list,
474 // etc.
475 m_ui->OnPlotSettingsChanged();
476 }
477 else
478 {
479 DisplayErrorMessage( this, _( "Another simulation is already running." ) );
480 }
481}
482
483
484SIM_TAB* SIMULATOR_FRAME::NewSimTab( const wxString& aSimCommand )
485{
486 return m_ui->NewSimTab( aSimCommand );
487}
488
489
490const std::vector<wxString> SIMULATOR_FRAME::SimPlotVectors()
491{
492 return m_ui->SimPlotVectors();
493}
494
495
496const std::vector<wxString> SIMULATOR_FRAME::Signals()
497{
498 return m_ui->Signals();
499}
500
501
502const std::map<int, wxString>& SIMULATOR_FRAME::UserDefinedSignals()
503{
504 return m_ui->UserDefinedSignals();
505}
506
507
508void SIMULATOR_FRAME::SetUserDefinedSignals( const std::map<int, wxString>& aSignals )
509{
510 m_ui->SetUserDefinedSignals( aSignals );
511}
512
513
514void SIMULATOR_FRAME::AddVoltageTrace( const wxString& aNetName )
515{
516 m_ui->AddTrace( aNetName, SPT_VOLTAGE );
517}
518
519
520void SIMULATOR_FRAME::AddCurrentTrace( const wxString& aDeviceName )
521{
522 m_ui->AddTrace( aDeviceName, SPT_CURRENT );
523}
524
525
526void SIMULATOR_FRAME::AddTuner( const SCH_SHEET_PATH& aSheetPath, SCH_SYMBOL* aSymbol )
527{
528 m_ui->AddTuner( aSheetPath, aSymbol );
529}
530
531
533{
534 return m_ui->GetCurrentSimTab();
535}
536
537
538bool SIMULATOR_FRAME::LoadWorkbook( const wxString& aPath )
539{
540 if( m_ui->LoadWorkbook( aPath ) )
541 {
542 UpdateTitle();
543
544 // Successfully loading a workbook does not count as modifying it. Clear the modified
545 // flag after all the EVT_WORKBOOK_MODIFIED events have been processed.
546 CallAfter( [this]()
547 {
548 m_workbookModified = false;
549 } );
550
551 return true;
552 }
553
554 DisplayErrorMessage( this, wxString::Format( _( "Unable to load or parse file %s" ), aPath ) );
555 return false;
556}
557
558
559bool SIMULATOR_FRAME::SaveWorkbook( const wxString& aPath )
560{
561 if( m_ui->SaveWorkbook( aPath ) )
562 {
563 m_workbookModified = false;
564 UpdateTitle();
565
566 return true;
567 }
568
569 return false;
570}
571
572
574{
575 m_ui->ToggleSimConsole();
576}
577
578
580{
581 m_ui->ToggleSimSidePanel();
582}
583
584
586{
587 m_ui->ToggleDarkModePlots();
588}
589
590
592{
593 SIM_TAB* simTab = m_ui->GetCurrentSimTab();
594 DIALOG_SIM_COMMAND dlg( this, m_circuitModel, m_simulator->Settings() );
595
596 s_reporter.Clear();
597
598 if( !simTab )
599 return false;
600
602 s_reporter );
603
605
606 dlg.SetSimCommand( simTab->GetSimCommand() );
607 dlg.SetSimOptions( simTab->GetSimOptions() );
608 dlg.SetPlotSettings( simTab );
609
610 if( dlg.ShowModal() == wxID_OK )
611 {
612 simTab->SetSimCommand( dlg.GetSimCommand() );
613 dlg.ApplySettings( simTab );
614 m_ui->OnPlotSettingsChanged();
615 OnModify();
616 return true;
617 }
618
619 return false;
620}
621
622
623bool SIMULATOR_FRAME::canCloseWindow( wxCloseEvent& aEvent )
624{
626 {
627 wxFileName filename = m_simulator->Settings()->GetWorkbookFilename();
628
629 if( filename.GetName().IsEmpty() )
630 {
631 if( Prj().GetProjectName().IsEmpty() )
632 filename.SetFullName( wxT( "noname.wbk" ) );
633 else
634 filename.SetFullName( Prj().GetProjectName() + wxT( ".wbk" ) );
635 }
636
637 return HandleUnsavedChanges( this, _( "Save changes to workbook?" ),
638 [&]() -> bool
639 {
640 return SaveWorkbook( Prj().AbsolutePath( filename.GetFullName() ) );
641 } );
642 }
643
644 return true;
645}
646
647
649{
650 if( m_simulator->IsRunning() )
651 m_simulator->Stop();
652
653 // Prevent memory leak on exit by deleting all simulation vectors
654 m_simulator->Clean();
655
656 // Cancel a running simProbe or simTune tool
657 m_schematicFrame->GetToolManager()->PostAction( ACTIONS::cancelInteractive );
658
659 SaveSettings( config() );
660
661 m_simulator->Settings().reset();
662
663 Destroy();
664}
665
666
668{
670
671 ACTION_MANAGER* mgr = m_toolManager->GetActionManager();
672 wxASSERT( mgr );
673
674 auto showGridCondition =
675 [this]( const SELECTION& aSel )
676 {
677 SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( GetCurrentSimTab() );
678 return plotTab && plotTab->IsGridShown();
679 };
680
681 auto showLegendCondition =
682 [this]( const SELECTION& aSel )
683 {
684 SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( GetCurrentSimTab() );
685 return plotTab && plotTab->IsLegendShown();
686 };
687
688 auto showDottedCondition =
689 [this]( const SELECTION& aSel )
690 {
691 SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( GetCurrentSimTab() );
692 return plotTab && plotTab->GetDottedSecondary();
693 };
694
695 auto darkModePlotCondition =
696 [this]( const SELECTION& aSel )
697 {
698 return m_ui->DarkModePlots();
699 };
700
701 auto simRunning =
702 [this]( const SELECTION& aSel )
703 {
704 return m_simulator && m_simulator->IsRunning();
705 };
706
707 auto simFinished =
708 [this]( const SELECTION& aSel )
709 {
710 return m_simFinished;
711 };
712
713 auto haveSim =
714 [this]( const SELECTION& aSel )
715 {
716 return GetCurrentSimTab() != nullptr;
717 };
718
719 auto havePlot =
720 [this]( const SELECTION& aSel )
721 {
722 return dynamic_cast<SIM_PLOT_TAB*>( GetCurrentSimTab() ) != nullptr;
723 };
724
725 auto haveZoomUndo =
726 [this]( const SELECTION& aSel )
727 {
728 SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( GetCurrentSimTab() );
729 return plotTab && plotTab->GetPlotWin()->UndoZoomStackSize() > 0;
730 };
731
732 auto haveZoomRedo =
733 [this]( const SELECTION& aSel )
734 {
735 SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( GetCurrentSimTab() );
736 return plotTab && plotTab->GetPlotWin()->RedoZoomStackSize() > 0;
737 };
738
739 // clang-format off
740 auto isSimConsoleShown =
741 [this]( const SELECTION& aSel )
742 {
743 bool aBool = false;
744
745 if( m_simulator )
746 return m_ui->IsSimConsoleShown();
747
748 return aBool;
749 };
750
751 auto isSimSidePanelShown =
752 [this]( const SELECTION& aSel )
753 {
754 bool aBool = false;
755
756 if( m_simulator )
757 return m_ui->IsSimSidePanelShown();
758
759 return aBool;
760 };
761 // clang-format on
762
763#define ENABLE( x ) ACTION_CONDITIONS().Enable( x )
764#define CHECK( x ) ACTION_CONDITIONS().Check( x )
765 // clang-format off
769
774
775 mgr->SetConditions( SCH_ACTIONS::toggleSimSidePanel, CHECK( isSimSidePanelShown ) );
776 mgr->SetConditions( SCH_ACTIONS::toggleSimConsole, CHECK( isSimConsoleShown ) );
777
778 mgr->SetConditions( ACTIONS::zoomUndo, ENABLE( haveZoomUndo ) );
779 mgr->SetConditions( ACTIONS::zoomRedo, ENABLE( haveZoomRedo ) );
780 mgr->SetConditions( SCH_ACTIONS::toggleGrid, CHECK( showGridCondition ) );
781 mgr->SetConditions( SCH_ACTIONS::toggleLegend, CHECK( showLegendCondition ) );
782 mgr->SetConditions( SCH_ACTIONS::toggleDottedSecondary, CHECK( showDottedCondition ) );
783 mgr->SetConditions( SCH_ACTIONS::toggleDarkModePlots, CHECK( darkModePlotCondition ) );
784
787 mgr->SetConditions( SCH_ACTIONS::runSimulation, ENABLE( !simRunning ) );
788 mgr->SetConditions( SCH_ACTIONS::stopSimulation, ENABLE( simRunning ) );
789 mgr->SetConditions( SCH_ACTIONS::simProbe, ENABLE( simFinished ) );
790 mgr->SetConditions( SCH_ACTIONS::simTune, ENABLE( simFinished ) );
792 // clang-format on
793#undef CHECK
794#undef ENABLE
795}
796
797
798void SIMULATOR_FRAME::onSimStarted( wxCommandEvent& aEvent )
799{
800 SetCursor( wxCURSOR_ARROWWAIT );
801}
802
803
804void SIMULATOR_FRAME::onSimFinished( wxCommandEvent& aEvent )
805{
806 // Sometimes (for instance with a directive like wrdata my_file.csv "my_signal")
807 // the simulator is in idle state (simulation is finished), but still running, during
808 // the time the file is written. So gives a slice of time to fully finish the work:
809 if( m_simulator->IsRunning() )
810 {
811 int max_time = 40; // For a max timeout = 2s
812
813 do
814 {
815 wxMilliSleep( 50 );
816 wxYield();
817
818 if( max_time )
819 max_time--;
820
821 } while( max_time && m_simulator->IsRunning() );
822 }
823
824 // ensure the shown cursor is the default cursor, not the wxCURSOR_ARROWWAIT set when
825 // staring the simulator in onSimStarted:
826 SetCursor( wxNullCursor );
827
828 // Is a warning message useful if the simulatior is still running?
829 SCHEMATIC& schematic = m_schematicFrame->Schematic();
830 schematic.ClearOperatingPoints();
831
832 m_simFinished = true;
833
834 m_ui->OnSimRefresh( true );
835
836 m_schematicFrame->RefreshOperatingPointDisplay();
837 m_schematicFrame->GetCanvas()->Refresh();
838}
839
840
841void SIMULATOR_FRAME::onUpdateSim( wxCommandEvent& aEvent )
842{
843 static bool updateInProgress = false;
844
845 // skip update when events are triggered too often and previous call didn't end yet
846 if( updateInProgress )
847 return;
848
849 updateInProgress = true;
850
851 if( m_simulator->IsRunning() )
852 m_simulator->Stop();
853
854 std::unique_lock<std::mutex> simulatorLock( m_simulator->GetMutex(), std::try_to_lock );
855
856 if( simulatorLock.owns_lock() )
857 {
858 m_ui->OnSimUpdate();
859 m_simulator->Run();
860 }
861 else
862 {
863 DisplayErrorMessage( this, _( "Another simulation is already running." ) );
864 }
865
866 updateInProgress = false;
867}
868
869
870void SIMULATOR_FRAME::onSimReport( wxCommandEvent& aEvent )
871{
872 m_ui->OnSimReport( aEvent.GetString() );
873}
874
875
876void SIMULATOR_FRAME::onExit( wxCommandEvent& aEvent )
877{
878 if( aEvent.GetId() == wxID_EXIT )
879 Kiway().OnKiCadExit();
880
881 if( aEvent.GetId() == wxID_CLOSE )
882 Close( false );
883}
884
885
892
893
894wxDEFINE_EVENT( EVT_SIM_UPDATE, wxCommandEvent );
895wxDEFINE_EVENT( EVT_SIM_REPORT, wxCommandEvent );
896
897wxDEFINE_EVENT( EVT_SIM_STARTED, wxCommandEvent );
898wxDEFINE_EVENT( EVT_SIM_FINISHED, wxCommandEvent );
constexpr EDA_IU_SCALE unityScale
Definition base_units.h:124
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:100
static TOOL_ACTION toggleGrid
Definition actions.h:194
static TOOL_ACTION cancelInteractive
Definition actions.h:68
static TOOL_ACTION zoomRedo
Definition actions.h:144
static TOOL_ACTION zoomUndo
Definition actions.h:143
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.
WINDOW_SETTINGS m_Window
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
Return the settings object used in SaveSettings(), and is overloaded in KICAD_MANAGER_FRAME.
void CommonSettingsChanged(int aFlags) override
Notification event that some of the common (suite-wide) settings have changed.
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...
WX_INFOBAR * m_infoBar
TOOLBAR_SETTINGS * m_toolbarSettings
virtual void configureToolbars()
virtual void RecreateToolbars()
virtual void LoadSettings(APP_SETTINGS_BASE *aCfg)
Load common frame parameters from a configuration file.
virtual void SaveSettings(APP_SETTINGS_BASE *aCfg)
Save common frame parameters to a configuration data file.
ACTION_TOOLBAR * m_tbTopMain
void ReCreateMenuBar()
Recreate the menu bar.
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.
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
KIWAY_PLAYER(KIWAY *aKiway, wxWindow *aParent, FRAME_T aFrameType, const wxString &aTitle, const wxPoint &aPos, const wxSize &aSize, long aStyle, const wxString &aFrameName, const EDA_IU_SCALE &aIuScale)
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:311
void OnKiCadExit()
Definition kiway.cpp:796
bool SaveToFile(const wxString &aDirectory="", bool aForce=false) override
Calls Store() and then saves the JSON document contents into the parent JSON_SETTINGS.
A singleton reporter that reports to nowhere.
Definition reporter.h:214
SCHEMATIC_SETTINGS * m_SchematicSettings
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:407
virtual bool HasMessageOfSeverity(int aSeverityMask) const
Returns true if the reporter has one or more messages matching the specified severity mask.
Definition reporter.h:141
REPORTER()
Definition reporter.h:73
virtual bool HasMessage() const
Returns true if any messages were reported.
Definition reporter.h:132
std::shared_ptr< NGSPICE_SETTINGS > m_NgspiceSettings
Ngspice simulator settings.
Holds all the data relating to one schematic.
Definition schematic.h:90
static TOOL_ACTION toggleSimConsole
static TOOL_ACTION exportPlotToClipboard
static TOOL_ACTION saveWorkbookAs
static TOOL_ACTION toggleSimSidePanel
static TOOL_ACTION exportPlotAsCSV
static TOOL_ACTION simAnalysisProperties
static TOOL_ACTION toggleDottedSecondary
static TOOL_ACTION simTune
static TOOL_ACTION toggleDarkModePlots
static TOOL_ACTION exportPlotAsPNG
static TOOL_ACTION exportPlotToSchematic
static TOOL_ACTION runSimulation
static TOOL_ACTION newAnalysisTab
static TOOL_ACTION simProbe
static TOOL_ACTION showNetlist
static TOOL_ACTION openWorkbook
static TOOL_ACTION saveWorkbook
static TOOL_ACTION toggleLegend
static TOOL_ACTION stopSimulation
Schematic editor (Eeschema) main window.
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:69
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.
The SIMULATOR_FRAME holds the main user-interface for running simulations.
SIMULATOR_FRAME(KIWAY *aKiway, wxWindow *aParent)
SIM_TAB * GetCurrentSimTab() const
Return the current tab (or NULL if there is none).
void ShowChangedLanguage() override
Redraw the menus and what not in current language.
bool canCloseWindow(wxCloseEvent &aEvent) override
void onSimFinished(wxCommandEvent &aEvent)
bool LoadSimulator(const wxString &aSimCommand, unsigned aSimOptions)
Check and load the current netlist into the simulator.
void onSimReport(wxCommandEvent &aEvent)
wxString GetCurrentSimCommand() const
void CommonSettingsChanged(int aFlags) override
Notification event that some of the common (suite-wide) settings have changed.
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.
ACTION_TOOLBAR * m_toolBar
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
Simple error container for failure to init the simulation engine and ultimately abort the frame const...
Interface to receive simulation updates from SPICE_SIMULATOR class.
static std::shared_ptr< SPICE_SIMULATOR > CreateInstance(const std::string &aName)
mpWindow * GetPlotWin() const
bool IsGridShown() const
bool GetDottedSecondary() const
Turn on/off the cursor for a particular trace.
bool IsLegendShown() const
int GetSimOptions() const
Definition sim_tab.h:51
void SetLastSchTextSimCommand(const wxString &aCmd)
Definition sim_tab.h:55
void SetSimCommand(const wxString &aSimCommand)
Definition sim_tab.h:49
const wxString & GetSimCommand() const
Definition sim_tab.h:48
wxString GetLastSchTextSimCommand() const
Definition sim_tab.h:54
void SetSpicePlotName(const wxString &aPlotName)
Definition sim_tab.h:58
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 any messages were reported.
void OnSimStateChange(SIMULATOR *aObject, SIM_STATE aNewState) override
static SIM_TYPE CommandToSimType(const wxString &aCmd)
Return simulation type basing on a simulation command directive.
TOOL_MANAGER * m_toolManager
TOOL_DISPATCHER * m_toolDispatcher
virtual void DispatchWxEvent(wxEvent &aEvent)
Process wxEvents (mostly UI events), translate them to TOOL_EVENTs, and make tools handle those.
Master controller class:
A modified version of the wxInfoBar class that allows us to:
Definition wx_infobar.h:77
A wrapper for reporting to a wxString object.
Definition reporter.h:189
const wxString & GetMessages() const
Definition reporter.cpp:101
int RedoZoomStackSize() const
Definition mathplot.h:1271
int UndoZoomStackSize() const
Definition mathplot.h:1270
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:274
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:245
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:146
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:217
This file is part of the common library.
#define CHECK(x)
#define ENABLE(x)
#define _(s)
@ FRAME_SCH
Definition frame_type.h:30
@ FRAME_SIMULATOR
Definition frame_type.h:34
PROJECT & Prj()
Definition kicad.cpp:730
EVT_MENU(ID_COMPARE_PROJECT_BRANCHES, KICAD_MANAGER_FRAME::OnCompareProjectBranches) KICAD_MANAGER_FRAME
see class PGM_BASE
SEVERITY
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_UNDEFINED
@ GLOBAL_CLEANUP
Definition schematic.h:79
T * GetToolbarSettings(const wxString &aFilename)
T * GetAppSettings(const char *aFilename)
@ SPT_VOLTAGE
Definition sim_types.h:48
@ SPT_CURRENT
Definition sim_types.h:49
SIM_TYPE
< Possible simulation types
Definition sim_types.h:28
@ ST_TRAN
Definition sim_types.h:38
wxDEFINE_EVENT(EVT_SIM_UPDATE, wxCommandEvent)
#define MAX_MESSAGES
static WX_STRING_REPORTER s_reporter
@ SIM_IDLE
@ SIM_RUNNING
KIWAY Kiway(KFCTL_STANDALONE)
Store the common settings that are saved and loaded for each window / frame.
Definition of file extensions used in Kicad.