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:
parent
827942c560
commit
0c055e15b7
|
@ -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 );
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Reference in New Issue