diff --git a/eeschema/netlist_exporters/netlist_exporter_pspice.cpp b/eeschema/netlist_exporters/netlist_exporter_pspice.cpp index d8f96d097a..174fbffffe 100644 --- a/eeschema/netlist_exporters/netlist_exporter_pspice.cpp +++ b/eeschema/netlist_exporters/netlist_exporter_pspice.cpp @@ -52,7 +52,8 @@ bool NETLIST_EXPORTER_PSPICE::Format( OUTPUTFORMATTER* aFormatter, unsigned aCtl // Netlist options const bool useNetcodeAsNetName = aCtl & NET_USE_NETCODES_AS_NETNAMES; - ProcessNetlist( aCtl ); + if( !ProcessNetlist( aCtl ) ) + return false; aFormatter->Print( 0, ".title KiCad schematic\n" ); @@ -234,10 +235,12 @@ wxString NETLIST_EXPORTER_PSPICE::GetSpiceFieldDefVal( SPICE_FIELD aField, } -void NETLIST_EXPORTER_PSPICE::ProcessNetlist( unsigned aCtl ) +bool NETLIST_EXPORTER_PSPICE::ProcessNetlist( unsigned aCtl ) { const wxString delimiters( "{:,; }" ); SCH_SHEET_LIST sheetList( g_RootSheet ); + // Set of reference names, to check for duplications + std::set refNames; // Prepare list of nets generation (not used here, but... for( unsigned ii = 0; ii < m_masterList->size(); ii++ ) @@ -275,6 +278,16 @@ void NETLIST_EXPORTER_PSPICE::ProcessNetlist( unsigned aCtl ) spiceItem.m_model = GetSpiceField( SF_MODEL, comp, aCtl ); spiceItem.m_refName = comp->GetRef( &sheetList[sheet_idx] ); + // Duplicate references will result in simulation errors + if( refNames.count( spiceItem.m_refName ) ) + { + DisplayError( NULL, wxT( "There are duplicate components. " + "You need to annotate schematics first." ) ); + return false; + } + + refNames.insert( spiceItem.m_refName ); + // Check to see if component should be removed from Spice netlist spiceItem.m_enabled = StringToBool( GetSpiceField( SF_ENABLED, comp, aCtl ) ); @@ -326,6 +339,8 @@ void NETLIST_EXPORTER_PSPICE::ProcessNetlist( unsigned aCtl ) m_spiceItems.push_back( spiceItem ); } } + + return true; } diff --git a/eeschema/netlist_exporters/netlist_exporter_pspice.h b/eeschema/netlist_exporters/netlist_exporter_pspice.h index d0407912fc..44d4ed6d10 100644 --- a/eeschema/netlist_exporters/netlist_exporter_pspice.h +++ b/eeschema/netlist_exporters/netlist_exporter_pspice.h @@ -113,7 +113,13 @@ public: bool Format( OUTPUTFORMATTER* aFormatter, unsigned aCtl ); - void ProcessNetlist( unsigned aCtl ); + /** + * @brief Processes the netlist to create net mapping and a list of SPICE_ITEMs. + * It is automatically called by WriteNetlist(), but might be used separately, + * if only net mapping and the list of SPICE_ITEMs are required. + * @return True if successful. + */ + bool ProcessNetlist( unsigned aCtl ); const NET_INDEX_MAP& GetNetIndexMap() const { diff --git a/eeschema/sim/sim_plot_frame.cpp b/eeschema/sim/sim_plot_frame.cpp index d3f0f7b6c1..772a6c365e 100644 --- a/eeschema/sim/sim_plot_frame.cpp +++ b/eeschema/sim/sim_plot_frame.cpp @@ -150,11 +150,16 @@ void SIM_PLOT_FRAME::StartSimulation() updateNetlistExporter(); m_exporter->SetSimCommand( m_settingsDlg.GetSimCommand() ); - m_exporter->Format( &formatter, m_settingsDlg.GetNetlistOptions() ); + + if( !m_exporter->Format( &formatter, m_settingsDlg.GetNetlistOptions() ) ) + { + DisplayError( this, wxT( "There were errors during netlist export, aborted." ) ); + return; + } if( m_exporter->GetSimType() == ST_UNKNOWN ) { - DisplayInfoMessage( this, wxT( "You need to select the simulation settings first" ) ); + DisplayInfoMessage( this, wxT( "You need to select the simulation settings first." ) ); return; } @@ -647,8 +652,15 @@ void SIM_PLOT_FRAME::onSimulate( wxCommandEvent& event ) void SIM_PLOT_FRAME::onSettings( wxCommandEvent& event ) { + // Initial processing is required to e.g. display a list of power sources updateNetlistExporter(); - m_exporter->ProcessNetlist( NET_ALL_FLAGS ); + + if( !m_exporter->ProcessNetlist( NET_ALL_FLAGS ) ) + { + DisplayError( this, wxT( "There were errors during netlist export, aborted." ) ); + return; + } + m_settingsDlg.SetNetlistExporter( m_exporter.get() ); m_settingsDlg.ShowModal(); } @@ -660,7 +672,7 @@ void SIM_PLOT_FRAME::onAddSignal( wxCommandEvent& event ) if( !plotPanel || !m_exporter || plotPanel->GetType() != m_exporter->GetSimType() ) { - DisplayInfoMessage( this, wxT( "You need to run simulation first" ) ); + DisplayInfoMessage( this, wxT( "You need to run simulation first." ) ); return; }