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
145 mainSizer->Add( m_ui, 1, wxEXPAND, 5 );
146
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();
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
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
227 m_toolManager->RegisterTool( new COMMON_CONTROL );
228 m_toolManager->RegisterTool( new SIMULATOR_CONTROL );
229 m_toolManager->InitTools();
230}
231
232
234{
236
237 UpdateTitle();
238
239 m_ui->ShowChangedLanguage();
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
265
266 if( m_schematicFrame && modified )
267 m_schematicFrame->OnModify();
268}
269
270
272{
274
276 m_ui->ApplyPreferences( cfg->m_Simulator.preferences );
277}
278
279
281{
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() )
293 return m_ui->GetCurrentSimTab()->GetSimCommand();
294 else
295 return m_circuitModel->GetSchTextSimCommand();
296}
297
298
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{
376 s_reporter.Clear();
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 )
383 m_schematicFrame->RecalculateConnections( nullptr, GLOBAL_CLEANUP );
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{
396 s_reporter.Clear();
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.
478 m_ui->OnPlotSettingsChanged();
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{
578 m_ui->ToggleSimConsole();
579}
580
581
583{
584 m_ui->ToggleSimSidePanel();
585}
586
587
589{
590 m_ui->ToggleDarkModePlots();
591}
592
593
595{
596 SIM_TAB* simTab = m_ui->GetCurrentSimTab();
597 DIALOG_SIM_COMMAND dlg( this, m_circuitModel, m_simulator->Settings() );
598
599 s_reporter.Clear();
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 );
617 m_ui->OnPlotSettingsChanged();
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
660 m_schematicFrame->GetToolManager()->PostAction( ACTIONS::cancelInteractive );
661
662 SaveSettings( config() );
663
664 m_simulator->Settings().reset();
665
666 Destroy();
667}
668
669
671{
673
674 ACTION_MANAGER* mgr = m_toolManager->GetActionManager();
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
839 m_schematicFrame->RefreshOperatingPointDisplay();
840 m_schematicFrame->GetCanvas()->Refresh();
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
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:197
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.
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:286
void OnKiCadExit()
Definition kiway.cpp:717
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: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:386
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:265
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: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.
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:76
A wrapper for reporting to a wxString object.
Definition reporter.h:191
const wxString & GetMessages() const
Definition reporter.cpp:77
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:612
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.