From 38906397d2a31f2721faebfa0e3e509db206a003 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Tue, 6 Dec 2022 14:00:11 +0000 Subject: [PATCH] Move V6->V7 sim model migration from sheets to screens. Also moves passive RLC inference out from migration to just-in-time creation for the simulator or netlisting. Also fixes a version guard mismatch because the spice migration was done inside UpdateSymbolInstances (which has its own version guard). Also changed UpdateSymbolInstances to UpdateSymbolInstanceData so someone else in the future doesn't think it's a general-purpose symbol instance updater. --- eeschema/dialogs/dialog_sheet_properties.cpp | 6 +- eeschema/eeschema.cpp | 7 +- eeschema/eeschema_helpers.cpp | 16 +- eeschema/files-io.cpp | 9 +- .../netlist_exporter_spice.cpp | 18 ++ eeschema/sch_file_versions.h | 3 +- eeschema/sch_screen.cpp | 154 ++++++++++++++ eeschema/sch_screen.h | 25 ++- eeschema/sch_sheet_path.cpp | 195 +----------------- eeschema/sch_sheet_path.h | 14 +- eeschema/sheet.cpp | 5 +- eeschema/sim/sim_lib_mgr.cpp | 19 ++ eeschema/sim/sim_model_ideal.cpp | 35 +++- eeschema/sim/sim_model_ideal.h | 2 + qa/schematic_utils/schematic_file_util.cpp | 11 +- qa/unittests/eeschema/eeschema_test_utils.cpp | 9 +- 16 files changed, 300 insertions(+), 228 deletions(-) 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();