Clean up (and better comment) referential model handling.

This commit is contained in:
Jeff Young 2024-09-02 09:49:06 +01:00
parent ee77d06be7
commit c7859e7ed7
8 changed files with 36 additions and 28 deletions

View File

@ -376,7 +376,6 @@ SIM_MODEL::SPICE_INFO SIM_MODEL::SpiceInfo( TYPE aType )
case TYPE::KIBIS_DRIVER_PRBS: return { "X" }; case TYPE::KIBIS_DRIVER_PRBS: return { "X" };
case TYPE::NONE: case TYPE::NONE:
case TYPE::REFERENTIAL:
case TYPE::RAWSPICE: return {}; case TYPE::RAWSPICE: return {};
default: wxFAIL; return {}; default: wxFAIL; return {};

View File

@ -280,7 +280,6 @@ public:
I_RANDPOISSON, I_RANDPOISSON,
I_BEHAVIORAL, I_BEHAVIORAL,
REFERENTIAL,
SUBCKT, SUBCKT,
XSPICE, XSPICE,

View File

@ -55,12 +55,11 @@ std::string SPICE_GENERATOR_SPICE::Preview( const SPICE_ITEM& aItem ) const
std::unique_ptr<SIM_MODEL_SPICE> SIM_MODEL_SPICE::Create( const SIM_LIBRARY_SPICE& aLibrary, std::unique_ptr<SIM_MODEL_SPICE> SIM_MODEL_SPICE::Create( const SIM_LIBRARY_SPICE& aLibrary,
const std::string& aSpiceCode, const std::string& aSpiceCode,
bool aSkipReferential, bool aFirstPass, REPORTER& aReporter )
REPORTER& aReporter )
{ {
SIM_MODEL::TYPE type = SPICE_MODEL_PARSER::ReadType( aLibrary, aSpiceCode, aSkipReferential ); SIM_MODEL::TYPE type = SIM_MODEL::TYPE::NONE;
if( type == SIM_MODEL::TYPE::REFERENTIAL ) if( !SPICE_MODEL_PARSER::ReadType( aLibrary, aSpiceCode, &type, aFirstPass ) )
return nullptr; return nullptr;
std::unique_ptr<SIM_MODEL> model = SIM_MODEL::Create( type ); std::unique_ptr<SIM_MODEL> model = SIM_MODEL::Create( type );

View File

@ -49,8 +49,7 @@ public:
static std::unique_ptr<SIM_MODEL_SPICE> Create( const SIM_LIBRARY_SPICE& aLibrary, static std::unique_ptr<SIM_MODEL_SPICE> Create( const SIM_LIBRARY_SPICE& aLibrary,
const std::string& aSpiceCode, const std::string& aSpiceCode,
bool aSkipReferential, bool aFirstPass, REPORTER& aReporter );
REPORTER& aReporter );
SIM_MODEL_SPICE( TYPE aType, SIM_MODEL_SPICE( TYPE aType,
std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator ); std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator );

View File

@ -128,10 +128,10 @@ void SPICE_LIBRARY_PARSER::ReadFile( const wxString& aFilePath, REPORTER& aRepor
} }
auto createModel = auto createModel =
[&]( int ii, bool aSkipReferential ) [&]( int ii, bool firstPass )
{ {
m_library.m_models[ii] = SIM_MODEL_SPICE::Create( m_library, modelQueue[ii].second, m_library.m_models[ii] = SIM_MODEL_SPICE::Create( m_library, modelQueue[ii].second,
aSkipReferential, aReporter ); firstPass, aReporter );
}; };
// Read all self-contained models in parallel // Read all self-contained models in parallel
@ -145,7 +145,7 @@ void SPICE_LIBRARY_PARSER::ReadFile( const wxString& aFilePath, REPORTER& aRepor
} ); } );
tp.wait_for_tasks(); tp.wait_for_tasks();
// Now read all referential models in order. // Now read all models that might refer to other models in order.
for( int ii = 0; ii < (int) modelQueue.size(); ++ii ) for( int ii = 0; ii < (int) modelQueue.size(); ++ii )
{ {
if( !m_library.m_models[ii] ) if( !m_library.m_models[ii] )

View File

@ -41,7 +41,7 @@ public:
virtual ~SPICE_LIBRARY_PARSER() virtual ~SPICE_LIBRARY_PARSER()
{}; {};
virtual void ReadFile( const wxString& aFilePath, REPORTER& aReporter ); virtual void ReadFile( const wxString& aFilePath, REPORTER& firstPass );
protected: protected:
void parseFile( const wxString& aFilePath, REPORTER& aReporter, void parseFile( const wxString& aFilePath, REPORTER& aReporter,

View File

@ -59,9 +59,11 @@ namespace SIM_MODEL_SPICE_PARSER
} }
SIM_MODEL::TYPE SPICE_MODEL_PARSER::ReadType( const SIM_LIBRARY_SPICE& aLibrary, bool SPICE_MODEL_PARSER::ReadType( const SIM_LIBRARY_SPICE& aLibrary, const std::string& aSpiceCode,
const std::string& aSpiceCode, bool aSkipReferential ) SIM_MODEL::TYPE* aType, bool aFirstPass )
{ {
*aType = SIM_MODEL::TYPE::NONE;
tao::pegtl::string_input<> in( aSpiceCode, "Spice_Code" ); tao::pegtl::string_input<> in( aSpiceCode, "Spice_Code" );
std::unique_ptr<tao::pegtl::parse_tree::node> root; std::unique_ptr<tao::pegtl::parse_tree::node> root;
@ -76,15 +78,17 @@ SIM_MODEL::TYPE SPICE_MODEL_PARSER::ReadType( const SIM_LIBRARY_SPICE& aLibrary,
catch( const tao::pegtl::parse_error& e ) catch( const tao::pegtl::parse_error& e )
{ {
wxLogTrace( traceSpiceModelParser, wxS( "%s" ), e.what() ); wxLogTrace( traceSpiceModelParser, wxS( "%s" ), e.what() );
return SIM_MODEL::TYPE::NONE; return true;
} }
for( const auto& node : root->children ) for( const auto& node : root->children )
{ {
if( node->is_type<SIM_MODEL_SPICE_PARSER::dotModelAko>() ) if( node->is_type<SIM_MODEL_SPICE_PARSER::dotModelAko>() )
{ {
if( aSkipReferential ) // The first pass of model loading is done in parallel, so we can't (yet) look
return SIM_MODEL::TYPE::REFERENTIAL; // up our reference model.
if( aFirstPass )
return false;
std::string modelName = node->children.at( 0 )->string(); std::string modelName = node->children.at( 0 )->string();
std::string akoName = node->children.at( 1 )->string(); std::string akoName = node->children.at( 1 )->string();
@ -98,7 +102,8 @@ SIM_MODEL::TYPE SPICE_MODEL_PARSER::ReadType( const SIM_LIBRARY_SPICE& aLibrary,
modelName ) ); modelName ) );
} }
return sourceModel->GetType(); *aType = sourceModel->GetType();
return true;
} }
else if( node->is_type<SIM_MODEL_SPICE_PARSER::dotModel>() ) else if( node->is_type<SIM_MODEL_SPICE_PARSER::dotModel>() )
{ {
@ -119,7 +124,10 @@ SIM_MODEL::TYPE SPICE_MODEL_PARSER::ReadType( const SIM_LIBRARY_SPICE& aLibrary,
SIM_MODEL::TYPE type = ReadTypeFromSpiceStrings( typeString ); SIM_MODEL::TYPE type = ReadTypeFromSpiceStrings( typeString );
if( type != SIM_MODEL::TYPE::RAWSPICE ) if( type != SIM_MODEL::TYPE::RAWSPICE )
return type; {
*aType = type;
return true;
}
} }
else if( subnode->is_type<SIM_MODEL_SPICE_PARSER::param>() ) else if( subnode->is_type<SIM_MODEL_SPICE_PARSER::param>() )
{ {
@ -137,7 +145,7 @@ SIM_MODEL::TYPE SPICE_MODEL_PARSER::ReadType( const SIM_LIBRARY_SPICE& aLibrary,
else else
{ {
wxFAIL_MSG( "Unhandled parse tree subnode" ); wxFAIL_MSG( "Unhandled parse tree subnode" );
return SIM_MODEL::TYPE::NONE; return true;
} }
} }
@ -145,24 +153,28 @@ SIM_MODEL::TYPE SPICE_MODEL_PARSER::ReadType( const SIM_LIBRARY_SPICE& aLibrary,
// `version` variables into account too. This is suboptimal since we read the model // `version` variables into account too. This is suboptimal since we read the model
// twice this way, and moreover the code is now somewhat duplicated. // twice this way, and moreover the code is now somewhat duplicated.
return ReadTypeFromSpiceStrings( typeString, level, version, false ); *aType = ReadTypeFromSpiceStrings( typeString, level, version, false );
return true;
} }
else if( node->is_type<SIM_MODEL_SPICE_PARSER::dotSubckt>() ) else if( node->is_type<SIM_MODEL_SPICE_PARSER::dotSubckt>() )
{ {
if( aSkipReferential ) // The first pass of model loading is done in parallel, so we can't (yet) refer to
return SIM_MODEL::TYPE::REFERENTIAL; // any other models in a subcircuit.
if( aFirstPass )
return false;
return SIM_MODEL::TYPE::SUBCKT; *aType = SIM_MODEL::TYPE::SUBCKT;
return true;
} }
else else
{ {
wxFAIL_MSG( "Unhandled parse tree node" ); wxFAIL_MSG( "Unhandled parse tree node" );
return SIM_MODEL::TYPE::NONE; return true;
} }
} }
wxFAIL_MSG( "Could not derive type from SPICE code" ); wxFAIL_MSG( "Could not derive type from SPICE code" );
return SIM_MODEL::TYPE::NONE; return true;
} }

View File

@ -34,8 +34,8 @@ class SIM_LIBRARY_SPICE;
class SPICE_MODEL_PARSER class SPICE_MODEL_PARSER
{ {
public: public:
static SIM_MODEL::TYPE ReadType( const SIM_LIBRARY_SPICE& aLibrary, static bool ReadType( const SIM_LIBRARY_SPICE& aLibrary, const std::string& aSpiceCode,
const std::string& aSpiceCode, bool aSkipReferential ); SIM_MODEL::TYPE* aType, bool aFirstPass );
SPICE_MODEL_PARSER( SIM_MODEL_SPICE& aModel ) : m_model( aModel ) {} SPICE_MODEL_PARSER( SIM_MODEL_SPICE& aModel ) : m_model( aModel ) {}
virtual ~SPICE_MODEL_PARSER() = default; virtual ~SPICE_MODEL_PARSER() = default;