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