KiCad PCB EDA Suite
Loading...
Searching...
No Matches
simulator_control.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) 2023 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <wx/ffile.h>
25#include <wx/filedlg.h>
26#include <wx_filename.h>
27#include <wx/stc/stc.h>
28
29#include <kiway.h>
30#include <confirm.h>
34#include <sch_edit_frame.h>
35#include <sim/simulator_frame.h>
36#include <tool/tool_manager.h>
37#include <tools/ee_actions.h>
39#include <scintilla_tricks.h>
41
42
44{
46 return true;
47}
48
49
51{
52 m_simulatorFrame = getEditFrame<SIMULATOR_FRAME>();
53
55 {
59 }
60}
61
62
64{
65 SIM_TYPE type = m_circuitModel->GetSimType();
66
67 if( SIM_PANEL_BASE::IsPlottable( type ) )
68 {
70 m_circuitModel->GetSimOptions() );
71 }
72
73 return 0;
74}
75
76
78{
79 wxFileDialog openDlg( m_simulatorFrame, _( "Open simulation workbook" ), getDefaultPath(), "",
80 WorkbookFileWildcard(), wxFD_OPEN | wxFD_FILE_MUST_EXIST );
81
82 if( openDlg.ShowModal() == wxID_CANCEL )
83 return -1;
84
85 m_simulatorFrame->LoadWorkbook( openDlg.GetPath() );
86 return 0;
87}
88
89
91{
92 wxFileName filename = m_simulator->Settings()->GetWorkbookFilename();
93
94 if( filename.GetName().IsEmpty() )
95 {
96 if( m_simulatorFrame->Prj().GetProjectName().IsEmpty() )
97 {
98 filename.SetName( _( "noname" ) );
99 filename.SetExt( WorkbookFileExtension );
100 }
101 else
102 {
103 filename.SetName( m_simulatorFrame->Prj().GetProjectName() );
104 filename.SetExt( WorkbookFileExtension );
105 }
106 }
107
108 return filename.GetFullName();
109}
110
111
113{
114 wxFileName path = m_simulator->Settings()->GetWorkbookFilename();
115
116 path.Normalize( FN_NORMALIZE_FLAGS|wxPATH_NORM_ENV_VARS,
118 return path.GetPath();
119}
120
121
123{
124 wxString filename;
125
126 if( aEvent.IsAction( &EE_ACTIONS::saveWorkbook ) )
127 filename = m_simulator->Settings()->GetWorkbookFilename();
128
129 if( filename.IsEmpty() )
130 {
131 wxFileDialog saveAsDlg( m_simulatorFrame, _( "Save Simulation Workbook As" ),
133 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
134
135 if( saveAsDlg.ShowModal() == wxID_CANCEL )
136 return -1;
137
138 filename = saveAsDlg.GetPath();
139 }
140
142 return 0;
143}
144
145
147{
149 return -1;
150
151 wxFileDialog saveDlg( m_simulatorFrame, _( "Save Plot as Image" ), "", "", PngFileWildcard(),
152 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
153
154 if( saveDlg.ShowModal() == wxID_CANCEL )
155 return -1;
156
158 wxBITMAP_TYPE_PNG );
159
160 return 0;
161}
162
163
165{
167 return -1;
168
169 const wxChar SEPARATOR = ';';
170
171 wxFileDialog saveDlg( m_simulatorFrame, _( "Save Plot Data" ), "", "", CsvFileWildcard(),
172 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
173
174 if( saveDlg.ShowModal() == wxID_CANCEL )
175 return -1;
176
177 wxFFile out( saveDlg.GetPath(), "wb" );
178
179 std::map<wxString, TRACE*> traces = m_simulatorFrame->GetCurrentPlot()->GetTraces();
180
181 if( traces.size() == 0 )
182 return -1;
183
184 SIM_TYPE simType = m_circuitModel->GetSimType();
185
186 std::size_t rowCount = traces.begin()->second->GetDataX().size();
187
188 // write column header names on the first row
189 wxString xAxisName( m_simulator->GetXAxis( simType ) );
190 out.Write( wxString::Format( wxT( "%s%c" ), xAxisName, SEPARATOR ) );
191
192 for( const auto& [name, trace] : traces )
193 out.Write( wxString::Format( wxT( "%s%c" ), name, SEPARATOR ) );
194
195 out.Write( wxS( "\r\n" ) );
196
197 // write each row's numerical value
198 for ( std::size_t curRow=0; curRow < rowCount; curRow++ )
199 {
200 double xAxisValue = traces.begin()->second->GetDataX().at( curRow );
201 out.Write( wxString::Format( wxT( "%g%c" ), xAxisValue, SEPARATOR ) );
202
203 for( const auto& [name, trace] : traces )
204 {
205 double yAxisValue = trace->GetDataY().at( curRow );
206 out.Write( wxString::Format( wxT( "%g%c" ), yAxisValue, SEPARATOR ) );
207 }
208
209 out.Write( wxS( "\r\n" ) );
210 }
211
212 out.Close();
213 return 0;
214}
215
216
218{
219 m_simulatorFrame->Close();
220 return 0;
221}
222
223
225{
227 {
228 if( aEvent.IsAction( &ACTIONS::zoomInCenter ) )
230 else if( aEvent.IsAction( &ACTIONS::zoomOutCenter ) )
232 else if( aEvent.IsAction( &ACTIONS::zoomFitScreen ) )
234 }
235
236 return 0;
237}
238
239
241{
243
244 if( plot )
245 {
246 plot->ShowGrid( !plot->IsGridShown() );
248 }
249
250 return 0;
251}
252
253
255{
257
258 if( plot )
259 {
260 plot->ShowLegend( !plot->IsLegendShown() );
262 }
263
264 return 0;
265}
266
267
269{
271
272 if( plot )
273 {
274 plot->SetDottedSecondary( !plot->GetDottedSecondary() );
276 }
277
278 return 0;
279}
280
281
283{
285 return 0;
286}
287
288
290{
292 return 0;
293}
294
295
297{
298 if( m_simulator->IsRunning() )
299 m_simulator->Stop();
300 else
302
303 return 0;
304}
305
306
308{
309 if( m_schematicFrame == nullptr )
310 return -1;
311
312 wxWindow* blocking_dialog = m_schematicFrame->Kiway().GetBlockingDialog();
313
314 if( blocking_dialog )
315 blocking_dialog->Close( true );
316
318 m_schematicFrame->Raise();
319
320 return 0;
321}
322
323
325{
326 if( m_schematicFrame == nullptr )
327 return -1;
328
329 wxWindow* blocking_dialog = m_schematicFrame->Kiway().GetBlockingDialog();
330
331 if( blocking_dialog )
332 blocking_dialog->Close( true );
333
335 m_schematicFrame->Raise();
336
337 return 0;
338}
339
340
342{
343public:
344 enum
345 {
347 };
348
349 void onClose( wxCloseEvent& evt )
350 {
351 wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL ) );
352 }
353
354 NETLIST_VIEW_DIALOG( wxWindow* parent ) :
355 DIALOG_SHIM( parent, wxID_ANY, _( "SPICE Netlist" ), wxDefaultPosition,
356 wxSize( 800, 800 ), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ),
357 m_textCtrl( nullptr ),
358 m_reporter( nullptr )
359 {
360 m_splitter = new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
361 wxSP_LIVE_UPDATE | wxSP_NOBORDER | wxSP_3DSASH );
362
363 //Avoid the splitter window being assigned as the Parent to additional windows
364 m_splitter->SetExtraStyle( wxWS_EX_TRANSIENT );
365
366 m_textCtrl = new wxStyledTextCtrl( m_splitter, wxID_ANY );
367
368 m_textCtrl->SetMarginWidth( MARGIN_LINE_NUMBERS, 50 );
369 m_textCtrl->StyleSetForeground( wxSTC_STYLE_LINENUMBER, wxColour( 75, 75, 75 ) );
370 m_textCtrl->StyleSetBackground( wxSTC_STYLE_LINENUMBER, wxColour( 220, 220, 220 ) );
371 m_textCtrl->SetMarginType( MARGIN_LINE_NUMBERS, wxSTC_MARGIN_NUMBER );
372
373 wxFont fixedFont = KIUI::GetMonospacedUIFont();
374
375 for( int i = 0; i < wxSTC_STYLE_MAX; ++i )
376 m_textCtrl->StyleSetFont( i, fixedFont );
377
378 m_textCtrl->StyleClearAll(); // Addresses a bug in wx3.0 where styles are not correctly set
379
380 m_textCtrl->SetWrapMode( wxSTC_WRAP_WORD );
381 m_textCtrl->SetLexer( wxSTC_LEX_SPICE );
382 m_textCtrl->SetMinSize( wxSize( 40, 40 ) );
383 m_textCtrl->SetSize( wxSize( 40, 40 ) );
384
385 m_reporter = new WX_HTML_REPORT_BOX( m_splitter, wxID_ANY );
386 m_reporter->SetMinSize( wxSize( 40, 40 ) );
387 m_reporter->SetSize( wxSize( 40, 40 ) );
388
389 m_splitter->SetMinimumPaneSize( 40 );
390 m_splitter->SetSashPosition( 760 );
391 m_splitter->SetSashGravity( 0.9 );
392 m_splitter->SplitHorizontally( m_textCtrl, m_reporter );
393
394 wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
395 sizer->Add( m_splitter, 1, wxEXPAND | wxALL, 5 );
396 SetSizer( sizer );
397 Layout();
398
399 Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( NETLIST_VIEW_DIALOG::onClose ),
400 nullptr, this );
401
402 m_scintillaTricks = std::make_unique<SCINTILLA_TRICKS>( m_textCtrl, wxT( "{}" ), false );
403
405 }
406
407 void SetNetlist( const wxString& aSource )
408 {
409 m_textCtrl->SetText( aSource );
410 m_textCtrl->SetEditable( false );
411
412 m_reporter->Flush();
413 }
414
416
417private:
418 wxSplitterWindow* m_splitter;
419 wxStyledTextCtrl* m_textCtrl;
421
422 std::unique_ptr<SCINTILLA_TRICKS> m_scintillaTricks;
423};
424
425
427{
428 std::map<int, wxString> userSignals = m_simulatorFrame->UserDefinedSignals();
429
431
432 if( dlg.ShowQuasiModal() == wxID_OK )
434
435 return 0;
436}
437
438
440{
441 if( m_schematicFrame == nullptr || m_simulator == nullptr )
442 return -1;
443
444 STRING_FORMATTER formatter;
446
448 m_circuitModel->GetNetlist( &formatter, *dlg.GetReporter() );
449
450 dlg.SetNetlist( wxString( formatter.GetString() ) );
451 dlg.ShowModal();
452
453 return 0;
454}
455
456
458{
466
474
480
483}
const char * name
Definition: DXF_plotter.cpp:56
static TOOL_ACTION toggleGrid
Definition: actions.h:144
static TOOL_ACTION zoomOutCenter
Definition: actions.h:97
static TOOL_ACTION quit
Definition: actions.h:59
static TOOL_ACTION zoomFitScreen
Definition: actions.h:99
static TOOL_ACTION zoomInCenter
Definition: actions.h:96
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition: dialog_shim.h:83
int ShowQuasiModal()
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
static TOOL_ACTION editUserDefinedSignals
Definition: ee_actions.h:279
static TOOL_ACTION simCommand
Definition: ee_actions.h:276
static TOOL_ACTION openWorkbook
Definition: ee_actions.h:265
static TOOL_ACTION stopSimulation
Definition: ee_actions.h:278
static TOOL_ACTION toggleLegend
Definition: ee_actions.h:273
static TOOL_ACTION saveWorkbook
Definition: ee_actions.h:266
static TOOL_ACTION saveWorkbookAs
Definition: ee_actions.h:267
static TOOL_ACTION exportPlotAsCSV
Definition: ee_actions.h:269
static TOOL_ACTION simTune
Definition: ee_actions.h:272
static TOOL_ACTION toggleDarkModePlots
Definition: ee_actions.h:275
static TOOL_ACTION exportPlotAsPNG
Definition: ee_actions.h:268
static TOOL_ACTION showNetlist
Definition: ee_actions.h:280
static TOOL_ACTION simProbe
Definition: ee_actions.h:271
static TOOL_ACTION toggleDottedSecondary
Definition: ee_actions.h:274
static TOOL_ACTION newPlot
Definition: ee_actions.h:264
static TOOL_ACTION runSimulation
Definition: ee_actions.h:277
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:53
wxWindow * GetBlockingDialog()
Gets the window pointer to the blocking dialog (to send it signals)
Definition: kiway.cpp:685
WX_HTML_REPORT_BOX * m_reporter
void SetNetlist(const wxString &aSource)
std::unique_ptr< SCINTILLA_TRICKS > m_scintillaTricks
void onClose(wxCloseEvent &evt)
wxStyledTextCtrl * m_textCtrl
NETLIST_VIEW_DIALOG(wxWindow *parent)
wxSplitterWindow * m_splitter
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:126
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition: project.cpp:132
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:305
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:71
int ExportPlotAsPNG(const TOOL_EVENT &aEvent)
wxString getDefaultPath()
Return the default path to be used in file browser dialog.
SCH_EDIT_FRAME * m_schematicFrame
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
int ToggleLegend(const TOOL_EVENT &aEvent)
int ShowNetlist(const TOOL_EVENT &aEvent)
int NewPlot(const TOOL_EVENT &aEvent)
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
int ToggleDarkModePlots(const TOOL_EVENT &aEvent)
int Tune(const TOOL_EVENT &aEvent)
wxString getDefaultFilename()
Return the default filename (with extension) to be used in file browser dialog.
SIMULATOR_FRAME * m_simulatorFrame
bool Init() override
Init() is called once upon a registration of the tool.
int SaveWorkbook(const TOOL_EVENT &aEvent)
std::shared_ptr< NGSPICE_CIRCUIT_MODEL > m_circuitModel
int RunSimulation(const TOOL_EVENT &aEvent)
int OpenWorkbook(const TOOL_EVENT &aEvent)
int EditUserDefinedSignals(const TOOL_EVENT &aEvent)
int ToggleGrid(const TOOL_EVENT &aEvent)
int Zoom(const TOOL_EVENT &aEvent)
int ToggleDottedSecondary(const TOOL_EVENT &aEvent)
std::shared_ptr< SPICE_SIMULATOR > m_simulator
int EditSimCommand(const TOOL_EVENT &aEvent)
int ExportPlotAsCSV(const TOOL_EVENT &aEvent)
int Probe(const TOOL_EVENT &aEvent)
int Close(const TOOL_EVENT &aEvent)
SIM_PANEL_BASE * NewPlotPanel(const wxString &aSimCommand, int aSimOptions)
Create a new plot tab for a given simulation type.
void OnModify() override
Must be called after a model change in order to set the "modify" flag and do other frame-specific pro...
std::shared_ptr< NGSPICE_CIRCUIT_MODEL > GetCircuitModel() const
bool SaveWorkbook(const wxString &aPath)
Save plot, signal, cursor, measurement, etc.
SCH_EDIT_FRAME * GetSchematicFrame() const
void ToggleDarkModePlots()
Toggle dark-mode of the plot tabs.
SIM_PLOT_PANEL * GetCurrentPlot() const
Return the current tab (or NULL if there is none).
int GetCurrentOptions() const
bool LoadWorkbook(const wxString &aPath)
Load plot, signal, cursor, measurement, etc.
bool EditSimCommand()
Shows a dialog for editing the current tab's simulation command, or creating a new tab with a differe...
const std::map< int, wxString > & UserDefinedSignals()
std::shared_ptr< SPICE_SIMULATOR > GetSimulator() const
void SetUserDefinedSignals(const std::map< int, wxString > &aSignals)
static bool IsPlottable(SIM_TYPE aSimType)
const std::map< wxString, TRACE * > & GetTraces() const
mpWindow * GetPlotWin() const
Implement an OUTPUTFORMATTER to a memory buffer.
Definition: richio.h:427
const std::string & GetString()
Definition: richio.h:450
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:54
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
@ MODEL_RELOAD
Model changes (the sheet for a schematic)
Definition: tool_base.h:80
Generic, UI-independent tool event.
Definition: tool_event.h:156
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
Definition: tool_event.cpp:81
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:142
A slimmed down version of WX_HTML_REPORT_PANEL.
void Flush()
Build the HTML messages page.
bool SaveScreenshot(const wxString &filename, wxBitmapType type=wxBITMAP_TYPE_BMP, wxSize imageSize=wxDefaultSize, bool fit=false)
Draw the window on a wxBitmap, then save it to a file.
Definition: mathplot.cpp:2695
void ZoomIn(const wxPoint &centerPoint=wxDefaultPosition)
Zoom into current view and refresh display.
Definition: mathplot.cpp:2128
void ZoomOut(const wxPoint &centerPoint=wxDefaultPosition)
Zoom out current view and refresh display.
Definition: mathplot.cpp:2185
void Fit() override
Set view to fit global bounding box of all plot layers and refresh display.
Definition: mathplot.cpp:1968
This file is part of the common library.
#define _(s)
void Reset() override
const std::string WorkbookFileExtension
wxString WorkbookFileWildcard()
wxString PngFileWildcard()
wxString CsvFileWildcard()
wxFont GetMonospacedUIFont()
Definition: ui_common.cpp:85
SIM_TYPE
< Possible simulation types
Definition: sim_types.h:32
Definition of file extensions used in Kicad.
#define SEPARATOR
Definition: wx_combobox.cpp:27
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition: wx_filename.h:38