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