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.
This commit is contained in:
Jeff Young 2022-12-06 14:00:11 +00:00
parent f8e0a272c0
commit 38906397d2
16 changed files with 300 additions and 228 deletions

View File

@ -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 )

View File

@ -87,12 +87,17 @@ static std::unique_ptr<SCHEMATIC> 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();

View File

@ -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();

View File

@ -447,14 +447,19 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& 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();

View File

@ -27,6 +27,7 @@
#include "netlist_exporter_spice.h"
#include <sim/sim_library_spice.h>
#include <sim/sim_model_raw_spice.h>
#include <sim/sim_model_ideal.h>
#include <sim/spice_grammar.h>
#include <common.h>
#include <confirm.h>
@ -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 ) )

View File

@ -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

View File

@ -52,6 +52,9 @@
#include <schematic.h>
#include <symbol_lib_table.h>
#include <tool/common_tools.h>
#include <sim/sim_model.h> // For V6 to V7 simulation model migration.
#include <sim/sim_value.h> //
#include <locale_io.h>
#include <algorithm>
@ -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<SCH_SYMBOL*>( 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 );
}
}

View File

@ -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.

View File

@ -32,7 +32,6 @@
#include <sch_sheet_path.h>
#include <sch_symbol.h>
#include <sch_sheet.h>
#include <sch_textbox.h>
#include <schematic.h>
#include <template_fieldnames.h>
#include <trace_helpers.h>
@ -40,11 +39,6 @@
#include <boost/functional/hash.hpp>
#include <wx/filename.h>
#include <wx/log.h>
#include "erc_item.h"
#include <sim/sim_model.h> // For V6 to V7 simulation model migration.
#include <sim/sim_value.h> //
#include <locale_io.h>
/**
@ -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<SYMBOL_INSTANCE_REFERENCE>& 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<SCH_SHEET_INSTANCE>& aSheetInstances )
void SCH_SHEET_LIST::UpdateSheetInstanceData( const std::vector<SCH_SHEET_INSTANCE>& 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<SCH_SYMBOL*>( 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 );
}
}

View File

@ -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<SYMBOL_INSTANCE_REFERENCE>& aSymbolInstances );
void UpdateSymbolInstanceData( const std::vector<SYMBOL_INSTANCE_REFERENCE>& 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<SCH_SHEET_INSTANCE>& aSheetInstances );
void UpdateSheetInstanceData( const std::vector<SCH_SHEET_INSTANCE>& aSheetInstances );
std::vector<KIID_PATH> 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;
};

View File

@ -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());
}
}

View File

@ -31,6 +31,8 @@
#include <sim/sim_lib_mgr.h>
#include <sim/sim_library.h>
#include <sim/sim_model.h>
#include <sim/sim_model_ideal.h>
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<int>( aSymbol.GetRawPins().size() ) );
}

View File

@ -26,7 +26,7 @@
#include <pegtl.hpp>
#include <pegtl/contrib/parse_tree.hpp>
#include <fmt/core.h>
#include <wx/regex.h>
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 )
{

View File

@ -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<std::string> getPinNames() const override { return { "+", "-" }; }

View File

@ -108,7 +108,7 @@ std::unique_ptr<SCHEMATIC> ReadSchematicFromFile( const std::string& aFilename,
void LoadSchematic( SETTINGS_MANAGER& aSettingsManager, const wxString& aRelPath,
std::unique_ptr<SCHEMATIC>& aSchematic )
std::unique_ptr<SCHEMATIC>& 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();

View File

@ -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();