Ibis: correctly load QA files up to v2.1
This commit is contained in:
parent
2919490e92
commit
8498630876
|
@ -710,6 +710,7 @@ bool IbisParser::ParseFile( std::string& aFileName )
|
|||
ss << ibisFile.rdbuf();
|
||||
const std::string& s = ss.str();
|
||||
m_buffer = std::vector<char>( s.begin(), s.end() );
|
||||
m_buffer.push_back( 0 );
|
||||
|
||||
long size = m_buffer.size();
|
||||
|
||||
|
@ -764,7 +765,7 @@ bool IbisParser::checkEndofLine()
|
|||
|
||||
if( m_lineIndex < m_lineLength )
|
||||
{
|
||||
Report( _( "A line did not end properly.." ), RPT_SEVERITY_ERROR );
|
||||
Report( _( "A line did not end properly." ), RPT_SEVERITY_ERROR );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -787,6 +788,14 @@ bool IbisParser::readDvdt( std::string& aString, dvdt& aDest )
|
|||
{
|
||||
bool status = true;
|
||||
|
||||
if( aString == "NA" )
|
||||
{
|
||||
aDest.m_dv = nan( NAN_NA );
|
||||
aDest.m_dt = nan( NAN_NA );
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
|
||||
for( i = 1; i < (int)aString.length(); i++ )
|
||||
|
@ -800,7 +809,7 @@ bool IbisParser::readDvdt( std::string& aString, dvdt& aDest )
|
|||
if( aString.at( i ) == '/' )
|
||||
{
|
||||
std::string str1 = aString.substr( 0, i );
|
||||
std::string str2 = aString.substr( i + 2, aString.size() );
|
||||
std::string str2 = aString.substr( i + 1, aString.size() - i - 1 );
|
||||
|
||||
if( !parseDouble( aDest.m_dv, str1, true ) || !parseDouble( aDest.m_dt, str2, true ) )
|
||||
{
|
||||
|
@ -808,16 +817,6 @@ bool IbisParser::readDvdt( std::string& aString, dvdt& aDest )
|
|||
}
|
||||
}
|
||||
|
||||
else if( aString == "NA" )
|
||||
{
|
||||
aDest.m_dv = nan( NAN_NA );
|
||||
aDest.m_dt = nan( NAN_NA );
|
||||
}
|
||||
else
|
||||
{
|
||||
status = false;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -836,18 +835,19 @@ bool IbisParser::parseDouble( double& aDest, std::string& aStr, bool aAllowModif
|
|||
double result;
|
||||
size_t size = 0;
|
||||
|
||||
try
|
||||
|
||||
if( str == "NA" )
|
||||
{
|
||||
result = std::stod( str, &size );
|
||||
converted = true;
|
||||
result = nan( NAN_NA );
|
||||
}
|
||||
catch( ... )
|
||||
else
|
||||
{
|
||||
if( str == "NA" )
|
||||
try
|
||||
{
|
||||
result = nan( NAN_NA );
|
||||
result = std::stod( str, &size );
|
||||
converted = true;
|
||||
}
|
||||
else
|
||||
catch( ... )
|
||||
{
|
||||
result = nan( NAN_INVALID );
|
||||
status = false;
|
||||
|
@ -887,6 +887,9 @@ bool IbisParser::getNextLine()
|
|||
|
||||
m_lineOffset = m_bufferIndex;
|
||||
|
||||
if( m_bufferIndex >= m_buffer.size() )
|
||||
return false;
|
||||
|
||||
char c = m_buffer[m_bufferIndex++];
|
||||
|
||||
int i = 1;
|
||||
|
@ -1047,15 +1050,17 @@ bool IbisParser::readString( std::string& aDest )
|
|||
|
||||
bool IbisParser::storeString( std::string& aDest, bool aMultiline )
|
||||
{
|
||||
bool status = true;
|
||||
|
||||
skipWhitespaces();
|
||||
|
||||
readString( aDest );
|
||||
status &= readString( aDest );
|
||||
|
||||
m_continue = aMultiline ? IBIS_PARSER_CONTINUE::STRING : IBIS_PARSER_CONTINUE::NONE;
|
||||
m_continuingString = &aDest;
|
||||
|
||||
return checkEndofLine();
|
||||
status &= checkEndofLine();
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1063,10 +1068,10 @@ bool IbisParser::changeCommentChar()
|
|||
{
|
||||
skipWhitespaces();
|
||||
|
||||
std::string strChar;
|
||||
std::string strChar = "";
|
||||
|
||||
// We cannot stop at m_lineLength here, because lineLength could stop before |_char
|
||||
// if the char is remains the same
|
||||
// if the char remains the same
|
||||
|
||||
char c = m_buffer[m_lineOffset + m_lineIndex++];
|
||||
char d = c;
|
||||
|
@ -1087,7 +1092,7 @@ bool IbisParser::changeCommentChar()
|
|||
c = m_buffer[m_lineOffset + m_lineIndex++];
|
||||
}
|
||||
|
||||
if( !strcmp( strChar.c_str(), "_char" ) )
|
||||
if( strChar != "_char" )
|
||||
{
|
||||
Report( _( "Invalid syntax. Should be |_char or &_char, etc..." ), RPT_SEVERITY_ERROR );
|
||||
return false;
|
||||
|
@ -1175,13 +1180,13 @@ bool IbisParser::changeContext( std::string& aKeyword )
|
|||
{
|
||||
m_ibisFile.m_components.push_back( IbisComponent( m_reporter ) );
|
||||
m_currentComponent = &( m_ibisFile.m_components.back() );
|
||||
storeString( m_currentComponent->m_name, false );
|
||||
status &= storeString( m_currentComponent->m_name, false );
|
||||
m_context = IBIS_PARSER_CONTEXT::COMPONENT;
|
||||
}
|
||||
else if( compareIbisWord( aKeyword.c_str(), "Model_Selector" ) )
|
||||
{
|
||||
IbisModelSelector MS( m_reporter );
|
||||
storeString( MS.m_name, false );
|
||||
status &= storeString( MS.m_name, false );
|
||||
m_ibisFile.m_modelSelectors.push_back( MS );
|
||||
m_currentModelSelector = &( m_ibisFile.m_modelSelectors.back() );
|
||||
m_context = IBIS_PARSER_CONTEXT::MODELSELECTOR;
|
||||
|
@ -1193,7 +1198,7 @@ bool IbisParser::changeContext( std::string& aKeyword )
|
|||
model.m_temperatureRange.value[IBIS_CORNER::MIN] = 0;
|
||||
model.m_temperatureRange.value[IBIS_CORNER::TYP] = 50;
|
||||
model.m_temperatureRange.value[IBIS_CORNER::MAX] = 100;
|
||||
storeString( model.m_name, false );
|
||||
status &= storeString( model.m_name, false );
|
||||
m_ibisFile.m_models.push_back( model );
|
||||
m_currentModel = &( m_ibisFile.m_models.back() );
|
||||
m_context = IBIS_PARSER_CONTEXT::MODEL;
|
||||
|
@ -1214,7 +1219,7 @@ bool IbisParser::changeContext( std::string& aKeyword )
|
|||
PM.m_capacitanceMatrix->m_dim = -1;
|
||||
PM.m_inductanceMatrix->m_dim = -1;
|
||||
|
||||
storeString( PM.m_name, false );
|
||||
status &= storeString( PM.m_name, false );
|
||||
|
||||
m_ibisFile.m_packageModels.push_back( PM );
|
||||
m_currentPackageModel = &( m_ibisFile.m_packageModels.back() );
|
||||
|
@ -1302,9 +1307,7 @@ bool IbisParser::readRamp()
|
|||
|
||||
m_continue = IBIS_PARSER_CONTINUE::RAMP;
|
||||
|
||||
std::string keyword = std::string( "R_load " );
|
||||
|
||||
if( !readNumericSubparam( std::string( "R_load " ), m_currentModel->m_ramp.m_Rload ) )
|
||||
if( !readNumericSubparam( std::string( "R_load" ), m_currentModel->m_ramp.m_Rload ) )
|
||||
{
|
||||
std::string str;
|
||||
|
||||
|
@ -1312,11 +1315,11 @@ bool IbisParser::readRamp()
|
|||
{
|
||||
if( !strcmp( str.c_str(), "dV/dt_r" ) )
|
||||
{
|
||||
readRampdvdt( m_currentModel->m_ramp.m_rising );
|
||||
status &= readRampdvdt( m_currentModel->m_ramp.m_rising );
|
||||
}
|
||||
else if( !strcmp( str.c_str(), "dV/dt_f" ) )
|
||||
{
|
||||
readRampdvdt( m_currentModel->m_ramp.m_falling );
|
||||
status &= readRampdvdt( m_currentModel->m_ramp.m_falling );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1703,18 +1706,12 @@ bool IbisParser::readModelSelector()
|
|||
|
||||
IbisModelSelectorEntry model;
|
||||
|
||||
if( readWord( model.m_modelName ) )
|
||||
{
|
||||
if( !readString( model.m_modelDescription ) )
|
||||
{
|
||||
status &= false;
|
||||
}
|
||||
m_currentModelSelector->m_models.push_back( model );
|
||||
}
|
||||
else
|
||||
{
|
||||
status = false;
|
||||
}
|
||||
if( !readWord( model.m_modelName ) )
|
||||
return false;
|
||||
|
||||
status &= readString( model.m_modelDescription );
|
||||
m_currentModelSelector->m_models.push_back( model );
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -1966,11 +1963,11 @@ bool IbisParser::parseHeader( std::string& aKeyword )
|
|||
}
|
||||
else if( compareIbisWord( aKeyword.c_str(), "Comment_char" ) )
|
||||
{
|
||||
changeCommentChar();
|
||||
status &= changeCommentChar();
|
||||
}
|
||||
else if( compareIbisWord( aKeyword.c_str(), "File_Name" ) )
|
||||
{
|
||||
storeString( m_ibisFile.m_header.m_fileName, false );
|
||||
status &= storeString( m_ibisFile.m_header.m_fileName, false );
|
||||
}
|
||||
else if( compareIbisWord( aKeyword.c_str(), "File_Rev" ) )
|
||||
{
|
||||
|
@ -1978,23 +1975,23 @@ bool IbisParser::parseHeader( std::string& aKeyword )
|
|||
}
|
||||
else if( compareIbisWord( aKeyword.c_str(), "Source" ) )
|
||||
{
|
||||
storeString( m_ibisFile.m_header.m_source, true );
|
||||
status &= storeString( m_ibisFile.m_header.m_source, true );
|
||||
}
|
||||
else if( compareIbisWord( aKeyword.c_str(), "Notes" ) )
|
||||
{
|
||||
storeString( m_ibisFile.m_header.m_notes, true );
|
||||
status &= storeString( m_ibisFile.m_header.m_notes, true );
|
||||
}
|
||||
else if( compareIbisWord( aKeyword.c_str(), "Disclaimer" ) )
|
||||
{
|
||||
storeString( m_ibisFile.m_header.m_disclaimer, true );
|
||||
status &= storeString( m_ibisFile.m_header.m_disclaimer, true );
|
||||
}
|
||||
else if( compareIbisWord( aKeyword.c_str(), "Copyright" ) )
|
||||
{
|
||||
storeString( m_ibisFile.m_header.m_copyright, true );
|
||||
status &= storeString( m_ibisFile.m_header.m_copyright, true );
|
||||
}
|
||||
else if( compareIbisWord( aKeyword.c_str(), "Date" ) )
|
||||
{
|
||||
storeString( m_ibisFile.m_header.m_date, false );
|
||||
status &= storeString( m_ibisFile.m_header.m_date, false );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2092,36 +2089,23 @@ bool IbisParser::readPackage()
|
|||
|
||||
if( (int)fields.size() == ( 4 + extraArg ) )
|
||||
{
|
||||
TypMinMaxValue* cValue;
|
||||
|
||||
if( fields.at( 0 ) == "R_pkg" )
|
||||
{
|
||||
if( parseDouble( R->value[IBIS_CORNER::TYP], fields.at( 1 ), true ) )
|
||||
{
|
||||
status = false;
|
||||
}
|
||||
|
||||
parseDouble( R->value[IBIS_CORNER::MIN], fields.at( 2 ), true );
|
||||
parseDouble( R->value[IBIS_CORNER::MAX], fields.at( 3 ), true );
|
||||
}
|
||||
cValue = R;
|
||||
else if( fields.at( 0 ) == "L_pkg" )
|
||||
{
|
||||
if( parseDouble( L->value[IBIS_CORNER::TYP], fields.at( 1 ), true ) )
|
||||
{
|
||||
status = false;
|
||||
}
|
||||
|
||||
parseDouble( L->value[IBIS_CORNER::MIN], fields.at( 2 ), true );
|
||||
parseDouble( L->value[IBIS_CORNER::MAX], fields.at( 3 ), true );
|
||||
}
|
||||
cValue = L;
|
||||
else if( fields.at( 0 ) == "C_pkg" )
|
||||
cValue = C;
|
||||
else
|
||||
{
|
||||
if( parseDouble( C->value[IBIS_CORNER::TYP], fields.at( 1 ), true ) )
|
||||
{
|
||||
status = false;
|
||||
}
|
||||
|
||||
parseDouble( C->value[IBIS_CORNER::MIN], fields.at( 2 ), true );
|
||||
parseDouble( C->value[IBIS_CORNER::MAX], fields.at( 3 ), true );
|
||||
Report( "Invalid field in [Package]" );
|
||||
return false;
|
||||
}
|
||||
status &= parseDouble( cValue->value[IBIS_CORNER::TYP], fields.at( 1 ), true );
|
||||
// Min / max values are optional, so don't update the status
|
||||
parseDouble( cValue->value[IBIS_CORNER::MIN], fields.at( 2 ), true );
|
||||
parseDouble( cValue->value[IBIS_CORNER::MAX], fields.at( 3 ), true );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2133,7 +2117,7 @@ bool IbisParser::readPackage()
|
|||
}
|
||||
m_continue = IBIS_PARSER_CONTINUE::COMPONENT_PACKAGE;
|
||||
|
||||
return true;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2475,7 +2459,7 @@ bool IbisParser::onNewLine()
|
|||
case IBIS_PARSER_CONTINUE::STRING:
|
||||
skipWhitespaces();
|
||||
*m_continuingString += '\n';
|
||||
readString( *m_continuingString );
|
||||
status &= readString( *m_continuingString );
|
||||
break;
|
||||
case IBIS_PARSER_CONTINUE::COMPONENT_PACKAGE: status &= readPackage(); break;
|
||||
case IBIS_PARSER_CONTINUE::COMPONENT_PIN: status &= readPin(); break;
|
||||
|
|
|
@ -45,6 +45,23 @@
|
|||
#define _( x ) x
|
||||
#endif
|
||||
|
||||
|
||||
std::vector<std::pair<int, double>> SimplifyBitSequence( std::vector<std::pair<int, double>> bits )
|
||||
{
|
||||
std::vector<std::pair<int, double>> result;
|
||||
int prevbit = -1;
|
||||
|
||||
for( std::pair<int, double> bit : bits )
|
||||
{
|
||||
if( prevbit != bit.first )
|
||||
result.push_back( bit );
|
||||
|
||||
prevbit = bit.first;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
KIBIS_ANY::KIBIS_ANY( KIBIS* aTopLevel ) : IBIS_ANY( aTopLevel->m_reporter )
|
||||
{
|
||||
m_topLevel = aTopLevel;
|
||||
|
@ -407,14 +424,14 @@ std::string KIBIS_MODEL::SpiceDie( KIBIS_PARAMETER& aParam, int aIndex )
|
|||
{
|
||||
result += m_pulldown.Spice( aIndex * 4 + 3, DIEBUFF, PD_GND, PD, supply );
|
||||
result += "VmeasPD GND " + PD_GND + " 0\n";
|
||||
result += "BKD GND " + DIE + " i=( -i(VmeasPU) * v(KU) )\n";
|
||||
result += "BKD GND " + DIE + " i=( i(VmeasPD) * v(KD) )\n";
|
||||
}
|
||||
|
||||
if( HasPullup() )
|
||||
{
|
||||
result += m_pullup.Spice( aIndex * 4 + 4, PU_PWR, DIEBUFF, PU, supply );
|
||||
result += "VmeasPU POWER " + PU_PWR + " 0\n";
|
||||
result += "BKU POWER " + DIE + " i=( i(VmeasPD) * v(KD) )\n";
|
||||
result += "BKU POWER " + DIE + " i=( -i(VmeasPU) * v(KU) )\n";
|
||||
}
|
||||
|
||||
result += "BDIEBUFF " + DIEBUFF + " GND v=v(" + DIE + ")\n";
|
||||
|
@ -781,31 +798,11 @@ std::string KIBIS_PIN::KuKdDriver( KIBIS_MODEL& aMode
|
|||
switch( wave->GetType() )
|
||||
{
|
||||
case KIBIS_WAVEFORM_TYPE::RECTANGULAR:
|
||||
{
|
||||
KIBIS_WAVEFORM_RECTANGULAR* rectWave = dynamic_cast<KIBIS_WAVEFORM_RECTANGULAR*>( wave );
|
||||
|
||||
if( !rectWave )
|
||||
{
|
||||
break;
|
||||
}
|
||||
if( rectWave->m_ton < risingWF->m_table.m_entries.back().t )
|
||||
{
|
||||
Report( _( "Rising edge is longer than on time." ), RPT_SEVERITY_WARNING );
|
||||
}
|
||||
|
||||
if( rectWave->m_toff < fallingWF->m_table.m_entries.back().t )
|
||||
{
|
||||
Report( _( "Falling edge is longer than off time." ), RPT_SEVERITY_WARNING );
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::pair<int, double>> bits = wave->GenerateBitSequence();
|
||||
simul += aModel.generateSquareWave( "DIE0", "GND", bits, aPair, aParam );
|
||||
break;
|
||||
}
|
||||
case KIBIS_WAVEFORM_TYPE::PRBS:
|
||||
{
|
||||
wave->Check( risingWF, fallingWF );
|
||||
std::vector<std::pair<int, double>> bits = wave->GenerateBitSequence();
|
||||
bits = SimplifyBitSequence( bits );
|
||||
simul += aModel.generateSquareWave( "DIE0", "GND", bits, aPair, aParam );
|
||||
break;
|
||||
}
|
||||
|
@ -959,26 +956,24 @@ void KIBIS_PIN::getKuKdNoWaveform( KIBIS_MODEL& aModel, KIBIS_PARAMETER& aParam
|
|||
switch( wave->GetType() )
|
||||
{
|
||||
case KIBIS_WAVEFORM_TYPE::RECTANGULAR:
|
||||
case KIBIS_WAVEFORM_TYPE::PRBS:
|
||||
{
|
||||
KIBIS_WAVEFORM_RECTANGULAR* rectWave = static_cast<KIBIS_WAVEFORM_RECTANGULAR*>( wave );
|
||||
wave->Check( aModel.m_ramp.m_rising, aModel.m_ramp.m_falling );
|
||||
std::vector<std::pair<int, double>> bits = wave->GenerateBitSequence();
|
||||
bits = SimplifyBitSequence( bits );
|
||||
|
||||
for( int i = 0; i < rectWave->m_cycles; i++ )
|
||||
for( std::pair<int, double> bit : bits )
|
||||
{
|
||||
ku.push_back( 0 );
|
||||
kd.push_back( 1 );
|
||||
t.push_back( ( rectWave->m_ton + rectWave->m_toff ) * i );
|
||||
ku.push_back( 1 );
|
||||
kd.push_back( 0 );
|
||||
t.push_back( ( rectWave->m_ton + rectWave->m_toff ) * i
|
||||
+ aModel.m_ramp.m_rising.value[supply].m_dt
|
||||
/ 0.6 ); // 0.6 because ibis only gives 20%-80% time
|
||||
ku.push_back( 1 );
|
||||
kd.push_back( 0 );
|
||||
t.push_back( ( rectWave->m_ton + rectWave->m_toff ) * i + rectWave->m_toff );
|
||||
ku.push_back( 0 );
|
||||
kd.push_back( 1 );
|
||||
t.push_back( ( rectWave->m_ton + rectWave->m_toff ) * i + rectWave->m_toff
|
||||
+ aModel.m_ramp.m_falling.value[supply].m_dt / 0.6 );
|
||||
ku.push_back( bit.first ? 0 : 1 );
|
||||
kd.push_back( bit.first ? 1 : 0 );
|
||||
t.push_back( bit.second );
|
||||
ku.push_back( bit.first ? 1 : 0 );
|
||||
kd.push_back( bit.first ? 0 : 1 );
|
||||
t.push_back( bit.second
|
||||
+ ( bit.first ? +aModel.m_ramp.m_rising.value[supply].m_dt
|
||||
: aModel.m_ramp.m_falling.value[supply].m_dt )
|
||||
/ 0.6 );
|
||||
// 0.6 because ibis only gives 20%-80% time
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1530,3 +1525,149 @@ std::vector<std::pair<int, double>> KIBIS_WAVEFORM_PRBS::GenerateBitSequence()
|
|||
|
||||
return bitSequence;
|
||||
}
|
||||
|
||||
bool KIBIS_WAVEFORM_RECTANGULAR::Check( IbisWaveform* aRisingWf, IbisWaveform* aFallingWf )
|
||||
{
|
||||
bool status = true;
|
||||
|
||||
if( m_cycles < 1 )
|
||||
{
|
||||
status = false;
|
||||
Report( _( "Number of cycles should be greater than 0." ), RPT_SEVERITY_ERROR );
|
||||
}
|
||||
|
||||
if( m_ton <= 0 )
|
||||
{
|
||||
status = false;
|
||||
Report( _( "ON time should be greater than 0." ), RPT_SEVERITY_ERROR );
|
||||
}
|
||||
|
||||
if( m_toff <= 0 )
|
||||
{
|
||||
status = false;
|
||||
Report( _( "OFF time should be greater than 0." ), RPT_SEVERITY_ERROR );
|
||||
}
|
||||
|
||||
if( aRisingWf )
|
||||
{
|
||||
if( m_ton < aRisingWf->m_table.m_entries.back().t )
|
||||
{
|
||||
status = false;
|
||||
Report( _( "Rising edge is longer than on time." ), RPT_SEVERITY_WARNING );
|
||||
}
|
||||
}
|
||||
|
||||
if( aFallingWf )
|
||||
{
|
||||
if( m_toff < aFallingWf->m_table.m_entries.back().t )
|
||||
{
|
||||
status = false;
|
||||
Report( _( "Falling edge is longer than off time." ), RPT_SEVERITY_WARNING );
|
||||
}
|
||||
}
|
||||
|
||||
status &= aRisingWf && aFallingWf;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
bool KIBIS_WAVEFORM_RECTANGULAR::Check( dvdtTypMinMax aRisingRp, dvdtTypMinMax aFallingRp )
|
||||
{
|
||||
bool status = true;
|
||||
|
||||
if( m_cycles < 1 )
|
||||
{
|
||||
status = false;
|
||||
Report( _( "Number of cycles should be greater than 0." ), RPT_SEVERITY_ERROR );
|
||||
}
|
||||
|
||||
if( m_ton <= 0 )
|
||||
{
|
||||
status = false;
|
||||
Report( _( "ON time should be greater than 0." ), RPT_SEVERITY_ERROR );
|
||||
}
|
||||
|
||||
if( m_toff <= 0 )
|
||||
{
|
||||
status = false;
|
||||
Report( _( "OFF time should be greater than 0." ), RPT_SEVERITY_ERROR );
|
||||
}
|
||||
|
||||
if( ( m_ton < aRisingRp.value[IBIS_CORNER::TYP].m_dt / 0.6 )
|
||||
|| ( m_ton < aRisingRp.value[IBIS_CORNER::MIN].m_dt / 0.6 )
|
||||
|| ( m_ton < aRisingRp.value[IBIS_CORNER::MAX].m_dt / 0.6 ) )
|
||||
{
|
||||
status = false;
|
||||
Report( _( "Rising edge is longer than ON time." ), RPT_SEVERITY_ERROR );
|
||||
}
|
||||
|
||||
if( ( m_toff < aFallingRp.value[IBIS_CORNER::TYP].m_dt / 0.6 )
|
||||
|| ( m_toff < aFallingRp.value[IBIS_CORNER::MIN].m_dt / 0.6 )
|
||||
|| ( m_toff < aFallingRp.value[IBIS_CORNER::MAX].m_dt / 0.6 ) )
|
||||
{
|
||||
status = false;
|
||||
Report( _( "Falling edge is longer than OFF time." ), RPT_SEVERITY_ERROR );
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
bool KIBIS_WAVEFORM_PRBS::Check( dvdtTypMinMax aRisingRp, dvdtTypMinMax aFallingRp )
|
||||
{
|
||||
bool status = true;
|
||||
|
||||
if( m_bitrate <= 0 )
|
||||
{
|
||||
status = false;
|
||||
Report( _( "Bitrate should be greater than 0." ), RPT_SEVERITY_ERROR );
|
||||
}
|
||||
|
||||
if( m_bits <= 0 )
|
||||
{
|
||||
status = false;
|
||||
Report( _( "Number of bits should be greater than 0." ), RPT_SEVERITY_ERROR );
|
||||
}
|
||||
|
||||
if( m_bitrate
|
||||
&& ( ( 1 / m_bitrate ) < ( aRisingRp.value[IBIS_CORNER::TYP].m_dt / 0.6
|
||||
+ aFallingRp.value[IBIS_CORNER::TYP].m_dt / 0.6 ) )
|
||||
&& ( ( 1 / m_bitrate ) < ( aRisingRp.value[IBIS_CORNER::TYP].m_dt / 0.6
|
||||
+ aFallingRp.value[IBIS_CORNER::TYP].m_dt / 0.6 ) )
|
||||
&& ( ( 1 / m_bitrate ) < ( aRisingRp.value[IBIS_CORNER::TYP].m_dt / 0.6
|
||||
+ aFallingRp.value[IBIS_CORNER::TYP].m_dt / 0.6 ) ) )
|
||||
{
|
||||
status = false;
|
||||
Report( _( "Bitrate is too high for rising / falling edges" ), RPT_SEVERITY_ERROR );
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool KIBIS_WAVEFORM_PRBS::Check( IbisWaveform* aRisingWf, IbisWaveform* aFallingWf )
|
||||
{
|
||||
bool status = true;
|
||||
|
||||
if( m_bitrate <= 0 )
|
||||
{
|
||||
status = false;
|
||||
Report( _( "Bitrate should be greater than 0." ), RPT_SEVERITY_ERROR );
|
||||
}
|
||||
|
||||
if( m_bits <= 0 )
|
||||
{
|
||||
status = false;
|
||||
Report( _( "Number of bits should be greater than 0." ), RPT_SEVERITY_ERROR );
|
||||
}
|
||||
|
||||
if( m_bitrate && aRisingWf && aFallingWf
|
||||
&& ( ( 1 / m_bitrate ) < ( aRisingWf->m_table.m_entries.back().t
|
||||
+ aFallingWf->m_table.m_entries.back().t ) ) )
|
||||
{
|
||||
status = false;
|
||||
Report( _( "Bitrate could be too high for rising / falling edges" ), RPT_SEVERITY_WARNING );
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -59,10 +59,10 @@ enum KIBIS_WAVEFORM_TYPE
|
|||
};
|
||||
|
||||
|
||||
class KIBIS_WAVEFORM
|
||||
class KIBIS_WAVEFORM : public KIBIS_ANY
|
||||
{
|
||||
public:
|
||||
KIBIS_WAVEFORM(){};
|
||||
KIBIS_WAVEFORM( KIBIS* aTopLevel ) : KIBIS_ANY{ aTopLevel } { m_valid = true; };
|
||||
KIBIS_WAVEFORM_TYPE GetType() { return m_type; };
|
||||
virtual double GetDuration() { return 1; };
|
||||
bool inverted = false; // Used for differential drivers
|
||||
|
@ -74,6 +74,11 @@ public:
|
|||
return bits;
|
||||
};
|
||||
|
||||
// Check fuction if using waveform data
|
||||
virtual bool Check( IbisWaveform* aRisingWf, IbisWaveform* aFallingWf ) { return true; };
|
||||
// Check fuction if using ramp data
|
||||
virtual bool Check( dvdtTypMinMax aRisingRp, dvdtTypMinMax aFallingRp ) { return true; };
|
||||
|
||||
protected:
|
||||
KIBIS_WAVEFORM_TYPE m_type = KIBIS_WAVEFORM_TYPE::NONE;
|
||||
};
|
||||
|
@ -81,13 +86,20 @@ protected:
|
|||
class KIBIS_WAVEFORM_RECTANGULAR : public KIBIS_WAVEFORM
|
||||
{
|
||||
public:
|
||||
KIBIS_WAVEFORM_RECTANGULAR() : KIBIS_WAVEFORM() { m_type = KIBIS_WAVEFORM_TYPE::RECTANGULAR; };
|
||||
KIBIS_WAVEFORM_RECTANGULAR( KIBIS* aTopLevel ) : KIBIS_WAVEFORM( aTopLevel )
|
||||
{
|
||||
m_type = KIBIS_WAVEFORM_TYPE::RECTANGULAR;
|
||||
};
|
||||
double m_ton = 100e-9;
|
||||
double m_toff = 100e-9;
|
||||
int m_cycles = 1;
|
||||
double m_delay = 0;
|
||||
|
||||
|
||||
std::vector<std::pair<int, double>> GenerateBitSequence() override;
|
||||
bool Check( IbisWaveform* aRisingWf, IbisWaveform* aFallingWf ) override;
|
||||
bool Check( dvdtTypMinMax aRisingRp, dvdtTypMinMax aFallingRp ) override;
|
||||
|
||||
double GetDuration() override { return ( m_ton + m_toff ) * m_cycles; };
|
||||
};
|
||||
|
||||
|
@ -95,33 +107,48 @@ public:
|
|||
class KIBIS_WAVEFORM_PRBS : public KIBIS_WAVEFORM
|
||||
{
|
||||
public:
|
||||
KIBIS_WAVEFORM_PRBS() : KIBIS_WAVEFORM() { m_type = KIBIS_WAVEFORM_TYPE::PRBS; };
|
||||
KIBIS_WAVEFORM_PRBS( KIBIS* aTopLevel ) : KIBIS_WAVEFORM( aTopLevel )
|
||||
{
|
||||
m_type = KIBIS_WAVEFORM_TYPE::PRBS;
|
||||
};
|
||||
double m_bitrate = 10e6;
|
||||
double m_delay = 0;
|
||||
double m_bits = 10;
|
||||
|
||||
std::vector<std::pair<int, double>> GenerateBitSequence() override;
|
||||
bool Check( IbisWaveform* aRisingWf, IbisWaveform* aFallingWf ) override;
|
||||
bool Check( dvdtTypMinMax aRisingRp, dvdtTypMinMax aFallingRp ) override;
|
||||
|
||||
double GetDuration() override { return m_bits / m_bitrate ; };
|
||||
};
|
||||
|
||||
class KIBIS_WAVEFORM_STUCK_HIGH : public KIBIS_WAVEFORM
|
||||
{
|
||||
public:
|
||||
KIBIS_WAVEFORM_STUCK_HIGH() : KIBIS_WAVEFORM() { m_type = KIBIS_WAVEFORM_TYPE::STUCK_HIGH; };
|
||||
KIBIS_WAVEFORM_STUCK_HIGH( KIBIS* aTopLevel ) : KIBIS_WAVEFORM( aTopLevel )
|
||||
{
|
||||
m_type = KIBIS_WAVEFORM_TYPE::STUCK_HIGH;
|
||||
};
|
||||
std::vector<std::pair<int, double>> GenerateBitSequence() override;
|
||||
};
|
||||
|
||||
class KIBIS_WAVEFORM_STUCK_LOW : public KIBIS_WAVEFORM
|
||||
{
|
||||
public:
|
||||
KIBIS_WAVEFORM_STUCK_LOW() : KIBIS_WAVEFORM() { m_type = KIBIS_WAVEFORM_TYPE::STUCK_LOW; };
|
||||
KIBIS_WAVEFORM_STUCK_LOW( KIBIS* aTopLevel ) : KIBIS_WAVEFORM( aTopLevel )
|
||||
{
|
||||
m_type = KIBIS_WAVEFORM_TYPE::STUCK_LOW;
|
||||
};
|
||||
std::vector<std::pair<int, double>> GenerateBitSequence() override;
|
||||
};
|
||||
|
||||
class KIBIS_WAVEFORM_HIGH_Z : public KIBIS_WAVEFORM
|
||||
{
|
||||
public:
|
||||
KIBIS_WAVEFORM_HIGH_Z() : KIBIS_WAVEFORM() { m_type = KIBIS_WAVEFORM_TYPE::HIGH_Z; };
|
||||
KIBIS_WAVEFORM_HIGH_Z( KIBIS* aTopLevel ) : KIBIS_WAVEFORM( aTopLevel )
|
||||
{
|
||||
m_type = KIBIS_WAVEFORM_TYPE::HIGH_Z;
|
||||
};
|
||||
std::vector<std::pair<int, double>> GenerateBitSequence() override;
|
||||
};
|
||||
|
||||
|
|
|
@ -143,17 +143,17 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem, const st
|
|||
if( paramValue == "hi-Z" )
|
||||
{
|
||||
kparams.m_waveform =
|
||||
static_cast<KIBIS_WAVEFORM*>( new KIBIS_WAVEFORM_HIGH_Z() );
|
||||
static_cast<KIBIS_WAVEFORM*>( new KIBIS_WAVEFORM_HIGH_Z( &kibis ) );
|
||||
}
|
||||
else if( paramValue == "low" )
|
||||
{
|
||||
kparams.m_waveform =
|
||||
static_cast<KIBIS_WAVEFORM*>( new KIBIS_WAVEFORM_STUCK_LOW() );
|
||||
static_cast<KIBIS_WAVEFORM*>( new KIBIS_WAVEFORM_STUCK_LOW( &kibis ) );
|
||||
}
|
||||
else if( paramValue == "high" )
|
||||
{
|
||||
kparams.m_waveform =
|
||||
static_cast<KIBIS_WAVEFORM*>( new KIBIS_WAVEFORM_STUCK_HIGH() );
|
||||
static_cast<KIBIS_WAVEFORM*>( new KIBIS_WAVEFORM_STUCK_HIGH( &kibis ) );
|
||||
}
|
||||
|
||||
if( diffMode )
|
||||
|
@ -165,7 +165,7 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem, const st
|
|||
|
||||
case SIM_MODEL::TYPE::KIBIS_DRIVER_RECT:
|
||||
{
|
||||
KIBIS_WAVEFORM_RECTANGULAR* waveform = new KIBIS_WAVEFORM_RECTANGULAR();
|
||||
KIBIS_WAVEFORM_RECTANGULAR* waveform = new KIBIS_WAVEFORM_RECTANGULAR( &kibis );
|
||||
|
||||
if ( m_model.FindParam( "ton" ) )
|
||||
waveform->m_ton = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "ton" )->value ).Get().value_or( 1 );
|
||||
|
@ -177,7 +177,7 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem, const st
|
|||
waveform->m_delay = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "delay" )->value ).Get().value_or( 0 );
|
||||
|
||||
if ( m_model.FindParam( "cycles" ) )
|
||||
waveform->m_cycles = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "cycles" )->value ).Get().value_or( 0 );
|
||||
waveform->m_cycles = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "cycles" )->value ).Get().value_or( 1 );
|
||||
|
||||
kparams.m_waveform = waveform;
|
||||
|
||||
|
@ -190,7 +190,7 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem, const st
|
|||
|
||||
case SIM_MODEL::TYPE::KIBIS_DRIVER_PRBS:
|
||||
{
|
||||
KIBIS_WAVEFORM_PRBS* waveform = new KIBIS_WAVEFORM_PRBS();
|
||||
KIBIS_WAVEFORM_PRBS* waveform = new KIBIS_WAVEFORM_PRBS( &kibis );
|
||||
|
||||
if ( m_model.FindParam( "f0" ) )
|
||||
waveform->m_bitrate = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "f0" )->value ).Get().value_or( 0 );
|
||||
|
|
|
@ -7,42 +7,21 @@
|
|||
source for the files
|
||||
[Notes] We can have some
|
||||
Notes
|
||||
[Disclaimer]
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
[Disclaimer] This is NOT a valid component.
|
||||
|
||||
[Component] Virtual
|
||||
[Manufacturer] KiCad
|
||||
[Package]
|
||||
R_pkg 1m 0.8m NA
|
||||
L_pkg 1m NA NA
|
||||
C_pkg 1m NA NA
|
||||
R_pkg 50m 40m 60m
|
||||
L_pkg 2n NA NA
|
||||
C_pkg 10p NA NA
|
||||
|
||||
[Pin] signal_name model_name R_pin L_pin C_pin
|
||||
1 VCC POWER 1m 0.8m NA
|
||||
2 GND GND 1m NA 2m
|
||||
3 X Input 1m NA NA
|
||||
4 Y Ouput 1m 0.8m 2m
|
||||
1 VCC POWER 5mm 2n NA
|
||||
2 GND GND 55m NA NA
|
||||
3 X Input 55m NA 0.2p
|
||||
4 Y Output 55m 2n 0.2p
|
||||
|
||||
[Model] Input
|
||||
Model_type Input
|
||||
|
@ -50,22 +29,10 @@ Polarity Non-Inverting
|
|||
Enable Active-High
|
||||
Vinl = 0.8V
|
||||
Vinh = 2.0V
|
||||
C_comp 10.0pF 8.0pF 15.0pF
|
||||
C_comp 1.0pF 0.5pF 2.0pF
|
||||
|
||||
[Voltage range] 5.0V 4.5V 5.5V
|
||||
[Pulldown]
|
||||
# Voltage I(typ) I(min) I(max)
|
||||
#
|
||||
-5.0V -50.0m -40.0m -60.0m
|
||||
0.0V 0 0 0
|
||||
5.0V 50.0m 40.0m 60.0m
|
||||
[Pullup]
|
||||
#
|
||||
# Voltage I(typ) I(min) I(max)
|
||||
#
|
||||
-5.0V 50.0m 40.0m 60.0m
|
||||
0.0V 0 0 0
|
||||
5.0V -50.0m -40.0m -60.0m
|
||||
|
||||
[GND_clamp]
|
||||
#
|
||||
# Voltage I(typ) I(min) I(max)
|
||||
|
@ -81,9 +48,46 @@ C_comp 10.0pF 8.0pF 15.0pF
|
|||
0.0V 0 NA NA
|
||||
5.0V 0 NA NA
|
||||
|
||||
[Model] Output
|
||||
Model_type Output
|
||||
Polarity Non-Inverting
|
||||
Enable Active-High
|
||||
C_comp 10.0pF 8.0pF 15.0pF
|
||||
|
||||
[Voltage range] 5.0V 4.5V 5.5V
|
||||
[Pulldown]
|
||||
# Voltage I(typ) I(min) I(max)
|
||||
#
|
||||
-5.0V -50.0m -40.0m -60.0m
|
||||
0.0V 0 0 0
|
||||
5.0V 500.0m 400.0m 600.0m
|
||||
10.0V 550.0m 440.0m 660.0m
|
||||
[Pullup]
|
||||
#
|
||||
# Voltage I(typ) I(min) I(max)
|
||||
#
|
||||
-5.0V 50.0m 40.0m 60.0m
|
||||
0.0V 0 0 0
|
||||
5.0V -500.0m -400.0m -600.0m
|
||||
10.0V -550.0m -440.0m -660.0m
|
||||
[GND_clamp]
|
||||
#
|
||||
# Voltage I(typ) I(min) I(max)
|
||||
#
|
||||
-5.0V -500.0m NA NA
|
||||
-0.7V 0 NA NA
|
||||
5.0V 0 NA NA
|
||||
[POWER_clamp]
|
||||
#
|
||||
# Voltage I(typ) I(min) I(max)
|
||||
#
|
||||
-5.0V 500.0m NA NA
|
||||
-0.7V 0 NA NA
|
||||
5.0V 0 NA NA
|
||||
|
||||
[Ramp]
|
||||
# variable typ min max
|
||||
dV/dt_r 3.0/2n 2.8/3n NA
|
||||
dV/dt_f 3.0/2n 2.8/3n 3.2/1n
|
||||
# variable typ min max
|
||||
dV/dt_r 3.0/30n 2.8/30n NA
|
||||
dV/dt_f 3.0/20n 2.8/20n 3.2/20n
|
||||
|
||||
[END]
|
|
@ -7,8 +7,7 @@
|
|||
source for the files
|
||||
[Notes] We can have some
|
||||
Notes
|
||||
[Copyright]
|
||||
/*
|
||||
[Copyright] /*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
|
@ -42,10 +41,10 @@ C_pkg 1m 0.8m 2m
|
|||
1 VCC POWER 1m 0.8m 2m
|
||||
2 GND GND 1m 0.8m 2m
|
||||
3 X Input 1m 0.8m 2m
|
||||
4 Y Ouput 1m 0.8m 2m
|
||||
5 YN Ouput 1m 0.8m 2m
|
||||
6 Y Ouput 1m 0.8m 2m
|
||||
7 YN Ouput 1m 0.8m 2m
|
||||
4 Y Output 1m 0.8m 2m
|
||||
5 YN Output 1m 0.8m 2m
|
||||
6 Y Output 1m 0.8m 2m
|
||||
7 YN Output 1m 0.8m 2m
|
||||
|
||||
[Package Model] QS-SMT-cer-8-pin-pkgs
|
||||
[Pin Mapping] pulldown_ref pullup_ref gnd_clamp_ref power_clamp_ref
|
||||
|
@ -116,6 +115,41 @@ C_comp 10.0pF 8.0pF 15.0pF
|
|||
[Rac] 30Ohm NA NA
|
||||
[Cac] 50pF NA NA
|
||||
|
||||
[Model] Output
|
||||
Model_type Output
|
||||
Polarity Non-Inverting
|
||||
Enable Active-High
|
||||
C_comp 10.0pF 8.0pF 15.0pF
|
||||
|
||||
[Voltage range] 5.0V 4.5V 5.5V
|
||||
[Pulldown]
|
||||
# Voltage I(typ) I(min) I(max)
|
||||
#
|
||||
-5.0V -50.0m -40.0m -60.0m
|
||||
0.0V 0 0 0
|
||||
5.0V 50.0m 40.0m 60.0m
|
||||
[Pullup]
|
||||
#
|
||||
# Voltage I(typ) I(min) I(max)
|
||||
#
|
||||
-5.0V 50.0m 40.0m 60.0m
|
||||
0.0V 0 0 0
|
||||
5.0V -50.0m -40.0m -60.0m
|
||||
[GND_clamp]
|
||||
#
|
||||
# Voltage I(typ) I(min) I(max)
|
||||
#
|
||||
-5.0V -50.0m NA NA
|
||||
0.0V 0 NA NA
|
||||
5.0V 0 NA NA
|
||||
[POWER_clamp]
|
||||
#
|
||||
# Voltage I(typ) I(min) I(max)
|
||||
#
|
||||
-5.0V 50.0m NA NA
|
||||
0.0V 0 NA NA
|
||||
5.0V 0 NA NA
|
||||
|
||||
|
||||
[Ramp]
|
||||
# variable typ min max
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
source for the files
|
||||
[Notes] We can have some
|
||||
Notes
|
||||
[Copyright]
|
||||
/*
|
||||
[Copyright] /*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
source for the files
|
||||
[Notes] We can have some
|
||||
Notes
|
||||
[Copyright]
|
||||
/*
|
||||
[Copyright] /*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
|
@ -42,10 +41,10 @@ C_pkg 1m 0.8m 2m
|
|||
1 VCC POWER 1m 0.8m 2m
|
||||
2 GND GND 1m 0.8m 2m
|
||||
3 X Input 1m 0.8m 2m
|
||||
4 Y Ouput 1m 0.8m 2m
|
||||
5 YN Ouput 1m 0.8m 2m
|
||||
6 Y Ouput 1m 0.8m 2m
|
||||
7 YN Ouput 1m 0.8m 2m
|
||||
4 Y Output 1m 0.8m 2m
|
||||
5 YN Output 1m 0.8m 2m
|
||||
6 Y Output 1m 0.8m 2m
|
||||
7 YN Output 1m 0.8m 2m
|
||||
|
||||
[Package Model] QS-SMT-cer-8-pin-pkgs
|
||||
[Pin Mapping] pulldown_ref pullup_ref gnd_clamp_ref power_clamp_ref
|
||||
|
@ -377,7 +376,7 @@ Off_delay 5n 6n 4n | Time from rising edge
|
|||
0.000 0.000e+00 0.000e+00 0.000e+00
|
||||
5.000 0.000e+00 0.000e+00 0.000e+00
|
||||
|
|
||||
[POWER Pulse Table] | POWER Clamp offset table |
|
||||
[POWER Pulse Table] | POWER Clamp offset table|
|
||||
| Time V(typ) V(min) V(max)
|
||||
|
|
||||
0 0 0 0
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
source for the files
|
||||
[Notes] We can have some
|
||||
Notes
|
||||
[Copyright]
|
||||
/*
|
||||
[Copyright] /*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
|
|
Loading…
Reference in New Issue