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, 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/sch_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>
62
63#include <memory>
64
65
66// Reporter is stored by pointer in KIBIS, so keep this here to avoid crashes
68
69
71{
72public:
74 m_parent( aParent )
75 {
76 }
77
78 REPORTER& Report( const wxString& aText, SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override
79 {
80 wxCommandEvent* event = new wxCommandEvent( EVT_SIM_REPORT );
81 event->SetString( aText );
82 wxQueueEvent( m_parent, event );
83 return *this;
84 }
85
86 bool HasMessage() const override
87 {
88 return false; // Technically "indeterminate" rather than false.
89 }
90
91 void OnSimStateChange( SIMULATOR* aObject, SIM_STATE aNewState ) override
92 {
93 wxCommandEvent* event = nullptr;
94
95 switch( aNewState )
96 {
97 case SIM_IDLE: event = new wxCommandEvent( EVT_SIM_FINISHED ); break;
98 case SIM_RUNNING: event = new wxCommandEvent( EVT_SIM_STARTED ); break;
99 default: wxFAIL; return;
100 }
101
102 wxQueueEvent( m_parent, event );
103 }
104
105private:
107};
108
109
110BEGIN_EVENT_TABLE( SIMULATOR_FRAME, KIWAY_PLAYER )
111 EVT_MENU( wxID_EXIT, SIMULATOR_FRAME::onExit )
112 EVT_MENU( wxID_CLOSE, SIMULATOR_FRAME::onExit )
113END_EVENT_TABLE()
114
115
116SIMULATOR_FRAME::SIMULATOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
117 KIWAY_PLAYER( aKiway, aParent, FRAME_SIMULATOR, _( "Simulator" ), wxDefaultPosition,
118 wxDefaultSize, wxDEFAULT_FRAME_STYLE, wxT( "simulator" ), unityScale ),
119 m_schematicFrame( nullptr ),
120 m_toolBar( nullptr ),
121 m_ui( nullptr ),
122 m_simFinished( false ),
123 m_workbookModified( false )
124{
125 m_schematicFrame = (SCH_EDIT_FRAME*) Kiway().Player( FRAME_SCH, false );
126 wxASSERT( m_schematicFrame );
127
128 // Give an icon
129 wxIcon icon;
130 icon.CopyFromBitmap( KiBitmap( BITMAPS::simulator ) );
131 SetIcon( icon );
132
133 wxBoxSizer* mainSizer = new wxBoxSizer( wxVERTICAL );
134 SetSizer( mainSizer );
135
136 m_infoBar = new WX_INFOBAR( this );
137 mainSizer->Add( m_infoBar, 0, wxEXPAND, 0 );
138
139 m_tbTopMain = new ACTION_TOOLBAR( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
140 wxAUI_TB_DEFAULT_STYLE|wxAUI_TB_HORZ_LAYOUT|wxAUI_TB_PLAIN_BACKGROUND );
141 m_tbTopMain->Realize();
142 mainSizer->Add( m_tbTopMain, 0, wxEXPAND, 5 );
143
144 m_ui = new SIMULATOR_FRAME_UI( this, m_schematicFrame );
145 mainSizer->Add( m_ui, 1, wxEXPAND, 5 );
146
147 m_simulator = SIMULATOR::CreateInstance( "ngspice" );
148
149 if( !m_simulator )
150 throw SIMULATOR_INIT_ERR( "Failed to create simulator instance" );
151
152 LoadSettings( config() );
153
154 std::shared_ptr<NGSPICE_SETTINGS> cfg = Prj().GetProjectFile().m_SchematicSettings->m_NgspiceSettings;
155
156 if( cfg->GetWorkbookFilename().IsEmpty() )
157 cfg->SetCompatibilityMode( NGSPICE_COMPATIBILITY_MODE::LT_PSPICE );
158
159 m_simulator->Init();
160
161 m_reporter = new SIM_THREAD_REPORTER( this );
162 m_simulator->SetReporter( m_reporter );
163
164 m_circuitModel = std::make_shared<SPICE_CIRCUIT_MODEL>( &m_schematicFrame->Schematic() );
165
166 setupTools();
167 setupUIConditions();
168
169 // Set the tool manager for the toolbar here, since the tool manager didn't exist when the toolbar
170 // was created.
171 m_tbTopMain->SetToolManager( m_toolManager );
172
173 m_toolbarSettings = GetToolbarSettings<SIMULATOR_TOOLBAR_SETTINGS>( "sim-toolbars" );
174 configureToolbars();
175 RecreateToolbars();
176 ReCreateMenuBar();
177
178 Bind( wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( SIMULATOR_FRAME::onExit ), this, wxID_EXIT );
179
180 Bind( EVT_SIM_UPDATE, &SIMULATOR_FRAME::onUpdateSim, this );
181 Bind( EVT_SIM_REPORT, &SIMULATOR_FRAME::onSimReport, this );
182 Bind( EVT_SIM_STARTED, &SIMULATOR_FRAME::onSimStarted, this );
183 Bind( EVT_SIM_FINISHED, &SIMULATOR_FRAME::onSimFinished, this );
184
185 // Ensure new items are taken in account by sizers:
186 Layout();
187
188 // resize the subwindows size. At least on Windows, calling wxSafeYield before
189 // resizing the subwindows forces the wxSplitWindows size events automatically generated
190 // by wxWidgets to be executed before our resize code.
191 // Otherwise, the changes made by setSubWindowsSashSize are overwritten by one these
192 // events
193 wxSafeYield();
194 m_ui->SetSubWindowsSashSize();
195
196 // Ensure the window is on top
197 Raise();
198
199 m_ui->InitWorkbook();
200 UpdateTitle();
201}
202
203
205{
206 NULL_REPORTER devnull;
207
208 m_simulator->Attach( nullptr, wxEmptyString, 0, wxEmptyString, devnull );
209 m_simulator->SetReporter( nullptr );
210 delete m_reporter;
211}
212
213
215{
216 // Create the manager
218 m_toolManager->SetEnvironment( nullptr, nullptr, nullptr, config(), this );
219
221
222 // Attach the events to the tool dispatcher
224 Bind( wxEVT_CHAR_HOOK, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher );
225
226 // Register tools
230}
231
232
234{
236
237 UpdateTitle();
238
240}
241
242
244{
245 if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( aCfg ) )
246 {
248 m_ui->LoadSettings( cfg );
249 }
250
251 if( m_simulator )
253}
254
255
257{
258 if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( aCfg ) )
259 {
261 m_ui->SaveSettings( cfg );
262 }
263
264 bool modified = Prj().GetProjectFile().m_SchematicSettings->m_NgspiceSettings->SaveToFile();
265
266 if( m_schematicFrame && modified )
268}
269
270
272{
274
275 if( EESCHEMA_SETTINGS* cfg = GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" ) )
276 m_ui->ApplyPreferences( cfg->m_Simulator.preferences );
277}
278
279
281{
282 if( EESCHEMA_SETTINGS* cfg = GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" ) )
283 return &cfg->m_Simulator.window;
284
285 wxFAIL_MSG( wxT( "SIMULATOR not running with EESCHEMA_SETTINGS" ) );
286 return &aCfg->m_Window; // non-null fail-safe
287}
288
289
291{
292 if( m_ui->GetCurrentSimTab() )
294 else
295 return m_circuitModel->GetSchTextSimCommand();
296}
297
298
300{
302}
303
304
306{
307 if( SIM_TAB* simTab = m_ui->GetCurrentSimTab() )
308 return simTab->GetSimOptions();
309 else
311}
312
313
315{
316 bool unsaved = true;
317 bool readOnly = false;
318 wxString title;
319 std::shared_ptr<NGSPICE_SETTINGS> cfg = Prj().GetProjectFile().m_SchematicSettings->m_NgspiceSettings;
320 wxFileName filename = Prj().AbsolutePath( cfg->GetWorkbookFilename() );
321
322 if( filename.IsOk() && filename.FileExists() )
323 {
324 unsaved = false;
325 readOnly = !filename.IsFileWritable();
326 }
327
329 title = wxT( "*" ) + filename.GetName();
330 else
331 title = filename.GetName();
332
333 if( readOnly )
334 title += wxS( " " ) + _( "[Read Only]" );
335
336 if( unsaved )
337 title += wxS( " " ) + _( "[Unsaved]" );
338
339 title += wxT( " \u2014 " ) + _( "SPICE Simulator" );
340
341 SetTitle( title );
342}
343
344
345// Don't let the dialog grow too tall: you may not be able to get to the OK button
346#define MAX_MESSAGES 20
347
349{
350 if( !aReporter.HasMessage() )
351 return;
352
353 wxArrayString lines = wxSplit( aReporter.GetMessages(), '\n' );
354
355 if( lines.size() > MAX_MESSAGES )
356 {
357 lines.RemoveAt( MAX_MESSAGES, lines.size() - MAX_MESSAGES );
358 lines.Add( wxS( "..." ) );
359 }
360
362 {
363 DisplayErrorMessage( this, _( "Errors during netlist generation." ),
364 wxJoin( lines, '\n' ) );
365 }
366 else if( aReporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) )
367 {
368 DisplayInfoMessage( this, _( "Warnings during netlist generation." ),
369 wxJoin( lines, '\n' ) );
370 }
371}
372
373
374bool SIMULATOR_FRAME::LoadSimulator( const wxString& aSimCommand, unsigned aSimOptions )
375{
377
378 if( !m_schematicFrame->ReadyToNetlist( _( "Simulator requires a fully annotated schematic." ) ) )
379 return false;
380
381 // If we are using the new connectivity, make sure that we do a full-rebuild
382 if( ADVANCED_CFG::GetCfg().m_IncrementalConnectivity )
384
385 bool success = m_simulator->Attach( m_circuitModel, aSimCommand, aSimOptions,
386 Prj().GetProjectPath(), s_reporter );
387
389
390 return success;
391}
392
393
394void SIMULATOR_FRAME::ReloadSimulator( const wxString& aSimCommand, unsigned aSimOptions )
395{
397
398 m_simulator->Attach( m_circuitModel, aSimCommand, aSimOptions, Prj().GetProjectPath(),
399 s_reporter );
400
402}
403
404
406{
407 SIM_TAB* simTab = m_ui->GetCurrentSimTab();
408
409 if( !simTab )
410 return;
411
412 if( simTab->GetSimCommand().Upper().StartsWith( wxT( "FFT" ) )
413 || simTab->GetSimCommand().Upper().Contains( wxT( "\nFFT" ) ) )
414 {
415 wxString tranSpicePlot;
416
417 if( SIM_TAB* tranPlotTab = m_ui->GetSimTab( ST_TRAN ) )
418 tranSpicePlot = tranPlotTab->GetSpicePlotName();
419
420 if( tranSpicePlot.IsEmpty() )
421 {
422 DisplayErrorMessage( this, _( "You must run a TRAN simulation first; its results"
423 "will be used for the fast Fourier transform." ) );
424 }
425 else
426 {
427 m_simulator->Command( "setplot " + tranSpicePlot.ToStdString() );
428
429 wxArrayString commands = wxSplit( simTab->GetSimCommand(), '\n' );
430
431 for( const wxString& command : commands )
432 {
433 wxBusyCursor wait;
434 m_simulator->Command( command.ToStdString() );
435 }
436
437 simTab->SetSpicePlotName( m_simulator->CurrentPlotName() );
438 m_ui->OnSimRefresh( true );
439
440#if 0
441 m_simulator->Command( "setplot" ); // Print available plots to console
442 m_simulator->Command( "display" ); // Print vectors in current plot to console
443#endif
444 }
445
446 return;
447 }
448 else
449 {
450 if( m_ui->GetSimTabIndex( simTab ) == 0
451 && m_circuitModel->GetSchTextSimCommand() != simTab->GetLastSchTextSimCommand() )
452 {
453 if( simTab->GetLastSchTextSimCommand().IsEmpty()
454 || IsOK( this, _( "Schematic sheet simulation command directive has changed. "
455 "Do you wish to update the Simulation Command?" ) ) )
456 {
457 simTab->SetSimCommand( m_circuitModel->GetSchTextSimCommand() );
458 simTab->SetLastSchTextSimCommand( simTab->GetSimCommand() );
459 OnModify();
460 }
461 }
462 }
463
464 if( !LoadSimulator( simTab->GetSimCommand(), simTab->GetSimOptions() ) )
465 return;
466
467 std::unique_lock<std::mutex> simulatorLock( m_simulator->GetMutex(), std::try_to_lock );
468
469 if( simulatorLock.owns_lock() )
470 {
471 m_simFinished = false;
472
473 m_ui->OnSimUpdate();
474 m_simulator->Run();
475
476 // Netlist from schematic may have changed; update signals list, measurements list,
477 // etc.
479 }
480 else
481 {
482 DisplayErrorMessage( this, _( "Another simulation is already running." ) );
483 }
484}
485
486
487SIM_TAB* SIMULATOR_FRAME::NewSimTab( const wxString& aSimCommand )
488{
489 return m_ui->NewSimTab( aSimCommand );
490}
491
492
493const std::vector<wxString> SIMULATOR_FRAME::SimPlotVectors()
494{
495 return m_ui->SimPlotVectors();
496}
497
498
499const std::vector<wxString> SIMULATOR_FRAME::Signals()
500{
501 return m_ui->Signals();
502}
503
504
505const std::map<int, wxString>& SIMULATOR_FRAME::UserDefinedSignals()
506{
507 return m_ui->UserDefinedSignals();
508}
509
510
511void SIMULATOR_FRAME::SetUserDefinedSignals( const std::map<int, wxString>& aSignals )
512{
513 m_ui->SetUserDefinedSignals( aSignals );
514}
515
516
517void SIMULATOR_FRAME::AddVoltageTrace( const wxString& aNetName )
518{
519 m_ui->AddTrace( aNetName, SPT_VOLTAGE );
520}
521
522
523void SIMULATOR_FRAME::AddCurrentTrace( const wxString& aDeviceName )
524{
525 m_ui->AddTrace( aDeviceName, SPT_CURRENT );
526}
527
528
529void SIMULATOR_FRAME::AddTuner( const SCH_SHEET_PATH& aSheetPath, SCH_SYMBOL* aSymbol )
530{
531 m_ui->AddTuner( aSheetPath, aSymbol );
532}
533
534
536{
537 return m_ui->GetCurrentSimTab();
538}
539
540
541bool SIMULATOR_FRAME::LoadWorkbook( const wxString& aPath )
542{
543 if( m_ui->LoadWorkbook( aPath ) )
544 {
545 UpdateTitle();
546
547 // Successfully loading a workbook does not count as modifying it. Clear the modified
548 // flag after all the EVT_WORKBOOK_MODIFIED events have been processed.
549 CallAfter( [this]()
550 {
551 m_workbookModified = false;
552 } );
553
554 return true;
555 }
556
557 DisplayErrorMessage( this, wxString::Format( _( "Unable to load or parse file %s" ), aPath ) );
558 return false;
559}
560
561
562bool SIMULATOR_FRAME::SaveWorkbook( const wxString& aPath )
563{
564 if( m_ui->SaveWorkbook( aPath ) )
565 {
566 m_workbookModified = false;
567 UpdateTitle();
568
569 return true;
570 }
571
572 return false;
573}
574
575
577{
579}
580
581
583{
585}
586
587
589{
591}
592
593
595{
596 SIM_TAB* simTab = m_ui->GetCurrentSimTab();
597 DIALOG_SIM_COMMAND dlg( this, m_circuitModel, m_simulator->Settings() );
598
600
601 if( !simTab )
602 return false;
603
605 s_reporter );
606
608
609 dlg.SetSimCommand( simTab->GetSimCommand() );
610 dlg.SetSimOptions( simTab->GetSimOptions() );
611 dlg.SetPlotSettings( simTab );
612
613 if( dlg.ShowModal() == wxID_OK )
614 {
615 simTab->SetSimCommand( dlg.GetSimCommand() );
616 dlg.ApplySettings( simTab );
618 OnModify();
619 return true;
620 }
621
622 return false;
623}
624
625
626bool SIMULATOR_FRAME::canCloseWindow( wxCloseEvent& aEvent )
627{
629 {
630 wxFileName filename = m_simulator->Settings()->GetWorkbookFilename();
631
632 if( filename.GetName().IsEmpty() )
633 {
634 if( Prj().GetProjectName().IsEmpty() )
635 filename.SetFullName( wxT( "noname.wbk" ) );
636 else
637 filename.SetFullName( Prj().GetProjectName() + wxT( ".wbk" ) );
638 }
639
640 return HandleUnsavedChanges( this, _( "Save changes to workbook?" ),
641 [&]() -> bool
642 {
643 return SaveWorkbook( Prj().AbsolutePath( filename.GetFullName() ) );
644 } );
645 }
646
647 return true;
648}
649
650
652{
653 if( m_simulator->IsRunning() )
654 m_simulator->Stop();
655
656 // Prevent memory leak on exit by deleting all simulation vectors
657 m_simulator->Clean();
658
659 // Cancel a running simProbe or simTune tool
661
662 SaveSettings( config() );
663
664 m_simulator->Settings().reset();
665
666 Destroy();
667}
668
669
671{
673
675 wxASSERT( mgr );
676
677 auto showGridCondition =
678 [this]( const SELECTION& aSel )
679 {
680 SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( GetCurrentSimTab() );
681 return plotTab && plotTab->IsGridShown();
682 };
683
684 auto showLegendCondition =
685 [this]( const SELECTION& aSel )
686 {
687 SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( GetCurrentSimTab() );
688 return plotTab && plotTab->IsLegendShown();
689 };
690
691 auto showDottedCondition =
692 [this]( const SELECTION& aSel )
693 {
694 SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( GetCurrentSimTab() );
695 return plotTab && plotTab->GetDottedSecondary();
696 };
697
698 auto darkModePlotCondition =
699 [this]( const SELECTION& aSel )
700 {
701 return m_ui->DarkModePlots();
702 };
703
704 auto simRunning =
705 [this]( const SELECTION& aSel )
706 {
707 return m_simulator && m_simulator->IsRunning();
708 };
709
710 auto simFinished =
711 [this]( const SELECTION& aSel )
712 {
713 return m_simFinished;
714 };
715
716 auto haveSim =
717 [this]( const SELECTION& aSel )
718 {
719 return GetCurrentSimTab() != nullptr;
720 };
721
722 auto havePlot =
723 [this]( const SELECTION& aSel )
724 {
725 return dynamic_cast<SIM_PLOT_TAB*>( GetCurrentSimTab() ) != nullptr;
726 };
727
728 auto haveZoomUndo =
729 [this]( const SELECTION& aSel )
730 {
731 SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( GetCurrentSimTab() );
732 return plotTab && plotTab->GetPlotWin()->UndoZoomStackSize() > 0;
733 };
734
735 auto haveZoomRedo =
736 [this]( const SELECTION& aSel )
737 {
738 SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( GetCurrentSimTab() );
739 return plotTab && plotTab->GetPlotWin()->RedoZoomStackSize() > 0;
740 };
741
742 // clang-format off
743 auto isSimConsoleShown =
744 [this]( const SELECTION& aSel )
745 {
746 bool aBool = false;
747
748 if( m_simulator )
749 return m_ui->IsSimConsoleShown();
750
751 return aBool;
752 };
753
754 auto isSimSidePanelShown =
755 [this]( const SELECTION& aSel )
756 {
757 bool aBool = false;
758
759 if( m_simulator )
760 return m_ui->IsSimSidePanelShown();
761
762 return aBool;
763 };
764 // clang-format on
765
766#define ENABLE( x ) ACTION_CONDITIONS().Enable( x )
767#define CHECK( x ) ACTION_CONDITIONS().Check( x )
768 // clang-format off
772
777
778 mgr->SetConditions( SCH_ACTIONS::toggleSimSidePanel, CHECK( isSimSidePanelShown ) );
779 mgr->SetConditions( SCH_ACTIONS::toggleSimConsole, CHECK( isSimConsoleShown ) );
780
781 mgr->SetConditions( ACTIONS::zoomUndo, ENABLE( haveZoomUndo ) );
782 mgr->SetConditions( ACTIONS::zoomRedo, ENABLE( haveZoomRedo ) );
783 mgr->SetConditions( SCH_ACTIONS::toggleGrid, CHECK( showGridCondition ) );
784 mgr->SetConditions( SCH_ACTIONS::toggleLegend, CHECK( showLegendCondition ) );
785 mgr->SetConditions( SCH_ACTIONS::toggleDottedSecondary, CHECK( showDottedCondition ) );
786 mgr->SetConditions( SCH_ACTIONS::toggleDarkModePlots, CHECK( darkModePlotCondition ) );
787
790 mgr->SetConditions( SCH_ACTIONS::runSimulation, ENABLE( !simRunning ) );
791 mgr->SetConditions( SCH_ACTIONS::stopSimulation, ENABLE( simRunning ) );
792 mgr->SetConditions( SCH_ACTIONS::simProbe, ENABLE( simFinished ) );
793 mgr->SetConditions( SCH_ACTIONS::simTune, ENABLE( simFinished ) );
795 // clang-format on
796#undef CHECK
797#undef ENABLE
798}
799
800
801void SIMULATOR_FRAME::onSimStarted( wxCommandEvent& aEvent )
802{
803 SetCursor( wxCURSOR_ARROWWAIT );
804}
805
806
807void SIMULATOR_FRAME::onSimFinished( wxCommandEvent& aEvent )
808{
809 // Sometimes (for instance with a directive like wrdata my_file.csv "my_signal")
810 // the simulator is in idle state (simulation is finished), but still running, during
811 // the time the file is written. So gives a slice of time to fully finish the work:
812 if( m_simulator->IsRunning() )
813 {
814 int max_time = 40; // For a max timeout = 2s
815
816 do
817 {
818 wxMilliSleep( 50 );
819 wxYield();
820
821 if( max_time )
822 max_time--;
823
824 } while( max_time && m_simulator->IsRunning() );
825 }
826
827 // ensure the shown cursor is the default cursor, not the wxCURSOR_ARROWWAIT set when
828 // staring the simulator in onSimStarted:
829 SetCursor( wxNullCursor );
830
831 // Is a warning message useful if the simulatior is still running?
832 SCHEMATIC& schematic = m_schematicFrame->Schematic();
833 schematic.ClearOperatingPoints();
834
835 m_simFinished = true;
836
837 m_ui->OnSimRefresh( true );
838
841}
842
843
844void SIMULATOR_FRAME::onUpdateSim( wxCommandEvent& aEvent )
845{
846 static bool updateInProgress = false;
847
848 // skip update when events are triggered too often and previous call didn't end yet
849 if( updateInProgress )
850 return;
851
852 updateInProgress = true;
853
854 if( m_simulator->IsRunning() )
855 m_simulator->Stop();
856
857 std::unique_lock<std::mutex> simulatorLock( m_simulator->GetMutex(), std::try_to_lock );
858
859 if( simulatorLock.owns_lock() )
860 {
861 m_ui->OnSimUpdate();
862 m_simulator->Run();
863 }
864 else
865 {
866 DisplayErrorMessage( this, _( "Another simulation is already running." ) );
867 }
868
869 updateInProgress = false;
870}
871
872
873void SIMULATOR_FRAME::onSimReport( wxCommandEvent& aEvent )
874{
875 m_ui->OnSimReport( aEvent.GetString() );
876}
877
878
879void SIMULATOR_FRAME::onExit( wxCommandEvent& aEvent )
880{
881 if( aEvent.GetId() == wxID_EXIT )
882 Kiway().OnKiCadExit();
883
884 if( aEvent.GetId() == wxID_CLOSE )
885 Close( false );
886}
887
888
890{
892 m_workbookModified = true;
893 UpdateTitle();
894}
895
896
897wxDEFINE_EVENT( EVT_SIM_UPDATE, wxCommandEvent );
898wxDEFINE_EVENT( EVT_SIM_REPORT, wxCommandEvent );
899
900wxDEFINE_EVENT( EVT_SIM_STARTED, wxCommandEvent );
901wxDEFINE_EVENT( EVT_SIM_FINISHED, wxCommandEvent );
constexpr EDA_IU_SCALE unityScale
Definition: base_units.h:115
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:195
static TOOL_ACTION cancelInteractive
Definition: actions.h:72
static TOOL_ACTION zoomRedo
Definition: actions.h:147
static TOOL_ACTION zoomUndo
Definition: actions.h:146
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:108
WINDOW_SETTINGS m_Window
Definition: app_settings.h:233
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...
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.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
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:286
void OnKiCadExit()
Definition: kiway.cpp:694
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:395
A singleton reporter that reports to nowhere.
Definition: reporter.h:217
SCHEMATIC_SETTINGS * m_SchematicSettings
Definition: project_file.h:151
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:204
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:373
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:73
virtual bool HasMessageOfSeverity(int aSeverityMask) const
Returns true if the reporter has one or more messages matching the specified severity mask.
Definition: reporter.h:140
std::shared_ptr< NGSPICE_SETTINGS > m_NgspiceSettings
Ngspice simulator settings.
Holds all the data relating to one schematic.
Definition: schematic.h:88
void ClearOperatingPoints()
Clear operating points from a .op simulation.
Definition: schematic.h:265
static TOOL_ACTION toggleSimConsole
Definition: sch_actions.h:284
static TOOL_ACTION exportPlotToClipboard
Definition: sch_actions.h:279
static TOOL_ACTION saveWorkbookAs
Definition: sch_actions.h:276
static TOOL_ACTION toggleSimSidePanel
Definition: sch_actions.h:285
static TOOL_ACTION exportPlotAsCSV
Definition: sch_actions.h:278
static TOOL_ACTION simAnalysisProperties
Definition: sch_actions.h:289
static TOOL_ACTION toggleDottedSecondary
Definition: sch_actions.h:287
static TOOL_ACTION simTune
Definition: sch_actions.h:283
static TOOL_ACTION toggleDarkModePlots
Definition: sch_actions.h:288
static TOOL_ACTION exportPlotAsPNG
Definition: sch_actions.h:277
static TOOL_ACTION exportPlotToSchematic
Definition: sch_actions.h:280
static TOOL_ACTION runSimulation
Definition: sch_actions.h:290
static TOOL_ACTION newAnalysisTab
Definition: sch_actions.h:273
static TOOL_ACTION simProbe
Definition: sch_actions.h:282
static TOOL_ACTION showNetlist
Definition: sch_actions.h:293
static TOOL_ACTION openWorkbook
Definition: sch_actions.h:274
static TOOL_ACTION saveWorkbook
Definition: sch_actions.h:275
static TOOL_ACTION toggleLegend
Definition: sch_actions.h:286
static TOOL_ACTION stopSimulation
Definition: sch_actions.h:291
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 operating 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.
void RecalculateConnections(SCH_COMMIT *aCommit, SCH_CLEANUP_FLAGS aCleanupFlags, PROGRESS_REPORTER *aProgressReporter=nullptr)
Generate the connection data for the entire schematic hierarchy.
SCHEMATIC & Schematic() const
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:75
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)
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.
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
Definition: sim_plot_tab.h:350
bool IsGridShown() const
Definition: sim_plot_tab.h:285
bool GetDottedSecondary() const
Turn on/off the 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.
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:171
TOOL_DISPATCHER * m_toolDispatcher
Definition: tools_holder.h:173
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:306
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()
Initialize 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:190
void Clear() override
Definition: reporter.cpp:89
bool HasMessage() const override
Returns true if the reporter client is non-empty.
Definition: reporter.cpp:96
const wxString & GetMessages() const
Definition: reporter.cpp:83
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:251
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:129
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:194
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
PROJECT & Prj()
Definition: kicad.cpp:608
see class PGM_BASE
SEVERITY
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_UNDEFINED
@ GLOBAL_CLEANUP
Definition: schematic.h:77
@ 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)
Store the common settings that are saved and loaded for each window / frame.
Definition: app_settings.h:90
Definition of file extensions used in Kicad.