Keep user-defined signals separate.

They can't be plotted till the end of the sim.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/15803
This commit is contained in:
Jeff Young 2023-10-03 12:55:29 +01:00
parent 827942c560
commit 0c055e15b7
2 changed files with 85 additions and 64 deletions

View File

@ -670,6 +670,22 @@ void SIMULATOR_FRAME_UI::SetSubWindowsSashSize()
} }
void sortSignals( std::vector<wxString>& signals )
{
std::sort( signals.begin(), signals.end(),
[]( const wxString& lhs, const wxString& rhs )
{
// Sort voltages first
if( lhs.Upper().StartsWith( 'V' ) && !rhs.Upper().StartsWith( 'V' ) )
return true;
else if( !lhs.Upper().StartsWith( 'V' ) && rhs.Upper().StartsWith( 'V' ) )
return false;
return StrNumCmp( lhs, rhs, true /* ignore case */ ) < 0;
} );
}
void SIMULATOR_FRAME_UI::rebuildSignalsGrid( wxString aFilter ) void SIMULATOR_FRAME_UI::rebuildSignalsGrid( wxString aFilter )
{ {
SUPPRESS_GRID_CELL_EVENTS raii( this ); SUPPRESS_GRID_CELL_EVENTS raii( this );
@ -695,7 +711,13 @@ void SIMULATOR_FRAME_UI::rebuildSignalsGrid( wxString aFilter )
} }
else else
{ {
signals.insert( signals.end(), m_signals.begin(), m_signals.end() ); for( const wxString& signal : m_signals )
signals.push_back( signal );
for( const auto& [ id, signal ] : m_userDefinedSignals )
signals.push_back( signal );
sortSignals( signals );
} }
if( aFilter.IsEmpty() ) if( aFilter.IsEmpty() )
@ -897,24 +919,6 @@ void SIMULATOR_FRAME_UI::rebuildSignalsList()
addSignal( directiveParams.Trim( true ).Trim( false ) ); addSignal( directiveParams.Trim( true ).Trim( false ) );
} }
} }
// JEY TODO: find and add SPICE "LET" commands
// Add user-defined signals
for( const auto& [ signalId, signalName ] : m_userDefinedSignals )
addSignal( signalName );
std::sort( m_signals.begin(), m_signals.end(),
[]( const wxString& lhs, const wxString& rhs )
{
// Sort voltages first
if( lhs.Upper().StartsWith( 'V' ) && !rhs.Upper().StartsWith( 'V' ) )
return true;
else if( !lhs.Upper().StartsWith( 'V' ) && rhs.Upper().StartsWith( 'V' ) )
return false;
return StrNumCmp( lhs, rhs, true /* ignore case */ ) < 0;
} );
} }
@ -1610,7 +1614,8 @@ void SIMULATOR_FRAME_UI::SetUserDefinedSignals( const std::map<int, wxString>& a
void SIMULATOR_FRAME_UI::updateTrace( const wxString& aVectorName, int aTraceType, void SIMULATOR_FRAME_UI::updateTrace( const wxString& aVectorName, int aTraceType,
SIM_PLOT_TAB* aPlotTab, std::vector<double>* aDataX ) SIM_PLOT_TAB* aPlotTab, std::vector<double>* aDataX,
bool aClearData )
{ {
SIM_TYPE simType = SPICE_CIRCUIT_MODEL::CommandToSimType( aPlotTab->GetSimCommand() ); SIM_TYPE simType = SPICE_CIRCUIT_MODEL::CommandToSimType( aPlotTab->GetSimCommand() );
@ -1633,11 +1638,11 @@ void SIMULATOR_FRAME_UI::updateTrace( const wxString& aVectorName, int aTraceTyp
std::vector<double> data_x; std::vector<double> data_x;
std::vector<double> data_y; std::vector<double> data_y;
if( !aDataX ) if( !aDataX || aClearData )
aDataX = &data_x; aDataX = &data_x;
// First, handle the x axis // First, handle the x axis
if( aDataX->empty() ) if( aDataX->empty() && !aClearData )
{ {
wxString xAxisName( simulator()->GetXAxis( simType ) ); wxString xAxisName( simulator()->GetXAxis( simType ) );
@ -2554,6 +2559,9 @@ void SIMULATOR_FRAME_UI::onPlotCursorUpdate( wxCommandEvent& aEvent )
void SIMULATOR_FRAME_UI::OnSimUpdate() void SIMULATOR_FRAME_UI::OnSimUpdate()
{ {
if( SIM_TAB* simTab = GetCurrentSimTab() )
simTab->SetSpicePlotName( simulator()->CurrentPlotName() );
if( SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( GetCurrentSimTab() ) ) if( SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( GetCurrentSimTab() ) )
plotTab->ResetScales( true ); plotTab->ResetScales( true );
@ -2594,24 +2602,27 @@ std::vector<wxString> SIMULATOR_FRAME_UI::Signals() const
for( const auto& [ id, signal ] : m_userDefinedSignals ) for( const auto& [ id, signal ] : m_userDefinedSignals )
signals.emplace_back( signal ); signals.emplace_back( signal );
sortSignals( signals );
return signals; return signals;
} }
void SIMULATOR_FRAME_UI::OnSimRefresh( bool aFinal ) void SIMULATOR_FRAME_UI::OnSimRefresh( bool aFinal )
{ {
if( aFinal )
m_refreshTimer.Stop();
SIM_TAB* simTab = GetCurrentSimTab(); SIM_TAB* simTab = GetCurrentSimTab();
if( !simTab ) if( !simTab )
return; return;
SIM_TYPE simType = simTab->GetSimType(); SIM_TYPE simType = simTab->GetSimType();
std::vector<wxString> oldSignals = m_signals; wxString msg;
wxString msg;
simTab->SetSpicePlotName( simulator()->CurrentPlotName() ); if( aFinal )
applyUserDefinedSignals(); applyUserDefinedSignals();
rebuildSignalsList();
// If there are any signals plotted, update them // If there are any signals plotted, update them
if( SIM_TAB::IsPlottable( simType ) ) if( SIM_TAB::IsPlottable( simType ) )
@ -2645,63 +2656,73 @@ void SIMULATOR_FRAME_UI::OnSimRefresh( bool aFinal )
SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( simTab ); SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( simTab );
wxCHECK_RET( plotTab, wxT( "not a SIM_PLOT_TAB" ) ); wxCHECK_RET( plotTab, wxT( "not a SIM_PLOT_TAB" ) );
// Map of TRACE* to { vectorName, traceType } struct TRACE_INFO
std::map<TRACE*, std::pair<wxString, int>> traceMap; {
wxString Vector;
int TraceType;
bool ClearData;
};
std::map<TRACE*, TRACE_INFO> traceMap;
for( const auto& [ name, trace ] : plotTab->GetTraces() ) for( const auto& [ name, trace ] : plotTab->GetTraces() )
traceMap[ trace ] = { wxEmptyString, SPT_UNKNOWN }; traceMap[ trace ] = { wxEmptyString, SPT_UNKNOWN, false };
auto addSignalToTraceMap =
[&]( const wxString& signal, bool clearData )
{
int traceType = SPT_UNKNOWN;
wxString vectorName = vectorNameFromSignalName( plotTab, signal, &traceType );
if( simType == ST_AC )
{
for( int subType : { SPT_AC_GAIN, SPT_AC_PHASE } )
{
if( TRACE* trace = plotTab->GetTrace( vectorName, traceType+subType ) )
traceMap[ trace ] = { vectorName, traceType, clearData };
}
}
else if( simType == ST_SP )
{
for( int subType : { SPT_SP_AMP, SPT_AC_PHASE } )
{
if( TRACE* trace = plotTab->GetTrace( vectorName, traceType+subType ) )
traceMap[trace] = { vectorName, traceType, clearData };
}
}
else
{
if( TRACE* trace = plotTab->GetTrace( vectorName, traceType ) )
traceMap[ trace ] = { vectorName, traceType, clearData };
}
};
for( const wxString& signal : m_signals ) for( const wxString& signal : m_signals )
{ addSignalToTraceMap( signal, false );
int traceType = SPT_UNKNOWN;
wxString vectorName = vectorNameFromSignalName( plotTab, signal, &traceType );
if( simType == ST_AC ) for( const auto& [ id, signal ] : m_userDefinedSignals )
{ addSignalToTraceMap( signal, !aFinal );
for( int subType : { SPT_AC_GAIN, SPT_AC_PHASE } )
{
if( TRACE* trace = plotTab->GetTrace( vectorName, traceType | subType ) )
traceMap[ trace ] = { vectorName, traceType };
}
}
else if( simType == ST_SP )
{
for( int subType : { SPT_SP_AMP, SPT_AC_PHASE } )
{
if( TRACE* trace = plotTab->GetTrace( vectorName, traceType | subType ) )
traceMap[trace] = { vectorName, traceType };
}
}
else
{
if( TRACE* trace = plotTab->GetTrace( vectorName, traceType ) )
traceMap[ trace ] = { vectorName, traceType };
}
}
// Two passes so that DC-sweep sub-traces get deleted and re-created: // Two passes so that DC-sweep sub-traces get deleted and re-created:
for( const auto& [ trace, traceInfo ] : traceMap ) for( const auto& [ trace, traceInfo ] : traceMap )
{ {
if( traceInfo.first.IsEmpty() ) if( traceInfo.Vector.IsEmpty() )
plotTab->DeleteTrace( trace ); plotTab->DeleteTrace( trace );
} }
for( const auto& [ trace, traceInfo ] : traceMap ) for( const auto& [ trace, info ] : traceMap )
{ {
std::vector<double> data_x; std::vector<double> data_x;
if( !traceInfo.first.IsEmpty() ) if( !info.Vector.IsEmpty() )
updateTrace( traceInfo.first, traceInfo.second, plotTab, &data_x ); updateTrace( info.Vector, info.TraceType, plotTab, &data_x, info.ClearData );
} }
plotTab->GetPlotWin()->UpdateAll(); plotTab->GetPlotWin()->UpdateAll();
if( aFinal ) if( aFinal )
{ {
rebuildSignalsGrid( m_filter->GetValue() );
updateSignalsGrid();
for( int row = 0; row < m_measurementsGrid->GetNumberRows(); ++row ) for( int row = 0; row < m_measurementsGrid->GetNumberRows(); ++row )
UpdateMeasurement( row ); UpdateMeasurement( row );

View File

@ -239,7 +239,7 @@ private:
* @param aPlotTab is the tab that should receive the update. * @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<double>* aDataX = nullptr ); std::vector<double>* aDataX = nullptr, bool aClearData = false );
/** /**
* Rebuild the list of signals available from the netlist. * Rebuild the list of signals available from the netlist.