Sim: Resolve name collisions for generated model names

This commit is contained in:
Mikolaj Wielgus 2022-10-10 13:35:18 +02:00
parent b2f05c758b
commit 4931b80066
6 changed files with 77 additions and 18 deletions

View File

@ -75,6 +75,25 @@ namespace NETLIST_EXPORTER_SPICE_PARSER
} }
std::string NAME_GENERATOR::Generate( const std::string& aProposedName )
{
if( !m_names.count( aProposedName ) )
return aProposedName;
for( uint64_t i = 1; i < UINT64_MAX; ++i )
{
std::string name = fmt::format( "{}#{}", aProposedName, i );
if( !m_names.count( name ) )
return name;
}
// Should never happen.
THROW_IO_ERROR( wxString::Format( _( "Failed to generate a name for '%s': exceeded UINT64_MAX" ),
aProposedName ) );
}
NETLIST_EXPORTER_SPICE::NETLIST_EXPORTER_SPICE( SCHEMATIC_IFACE* aSchematic ) : NETLIST_EXPORTER_SPICE::NETLIST_EXPORTER_SPICE( SCHEMATIC_IFACE* aSchematic ) :
NETLIST_EXPORTER_BASE( aSchematic ), NETLIST_EXPORTER_BASE( aSchematic ),
m_libMgr( aSchematic->Prj() ) m_libMgr( aSchematic->Prj() )
@ -322,11 +341,15 @@ bool NETLIST_EXPORTER_SPICE::readRefName( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aS
void NETLIST_EXPORTER_SPICE::readModel( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aSymbol, ITEM& aItem ) void NETLIST_EXPORTER_SPICE::readModel( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aSymbol, ITEM& aItem )
{ {
auto [modelName, model] = m_libMgr.CreateModel( aSymbol ); auto [baseModelName, model] = m_libMgr.CreateModel( aSymbol );
aItem.modelName = ( modelName != "" ) ? modelName : ( "__" + aItem.refName );
aItem.model = &model; aItem.model = &model;
// FIXME: Special cases for raw Spice models and KIBIS. std::string modelName = aItem.model->SpiceGenerator().ModelName( aItem.refName,
baseModelName );
// Resolve model name collisions.
aItem.modelName = m_modelNameGenerator.Generate( modelName );
// FIXME: Don't have special cases for raw Spice models and KIBIS.
if( auto rawSpiceModel = dynamic_cast<const SIM_MODEL_RAW_SPICE*>( aItem.model ) ) if( auto rawSpiceModel = dynamic_cast<const SIM_MODEL_RAW_SPICE*>( aItem.model ) )
{ {
int libParamIndex = static_cast<int>( SIM_MODEL_RAW_SPICE::SPICE_PARAM::LIB ); int libParamIndex = static_cast<int>( SIM_MODEL_RAW_SPICE::SPICE_PARAM::LIB );
@ -337,9 +360,6 @@ void NETLIST_EXPORTER_SPICE::readModel( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aSym
} }
else if( auto kibisModel = dynamic_cast<const SIM_MODEL_KIBIS*>( aItem.model ) ) else if( auto kibisModel = dynamic_cast<const SIM_MODEL_KIBIS*>( aItem.model ) )
{ {
aItem.modelName = aItem.model->GetFieldValue( &aSymbol.GetFields(),
SIM_LIBRARY_KIBIS::MODEL_FIELD );
wxFileName cacheDir; wxFileName cacheDir;
cacheDir.AssignDir( PATHS::GetUserCachePath() ); cacheDir.AssignDir( PATHS::GetUserCachePath() );
cacheDir.AppendDir( wxT( "ibis" ) ); cacheDir.AppendDir( wxT( "ibis" ) );
@ -357,7 +377,7 @@ void NETLIST_EXPORTER_SPICE::readModel( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aSym
} }
auto spiceGenerator = static_cast<const SPICE_GENERATOR_KIBIS&>( kibisModel->SpiceGenerator() ); auto spiceGenerator = static_cast<const SPICE_GENERATOR_KIBIS&>( kibisModel->SpiceGenerator() );
std::string modelData = spiceGenerator.IbisDevice( aSymbol.GetFields() ); std::string modelData = spiceGenerator.IbisDevice( aSymbol.GetFields(), aItem.modelName );
cacheFile.Write( wxString( modelData ) ); cacheFile.Write( wxString( modelData ) );
m_rawIncludes.insert( libraryPath ); m_rawIncludes.insert( libraryPath );

View File

@ -32,6 +32,16 @@
#include <sim/sim_model.h> #include <sim/sim_model.h>
class NAME_GENERATOR
{
public:
std::string Generate( const std::string& aProposedName );
private:
std::unordered_set<std::string> m_names;
};
class NETLIST_EXPORTER_SPICE : public NETLIST_EXPORTER_BASE class NETLIST_EXPORTER_SPICE : public NETLIST_EXPORTER_BASE
{ {
public: public:
@ -141,13 +151,15 @@ private:
void writeModels( OUTPUTFORMATTER& aFormatter ); void writeModels( OUTPUTFORMATTER& aFormatter );
void writeItems( OUTPUTFORMATTER& aFormatter ); void writeItems( OUTPUTFORMATTER& aFormatter );
SIM_LIB_MGR m_libMgr; ///< Holds libraries and models SIM_LIB_MGR m_libMgr; ///< Holds libraries and models
std::string m_title; ///< Spice simulation title found in the schematic sheet NAME_GENERATOR m_modelNameGenerator; ///< Generates unique model names
std::vector<std::string> m_directives; ///< Spice directives found in the schematic sheet NAME_GENERATOR m_netNameGenerator; ///< Generates unique net names (only unique for NC nets for now)
std::string m_title; ///< Spice simulation title found in the schematic sheet
std::vector<std::string> m_directives; ///< Spice directives found in the schematic sheet
//std::map<std::string, std::unique_ptr<SIM_LIBRARY>> m_libraries; ///< Spice libraries //std::map<std::string, std::unique_ptr<SIM_LIBRARY>> m_libraries; ///< Spice libraries
std::set<std::string> m_rawIncludes; ///< include directives found in symbols std::set<std::string> m_rawIncludes; ///< include directives found in symbols
std::set<std::string> m_nets; std::set<std::string> m_nets;
std::list<ITEM> m_items; ///< Items representing schematic symbols in Spice world std::list<ITEM> m_items; ///< Items representing schematic symbols in Spice world
}; };

View File

@ -28,6 +28,13 @@
#include <fmt/core.h> #include <fmt/core.h>
std::string SPICE_GENERATOR_KIBIS::ModelName( const std::string& aRefName,
const std::string& aBaseModelName ) const
{
return fmt::format( "{}.{}", aRefName, aBaseModelName );
}
std::string SPICE_GENERATOR_KIBIS::ModelLine( const std::string& aModelName ) const std::string SPICE_GENERATOR_KIBIS::ModelLine( const std::string& aModelName ) const
{ {
return ""; return "";
@ -51,7 +58,8 @@ std::vector<std::string> SPICE_GENERATOR_KIBIS::CurrentNames( const std::string&
} }
std::string SPICE_GENERATOR_KIBIS::IbisDevice( const std::vector<SCH_FIELD>& aFields ) const std::string SPICE_GENERATOR_KIBIS::IbisDevice( const std::vector<SCH_FIELD>& aFields,
const std::string& aModelName ) const
{ {
std::string ibisLibFilename = SIM_MODEL::GetFieldValue( &aFields, SIM_LIBRARY::LIBRARY_FIELD ); std::string ibisLibFilename = SIM_MODEL::GetFieldValue( &aFields, SIM_LIBRARY::LIBRARY_FIELD );
std::string ibisCompName = SIM_MODEL::GetFieldValue( &aFields, SIM_LIBRARY::NAME_FIELD ); std::string ibisCompName = SIM_MODEL::GetFieldValue( &aFields, SIM_LIBRARY::NAME_FIELD );
@ -101,7 +109,7 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const std::vector<SCH_FIELD>& aFi
switch( m_model.GetType() ) switch( m_model.GetType() )
{ {
case SIM_MODEL::TYPE::KIBIS_DEVICE: case SIM_MODEL::TYPE::KIBIS_DEVICE:
kpin->writeSpiceDevice( &result, ibisModelName, *kmodel, kparams ); kpin->writeSpiceDevice( &result, aModelName, *kmodel, kparams );
break; break;
case SIM_MODEL::TYPE::KIBIS_DRIVER_DC: case SIM_MODEL::TYPE::KIBIS_DRIVER_DC:
@ -124,7 +132,7 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const std::vector<SCH_FIELD>& aFi
static_cast<KIBIS_WAVEFORM*>( new KIBIS_WAVEFORM_STUCK_HIGH() ); static_cast<KIBIS_WAVEFORM*>( new KIBIS_WAVEFORM_STUCK_HIGH() );
} }
kpin->writeSpiceDriver( &result, ibisModelName, *kmodel, kparams ); kpin->writeSpiceDriver( &result, aModelName, *kmodel, kparams );
break; break;
} }
@ -137,7 +145,7 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const std::vector<SCH_FIELD>& aFi
waveform->m_delay = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "delay" )->value ).Get().value_or( 0 ); waveform->m_delay = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "delay" )->value ).Get().value_or( 0 );
kparams.m_waveform = waveform; kparams.m_waveform = waveform;
kpin->writeSpiceDriver( &result, ibisModelName, *kmodel, kparams ); kpin->writeSpiceDriver( &result, aModelName, *kmodel, kparams );
break; break;
} }
@ -150,7 +158,7 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const std::vector<SCH_FIELD>& aFi
waveform->m_delay = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "delay" )->value ).Get().value_or( 0 ); waveform->m_delay = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "delay" )->value ).Get().value_or( 0 );
kparams.m_waveform = waveform; kparams.m_waveform = waveform;
kpin->writeSpiceDriver( &result, ibisModelName, *kmodel, kparams ); kpin->writeSpiceDriver( &result, aModelName, *kmodel, kparams );
break; break;
} }

