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_BASE( aSchematic ),
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 )
{
auto [modelName, model] = m_libMgr.CreateModel( aSymbol );
aItem.modelName = ( modelName != "" ) ? modelName : ( "__" + aItem.refName );
auto [baseModelName, model] = m_libMgr.CreateModel( aSymbol );
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 ) )
{
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 ) )
{
aItem.modelName = aItem.model->GetFieldValue( &aSymbol.GetFields(),
SIM_LIBRARY_KIBIS::MODEL_FIELD );
wxFileName cacheDir;
cacheDir.AssignDir( PATHS::GetUserCachePath() );
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() );
std::string modelData = spiceGenerator.IbisDevice( aSymbol.GetFields() );
std::string modelData = spiceGenerator.IbisDevice( aSymbol.GetFields(), aItem.modelName );
cacheFile.Write( wxString( modelData ) );
m_rawIncludes.insert( libraryPath );

View File

@ -32,6 +32,16 @@
#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
{
public:
@ -141,13 +151,15 @@ private:
void writeModels( OUTPUTFORMATTER& aFormatter );
void writeItems( OUTPUTFORMATTER& aFormatter );
SIM_LIB_MGR m_libMgr; ///< Holds libraries and models
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
SIM_LIB_MGR m_libMgr; ///< Holds libraries and models
NAME_GENERATOR m_modelNameGenerator; ///< Generates unique model names
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::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::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>
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
{
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 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() )
{
case SIM_MODEL::TYPE::KIBIS_DEVICE:
kpin->writeSpiceDevice( &result, ibisModelName, *kmodel, kparams );
kpin->writeSpiceDevice( &result, aModelName, *kmodel, kparams );
break;
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() );
}
kpin->writeSpiceDriver( &result, ibisModelName, *kmodel, kparams );
kpin->writeSpiceDriver( &result, aModelName, *kmodel, kparams );
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 );
kparams.m_waveform = waveform;
kpin->writeSpiceDriver( &result, ibisModelName, *kmodel, kparams );
kpin->writeSpiceDriver( &result, aModelName, *kmodel, kparams );
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 );
kparams.m_waveform = waveform;
kpin->writeSpiceDriver( &result, ibisModelName, *kmodel, kparams );
kpin->writeSpiceDriver( &result, aModelName, *kmodel, kparams );
break;
}

View File

@ -37,10 +37,13 @@ class SPICE_GENERATOR_KIBIS : public SPICE_GENERATOR
public:
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::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:
std::vector<std::reference_wrapper<const SIM_MODEL::PARAM>> GetInstanceParams() const override;

View File

@ -29,6 +29,20 @@
#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
{
if( !m_model.HasSpiceNonInstanceOverrides() && !m_model.requiresSpiceModelLine() )

View File

@ -34,6 +34,8 @@ public:
SPICE_GENERATOR( const SIM_MODEL& aModel ) : m_model( aModel ) {}
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;
std::string ItemLine( const std::string& aRefName,