Sim: Use the new library manager class in Spice netlist exporter

Temporarily comment out IBIS processing.
This commit is contained in:
Mikolaj Wielgus 2022-10-06 09:47:03 +02:00
parent 0a620816a8
commit b95f4ec6bb
5 changed files with 103 additions and 144 deletions

View File

@ -74,6 +74,13 @@ namespace NETLIST_EXPORTER_SPICE_PARSER
}
NETLIST_EXPORTER_SPICE::NETLIST_EXPORTER_SPICE( SCHEMATIC_IFACE* aSchematic ) :
NETLIST_EXPORTER_BASE( aSchematic ),
m_libMgr( aSchematic->Prj() )
{
}
bool NETLIST_EXPORTER_SPICE::WriteNetlist( const wxString& aOutFileName, unsigned aNetlistOptions )
{
FILE_OUTPUTFORMATTER formatter( aOutFileName, wxT( "wt" ), '\'' );
@ -181,7 +188,7 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
ITEM spiceItem;
// @TODO This is to be removed once ngspice gets ibis support
if( SIM_MODEL::GetFieldValue( &( symbol->GetFields() ), SIM_MODEL::DEVICE_TYPE_FIELD )
/*if( SIM_MODEL::GetFieldValue( &( symbol->GetFields() ), SIM_MODEL::DEVICE_TYPE_FIELD )
== "IBIS" )
{
if( !readRefName( sheet, *symbol, spiceItem, refNames ) )
@ -433,23 +440,26 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
m_items.push_back( std::move( spiceItem ) );
continue;
}*/
try
{
if( !readRefName( sheet, *symbol, spiceItem, refNames ) )
return false;
readModel( *symbol, spiceItem );
readPinNumbers( *symbol, spiceItem );
readPinNetNames( *symbol, spiceItem, ncCounter );
// TODO: transmission line handling?
m_items.push_back( std::move( spiceItem ) );
}
catch( const IO_ERROR& e )
{
DisplayErrorMessage( nullptr, e.What() );
}
if( !readRefName( sheet, *symbol, spiceItem, refNames ) )
return false;
readLibraryField( *symbol, spiceItem );
readNameField( *symbol, spiceItem );
if( !readModel( *symbol, spiceItem ) )
continue;
readPinNumbers( *symbol, spiceItem );
readPinNetNames( *symbol, spiceItem, ncCounter );
// TODO: transmission line handling?
m_items.push_back( std::move( spiceItem ) );
}
}
@ -528,7 +538,7 @@ void NETLIST_EXPORTER_SPICE::ReadDirectives( unsigned aNetlistOptions )
try
{
m_libraries.try_emplace( path, SIM_LIBRARY::Create( path ) );
m_libMgr.CreateLibrary( path );
}
catch( const IO_ERROR& e )
{
@ -545,72 +555,6 @@ void NETLIST_EXPORTER_SPICE::ReadDirectives( unsigned aNetlistOptions )
}
void NETLIST_EXPORTER_SPICE::readLibraryField( SCH_SYMBOL& aSymbol, ITEM& aItem )
{
SCH_FIELD* field = aSymbol.FindField( SIM_LIBRARY::LIBRARY_FIELD );
std::string path;
if( field )
path = std::string( field->GetShownText().ToUTF8() );
if( path == "" )
return;
wxString absolutePath = m_schematic->Prj().AbsolutePath( path );
try
{
m_libraries.try_emplace( path, SIM_LIBRARY::Create( std::string( absolutePath.ToUTF8() ) ) );
}
catch( const IO_ERROR& e )
{
DisplayErrorMessage( nullptr, wxString::Format( "Failed reading model library '%s'.",
absolutePath ),
e.What() );
}
aItem.libraryPath = path;
}
void NETLIST_EXPORTER_SPICE::readNameField( SCH_SYMBOL& aSymbol, ITEM& aItem )
{
if( m_libraries.count( aItem.libraryPath ) )
{
SCH_FIELD* field = aSymbol.FindField( SIM_LIBRARY::NAME_FIELD );
if( !field )
return;
std::string modelName = std::string( field->GetShownText().ToUTF8() );
const SIM_LIBRARY& library = *m_libraries.at( aItem.libraryPath );
const SIM_MODEL* baseModel = library.FindModel( modelName );
if( baseModel )
{
try
{
aItem.model = SIM_MODEL::Create( *baseModel,
m_sortedSymbolPinList.size(),
aSymbol.GetFields() );
}
catch( const IO_ERROR& e )
{
DisplayErrorMessage( nullptr,
wxString::Format( "Failed reading %s simulation model.", aItem.refName ),
e.What() );
return;
}
aItem.modelName = modelName;
return;
}
}
else
aItem.modelName = "__" + aItem.refName;
}
bool NETLIST_EXPORTER_SPICE::readRefName( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aSymbol,
ITEM& aItem,
std::set<std::string>& aRefNames )
@ -630,35 +574,20 @@ bool NETLIST_EXPORTER_SPICE::readRefName( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aS
}
bool NETLIST_EXPORTER_SPICE::readModel( SCH_SYMBOL& aSymbol, ITEM& aItem )
void NETLIST_EXPORTER_SPICE::readModel( SCH_SYMBOL& aSymbol, ITEM& aItem )
{
if( !aItem.model.get() )
{
try
{
aItem.model = SIM_MODEL::Create(
static_cast<int>( m_sortedSymbolPinList.size() ), aSymbol.GetFields() );
}
catch( const IO_ERROR& e )
{
DisplayErrorMessage( nullptr,
wxString::Format( _( "Failed reading %s simulation model." ), aItem.refName ),
e.What() );
return false;
}
}
auto [modelName, model] = m_libMgr.CreateModel( aSymbol );
aItem.modelName = ( modelName != "" ) ? modelName : ( "__" + aItem.refName );
aItem.model = &model;
// Special case for legacy models.
if( auto model = dynamic_cast<const SIM_MODEL_RAW_SPICE*>( aItem.model.get() ) )
if( auto rawSpiceModel = dynamic_cast<const SIM_MODEL_RAW_SPICE*>( aItem.model ) )
{
unsigned libParamIndex = static_cast<unsigned>( SIM_MODEL_RAW_SPICE::SPICE_PARAM::LIB );
std::string path = model->GetParam( libParamIndex ).value->ToString();
int libParamIndex = static_cast<int>( SIM_MODEL_RAW_SPICE::SPICE_PARAM::LIB );
std::string path = rawSpiceModel->GetParam( libParamIndex ).value->ToString();
if( path != "" )
m_rawIncludes.insert( path );
}
return true;
}
@ -713,7 +642,7 @@ void NETLIST_EXPORTER_SPICE::writeInclude( OUTPUTFORMATTER& aFormatter, unsigned
void NETLIST_EXPORTER_SPICE::writeIncludes( OUTPUTFORMATTER& aFormatter, unsigned aNetlistOptions )
{
for( auto&& [path, library] : m_libraries )
for( auto&& [path, library] : m_libMgr.GetLibraries() )
writeInclude( aFormatter, aNetlistOptions, path );
for( const std::string& path : m_rawIncludes )

View File

@ -27,8 +27,9 @@
#define NETLIST_EXPORTER_SPICE_H
#include "netlist_exporter_base.h"
#include <sim/sim_model.h>
#include <sim/sim_lib_mgr.h>
#include <sim/sim_library.h>
#include <sim/sim_model.h>
class NETLIST_EXPORTER_SPICE : public NETLIST_EXPORTER_BASE
@ -53,11 +54,11 @@ public:
std::string libraryPath;
std::vector<std::string> pinNumbers;
std::vector<std::string> pinNetNames;
std::unique_ptr<const SIM_MODEL> model;
const SIM_MODEL* model;
std::string modelName;
};
NETLIST_EXPORTER_SPICE( SCHEMATIC_IFACE* aSchematic ) : NETLIST_EXPORTER_BASE( aSchematic ) {}
NETLIST_EXPORTER_SPICE( SCHEMATIC_IFACE* aSchematic );
/**
* Write to specified output file.
@ -128,12 +129,9 @@ protected:
SCH_SHEET_LIST GetSheets( unsigned aNetlistOptions = 0 ) const;
private:
void readLibraryField( SCH_SYMBOL& aSymbol, ITEM& aItem );
void readNameField( SCH_SYMBOL& aSymbol, ITEM& aItem );
void readEnabledField( SCH_SYMBOL& aSymbol, ITEM& aItem );
bool readRefName( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aSymbol, ITEM& aItem,
std::set<std::string>& aRefNames );
bool readModel( SCH_SYMBOL& aSymbol, ITEM& aItem );
void readModel( SCH_SYMBOL& aSymbol, ITEM& aItem );
void readPinNumbers( SCH_SYMBOL& aSymbol, ITEM& aItem );
void readPinNetNames( SCH_SYMBOL& aSymbol, ITEM& aItem, int& aNcCounter );
@ -144,12 +142,13 @@ 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
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_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

@ -27,6 +27,7 @@
#include <sim/sim_library.h>
#include <sim/sim_model.h>
#include <pgm_base.h>
#include <string>
SIM_LIB_MGR::SIM_LIB_MGR( const PROJECT& aPrj ) : m_project( aPrj )
@ -34,10 +35,11 @@ SIM_LIB_MGR::SIM_LIB_MGR( const PROJECT& aPrj ) : m_project( aPrj )
}
SIM_MODEL& SIM_LIB_MGR::CreateModel( SCH_SYMBOL& aSymbol )
std::pair<std::string, SIM_MODEL&> SIM_LIB_MGR::CreateModel( SCH_SYMBOL& aSymbol )
{
std::vector<LIB_PIN*> pins = aSymbol.GetLibPins();
SCH_FIELD* libraryField = aSymbol.FindField( SIM_LIBRARY::LIBRARY_FIELD );
std::string baseModelName;
if( libraryField )
{
@ -54,7 +56,7 @@ SIM_MODEL& SIM_LIB_MGR::CreateModel( SCH_SYMBOL& aSymbol )
catch( const IO_ERROR& e )
{
THROW_IO_ERROR(
wxString::Format( _( "Error loading simulation model library '%s'.\n%s" ),
wxString::Format( _( "Error loading simulation model library '%s': %s" ),
absolutePath,
e.What() ) );
}
@ -67,7 +69,7 @@ SIM_MODEL& SIM_LIB_MGR::CreateModel( SCH_SYMBOL& aSymbol )
SIM_LIBRARY::NAME_FIELD ) );
}
std::string baseModelName = std::string( nameField->GetShownText().ToUTF8() );
baseModelName = std::string( nameField->GetShownText().ToUTF8() );
SIM_MODEL* baseModel = library->FindModel( baseModelName );
if( !baseModel )
@ -88,5 +90,23 @@ SIM_MODEL& SIM_LIB_MGR::CreateModel( SCH_SYMBOL& aSymbol )
aSymbol.GetFields() ) );
}
return *m_models.back();
return std::pair<std::string, SIM_MODEL&>( baseModelName, *m_models.back() );
}
SIM_LIBRARY& SIM_LIB_MGR::CreateLibrary( const std::string& aLibraryPath )
{
auto it = m_libraries.try_emplace( aLibraryPath, SIM_LIBRARY::Create( aLibraryPath ) ).first;
return *it->second;
}
std::map<std::string, std::reference_wrapper<const SIM_LIBRARY>> SIM_LIB_MGR::GetLibraries() const
{
std::map<std::string, std::reference_wrapper<const SIM_LIBRARY>> result;
for( auto&& [path, library] : m_libraries )
result.try_emplace( path, *library );
return result;
}

View File

@ -40,10 +40,14 @@ class SIM_LIB_MGR
{
public:
SIM_LIB_MGR( const PROJECT& aPrj );
virtual ~SIM_LIB_MGR() = default;
// TODO: The argument can be made const.
SIM_MODEL& CreateModel( SCH_SYMBOL& aSymbol );
std::pair<std::string, SIM_MODEL&> CreateModel( SCH_SYMBOL& aSymbol );
SIM_LIBRARY& CreateLibrary( const std::string& aLibraryPath );
std::map<std::string, std::reference_wrapper<const SIM_LIBRARY>> GetLibraries() const;
private:
const PROJECT& m_project;

View File

@ -880,32 +880,39 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent )
if( item->Type() == SCH_PIN_T )
{
LIB_PIN* pin = static_cast<SCH_PIN*>( item )->GetLibPin();
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item->GetParent() );
std::vector<LIB_PIN*> pins = symbol->GetLibPins();
SIM_LIB_MGR mgr( m_frame->Prj() );
SIM_MODEL& model = mgr.CreateModel( *symbol );
auto ref = std::string( symbol->GetRef( &m_frame->GetCurrentSheet() ).ToUTF8() );
std::vector<std::string> currentNames =
model.SpiceGenerator().CurrentNames( ref );
if( currentNames.size() == 0 )
return true;
else if( currentNames.size() == 1 )
try
{
simFrame->AddCurrentPlot( currentNames.at( 0 ) );
return true;
LIB_PIN* pin = static_cast<SCH_PIN*>( item )->GetLibPin();
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item->GetParent() );
std::vector<LIB_PIN*> pins = symbol->GetLibPins();
SIM_LIB_MGR mgr( m_frame->Prj() );
SIM_MODEL& model = mgr.CreateModel( *symbol ).second;
auto ref = std::string( symbol->GetRef( &m_frame->GetCurrentSheet() ).ToUTF8() );
std::vector<std::string> currentNames =
model.SpiceGenerator().CurrentNames( ref );
if( currentNames.size() == 0 )
return true;
else if( currentNames.size() == 1 )
{
simFrame->AddCurrentPlot( currentNames.at( 0 ) );
return true;
}
int modelPinIndex =
model.FindModelPinIndex( std::string( pin->GetNumber().ToUTF8() ) );
if( modelPinIndex != SIM_MODEL::PIN::NOT_CONNECTED )
{
wxString name = currentNames.at( modelPinIndex );
simFrame->AddCurrentPlot( name );
}
}
int modelPinIndex =
model.FindModelPinIndex( std::string( pin->GetNumber().ToUTF8() ) );
if( modelPinIndex != SIM_MODEL::PIN::NOT_CONNECTED )
catch( const IO_ERROR& e )
{
wxString name = currentNames.at( modelPinIndex );
simFrame->AddCurrentPlot( name );
DisplayErrorMessage( m_frame, e.What() );
}
}
else if( item->IsType( { SCH_ITEM_LOCATE_WIRE_T } ) )