diff --git a/eeschema/dialogs/dialog_sheet_properties.cpp b/eeschema/dialogs/dialog_sheet_properties.cpp index 7ab656411c..24ccb79f73 100644 --- a/eeschema/dialogs/dialog_sheet_properties.cpp +++ b/eeschema/dialogs/dialog_sheet_properties.cpp @@ -642,10 +642,10 @@ bool DIALOG_SHEET_PROPERTIES::onSheetFilenameChanged( const wxString& aNewFilena if( restoreSheet ) currentSheet.LastScreen()->Append( m_sheet ); - // The full hierarchy needs to be reloaded because due to the addition of a new sheet. + // The full hierarchy needs to be reloaded due to the addition of a new sheet. fullHierarchy = schematic.GetFullHierarchy(); - fullHierarchy.UpdateSheetInstances( sheetInstances ); - fullHierarchy.UpdateSymbolInstances( symbolInstances ); + fullHierarchy.UpdateSheetInstanceData( sheetInstances ); + fullHierarchy.UpdateSymbolInstanceData( symbolInstances ); } if( m_clearAnnotationNewItems ) diff --git a/eeschema/eeschema.cpp b/eeschema/eeschema.cpp index 31946a714a..01da086472 100644 --- a/eeschema/eeschema.cpp +++ b/eeschema/eeschema.cpp @@ -87,12 +87,17 @@ static std::unique_ptr readSchematicFromFile( const std::string& aFil SCH_SCREENS screens( schematic->Root() ); for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() ) + { screen->UpdateLocalLibSymbolLinks(); + if( schematic->RootScreen()->GetFileFormatVersionAtLoad() < 20221206 ) + screen->MigrateSimModels(); + } + SCH_SHEET_LIST sheets = schematic->GetSheets(); // Restore all of the loaded symbol instances from the root sheet screen. - sheets.UpdateSymbolInstances( schematic->RootScreen()->GetSymbolInstances() ); + sheets.UpdateSymbolInstanceData( schematic->RootScreen()->GetSymbolInstances() ); sheets.AnnotatePowerSymbols(); diff --git a/eeschema/eeschema_helpers.cpp b/eeschema/eeschema_helpers.cpp index de65e056f0..6426cb7b70 100644 --- a/eeschema/eeschema_helpers.cpp +++ b/eeschema/eeschema_helpers.cpp @@ -136,16 +136,20 @@ SCHEMATIC* EESCHEMA_HELPERS::LoadSchematic( wxString& aFileName, SCH_IO_MGR::SCH } SCH_SHEET_LIST sheetList = schematic->GetSheets(); - SCH_SCREENS schematicScreenRoot( schematic->Root() ); + SCH_SCREENS screens( schematic->Root() ); - for( SCH_SCREEN* screen = schematicScreenRoot.GetFirst(); screen; - screen = schematicScreenRoot.GetNext() ) + for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() ) + { screen->UpdateLocalLibSymbolLinks(); - if( schematic->RootScreen()->GetFileFormatVersionAtLoad() < 20221002 ) - sheetList.UpdateSymbolInstances( schematic->RootScreen()->GetSymbolInstances() ); + if( schematic->RootScreen()->GetFileFormatVersionAtLoad() < 20221206 ) + screen->MigrateSimModels(); + } - sheetList.UpdateSheetInstances( schematic->RootScreen()->GetSheetInstances() ); + if( schematic->RootScreen()->GetFileFormatVersionAtLoad() < 20221002 ) + sheetList.UpdateSymbolInstanceData( schematic->RootScreen()->GetSymbolInstances()); + + sheetList.UpdateSheetInstanceData( schematic->RootScreen()->GetSheetInstances()); sheetList.AnnotatePowerSymbols(); diff --git a/eeschema/files-io.cpp b/eeschema/files-io.cpp index 965e42e3ac..a55cb64d4e 100644 --- a/eeschema/files-io.cpp +++ b/eeschema/files-io.cpp @@ -447,14 +447,19 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector& aFileSet, in } for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() ) + { screen->UpdateLocalLibSymbolLinks(); + if( Schematic().RootScreen()->GetFileFormatVersionAtLoad() < 20221206 ) + screen->MigrateSimModels(); + } + // Restore all of the loaded symbol and sheet instances from the root sheet. if( Schematic().RootScreen()->GetFileFormatVersionAtLoad() < 20221002 ) - sheetList.UpdateSymbolInstances( Schematic().RootScreen()->GetSymbolInstances() ); + sheetList.UpdateSymbolInstanceData( Schematic().RootScreen()->GetSymbolInstances()); if( Schematic().RootScreen()->GetFileFormatVersionAtLoad() < 20221110 ) - sheetList.UpdateSheetInstances( Schematic().RootScreen()->GetSheetInstances() ); + sheetList.UpdateSheetInstanceData( Schematic().RootScreen()->GetSheetInstances()); } Schematic().ConnectionGraph()->Reset(); diff --git a/eeschema/netlist_exporters/netlist_exporter_spice.cpp b/eeschema/netlist_exporters/netlist_exporter_spice.cpp index fad5133f33..8c4b013297 100644 --- a/eeschema/netlist_exporters/netlist_exporter_spice.cpp +++ b/eeschema/netlist_exporters/netlist_exporter_spice.cpp @@ -27,6 +27,7 @@ #include "netlist_exporter_spice.h" #include #include +#include #include #include #include @@ -228,6 +229,23 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions spiceItem.fields.back().SetText( symbol->GetFields()[i].GetShownText( 0, false ) ); } + // Infer RLC passive models if they aren't specified + if( !symbol->FindField( SIM_MODEL::DEVICE_TYPE_FIELD, false ) + && !symbol->FindField( SIM_MODEL::PARAMS_FIELD, false ) ) + { + wxString simParams = SIM_MODEL_IDEAL::InferSimParams( symbol->GetPrefix(), + symbol->GetValueFieldText( true ) ); + + if( !simParams.IsEmpty() ) + { + spiceItem.fields.emplace_back( VECTOR2I(), -1, symbol, SIM_MODEL::DEVICE_TYPE_FIELD ); + spiceItem.fields.back().SetText( symbol->GetPrefix() ); + + spiceItem.fields.emplace_back( VECTOR2I(), -1, symbol, SIM_MODEL::PARAMS_FIELD ); + spiceItem.fields.back().SetText( simParams ); + } + } + try { if( !readRefName( sheet, *symbol, spiceItem, refNames ) ) diff --git a/eeschema/sch_file_versions.h b/eeschema/sch_file_versions.h index db8dab4927..711538cb76 100644 --- a/eeschema/sch_file_versions.h +++ b/eeschema/sch_file_versions.h @@ -92,4 +92,5 @@ //#define SEXPR_SCHEMATIC_FILE_VERSION 20221002 // Move instance data back into symbol definition. //#define SEXPR_SCHEMATIC_FILE_VERSION 20221004 // Move instance data back into symbol definition. //#define SEXPR_SCHEMATIC_FILE_VERSION 20221110 // Move sheet instance data to sheet definition. -#define SEXPR_SCHEMATIC_FILE_VERSION 20221126 // Remove value and footprint from instance data. +//#define SEXPR_SCHEMATIC_FILE_VERSION 20221126 // Remove value and footprint from instance data. +#define SEXPR_SCHEMATIC_FILE_VERSION 20221206 // Simulation model fields V6 -> V7 diff --git a/eeschema/sch_screen.cpp b/eeschema/sch_screen.cpp index 0e9782d34a..31095390e9 100644 --- a/eeschema/sch_screen.cpp +++ b/eeschema/sch_screen.cpp @@ -52,6 +52,9 @@ #include #include #include +#include // For V6 to V7 simulation model migration. +#include // +#include #include @@ -1840,3 +1843,154 @@ void SCH_SCREENS::SetLegacySymbolInstanceData() for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() ) screen->SetLegacySymbolInstanceData(); } + + +void SCH_SCREEN::MigrateSimModels() +{ + LOCALE_IO toggle; + + // V6 schematics may specify model names in Value fields, which we don't do in V7. + // Migrate by adding an equivalent model for these symbols. + + for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) ) + { + SCH_SYMBOL* symbol = static_cast( item ); + migrateSimModel( *symbol ); + } +} + + +void SCH_SCREEN::migrateSimModel( SCH_SYMBOL& aSymbol ) +{ + if( aSymbol.FindField( SIM_MODEL::DEVICE_TYPE_FIELD ) + || aSymbol.FindField( SIM_MODEL::TYPE_FIELD ) + || aSymbol.FindField( SIM_MODEL::PINS_FIELD ) + || aSymbol.FindField( SIM_MODEL::PARAMS_FIELD ) ) + { + // Has a V7 model field -- skip. + return; + } + + wxString prefix = aSymbol.GetPrefix(); + wxString value = aSymbol.GetValueFieldText( true ); + + wxString spiceType; + wxString spiceModel; + wxString spiceLib; + wxString pinMap; + + if( aSymbol.FindField( "Spice_Primitive" ) + || aSymbol.FindField( "Spice_Node_Sequence" ) + || aSymbol.FindField( "Spice_Model" ) + || aSymbol.FindField( "Spice_Netlist_Enabled" ) + || aSymbol.FindField( "Spice_Lib_File" ) ) + { + if( SCH_FIELD* primitiveField = aSymbol.FindField( "Spice_Primitive" ) ) + { + spiceType = primitiveField->GetText(); + aSymbol.RemoveField( "Spice_Primitive" ); + } + + if( SCH_FIELD* nodeSequenceField = aSymbol.FindField( "Spice_Node_Sequence" ) ) + { + const wxString delimiters( "{:,; }" ); + const wxString& nodeSequence = nodeSequenceField->GetText(); + + if( nodeSequence != "" ) + { + wxStringTokenizer tkz( nodeSequence, delimiters ); + + for( long modelPinNumber = 1; tkz.HasMoreTokens(); ++modelPinNumber ) + { + long symbolPinNumber = 1; + tkz.GetNextToken().ToLong( &symbolPinNumber ); + + if( modelPinNumber != 1 ) + pinMap.Append( " " ); + + pinMap.Append( wxString::Format( "%ld=%ld", symbolPinNumber, modelPinNumber ) ); + } + } + + aSymbol.RemoveField( "Spice_Node_Sequence" ); + } + + if( SCH_FIELD* modelField = aSymbol.FindField( "Spice_Model" ) ) + { + spiceModel = modelField->GetText(); + aSymbol.RemoveField( "Spice_Model" ); + } + else + { + spiceModel = aSymbol.FindField( "Value" )->GetText(); + } + + if( SCH_FIELD* netlistEnabledField = aSymbol.FindField( "Spice_Netlist_Enabled" ) ) + { + wxString netlistEnabled = netlistEnabledField->GetText().Lower(); + + if( netlistEnabled.StartsWith( "0" ) + || netlistEnabled.StartsWith( "n" ) + || netlistEnabled.StartsWith( "f" ) ) + { + SCH_FIELD enableField( VECTOR2I( 0, 0 ), aSymbol.GetFieldCount(), &aSymbol, + SIM_MODEL::ENABLE_FIELD ); + } + } + + if( SCH_FIELD* libFileField = aSymbol.FindField( "Spice_Lib_File" ) ) + { + spiceLib = libFileField->GetText(); + aSymbol.RemoveField( "Spice_Lib_File" ); + } + } + else if( prefix == wxT( "V" ) || prefix == wxT( "I" ) ) + { + spiceModel = value; + } + else + { + return; + } + + // Insert a plaintext model as a substitute. + + SCH_FIELD deviceTypeField( VECTOR2I( 0, 0 ), aSymbol.GetFieldCount(), &aSymbol, + SIM_MODEL::DEVICE_TYPE_FIELD ); + deviceTypeField.SetText( + SIM_MODEL::DeviceInfo( SIM_MODEL::DEVICE_TYPE_::SPICE ).fieldValue ); + aSymbol.AddField( deviceTypeField ); + + SCH_FIELD paramsField( VECTOR2I( 0, 0 ), aSymbol.GetFieldCount(), &aSymbol, + SIM_MODEL::PARAMS_FIELD ); + paramsField.SetText( wxString::Format( "type=\"%s\" model=\"%s\" lib=\"%s\"", + spiceType, spiceModel, spiceLib ) ); + aSymbol.AddField( paramsField ); + + // Legacy models by default get linear pin mapping. + if( pinMap != "" ) + { + SCH_FIELD pinsField( VECTOR2I( 0, 0 ), aSymbol.GetFieldCount(), &aSymbol, + SIM_MODEL::PINS_FIELD ); + + pinsField.SetText( pinMap ); + aSymbol.AddField( pinsField ); + } + else + { + wxString pins; + + for( unsigned i = 0; i < aSymbol.GetLibPins().size(); ++i ) + { + if( i != 0 ) + pins.Append( " " ); + + pins.Append( wxString::Format( "%u=%u", i + 1, i + 1 ) ); + } + + SCH_FIELD pinsField( VECTOR2I( 0, 0 ), aSymbol.GetFieldCount(), &aSymbol, + SIM_MODEL::PINS_FIELD ); + pinsField.SetText( pins ); + aSymbol.AddField( pinsField ); + } +} diff --git a/eeschema/sch_screen.h b/eeschema/sch_screen.h index e3e093d60d..3f552eabac 100644 --- a/eeschema/sch_screen.h +++ b/eeschema/sch_screen.h @@ -515,14 +515,9 @@ public: #endif /** - * last value for the zoom level, useful in Eeschema when changing the current displayed - * sheet to reuse the same zoom level when back to the sheet using this screen + * Migrate any symbols having V6 simulation models to their V7 equivalents. */ - double m_LastZoomLevel; - -private: - bool doIsJunction( const VECTOR2I& aPosition, bool aBreakCrossings, - bool* aHasExplicitJunctionDot, bool* aHasBusEntry ) const; + void MigrateSimModels(); private: friend SCH_EDIT_FRAME; // Only to populate m_symbolInstances. @@ -530,8 +525,24 @@ private: friend SCH_SEXPR_PLUGIN; // Only to save the loaded instance information to schematic file. friend SCH_ALTIUM_PLUGIN; + bool doIsJunction( const VECTOR2I& aPosition, bool aBreakCrossings, + bool* aHasExplicitJunctionDot, bool* aHasBusEntry ) const; + void clearLibSymbols(); + /** + * Migrate the symbol's V6 simulation model SCH_FIELDs to their V7 equivalents + */ + void migrateSimModel( SCH_SYMBOL& aSymbol ); + +public: + /** + * last value for the zoom level, useful in Eeschema when changing the current displayed + * sheet to reuse the same zoom level when back to the sheet using this screen + */ + double m_LastZoomLevel; + +private: wxString m_fileName; // File used to load the screen. int m_fileFormatVersionAtLoad; int m_refCount; // Number of sheets referencing this screen. diff --git a/eeschema/sch_sheet_path.cpp b/eeschema/sch_sheet_path.cpp index fc778c3f50..acd4d61eca 100644 --- a/eeschema/sch_sheet_path.cpp +++ b/eeschema/sch_sheet_path.cpp @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -40,11 +39,6 @@ #include #include #include -#include "erc_item.h" - -#include // For V6 to V7 simulation model migration. -#include // -#include /** @@ -1096,7 +1090,7 @@ SCH_SHEET_LIST SCH_SHEET_LIST::FindAllSheetsForScreen( const SCH_SCREEN* aScreen } -void SCH_SHEET_LIST::UpdateSymbolInstances( +void SCH_SHEET_LIST::UpdateSymbolInstanceData( const std::vector& aSymbolInstances ) { for( SCH_SHEET_PATH& sheetPath : *this ) @@ -1111,10 +1105,10 @@ void SCH_SHEET_LIST::UpdateSymbolInstances( sheetPathWithSymbolUuid.push_back( symbol->m_Uuid ); auto it = std::find_if( aSymbolInstances.begin(), aSymbolInstances.end(), - [ sheetPathWithSymbolUuid ]( const SYMBOL_INSTANCE_REFERENCE& r ) -> bool - { - return sheetPathWithSymbolUuid == r.m_Path; - } ); + [ sheetPathWithSymbolUuid ]( const SYMBOL_INSTANCE_REFERENCE& r ) -> bool + { + return sheetPathWithSymbolUuid == r.m_Path; + } ); if( it == aSymbolInstances.end() ) { @@ -1131,13 +1125,10 @@ void SCH_SHEET_LIST::UpdateSymbolInstances( symbol->SetFootprintFieldText( it->m_Footprint ); } } - - if( size() >= 1 && at( 0 ).LastScreen()->GetFileFormatVersionAtLoad() < 20220622 ) - MigrateSimModelNameFields(); } -void SCH_SHEET_LIST::UpdateSheetInstances( const std::vector& aSheetInstances ) +void SCH_SHEET_LIST::UpdateSheetInstanceData( const std::vector& aSheetInstances ) { for( SCH_SHEET_PATH& path : *this ) @@ -1269,177 +1260,3 @@ int SCH_SHEET_LIST::GetLastVirtualPageNumber() const return lastVirtualPageNumber; } - -void SCH_SHEET_LIST::MigrateSimModelNameFields() -{ - LOCALE_IO toggle; - - for( unsigned sheetIndex = 0; sheetIndex < size(); ++sheetIndex ) - { - SCH_SCREEN* screen = at( sheetIndex ).LastScreen(); - - // V6 schematics may specify model names in Value fields, which we don't do in V7. - // Migrate by adding an equivalent model for these symbols. - - for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) ) - { - SCH_SYMBOL* symbol = static_cast( item ); - - if( !symbol ) - { - // Shouldn't happen. - wxFAIL; - continue; - } - - migrateSimModel( *symbol, sheetIndex ); - } - } -} - - -void SCH_SHEET_LIST::migrateSimModel( SCH_SYMBOL& aSymbol, unsigned aSheetIndex ) -{ - if( aSymbol.FindField( SIM_MODEL::DEVICE_TYPE_FIELD ) - || aSymbol.FindField( SIM_MODEL::TYPE_FIELD ) - || aSymbol.FindField( SIM_MODEL::PINS_FIELD ) - || aSymbol.FindField( SIM_MODEL::PARAMS_FIELD ) ) - { - // Has a V7 model field -- skip. - return; - } - - wxString ref = aSymbol.GetRef( &at( aSheetIndex ), true ); - wxString value = aSymbol.GetValueFieldText( true ); - - wxString spiceType; - wxString spiceModel; - wxString spiceLib; - wxString pinMap; - - if( aSymbol.FindField( "Spice_Primitive" ) - || aSymbol.FindField( "Spice_Node_Sequence" ) - || aSymbol.FindField( "Spice_Model" ) - || aSymbol.FindField( "Spice_Netlist_Enabled" ) - || aSymbol.FindField( "Spice_Lib_File" ) ) - { - if( SCH_FIELD* primitiveField = aSymbol.FindField( "Spice_Primitive" ) ) - { - spiceType = primitiveField->GetText(); - aSymbol.RemoveField( "Spice_Primitive" ); - } - - if( SCH_FIELD* nodeSequenceField = aSymbol.FindField( "Spice_Node_Sequence" ) ) - { - const wxString delimiters( "{:,; }" ); - const wxString& nodeSequence = nodeSequenceField->GetText(); - - if( nodeSequence != "" ) - { - wxStringTokenizer tkz( nodeSequence, delimiters ); - - for( long modelPinNumber = 1; tkz.HasMoreTokens(); ++modelPinNumber ) - { - long symbolPinNumber = 1; - tkz.GetNextToken().ToLong( &symbolPinNumber ); - - if( modelPinNumber != 1 ) - pinMap.Append( " " ); - - pinMap.Append( wxString::Format( "%ld=%ld", symbolPinNumber, modelPinNumber ) ); - } - } - - aSymbol.RemoveField( "Spice_Node_Sequence" ); - } - - if( SCH_FIELD* modelField = aSymbol.FindField( "Spice_Model" ) ) - { - spiceModel = modelField->GetText(); - aSymbol.RemoveField( "Spice_Model" ); - } - else - spiceModel = aSymbol.FindField( "Value" )->GetText(); - - if( SCH_FIELD* netlistEnabledField = aSymbol.FindField( "Spice_Netlist_Enabled" ) ) - { - wxString netlistEnabled = netlistEnabledField->GetText().Lower(); - - if( netlistEnabled.StartsWith( "0" ) - || netlistEnabled.StartsWith( "n" ) - || netlistEnabled.StartsWith( "f" ) ) - { - SCH_FIELD enableField( VECTOR2I( 0, 0 ), aSymbol.GetFieldCount(), &aSymbol, - SIM_MODEL::ENABLE_FIELD ); - } - } - - if( SCH_FIELD* libFileField = aSymbol.FindField( "Spice_Lib_File" ) ) - { - spiceLib = libFileField->GetText(); - aSymbol.RemoveField( "Spice_Lib_File" ); - } - } - else if( ref.StartsWith( "R" ) || ref.StartsWith( "L" ) || ref.StartsWith( "C" ) ) - { - wxRegEx passiveVal( - wxT( "^([0-9\\. ]+)([fFpPnNuUmMkKgGtTμµ𝛍𝜇𝝁 ]|M(e|E)(g|G))?([fFhHΩΩ𝛀𝛺𝝮]|ohm)?([-1-9 ]*)$" ) ); - - if( !passiveVal.Matches( value ) ) - return; - - wxString prefix( passiveVal.GetMatch( value, 1 ) ); - wxString unit( passiveVal.GetMatch( value, 2 ) ); - wxString suffix( passiveVal.GetMatch( value, 6 ) ); - - if( unit == "M" ) - unit = "Meg"; - - spiceModel = prefix + unit; - } - else if( ref.StartsWith( "V" ) || ref.StartsWith( "I" ) ) - spiceModel = value; - else - return; - - // Insert a plaintext model as a substitute. - - SCH_FIELD deviceTypeField( VECTOR2I( 0, 0 ), aSymbol.GetFieldCount(), &aSymbol, - SIM_MODEL::DEVICE_TYPE_FIELD ); - deviceTypeField.SetText( - SIM_MODEL::DeviceInfo( SIM_MODEL::DEVICE_TYPE_::SPICE ).fieldValue ); - aSymbol.AddField( deviceTypeField ); - - SCH_FIELD paramsField( VECTOR2I( 0, 0 ), aSymbol.GetFieldCount(), &aSymbol, - SIM_MODEL::PARAMS_FIELD ); - paramsField.SetText( wxString::Format( "type=\"%s\" model=\"%s\" lib=\"%s\"", - spiceType, spiceModel, spiceLib ) ); - aSymbol.AddField( paramsField ); - - // Legacy models by default get linear pin mapping. - if( pinMap != "" ) - { - SCH_FIELD pinsField( VECTOR2I( 0, 0 ), aSymbol.GetFieldCount(), &aSymbol, - SIM_MODEL::PINS_FIELD ); - - pinsField.SetText( pinMap ); - aSymbol.AddField( pinsField ); - } - else - { - wxString pins; - - for( unsigned i = 0; i < aSymbol.GetLibPins().size(); ++i ) - { - if( i != 0 ) - pins.Append( " " ); - - pins.Append( wxString::Format( "%u=%u", i + 1, i + 1 ) ); - } - - SCH_FIELD pinsField( VECTOR2I( 0, 0 ), aSymbol.GetFieldCount(), &aSymbol, - SIM_MODEL::PINS_FIELD ); - pinsField.SetText( pins ); - aSymbol.AddField( pinsField ); - } -} diff --git a/eeschema/sch_sheet_path.h b/eeschema/sch_sheet_path.h index 1f98a609e6..05e6948f7e 100644 --- a/eeschema/sch_sheet_path.h +++ b/eeschema/sch_sheet_path.h @@ -614,7 +614,7 @@ public: * WARNING: Do not call this on anything other than the full hierarchy. * @param aSymbolInstances is the symbol path information loaded from the root schematic. */ - void UpdateSymbolInstances( const std::vector& aSymbolInstances ); + void UpdateSymbolInstanceData( const std::vector& aSymbolInstances ); /** * Update all of the sheet instance information using \a aSheetInstances. @@ -623,7 +623,7 @@ public: * * @param aSymbolInstances is the symbol path information loaded from the root schematic. */ - void UpdateSheetInstances( const std::vector& aSheetInstances ); + void UpdateSheetInstanceData( const std::vector& aSheetInstances ); std::vector GetPaths() const; @@ -667,17 +667,7 @@ public: void RemoveSymbolInstances( const SCH_SHEET_PATH& aPrefixSheetPath ); - /** - * Migrate V6 simulator models to V7. Must be called only after UpdateSymbolInstances(). - */ - void MigrateSimModelNameFields(); - private: - /** - * Migrate a single V6 simulator model to V7. Must be called only after UpdateSymbolInstances(). - */ - void migrateSimModel( SCH_SYMBOL& aSymbol, unsigned aSheetIndex ); - SCH_SHEET_PATH m_currentSheetPath; }; diff --git a/eeschema/sheet.cpp b/eeschema/sheet.cpp index e351670994..926ec12a31 100644 --- a/eeschema/sheet.cpp +++ b/eeschema/sheet.cpp @@ -166,6 +166,9 @@ bool SCH_EDIT_FRAME::LoadSheetFromFile( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHier return false; } + if( newSheet->GetScreen()->GetFileFormatVersionAtLoad() < 20221206 ) + newSheet->GetScreen()->MigrateSimModels(); + // If the loaded schematic is in a different folder from the current project and // it contains hierarchical sheets, the hierarchical sheet paths need to be updated. if( fileName.GetPathWithSep() != Prj().GetProjectPath() && newSheet->CountSheets() ) @@ -498,7 +501,7 @@ bool SCH_EDIT_FRAME::LoadSheetFromFile( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHier { // If the loaded schematic is a root sheet for another project, update the symbol // instances. - sheetHierarchy.UpdateSymbolInstances( newScreen->GetSymbolInstances() ); + sheetHierarchy.UpdateSymbolInstanceData( newScreen->GetSymbolInstances()); } } diff --git a/eeschema/sim/sim_lib_mgr.cpp b/eeschema/sim/sim_lib_mgr.cpp index 80af5e0b58..a133c0c6a4 100644 --- a/eeschema/sim/sim_lib_mgr.cpp +++ b/eeschema/sim/sim_lib_mgr.cpp @@ -31,6 +31,8 @@ #include #include #include +#include + SIM_LIB_MGR::SIM_LIB_MGR( const PROJECT& aPrj ) : m_project( aPrj ) { @@ -109,6 +111,23 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const SCH_SHEET_PATH* aSheetPath, S fields.back().SetText( aSymbol.GetFields()[ i ].GetShownText( 0, false ) ); } + // Infer RLC passive models if they aren't specified + if( !aSymbol.FindField( SIM_MODEL::DEVICE_TYPE_FIELD, false ) + && !aSymbol.FindField( SIM_MODEL::PARAMS_FIELD, false ) ) + { + wxString simParams = SIM_MODEL_IDEAL::InferSimParams( aSymbol.GetPrefix(), + aSymbol.GetValueFieldText( true ) ); + + if( !simParams.IsEmpty() ) + { + fields.emplace_back( VECTOR2I(), -1, &aSymbol, SIM_MODEL::DEVICE_TYPE_FIELD ); + fields.back().SetText( aSymbol.GetPrefix() ); + + fields.emplace_back( VECTOR2I(), -1, &aSymbol, SIM_MODEL::PARAMS_FIELD ); + fields.back().SetText( simParams ); + } + } + return CreateModel( fields, static_cast( aSymbol.GetRawPins().size() ) ); } diff --git a/eeschema/sim/sim_model_ideal.cpp b/eeschema/sim/sim_model_ideal.cpp index ed5eb08e7f..2e5857dd1d 100644 --- a/eeschema/sim/sim_model_ideal.cpp +++ b/eeschema/sim/sim_model_ideal.cpp @@ -26,7 +26,7 @@ #include #include #include - +#include std::string SPICE_GENERATOR_IDEAL::ModelLine( const SPICE_ITEM& aItem ) const { @@ -73,6 +73,39 @@ SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType ) : } +wxString SIM_MODEL_IDEAL::InferSimParams( const wxString& aPrefix, const wxString& aValue ) +{ + wxString spiceModel; + + if( aPrefix == wxT( "R" ) || aPrefix == wxT( "L" ) || aPrefix == wxT( "C" ) ) + { + wxRegEx passiveVal( + wxT( "^([0-9\\. ]+)([fFpPnNuUmMkKgGtTμµ𝛍𝜇𝝁 ]|M(e|E)(g|G))?([fFhHΩΩ𝛀𝛺𝝮]|ohm)?([-1-9 ]*)$" ) ); + + if( passiveVal.Matches( aValue ) ) + { + wxString valuePrefix( passiveVal.GetMatch( aValue, 1 ) ); + wxString valueUnits( passiveVal.GetMatch( aValue, 2 ) ); + wxString valueSuffix( passiveVal.GetMatch( aValue, 6 ) ); + + if( valueUnits == "M" ) + valueUnits = "Meg"; + + spiceModel = valuePrefix + valueUnits; + } + else + { + spiceModel = aValue; + } + } + + if( !spiceModel.IsEmpty() ) + return wxString::Format( wxT( "%s=\"%s\"" ), aPrefix.Lower(), spiceModel ); + else + return wxEmptyString; +} + + SIM_MODEL::PARAM::INFO SIM_MODEL_IDEAL::makeParamInfo( std::string aName, std::string aDescription, std::string aUnit ) { diff --git a/eeschema/sim/sim_model_ideal.h b/eeschema/sim/sim_model_ideal.h index 2cd57d2a8a..1c97af0c1f 100644 --- a/eeschema/sim/sim_model_ideal.h +++ b/eeschema/sim/sim_model_ideal.h @@ -49,6 +49,8 @@ public: const PARAM* GetTunerParam() const override { return &GetParam( 0 ); } bool HasPrimaryValue() const override { return true; } + static wxString InferSimParams( const wxString& aPrefix, const wxString& aValue ); + private: std::vector getPinNames() const override { return { "+", "-" }; } diff --git a/qa/schematic_utils/schematic_file_util.cpp b/qa/schematic_utils/schematic_file_util.cpp index 5396e48c20..86324663ff 100644 --- a/qa/schematic_utils/schematic_file_util.cpp +++ b/qa/schematic_utils/schematic_file_util.cpp @@ -108,7 +108,7 @@ std::unique_ptr ReadSchematicFromFile( const std::string& aFilename, void LoadSchematic( SETTINGS_MANAGER& aSettingsManager, const wxString& aRelPath, - std::unique_ptr& aSchematic ) + std::unique_ptr& aSchematic ) { if( aSchematic ) { @@ -140,13 +140,18 @@ void LoadSchematic( SETTINGS_MANAGER& aSettingsManager, const wxString& aRelPath SCH_SCREENS screens( aSchematic->Root() ); for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() ) + { screen->UpdateLocalLibSymbolLinks(); + if( aSchematic->RootScreen()->GetFileFormatVersionAtLoad() < 20221206 ) + screen->MigrateSimModels(); + } + SCH_SHEET_LIST sheets = aSchematic->GetSheets(); // Restore all of the loaded symbol instances from the root sheet screen. - sheets.UpdateSymbolInstances( aSchematic->RootScreen()->GetSymbolInstances() ); - sheets.UpdateSheetInstances( aSchematic->RootScreen()->GetSheetInstances() ); + sheets.UpdateSymbolInstanceData( aSchematic->RootScreen()->GetSymbolInstances() ); + sheets.UpdateSheetInstanceData( aSchematic->RootScreen()->GetSheetInstances() ); sheets.AnnotatePowerSymbols(); diff --git a/qa/unittests/eeschema/eeschema_test_utils.cpp b/qa/unittests/eeschema/eeschema_test_utils.cpp index 9ac097bfbc..100b0cc19a 100644 --- a/qa/unittests/eeschema/eeschema_test_utils.cpp +++ b/qa/unittests/eeschema/eeschema_test_utils.cpp @@ -87,16 +87,21 @@ void KI_TEST::SCHEMATIC_TEST_FIXTURE::LoadSchematic( const wxString& aBaseName ) SCH_SCREENS screens( m_schematic.Root() ); for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() ) + { screen->UpdateLocalLibSymbolLinks(); + if( m_schematic.RootScreen()->GetFileFormatVersionAtLoad() < 20221206 ) + screen->MigrateSimModels(); + } + SCH_SHEET_LIST sheets = m_schematic.GetSheets(); // Restore all of the loaded symbol instances from the root sheet screen. if( m_schematic.RootScreen()->GetFileFormatVersionAtLoad() < 20221002 ) - sheets.UpdateSymbolInstances( m_schematic.RootScreen()->GetSymbolInstances() ); + sheets.UpdateSymbolInstanceData( m_schematic.RootScreen()->GetSymbolInstances()); if( m_schematic.RootScreen()->GetFileFormatVersionAtLoad() < 20221110 ) - sheets.UpdateSheetInstances( m_schematic.RootScreen()->GetSheetInstances() ); + sheets.UpdateSheetInstanceData( m_schematic.RootScreen()->GetSheetInstances()); sheets.AnnotatePowerSymbols();