From 463e7c3b30bed7e2f4cf0f9aae1ce0dc00d4d187 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Fri, 22 Sep 2023 21:40:35 +0100 Subject: [PATCH] Improve performance & responsiveness of sim updates. The x-axis only needs to be fetched once per update. Same for redrawing the screen. And there's no reason to fetch more y data than we have x data for (which happens to subsequent traces as the sim is still running as we're updating). Fixes https://gitlab.com/kicad/code/kicad/-/issues/15673 --- eeschema/sim/sim_plot_tab.cpp | 2 - eeschema/sim/simulator_frame_ui.cpp | 59 ++++++++++++++++++----------- eeschema/sim/simulator_frame_ui.h | 3 +- 3 files changed, 39 insertions(+), 25 deletions(-) diff --git a/eeschema/sim/sim_plot_tab.cpp b/eeschema/sim/sim_plot_tab.cpp index 84885c6d4a..519eb38b35 100644 --- a/eeschema/sim/sim_plot_tab.cpp +++ b/eeschema/sim/sim_plot_tab.cpp @@ -913,8 +913,6 @@ void SIM_PLOT_TAB::SetTraceData( TRACE* trace, std::vector& aX, std::vec if( cursor ) cursor->SetCoordX( cursor->GetCoords().x ); } - - m_plotWin->UpdateAll(); } diff --git a/eeschema/sim/simulator_frame_ui.cpp b/eeschema/sim/simulator_frame_ui.cpp index 4494426950..b6f4eeedcf 100644 --- a/eeschema/sim/simulator_frame_ui.cpp +++ b/eeschema/sim/simulator_frame_ui.cpp @@ -1057,6 +1057,8 @@ void SIMULATOR_FRAME_UI::onSignalsGridCellChanged( wxGridEvent& aEvent ) else plotTab->DeleteTrace( vectorName, traceType ); + plotTab->GetPlotWin()->UpdateAll(); + // Update enabled/visible states of other controls updateSignalsGrid(); updatePlotCursors(); @@ -1529,6 +1531,8 @@ void SIMULATOR_FRAME_UI::AddTrace( const wxString& aName, SIM_TRACE_TYPE aType ) updateTrace( aName, aType, plotTab ); } + plotTab->GetPlotWin()->UpdateAll(); + updateSignalsGrid(); m_simulatorFrame->OnModify(); } @@ -1606,7 +1610,7 @@ void SIMULATOR_FRAME_UI::SetUserDefinedSignals( const std::map& a void SIMULATOR_FRAME_UI::updateTrace( const wxString& aVectorName, int aTraceType, - SIM_PLOT_TAB* aPlotTab ) + SIM_PLOT_TAB* aPlotTab, std::vector* aDataX ) { SIM_TYPE simType = SPICE_CIRCUIT_MODEL::CommandToSimType( aPlotTab->GetSimCommand() ); @@ -1626,51 +1630,60 @@ void SIMULATOR_FRAME_UI::updateTrace( const wxString& aVectorName, int aTraceTyp return; } - // First, handle the x axis - wxString xAxisName( simulator()->GetXAxis( simType ) ); - - if( xAxisName.IsEmpty() ) - return; - std::vector data_x; std::vector data_y; - data_x = simulator()->GetGainVector( (const char*) xAxisName.c_str() ); + if( !aDataX ) + aDataX = &data_x; + + // First, handle the x axis + if( aDataX->empty() ) + { + wxString xAxisName( simulator()->GetXAxis( simType ) ); + + if( xAxisName.IsEmpty() ) + return; + + *aDataX = simulator()->GetGainVector( (const char*) xAxisName.c_str() ); + } + + unsigned int size = aDataX->size(); switch( simType ) { case ST_AC: if( aTraceType & SPT_AC_GAIN ) - data_y = simulator()->GetGainVector( (const char*) simVectorName.c_str() ); + data_y = simulator()->GetGainVector( (const char*) simVectorName.c_str(), size ); else if( aTraceType & SPT_AC_PHASE ) - data_y = simulator()->GetPhaseVector( (const char*) simVectorName.c_str() ); + data_y = simulator()->GetPhaseVector( (const char*) simVectorName.c_str(), size ); else wxFAIL_MSG( wxT( "Plot type missing AC_PHASE or AC_MAG bit" ) ); break; case ST_SP: if( aTraceType & SPT_SP_AMP ) - data_y = simulator()->GetGainVector( (const char*) simVectorName.c_str() ); + data_y = simulator()->GetGainVector( (const char*) simVectorName.c_str(), size ); else if( aTraceType & SPT_AC_PHASE ) - data_y = simulator()->GetPhaseVector( (const char*) simVectorName.c_str() ); + data_y = simulator()->GetPhaseVector( (const char*) simVectorName.c_str(), size ); else wxFAIL_MSG( wxT( "Plot type missing AC_PHASE or SPT_SP_AMP bit" ) ); break; - case ST_NOISE: case ST_DC: + data_y = simulator()->GetGainVector( (const char*) simVectorName.c_str(), -1 ); + break; + + case ST_NOISE: case ST_TRAN: case ST_FFT: - data_y = simulator()->GetGainVector( (const char*) simVectorName.c_str() ); + data_y = simulator()->GetGainVector( (const char*) simVectorName.c_str(), size ); break; default: wxFAIL_MSG( wxT( "Unhandled plot type" ) ); } - unsigned int size = data_x.size(); - // If we did a two-source DC analysis, we need to split the resulting vector and add traces // for each input step SPICE_DC_PARAMS source1, source2; @@ -1684,9 +1697,9 @@ void SIMULATOR_FRAME_UI::updateTrace( const wxString& aVectorName, int aTraceTyp size_t offset = 0; size_t outer = ( size_t )( ( source2.m_vend - v ) / source2.m_vincrement ).ToDouble(); - size_t inner = data_x.size() / ( outer + 1 ); + size_t inner = aDataX->size() / ( outer + 1 ); - wxASSERT( data_x.size() % ( outer + 1 ) == 0 ); + wxASSERT( aDataX->size() % ( outer + 1 ) == 0 ); for( size_t idx = 0; idx <= outer; idx++ ) { @@ -1694,8 +1707,8 @@ void SIMULATOR_FRAME_UI::updateTrace( const wxString& aVectorName, int aTraceTyp { if( data_y.size() >= size ) { - std::vector sub_x( data_x.begin() + offset, - data_x.begin() + offset + inner ); + std::vector sub_x( aDataX->begin() + offset, + aDataX->begin() + offset + inner ); std::vector sub_y( data_y.begin() + offset, data_y.begin() + offset + inner ); @@ -1710,7 +1723,7 @@ void SIMULATOR_FRAME_UI::updateTrace( const wxString& aVectorName, int aTraceTyp else if( TRACE* trace = aPlotTab->AddTrace( aVectorName, aTraceType ) ) { if( data_y.size() >= size ) - aPlotTab->SetTraceData( trace, data_x, data_y ); + aPlotTab->SetTraceData( trace, *aDataX, data_y ); } } @@ -2676,8 +2689,10 @@ void SIMULATOR_FRAME_UI::OnSimRefresh( bool aFinal ) for( const auto& [ trace, traceInfo ] : traceMap ) { + std::vector data_x; + if( !traceInfo.first.IsEmpty() ) - updateTrace( traceInfo.first, traceInfo.second, plotTab ); + updateTrace( traceInfo.first, traceInfo.second, plotTab, &data_x ); } plotTab->GetPlotWin()->UpdateAll(); diff --git a/eeschema/sim/simulator_frame_ui.h b/eeschema/sim/simulator_frame_ui.h index c606372695..054f53476a 100644 --- a/eeschema/sim/simulator_frame_ui.h +++ b/eeschema/sim/simulator_frame_ui.h @@ -238,7 +238,8 @@ private: * @param aTraceType describes the type of plot. * @param aPlotTab is the tab that should receive the update. */ - void updateTrace( const wxString& aVectorName, int aTraceType, SIM_PLOT_TAB* aPlotTab ); + void updateTrace( const wxString& aVectorName, int aTraceType, SIM_PLOT_TAB* aPlotTab, + std::vector* aDataX = nullptr ); /** * Rebuild the list of signals available from the netlist.