Manual cherry-pick of much of 6d296038f3
This commit is contained in:
parent
c41b1e2f06
commit
70e86434ef
|
@ -136,6 +136,9 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataToWindow()
|
|||
wxString pinMap;
|
||||
bool storeInValue = false;
|
||||
|
||||
wxString msg;
|
||||
WX_STRING_REPORTER reporter( &msg );
|
||||
|
||||
// Infer RLC and VI models if they aren't specified
|
||||
if( SIM_MODEL::InferSimModel( m_symbol, &m_fields, false, SIM_VALUE_GRAMMAR::NOTATION::SI,
|
||||
&deviceType, &modelType, &modelParams, &pinMap ) )
|
||||
|
@ -180,7 +183,7 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataToWindow()
|
|||
if( !loadLibrary( libraryFilename ) )
|
||||
{
|
||||
m_libraryPathText->ChangeValue( libraryFilename );
|
||||
m_curModelType = SIM_MODEL::ReadTypeFromFields( m_fields );
|
||||
m_curModelType = SIM_MODEL::ReadTypeFromFields( m_fields, &reporter );
|
||||
m_libraryModelsMgr.CreateModel( nullptr, sourcePins, m_fields );
|
||||
|
||||
m_modelNameChoice->Append( _( "<unknown>" ) );
|
||||
|
@ -256,25 +259,32 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataToWindow()
|
|||
{
|
||||
// The model is sourced from the instance.
|
||||
m_useInstanceModelRadioButton->SetValue( true );
|
||||
m_curModelType = SIM_MODEL::ReadTypeFromFields( m_fields );
|
||||
|
||||
msg.clear();
|
||||
m_curModelType = SIM_MODEL::ReadTypeFromFields( m_fields, &reporter );
|
||||
|
||||
if( reporter.HasMessage() )
|
||||
DisplayErrorMessage( this, msg );
|
||||
}
|
||||
|
||||
m_builtinModelsMgr.SetReporter( &reporter );
|
||||
|
||||
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
|
||||
{
|
||||
wxString msg;
|
||||
WX_STRING_REPORTER reporter( &msg );
|
||||
|
||||
m_builtinModelsMgr.SetReporter( &reporter );
|
||||
|
||||
if( m_useInstanceModelRadioButton->GetValue() && type == m_curModelType )
|
||||
m_builtinModelsMgr.CreateModel( m_fields, sourcePins, false );
|
||||
else
|
||||
m_builtinModelsMgr.CreateModel( type, sourcePins );
|
||||
|
||||
if( reporter.HasMessage() )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "Failed to read simulation model from fields." )
|
||||
+ wxT( "\n\n" ) + msg );
|
||||
msg.clear();
|
||||
m_builtinModelsMgr.CreateModel( m_fields, sourcePins, false );
|
||||
|
||||
if( reporter.HasMessage() )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "Failed to read simulation model from fields." )
|
||||
+ wxT( "\n\n" ) + msg );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_builtinModelsMgr.CreateModel( type, sourcePins );
|
||||
}
|
||||
|
||||
SIM_MODEL::DEVICE_T deviceTypeT = SIM_MODEL::TypeInfo( type ).deviceType;
|
||||
|
@ -698,7 +708,7 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::loadLibrary( const wxString& aLibraryP
|
|||
|
||||
std::string modelName = SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY::NAME_FIELD );
|
||||
|
||||
for( auto& [baseModelName, baseModel] : library()->GetModels() )
|
||||
for( const auto& [baseModelName, baseModel] : library()->GetModels() )
|
||||
{
|
||||
if( baseModelName == modelName )
|
||||
m_libraryModelsMgr.CreateModel( &baseModel, sourcePins, m_fields );
|
||||
|
@ -714,7 +724,7 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::loadLibrary( const wxString& aLibraryP
|
|||
|
||||
wxArrayString modelNames;
|
||||
|
||||
for( auto& [name, model] : library()->GetModels() )
|
||||
for( const auto& [name, model] : library()->GetModels() )
|
||||
modelNames.Add( name );
|
||||
|
||||
m_modelNameChoice->Clear();
|
||||
|
@ -1407,22 +1417,16 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::adjustParamGridColumns( int aWidth, bo
|
|||
|
||||
for( size_t ii = 0; ii < grid->GetColumnCount(); ii++ )
|
||||
{
|
||||
if( ii == 0 )
|
||||
if( ii == PARAM_COLUMN::DESCRIPTION )
|
||||
colWidths.push_back( grid->GetState()->GetColumnWidth( ii ) + margin + indent );
|
||||
else if( ii == 1 )
|
||||
colWidths.push_back( grid->GetState()->GetColumnWidth( ii ) + margin );
|
||||
else if( ii == PARAM_COLUMN::VALUE )
|
||||
colWidths.push_back( std::max( 72, grid->GetState()->GetColumnWidth( ii ) ) + margin );
|
||||
else
|
||||
colWidths.push_back( 50 );
|
||||
colWidths.push_back( 60 + margin );
|
||||
|
||||
aWidth -= colWidths[ ii ];
|
||||
}
|
||||
|
||||
// Account for scroll bars
|
||||
aWidth -= ( grid->GetSize().x - grid->GetClientSize().x );
|
||||
|
||||
if( aWidth > 0 )
|
||||
colWidths[ PARAM_COLUMN::VALUE ] += aWidth;
|
||||
|
||||
for( size_t ii = 0; ii < grid->GetColumnCount(); ii++ )
|
||||
grid->SetColumnProportion( ii, colWidths[ ii ] );
|
||||
|
||||
|
|
|
@ -83,20 +83,13 @@ namespace NETLIST_EXPORTER_SPICE_PARSER
|
|||
|
||||
std::string NAME_GENERATOR::Generate( const std::string& aProposedName )
|
||||
{
|
||||
if( !m_names.count( aProposedName ) )
|
||||
return aProposedName;
|
||||
std::string name = aProposedName;
|
||||
int ii = 1;
|
||||
|
||||
for( uint64_t i = 1; i < UINT64_MAX; ++i )
|
||||
{
|
||||
std::string name = fmt::format( "{}#{}", aProposedName, i );
|
||||
while( m_names.count( name ) )
|
||||
name = fmt::format( "{}#{}", aProposedName, ii++ );
|
||||
|
||||
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 ) );
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
|
@ -126,8 +119,7 @@ bool NETLIST_EXPORTER_SPICE::DoWriteNetlist( OUTPUTFORMATTER& aFormatter, unsign
|
|||
// Cleanup list to avoid duplicate if the netlist exporter is run more than once.
|
||||
m_rawIncludes.clear();
|
||||
|
||||
if( !ReadSchematicAndLibraries( aNetlistOptions, aReporter ) )
|
||||
return false;
|
||||
bool result = ReadSchematicAndLibraries( aNetlistOptions, aReporter );
|
||||
|
||||
WriteHead( aFormatter, aNetlistOptions );
|
||||
|
||||
|
@ -142,7 +134,7 @@ bool NETLIST_EXPORTER_SPICE::DoWriteNetlist( OUTPUTFORMATTER& aFormatter, unsign
|
|||
|
||||
WriteTail( aFormatter, aNetlistOptions );
|
||||
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
@ -165,6 +157,8 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
|
|||
std::set<std::string> refNames; // Set of reference names to check for duplication.
|
||||
int ncCounter = 1;
|
||||
|
||||
m_libMgr.SetReporter( &aReporter );
|
||||
|
||||
ReadDirectives( aNetlistOptions );
|
||||
|
||||
m_nets.clear();
|
||||
|
@ -240,50 +234,19 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
|
|||
wxString modelParams;
|
||||
wxString pinMap;
|
||||
|
||||
// JEY TODO: readModel() below will also do the inference, so I don't think this
|
||||
// accomplishes anything....
|
||||
// Infer RLC and VI models if they aren't specified
|
||||
if( SIM_MODEL::InferSimModel( *symbol, &spiceItem.fields, true,
|
||||
SIM_VALUE_GRAMMAR::NOTATION::SPICE, &deviceType,
|
||||
&modelType, &modelParams, &pinMap ) )
|
||||
{
|
||||
spiceItem.fields.emplace_back( symbol, -1, SIM_DEVICE_TYPE_FIELD );
|
||||
spiceItem.fields.back().SetText( deviceType );
|
||||
readRefName( sheet, *symbol, spiceItem, refNames );
|
||||
readModel( sheet, *symbol, spiceItem );
|
||||
readPinNumbers( *symbol, spiceItem, pins );
|
||||
readPinNetNames( *symbol, spiceItem, pins, ncCounter );
|
||||
|
||||
if( !modelType.IsEmpty() )
|
||||
{
|
||||
spiceItem.fields.emplace_back( symbol, -1, SIM_TYPE_FIELD );
|
||||
spiceItem.fields.back().SetText( modelType );
|
||||
}
|
||||
// TODO: transmission line handling?
|
||||
|
||||
spiceItem.fields.emplace_back( symbol, -1, SIM_PARAMS_FIELD );
|
||||
spiceItem.fields.back().SetText( modelParams );
|
||||
|
||||
spiceItem.fields.emplace_back( symbol, -1, SIM_PINS_FIELD );
|
||||
spiceItem.fields.back().SetText( pinMap );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
readRefName( sheet, *symbol, spiceItem, refNames );
|
||||
readModel( sheet, *symbol, spiceItem );
|
||||
readPinNumbers( *symbol, spiceItem, pins );
|
||||
readPinNetNames( *symbol, spiceItem, pins, ncCounter );
|
||||
|
||||
// TODO: transmission line handling?
|
||||
|
||||
m_items.push_back( std::move( spiceItem ) );
|
||||
}
|
||||
catch( const IO_ERROR& e )
|
||||
{
|
||||
msg.Printf( _( "Error reading simulation model from symbol '%s':\n%s" ),
|
||||
symbol->GetRef( &sheet ),
|
||||
e.Problem() );
|
||||
aReporter.Report( msg, RPT_SEVERITY_ERROR );
|
||||
}
|
||||
m_items.push_back( std::move( spiceItem ) );
|
||||
}
|
||||
}
|
||||
|
||||
m_libMgr.SetReporter( nullptr );
|
||||
|
||||
return !aReporter.HasMessage();
|
||||
}
|
||||
|
||||
|
@ -595,7 +558,7 @@ void NETLIST_EXPORTER_SPICE::writeInclude( OUTPUTFORMATTER& aFormatter, unsigned
|
|||
|
||||
void NETLIST_EXPORTER_SPICE::writeIncludes( OUTPUTFORMATTER& aFormatter, unsigned aNetlistOptions )
|
||||
{
|
||||
for( auto& [path, library] : m_libMgr.GetLibraries() )
|
||||
for( const auto& [path, library] : m_libMgr.GetLibraries() )
|
||||
{
|
||||
if( dynamic_cast<const SIM_LIBRARY_SPICE*>( &library.get() ) )
|
||||
writeInclude( aFormatter, aNetlistOptions, path );
|
||||
|
|
|
@ -49,7 +49,7 @@ void SIM_LIBRARY_KIBIS::ReadFile( const std::string& aFilePath, REPORTER* aRepor
|
|||
|
||||
for( KIBIS_COMPONENT& kcomp : m_kibis.m_components )
|
||||
{
|
||||
m_models.push_back( SIM_MODEL::Create( SIM_MODEL::TYPE::KIBIS_DEVICE, pins, nullptr ) );
|
||||
m_models.push_back( SIM_MODEL::Create( SIM_MODEL::TYPE::KIBIS_DEVICE, pins, aReporter ) );
|
||||
m_modelNames.emplace_back( kcomp.m_name );
|
||||
|
||||
SIM_MODEL_KIBIS* libcomp = dynamic_cast<SIM_MODEL_KIBIS*>( m_models.back().get() );
|
||||
|
|
|
@ -361,11 +361,13 @@ SIM_MODEL::SPICE_INFO SIM_MODEL::SpiceInfo( TYPE aType )
|
|||
}
|
||||
|
||||
|
||||
template TYPE SIM_MODEL::ReadTypeFromFields( const std::vector<SCH_FIELD>& aFields );
|
||||
template TYPE SIM_MODEL::ReadTypeFromFields( const std::vector<LIB_FIELD>& aFields );
|
||||
template TYPE SIM_MODEL::ReadTypeFromFields( const std::vector<SCH_FIELD>& aFields,
|
||||
REPORTER* aReporter );
|
||||
template TYPE SIM_MODEL::ReadTypeFromFields( const std::vector<LIB_FIELD>& aFields,
|
||||
REPORTER* aReporter );
|
||||
|
||||
template <typename T>
|
||||
TYPE SIM_MODEL::ReadTypeFromFields( const std::vector<T>& aFields )
|
||||
TYPE SIM_MODEL::ReadTypeFromFields( const std::vector<T>& aFields, REPORTER* aReporter )
|
||||
{
|
||||
std::string deviceTypeFieldValue = GetFieldValue( &aFields, SIM_DEVICE_TYPE_FIELD );
|
||||
std::string typeFieldValue = GetFieldValue( &aFields, SIM_TYPE_FIELD );
|
||||
|
@ -392,6 +394,17 @@ TYPE SIM_MODEL::ReadTypeFromFields( const std::vector<T>& aFields )
|
|||
if( typeFromLegacyFields != TYPE::NONE )
|
||||
return typeFromLegacyFields;
|
||||
|
||||
if( aReporter )
|
||||
{
|
||||
if( aFields.size() > REFERENCE_FIELD )
|
||||
{
|
||||
aReporter->Report( wxString::Format( _( "Error reading simulation model from symbol '%s':\n%s" ),
|
||||
aFields[REFERENCE_FIELD].GetText(),
|
||||
_( "Failed to read simulation model from fields." ) ),
|
||||
RPT_SEVERITY_ERROR );
|
||||
}
|
||||
}
|
||||
|
||||
return TYPE::NONE;
|
||||
}
|
||||
|
||||
|
@ -506,7 +519,7 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL* aBaseModel,
|
|||
const std::vector<T>& aFields,
|
||||
REPORTER* aReporter )
|
||||
{
|
||||
TYPE type = ReadTypeFromFields( aFields );
|
||||
TYPE type = ReadTypeFromFields( aFields, aReporter );
|
||||
|
||||
// If the model has a specified type, it takes priority over the type of its base class.
|
||||
if( type == TYPE::NONE && aBaseModel )
|
||||
|
@ -533,9 +546,13 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL* aBaseModel,
|
|||
catch( IO_ERROR& err )
|
||||
{
|
||||
if( aReporter )
|
||||
aReporter->Report( err.What(), RPT_SEVERITY_ERROR );
|
||||
else
|
||||
DisplayErrorMessage( nullptr, err.What() );
|
||||
{
|
||||
aReporter->Report( wxString::Format( _( "Error reading simulation model from "
|
||||
"symbol '%s':\n%s" ),
|
||||
aFields[REFERENCE_FIELD].GetText(),
|
||||
err.Problem() ),
|
||||
RPT_SEVERITY_ERROR );
|
||||
}
|
||||
}
|
||||
|
||||
return model;
|
||||
|
@ -557,7 +574,7 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<T>& aFields,
|
|||
const std::vector<LIB_PIN*>& aPins,
|
||||
bool aResolved, REPORTER* aReporter )
|
||||
{
|
||||
TYPE type = ReadTypeFromFields( aFields );
|
||||
TYPE type = ReadTypeFromFields( aFields, aReporter );
|
||||
std::unique_ptr<SIM_MODEL> model = SIM_MODEL::Create( type );
|
||||
|
||||
try
|
||||
|
@ -589,11 +606,15 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<T>& aFields,
|
|||
}
|
||||
catch( const IO_ERROR& err )
|
||||
{
|
||||
// We own the pin syntax, so if we can't parse it then there's an error, full stop.
|
||||
// We own the pin syntax, so if we can't parse it then there's an error.
|
||||
if( aReporter )
|
||||
aReporter->Report( err.Problem(), RPT_SEVERITY_ERROR );
|
||||
else
|
||||
THROW_IO_ERROR( err.Problem() );
|
||||
{
|
||||
aReporter->Report( wxString::Format( _( "Error reading simulation model from "
|
||||
"symbol '%s':\n%s" ),
|
||||
aFields[REFERENCE_FIELD].GetText(),
|
||||
err.Problem() ),
|
||||
RPT_SEVERITY_ERROR );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -726,21 +747,8 @@ void SIM_MODEL::AddParam( const PARAM::INFO& aInfo )
|
|||
|
||||
void SIM_MODEL::SetBaseModel( const SIM_MODEL& aBaseModel )
|
||||
{
|
||||
auto describe =
|
||||
[]( const SIM_MODEL* aModel )
|
||||
{
|
||||
return fmt::format( "{} ({})",
|
||||
aModel->GetDeviceInfo().fieldValue,
|
||||
aModel->GetTypeInfo().description );
|
||||
};
|
||||
|
||||
if( GetType() != aBaseModel.GetType() )
|
||||
{
|
||||
THROW_IO_ERROR( wxString::Format( _( "Simulation model type must be the same as of its "
|
||||
"base class: '%s', but is '%s'" ),
|
||||
describe( &aBaseModel ),
|
||||
describe( this ) ) );
|
||||
}
|
||||
wxASSERT_MSG( GetType() == aBaseModel.GetType(),
|
||||
wxS( "Simulation model type must be the same as its base class!" ) );
|
||||
|
||||
m_baseModel = &aBaseModel;
|
||||
}
|
||||
|
|
|
@ -384,7 +384,7 @@ public:
|
|||
|
||||
|
||||
template <typename T>
|
||||
static TYPE ReadTypeFromFields( const std::vector<T>& aFields );
|
||||
static TYPE ReadTypeFromFields( const std::vector<T>& aFields, REPORTER* aReporter );
|
||||
|
||||
template <typename T>
|
||||
static TYPE InferTypeFromLegacyFields( const std::vector<T>& aFields );
|
||||
|
|
|
@ -55,7 +55,6 @@ std::vector<std::string> SPICE_GENERATOR_NGSPICE::CurrentNames( const SPICE_ITEM
|
|||
return SPICE_GENERATOR::CurrentNames( aItem );
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "Unhandled model device type in SIM_MODEL_NGSPICE" );
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,6 +95,10 @@ std::string SPICE_GENERATOR::ModelLine( const SPICE_ITEM& aItem ) const
|
|||
value ) );
|
||||
}
|
||||
|
||||
// Don't send SPICE empty models.
|
||||
if( result.length() == indentLength + 1 /* line ending */ )
|
||||
result.clear();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue