Ibis: correctly load QA files up to v2.1

This commit is contained in:
Fabien Corona 2022-11-20 19:10:46 +00:00 committed by Mikolaj Wielgus
parent 2919490e92
commit 8498630876
9 changed files with 386 additions and 199 deletions

View File

@ -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;
if( str == "NA" )
{
result = nan( NAN_NA );
}
else
{
try
{
result = std::stod( str, &size );
converted = true;
}
catch( ... )
{
if( str == "NA" )
{
result = nan( NAN_NA );
}
else
{
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,8 +1307,6 @@ 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 ) )
{
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;
}
if( !readWord( model.m_modelName ) )
return false;
status &= readString( model.m_modelDescription );
m_currentModelSelector->m_models.push_back( model );
}
else
{
status = false;
}
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;

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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 );

View File

@ -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
dV/dt_r 3.0/30n 2.8/30n NA
dV/dt_f 3.0/20n 2.8/20n 3.2/20n
[END]

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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.