View File

@ -37,10 +37,13 @@ class SPICE_GENERATOR_KIBIS : public SPICE_GENERATOR
public: public:
using SPICE_GENERATOR::SPICE_GENERATOR; using SPICE_GENERATOR::SPICE_GENERATOR;
std::string ModelName( const std::string& aRefName,
const std::string& aBaseModelName ) const override;
std::string ModelLine( const std::string& aModelName ) const override; std::string ModelLine( const std::string& aModelName ) const override;
std::vector<std::string> CurrentNames( const std::string& aRefName ) const override; std::vector<std::string> CurrentNames( const std::string& aRefName ) const override;
std::string IbisDevice( const std::vector<SCH_FIELD>& aFields ) const; std::string IbisDevice( const std::vector<SCH_FIELD>& aFields,
const std::string& aModelName ) const;
protected: protected:
std::vector<std::reference_wrapper<const SIM_MODEL::PARAM>> GetInstanceParams() const override; std::vector<std::reference_wrapper<const SIM_MODEL::PARAM>> GetInstanceParams() const override;

View File

@ -29,6 +29,20 @@
#include <fmt/core.h> #include <fmt/core.h>
std::string SPICE_GENERATOR::ModelName( const std::string& aRefName,
const std::string& aBaseModelName ) const
{
if( aBaseModelName == "" )
return fmt::format( "__{}", aRefName );
// FIXME: This ModelLine() call is relatively expensive.
if( ModelLine( aBaseModelName ) != "" )
return fmt::format( "{}.{}", aRefName, aBaseModelName );
return aBaseModelName;
}
std::string SPICE_GENERATOR::ModelLine( const std::string& aModelName ) const std::string SPICE_GENERATOR::ModelLine( const std::string& aModelName ) const
{ {
if( !m_model.HasSpiceNonInstanceOverrides() && !m_model.requiresSpiceModelLine() ) if( !m_model.HasSpiceNonInstanceOverrides() && !m_model.requiresSpiceModelLine() )

View File

@ -34,6 +34,8 @@ public:
SPICE_GENERATOR( const SIM_MODEL& aModel ) : m_model( aModel ) {} SPICE_GENERATOR( const SIM_MODEL& aModel ) : m_model( aModel ) {}
virtual ~SPICE_GENERATOR() = default; virtual ~SPICE_GENERATOR() = default;
virtual std::string ModelName( const std::string& aRefName,
const std::string& aBaseModelName ) const;
virtual std::string ModelLine( const std::string& aModelName ) const; virtual std::string ModelLine( const std::string& aModelName ) const;
std::string ItemLine( const std::string& aRefName, std::string ItemLine( const std::string& aRefName,