54 return std::equal( stra.begin(), stra.end(),
55 strb.begin(), strb.end(),
58 return std::tolower(a) == std::tolower(b);
71 for(
size_t i = 0; i <
m_data.size(); i++ )
73 if( std::isnan(
m_data[i] ) )
87 return std::memcmp( &aNumber, &
NA,
sizeof NA ) == 0;
163 std::stringstream message;
229 std::stringstream message;
230 message <<
_(
"Checking component " ) <<
m_name;
269 status &=
pin.Check();
283 std::ostringstream ss;
284 ss.setf( std::ios_base::scientific, std::ios_base::floatfield );
290std::string
IVtable::Spice(
int aN,
const std::string& aPort1,
const std::string& aPort2,
bool aNegateI,
291 const std::string& aModelName,
IBIS_CORNER aCorner )
const
298 result += std::to_string( aN );
304 result += aNegateI ? aPort2 : aPort1;
306 result += aNegateI ? aPort1 : aPort2;
313 result +=
" pwl(\n+ x_array=[";
324 result +=
"]\n+ y_array=[";
335 result +=
"]\n+ input_domain=0.05 fraction=TRUE)\n\n";
347 return m_entries.back().I.value[aCorner];
350 return m_entries.at( 0 ).I.value[aCorner];
352 for(
size_t i = 1; i <
m_entries.size(); i++ )
356 return m_entries.at( i - 1 ).I.value[aCorner]
358 -
m_entries.at( i - 1 ).I.value[aCorner] )
381 if( std::isnan( entry.V ) )
388 if( !entry.I.Check() )
474 std::stringstream message;
475 message <<
_(
"Checking model " ) <<
m_name;
692 auto checkSeriesData = [&](
IbisSeriesData& aData,
const wxString& aLabel )
694 auto report = [&](
const wxString& aMsg )
701 report(
_(
"Invalid Series Current table in %s." ) );
705 if( !
mosfet.m_table.Check() )
706 report(
_(
"Invalid Series MOSFET table in %s." ) );
709 report(
_(
"Series MOSFET Vds must be > 0 in %s." ) );
713 report(
_(
"Rl Series requires L Series in %s." ) );
716 report(
_(
"Rc/Lc Series requires C Series in %s." ) );
721 checkSeriesData(
m_series, wxT(
"[Model]" ) );
725 Report(
_(
"[On] and [Off] are only allowed in Series_switch models." ),
736 else if( isSeriesSwitch )
755 Report(
_(
"Series_switch model has series elements outside [On]/[Off]." ),
795 std::stringstream message;
796 message <<
_(
"Checking submodel " ) <<
m_name;
868 std::stringstream err_msg;
873 default: wxLogMessage(
"Invalid submodel type: %i", (
int)
m_type );
return false;
875 err_msg <<
_(
" submodels are not yet supported." );
892 std::stringstream message;
893 message <<
_(
"Checking Header..." );
933 if( !( !strcmp( ext.c_str(),
".ibs" ) || !strcmp( ext.c_str(),
".pkg" )
934 || !strcmp( ext.c_str(),
".ebd" ) || !strcmp( ext.c_str(),
".ims" ) ) )
956 std::stringstream message;
957 message <<
_(
"Checking package model " ) <<
m_name;
1069 std::stringstream err_msg;
1071 std::ifstream ibisFile;
1072 ibisFile.open( aFileName );
1074 if( !ibisFile.is_open() )
1076 err_msg <<
_(
"Cannot open file " ) << aFileName;
1081 std::ostringstream ss;
1082 ss << ibisFile.rdbuf();
1083 const std::string& s = ss.str();
1084 m_buffer = std::vector<char>( s.begin(), s.end() );
1110 err_msg <<
_(
"Error on line " ) << std::to_string(
m_lineCounter );
1128 err_msg << submodel.
m_name <<
_(
" submodel not found." );
1178 if( aString ==
"NA" )
1188 for( i = 1; i < (int)aString.length(); i++ )
1190 if( aString.at( i ) ==
'/' )
1194 if( aString.at( i ) ==
'/' )
1196 std::string str1 = aString.substr( 0, i );
1197 std::string str2 = aString.substr( i + 1, aString.size() - i - 1 );
1216 std::stringstream message;
1217 message << str <<
_(
" is not a valid dV/dt value." );
1239 bool converted =
false;
1241 std::string str = aStr;
1255 result = std::stod( str, &size );
1265 if( converted && ( size < str.length() ) )
1267 switch(
static_cast<char>( str.at( size ) ) )
1269 case 'T':
result *= 1e12;
break;
1270 case 'G':
result *= 1e9;
break;
1271 case 'M':
result *= 1e6;
break;
1272 case 'k':
result *= 1e3;
break;
1273 case 'm':
result *= 1e-3;
break;
1274 case 'u':
result *= 1e-6;
break;
1275 case 'n':
result *= 1e-9;
break;
1276 case 'p':
result *= 1e-12;
break;
1277 case 'f':
result *= 1e-15;
break;
1322 while( c != 0 && c !=
'\n' )
1341 std::cout << std::endl;
1378 result = std::stoi( str, &size );
1393 if( size != str.size() )
1421 aDest = std::string( start,
end );
1423 return ( aDest.size() > 0 );
1432 int len = aDest.length();
1437 char c = aDest[len - 1];
1440 while( isspace( c ) && ( i < len ) )
1442 c = aDest[len - 1 - i];
1446 aDest = aDest.substr( 0, len - i + 1 );
1471 std::string strChar =
"";
1479 if( !( c ==
'!' || c ==
'"' || c ==
'#' || c ==
'$' || c ==
'%' || c ==
'&' || c ==
'\''
1480 || c ==
'(' || c ==
')' || c ==
'*' || c ==
',' || c ==
':' || c ==
';' || c ==
'<'
1481 || c ==
'>' || c ==
'?' || c ==
'@' || c ==
'\\' || c ==
'^' || c ==
'`' || c ==
'{'
1482 || c ==
'|' || c ==
'}' || c ==
'~' || c ==
')' ) )
1489 while( ( !isspace( c ) ) && c != 0 && c !=
'\n' )
1495 if( strChar !=
"_char" )
1501 while( isspace( c ) && c != 0 && c !=
'\n' && c != d )
1504 if( ( !isspace( c ) ) && c != d )
1519 std::string keyword =
"";
1565 Report(
"Cannot change context after [END]" );
1569 Report(
"Changing context from an undefined context" );
1614 std::stringstream message;
1615 message <<
_(
"Submodel name is not unique: " ) <<
model.m_name;
1624 else if(
compareIbisWord( aKeyword.c_str(),
"Define_Package_Model" ) )
1653 std::string context_string;
1663 default: context_string +=
"???";
break;
1666 std::stringstream message;
1667 message <<
_(
"Unknown keyword in " ) << context_string <<
_(
" context: " ) << aKeyword;
1717 wxLogMessage(
"Invalid context for ramp: %i.", (
int)
m_context );
1727 if( !strcmp( str.c_str(),
"dV/dt_r" ) )
1731 else if( !strcmp( str.c_str(),
"dV/dt_f" ) )
1850 Report(
_(
"The submodel name is missing." ) );
1857 Report(
_(
"The submodel mode is missing." ) );
1862 if( !strcmp( str.c_str(),
"All" ) )
1866 else if( !strcmp( str.c_str(),
"Driving" ) )
1870 else if( !strcmp( str.c_str(),
"Non-Driving" ) )
1876 std::stringstream message;
1877 message << str <<
_(
" is not a recognised submodel mode." );
1891 bool status =
false;
1925 else if(
compareIbisWord( aKeyword.c_str(),
"POWER_Clamp_Reference" ) )
1991 std::string subparam;
1994 if( !strcmp( subparam.c_str(),
"Off_delay" ) )
1996 else if( !strcmp( subparam.c_str(),
"V_trigger_r" ) )
1998 else if( !strcmp( subparam.c_str(),
"V_trigger_f" ) )
2002 std::stringstream message;
2003 message << subparam <<
_(
" is not a recognised Submodel Spec subparameter." );
2015 bool status =
false;
2062 Report(
_(
"Missing pin name/number for matrix row." ) );
2068 Report(
_(
"Invalid pin name/number in matrix row." ) );
2071 aDest =
pin->second;
2106 std::stringstream message;
2107 message << str <<
_(
" is not a recognised matrix type." );
2134 bool status =
readInt( bandwidth );
2177 std::vector<std::string> values;
2180 for(
size_t i = 0; i < values.size(); i++ )
2243 wxLogMessage(
"Invalid matrix type: %i", (
int)
m_currentMatrix->m_type );
2249 wxLogMessage(
"Matrix pointer is null" );
2335 std::string paramName;
2347 for(
size_t i = 0; i < aSubparam.size(); i++ )
2350 if( strcmp( paramName.c_str(), aSubparam.c_str() ) )
2395 std::string paramName;
2402 for(
size_t i = 0; i < aSubparam.size(); i++ )
2421 std::string subparam;
2429 if( !strcmp( subparam.substr( 0, 10 ).c_str(),
"Model_type" ) )
2469 std::stringstream message;
2470 message <<
_(
"Unknown Model_type " ) << subparam;
2481 else if( !strcmp( subparam.substr( 0, 7 ).c_str(),
"Enable" ) )
2485 if( !strcmp( subparam.c_str(),
"Active-High" ) )
2487 else if( !strcmp( subparam.c_str(),
"Active-Low" ) )
2491 std::stringstream message;
2492 message <<
_(
"Unknown Enable: " ) << subparam;
2503 else if( subparam.substr( 0, 9 ) ==
"Polarity" )
2507 if( subparam ==
"Inverting" )
2509 else if( subparam ==
"Non-Inverting" )
2513 std::stringstream message;
2514 message <<
_(
"Unknown polarity " ) << subparam;
2560 Report(
_(
"Continued reading a model that did not begin. ( internal error )" ),
2573 std::string subparam;
2576 if( !strcmp( subparam.c_str(),
"Submodel_type" ) )
2580 if( !strcmp( subparam.c_str(),
"Dynamic_clamp" ) )
2582 else if( !strcmp( subparam.c_str(),
"Bus_hold" ) )
2584 else if( !strcmp( subparam.c_str(),
"Fall_back" ) )
2588 std::stringstream message;
2589 message << subparam <<
_(
" is not a recognised submodel type." );
2602 std::stringstream message;
2603 message << subparam <<
_(
" is not a recognised Submodel subparameter." );
2719 if( str.size() > 0 )
2720 aDest.push_back( str );
2733 std::vector<std::string> fields;
2743 if( (
int)fields.size() == ( 4 + extraArg ) )
2747 if( fields.at( 0 ) ==
"R_pkg" )
2749 else if( fields.at( 0 ) ==
"L_pkg" )
2751 else if( fields.at( 0 ) ==
"C_pkg" )
2755 Report(
"Invalid field in [Package]" );
2765 if( fields.size() != 0 )
2782 std::vector<std::string> fields;
2789 if( ( fields.size() == 3 ) )
2793 pin.m_pinName = fields.at( 0 );
2794 pin.m_signalName = fields.at( 1 );
2795 pin.m_modelName = fields.at( 2 );
2809 pin.m_pinName = fields.at( 0 );
2810 pin.m_signalName = fields.at( 1 );
2811 pin.m_modelName = fields.at( 2 );
2817 if(
pin.m_Rcol == 0 ||
pin.m_Lcol == 0 ||
pin.m_Ccol == 0 )
2819 Report(
_(
"Invalid pin entry: 6 values from a table with only 3." ),
2836 for(
int i = 3; i < 6; i++ )
2838 if( fields.at( i ) ==
"R_pin" )
2842 else if( fields.at( i ) ==
"L_pin" )
2846 else if( fields.at( i ) ==
"C_pin" )
2857 if(
pin.m_Rcol == 0 ||
pin.m_Lcol == 0 ||
pin.m_Ccol == 0 )
2879 std::vector<std::string> fields;
2891 if( fields.size() != 0 )
2893 if( fields.size() > 6 || fields.size() < 3 )
2901 pinMapping.
m_PDref = fields.at( 1 );
2902 pinMapping.
m_PUref = fields.at( 2 );
2904 if( fields.size() > 3 )
2907 if( fields.size() > 4 )
2910 if( fields.size() > 5 )
2911 pinMapping.
m_extRef = fields.at( 5 );
2962 std::vector<std::string> fields;
2969 else if( !fields.empty() )
2973 if( fields.size() >= 3 )
2975 mapping.
m_pin1 = fields.at( 0 );
2976 mapping.
m_pin2 = fields.at( 1 );
2979 if( fields.size() > 3 )
3064 wxLogMessage(
"Invalid waveform type: %i", (
int) aType );
3078 wxLogMessage(
"Invalid waveform type: %i", (
int) aType );
3083 wxLogMessage(
"Invalid context for waveform: %i", (
int)
m_context );
3089 if( aDest !=
nullptr )
3139 if( keyword.size() > 0 )
3262 while( ( c !=
'\n' ) && ( c != 0 ) )
void Report(const std::string &aMsg, SEVERITY aSeverity=RPT_SEVERITY_INFO) const
Print a message.
static std::string doubleToString(double aNumber)
Convert a double to string using scientific notation.
std::vector< double > m_data
bool Check() override
Check if the data held by the object is valid.
bool Check() override
Check if the data held by the object is valid.
double InterpolatedI(double aV, IBIS_CORNER aCorner) const
Interpolate the IV table.
std::string Spice(int aN, const std::string &aPort1, const std::string &aPort2, bool aNegateI, const std::string &aModelName, IBIS_CORNER aCorner) const
Interpolate the IV table.
std::vector< IVtableEntry > m_entries
bool Check() override
Check if the data held by the object is valid.
std::string m_GNDClampRef
std::string m_POWERClampRef
bool Check() override
Check if the data held by the object is valid.
One row of a [Series Pin Mapping] table (IBIS 4.1+).
std::string m_functionTableGroup
std::string m_manufacturer
IbisComponentPackage m_package
bool Check() override
Check if the data held by the object is valid.
std::vector< IbisComponentPin > m_pins
bool Check() override
Check if the data held by the object is valid.
TypMinMaxValue m_C_comp_pullup
TypMinMaxValue m_C_comp_power_clamp
IbisSeriesData m_seriesOff
TypMinMaxValue m_pullupReference
TypMinMaxValue m_C_comp_pulldown
TypMinMaxValue m_C_comp_gnd_clamp
bool Check() override
Check if the data held by the object is valid.
TypMinMaxValue m_POWERClampReference
IbisSeriesData m_seriesOn
IVtable m_compositeCurrent
TypMinMaxValue m_temperatureRange
TypMinMaxValue m_pulldownReference
TypMinMaxValue m_GNDClampReference
TypMinMaxValue m_voltageRange
std::map< std::string, int > m_pins
std::shared_ptr< IBIS_MATRIX > m_resistanceMatrix
std::shared_ptr< IBIS_MATRIX > m_inductanceMatrix
bool Check() override
Check if the data held by the object is valid.
std::shared_ptr< IBIS_MATRIX > m_capacitanceMatrix
std::string m_manufacturer
bool parseSubmodel(std::string &aKeyword)
Parse a single keyword in the submodel context.
std::vector< char > m_buffer
bool readAlgorithmicModel()
bool readMatrixBandedOrFull()
IBIS_PARSER_CONTINUE m_continue
bool changeCommentChar()
Ibis can change the character used for comments.
bool getNextLine()
Load the next line.
bool parseComponent(std::string &aKeyword)
Parse a single keyword in the component context.
bool parseModel(std::string &aKeyword)
Parse a single keyword in the model context.
VTtable * m_currentVTtable
bool readMatrixBandwidth()
bool parsePackageModelModelData(std::string &aKeyword)
Parse a single keyword in the package model model data context.
bool isLineEmptyFromCursor()
void printLine()
Print the current line.
bool changeContext(std::string &aKeyword)
bool parseDouble(double &aDest, std::string &aStr, bool aAllowModifiers=false)
Parse a double according to the ibis standard.
bool onNewLine()
Parse the current line.
bool readWord(std::string &aDest)
bool readTypMinMaxValue(TypMinMaxValue &aDest)
bool compareIbisWord(const std::string &a, const std::string &b)
compare two strings without being case sensitive
bool readDvdt(dvdt &aDest)
IbisComponent * m_currentComponent
std::shared_ptr< IBIS_MATRIX > m_currentMatrix
IbisSubmodel * m_currentSubmodel
bool ParseFile(const std::string &aFileName)
Parse a file.
bool readMatrixType(std::shared_ptr< IBIS_MATRIX > &aDest)
std::string * m_continuingString
IbisModel * m_currentModel
bool readSeriesPinMapping()
bool parseDvdt(dvdt &aDest, std::string &aStr)
Parse a dV/dt value according to the ibis standard.
IbisPackageModel * m_currentPackageModel
IbisSeriesData * currentSeriesData()
Active series data: [On]/[Off] sub-block when set, else m_series.
bool readDouble(double &aDest)
IbisModelSelector * m_currentModelSelector
bool parsePackageModel(std::string &aKeyword)
Parse a single keyword in the package model context.
bool readSeriesMosfet()
Read one [Series MOSFET] line (Vds subparam or IV row).
bool readString(std::string &aDest)
bool readTypMinMaxValueSubparam(const std::string &aSubparam, TypMinMaxValue &aDest)
bool parseAlgorithmicModel(std::string &aKeyword)
Parse a single keyword in the algorithmic model context.
bool readNumericSubparam(const std::string &aSubparam, double &aDest)
bool readMatrixPinIndex(int &aDest)
IBIS_PARSER_CONTEXT m_context
IVtable * m_currentIVtable
bool readIVtableEntry(IVtable &aTable)
IbisSeriesData * m_currentSeriesData
bool readVTtableEntry(VTtable &aTable)
bool parseModelSelector(std::string &aKeyword)
Parse a single keyword in the model selector context.
bool readReceiverThresholds()
bool storeString(std::string &aDest, bool aMultiline)
bool readPackageModelPins()
IbisMosfetEntry * m_currentMosfetEntry
bool readRampdvdt(dvdtTypMinMax &aDest)
bool readTableLine(std::vector< std::string > &aDest)
bool parseHeader(std::string &aKeyword)
Parse a single keyword in the header context.
bool readWaveform(IbisWaveform *aDest, IBIS_WAVEFORM_TYPE aType)
IbisWaveform * m_currentWaveform
bool Check() override
Check if the data held by the object is valid.
TypMinMaxValue m_RlSeries
TypMinMaxValue m_LcSeries
std::vector< IbisMosfetEntry > m_seriesMosfet
TypMinMaxValue m_RcSeries
TypMinMaxValue m_VtriggerR
bool Check() override
Check if the data held by the object is valid.
IBIS_SUBMODEL_TYPE m_type
TypMinMaxValue m_offDelay
TypMinMaxValue m_VtriggerF
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
TypMinMaxValue(REPORTER *aReporter)
bool Check() override
Check if the data held by the object is valid.
void Add(const TypMinMaxValue &aValue)
std::vector< VTtableEntry > m_entries
bool Check() override
Check if the data held by the object is valid.
bool isNumberNA(double aNumber)
@ COMPONENT_SERIES_PIN_MAPPING
#define IBIS_MAX_LINE_LENGTH
static std::string strValue(double aValue)
const IbisMosfetEntry & mosfet
wxString result
Test unit parsing edge cases and error handling.